diff options
| author | SND\weimingzhi_cp <SND\weimingzhi_cp@e17a0e51-4ae3-4d35-97c3-1a29b211df97> | 2009-04-16 06:22:51 +0000 |
|---|---|---|
| committer | SND\weimingzhi_cp <SND\weimingzhi_cp@e17a0e51-4ae3-4d35-97c3-1a29b211df97> | 2009-04-16 06:22:51 +0000 |
| commit | 8139fbf8204882663446bcb06f68789353597820 (patch) | |
| tree | 6ea1f39932b33faee84d603e956470e37f135804 /libpcsxcore | |
| download | pcsxr-8139fbf8204882663446bcb06f68789353597820.tar.gz | |
git-svn-id: https://pcsxr.svn.codeplex.com/svn/pcsxr@23061 e17a0e51-4ae3-4d35-97c3-1a29b211df97
Diffstat (limited to 'libpcsxcore')
65 files changed, 39592 insertions, 0 deletions
diff --git a/libpcsxcore/Makefile.am b/libpcsxcore/Makefile.am new file mode 100644 index 00000000..cda48978 --- /dev/null +++ b/libpcsxcore/Makefile.am @@ -0,0 +1,76 @@ +INCLUDES = -DLOCALE_DIR=\"${datadir}/locale/\" \ + -I$(top_srcdir)/include + +noinst_LIBRARIES = libpcsxcore.a + +libpcsxcore_a_SOURCES = \ + $(top_builddir)/libpcsxcore/psxbios.c \ + $(top_builddir)/libpcsxcore/cdrom.c \ + $(top_builddir)/libpcsxcore/psxcounters.c \ + $(top_builddir)/libpcsxcore/psxdma.c \ + $(top_builddir)/libpcsxcore/disr3000a.c \ + $(top_builddir)/libpcsxcore/spu.c \ + $(top_builddir)/libpcsxcore/sio.c \ + $(top_builddir)/libpcsxcore/psxhw.c \ + $(top_builddir)/libpcsxcore/mdec.c \ + $(top_builddir)/libpcsxcore/psxmem.c \ + $(top_builddir)/libpcsxcore/misc.c \ + $(top_builddir)/libpcsxcore/plugins.c \ + $(top_builddir)/libpcsxcore/decode_xa.c \ + $(top_builddir)/libpcsxcore/r3000a.c \ + $(top_builddir)/libpcsxcore/psxinterpreter.c \ + $(top_builddir)/libpcsxcore/gte.c \ + $(top_builddir)/libpcsxcore/psxhle.c \ + $(top_builddir)/libpcsxcore/cdrom.h \ + $(top_builddir)/libpcsxcore/coff.h \ + $(top_builddir)/libpcsxcore/debug.h \ + $(top_builddir)/libpcsxcore/decode_xa.h \ + $(top_builddir)/libpcsxcore/gte.h \ + $(top_builddir)/libpcsxcore/mdec.h \ + $(top_builddir)/libpcsxcore/misc.h \ + $(top_builddir)/libpcsxcore/plugins.h \ + $(top_builddir)/libpcsxcore/psemu_plugin_defs.h \ + $(top_builddir)/libpcsxcore/psxbios.h \ + $(top_builddir)/libpcsxcore/psxcommon.h \ + $(top_builddir)/libpcsxcore/psxcounters.h \ + $(top_builddir)/libpcsxcore/psxdma.h \ + $(top_builddir)/libpcsxcore/psxhle.h \ + $(top_builddir)/libpcsxcore/psxhw.h \ + $(top_builddir)/libpcsxcore/psxmem.h \ + $(top_builddir)/libpcsxcore/r3000a.h \ + $(top_builddir)/libpcsxcore/sio.h \ + $(top_builddir)/libpcsxcore/spu.h \ + $(top_builddir)/libpcsxcore/system.h \ + $(top_builddir)/libpcsxcore/cdriso.c \ + $(top_builddir)/libpcsxcore/cdriso.h \ + $(top_builddir)/libpcsxcore/cheat.c \ + $(top_builddir)/libpcsxcore/cheat.h + +if ARCH_X86_64 +libpcsxcore_a_SOURCES += \ + $(top_builddir)/libpcsxcore/ix86_64/iR3000A-64.c \ + $(top_builddir)/libpcsxcore/ix86_64/ix86-64.c \ + $(top_builddir)/libpcsxcore/ix86_64/ix86_cpudetect.c \ + $(top_builddir)/libpcsxcore/ix86_64/ix86_fpu.c \ + $(top_builddir)/libpcsxcore/ix86_64/ix86_3dnow.c \ + $(top_builddir)/libpcsxcore/ix86_64/ix86_mmx.c \ + $(top_builddir)/libpcsxcore/ix86_64/ix86_sse.c \ + $(top_builddir)/libpcsxcore/ +else +if ARCH_X86 +libpcsxcore_a_SOURCES += \ + $(top_builddir)/libpcsxcore/ix86/iR3000A.c \ + $(top_builddir)/libpcsxcore/ix86/ix86.c \ + $(top_builddir)/libpcsxcore/ +endif +endif + +if ARCH_PPC +libpcsxcore_a_SOURCES += \ + $(top_builddir)/libpcsxcore/ppc/pR3000A.c \ + $(top_builddir)/libpcsxcore/ppc/ppc.c \ + $(top_builddir)/libpcsxcore/ppc/reguse.c \ + $(top_builddir)/libpcsxcore/ppc/pasm.s \ + $(top_builddir)/libpcsxcore/ +libpcsxcore_a_CCASFLAGS = -x assembler-with-cpp -mregnames +endif diff --git a/libpcsxcore/Makefile.in b/libpcsxcore/Makefile.in new file mode 100644 index 00000000..53c18ed1 --- /dev/null +++ b/libpcsxcore/Makefile.in @@ -0,0 +1,1088 @@ +# Makefile.in generated by automake 1.10.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +@ARCH_X86_64_TRUE@am__append_1 = \ +@ARCH_X86_64_TRUE@ $(top_builddir)/libpcsxcore/ix86_64/iR3000A-64.c \ +@ARCH_X86_64_TRUE@ $(top_builddir)/libpcsxcore/ix86_64/ix86-64.c \ +@ARCH_X86_64_TRUE@ $(top_builddir)/libpcsxcore/ix86_64/ix86_cpudetect.c \ +@ARCH_X86_64_TRUE@ $(top_builddir)/libpcsxcore/ix86_64/ix86_fpu.c \ +@ARCH_X86_64_TRUE@ $(top_builddir)/libpcsxcore/ix86_64/ix86_3dnow.c \ +@ARCH_X86_64_TRUE@ $(top_builddir)/libpcsxcore/ix86_64/ix86_mmx.c \ +@ARCH_X86_64_TRUE@ $(top_builddir)/libpcsxcore/ix86_64/ix86_sse.c \ +@ARCH_X86_64_TRUE@ $(top_builddir)/libpcsxcore/ + +@ARCH_X86_64_FALSE@@ARCH_X86_TRUE@am__append_2 = \ +@ARCH_X86_64_FALSE@@ARCH_X86_TRUE@ $(top_builddir)/libpcsxcore/ix86/iR3000A.c \ +@ARCH_X86_64_FALSE@@ARCH_X86_TRUE@ $(top_builddir)/libpcsxcore/ix86/ix86.c \ +@ARCH_X86_64_FALSE@@ARCH_X86_TRUE@ $(top_builddir)/libpcsxcore/ + +@ARCH_PPC_TRUE@am__append_3 = \ +@ARCH_PPC_TRUE@ $(top_builddir)/libpcsxcore/ppc/pR3000A.c \ +@ARCH_PPC_TRUE@ $(top_builddir)/libpcsxcore/ppc/ppc.c \ +@ARCH_PPC_TRUE@ $(top_builddir)/libpcsxcore/ppc/reguse.c \ +@ARCH_PPC_TRUE@ $(top_builddir)/libpcsxcore/ppc/pasm.s \ +@ARCH_PPC_TRUE@ $(top_builddir)/libpcsxcore/ + +subdir = libpcsxcore +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/include/config.h +CONFIG_CLEAN_FILES = +LIBRARIES = $(noinst_LIBRARIES) +ARFLAGS = cru +libpcsxcore_a_AR = $(AR) $(ARFLAGS) +libpcsxcore_a_LIBADD = +am__libpcsxcore_a_SOURCES_DIST = \ + $(top_builddir)/libpcsxcore/psxbios.c \ + $(top_builddir)/libpcsxcore/cdrom.c \ + $(top_builddir)/libpcsxcore/psxcounters.c \ + $(top_builddir)/libpcsxcore/psxdma.c \ + $(top_builddir)/libpcsxcore/disr3000a.c \ + $(top_builddir)/libpcsxcore/spu.c \ + $(top_builddir)/libpcsxcore/sio.c \ + $(top_builddir)/libpcsxcore/psxhw.c \ + $(top_builddir)/libpcsxcore/mdec.c \ + $(top_builddir)/libpcsxcore/psxmem.c \ + $(top_builddir)/libpcsxcore/misc.c \ + $(top_builddir)/libpcsxcore/plugins.c \ + $(top_builddir)/libpcsxcore/decode_xa.c \ + $(top_builddir)/libpcsxcore/r3000a.c \ + $(top_builddir)/libpcsxcore/psxinterpreter.c \ + $(top_builddir)/libpcsxcore/gte.c \ + $(top_builddir)/libpcsxcore/psxhle.c \ + $(top_builddir)/libpcsxcore/cdrom.h \ + $(top_builddir)/libpcsxcore/coff.h \ + $(top_builddir)/libpcsxcore/debug.h \ + $(top_builddir)/libpcsxcore/decode_xa.h \ + $(top_builddir)/libpcsxcore/gte.h \ + $(top_builddir)/libpcsxcore/mdec.h \ + $(top_builddir)/libpcsxcore/misc.h \ + $(top_builddir)/libpcsxcore/plugins.h \ + $(top_builddir)/libpcsxcore/psemu_plugin_defs.h \ + $(top_builddir)/libpcsxcore/psxbios.h \ + $(top_builddir)/libpcsxcore/psxcommon.h \ + $(top_builddir)/libpcsxcore/psxcounters.h \ + $(top_builddir)/libpcsxcore/psxdma.h \ + $(top_builddir)/libpcsxcore/psxhle.h \ + $(top_builddir)/libpcsxcore/psxhw.h \ + $(top_builddir)/libpcsxcore/psxmem.h \ + $(top_builddir)/libpcsxcore/r3000a.h \ + $(top_builddir)/libpcsxcore/sio.h \ + $(top_builddir)/libpcsxcore/spu.h \ + $(top_builddir)/libpcsxcore/system.h \ + $(top_builddir)/libpcsxcore/cdriso.c \ + $(top_builddir)/libpcsxcore/cdriso.h \ + $(top_builddir)/libpcsxcore/cheat.c \ + $(top_builddir)/libpcsxcore/cheat.h \ + $(top_builddir)/libpcsxcore/ix86_64/iR3000A-64.c \ + $(top_builddir)/libpcsxcore/ix86_64/ix86-64.c \ + $(top_builddir)/libpcsxcore/ix86_64/ix86_cpudetect.c \ + $(top_builddir)/libpcsxcore/ix86_64/ix86_fpu.c \ + $(top_builddir)/libpcsxcore/ix86_64/ix86_3dnow.c \ + $(top_builddir)/libpcsxcore/ix86_64/ix86_mmx.c \ + $(top_builddir)/libpcsxcore/ix86_64/ix86_sse.c \ + $(top_builddir)/libpcsxcore/ \ + $(top_builddir)/libpcsxcore/ix86/iR3000A.c \ + $(top_builddir)/libpcsxcore/ix86/ix86.c \ + $(top_builddir)/libpcsxcore/ppc/pR3000A.c \ + $(top_builddir)/libpcsxcore/ppc/ppc.c \ + $(top_builddir)/libpcsxcore/ppc/reguse.c \ + $(top_builddir)/libpcsxcore/ppc/pasm.s +@ARCH_X86_64_TRUE@am__objects_1 = iR3000A-64.$(OBJEXT) \ +@ARCH_X86_64_TRUE@ ix86-64.$(OBJEXT) ix86_cpudetect.$(OBJEXT) \ +@ARCH_X86_64_TRUE@ ix86_fpu.$(OBJEXT) ix86_3dnow.$(OBJEXT) \ +@ARCH_X86_64_TRUE@ ix86_mmx.$(OBJEXT) ix86_sse.$(OBJEXT) +@ARCH_X86_64_FALSE@@ARCH_X86_TRUE@am__objects_2 = iR3000A.$(OBJEXT) \ +@ARCH_X86_64_FALSE@@ARCH_X86_TRUE@ ix86.$(OBJEXT) +@ARCH_PPC_TRUE@am__objects_3 = pR3000A.$(OBJEXT) ppc.$(OBJEXT) \ +@ARCH_PPC_TRUE@ reguse.$(OBJEXT) libpcsxcore_a-pasm.$(OBJEXT) +am_libpcsxcore_a_OBJECTS = psxbios.$(OBJEXT) cdrom.$(OBJEXT) \ + psxcounters.$(OBJEXT) psxdma.$(OBJEXT) disr3000a.$(OBJEXT) \ + spu.$(OBJEXT) sio.$(OBJEXT) psxhw.$(OBJEXT) mdec.$(OBJEXT) \ + psxmem.$(OBJEXT) misc.$(OBJEXT) plugins.$(OBJEXT) \ + decode_xa.$(OBJEXT) r3000a.$(OBJEXT) psxinterpreter.$(OBJEXT) \ + gte.$(OBJEXT) psxhle.$(OBJEXT) cdriso.$(OBJEXT) \ + cheat.$(OBJEXT) $(am__objects_1) $(am__objects_2) \ + $(am__objects_3) +libpcsxcore_a_OBJECTS = $(am_libpcsxcore_a_OBJECTS) +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/include +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +CCASCOMPILE = $(CCAS) $(AM_CCASFLAGS) $(CCASFLAGS) +LTCCASCOMPILE = $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(CCAS) $(AM_CCASFLAGS) $(CCASFLAGS) +SOURCES = $(libpcsxcore_a_SOURCES) +DIST_SOURCES = $(am__libpcsxcore_a_SOURCES_DIST) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALSA_LIBS = @ALSA_LIBS@ +AMTAR = @AMTAR@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCAS = @CCAS@ +CCASDEPMODE = @CCASDEPMODE@ +CCASFLAGS = @CCASFLAGS@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DFOPENGL = @DFOPENGL@ +DSYMUTIL = @DSYMUTIL@ +ECHO = @ECHO@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +F77 = @F77@ +FFLAGS = @FFLAGS@ +GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GLADE2_CFLAGS = @GLADE2_CFLAGS@ +GLADE2_LIBS = @GLADE2_LIBS@ +GLIB2_CFLAGS = @GLIB2_CFLAGS@ +GLIB2_LIBS = @GLIB2_LIBS@ +GMSGFMT = @GMSGFMT@ +GMSGFMT_015 = @GMSGFMT_015@ +GREP = @GREP@ +GTK2_CFLAGS = @GTK2_CFLAGS@ +GTK2_LIBS = @GTK2_LIBS@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTLLIBS = @INTLLIBS@ +INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +LDFLAGS = @LDFLAGS@ +LIBICONV = @LIBICONV@ +LIBINTL = @LIBINTL@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LN_S = @LN_S@ +LTLIBICONV = @LTLIBICONV@ +LTLIBINTL = @LTLIBINTL@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +MSGFMT = @MSGFMT@ +MSGFMT_015 = @MSGFMT_015@ +MSGMERGE = @MSGMERGE@ +NASM = @NASM@ +NMEDIT = @NMEDIT@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +POSUB = @POSUB@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +USE_NLS = @USE_NLS@ +VERSION = @VERSION@ +XGETTEXT = @XGETTEXT@ +XGETTEXT_015 = @XGETTEXT_015@ +XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_F77 = @ac_ct_F77@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +INCLUDES = -DLOCALE_DIR=\"${datadir}/locale/\" \ + -I$(top_srcdir)/include + +noinst_LIBRARIES = libpcsxcore.a +libpcsxcore_a_SOURCES = $(top_builddir)/libpcsxcore/psxbios.c \ + $(top_builddir)/libpcsxcore/cdrom.c \ + $(top_builddir)/libpcsxcore/psxcounters.c \ + $(top_builddir)/libpcsxcore/psxdma.c \ + $(top_builddir)/libpcsxcore/disr3000a.c \ + $(top_builddir)/libpcsxcore/spu.c \ + $(top_builddir)/libpcsxcore/sio.c \ + $(top_builddir)/libpcsxcore/psxhw.c \ + $(top_builddir)/libpcsxcore/mdec.c \ + $(top_builddir)/libpcsxcore/psxmem.c \ + $(top_builddir)/libpcsxcore/misc.c \ + $(top_builddir)/libpcsxcore/plugins.c \ + $(top_builddir)/libpcsxcore/decode_xa.c \ + $(top_builddir)/libpcsxcore/r3000a.c \ + $(top_builddir)/libpcsxcore/psxinterpreter.c \ + $(top_builddir)/libpcsxcore/gte.c \ + $(top_builddir)/libpcsxcore/psxhle.c \ + $(top_builddir)/libpcsxcore/cdrom.h \ + $(top_builddir)/libpcsxcore/coff.h \ + $(top_builddir)/libpcsxcore/debug.h \ + $(top_builddir)/libpcsxcore/decode_xa.h \ + $(top_builddir)/libpcsxcore/gte.h \ + $(top_builddir)/libpcsxcore/mdec.h \ + $(top_builddir)/libpcsxcore/misc.h \ + $(top_builddir)/libpcsxcore/plugins.h \ + $(top_builddir)/libpcsxcore/psemu_plugin_defs.h \ + $(top_builddir)/libpcsxcore/psxbios.h \ + $(top_builddir)/libpcsxcore/psxcommon.h \ + $(top_builddir)/libpcsxcore/psxcounters.h \ + $(top_builddir)/libpcsxcore/psxdma.h \ + $(top_builddir)/libpcsxcore/psxhle.h \ + $(top_builddir)/libpcsxcore/psxhw.h \ + $(top_builddir)/libpcsxcore/psxmem.h \ + $(top_builddir)/libpcsxcore/r3000a.h \ + $(top_builddir)/libpcsxcore/sio.h \ + $(top_builddir)/libpcsxcore/spu.h \ + $(top_builddir)/libpcsxcore/system.h \ + $(top_builddir)/libpcsxcore/cdriso.c \ + $(top_builddir)/libpcsxcore/cdriso.h \ + $(top_builddir)/libpcsxcore/cheat.c \ + $(top_builddir)/libpcsxcore/cheat.h $(am__append_1) \ + $(am__append_2) $(am__append_3) +@ARCH_PPC_TRUE@libpcsxcore_a_CCASFLAGS = -x assembler-with-cpp -mregnames +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj .s +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu libpcsxcore/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnu libpcsxcore/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +clean-noinstLIBRARIES: + -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) +libpcsxcore.a: $(libpcsxcore_a_OBJECTS) $(libpcsxcore_a_DEPENDENCIES) + -rm -f libpcsxcore.a + $(libpcsxcore_a_AR) libpcsxcore.a $(libpcsxcore_a_OBJECTS) $(libpcsxcore_a_LIBADD) + $(RANLIB) libpcsxcore.a + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cdriso.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cdrom.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cheat.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/decode_xa.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/disr3000a.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gte.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iR3000A-64.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iR3000A.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ix86-64.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ix86.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ix86_3dnow.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ix86_cpudetect.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ix86_fpu.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ix86_mmx.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ix86_sse.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mdec.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/misc.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pR3000A.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plugins.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ppc.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/psxbios.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/psxcounters.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/psxdma.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/psxhle.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/psxhw.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/psxinterpreter.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/psxmem.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/r3000a.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/reguse.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sio.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/spu.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< + +psxbios.o: $(top_builddir)/libpcsxcore/psxbios.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT psxbios.o -MD -MP -MF $(DEPDIR)/psxbios.Tpo -c -o psxbios.o `test -f '$(top_builddir)/libpcsxcore/psxbios.c' || echo '$(srcdir)/'`$(top_builddir)/libpcsxcore/psxbios.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/psxbios.Tpo $(DEPDIR)/psxbios.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(top_builddir)/libpcsxcore/psxbios.c' object='psxbios.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o psxbios.o `test -f '$(top_builddir)/libpcsxcore/psxbios.c' || echo '$(srcdir)/'`$(top_builddir)/libpcsxcore/psxbios.c + +psxbios.obj: $(top_builddir)/libpcsxcore/psxbios.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT psxbios.obj -MD -MP -MF $(DEPDIR)/psxbios.Tpo -c -o psxbios.obj `if test -f '$(top_builddir)/libpcsxcore/psxbios.c'; then $(CYGPATH_W) '$(top_builddir)/libpcsxcore/psxbios.c'; else $(CYGPATH_W) '$(srcdir)/$(top_builddir)/libpcsxcore/psxbios.c'; fi` +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/psxbios.Tpo $(DEPDIR)/psxbios.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(top_builddir)/libpcsxcore/psxbios.c' object='psxbios.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o psxbios.obj `if test -f '$(top_builddir)/libpcsxcore/psxbios.c'; then $(CYGPATH_W) '$(top_builddir)/libpcsxcore/psxbios.c'; else $(CYGPATH_W) '$(srcdir)/$(top_builddir)/libpcsxcore/psxbios.c'; fi` + +cdrom.o: $(top_builddir)/libpcsxcore/cdrom.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cdrom.o -MD -MP -MF $(DEPDIR)/cdrom.Tpo -c -o cdrom.o `test -f '$(top_builddir)/libpcsxcore/cdrom.c' || echo '$(srcdir)/'`$(top_builddir)/libpcsxcore/cdrom.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/cdrom.Tpo $(DEPDIR)/cdrom.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(top_builddir)/libpcsxcore/cdrom.c' object='cdrom.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cdrom.o `test -f '$(top_builddir)/libpcsxcore/cdrom.c' || echo '$(srcdir)/'`$(top_builddir)/libpcsxcore/cdrom.c + +cdrom.obj: $(top_builddir)/libpcsxcore/cdrom.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cdrom.obj -MD -MP -MF $(DEPDIR)/cdrom.Tpo -c -o cdrom.obj `if test -f '$(top_builddir)/libpcsxcore/cdrom.c'; then $(CYGPATH_W) '$(top_builddir)/libpcsxcore/cdrom.c'; else $(CYGPATH_W) '$(srcdir)/$(top_builddir)/libpcsxcore/cdrom.c'; fi` +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/cdrom.Tpo $(DEPDIR)/cdrom.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(top_builddir)/libpcsxcore/cdrom.c' object='cdrom.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cdrom.obj `if test -f '$(top_builddir)/libpcsxcore/cdrom.c'; then $(CYGPATH_W) '$(top_builddir)/libpcsxcore/cdrom.c'; else $(CYGPATH_W) '$(srcdir)/$(top_builddir)/libpcsxcore/cdrom.c'; fi` + +psxcounters.o: $(top_builddir)/libpcsxcore/psxcounters.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT psxcounters.o -MD -MP -MF $(DEPDIR)/psxcounters.Tpo -c -o psxcounters.o `test -f '$(top_builddir)/libpcsxcore/psxcounters.c' || echo '$(srcdir)/'`$(top_builddir)/libpcsxcore/psxcounters.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/psxcounters.Tpo $(DEPDIR)/psxcounters.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(top_builddir)/libpcsxcore/psxcounters.c' object='psxcounters.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o psxcounters.o `test -f '$(top_builddir)/libpcsxcore/psxcounters.c' || echo '$(srcdir)/'`$(top_builddir)/libpcsxcore/psxcounters.c + +psxcounters.obj: $(top_builddir)/libpcsxcore/psxcounters.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT psxcounters.obj -MD -MP -MF $(DEPDIR)/psxcounters.Tpo -c -o psxcounters.obj `if test -f '$(top_builddir)/libpcsxcore/psxcounters.c'; then $(CYGPATH_W) '$(top_builddir)/libpcsxcore/psxcounters.c'; else $(CYGPATH_W) '$(srcdir)/$(top_builddir)/libpcsxcore/psxcounters.c'; fi` +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/psxcounters.Tpo $(DEPDIR)/psxcounters.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(top_builddir)/libpcsxcore/psxcounters.c' object='psxcounters.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o psxcounters.obj `if test -f '$(top_builddir)/libpcsxcore/psxcounters.c'; then $(CYGPATH_W) '$(top_builddir)/libpcsxcore/psxcounters.c'; else $(CYGPATH_W) '$(srcdir)/$(top_builddir)/libpcsxcore/psxcounters.c'; fi` + +psxdma.o: $(top_builddir)/libpcsxcore/psxdma.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT psxdma.o -MD -MP -MF $(DEPDIR)/psxdma.Tpo -c -o psxdma.o `test -f '$(top_builddir)/libpcsxcore/psxdma.c' || echo '$(srcdir)/'`$(top_builddir)/libpcsxcore/psxdma.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/psxdma.Tpo $(DEPDIR)/psxdma.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(top_builddir)/libpcsxcore/psxdma.c' object='psxdma.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o psxdma.o `test -f '$(top_builddir)/libpcsxcore/psxdma.c' || echo '$(srcdir)/'`$(top_builddir)/libpcsxcore/psxdma.c + +psxdma.obj: $(top_builddir)/libpcsxcore/psxdma.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT psxdma.obj -MD -MP -MF $(DEPDIR)/psxdma.Tpo -c -o psxdma.obj `if test -f '$(top_builddir)/libpcsxcore/psxdma.c'; then $(CYGPATH_W) '$(top_builddir)/libpcsxcore/psxdma.c'; else $(CYGPATH_W) '$(srcdir)/$(top_builddir)/libpcsxcore/psxdma.c'; fi` +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/psxdma.Tpo $(DEPDIR)/psxdma.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(top_builddir)/libpcsxcore/psxdma.c' object='psxdma.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o psxdma.obj `if test -f '$(top_builddir)/libpcsxcore/psxdma.c'; then $(CYGPATH_W) '$(top_builddir)/libpcsxcore/psxdma.c'; else $(CYGPATH_W) '$(srcdir)/$(top_builddir)/libpcsxcore/psxdma.c'; fi` + +disr3000a.o: $(top_builddir)/libpcsxcore/disr3000a.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT disr3000a.o -MD -MP -MF $(DEPDIR)/disr3000a.Tpo -c -o disr3000a.o `test -f '$(top_builddir)/libpcsxcore/disr3000a.c' || echo '$(srcdir)/'`$(top_builddir)/libpcsxcore/disr3000a.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/disr3000a.Tpo $(DEPDIR)/disr3000a.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(top_builddir)/libpcsxcore/disr3000a.c' object='disr3000a.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o disr3000a.o `test -f '$(top_builddir)/libpcsxcore/disr3000a.c' || echo '$(srcdir)/'`$(top_builddir)/libpcsxcore/disr3000a.c + +disr3000a.obj: $(top_builddir)/libpcsxcore/disr3000a.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT disr3000a.obj -MD -MP -MF $(DEPDIR)/disr3000a.Tpo -c -o disr3000a.obj `if test -f '$(top_builddir)/libpcsxcore/disr3000a.c'; then $(CYGPATH_W) '$(top_builddir)/libpcsxcore/disr3000a.c'; else $(CYGPATH_W) '$(srcdir)/$(top_builddir)/libpcsxcore/disr3000a.c'; fi` +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/disr3000a.Tpo $(DEPDIR)/disr3000a.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(top_builddir)/libpcsxcore/disr3000a.c' object='disr3000a.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o disr3000a.obj `if test -f '$(top_builddir)/libpcsxcore/disr3000a.c'; then $(CYGPATH_W) '$(top_builddir)/libpcsxcore/disr3000a.c'; else $(CYGPATH_W) '$(srcdir)/$(top_builddir)/libpcsxcore/disr3000a.c'; fi` + +spu.o: $(top_builddir)/libpcsxcore/spu.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT spu.o -MD -MP -MF $(DEPDIR)/spu.Tpo -c -o spu.o `test -f '$(top_builddir)/libpcsxcore/spu.c' || echo '$(srcdir)/'`$(top_builddir)/libpcsxcore/spu.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/spu.Tpo $(DEPDIR)/spu.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(top_builddir)/libpcsxcore/spu.c' object='spu.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o spu.o `test -f '$(top_builddir)/libpcsxcore/spu.c' || echo '$(srcdir)/'`$(top_builddir)/libpcsxcore/spu.c + +spu.obj: $(top_builddir)/libpcsxcore/spu.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT spu.obj -MD -MP -MF $(DEPDIR)/spu.Tpo -c -o spu.obj `if test -f '$(top_builddir)/libpcsxcore/spu.c'; then $(CYGPATH_W) '$(top_builddir)/libpcsxcore/spu.c'; else $(CYGPATH_W) '$(srcdir)/$(top_builddir)/libpcsxcore/spu.c'; fi` +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/spu.Tpo $(DEPDIR)/spu.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(top_builddir)/libpcsxcore/spu.c' object='spu.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o spu.obj `if test -f '$(top_builddir)/libpcsxcore/spu.c'; then $(CYGPATH_W) '$(top_builddir)/libpcsxcore/spu.c'; else $(CYGPATH_W) '$(srcdir)/$(top_builddir)/libpcsxcore/spu.c'; fi` + +sio.o: $(top_builddir)/libpcsxcore/sio.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sio.o -MD -MP -MF $(DEPDIR)/sio.Tpo -c -o sio.o `test -f '$(top_builddir)/libpcsxcore/sio.c' || echo '$(srcdir)/'`$(top_builddir)/libpcsxcore/sio.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/sio.Tpo $(DEPDIR)/sio.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(top_builddir)/libpcsxcore/sio.c' object='sio.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sio.o `test -f '$(top_builddir)/libpcsxcore/sio.c' || echo '$(srcdir)/'`$(top_builddir)/libpcsxcore/sio.c + +sio.obj: $(top_builddir)/libpcsxcore/sio.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sio.obj -MD -MP -MF $(DEPDIR)/sio.Tpo -c -o sio.obj `if test -f '$(top_builddir)/libpcsxcore/sio.c'; then $(CYGPATH_W) '$(top_builddir)/libpcsxcore/sio.c'; else $(CYGPATH_W) '$(srcdir)/$(top_builddir)/libpcsxcore/sio.c'; fi` +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/sio.Tpo $(DEPDIR)/sio.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(top_builddir)/libpcsxcore/sio.c' object='sio.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sio.obj `if test -f '$(top_builddir)/libpcsxcore/sio.c'; then $(CYGPATH_W) '$(top_builddir)/libpcsxcore/sio.c'; else $(CYGPATH_W) '$(srcdir)/$(top_builddir)/libpcsxcore/sio.c'; fi` + +psxhw.o: $(top_builddir)/libpcsxcore/psxhw.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT psxhw.o -MD -MP -MF $(DEPDIR)/psxhw.Tpo -c -o psxhw.o `test -f '$(top_builddir)/libpcsxcore/psxhw.c' || echo '$(srcdir)/'`$(top_builddir)/libpcsxcore/psxhw.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/psxhw.Tpo $(DEPDIR)/psxhw.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(top_builddir)/libpcsxcore/psxhw.c' object='psxhw.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o psxhw.o `test -f '$(top_builddir)/libpcsxcore/psxhw.c' || echo '$(srcdir)/'`$(top_builddir)/libpcsxcore/psxhw.c + +psxhw.obj: $(top_builddir)/libpcsxcore/psxhw.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT psxhw.obj -MD -MP -MF $(DEPDIR)/psxhw.Tpo -c -o psxhw.obj `if test -f '$(top_builddir)/libpcsxcore/psxhw.c'; then $(CYGPATH_W) '$(top_builddir)/libpcsxcore/psxhw.c'; else $(CYGPATH_W) '$(srcdir)/$(top_builddir)/libpcsxcore/psxhw.c'; fi` +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/psxhw.Tpo $(DEPDIR)/psxhw.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(top_builddir)/libpcsxcore/psxhw.c' object='psxhw.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o psxhw.obj `if test -f '$(top_builddir)/libpcsxcore/psxhw.c'; then $(CYGPATH_W) '$(top_builddir)/libpcsxcore/psxhw.c'; else $(CYGPATH_W) '$(srcdir)/$(top_builddir)/libpcsxcore/psxhw.c'; fi` + +mdec.o: $(top_builddir)/libpcsxcore/mdec.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mdec.o -MD -MP -MF $(DEPDIR)/mdec.Tpo -c -o mdec.o `test -f '$(top_builddir)/libpcsxcore/mdec.c' || echo '$(srcdir)/'`$(top_builddir)/libpcsxcore/mdec.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/mdec.Tpo $(DEPDIR)/mdec.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(top_builddir)/libpcsxcore/mdec.c' object='mdec.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mdec.o `test -f '$(top_builddir)/libpcsxcore/mdec.c' || echo '$(srcdir)/'`$(top_builddir)/libpcsxcore/mdec.c + +mdec.obj: $(top_builddir)/libpcsxcore/mdec.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mdec.obj -MD -MP -MF $(DEPDIR)/mdec.Tpo -c -o mdec.obj `if test -f '$(top_builddir)/libpcsxcore/mdec.c'; then $(CYGPATH_W) '$(top_builddir)/libpcsxcore/mdec.c'; else $(CYGPATH_W) '$(srcdir)/$(top_builddir)/libpcsxcore/mdec.c'; fi` +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/mdec.Tpo $(DEPDIR)/mdec.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(top_builddir)/libpcsxcore/mdec.c' object='mdec.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mdec.obj `if test -f '$(top_builddir)/libpcsxcore/mdec.c'; then $(CYGPATH_W) '$(top_builddir)/libpcsxcore/mdec.c'; else $(CYGPATH_W) '$(srcdir)/$(top_builddir)/libpcsxcore/mdec.c'; fi` + +psxmem.o: $(top_builddir)/libpcsxcore/psxmem.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT psxmem.o -MD -MP -MF $(DEPDIR)/psxmem.Tpo -c -o psxmem.o `test -f '$(top_builddir)/libpcsxcore/psxmem.c' || echo '$(srcdir)/'`$(top_builddir)/libpcsxcore/psxmem.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/psxmem.Tpo $(DEPDIR)/psxmem.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(top_builddir)/libpcsxcore/psxmem.c' object='psxmem.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o psxmem.o `test -f '$(top_builddir)/libpcsxcore/psxmem.c' || echo '$(srcdir)/'`$(top_builddir)/libpcsxcore/psxmem.c + +psxmem.obj: $(top_builddir)/libpcsxcore/psxmem.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT psxmem.obj -MD -MP -MF $(DEPDIR)/psxmem.Tpo -c -o psxmem.obj `if test -f '$(top_builddir)/libpcsxcore/psxmem.c'; then $(CYGPATH_W) '$(top_builddir)/libpcsxcore/psxmem.c'; else $(CYGPATH_W) '$(srcdir)/$(top_builddir)/libpcsxcore/psxmem.c'; fi` +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/psxmem.Tpo $(DEPDIR)/psxmem.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(top_builddir)/libpcsxcore/psxmem.c' object='psxmem.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o psxmem.obj `if test -f '$(top_builddir)/libpcsxcore/psxmem.c'; then $(CYGPATH_W) '$(top_builddir)/libpcsxcore/psxmem.c'; else $(CYGPATH_W) '$(srcdir)/$(top_builddir)/libpcsxcore/psxmem.c'; fi` + +misc.o: $(top_builddir)/libpcsxcore/misc.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT misc.o -MD -MP -MF $(DEPDIR)/misc.Tpo -c -o misc.o `test -f '$(top_builddir)/libpcsxcore/misc.c' || echo '$(srcdir)/'`$(top_builddir)/libpcsxcore/misc.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/misc.Tpo $(DEPDIR)/misc.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(top_builddir)/libpcsxcore/misc.c' object='misc.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o misc.o `test -f '$(top_builddir)/libpcsxcore/misc.c' || echo '$(srcdir)/'`$(top_builddir)/libpcsxcore/misc.c + +misc.obj: $(top_builddir)/libpcsxcore/misc.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT misc.obj -MD -MP -MF $(DEPDIR)/misc.Tpo -c -o misc.obj `if test -f '$(top_builddir)/libpcsxcore/misc.c'; then $(CYGPATH_W) '$(top_builddir)/libpcsxcore/misc.c'; else $(CYGPATH_W) '$(srcdir)/$(top_builddir)/libpcsxcore/misc.c'; fi` +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/misc.Tpo $(DEPDIR)/misc.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(top_builddir)/libpcsxcore/misc.c' object='misc.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o misc.obj `if test -f '$(top_builddir)/libpcsxcore/misc.c'; then $(CYGPATH_W) '$(top_builddir)/libpcsxcore/misc.c'; else $(CYGPATH_W) '$(srcdir)/$(top_builddir)/libpcsxcore/misc.c'; fi` + +plugins.o: $(top_builddir)/libpcsxcore/plugins.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT plugins.o -MD -MP -MF $(DEPDIR)/plugins.Tpo -c -o plugins.o `test -f '$(top_builddir)/libpcsxcore/plugins.c' || echo '$(srcdir)/'`$(top_builddir)/libpcsxcore/plugins.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/plugins.Tpo $(DEPDIR)/plugins.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(top_builddir)/libpcsxcore/plugins.c' object='plugins.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o plugins.o `test -f '$(top_builddir)/libpcsxcore/plugins.c' || echo '$(srcdir)/'`$(top_builddir)/libpcsxcore/plugins.c + +plugins.obj: $(top_builddir)/libpcsxcore/plugins.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT plugins.obj -MD -MP -MF $(DEPDIR)/plugins.Tpo -c -o plugins.obj `if test -f '$(top_builddir)/libpcsxcore/plugins.c'; then $(CYGPATH_W) '$(top_builddir)/libpcsxcore/plugins.c'; else $(CYGPATH_W) '$(srcdir)/$(top_builddir)/libpcsxcore/plugins.c'; fi` +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/plugins.Tpo $(DEPDIR)/plugins.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(top_builddir)/libpcsxcore/plugins.c' object='plugins.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o plugins.obj `if test -f '$(top_builddir)/libpcsxcore/plugins.c'; then $(CYGPATH_W) '$(top_builddir)/libpcsxcore/plugins.c'; else $(CYGPATH_W) '$(srcdir)/$(top_builddir)/libpcsxcore/plugins.c'; fi` + +decode_xa.o: $(top_builddir)/libpcsxcore/decode_xa.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT decode_xa.o -MD -MP -MF $(DEPDIR)/decode_xa.Tpo -c -o decode_xa.o `test -f '$(top_builddir)/libpcsxcore/decode_xa.c' || echo '$(srcdir)/'`$(top_builddir)/libpcsxcore/decode_xa.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/decode_xa.Tpo $(DEPDIR)/decode_xa.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(top_builddir)/libpcsxcore/decode_xa.c' object='decode_xa.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o decode_xa.o `test -f '$(top_builddir)/libpcsxcore/decode_xa.c' || echo '$(srcdir)/'`$(top_builddir)/libpcsxcore/decode_xa.c + +decode_xa.obj: $(top_builddir)/libpcsxcore/decode_xa.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT decode_xa.obj -MD -MP -MF $(DEPDIR)/decode_xa.Tpo -c -o decode_xa.obj `if test -f '$(top_builddir)/libpcsxcore/decode_xa.c'; then $(CYGPATH_W) '$(top_builddir)/libpcsxcore/decode_xa.c'; else $(CYGPATH_W) '$(srcdir)/$(top_builddir)/libpcsxcore/decode_xa.c'; fi` +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/decode_xa.Tpo $(DEPDIR)/decode_xa.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(top_builddir)/libpcsxcore/decode_xa.c' object='decode_xa.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o decode_xa.obj `if test -f '$(top_builddir)/libpcsxcore/decode_xa.c'; then $(CYGPATH_W) '$(top_builddir)/libpcsxcore/decode_xa.c'; else $(CYGPATH_W) '$(srcdir)/$(top_builddir)/libpcsxcore/decode_xa.c'; fi` + +r3000a.o: $(top_builddir)/libpcsxcore/r3000a.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT r3000a.o -MD -MP -MF $(DEPDIR)/r3000a.Tpo -c -o r3000a.o `test -f '$(top_builddir)/libpcsxcore/r3000a.c' || echo '$(srcdir)/'`$(top_builddir)/libpcsxcore/r3000a.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/r3000a.Tpo $(DEPDIR)/r3000a.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(top_builddir)/libpcsxcore/r3000a.c' object='r3000a.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o r3000a.o `test -f '$(top_builddir)/libpcsxcore/r3000a.c' || echo '$(srcdir)/'`$(top_builddir)/libpcsxcore/r3000a.c + +r3000a.obj: $(top_builddir)/libpcsxcore/r3000a.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT r3000a.obj -MD -MP -MF $(DEPDIR)/r3000a.Tpo -c -o r3000a.obj `if test -f '$(top_builddir)/libpcsxcore/r3000a.c'; then $(CYGPATH_W) '$(top_builddir)/libpcsxcore/r3000a.c'; else $(CYGPATH_W) '$(srcdir)/$(top_builddir)/libpcsxcore/r3000a.c'; fi` +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/r3000a.Tpo $(DEPDIR)/r3000a.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(top_builddir)/libpcsxcore/r3000a.c' object='r3000a.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o r3000a.obj `if test -f '$(top_builddir)/libpcsxcore/r3000a.c'; then $(CYGPATH_W) '$(top_builddir)/libpcsxcore/r3000a.c'; else $(CYGPATH_W) '$(srcdir)/$(top_builddir)/libpcsxcore/r3000a.c'; fi` + +psxinterpreter.o: $(top_builddir)/libpcsxcore/psxinterpreter.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT psxinterpreter.o -MD -MP -MF $(DEPDIR)/psxinterpreter.Tpo -c -o psxinterpreter.o `test -f '$(top_builddir)/libpcsxcore/psxinterpreter.c' || echo '$(srcdir)/'`$(top_builddir)/libpcsxcore/psxinterpreter.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/psxinterpreter.Tpo $(DEPDIR)/psxinterpreter.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(top_builddir)/libpcsxcore/psxinterpreter.c' object='psxinterpreter.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o psxinterpreter.o `test -f '$(top_builddir)/libpcsxcore/psxinterpreter.c' || echo '$(srcdir)/'`$(top_builddir)/libpcsxcore/psxinterpreter.c + +psxinterpreter.obj: $(top_builddir)/libpcsxcore/psxinterpreter.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT psxinterpreter.obj -MD -MP -MF $(DEPDIR)/psxinterpreter.Tpo -c -o psxinterpreter.obj `if test -f '$(top_builddir)/libpcsxcore/psxinterpreter.c'; then $(CYGPATH_W) '$(top_builddir)/libpcsxcore/psxinterpreter.c'; else $(CYGPATH_W) '$(srcdir)/$(top_builddir)/libpcsxcore/psxinterpreter.c'; fi` +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/psxinterpreter.Tpo $(DEPDIR)/psxinterpreter.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(top_builddir)/libpcsxcore/psxinterpreter.c' object='psxinterpreter.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o psxinterpreter.obj `if test -f '$(top_builddir)/libpcsxcore/psxinterpreter.c'; then $(CYGPATH_W) '$(top_builddir)/libpcsxcore/psxinterpreter.c'; else $(CYGPATH_W) '$(srcdir)/$(top_builddir)/libpcsxcore/psxinterpreter.c'; fi` + +gte.o: $(top_builddir)/libpcsxcore/gte.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT gte.o -MD -MP -MF $(DEPDIR)/gte.Tpo -c -o gte.o `test -f '$(top_builddir)/libpcsxcore/gte.c' || echo '$(srcdir)/'`$(top_builddir)/libpcsxcore/gte.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/gte.Tpo $(DEPDIR)/gte.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(top_builddir)/libpcsxcore/gte.c' object='gte.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o gte.o `test -f '$(top_builddir)/libpcsxcore/gte.c' || echo '$(srcdir)/'`$(top_builddir)/libpcsxcore/gte.c + +gte.obj: $(top_builddir)/libpcsxcore/gte.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT gte.obj -MD -MP -MF $(DEPDIR)/gte.Tpo -c -o gte.obj `if test -f '$(top_builddir)/libpcsxcore/gte.c'; then $(CYGPATH_W) '$(top_builddir)/libpcsxcore/gte.c'; else $(CYGPATH_W) '$(srcdir)/$(top_builddir)/libpcsxcore/gte.c'; fi` +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/gte.Tpo $(DEPDIR)/gte.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(top_builddir)/libpcsxcore/gte.c' object='gte.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o gte.obj `if test -f '$(top_builddir)/libpcsxcore/gte.c'; then $(CYGPATH_W) '$(top_builddir)/libpcsxcore/gte.c'; else $(CYGPATH_W) '$(srcdir)/$(top_builddir)/libpcsxcore/gte.c'; fi` + +psxhle.o: $(top_builddir)/libpcsxcore/psxhle.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT psxhle.o -MD -MP -MF $(DEPDIR)/psxhle.Tpo -c -o psxhle.o `test -f '$(top_builddir)/libpcsxcore/psxhle.c' || echo '$(srcdir)/'`$(top_builddir)/libpcsxcore/psxhle.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/psxhle.Tpo $(DEPDIR)/psxhle.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(top_builddir)/libpcsxcore/psxhle.c' object='psxhle.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o psxhle.o `test -f '$(top_builddir)/libpcsxcore/psxhle.c' || echo '$(srcdir)/'`$(top_builddir)/libpcsxcore/psxhle.c + +psxhle.obj: $(top_builddir)/libpcsxcore/psxhle.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT psxhle.obj -MD -MP -MF $(DEPDIR)/psxhle.Tpo -c -o psxhle.obj `if test -f '$(top_builddir)/libpcsxcore/psxhle.c'; then $(CYGPATH_W) '$(top_builddir)/libpcsxcore/psxhle.c'; else $(CYGPATH_W) '$(srcdir)/$(top_builddir)/libpcsxcore/psxhle.c'; fi` +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/psxhle.Tpo $(DEPDIR)/psxhle.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(top_builddir)/libpcsxcore/psxhle.c' object='psxhle.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o psxhle.obj `if test -f '$(top_builddir)/libpcsxcore/psxhle.c'; then $(CYGPATH_W) '$(top_builddir)/libpcsxcore/psxhle.c'; else $(CYGPATH_W) '$(srcdir)/$(top_builddir)/libpcsxcore/psxhle.c'; fi` + +cdriso.o: $(top_builddir)/libpcsxcore/cdriso.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cdriso.o -MD -MP -MF $(DEPDIR)/cdriso.Tpo -c -o cdriso.o `test -f '$(top_builddir)/libpcsxcore/cdriso.c' || echo '$(srcdir)/'`$(top_builddir)/libpcsxcore/cdriso.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/cdriso.Tpo $(DEPDIR)/cdriso.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(top_builddir)/libpcsxcore/cdriso.c' object='cdriso.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cdriso.o `test -f '$(top_builddir)/libpcsxcore/cdriso.c' || echo '$(srcdir)/'`$(top_builddir)/libpcsxcore/cdriso.c + +cdriso.obj: $(top_builddir)/libpcsxcore/cdriso.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cdriso.obj -MD -MP -MF $(DEPDIR)/cdriso.Tpo -c -o cdriso.obj `if test -f '$(top_builddir)/libpcsxcore/cdriso.c'; then $(CYGPATH_W) '$(top_builddir)/libpcsxcore/cdriso.c'; else $(CYGPATH_W) '$(srcdir)/$(top_builddir)/libpcsxcore/cdriso.c'; fi` +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/cdriso.Tpo $(DEPDIR)/cdriso.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(top_builddir)/libpcsxcore/cdriso.c' object='cdriso.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cdriso.obj `if test -f '$(top_builddir)/libpcsxcore/cdriso.c'; then $(CYGPATH_W) '$(top_builddir)/libpcsxcore/cdriso.c'; else $(CYGPATH_W) '$(srcdir)/$(top_builddir)/libpcsxcore/cdriso.c'; fi` + +cheat.o: $(top_builddir)/libpcsxcore/cheat.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cheat.o -MD -MP -MF $(DEPDIR)/cheat.Tpo -c -o cheat.o `test -f '$(top_builddir)/libpcsxcore/cheat.c' || echo '$(srcdir)/'`$(top_builddir)/libpcsxcore/cheat.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/cheat.Tpo $(DEPDIR)/cheat.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(top_builddir)/libpcsxcore/cheat.c' object='cheat.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cheat.o `test -f '$(top_builddir)/libpcsxcore/cheat.c' || echo '$(srcdir)/'`$(top_builddir)/libpcsxcore/cheat.c + +cheat.obj: $(top_builddir)/libpcsxcore/cheat.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cheat.obj -MD -MP -MF $(DEPDIR)/cheat.Tpo -c -o cheat.obj `if test -f '$(top_builddir)/libpcsxcore/cheat.c'; then $(CYGPATH_W) '$(top_builddir)/libpcsxcore/cheat.c'; else $(CYGPATH_W) '$(srcdir)/$(top_builddir)/libpcsxcore/cheat.c'; fi` +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/cheat.Tpo $(DEPDIR)/cheat.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(top_builddir)/libpcsxcore/cheat.c' object='cheat.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cheat.obj `if test -f '$(top_builddir)/libpcsxcore/cheat.c'; then $(CYGPATH_W) '$(top_builddir)/libpcsxcore/cheat.c'; else $(CYGPATH_W) '$(srcdir)/$(top_builddir)/libpcsxcore/cheat.c'; fi` + +iR3000A-64.o: $(top_builddir)/libpcsxcore/ix86_64/iR3000A-64.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT iR3000A-64.o -MD -MP -MF $(DEPDIR)/iR3000A-64.Tpo -c -o iR3000A-64.o `test -f '$(top_builddir)/libpcsxcore/ix86_64/iR3000A-64.c' || echo '$(srcdir)/'`$(top_builddir)/libpcsxcore/ix86_64/iR3000A-64.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/iR3000A-64.Tpo $(DEPDIR)/iR3000A-64.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(top_builddir)/libpcsxcore/ix86_64/iR3000A-64.c' object='iR3000A-64.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o iR3000A-64.o `test -f '$(top_builddir)/libpcsxcore/ix86_64/iR3000A-64.c' || echo '$(srcdir)/'`$(top_builddir)/libpcsxcore/ix86_64/iR3000A-64.c + +iR3000A-64.obj: $(top_builddir)/libpcsxcore/ix86_64/iR3000A-64.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT iR3000A-64.obj -MD -MP -MF $(DEPDIR)/iR3000A-64.Tpo -c -o iR3000A-64.obj `if test -f '$(top_builddir)/libpcsxcore/ix86_64/iR3000A-64.c'; then $(CYGPATH_W) '$(top_builddir)/libpcsxcore/ix86_64/iR3000A-64.c'; else $(CYGPATH_W) '$(srcdir)/$(top_builddir)/libpcsxcore/ix86_64/iR3000A-64.c'; fi` +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/iR3000A-64.Tpo $(DEPDIR)/iR3000A-64.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(top_builddir)/libpcsxcore/ix86_64/iR3000A-64.c' object='iR3000A-64.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o iR3000A-64.obj `if test -f '$(top_builddir)/libpcsxcore/ix86_64/iR3000A-64.c'; then $(CYGPATH_W) '$(top_builddir)/libpcsxcore/ix86_64/iR3000A-64.c'; else $(CYGPATH_W) '$(srcdir)/$(top_builddir)/libpcsxcore/ix86_64/iR3000A-64.c'; fi` + +ix86-64.o: $(top_builddir)/libpcsxcore/ix86_64/ix86-64.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ix86-64.o -MD -MP -MF $(DEPDIR)/ix86-64.Tpo -c -o ix86-64.o `test -f '$(top_builddir)/libpcsxcore/ix86_64/ix86-64.c' || echo '$(srcdir)/'`$(top_builddir)/libpcsxcore/ix86_64/ix86-64.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/ix86-64.Tpo $(DEPDIR)/ix86-64.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(top_builddir)/libpcsxcore/ix86_64/ix86-64.c' object='ix86-64.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ix86-64.o `test -f '$(top_builddir)/libpcsxcore/ix86_64/ix86-64.c' || echo '$(srcdir)/'`$(top_builddir)/libpcsxcore/ix86_64/ix86-64.c + +ix86-64.obj: $(top_builddir)/libpcsxcore/ix86_64/ix86-64.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ix86-64.obj -MD -MP -MF $(DEPDIR)/ix86-64.Tpo -c -o ix86-64.obj `if test -f '$(top_builddir)/libpcsxcore/ix86_64/ix86-64.c'; then $(CYGPATH_W) '$(top_builddir)/libpcsxcore/ix86_64/ix86-64.c'; else $(CYGPATH_W) '$(srcdir)/$(top_builddir)/libpcsxcore/ix86_64/ix86-64.c'; fi` +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/ix86-64.Tpo $(DEPDIR)/ix86-64.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(top_builddir)/libpcsxcore/ix86_64/ix86-64.c' object='ix86-64.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ix86-64.obj `if test -f '$(top_builddir)/libpcsxcore/ix86_64/ix86-64.c'; then $(CYGPATH_W) '$(top_builddir)/libpcsxcore/ix86_64/ix86-64.c'; else $(CYGPATH_W) '$(srcdir)/$(top_builddir)/libpcsxcore/ix86_64/ix86-64.c'; fi` + +ix86_cpudetect.o: $(top_builddir)/libpcsxcore/ix86_64/ix86_cpudetect.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ix86_cpudetect.o -MD -MP -MF $(DEPDIR)/ix86_cpudetect.Tpo -c -o ix86_cpudetect.o `test -f '$(top_builddir)/libpcsxcore/ix86_64/ix86_cpudetect.c' || echo '$(srcdir)/'`$(top_builddir)/libpcsxcore/ix86_64/ix86_cpudetect.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/ix86_cpudetect.Tpo $(DEPDIR)/ix86_cpudetect.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(top_builddir)/libpcsxcore/ix86_64/ix86_cpudetect.c' object='ix86_cpudetect.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ix86_cpudetect.o `test -f '$(top_builddir)/libpcsxcore/ix86_64/ix86_cpudetect.c' || echo '$(srcdir)/'`$(top_builddir)/libpcsxcore/ix86_64/ix86_cpudetect.c + +ix86_cpudetect.obj: $(top_builddir)/libpcsxcore/ix86_64/ix86_cpudetect.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ix86_cpudetect.obj -MD -MP -MF $(DEPDIR)/ix86_cpudetect.Tpo -c -o ix86_cpudetect.obj `if test -f '$(top_builddir)/libpcsxcore/ix86_64/ix86_cpudetect.c'; then $(CYGPATH_W) '$(top_builddir)/libpcsxcore/ix86_64/ix86_cpudetect.c'; else $(CYGPATH_W) '$(srcdir)/$(top_builddir)/libpcsxcore/ix86_64/ix86_cpudetect.c'; fi` +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/ix86_cpudetect.Tpo $(DEPDIR)/ix86_cpudetect.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(top_builddir)/libpcsxcore/ix86_64/ix86_cpudetect.c' object='ix86_cpudetect.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ix86_cpudetect.obj `if test -f '$(top_builddir)/libpcsxcore/ix86_64/ix86_cpudetect.c'; then $(CYGPATH_W) '$(top_builddir)/libpcsxcore/ix86_64/ix86_cpudetect.c'; else $(CYGPATH_W) '$(srcdir)/$(top_builddir)/libpcsxcore/ix86_64/ix86_cpudetect.c'; fi` + +ix86_fpu.o: $(top_builddir)/libpcsxcore/ix86_64/ix86_fpu.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ix86_fpu.o -MD -MP -MF $(DEPDIR)/ix86_fpu.Tpo -c -o ix86_fpu.o `test -f '$(top_builddir)/libpcsxcore/ix86_64/ix86_fpu.c' || echo '$(srcdir)/'`$(top_builddir)/libpcsxcore/ix86_64/ix86_fpu.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/ix86_fpu.Tpo $(DEPDIR)/ix86_fpu.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(top_builddir)/libpcsxcore/ix86_64/ix86_fpu.c' object='ix86_fpu.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ix86_fpu.o `test -f '$(top_builddir)/libpcsxcore/ix86_64/ix86_fpu.c' || echo '$(srcdir)/'`$(top_builddir)/libpcsxcore/ix86_64/ix86_fpu.c + +ix86_fpu.obj: $(top_builddir)/libpcsxcore/ix86_64/ix86_fpu.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ix86_fpu.obj -MD -MP -MF $(DEPDIR)/ix86_fpu.Tpo -c -o ix86_fpu.obj `if test -f '$(top_builddir)/libpcsxcore/ix86_64/ix86_fpu.c'; then $(CYGPATH_W) '$(top_builddir)/libpcsxcore/ix86_64/ix86_fpu.c'; else $(CYGPATH_W) '$(srcdir)/$(top_builddir)/libpcsxcore/ix86_64/ix86_fpu.c'; fi` +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/ix86_fpu.Tpo $(DEPDIR)/ix86_fpu.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(top_builddir)/libpcsxcore/ix86_64/ix86_fpu.c' object='ix86_fpu.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ix86_fpu.obj `if test -f '$(top_builddir)/libpcsxcore/ix86_64/ix86_fpu.c'; then $(CYGPATH_W) '$(top_builddir)/libpcsxcore/ix86_64/ix86_fpu.c'; else $(CYGPATH_W) '$(srcdir)/$(top_builddir)/libpcsxcore/ix86_64/ix86_fpu.c'; fi` + +ix86_3dnow.o: $(top_builddir)/libpcsxcore/ix86_64/ix86_3dnow.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ix86_3dnow.o -MD -MP -MF $(DEPDIR)/ix86_3dnow.Tpo -c -o ix86_3dnow.o `test -f '$(top_builddir)/libpcsxcore/ix86_64/ix86_3dnow.c' || echo '$(srcdir)/'`$(top_builddir)/libpcsxcore/ix86_64/ix86_3dnow.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/ix86_3dnow.Tpo $(DEPDIR)/ix86_3dnow.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(top_builddir)/libpcsxcore/ix86_64/ix86_3dnow.c' object='ix86_3dnow.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ix86_3dnow.o `test -f '$(top_builddir)/libpcsxcore/ix86_64/ix86_3dnow.c' || echo '$(srcdir)/'`$(top_builddir)/libpcsxcore/ix86_64/ix86_3dnow.c + +ix86_3dnow.obj: $(top_builddir)/libpcsxcore/ix86_64/ix86_3dnow.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ix86_3dnow.obj -MD -MP -MF $(DEPDIR)/ix86_3dnow.Tpo -c -o ix86_3dnow.obj `if test -f '$(top_builddir)/libpcsxcore/ix86_64/ix86_3dnow.c'; then $(CYGPATH_W) '$(top_builddir)/libpcsxcore/ix86_64/ix86_3dnow.c'; else $(CYGPATH_W) '$(srcdir)/$(top_builddir)/libpcsxcore/ix86_64/ix86_3dnow.c'; fi` +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/ix86_3dnow.Tpo $(DEPDIR)/ix86_3dnow.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(top_builddir)/libpcsxcore/ix86_64/ix86_3dnow.c' object='ix86_3dnow.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ix86_3dnow.obj `if test -f '$(top_builddir)/libpcsxcore/ix86_64/ix86_3dnow.c'; then $(CYGPATH_W) '$(top_builddir)/libpcsxcore/ix86_64/ix86_3dnow.c'; else $(CYGPATH_W) '$(srcdir)/$(top_builddir)/libpcsxcore/ix86_64/ix86_3dnow.c'; fi` + +ix86_mmx.o: $(top_builddir)/libpcsxcore/ix86_64/ix86_mmx.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ix86_mmx.o -MD -MP -MF $(DEPDIR)/ix86_mmx.Tpo -c -o ix86_mmx.o `test -f '$(top_builddir)/libpcsxcore/ix86_64/ix86_mmx.c' || echo '$(srcdir)/'`$(top_builddir)/libpcsxcore/ix86_64/ix86_mmx.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/ix86_mmx.Tpo $(DEPDIR)/ix86_mmx.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(top_builddir)/libpcsxcore/ix86_64/ix86_mmx.c' object='ix86_mmx.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ix86_mmx.o `test -f '$(top_builddir)/libpcsxcore/ix86_64/ix86_mmx.c' || echo '$(srcdir)/'`$(top_builddir)/libpcsxcore/ix86_64/ix86_mmx.c + +ix86_mmx.obj: $(top_builddir)/libpcsxcore/ix86_64/ix86_mmx.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ix86_mmx.obj -MD -MP -MF $(DEPDIR)/ix86_mmx.Tpo -c -o ix86_mmx.obj `if test -f '$(top_builddir)/libpcsxcore/ix86_64/ix86_mmx.c'; then $(CYGPATH_W) '$(top_builddir)/libpcsxcore/ix86_64/ix86_mmx.c'; else $(CYGPATH_W) '$(srcdir)/$(top_builddir)/libpcsxcore/ix86_64/ix86_mmx.c'; fi` +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/ix86_mmx.Tpo $(DEPDIR)/ix86_mmx.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(top_builddir)/libpcsxcore/ix86_64/ix86_mmx.c' object='ix86_mmx.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ix86_mmx.obj `if test -f '$(top_builddir)/libpcsxcore/ix86_64/ix86_mmx.c'; then $(CYGPATH_W) '$(top_builddir)/libpcsxcore/ix86_64/ix86_mmx.c'; else $(CYGPATH_W) '$(srcdir)/$(top_builddir)/libpcsxcore/ix86_64/ix86_mmx.c'; fi` + +ix86_sse.o: $(top_builddir)/libpcsxcore/ix86_64/ix86_sse.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ix86_sse.o -MD -MP -MF $(DEPDIR)/ix86_sse.Tpo -c -o ix86_sse.o `test -f '$(top_builddir)/libpcsxcore/ix86_64/ix86_sse.c' || echo '$(srcdir)/'`$(top_builddir)/libpcsxcore/ix86_64/ix86_sse.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/ix86_sse.Tpo $(DEPDIR)/ix86_sse.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(top_builddir)/libpcsxcore/ix86_64/ix86_sse.c' object='ix86_sse.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ix86_sse.o `test -f '$(top_builddir)/libpcsxcore/ix86_64/ix86_sse.c' || echo '$(srcdir)/'`$(top_builddir)/libpcsxcore/ix86_64/ix86_sse.c + +ix86_sse.obj: $(top_builddir)/libpcsxcore/ix86_64/ix86_sse.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ix86_sse.obj -MD -MP -MF $(DEPDIR)/ix86_sse.Tpo -c -o ix86_sse.obj `if test -f '$(top_builddir)/libpcsxcore/ix86_64/ix86_sse.c'; then $(CYGPATH_W) '$(top_builddir)/libpcsxcore/ix86_64/ix86_sse.c'; else $(CYGPATH_W) '$(srcdir)/$(top_builddir)/libpcsxcore/ix86_64/ix86_sse.c'; fi` +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/ix86_sse.Tpo $(DEPDIR)/ix86_sse.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(top_builddir)/libpcsxcore/ix86_64/ix86_sse.c' object='ix86_sse.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ix86_sse.obj `if test -f '$(top_builddir)/libpcsxcore/ix86_64/ix86_sse.c'; then $(CYGPATH_W) '$(top_builddir)/libpcsxcore/ix86_64/ix86_sse.c'; else $(CYGPATH_W) '$(srcdir)/$(top_builddir)/libpcsxcore/ix86_64/ix86_sse.c'; fi` + +iR3000A.o: $(top_builddir)/libpcsxcore/ix86/iR3000A.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT iR3000A.o -MD -MP -MF $(DEPDIR)/iR3000A.Tpo -c -o iR3000A.o `test -f '$(top_builddir)/libpcsxcore/ix86/iR3000A.c' || echo '$(srcdir)/'`$(top_builddir)/libpcsxcore/ix86/iR3000A.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/iR3000A.Tpo $(DEPDIR)/iR3000A.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(top_builddir)/libpcsxcore/ix86/iR3000A.c' object='iR3000A.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o iR3000A.o `test -f '$(top_builddir)/libpcsxcore/ix86/iR3000A.c' || echo '$(srcdir)/'`$(top_builddir)/libpcsxcore/ix86/iR3000A.c + +iR3000A.obj: $(top_builddir)/libpcsxcore/ix86/iR3000A.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT iR3000A.obj -MD -MP -MF $(DEPDIR)/iR3000A.Tpo -c -o iR3000A.obj `if test -f '$(top_builddir)/libpcsxcore/ix86/iR3000A.c'; then $(CYGPATH_W) '$(top_builddir)/libpcsxcore/ix86/iR3000A.c'; else $(CYGPATH_W) '$(srcdir)/$(top_builddir)/libpcsxcore/ix86/iR3000A.c'; fi` +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/iR3000A.Tpo $(DEPDIR)/iR3000A.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(top_builddir)/libpcsxcore/ix86/iR3000A.c' object='iR3000A.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o iR3000A.obj `if test -f '$(top_builddir)/libpcsxcore/ix86/iR3000A.c'; then $(CYGPATH_W) '$(top_builddir)/libpcsxcore/ix86/iR3000A.c'; else $(CYGPATH_W) '$(srcdir)/$(top_builddir)/libpcsxcore/ix86/iR3000A.c'; fi` + +ix86.o: $(top_builddir)/libpcsxcore/ix86/ix86.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ix86.o -MD -MP -MF $(DEPDIR)/ix86.Tpo -c -o ix86.o `test -f '$(top_builddir)/libpcsxcore/ix86/ix86.c' || echo '$(srcdir)/'`$(top_builddir)/libpcsxcore/ix86/ix86.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/ix86.Tpo $(DEPDIR)/ix86.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(top_builddir)/libpcsxcore/ix86/ix86.c' object='ix86.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ix86.o `test -f '$(top_builddir)/libpcsxcore/ix86/ix86.c' || echo '$(srcdir)/'`$(top_builddir)/libpcsxcore/ix86/ix86.c + +ix86.obj: $(top_builddir)/libpcsxcore/ix86/ix86.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ix86.obj -MD -MP -MF $(DEPDIR)/ix86.Tpo -c -o ix86.obj `if test -f '$(top_builddir)/libpcsxcore/ix86/ix86.c'; then $(CYGPATH_W) '$(top_builddir)/libpcsxcore/ix86/ix86.c'; else $(CYGPATH_W) '$(srcdir)/$(top_builddir)/libpcsxcore/ix86/ix86.c'; fi` +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/ix86.Tpo $(DEPDIR)/ix86.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(top_builddir)/libpcsxcore/ix86/ix86.c' object='ix86.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ix86.obj `if test -f '$(top_builddir)/libpcsxcore/ix86/ix86.c'; then $(CYGPATH_W) '$(top_builddir)/libpcsxcore/ix86/ix86.c'; else $(CYGPATH_W) '$(srcdir)/$(top_builddir)/libpcsxcore/ix86/ix86.c'; fi` + +pR3000A.o: $(top_builddir)/libpcsxcore/ppc/pR3000A.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT pR3000A.o -MD -MP -MF $(DEPDIR)/pR3000A.Tpo -c -o pR3000A.o `test -f '$(top_builddir)/libpcsxcore/ppc/pR3000A.c' || echo '$(srcdir)/'`$(top_builddir)/libpcsxcore/ppc/pR3000A.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/pR3000A.Tpo $(DEPDIR)/pR3000A.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(top_builddir)/libpcsxcore/ppc/pR3000A.c' object='pR3000A.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o pR3000A.o `test -f '$(top_builddir)/libpcsxcore/ppc/pR3000A.c' || echo '$(srcdir)/'`$(top_builddir)/libpcsxcore/ppc/pR3000A.c + +pR3000A.obj: $(top_builddir)/libpcsxcore/ppc/pR3000A.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT pR3000A.obj -MD -MP -MF $(DEPDIR)/pR3000A.Tpo -c -o pR3000A.obj `if test -f '$(top_builddir)/libpcsxcore/ppc/pR3000A.c'; then $(CYGPATH_W) '$(top_builddir)/libpcsxcore/ppc/pR3000A.c'; else $(CYGPATH_W) '$(srcdir)/$(top_builddir)/libpcsxcore/ppc/pR3000A.c'; fi` +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/pR3000A.Tpo $(DEPDIR)/pR3000A.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(top_builddir)/libpcsxcore/ppc/pR3000A.c' object='pR3000A.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o pR3000A.obj `if test -f '$(top_builddir)/libpcsxcore/ppc/pR3000A.c'; then $(CYGPATH_W) '$(top_builddir)/libpcsxcore/ppc/pR3000A.c'; else $(CYGPATH_W) '$(srcdir)/$(top_builddir)/libpcsxcore/ppc/pR3000A.c'; fi` + +ppc.o: $(top_builddir)/libpcsxcore/ppc/ppc.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ppc.o -MD -MP -MF $(DEPDIR)/ppc.Tpo -c -o ppc.o `test -f '$(top_builddir)/libpcsxcore/ppc/ppc.c' || echo '$(srcdir)/'`$(top_builddir)/libpcsxcore/ppc/ppc.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/ppc.Tpo $(DEPDIR)/ppc.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(top_builddir)/libpcsxcore/ppc/ppc.c' object='ppc.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ppc.o `test -f '$(top_builddir)/libpcsxcore/ppc/ppc.c' || echo '$(srcdir)/'`$(top_builddir)/libpcsxcore/ppc/ppc.c + +ppc.obj: $(top_builddir)/libpcsxcore/ppc/ppc.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ppc.obj -MD -MP -MF $(DEPDIR)/ppc.Tpo -c -o ppc.obj `if test -f '$(top_builddir)/libpcsxcore/ppc/ppc.c'; then $(CYGPATH_W) '$(top_builddir)/libpcsxcore/ppc/ppc.c'; else $(CYGPATH_W) '$(srcdir)/$(top_builddir)/libpcsxcore/ppc/ppc.c'; fi` +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/ppc.Tpo $(DEPDIR)/ppc.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(top_builddir)/libpcsxcore/ppc/ppc.c' object='ppc.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ppc.obj `if test -f '$(top_builddir)/libpcsxcore/ppc/ppc.c'; then $(CYGPATH_W) '$(top_builddir)/libpcsxcore/ppc/ppc.c'; else $(CYGPATH_W) '$(srcdir)/$(top_builddir)/libpcsxcore/ppc/ppc.c'; fi` + +reguse.o: $(top_builddir)/libpcsxcore/ppc/reguse.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT reguse.o -MD -MP -MF $(DEPDIR)/reguse.Tpo -c -o reguse.o `test -f '$(top_builddir)/libpcsxcore/ppc/reguse.c' || echo '$(srcdir)/'`$(top_builddir)/libpcsxcore/ppc/reguse.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/reguse.Tpo $(DEPDIR)/reguse.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(top_builddir)/libpcsxcore/ppc/reguse.c' object='reguse.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o reguse.o `test -f '$(top_builddir)/libpcsxcore/ppc/reguse.c' || echo '$(srcdir)/'`$(top_builddir)/libpcsxcore/ppc/reguse.c + +reguse.obj: $(top_builddir)/libpcsxcore/ppc/reguse.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT reguse.obj -MD -MP -MF $(DEPDIR)/reguse.Tpo -c -o reguse.obj `if test -f '$(top_builddir)/libpcsxcore/ppc/reguse.c'; then $(CYGPATH_W) '$(top_builddir)/libpcsxcore/ppc/reguse.c'; else $(CYGPATH_W) '$(srcdir)/$(top_builddir)/libpcsxcore/ppc/reguse.c'; fi` +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/reguse.Tpo $(DEPDIR)/reguse.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(top_builddir)/libpcsxcore/ppc/reguse.c' object='reguse.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o reguse.obj `if test -f '$(top_builddir)/libpcsxcore/ppc/reguse.c'; then $(CYGPATH_W) '$(top_builddir)/libpcsxcore/ppc/reguse.c'; else $(CYGPATH_W) '$(srcdir)/$(top_builddir)/libpcsxcore/ppc/reguse.c'; fi` + +.s.o: + $(CCASCOMPILE) -c -o $@ $< + +.s.obj: + $(CCASCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.s.lo: + $(LTCCASCOMPILE) -c -o $@ $< + +libpcsxcore_a-pasm.o: $(top_builddir)/libpcsxcore/ppc/pasm.s + $(CCAS) $(libpcsxcore_a_CCASFLAGS) $(CCASFLAGS) -c -o libpcsxcore_a-pasm.o `test -f '$(top_builddir)/libpcsxcore/ppc/pasm.s' || echo '$(srcdir)/'`$(top_builddir)/libpcsxcore/ppc/pasm.s + +libpcsxcore_a-pasm.obj: $(top_builddir)/libpcsxcore/ppc/pasm.s + $(CCAS) $(libpcsxcore_a_CCASFLAGS) $(CCASFLAGS) -c -o libpcsxcore_a-pasm.obj `if test -f '$(top_builddir)/libpcsxcore/ppc/pasm.s'; then $(CYGPATH_W) '$(top_builddir)/libpcsxcore/ppc/pasm.s'; else $(CYGPATH_W) '$(srcdir)/$(top_builddir)/libpcsxcore/ppc/pasm.s'; fi` + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonemtpy = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LIBRARIES) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-exec-am: + +install-html: install-html-am + +install-info: install-info-am + +install-man: + +install-pdf: install-pdf-am + +install-ps: install-ps-am + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstLIBRARIES ctags distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ + pdf pdf-am ps ps-am tags uninstall uninstall-am + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/libpcsxcore/cdriso.c b/libpcsxcore/cdriso.c new file mode 100644 index 00000000..8de93763 --- /dev/null +++ b/libpcsxcore/cdriso.c @@ -0,0 +1,305 @@ +/*************************************************************************** + * 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 Steet, Fifth Floor, Boston, MA 02111-1307 USA. * + ***************************************************************************/ + +// TODO: implement CDDA & subchannel support. + +#include "psxcommon.h" +#include "plugins.h" + +#define MSF2SECT(m, s, f) (((m) * 60 + (s) - 2) * 75 + (f)) +#define btoi(b) ((b) / 16 * 10 + (b) % 16) /* BCD to u_char */ + +#define CD_FRAMESIZE_RAW 2352 +#define DATA_SIZE (CD_FRAMESIZE_RAW - 12) + +FILE *cdHandle = NULL; +static unsigned char cdbuffer[CD_FRAMESIZE_RAW * 10]; + +char* CALLBACK CDR__getDriveLetter(void); +unsigned char* CALLBACK CDR__getBufferSub(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, CDDA} type; + char start[3]; // MSF-format + char length[3]; // MSF-format + char gap[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 +static unsigned int msf2sec(char *msf) { + return ((msf[0] * 60 + msf[1]) * 75) + msf[2]; +} + +static 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; +} + +// get size of a track given the sector +unsigned int ISOgetTrackLength(unsigned int s) { + int i = 1; + + while ((msf2sec(ti[i].start) < s) && i <= numtracks) + i++; + + return msf2sec(ti[--i].length); +} + +// 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; +} + +// this function tries to get the .toc file of the given .bin +// the neccessary data is put into the ti (trackinformation)-array +static int parsetoc(char *isofile) { + char tocname[MAXPATHLEN]; + FILE *fi; + char linebuf[256], dummy[256]; + char *token; + char name[256]; + char time[20], time2[20]; + unsigned int i, t; + + numtracks = 0; + + // copy name of the iso and change extension from .bin to .toc + strncpy(tocname, isofile, sizeof(tocname)); + token = strstr(tocname, ".bin"); + if (token) + sprintf((char *)token, ".toc"); + else + return -1; + + if ((fi = fopen(tocname, "r")) == NULL) { + SysPrintf(_("Could not open %s.\n"), tocname); + return -1; + } + + memset(&ti, 0, sizeof(ti)); + + // parse the .toc file + while (fgets(linebuf, sizeof(linebuf), fi) != NULL) { + // search for tracks + strncpy(dummy, linebuf, sizeof(linebuf)); + token = strtok(dummy, " "); + + // a new track is found + if (!strcmp(token, "TRACK")) { + // get type of track + token = strtok(NULL, " "); + + numtracks++; + + if (!strcmp(token, "MODE2_RAW\n")) { + ti[numtracks].type = DATA; + sec2msf(2 * 75, ti[numtracks].start); // assume data track on 0:2:0 + } + + if (!strcmp(token, "AUDIO\n")) + ti[numtracks].type = CDDA; + } + + // interpretation of other lines + if (!strcmp(token, "DATAFILE")) { + sscanf(linebuf, "DATAFILE %s %s", name, time); + tok2msf((char *)&time, (char *)&ti[numtracks].length); + } + + if (!strcmp(token, "FILE")) { + sscanf(linebuf, "FILE %s %s %s %s", name, dummy, time, time2); + tok2msf((char *)&time, (char *)&ti[numtracks].start); + tok2msf((char *)&time2, (char *)&ti[numtracks].length); + } + + if (!strcmp(token, "START")) { + sscanf(linebuf, "START %s", time); + tok2msf((char *)&time, (char *)&ti[numtracks].gap); + } + } + + fclose(fi); + + // calculate the true start of each track + // start+gap+datasize (+2 secs of silence ? I dunno...) + for(i = 2; i <= numtracks; i++) { + t = msf2sec(ti[1].start) + msf2sec(ti[1].length) + msf2sec(ti[i].start) + msf2sec(ti[i].gap); + sec2msf(t, ti[i].start); + } + + return 0; +} + +static long CALLBACK ISOinit(void) { + assert(cdHandle == NULL); + return 0; // do nothing +} + +static long CALLBACK ISOshutdown(void) { + if (cdHandle != NULL) { + fclose(cdHandle); + cdHandle = NULL; + } + return 0; +} + +// This function is invoked by the front-end when opening an ISO +// file for playback +static long CALLBACK ISOopen(void) { + if (cdHandle != NULL) + return 0; // it's already open + + cdHandle = fopen(cdrfilename, "rb"); + if (cdHandle == NULL) + return -1; + + parsetoc(cdrfilename); + return 0; +} + +static long CALLBACK ISOclose(void) { + if (cdHandle != NULL) { + fclose(cdHandle); + cdHandle = NULL; + } + 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 (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; +} + +// 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; + + fseek(cdHandle, MSF2SECT(btoi(time[0]), btoi(time[1]), btoi(time[2])) * CD_FRAMESIZE_RAW + 12, SEEK_SET); + fread(cdbuffer, 1, DATA_SIZE, cdHandle); + + return 0; +} + +// return readed track +static unsigned char * CALLBACK ISOgetBuffer(void) { + return (unsigned char *)&cdbuffer; +} + +// 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) { + return 0; // TODO +} + +// stops cdda audio +static long CALLBACK ISOstop(void) { + return 0; // TODO +} + +void imageReaderInit(void) { + assert(hCDRDriver == NULL); + + 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_getStatus = CDR__getStatus; + CDR_getDriveLetter = CDR__getDriveLetter; + CDR_getBufferSub = CDR__getBufferSub; + CDR_configure = CDR__configure; + CDR_test = CDR__test; + CDR_about = CDR__about; + CDR_setfilename = CDR__setfilename; + + numtracks = 0; +} diff --git a/libpcsxcore/cdriso.h b/libpcsxcore/cdriso.h new file mode 100644 index 00000000..ca5d2bfd --- /dev/null +++ b/libpcsxcore/cdriso.h @@ -0,0 +1,27 @@ +/*************************************************************************** + * 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 Steet, Fifth Floor, Boston, MA 02111-1307 USA. * + ***************************************************************************/ + +#ifndef CDRISO_H +#define CDRISO_H + +int imageReaderInit(void); +unsigned int ISOgetTrackLength(unsigned int s); + +#endif diff --git a/libpcsxcore/cdrom.c b/libpcsxcore/cdrom.c new file mode 100644 index 00000000..44e4a3d9 --- /dev/null +++ b/libpcsxcore/cdrom.c @@ -0,0 +1,1105 @@ +/*************************************************************************** + * Copyright (C) 2007 Ryan Schultz, PCSX-df Team, PCSX team * + * schultz.ryan@gmail.com, http://rschultz.ath.cx/code.php * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You 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 Steet, Fifth Floor, Boston, MA 02111-1307 USA. * + ***************************************************************************/ + +/* +* Handles all CD-ROM registers and functions. +*/ + +#include "cdrom.h" + +/* 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 Cdl18 18 +#define CdlGetTN 19 +#define CdlGetTD 20 +#define CdlSeekL 21 +#define CdlSeekP 22 +#define CdlTest 25 +#define CdlID 26 +#define CdlReadS 27 +#define CdlReset 28 +#define CdlReadToc 30 + +#define AUTOPAUSE 249 +#define READ_ACK 250 +#define READ 251 +#define REPPLAY_ACK 252 +#define REPPLAY 253 +#define ASYNC 254 +/* don't set 255, it's reserved */ + +char *CmdName[0x100]= { + "CdlSync", "CdlNop", "CdlSetloc", "CdlPlay", + "CdlForward", "CdlBackward", "CdlReadN", "CdlStandby", + "CdlStop", "CdlPause", "CdlInit", "CdlMute", + "CdlDemute", "CdlSetfilter", "CdlSetmode", "CdlGetmode", + "CdlGetlocL", "CdlGetlocP", "Cdl18", "CdlGetTN", + "CdlGetTD", "CdlSeekL", "CdlSeekP", NULL, + NULL, "CdlTest", "CdlID", "CdlReadS", + "CdlReset", NULL, "CDlReadToc", NULL +}; + +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 }; + +// 1x = 75 sectors per second +// PSXCLK = 1 sec in the ps +// so (PSXCLK / 75) / BIAS = cdr read time (linuzappz) +#define cdReadTime ((PSXCLK / 75) / BIAS) + +#define btoi(b) ((b)/16*10 + (b)%16) /* BCD to u_char */ +#define itob(i) ((i)/10*16 + (i)%10) /* u_char to BCD */ + +static struct CdrStat stat; +static struct SubQ *subq; + +#define CDR_INT(eCycle) { \ + psxRegs.interrupt |= 0x4; \ + psxRegs.intCycle[2 + 1] = eCycle; \ + psxRegs.intCycle[2] = psxRegs.cycle; } + +#define CDREAD_INT(eCycle) { \ + psxRegs.interrupt |= 0x40000; \ + psxRegs.intCycle[2 + 16 + 1] = eCycle; \ + psxRegs.intCycle[2 + 16] = psxRegs.cycle; } + +#define StartReading(type) { \ + cdr.Reading = type; \ + cdr.FirstSector = 1; \ + cdr.Readed = 0xff; \ + AddIrqQueue(READ_ACK, 0x800); \ +} + +#define StopReading() { \ + if (cdr.Reading) { \ + cdr.Reading = 0; \ + psxRegs.interrupt &= ~0x40000; \ + } \ +} + +#define StopCdda() { \ + if (cdr.Play) { \ + if (!Config.Cdda) CDR_stop(); \ + cdr.StatP &= ~0x80; \ + cdr.Play = 0; \ + } \ +} + +#define SetResultSize(size) { \ + cdr.ResultP = 0; \ + cdr.ResultC = size; \ + cdr.ResultReady = 1; \ +} + +void ReadTrack() { + cdr.Prev[0] = itob(cdr.SetSector[0]); + cdr.Prev[1] = itob(cdr.SetSector[1]); + cdr.Prev[2] = itob(cdr.SetSector[2]); + +#ifdef CDR_LOG + CDR_LOG("ReadTrack() Log: KEY *** %x:%x:%x\n", cdr.Prev[0], cdr.Prev[1], cdr.Prev[2]); +#endif + cdr.RErr = CDR_readTrack(cdr.Prev); +} + +// cdr.Stat: +#define NoIntr 0 +#define DataReady 1 +#define Complete 2 +#define Acknowledge 3 +#define DataEnd 4 +#define DiskError 5 + +void AddIrqQueue(unsigned char irq, unsigned long ecycle) { + cdr.Irq = irq; + if (cdr.Stat) { + cdr.eCycle = ecycle; + } else { + CDR_INT(ecycle); + } +} + +void cdrInterrupt() { + int i; + unsigned char Irq = cdr.Irq; + + if (cdr.Stat) { + CDR_INT(0x800); + return; + } + + cdr.Irq = 0xff; + cdr.Ctrl &= ~0x80; + + switch (Irq) { + case CdlSync: + SetResultSize(1); + cdr.StatP |= 0x2; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Acknowledge; + break; + + case CdlNop: + SetResultSize(1); + cdr.Result[0] = cdr.StatP; + cdr.Stat = Acknowledge; + i = stat.Status; + if (CDR_getStatus(&stat) != -1) { + if (stat.Type == 0xff) cdr.Stat = DiskError; + if (stat.Status & 0x10) { + cdr.Stat = DiskError; + cdr.Result[0] |= 0x11; + cdr.Result[0] &= ~0x02; + } + else if (i & 0x10) { + cdr.StatP |= 0x2; + cdr.Result[0] |= 0x2; + CheckCdrom(); + } + } + break; + + case CdlSetloc: + cdr.CmdProcess = 0; + SetResultSize(1); + cdr.StatP |= 0x2; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Acknowledge; + break; + + case CdlPlay: + cdr.CmdProcess = 0; + SetResultSize(1); + cdr.StatP |= 0x2; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Acknowledge; + cdr.StatP |= 0x80; +// if ((cdr.Mode & 0x5) == 0x5) AddIrqQueue(REPPLAY, cdReadTime); + break; + + case CdlForward: + cdr.CmdProcess = 0; + SetResultSize(1); + cdr.StatP |= 0x2; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Complete; + break; + + case CdlBackward: + cdr.CmdProcess = 0; + SetResultSize(1); + cdr.StatP |= 0x2; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Complete; + break; + + case CdlStandby: + cdr.CmdProcess = 0; + SetResultSize(1); + cdr.StatP |= 0x2; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Complete; + break; + + case CdlStop: + cdr.CmdProcess = 0; + SetResultSize(1); + cdr.StatP &= ~0x2; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Complete; +// cdr.Stat = Acknowledge; + break; + + case CdlPause: + SetResultSize(1); + cdr.Result[0] = cdr.StatP; + cdr.Stat = Acknowledge; + AddIrqQueue(CdlPause + 0x20, 0x800); + cdr.Ctrl |= 0x80; + break; + + case CdlPause + 0x20: + SetResultSize(1); + cdr.StatP &= ~0x20; + cdr.StatP |= 0x2; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Complete; + break; + + case CdlInit: + SetResultSize(1); + cdr.StatP = 0x2; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Acknowledge; +// if (!cdr.Init) { + AddIrqQueue(CdlInit + 0x20, 0x800); +// } + break; + + case CdlInit + 0x20: + SetResultSize(1); + cdr.Result[0] = cdr.StatP; + cdr.Stat = Complete; + cdr.Init = 1; + break; + + case CdlMute: + SetResultSize(1); + cdr.StatP |= 0x2; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Acknowledge; + break; + + case CdlDemute: + SetResultSize(1); + cdr.StatP |= 0x2; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Acknowledge; + break; + + case CdlSetfilter: + SetResultSize(1); + cdr.StatP |= 0x2; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Acknowledge; + break; + + case CdlSetmode: + SetResultSize(1); + cdr.StatP |= 0x2; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Acknowledge; + break; + + case CdlGetmode: + SetResultSize(6); + cdr.StatP |= 0x2; + cdr.Result[0] = cdr.StatP; + cdr.Result[1] = cdr.Mode; + cdr.Result[2] = cdr.File; + cdr.Result[3] = cdr.Channel; + cdr.Result[4] = 0; + cdr.Result[5] = 0; + cdr.Stat = Acknowledge; + break; + + case CdlGetlocL: + SetResultSize(8); +// for (i = 0; i < 8; i++) +// cdr.Result[i] = itob(cdr.Transfer[i]); + for (i = 0; i < 8; i++) + cdr.Result[i] = cdr.Transfer[i]; + cdr.Stat = Acknowledge; + break; + + case CdlGetlocP: + SetResultSize(8); + subq = (struct SubQ *)CDR_getBufferSub(); + if (subq != NULL) { + cdr.Result[0] = subq->TrackNumber; + cdr.Result[1] = subq->IndexNumber; + memcpy(cdr.Result + 2, subq->TrackRelativeAddress, 3); + memcpy(cdr.Result + 5, subq->AbsoluteAddress, 3); + } else { + cdr.Result[0] = 1; + cdr.Result[1] = 1; + cdr.Result[2] = cdr.Prev[0]; + cdr.Result[3] = itob((btoi(cdr.Prev[1])) - 2); + cdr.Result[4] = cdr.Prev[2]; + memcpy(cdr.Result + 5, cdr.Prev, 3); + } + cdr.Stat = Acknowledge; + break; + + case CdlGetTN: + cdr.CmdProcess = 0; + SetResultSize(3); + cdr.StatP |= 0x2; + cdr.Result[0] = cdr.StatP; + if (CDR_getTN(cdr.ResultTN) == -1) { + cdr.Stat = DiskError; + cdr.Result[0] |= 0x01; + } 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|= 0x2; + if (CDR_getTD(cdr.Track, cdr.ResultTD) == -1) { + cdr.Stat = DiskError; + cdr.Result[0] |= 0x01; + } 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 |= 0x2; + cdr.Result[0] = cdr.StatP; + cdr.StatP |= 0x40; + cdr.Stat = Acknowledge; + cdr.Seeked = 1; + AddIrqQueue(CdlSeekL + 0x20, 0x800); + break; + + case CdlSeekL + 0x20: + SetResultSize(1); + cdr.StatP |= 0x2; + cdr.StatP &= ~0x40; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Complete; + break; + + case CdlSeekP: + SetResultSize(1); + cdr.StatP |= 0x2; + cdr.Result[0] = cdr.StatP; + cdr.StatP |= 0x40; + cdr.Stat = Acknowledge; + AddIrqQueue(CdlSeekP + 0x20, 0x800); + break; + + case CdlSeekP + 0x20: + SetResultSize(1); + cdr.StatP |= 0x2; + cdr.StatP &= ~0x40; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Complete; + break; + + case CdlTest: + cdr.Stat = Acknowledge; + switch (cdr.Param[0]) { + case 0x20: // System Controller ROM Version + SetResultSize(4); + memcpy(cdr.Result, Test20, 4); + break; + case 0x22: + SetResultSize(8); + memcpy(cdr.Result, Test22, 4); + break; + case 0x23: case 0x24: + SetResultSize(8); + memcpy(cdr.Result, Test23, 4); + break; + } + break; + + case CdlID: + SetResultSize(1); + cdr.StatP |= 0x2; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Acknowledge; + AddIrqQueue(CdlID + 0x20, 0x800); + break; + + case CdlID + 0x20: + SetResultSize(8); + if (CDR_getStatus(&stat) == -1) { + cdr.Result[0] = 0x00; // 0x08 and cdr.Result[1]|0x10 : audio cd, enters cd player + cdr.Result[1] = 0x00; // 0x80 leads to the menu in the bios, else loads CD + } + else { + if (stat.Type == 2) { + cdr.Result[0] = 0x08; + cdr.Result[1] = 0x10; + } + else { + cdr.Result[0] = 0x00; + cdr.Result[1] = 0x00; + } + } + cdr.Result[1] |= 0x80; + cdr.Result[2] = 0x00; + cdr.Result[3] = 0x00; + strncpy((char *)&cdr.Result[4], "PCSX", 4); + cdr.Stat = Complete; + break; + + case CdlReset: + SetResultSize(1); + cdr.StatP = 0x2; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Acknowledge; + break; + + case CdlReadToc: + SetResultSize(1); + cdr.StatP |= 0x2; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Acknowledge; + AddIrqQueue(CdlReadToc + 0x20, 0x800); + break; + + case CdlReadToc + 0x20: + SetResultSize(1); + cdr.StatP |= 0x2; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Complete; + break; + + case AUTOPAUSE: + cdr.OCUP = 0; +/* SetResultSize(1); + StopCdda(); + StopReading(); + cdr.OCUP = 0; + cdr.StatP&=~0x20; + cdr.StatP|= 0x2; + cdr.Result[0] = cdr.StatP; + cdr.Stat = DataEnd; +*/ AddIrqQueue(CdlPause, 0x400); + break; + + case READ_ACK: + if (!cdr.Reading) return; + + SetResultSize(1); + cdr.StatP |= 0x2; + cdr.Result[0] = cdr.StatP; + if (cdr.Seeked == 0) { + cdr.Seeked = 1; + cdr.StatP|= 0x40; + } + cdr.StatP |= 0x20; + cdr.Stat = Acknowledge; + + ReadTrack(); + +// CDREAD_INT((cdr.Mode & 0x80) ? (cdReadTime / 2) : cdReadTime); + CDREAD_INT(0x40000); + break; + + case REPPLAY_ACK: + cdr.Stat = Acknowledge; + cdr.Result[0] = cdr.StatP; + SetResultSize(1); + AddIrqQueue(REPPLAY, cdReadTime); + break; + + case REPPLAY: + if ((cdr.Mode & 5) != 5) break; +/* if (CDR_getStatus(&stat) == -1) { + cdr.Result[0] = 0; + cdr.Result[1] = 0; + cdr.Result[2] = 0; + cdr.Result[3] = 0; + cdr.Result[4] = 0; + cdr.Result[5] = 0; + cdr.Result[6] = 0; + cdr.Result[7] = 0; + } else memcpy(cdr.Result, &stat.Track, 8); + cdr.Stat = 1; + SetResultSize(8); + AddIrqQueue(REPPLAY_ACK, cdReadTime); +*/ break; + + case 0xff: + return; + + default: + cdr.Stat = Complete; + break; + } + + if (cdr.Stat != NoIntr && cdr.Reg2 != 0x18) { + psxHu32ref(0x1070) |= SWAP32((u32)0x4); + psxRegs.interrupt |= 0x80000000; + } + +#ifdef CDR_LOG + CDR_LOG("cdrInterrupt() Log: CDR Interrupt IRQ %x\n", Irq); +#endif +} + +void cdrReadInterrupt() { + u8 *buf; + + if (!cdr.Reading) + return; + + if (cdr.Stat) { + CDREAD_INT(0x800); + return; + } + +#ifdef CDR_LOG + CDR_LOG("cdrReadInterrupt() Log: KEY END"); +#endif + + cdr.OCUP = 1; + SetResultSize(1); + cdr.StatP |= 0x22; + cdr.StatP &= ~0x40; + cdr.Result[0] = cdr.StatP; + + 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, 2340); + cdr.Stat = DiskError; + cdr.Result[0] |= 0x01; + ReadTrack(); + CDREAD_INT((cdr.Mode & 0x80) ? (cdReadTime / 2) : cdReadTime); + return; + } + + memcpy(cdr.Transfer, buf, 2340); + cdr.Stat = DataReady; + +#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 == 1) && (cdr.Mode & 0x40) && (!Config.Xa) && (cdr.FirstSector != -1)) { // CD-XA + if ((cdr.Transfer[4 + 2] & 0x4) && + ((cdr.Mode & 0x8) ? (cdr.Transfer[4 + 1] == cdr.Channel) : 1) && + (cdr.Transfer[4 + 0] == cdr.File)) { + int ret = xa_decode_sector(&cdr.Xa, cdr.Transfer+4, cdr.FirstSector); + + if (!ret) { + SPU_playADPCMchannel(&cdr.Xa); + cdr.FirstSector = 0; + } + else cdr.FirstSector = -1; + } + } + + cdr.SetSector[2]++; + if (cdr.SetSector[2] == 75) { + cdr.SetSector[2] = 0; + cdr.SetSector[1]++; + if (cdr.SetSector[1] == 60) { + cdr.SetSector[1] = 0; + cdr.SetSector[0]++; + } + } + + cdr.Readed = 0; + + if ((cdr.Transfer[4 + 2] & 0x80) && (cdr.Mode & 0x2)) { // EOF +#ifdef CDR_LOG + CDR_LOG("cdrReadInterrupt() Log: Autopausing read\n"); +#endif +// AddIrqQueue(AUTOPAUSE, 0x800); + AddIrqQueue(CdlPause, 0x800); + } + else { + ReadTrack(); + CDREAD_INT((cdr.Mode & 0x80) ? (cdReadTime / 2) : cdReadTime); + } + psxHu32ref(0x1070) |= SWAP32((u32)0x4); + psxRegs.interrupt |= 0x80000000; +} + +/* +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; + } +} + +unsigned char cdrRead1(void) { + if (cdr.ResultReady) { // && cdr.Ctrl & 0x1) { + psxHu8(0x1801) = cdr.Result[cdr.ResultP++]; + if (cdr.ResultP == cdr.ResultC) + cdr.ResultReady = 0; + } else { + psxHu8(0x1801) = 0; + } +#ifdef CDR_LOG + CDR_LOG("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 +// 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; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + case CdlSetloc: + StopReading(); + cdr.Seeked = 0; + for (i = 0; i < 3; i++) + cdr.SetSector[i] = btoi(cdr.Param[i]); + cdr.SetSector[3] = 0; +/* 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: + if (!cdr.SetSector[0] & !cdr.SetSector[1] & !cdr.SetSector[2]) { + if (CDR_getTN(cdr.ResultTN) != -1) { + if (cdr.CurTrack > cdr.ResultTN[1]) + cdr.CurTrack = cdr.ResultTN[1]; + if (CDR_getTD((unsigned char)(cdr.CurTrack), cdr.ResultTD) != -1) { + int tmp = cdr.ResultTD[2]; + cdr.ResultTD[2] = cdr.ResultTD[0]; + cdr.ResultTD[0] = tmp; + if (!Config.Cdda) CDR_play(cdr.ResultTD); + } + } + } else if (!Config.Cdda) { + CDR_play(cdr.SetSector); + } + cdr.Play = 1; + cdr.Ctrl |= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + case CdlForward: + if (cdr.CurTrack < 0xaa) + cdr.CurTrack++; + cdr.Ctrl |= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + case CdlBackward: + if (cdr.CurTrack > 1) + cdr.CurTrack--; + cdr.Ctrl |= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + case CdlReadN: + cdr.Irq = 0; + StopReading(); + cdr.Ctrl|= 0x80; + cdr.Stat = NoIntr; + StartReading(1); + break; + + case CdlStandby: + StopCdda(); + StopReading(); + cdr.Ctrl |= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + case CdlStop: + StopCdda(); + StopReading(); + cdr.Ctrl |= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + case CdlPause: + StopCdda(); + StopReading(); + cdr.Ctrl |= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x40000); + break; + + case CdlReset: + case CdlInit: + StopCdda(); + StopReading(); + cdr.Ctrl |= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + case CdlMute: + cdr.Muted = 0; + cdr.Ctrl |= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + case CdlDemute: + cdr.Muted = 1; + cdr.Ctrl |= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + case CdlSetfilter: + cdr.File = cdr.Param[0]; + cdr.Channel = cdr.Param[1]; + cdr.Ctrl |= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + case CdlSetmode: +#ifdef CDR_LOG + CDR_LOG("cdrWrite1() Log: Setmode %x\n", cdr.Param[0]); +#endif + cdr.Mode = cdr.Param[0]; + cdr.Ctrl |= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + case CdlGetmode: + cdr.Ctrl |= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + case CdlGetlocL: + cdr.Ctrl |= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + case CdlGetlocP: + cdr.Ctrl |= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + case CdlGetTN: + cdr.Ctrl |= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + case CdlGetTD: + cdr.Ctrl |= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + case CdlSeekL: +// ((u32 *)cdr.SetSectorSeek)[0] = ((u32 *)cdr.SetSector)[0]; + cdr.Ctrl |= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + case CdlSeekP: +// ((u32 *)cdr.SetSectorSeek)[0] = ((u32 *)cdr.SetSector)[0]; + cdr.Ctrl |= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + case CdlTest: + cdr.Ctrl |= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + case CdlID: + cdr.Ctrl |= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + case CdlReadS: + cdr.Irq = 0; + StopReading(); + cdr.Ctrl |= 0x80; + cdr.Stat = NoIntr; + StartReading(2); + break; + + case CdlReadToc: + cdr.Ctrl |= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + default: +#ifdef CDR_LOG + CDR_LOG("cdrWrite1() Log: Unknown command: %x\n", cdr.Cmd); +#endif + return; + } + if (cdr.Stat != NoIntr) { + psxHu32ref(0x1070) |= SWAP32((u32)0x4); + psxRegs.interrupt |= 0x80000000; + } +} + +unsigned char cdrRead2(void) { + unsigned char ret; + + if (cdr.Readed == 0) { + ret = 0; + } else { + ret = *cdr.pTransfer++; + } + +#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 + 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 + if (rt == 0x07 && cdr.Ctrl & 0x1) { + cdr.Stat = 0; + + if (cdr.Irq == 0xff) { + cdr.Irq = 0; + return; + } + if (cdr.Irq) + CDR_INT(cdr.eCycle); + if (cdr.Reading && !cdr.ResultReady) + CDREAD_INT((cdr.Mode & 0x80) ? (cdReadTime / 2) : cdReadTime); + + return; + } + if (rt == 0x80 && !(cdr.Ctrl & 0x1) && cdr.Readed == 0) { + cdr.Readed = 1; + cdr.pTransfer = cdr.Transfer; + + switch (cdr.Mode&0x30) { + case 0x10: + case 0x00: + cdr.pTransfer += 12; + break; + default: + break; + } + } +} + +void psxDma3(u32 madr, u32 bcr, u32 chcr) { + u32 cdsize; + u8 *ptr; + +#ifdef CDR_LOG + CDR_LOG("psxDma3() Log: *** DMA 3 *** %lx addr = %lx size = %lx\n", chcr, madr, bcr); +#endif + + switch (chcr) { + case 0x11000000: + case 0x11400100: + if (cdr.Readed == 0) { +#ifdef CDR_LOG + CDR_LOG("psxDma3() Log: *** DMA 3 *** NOT READY\n"); +#endif + break; + } + + cdsize = (bcr & 0xffff) * 4; + + ptr = (u8 *)PSXM(madr); + if (ptr == NULL) { +#ifdef CPU_LOG + CDR_LOG("psxDma3() Log: *** DMA 3 *** NULL Pointer!\n"); +#endif + break; + } + memcpy(ptr, cdr.pTransfer, cdsize); + psxCpu->Clear(madr, cdsize / 4); + cdr.pTransfer += cdsize; + break; + default: +#ifdef CDR_LOG + CDR_LOG("psxDma3() Log: Unknown cddma %lx\n", chcr); +#endif + break; + } + + HW_DMA3_CHCR &= SWAP32(~0x01000000); + DMA_INTERRUPT(3); +} + +void cdrReset() { + memset(&cdr, 0, sizeof(cdr)); + cdr.CurTrack = 1; + cdr.File = 1; + cdr.Channel = 1; +} + +int cdrFreeze(gzFile f, int Mode) { + uintptr_t tmp; + + gzfreeze(&cdr, sizeof(cdr)); + + if (Mode == 1) + tmp = cdr.pTransfer - cdr.Transfer; + + gzfreezel(&tmp); + + if (Mode == 0) + cdr.pTransfer = cdr.Transfer + tmp; + + return 0; +} diff --git a/libpcsxcore/cdrom.h b/libpcsxcore/cdrom.h new file mode 100644 index 00000000..70f93a5d --- /dev/null +++ b/libpcsxcore/cdrom.h @@ -0,0 +1,96 @@ +/*************************************************************************** + * Copyright (C) 2007 Ryan Schultz, PCSX-df Team, PCSX team * + * schultz.ryan@gmail.com, http://rschultz.ath.cx/code.php * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You 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 Steet, Fifth Floor, Boston, MA 02111-1307 USA. * + ***************************************************************************/ + +#ifndef __CDROM_H__ +#define __CDROM_H__ + +#include "psxcommon.h" +#include "decode_xa.h" +#include "r3000a.h" +#include "plugins.h" +#include "psxmem.h" +#include "psxhw.h" + +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[2352]; + unsigned char *pTransfer; + + unsigned char Prev[4]; + unsigned char Param[8]; + unsigned char Result[8]; + + unsigned char ParamC; + unsigned char ParamP; + unsigned char ResultC; + unsigned char ResultP; + unsigned char ResultReady; + unsigned char Cmd; + unsigned char Readed; + unsigned long Reading; + + unsigned char ResultTN[6]; + unsigned char ResultTD[4]; + unsigned char SetSector[4]; + unsigned char SetSectorSeek[4]; + unsigned char Track; + int Play; + int CurTrack; + int Mode, File, Channel, Muted; + int Reset; + int RErr; + int FirstSector; + + xa_decode_t Xa; + + int Init; + + unsigned char Irq; + unsigned long eCycle; + + int Seeked; + + char Unused[4083]; +} cdrStruct; + +cdrStruct cdr; + +void cdrReset(); +void cdrInterrupt(); +void cdrReadInterrupt(); +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); + +#endif /* __CDROM_H__ */ diff --git a/libpcsxcore/cheat.c b/libpcsxcore/cheat.c new file mode 100644 index 00000000..284d833b --- /dev/null +++ b/libpcsxcore/cheat.c @@ -0,0 +1,459 @@ +/* Cheat Support for PCSX-Reloaded + * + * Copyright (c) 2009, Wei Mingzhi <whistler@openoffice.org>. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You 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 Steet, Fifth Floor, Boston, MA 02111-1307 USA + */ + +#include "psxcommon.h" +#include "r3000a.h" +#include "psxmem.h" + +#include "cheat.h" + +Cheat *Cheats = NULL; +int NumCheats = 0; +static int NumCheatsAllocated = 0; + +CheatCode *CheatCodes = NULL; +int NumCodes = 0; +static int NumCodesAllocated = 0; + +#define ALLOC_INCREMENT 100 + +// cheat types +#define CHEAT_CONST8 0x30 /* 8-bit Constant Write */ +#define CHEAT_CONST16 0x80 /* 16-bit Constant Write */ +#define CHEAT_INC16 0x10 /* 16-bit Increment */ +#define CHEAT_DEC16 0x11 /* 16-bit Decrement */ +#define CHEAT_INC8 0x20 /* 8-bit Increment */ +#define CHEAT_DEC8 0x21 /* 8-bit Decrement */ +#define CHEAT_SLIDE 0x50 /* Slide Codes */ +#define CHEAT_MEMCPY 0xC2 /* Memory Copy */ + +#define CHEAT_EQU8 0xE0 /* 8-bit Equal To */ +#define CHEAT_NOTEQU8 0xE1 /* 8-bit Not Equal To */ +#define CHEAT_LESSTHAN8 0xE2 /* 8-bit Less Than */ +#define CHEAT_GREATERTHAN8 0xE3 /* 8-bit Greater Than */ +#define CHEAT_EQU16 0xD0 /* 16-bit Equal To */ +#define CHEAT_NOTEQU16 0xD1 /* 16-bit Not Equal To */ +#define CHEAT_LESSTHAN16 0xD2 /* 16-bit Less Than */ +#define CHEAT_GREATERTHAN16 0xD3 /* 16-bit Greater Than */ + +void ClearAllCheats() { + int i; + + if (Cheats != NULL) { + for (i = 0; i < NumCheats; i++) { + free(Cheats[i].Descr); + } + free(Cheats); + } + + Cheats = NULL; + NumCheats = 0; + NumCheatsAllocated = 0; + + if (CheatCodes != NULL) { + free(CheatCodes); + } + + CheatCodes = NULL; + NumCodes = 0; + NumCodesAllocated = 0; +} + +// load cheats from the specific filename +void LoadCheats(const char *filename) { + FILE *fp; + char buf[256]; + int count = 0; + unsigned int t1, t2; + + fp = fopen(filename, "r"); + if (fp == NULL) { + return; + } + + ClearAllCheats(); + + while (fgets(buf, 255, fp) != NULL) { + buf[255] = '\0'; + trim(buf); + + // Skip comment or blank lines + if (buf[0] == '#' || buf[0] == ';' || buf[0] == '/' || buf[0] == '\"' || buf[0] == '\0') + continue; + + if (buf[0] == '[' && buf[strlen(buf) - 1] == ']') { + if (NumCheats > 0) + Cheats[NumCheats - 1].n = count; + + if (NumCheats >= NumCheatsAllocated) { + NumCheatsAllocated += ALLOC_INCREMENT; + + if (Cheats == NULL) { + assert(NumCheats == 0); + assert(NumCheatsAllocated == ALLOC_INCREMENT); + Cheats = (Cheat *)malloc(sizeof(Cheat) * NumCheatsAllocated); + } else { + Cheats = (Cheat *)realloc(Cheats, sizeof(Cheat) * NumCheatsAllocated); + } + } + + buf[strlen(buf) - 1] = '\0'; + count = 0; + + if (buf[1] == '*') { + Cheats[NumCheats].Descr = strdup(buf + 2); + Cheats[NumCheats].Enabled = 1; + } else { + Cheats[NumCheats].Descr = strdup(buf + 1); + Cheats[NumCheats].Enabled = 0; + } + + Cheats[NumCheats].First = NumCodes; + + NumCheats++; + continue; + } + + if (NumCheats <= 0) + continue; + + if (NumCodes >= NumCodesAllocated) { + NumCodesAllocated += ALLOC_INCREMENT; + + if (CheatCodes == NULL) { + assert(NumCodes == 0); + assert(NumCodesAllocated == ALLOC_INCREMENT); + CheatCodes = (CheatCode *)malloc(sizeof(CheatCode) * NumCodesAllocated); + } else { + CheatCodes = (CheatCode *)realloc(CheatCodes, sizeof(CheatCode) * NumCodesAllocated); + } + } + + sscanf(buf, "%x %x", &t1, &t2); + + CheatCodes[NumCodes].Addr = t1; + CheatCodes[NumCodes].Val = t2; + + NumCodes++; + count++; + } + + if (NumCheats > 0) + Cheats[NumCheats - 1].n = count; + + fclose(fp); + + SysPrintf("Cheats loaded from: %s\n", filename); +} + +// save all cheats to the specified filename +void SaveCheats(const char *filename) { + FILE *fp; + int i, j; + + fp = fopen(filename, "w"); + if (fp == NULL) { + return; + } + + for (i = 0; i < NumCheats; i++) { + // write the description + if (Cheats[i].Enabled) + fprintf(fp, "[*%s]\n", Cheats[i].Descr); + else + fprintf(fp, "[%s]\n", Cheats[i].Descr); + + // write all cheat codes + for (j = 0; j < Cheats[i].n; j++) { + fprintf(fp, "%.8X %.4X\n", + CheatCodes[Cheats[i].First + j].Addr, + CheatCodes[Cheats[i].First + j].Val); + } + + fprintf(fp, "\n"); + } + + fclose(fp); + + SysPrintf("Cheats saved to: %s\n", filename); +} + +// apply all enabled cheats +void ApplyCheats() { + int i, j, k, endindex; + + for (i = 0; i < NumCheats; i++) { + if (!Cheats[i].Enabled) { + continue; + } + + // process all cheat codes + endindex = Cheats[i].First + Cheats[i].n; + + for (j = Cheats[i].First; j < endindex; j++) { + u8 type = (uint8_t)(CheatCodes[j].Addr >> 24); + u32 addr = (CheatCodes[j].Addr & 0x001FFFFF); + u16 val = CheatCodes[j].Val; + u32 taddr; + + switch (type) { + case CHEAT_CONST8: + psxMemWrite8(addr, (u8)val); + break; + + case CHEAT_CONST16: + psxMemWrite16(addr, (u16)val); + break; + + case CHEAT_INC16: + psxMemWrite16(addr, psxMemRead16(addr) + val); + break; + + case CHEAT_DEC16: + psxMemWrite16(addr, psxMemRead16(addr) - val); + break; + + case CHEAT_INC8: + psxMemWrite8(addr, psxMemRead8(addr) + (u8)val); + break; + + case CHEAT_DEC8: + psxMemWrite8(addr, psxMemRead8(addr) - (u8)val); + break; + + case CHEAT_SLIDE: + j++; + if (j >= endindex) + break; + + type = (uint8_t)(CheatCodes[j].Addr >> 24); + taddr = (CheatCodes[j].Addr & 0x001FFFFF); + val = CheatCodes[j].Val; + + if (type == CHEAT_CONST8) { + for (k = 0; k < ((addr >> 8) & 0xFF); k++) { + psxMemWrite8(taddr, (u8)val); + taddr += (s8)(addr & 0xFF); + val += (s8)(CheatCodes[j - 1].Val & 0xFF); + } + } else if (type == CHEAT_CONST16) { + for (k = 0; k < ((addr >> 8) & 0xFF); k++) { + psxMemWrite16(taddr, val); + taddr += (s8)(addr & 0xFF); + val += (s8)(CheatCodes[j - 1].Val & 0xFF); + } + } + break; + + case CHEAT_MEMCPY: + j++; + if (j >= endindex) + break; + + taddr = (CheatCodes[j].Addr & 0x001FFFFF); + for (k = 0; k < val; k++) { + psxMemWrite8(taddr + k, psxMemRead8(addr + k)); + } + break; + + case CHEAT_EQU8: + if (psxMemRead8(addr) != (u8)val) + j++; // skip the next code + break; + + case CHEAT_NOTEQU8: + if (psxMemRead8(addr) == (u8)val) + j++; // skip the next code + break; + + case CHEAT_LESSTHAN8: + if (psxMemRead8(addr) >= (u8)val) + j++; // skip the next code + break; + + case CHEAT_GREATERTHAN8: + if (psxMemRead8(addr) <= (u8)val) + j++; // skip the next code + break; + + case CHEAT_EQU16: + if (psxMemRead16(addr) != val) + j++; // skip the next code + break; + + case CHEAT_NOTEQU16: + if (psxMemRead16(addr) == val) + j++; // skip the next code + break; + + case CHEAT_LESSTHAN16: + if (psxMemRead16(addr) >= val) + j++; // skip the next code + break; + + case CHEAT_GREATERTHAN16: + if (psxMemRead16(addr) <= val) + j++; // skip the next code + break; + } + } + } +} + +int AddCheat(const char *descr, char *code) { + int c = 1; + char *p1, *p2; + + if (NumCheats >= NumCheatsAllocated) { + NumCheatsAllocated += ALLOC_INCREMENT; + + if (Cheats == NULL) { + assert(NumCheats == 0); + assert(NumCheatsAllocated == ALLOC_INCREMENT); + Cheats = (Cheat *)malloc(sizeof(Cheat) * NumCheatsAllocated); + } else { + Cheats = (Cheat *)realloc(Cheats, sizeof(Cheat) * NumCheatsAllocated); + } + } + + Cheats[NumCheats].Descr = strdup(descr[0] ? descr : _("(Untitled)")); + Cheats[NumCheats].Enabled = 0; + Cheats[NumCheats].First = NumCodes; + Cheats[NumCheats].n = 0; + + p1 = code; + p2 = code; + + while (c) { + unsigned int t1, t2; + + while (*p2 != '\n' && *p2 != '\0') + p2++; + + if (*p2 == '\0') + c = 0; + + *p2 = '\0'; + p2++; + + t1 = 0; + t2 = 0; + sscanf(p1, "%x %x", &t1, &t2); + + if (t1 > 0x10000000) { + if (NumCodes >= NumCodesAllocated) { + NumCodesAllocated += ALLOC_INCREMENT; + + if (CheatCodes == NULL) { + assert(NumCodes == 0); + assert(NumCodesAllocated == ALLOC_INCREMENT); + CheatCodes = (CheatCode *)malloc(sizeof(CheatCode) * NumCodesAllocated); + } else { + CheatCodes = (CheatCode *)realloc(CheatCodes, sizeof(CheatCode) * NumCodesAllocated); + } + } + + CheatCodes[NumCodes].Addr = t1; + CheatCodes[NumCodes].Val = t2; + NumCodes++; + Cheats[NumCheats].n++; + } + + p1 = p2; + } + + if (Cheats[NumCheats].n == 0) { + return -1; + } + + NumCheats++; + return 0; +} + +void RemoveCheat(int index) { + assert(index >= 0 && index < NumCheats); + + free(Cheats[index].Descr); + + while (index < NumCheats - 1) { + Cheats[index] = Cheats[index + 1]; + index++; + } + + NumCheats--; +} + +int EditCheat(int index, const char *descr, char *code) { + int c = 1; + int prev = NumCodes; + char *p1, *p2; + + assert(index >= 0 && index < NumCheats); + + p1 = code; + p2 = code; + + while (c) { + unsigned int t1, t2; + + while (*p2 != '\n' && *p2 != '\0') + p2++; + + if (*p2 == '\0') + c = 0; + + *p2 = '\0'; + p2++; + + t1 = 0; + t2 = 0; + sscanf(p1, "%x %x", &t1, &t2); + + if (t1 > 0x10000000) { + if (NumCodes >= NumCodesAllocated) { + NumCodesAllocated += ALLOC_INCREMENT; + + if (CheatCodes == NULL) { + assert(NumCodes == 0); + assert(NumCodesAllocated == ALLOC_INCREMENT); + CheatCodes = (CheatCode *)malloc(sizeof(CheatCode) * NumCodesAllocated); + } else { + CheatCodes = (CheatCode *)realloc(CheatCodes, sizeof(CheatCode) * NumCodesAllocated); + } + } + + CheatCodes[NumCodes].Addr = t1; + CheatCodes[NumCodes].Val = t2; + NumCodes++; + } + + p1 = p2; + } + + if (NumCodes == prev) { + return -1; + } + + free(Cheats[index].Descr); + Cheats[index].Descr = strdup(descr[0] ? descr : _("(Untitled)")); + Cheats[index].First = prev; + Cheats[index].n = NumCodes - prev; + + return 0; +} diff --git a/libpcsxcore/cheat.h b/libpcsxcore/cheat.h new file mode 100644 index 00000000..3e32c753 --- /dev/null +++ b/libpcsxcore/cheat.h @@ -0,0 +1,51 @@ +/* Cheat Support for PCSX-Reloaded + * + * Copyright (C) 2009, Wei Mingzhi <whistler@openoffice.org>. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You 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 Steet, Fifth Floor, Boston, MA 02111-1307 USA + */ + +#ifndef CHEAT_H +#define CHEAT_H + +typedef struct { + uint32_t Addr; + uint16_t Val; +} CheatCode; + +typedef struct { + char *Descr; + int First; // index of the first cheat code + int n; // number of cheat codes for this cheat + int Enabled; +} Cheat; + +void ClearAllCheats(); + +void LoadCheats(const char *filename); +void SaveCheats(const char *filename); + +void ApplyCheats(); + +int AddCheat(const char *descr, char *code); +void RemoveCheat(int index); +int EditCheat(int index, const char *descr, char *code); + +extern Cheat *Cheats; +extern CheatCode *CheatCodes; +extern int NumCheats; +extern int NumCodes; + +#endif diff --git a/libpcsxcore/coff.h b/libpcsxcore/coff.h new file mode 100644 index 00000000..74f3dc41 --- /dev/null +++ b/libpcsxcore/coff.h @@ -0,0 +1,39 @@ +/*************************************************************************** + * Copyright (C) 2007 Ryan Schultz, PCSX-df Team, PCSX team * + * schultz.ryan@gmail.com, http://rschultz.ath.cx/code.php * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You 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 Steet, Fifth Floor, Boston, MA 02111-1307 USA. * + ***************************************************************************/ + +#ifndef __COFF_H__ +#define __COFF_H__ + +/********************** FILE HEADER **********************/ + +struct external_filehdr { + unsigned short f_magic; /* magic number */ + unsigned short f_nscns; /* number of sections */ + unsigned long f_timdat; /* time & date stamp */ + unsigned long f_symptr; /* file pointer to symtab */ + unsigned long f_nsyms; /* number of symtab entries */ + unsigned short f_opthdr; /* sizeof(optional hdr) */ + unsigned short f_flags; /* flags */ +}; + +#define FILHDR struct external_filehdr +#define FILHSZ sizeof(FILHDR) + +#endif /* __COFF_H__ */ diff --git a/libpcsxcore/debug.h b/libpcsxcore/debug.h new file mode 100644 index 00000000..d61f2ba0 --- /dev/null +++ b/libpcsxcore/debug.h @@ -0,0 +1,60 @@ +/*************************************************************************** + * Copyright (C) 2007 Ryan Schultz, PCSX-df Team, PCSX team * + * schultz.ryan@gmail.com, http://rschultz.ath.cx/code.php * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You 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 Steet, Fifth Floor, Boston, MA 02111-1307 USA. * + ***************************************************************************/ + +/* +* Specficies which logs should be activated. +* Ryan TODO: These should ALL be definable with configure flags. +*/ + +#ifndef __DEBUG_H__ +#define __DEBUG_H__ + +extern char *disRNameCP0[]; + +char* disR3000AF(u32 code, u32 pc); + +FILE *emuLog; + +//#define GTE_DUMP + +#ifdef GTE_DUMP +FILE *gteLog; +#endif + +//#define LOG_STDOUT + +//#define PAD_LOG __Log +//#define GTE_LOG __Log +//#define CDR_LOG __Log("%8.8lx %8.8lx: ", psxRegs.pc, psxRegs.cycle); __Log + +//#define PSXHW_LOG __Log("%8.8lx %8.8lx: ", psxRegs.pc, psxRegs.cycle); __Log +//#define PSXBIOS_LOG __Log("%8.8lx %8.8lx: ", psxRegs.pc, psxRegs.cycle); __Log +//#define PSXDMA_LOG __Log +//#define PSXMEM_LOG __Log("%8.8lx %8.8lx: ", psxRegs.pc, psxRegs.cycle); __Log +//#define PSXCPU_LOG __Log + +//#define CDRCMD_DEBUG + +#if defined (PSXCPU_LOG) || defined(PSXDMA_LOG) || defined(CDR_LOG) || defined(PSXHW_LOG) || \ + defined(PSXBIOS_LOG) || defined(PSXMEM_LOG) || defined(GTE_LOG) || defined(PAD_LOG) +#define EMU_LOG __Log +#endif + +#endif /* __DEBUG_H__ */ diff --git a/libpcsxcore/decode_xa.c b/libpcsxcore/decode_xa.c new file mode 100644 index 00000000..385c0571 --- /dev/null +++ b/libpcsxcore/decode_xa.c @@ -0,0 +1,368 @@ +/*************************************************************************** + * Copyright (C) 2007 Ryan Schultz, PCSX-df Team, PCSX team * + * schultz.ryan@gmail.com, http://rschultz.ath.cx/code.php * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You 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 Steet, Fifth Floor, Boston, MA 02111-1307 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/decode_xa.h b/libpcsxcore/decode_xa.h new file mode 100644 index 00000000..2fc71140 --- /dev/null +++ b/libpcsxcore/decode_xa.h @@ -0,0 +1,43 @@ +/*************************************************************************** + * Copyright (C) 2007 Ryan Schultz, PCSX-df Team, PCSX team * + * schultz.ryan@gmail.com, http://rschultz.ath.cx/code.php * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You 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 Steet, Fifth Floor, Boston, MA 02111-1307 USA. * + ***************************************************************************/ + +#ifndef __DECODE_XA_H__ +#define __DECODE_XA_H__ + +#include "psxcommon.h" + +typedef struct { + s32 y0, y1; +} ADPCM_Decode_t; + +typedef struct { + int freq; + int nbits; + int stereo; + int nsamples; + ADPCM_Decode_t left, right; + short pcm[16384]; +} xa_decode_t; + +s32 xa_decode_sector( xa_decode_t *xdp, + unsigned char *sectorp, + int is_first_sector ); + +#endif diff --git a/libpcsxcore/disr3000a.c b/libpcsxcore/disr3000a.c new file mode 100644 index 00000000..3314df88 --- /dev/null +++ b/libpcsxcore/disr3000a.c @@ -0,0 +1,324 @@ +/*************************************************************************** + * Copyright (C) 2007 Ryan Schultz, PCSX-df Team, PCSX team * + * schultz.ryan@gmail.com, http://rschultz.ath.cx/code.php * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You 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 Steet, Fifth Floor, Boston, MA 02111-1307 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"}; + +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 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_);) +MakeDisF(disCFC2, dName("CFC2"); dGPR(_Rt_);) +MakeDisF(disMTC2, dName("MTC2"); dGPR(_Rt_);) +MakeDisF(disCTC2, dName("CTC2"); 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"); dGPR(_Rt_); dOfB();) +MakeDisF(disSB, dName("SB"); dGPR(_Rt_); dOfB();) +MakeDisF(disSH, dName("SH"); dGPR(_Rt_); dOfB();) +MakeDisF(disSW, dName("SW"); dGPR(_Rt_); dOfB();) +MakeDisF(disSWL, dName("SWL"); dGPR(_Rt_); dOfB();) +MakeDisF(disSWR, dName("SWR"); dGPR(_Rt_); dOfB();) +MakeDisF(disSWC2, dName("SWC2"); dGPR(_Rt_); dOfB();) + +/********************************************************* +* Moves between GPR and COPx * +* Format: OP rt, fs * +*********************************************************/ +MakeDisF(disMFC0, dName("MFC0"); dGPR(_Rt_); dCP0(_Rd_);) +MakeDisF(disMTC0, dName("MTC0"); dCP0(_Rd_); dGPR(_Rt_);) +MakeDisF(disCFC0, dName("CFC0"); dGPR(_Rt_); dCP0(_Rd_);) +MakeDisF(disCTC0, dName("CTC0"); dCP0(_Rd_); dGPR(_Rt_);) + +/********************************************************* +* Unknow instruction (would generate an exception) * +* Format: ? * +*********************************************************/ +MakeDisF(disNULL, dName("*** Bad OP ***");) + + +TdisR3000AF disR3000A_SPECIAL[] = { // Subset of disSPECIAL + disSLL , disNULL , disSRL , disSRA , disSLLV , disNULL , disSRLV , disSRAV , + disJR , disJALR , disNULL, disNULL, disSYSCALL, disBREAK , disNULL , disNULL , + disMFHI, disMTHI , disMFLO, disMTLO, disNULL , disNULL , disNULL , disNULL , + disMULT, disMULTU, disDIV , disDIVU, disNULL , disNULL , disNULL , disNULL , + disADD , disADDU , disSUB , disSUBU, disAND , disOR , disXOR , disNOR , + disNULL, disNULL , disSLT , disSLTU, disNULL , disNULL , disNULL , disNULL , + disNULL, disNULL , disNULL, disNULL, disNULL , disNULL , disNULL , disNULL , + disNULL, disNULL , disNULL, disNULL, disNULL , disNULL , disNULL , disNULL}; + +MakeDisF(disSPECIAL, disR3000A_SPECIAL[_Funct_](code, pc)) + +TdisR3000AF disR3000A_BCOND[] = { // Subset of disBCOND + disBLTZ , disBGEZ , disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disNULL , disNULL , disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disBLTZAL, disBGEZAL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disNULL , disNULL , disNULL, disNULL, disNULL, disNULL, disNULL, disNULL}; + +MakeDisF(disBCOND, disR3000A_BCOND[_Rt_](code, pc)) + +TdisR3000AF disR3000A_COP0[] = { // Subset of disCOP0 + disMFC0, disNULL, disCFC0, disNULL, disMTC0, disNULL, disCTC0, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disRFE , disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL}; + +MakeDisF(disCOP0, disR3000A_COP0[_Rs_](code, pc)) + +TdisR3000AF disR3000A_BASIC[] = { // Subset of disBASIC (based on rs) + disMFC2, disNULL, disCFC2, disNULL, disMTC2, disNULL, disCTC2, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL}; + +MakeDisF(disBASIC, disR3000A_BASIC[_Rs_](code, pc)) + +TdisR3000AF disR3000A_COP2[] = { // Subset of disR3000F_COP2 (based on funct) + disBASIC, disRTPS , disNULL , disNULL , disNULL, disNULL , disNCLIP, disNULL, + disNULL , disNULL , disNULL , disNULL , disOP , disNULL , disNULL , disNULL, + disDPCS , disINTPL, disMVMVA, disNCDS , disCDP , disNULL , disNCDT , disNULL, + disNULL , disNULL , disNULL , disNCCS , disCC , disNULL , disNCS , disNULL, + disNCT , disNULL , disNULL , disNULL , disNULL, disNULL , disNULL , disNULL, + disSQR , disDCPL , disDPCT , disNULL , disNULL, disAVSZ3, disAVSZ4, disNULL, + disRTPT , disNULL , disNULL , disNULL , disNULL, disNULL , disNULL , disNULL, + disNULL , disNULL , disNULL , disNULL , disNULL, disGPF , disGPL , disNCCT }; + +MakeDisF(disCOP2, disR3000A_COP2[_Funct_](code, pc)) + +TdisR3000AF disR3000A[] = { + disSPECIAL , disBCOND , disJ , disJAL , disBEQ , disBNE , disBLEZ , disBGTZ , + disADDI , disADDIU , disSLTI , disSLTIU, disANDI, disORI , disXORI , disLUI , + disCOP0 , disNULL , disCOP2 , disNULL , disNULL, disNULL, disNULL , disNULL , + disNULL , disNULL , disNULL , disNULL , disNULL, disNULL, disNULL , disNULL , + disLB , disLH , disLWL , disLW , disLBU , disLHU , disLWR , disNULL , + disSB , disSH , disSWL , disSW , disNULL, disNULL, disSWR , disNULL , + disNULL , disNULL , disLWC2 , disNULL , disNULL, disNULL, disNULL , disNULL , + disNULL , disNULL , disSWC2 , disHLE , disNULL, disNULL, disNULL , disNULL }; + +MakeDisFg(disR3000AF, disR3000A[code >> 26](code, pc)) diff --git a/libpcsxcore/gte.c b/libpcsxcore/gte.c new file mode 100644 index 00000000..6e42c5cb --- /dev/null +++ b/libpcsxcore/gte.c @@ -0,0 +1,3124 @@ +/*************************************************************************** + * Copyright (C) 2007 Ryan Schultz, PCSX-df Team, PCSX team * + * schultz.ryan@gmail.com, http://rschultz.ath.cx/code.php * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You 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 Steet, Fifth Floor, Boston, MA 02111-1307 USA. * + ***************************************************************************/ + +/* +* GTE functions. +*/ + +#include "gte.h" + +#ifdef GTE_DUMP +#define G_OP(name,delay) fprintf(gteLog, "* : %08X : %02d : %s\n", psxRegs.code, delay, name); +#define G_SD(reg) fprintf(gteLog, "+D%02d : %08X\n", reg, psxRegs.CP2D.r[reg]); +#define G_SC(reg) fprintf(gteLog, "+C%02d : %08X\n", reg, psxRegs.CP2C.r[reg]); +#define G_GD(reg) fprintf(gteLog, "-D%02d : %08X\n", reg, psxRegs.CP2D.r[reg]); +#define G_GC(reg) fprintf(gteLog, "-C%02d : %08X\n", reg, psxRegs.CP2C.r[reg]); +#else +#define G_OP(name,delay) +#define G_SD(reg) +#define G_SC(reg) +#define G_GD(reg) +#define G_GC(reg) +#endif + +#define SUM_FLAG if (gteFLAG & 0x7F87E000) gteFLAG |= 0x80000000; + +#ifndef _MSC_VER +#define UNDERFLOW_BOUND ((s64)0xffffffff80000000LL) +#else +#define UNDERFLOW_BOUND ((s64)0xffffffff80000000) +#endif + +#if defined(__BIGENDIAN__) +#define SEL16(n) ((n)^1) +#define SEL8(n) ((n)^3) +#else +#define SEL16(n) (n) +#define SEL8(n) (n) +#endif + +#define gteVX0 ((s16*)psxRegs.CP2D.r)[SEL16(0)] +#define gteVY0 ((s16*)psxRegs.CP2D.r)[SEL16(1)] +#define gteVZ0 ((s16*)psxRegs.CP2D.r)[SEL16(2)] +#define gteVX1 ((s16*)psxRegs.CP2D.r)[SEL16(4)] +#define gteVY1 ((s16*)psxRegs.CP2D.r)[SEL16(5)] +#define gteVZ1 ((s16*)psxRegs.CP2D.r)[SEL16(6)] +#define gteVX2 ((s16*)psxRegs.CP2D.r)[SEL16(8)] +#define gteVY2 ((s16*)psxRegs.CP2D.r)[SEL16(9)] +#define gteVZ2 ((s16*)psxRegs.CP2D.r)[SEL16(10)] +#define gteRGB psxRegs.CP2D.r[6] +#define gteOTZ ((s16*)psxRegs.CP2D.r)[SEL16(7*2)] +#define gteIR0 ((s32*)psxRegs.CP2D.r)[8] +#define gteIR1 ((s32*)psxRegs.CP2D.r)[9] +#define gteIR2 ((s32*)psxRegs.CP2D.r)[10] +#define gteIR3 ((s32*)psxRegs.CP2D.r)[11] +#define gteSXY0 ((s32*)psxRegs.CP2D.r)[12] +#define gteSXY1 ((s32*)psxRegs.CP2D.r)[13] +#define gteSXY2 ((s32*)psxRegs.CP2D.r)[14] +#define gteSXYP ((s32*)psxRegs.CP2D.r)[15] +#define gteSX0 ((s16*)psxRegs.CP2D.r)[SEL16(12*2)] +#define gteSY0 ((s16*)psxRegs.CP2D.r)[SEL16(12*2+1)] +#define gteSX1 ((s16*)psxRegs.CP2D.r)[SEL16(13*2)] +#define gteSY1 ((s16*)psxRegs.CP2D.r)[SEL16(13*2+1)] +#define gteSX2 ((s16*)psxRegs.CP2D.r)[SEL16(14*2)] +#define gteSY2 ((s16*)psxRegs.CP2D.r)[SEL16(14*2+1)] +#define gteSXP ((s16*)psxRegs.CP2D.r)[SEL16(15*2)] +#define gteSYP ((s16*)psxRegs.CP2D.r)[SEL16(15*2+1)] +#define gteSZx ((u16*)psxRegs.CP2D.r)[SEL16(16*2)] +#define gteSZ0 ((u16*)psxRegs.CP2D.r)[SEL16(17*2)] +#define gteSZ1 ((u16*)psxRegs.CP2D.r)[SEL16(18*2)] +#define gteSZ2 ((u16*)psxRegs.CP2D.r)[SEL16(19*2)] +#define gteRGB0 psxRegs.CP2D.r[20] +#define gteRGB1 psxRegs.CP2D.r[21] +#define gteRGB2 psxRegs.CP2D.r[22] +#define gteMAC0 psxRegs.CP2D.r[24] +#define gteMAC1 ((s32*)psxRegs.CP2D.r)[25] +#define gteMAC2 ((s32*)psxRegs.CP2D.r)[26] +#define gteMAC3 ((s32*)psxRegs.CP2D.r)[27] +#define gteIRGB psxRegs.CP2D.r[28] +#define gteORGB psxRegs.CP2D.r[29] +#define gteLZCS psxRegs.CP2D.r[30] +#define gteLZCR psxRegs.CP2D.r[31] + +#define gteR ((u8 *)psxRegs.CP2D.r)[SEL8(6*4)] +#define gteG ((u8 *)psxRegs.CP2D.r)[SEL8(6*4+1)] +#define gteB ((u8 *)psxRegs.CP2D.r)[SEL8(6*4+2)] +#define gteCODE ((u8 *)psxRegs.CP2D.r)[SEL8(6*4+3)] +#define gteC gteCODE + +#define gteR0 ((u8 *)psxRegs.CP2D.r)[SEL8(20*4)] +#define gteG0 ((u8 *)psxRegs.CP2D.r)[SEL8(20*4+1)] +#define gteB0 ((u8 *)psxRegs.CP2D.r)[SEL8(20*4+2)] +#define gteCODE0 ((u8 *)psxRegs.CP2D.r)[SEL8(20*4+3)] +#define gteC0 gteCODE0 + +#define gteR1 ((u8 *)psxRegs.CP2D.r)[SEL8(21*4)] +#define gteG1 ((u8 *)psxRegs.CP2D.r)[SEL8(21*4+1)] +#define gteB1 ((u8 *)psxRegs.CP2D.r)[SEL8(21*4+2)] +#define gteCODE1 ((u8 *)psxRegs.CP2D.r)[SEL8(21*4+3)] +#define gteC1 gteCODE1 + +#define gteR2 ((u8 *)psxRegs.CP2D.r)[SEL8(22*4)] +#define gteG2 ((u8 *)psxRegs.CP2D.r)[SEL8(22*4+1)] +#define gteB2 ((u8 *)psxRegs.CP2D.r)[SEL8(22*4+2)] +#define gteCODE2 ((u8 *)psxRegs.CP2D.r)[SEL8(22*4+3)] +#define gteC2 gteCODE2 + + + +#define gteR11 ((s16*)psxRegs.CP2C.r)[SEL16(0)] +#define gteR12 ((s16*)psxRegs.CP2C.r)[SEL16(1)] +#define gteR13 ((s16*)psxRegs.CP2C.r)[SEL16(2)] +#define gteR21 ((s16*)psxRegs.CP2C.r)[SEL16(3)] +#define gteR22 ((s16*)psxRegs.CP2C.r)[SEL16(4)] +#define gteR23 ((s16*)psxRegs.CP2C.r)[SEL16(5)] +#define gteR31 ((s16*)psxRegs.CP2C.r)[SEL16(6)] +#define gteR32 ((s16*)psxRegs.CP2C.r)[SEL16(7)] +#define gteR33 ((s16*)psxRegs.CP2C.r)[SEL16(8)] +#define gteTRX ((s32*)psxRegs.CP2C.r)[5] +#define gteTRY ((s32*)psxRegs.CP2C.r)[6] +#define gteTRZ ((s32*)psxRegs.CP2C.r)[7] +#define gteL11 ((s16*)psxRegs.CP2C.r)[SEL16(16)] +#define gteL12 ((s16*)psxRegs.CP2C.r)[SEL16(17)] +#define gteL13 ((s16*)psxRegs.CP2C.r)[SEL16(18)] +#define gteL21 ((s16*)psxRegs.CP2C.r)[SEL16(19)] +#define gteL22 ((s16*)psxRegs.CP2C.r)[SEL16(20)] +#define gteL23 ((s16*)psxRegs.CP2C.r)[SEL16(21)] +#define gteL31 ((s16*)psxRegs.CP2C.r)[SEL16(22)] +#define gteL32 ((s16*)psxRegs.CP2C.r)[SEL16(23)] +#define gteL33 ((s16*)psxRegs.CP2C.r)[SEL16(24)] +#define gteRBK ((s32*)psxRegs.CP2C.r)[13] +#define gteGBK ((s32*)psxRegs.CP2C.r)[14] +#define gteBBK ((s32*)psxRegs.CP2C.r)[15] +#define gteLR1 ((s16*)psxRegs.CP2C.r)[SEL16(32)] +#define gteLR2 ((s16*)psxRegs.CP2C.r)[SEL16(33)] +#define gteLR3 ((s16*)psxRegs.CP2C.r)[SEL16(34)] +#define gteLG1 ((s16*)psxRegs.CP2C.r)[SEL16(35)] +#define gteLG2 ((s16*)psxRegs.CP2C.r)[SEL16(36)] +#define gteLG3 ((s16*)psxRegs.CP2C.r)[SEL16(37)] +#define gteLB1 ((s16*)psxRegs.CP2C.r)[SEL16(38)] +#define gteLB2 ((s16*)psxRegs.CP2C.r)[SEL16(39)] +#define gteLB3 ((s16*)psxRegs.CP2C.r)[SEL16(40)] +#define gteRFC ((s32*)psxRegs.CP2C.r)[21] +#define gteGFC ((s32*)psxRegs.CP2C.r)[22] +#define gteBFC ((s32*)psxRegs.CP2C.r)[23] +#define gteOFX ((s32*)psxRegs.CP2C.r)[24] +#define gteOFY ((s32*)psxRegs.CP2C.r)[25] +#define gteH ((u16*)psxRegs.CP2C.r)[SEL16(52)] +#define gteDQA ((s16*)psxRegs.CP2C.r)[SEL16(54)] +#define gteDQB ((s32*)psxRegs.CP2C.r)[28] +#define gteZSF3 ((s16*)psxRegs.CP2C.r)[SEL16(58)] +#define gteZSF4 ((s16*)psxRegs.CP2C.r)[SEL16(60)] +#define gteFLAG psxRegs.CP2C.r[31] + +__inline u32 MFC2(int reg) { + switch(reg) { + case 29: + gteORGB = (((gteIR1 >> 7) & 0x1f)) | + (((gteIR2 >> 7) & 0x1f)<<5) | + (((gteIR3 >> 7) & 0x1f)<<10); +// gteORGB = (gteIR1 ) | +// (gteIR2 << 5) | +// (gteIR3 << 10); +// gteORGB = ((gteIR1 & 0xf80)>>7) | +// ((gteIR2 & 0xf80)>>2) | +// ((gteIR3 & 0xf80)<<3); + return gteORGB; + + default: + return psxRegs.CP2D.r[reg]; + } +} + +__inline void MTC2(u32 value, int reg) { + int a; + + switch(reg) { + case 8: case 9: case 10: case 11: + psxRegs.CP2D.r[reg] = (short)value; + break; + + case 15: + gteSXY0 = gteSXY1; + gteSXY1 = gteSXY2; + gteSXY2 = value; + gteSXYP = value; + break; + + case 16: case 17: case 18: case 19: + psxRegs.CP2D.r[reg] = (value & 0xffff); + break; + + case 28: + psxRegs.CP2D.r[28] = value; + gteIR1 = ((value ) & 0x1f) << 7; + gteIR2 = ((value >> 5) & 0x1f) << 7; + gteIR3 = ((value >> 10) & 0x1f) << 7; +// gteIR1 = (value ) & 0x1f; +// gteIR2 = (value >> 5) & 0x1f; +// gteIR3 = (value >> 10) & 0x1f; +// gteIR1 = ((value ) & 0x1f) << 4; +// gteIR2 = ((value >> 5) & 0x1f) << 4; +// gteIR3 = ((value >> 10) & 0x1f) << 4; + break; + + case 30: + psxRegs.CP2D.r[30] = value; + + a = psxRegs.CP2D.r[30]; + if (a > 0) { + int i; + for (i=31; (a & (1 << i)) == 0 && i >= 0; i--); + psxRegs.CP2D.r[31] = 31 - i; + } else if (a < 0) { + int i; + a^= 0xffffffff; + for (i=31; (a & (1 << i)) == 0 && i >= 0; i--); + psxRegs.CP2D.r[31] = 31 - i; + } else { + psxRegs.CP2D.r[31] = 32; + } + break; + + default: + psxRegs.CP2D.r[reg] = value; + } +} + +void gteMFC2() { + if (!_Rt_) return; + psxRegs.GPR.r[_Rt_] = MFC2(_Rd_); +} + +void gteCFC2() { + if (!_Rt_) return; + psxRegs.GPR.r[_Rt_] = psxRegs.CP2C.r[_Rd_]; +} + +void gteMTC2() { + MTC2(psxRegs.GPR.r[_Rt_], _Rd_); +} + +void gteCTC2() { + psxRegs.CP2C.r[_Rd_] = psxRegs.GPR.r[_Rt_]; +} + +#define _oB_ (psxRegs.GPR.r[_Rs_] + _Imm_) + +void gteLWC2() { + MTC2(psxMemRead32(_oB_), _Rt_); +} + +void gteSWC2() { + psxMemWrite32(_oB_, MFC2(_Rt_)); +} + +/////LIMITATIONS AND OTHER STUFF************************************ + + +/* +#define MAGIC (((65536. * 65536. * 16) + (65536.*.5)) * 65536.) + +static __inline long float2int(double d) +{ + double dtemp = MAGIC + d; + return (*(long *)&dtemp)-0x80000000; +}*/ +/* +__inline double EDETEC1(double data) +{ + if (data<(double)-2147483647) {gteFLAG|=1<<30; return (double)-2147483647;} + else + if (data>(double) 2147483647) {gteFLAG|=1<<27; return (double) 2147483647;} + + else return data; +} + +__inline double EDETEC2(double data) +{ + if (data<(double)-2147483647) {gteFLAG|=1<<29; return (double)-2147483647;} + else + if (data>(double) 2147483647) {gteFLAG|=1<<26; return (double) 2147483647;} + + else return data; +} + +__inline double EDETEC3(double data) +{ + if (data<(double)-2147483647) {gteFLAG|=1<<28; return (double)-2147483647;} + else + if (data>(double) 2147483647) {gteFLAG|=1<<25; return (double) 2147483647;} + + else return data; +} + +__inline double EDETEC4(double data) +{ + if (data<(double)-2147483647) {gteFLAG|=1<<16; return (double)-2147483647;} + else + if (data>(double) 2147483647) {gteFLAG|=1<<15; return (double) 2147483647;} + + else return data; +}*/ +/* +double LimitAU(double fraction,unsigned long bitIndex) { + if (fraction < 0.0) { fraction = 0.0; gteFLAG |= (1<<bitIndex); } + else + if (fraction > 32767.0) { fraction = 32767.0; gteFLAG |= (1<<bitIndex); } + + return (fraction); +} + +double LimitAS(double fraction,unsigned long bitIndex) { + if (fraction <-32768.0) { fraction =-32768.0; gteFLAG |= (1<<bitIndex); } + else + if (fraction > 32767.0) { fraction = 32767.0; gteFLAG |= (1<<bitIndex); } + + return (fraction); +} + +double LimitB (double fraction,unsigned long bitIndex) { + if (fraction < 0.0) { fraction = 0.0; gteFLAG |= (1<<bitIndex); } + else + if (fraction > 255.0) { fraction = 255.0; gteFLAG |= (1<<bitIndex); } + + return (fraction); +} + +double LimitC (double fraction,unsigned long bitIndex) { + if (fraction < 0.0) { fraction = 0.0; gteFLAG |= (1<<bitIndex); } + else + if (fraction > 65535.0) { fraction = 65535.0; gteFLAG |= (1<<bitIndex); } + + return (fraction); +} + +double LimitD (double fraction,unsigned long bitIndex) { + if (fraction < -1024.0) { fraction = -1024.0; gteFLAG |= (1<<bitIndex); } + else + if (fraction > 1023.0) { fraction = 1023.0; gteFLAG |= (1<<bitIndex); } + + return (fraction); +} + +double LimitE (double fraction,unsigned long bitIndex) { + if (fraction < 0.0) { fraction = 0.0; gteFLAG |= (1<<bitIndex); } + else + if (fraction > 1023.0) { fraction = 1023.0; gteFLAG |= (1<<bitIndex); } + + return (fraction); +} + +double LIMIT(double data,double MIN,double MAX,int FLAG) +{ + if (data<MIN) {gteFLAG|=1<<FLAG; return MIN;} + else + if (data>MAX) {gteFLAG|=1<<FLAG; return MAX;} + + else return data; +} + +double ALIMIT(double data,double MIN,double MAX) +{ + if (data<MIN) return MIN; + else + if (data>MAX) return MAX; + + else return data; +} + +double OLIMIT(double data) +{ + data=(data); + + if (data<(double)-2147483647) {return (double)-2147483647;} + else + if (data>(double) 2147483647) {return (double) 2147483647;} + + else return data; +}*/ + +__inline double NC_OVERFLOW1(double x) { + if (x<-2147483648.0) {gteFLAG |= 1<<29;} + else if (x> 2147483647.0) {gteFLAG |= 1<<26;} + + return x; +} + +__inline double NC_OVERFLOW2(double x) { + if (x<-2147483648.0) {gteFLAG |= 1<<28;} + else if (x> 2147483647.0) {gteFLAG |= 1<<25;} + + return x; +} + +__inline double NC_OVERFLOW3(double x) { + if (x<-2147483648.0) {gteFLAG |= 1<<27;} + else if (x> 2147483647.0) {gteFLAG |= 1<<24;} + + return x; +} + +__inline double NC_OVERFLOW4(double x) { + if (x<-2147483648.0) {gteFLAG |= 1<<16;} + else if (x> 2147483647.0) {gteFLAG |= 1<<15;} + + return x; +} + +__inline s32 FNC_OVERFLOW1(s64 x) { + if (x < UNDERFLOW_BOUND) { gteFLAG |= (1 << 29); } + else if (x > 2147483647) { gteFLAG |= (1 << 26); } + + return (s32)x; +} + +__inline s32 FNC_OVERFLOW2(s64 x) { + if (x < UNDERFLOW_BOUND) { gteFLAG |= (1 << 28); } + else if (x > 2147483647) { gteFLAG |= (1 << 25); } + + return (s32)x; +} + +__inline s32 FNC_OVERFLOW3(s64 x) { + if (x < UNDERFLOW_BOUND) { gteFLAG |= (1 << 27); } + else if (x > 2147483647) { gteFLAG |= (1 << 24); } + + return (s32)x; +} + +__inline s32 FNC_OVERFLOW4(s64 x) { + if (x < UNDERFLOW_BOUND) { gteFLAG |= (1 << 16); } + else if (x > 2147483647) { gteFLAG |= (1 << 15); } + + return (s32)x; +} + +#define _LIMX(negv, posv, flagb) { \ + if (x < (negv)) { x = (negv); gteFLAG |= (1<<flagb); } else \ + if (x > (posv)) { x = (posv); gteFLAG |= (1<<flagb); } return (x); \ +} + +__inline double limA1S(double x) { _LIMX(-32768.0, 32767.0, 24); } +__inline double limA2S(double x) { _LIMX(-32768.0, 32767.0, 23); } +__inline double limA3S(double x) { _LIMX(-32768.0, 32767.0, 22); } +__inline double limA1U(double x) { _LIMX(0.0, 32767.0, 24); } +__inline double limA2U(double x) { _LIMX(0.0, 32767.0, 23); } +__inline double limA3U(double x) { _LIMX(0.0, 32767.0, 22); } +__inline double limB1 (double x) { _LIMX(0.0, 255.0, 21); } +__inline double limB2 (double x) { _LIMX(0.0, 255.0, 20); } +__inline double limB3 (double x) { _LIMX(0.0, 255.0, 19); } +__inline double limC (double x) { _LIMX(0.0, 65535.0, 18); } +__inline double limD1 (double x) { _LIMX(-1024.0, 1023.0, 14); } +__inline double limD2 (double x) { _LIMX(-1024.0, 1023.0, 13); } +__inline double limE (double x) { _LIMX(0.0, 4095.0, 12); } + +__inline double limG1(double x) { + if (x > 2147483647.0) { gteFLAG |= (1<<16); } else + if (x <-2147483648.0) { gteFLAG |= (1<<15); } + + if (x > 1023.0) { x = 1023.0; gteFLAG |= (1<<14); } else + if (x < -1024.0) { x = -1024.0; gteFLAG |= (1<<14); } return (x); +} + +__inline double limG2(double x) { + if (x > 2147483647.0) { gteFLAG |= (1<<16); } else + if (x <-2147483648.0) { gteFLAG |= (1<<15); } + + if (x > 1023.0) { x = 1023.0; gteFLAG |= (1<<13); } else + if (x < -1024.0) { x = -1024.0; gteFLAG |= (1<<13); } return (x); +} + +__inline s32 F12limA1S(s64 x) { _LIMX(-32768<<12, 32767<<12, 24); } +__inline s32 F12limA2S(s64 x) { _LIMX(-32768<<12, 32767<<12, 23); } +__inline s32 F12limA3S(s64 x) { _LIMX(-32768<<12, 32767<<12, 22); } +__inline s32 F12limA1U(s64 x) { _LIMX(0, 32767<<12, 24); } +__inline s32 F12limA2U(s64 x) { _LIMX(0, 32767<<12, 23); } +__inline s32 F12limA3U(s64 x) { _LIMX(0, 32767<<12, 22); } + +__inline s16 FlimA1S(s32 x) { _LIMX(-32768, 32767, 24); } +__inline s16 FlimA2S(s32 x) { _LIMX(-32768, 32767, 23); } +__inline s16 FlimA3S(s32 x) { _LIMX(-32768, 32767, 22); } +__inline s16 FlimA1U(s32 x) { _LIMX(0, 32767, 24); } +__inline s16 FlimA2U(s32 x) { _LIMX(0, 32767, 23); } +__inline s16 FlimA3U(s32 x) { _LIMX(0, 32767, 22); } +__inline u8 FlimB1 (s32 x) { _LIMX(0, 255, 21); } +__inline u8 FlimB2 (s32 x) { _LIMX(0, 255, 20); } +__inline u8 FlimB3 (s32 x) { _LIMX(0, 255, 19); } +__inline u16 FlimC (s32 x) { _LIMX(0, 65535, 18); } +__inline s32 FlimD1 (s32 x) { _LIMX(-1024, 1023, 14); } +__inline s32 FlimD2 (s32 x) { _LIMX(-1024, 1023, 13); } +__inline s32 FlimE (s32 x) { _LIMX(0, 65535, 12); } +//__inline s32 FlimE (s32 x) { _LIMX(0, 4095, 12); } + +__inline s32 FlimG1(s64 x) { + if (x > 2147483647) { gteFLAG |= (1 << 16); } + else if (x < UNDERFLOW_BOUND) { gteFLAG |= (1 << 15); } + + if (x > 1023) { x = 1023; gteFLAG |= (1 << 14); } + else if (x < -1024) { x = -1024; gteFLAG |= (1 << 14); } return (x); +} + +__inline s32 FlimG2(s64 x) { + if (x > 2147483647) { gteFLAG |= (1 << 16); } + else if (x < UNDERFLOW_BOUND) { gteFLAG |= (1 << 15); } + + if (x > 1023) { x = 1023; gteFLAG |= (1 << 13); } + else if (x < -1024) { x = -1024; gteFLAG |= (1 << 13); } return (x); +} + +#define MAC2IR() { \ + if (gteMAC1 < (long)(-32768)) { gteIR1=(long)(-32768); gteFLAG |= (1 << 24);} \ + else \ + if (gteMAC1 > (long)( 32767)) { gteIR1=(long)( 32767); gteFLAG |= (1 << 24);} \ + else gteIR1=(long)gteMAC1; \ + if (gteMAC2 < (long)(-32768)) { gteIR2=(long)(-32768); gteFLAG|=1<<23;} \ + else \ + if (gteMAC2 > (long)( 32767)) { gteIR2=(long)( 32767); gteFLAG|=1<<23;} \ + else gteIR2=(long)gteMAC2; \ + if (gteMAC3 < (long)(-32768)) { gteIR3=(long)(-32768); gteFLAG|=1<<22;} \ + else \ + if (gteMAC3 > (long)( 32767)) { gteIR3=(long)( 32767); gteFLAG|=1<<22;} \ + else gteIR3=(long)gteMAC3; \ +} + + +#define MAC2IR1() { \ + if (gteMAC1 < (long)0) { gteIR1=(long)0; gteFLAG|=1<<24;} \ + else if (gteMAC1 > (long)(32767)) { gteIR1=(long)(32767); gteFLAG|=1<<24;} \ + else gteIR1=(long)gteMAC1; \ + if (gteMAC2 < (long)0) { gteIR2=(long)0; gteFLAG|=1<<23;} \ + else if (gteMAC2 > (long)(32767)) { gteIR2=(long)(32767); gteFLAG|=1<<23;} \ + else gteIR2=(long)gteMAC2; \ + if (gteMAC3 < (long)0) { gteIR3=(long)0; gteFLAG|=1<<22;} \ + else if (gteMAC3 > (long)(32767)) { gteIR3=(long)(32767); gteFLAG|=1<<22;} \ + else gteIR3=(long)gteMAC3; \ +} + +//********END OF LIMITATIONS**********************************/ + +#define GTE_RTPS1(vn) { \ + gteMAC1 = FNC_OVERFLOW1(((signed long)(gteR11*gteVX##vn + gteR12*gteVY##vn + gteR13*gteVZ##vn)>>12) + gteTRX); \ + gteMAC2 = FNC_OVERFLOW2(((signed long)(gteR21*gteVX##vn + gteR22*gteVY##vn + gteR23*gteVZ##vn)>>12) + gteTRY); \ + gteMAC3 = FNC_OVERFLOW3(((signed long)(gteR31*gteVX##vn + gteR32*gteVY##vn + gteR33*gteVZ##vn)>>12) + gteTRZ); \ +} + +/* gteMAC1 = NC_OVERFLOW1(((signed long)(gteR11*gteVX0 + gteR12*gteVY0 + gteR13*gteVZ0)>>12) + gteTRX); + gteMAC2 = NC_OVERFLOW2(((signed long)(gteR21*gteVX0 + gteR22*gteVY0 + gteR23*gteVZ0)>>12) + gteTRY); + gteMAC3 = NC_OVERFLOW3(((signed long)(gteR31*gteVX0 + gteR32*gteVY0 + gteR33*gteVZ0)>>12) + gteTRZ);*/ + +#if 0 + +#define GTE_RTPS2(vn) { \ + if (gteSZ##vn == 0) { \ + DSZ = 2.0f; gteFLAG |= 1<<17; \ + } else { \ + DSZ = (double)gteH / gteSZ##vn; \ + if (DSZ > 2.0) { DSZ = 2.0f; gteFLAG |= 1<<17; } \ +/* if (DSZ > 2147483647.0) { DSZ = 2.0f; gteFLAG |= 1<<17; }*/ \ + } \ + \ +/* gteSX##vn = limG1(gteOFX/65536.0 + (limA1S(gteMAC1) * DSZ));*/ \ +/* gteSY##vn = limG2(gteOFY/65536.0 + (limA2S(gteMAC2) * DSZ));*/ \ + gteSX##vn = FlimG1(gteOFX/65536.0 + (gteIR1 * DSZ)); \ + gteSY##vn = FlimG2(gteOFY/65536.0 + (gteIR2 * DSZ)); \ +} + +#define GTE_RTPS3() { \ + DSZ = gteDQB/16777216.0 + (gteDQA/256.0) * DSZ; \ + gteMAC0 = DSZ * 16777216.0; \ + gteIR0 = limE(DSZ * 4096.0f); \ +printf("zero %x, %x\n", gteMAC0, gteIR0); \ +} +#endif +//#if 0 +#define GTE_RTPS2(vn) { \ + if (gteSZ##vn == 0) { \ + FDSZ = 2 << 16; gteFLAG |= 1<<17; \ + } else { \ + FDSZ = ((u64)gteH << 32) / ((u64)gteSZ##vn << 16); \ + if ((u64)FDSZ > (2 << 16)) { FDSZ = 2 << 16; gteFLAG |= 1<<17; } \ + } \ + \ + gteSX##vn = FlimG1((gteOFX + (((s64)((s64)gteIR1 << 16) * FDSZ) >> 16)) >> 16); \ + gteSY##vn = FlimG2((gteOFY + (((s64)((s64)gteIR2 << 16) * FDSZ) >> 16)) >> 16); \ +} + +#define GTE_RTPS3() { \ + FDSZ = (s64)((s64)gteDQB + (((s64)((s64)gteDQA << 8) * FDSZ) >> 8)); \ + gteMAC0 = FDSZ; \ + gteIR0 = FlimE(FDSZ >> 12); \ +} +//#endif +// gteMAC0 = (gteDQB/16777216.0 + (gteDQA/256.0) * DSZ) * 16777216.0; +// gteIR0 = limE((gteDQB/16777216.0 + (gteDQA/256.0) * DSZ) * 4096.0); +// gteMAC0 = ((gteDQB >> 24) + (gteDQA >> 8) * DSZ) * 16777216.0; +// gteIR0 = FlimE(((gteDQB >> 24) + (gteDQA >> 8) * DSZ) * 4096.0); + + +void gteRTPS() { +// double SSX0,SSY0,SSZ0; +// double SZ; +// double DSZ; + s64 FDSZ; +#ifdef GTE_DUMP + static int sample = 0; sample++; +#endif + +#ifdef GTE_LOG + GTE_LOG("GTE_RTPS\n"); +#endif + +#ifdef GTE_DUMP + if(sample < 100) + { + G_OP("RTPS", 14); + G_SD(0); + G_SD(1); + + G_SD(16); // Store original fifo + G_SD(17); + G_SD(18); + G_SD(19); + + G_SC(0); + G_SC(1); + G_SC(2); + G_SC(3); + G_SC(4); + G_SC(5); + G_SC(6); + G_SC(7); + + G_SC(24); + G_SC(25); + G_SC(26); + G_SC(27); + G_SC(28); + } +#endif +/* gteFLAG = 0; + + SSX0 = NC_OVERFLOW1((double)gteTRX + ((double)(gteVX0*gteR11) + (double)(gteVY0*gteR12) + (double)(gteVZ0*gteR13))/4096.0); + SSY0 = NC_OVERFLOW2((double)gteTRY + ((double)(gteVX0*gteR21) + (double)(gteVY0*gteR22) + (double)(gteVZ0*gteR23))/4096.0); + SSZ0 = NC_OVERFLOW3((double)gteTRZ + ((double)(gteVX0*gteR31) + (double)(gteVY0*gteR32) + (double)(gteVZ0*gteR33))/4096.0); + + SZ = LIMIT(SSZ0,(double)0,(double)65535,18); + DSZ = ((double)gteH/SZ); + + if ((DSZ>(double)2147483647)) {DSZ=(double)2; gteFLAG|=1<<17;} + + gteSZ0 = gteSZ1; + gteSZ1 = gteSZ2; + gteSZ2 = gteSZx; + gteSZx = (unsigned short)float2int(SZ); + + psxRegs.CP2D.r[12]= psxRegs.CP2D.r[13]; + psxRegs.CP2D.r[13]= psxRegs.CP2D.r[14]; + + gteSX2 = (signed short)float2int(LIMIT((double)(gteOFX)/65536.0f + (LimitAS(SSX0,24)*DSZ),(double)-1024,(double)1024,14)); + gteSY2 = (signed short)float2int(LIMIT((double)(gteOFY)/65536.0f + (LimitAS(SSY0,23)*DSZ),(double)-1024,(double)1024,13)); + + gteMAC1 = (signed long)(SSX0); + gteMAC2 = (signed long)(SSY0); + gteMAC3 = (signed long)(SSZ0); + + MAC2IR(); + + gteMAC0 = (signed long)float2int(OLIMIT((((double)gteDQB/(double)16777216) + (((double)gteDQA/(double)256)*DSZ))*16777216)); + gteIR0 = (signed long)float2int(LIMIT(((((double)gteDQB/(double)16777216) + (((double)gteDQA/(double)256)*DSZ))*4096),(double)0,(double)4095,12)); + + if (gteFLAG & 0x7f87e000) gteFLAG|=0x80000000;*/ + + gteFLAG = 0; + + GTE_RTPS1(0); + + MAC2IR(); + + gteSZx = gteSZ0; + gteSZ0 = gteSZ1; + gteSZ1 = gteSZ2; +// gteSZ2 = limC(gteMAC3); + gteSZ2 = FlimC(gteMAC3); + + gteSXY0 = gteSXY1; + gteSXY1 = gteSXY2; + + GTE_RTPS2(2); + gteSXYP = gteSXY2; + + GTE_RTPS3(); + + SUM_FLAG; + +#ifdef GTE_DUMP + if(sample < 100) + { + G_GD(8); + G_GD(9); + G_GD(10); + G_GD(11); + + //G_GD(12); + //G_GD(13); + G_GD(14); + + G_GD(16); + G_GD(17); + G_GD(18); + G_GD(19); + + G_GD(24); + G_GD(25); + G_GD(26); + G_GD(27); + + G_GC(31); + } +#endif +} + +void gteRTPT() { +// double SSX0,SSY0,SSZ0; +// double SZ; +// double DSZ; + s64 FDSZ; +#ifdef GTE_DUMP + static int sample = 0; sample++; +#endif + +#ifdef GTE_LOG + GTE_LOG("GTE_RTPT\n"); +#endif + +#ifdef GTE_DUMP + if(sample < 100) + { + G_OP("RTPT", 22); + G_SD(0); + G_SD(1); + G_SD(2); + G_SD(3); + G_SD(4); + G_SD(5); + + G_SD(16); // Store original fifo + G_SD(17); + G_SD(18); + G_SD(19); + + G_SC(0); + G_SC(1); + G_SC(2); + G_SC(3); + G_SC(4); + G_SC(5); + G_SC(6); + G_SC(7); + + G_SC(24); + G_SC(25); + G_SC(26); + G_SC(27); + G_SC(28); + } +#endif +/* gteFLAG = 0; + + gteSZ0 = gteSZx; + + SSX0 = NC_OVERFLOW1((double)gteTRX + ((double)(gteVX0 * gteR11) + (double)(gteVY0 * gteR12) + (double)(gteVZ0 * gteR13)) / 4096.0); + SSY0 = NC_OVERFLOW2((double)gteTRY + ((double)(gteVX0 * gteR21) + (double)(gteVY0 * gteR22) + (double)(gteVZ0 * gteR23)) / 4096.0); + SSZ0 = NC_OVERFLOW3((double)gteTRZ + ((double)(gteVX0 * gteR31) + (double)(gteVY0 * gteR32) + (double)(gteVZ0 * gteR33)) / 4096.0); + + SZ = LIMIT(SSZ0, (double)0, (double)65535, 18); + DSZ = ((double)gteH / SZ); + + if ((DSZ>(double)2147483647)) {DSZ=(double)2; gteFLAG|=1<<17;} + + gteSZ1 = (unsigned short)float2int(SZ); + gteSX0 = (signed short)float2int(LIMIT((double)(gteOFX)/65536.0f + (LimitAS(SSX0,24)*DSZ),(double)-1024,(double)1023,14)); + gteSY0 = (signed short)float2int(LIMIT((double)(gteOFY)/65536.0f + (LimitAS(SSY0,23)*DSZ),(double)-1024,(double)1023,13)); + + SSX0 = NC_OVERFLOW1((double)gteTRX + ((double)(gteVX1*gteR11) + (double)(gteVY1*gteR12) + (double)(gteVZ1*gteR13))/4096.0); + SSY0 = NC_OVERFLOW2((double)gteTRY + ((double)(gteVX1*gteR21) + (double)(gteVY1*gteR22) + (double)(gteVZ1*gteR23))/4096.0); + SSZ0 = NC_OVERFLOW3((double)gteTRZ + ((double)(gteVX1*gteR31) + (double)(gteVY1*gteR32) + (double)(gteVZ1*gteR33))/4096.0); + + SZ = LIMIT(SSZ0,(double)0,(double)65535,18); + DSZ = ((double)gteH/SZ); + + if ((DSZ>(double)2147483647)) {DSZ=(double)2; gteFLAG|=1<<17;} + + gteSZ2 = (unsigned short)float2int(SZ); + gteSX1 = (signed short)float2int(LIMIT((double)(gteOFX)/65536.0f + (LimitAS(SSX0,24)*DSZ),(double)-1024,(double)1023,14)); + gteSY1 = (signed short)float2int(LIMIT((double)(gteOFY)/65536.0f + (LimitAS(SSY0,23)*DSZ),(double)-1024,(double)1023,13)); + + SSX0 = NC_OVERFLOW1((double)gteTRX + ((double)(gteVX2*gteR11) + (double)(gteVY2*gteR12) + (double)(gteVZ2*gteR13))/4096.0); + SSY0 = NC_OVERFLOW2((double)gteTRY + ((double)(gteVX2*gteR21) + (double)(gteVY2*gteR22) + (double)(gteVZ2*gteR23))/4096.0); + SSZ0 = NC_OVERFLOW3((double)gteTRZ + ((double)(gteVX2*gteR31) + (double)(gteVY2*gteR32) + (double)(gteVZ2*gteR33))/4096.0); + + SZ = LIMIT(SSZ0,(double)0,(double)65535,18); + DSZ = ((double)gteH/SZ); + + if ((DSZ>(double)2147483647)) {DSZ=(double)2; gteFLAG|=1<<17;} + + gteSZx = (unsigned short)float2int(SZ); + gteSX2 = (signed short)float2int(LIMIT((double)(gteOFX)/65536.0f + (LimitAS(SSX0,24)*DSZ),(double)-1024,(double)1023,14)); + gteSY2 = (signed short)float2int(LIMIT((double)(gteOFY)/65536.0f + (LimitAS(SSY0,23)*DSZ),(double)-1024,(double)1023,13)); + + gteMAC1 = (signed long)float2int(SSX0); + gteMAC2 = (signed long)float2int(SSY0); + gteMAC3 = (signed long)float2int(SSZ0); + + MAC2IR(); + + gteMAC0 = (signed long)float2int(OLIMIT((((double)gteDQB/(double)16777216) + (((double)gteDQA/(double)256)*DSZ))*16777216)); + gteIR0 = (signed long)float2int(LIMIT(((((double)gteDQB/(double)16777216) + (((double)gteDQA/(double)256)*DSZ))*4096),(double)0,(double)4095,12)); + + if (gteFLAG & 0x7f87e000) gteFLAG|=0x80000000;*/ + + /* NC: old + gteFLAG = 0; + + gteSZ0 = gteSZx; + + gteMAC1 = NC_OVERFLOW1(((signed long)(gteR11*gteVX0 + gteR12*gteVY0 + gteR13*gteVZ0)>>12) + gteTRX); + gteMAC2 = NC_OVERFLOW2(((signed long)(gteR21*gteVX0 + gteR22*gteVY0 + gteR23*gteVZ0)>>12) + gteTRY); + gteMAC3 = NC_OVERFLOW3(((signed long)(gteR31*gteVX0 + gteR32*gteVY0 + gteR33*gteVZ0)>>12) + gteTRZ); + + DSZ = gteH / limC(gteMAC3); + if (DSZ > 2147483647.0) { DSZ = 2.0f; gteFLAG |= 1<<17; } + + gteSZ1 = limC(gteMAC3); + + gteSX0 = limG1(gteOFX/65536.0 + (limA1S(gteMAC1) * DSZ)); + gteSY0 = limG2(gteOFY/65536.0 + (limA2S(gteMAC2) * DSZ)); + + gteMAC1 = NC_OVERFLOW1(((signed long)(gteR11*gteVX1 + gteR12*gteVY1 + gteR13*gteVZ1)>>12) + gteTRX); + gteMAC2 = NC_OVERFLOW2(((signed long)(gteR21*gteVX1 + gteR22*gteVY1 + gteR23*gteVZ1)>>12) + gteTRY); + gteMAC3 = NC_OVERFLOW3(((signed long)(gteR31*gteVX1 + gteR32*gteVY1 + gteR33*gteVZ1)>>12) + gteTRZ); + + DSZ = gteH / limC(gteMAC3); + if (DSZ > 2147483647.0) { DSZ = 2.0f; gteFLAG |= 1<<17; } + + gteSZ2 = limC(gteMAC3); + + gteSX1 = limG1(gteOFX/65536.0 + (limA1S(gteMAC1) * DSZ )); + gteSY1 = limG2(gteOFY/65536.0 + (limA2S(gteMAC2) * DSZ )); + + gteMAC1 = NC_OVERFLOW1(((signed long)(gteR11*gteVX2 + gteR12*gteVY2 + gteR13*gteVZ2)>>12) + gteTRX); + gteMAC2 = NC_OVERFLOW2(((signed long)(gteR21*gteVX2 + gteR22*gteVY2 + gteR23*gteVZ2)>>12) + gteTRY); + gteMAC3 = NC_OVERFLOW3(((signed long)(gteR31*gteVX2 + gteR32*gteVY2 + gteR33*gteVZ2)>>12) + gteTRZ); + + DSZ = gteH / limC(gteMAC3); if (DSZ > 2147483647.0f) { DSZ = 2.0f; gteFLAG |= 1<<17; } + + gteSZx = gteSZ2; + + gteSX2 = limG1(gteOFX/65536.0 + (limA1S(gteMAC1) * DSZ )); + gteSY2 = limG2(gteOFY/65536.0 + (limA2S(gteMAC2) * DSZ )); + + MAC2IR(); + + gteMAC0 = (gteDQB/16777216.0 + (gteDQA/256.0) * DSZ ) * 16777216.0; + gteIR0 = limE((gteDQB/16777216.0 + (gteDQA/256.0) * DSZ ) * 4096.0f); + */ + + gteFLAG = 0; + + gteSZx = gteSZ2; + + GTE_RTPS1(0); + +// gteSZ0 = limC(gteMAC3); + gteSZ0 = FlimC(gteMAC3); + + gteIR1 = FlimA1S(gteMAC1); + gteIR2 = FlimA2S(gteMAC2); + GTE_RTPS2(0); + + GTE_RTPS1(1); + +// gteSZ1 = limC(gteMAC3); + gteSZ1 = FlimC(gteMAC3); + + gteIR1 = FlimA1S(gteMAC1); + gteIR2 = FlimA2S(gteMAC2); + GTE_RTPS2(1); + + GTE_RTPS1(2); + + MAC2IR(); + +// gteSZ2 = limC(gteMAC3); + gteSZ2 = FlimC(gteMAC3); + + GTE_RTPS2(2); + gteSXYP = gteSXY2; + + GTE_RTPS3(); + + SUM_FLAG; + +#ifdef GTE_DUMP + if(sample < 100) + { + G_GD(8); + G_GD(9); + G_GD(10); + G_GD(11); + + G_GD(12); + G_GD(13); + G_GD(14); + + G_GD(16); + G_GD(17); + G_GD(18); + G_GD(19); + + G_GD(24); + G_GD(25); + G_GD(26); + G_GD(27); + + G_GC(31); + } +#endif +} + +#define gte_C11 gteLR1 +#define gte_C12 gteLR2 +#define gte_C13 gteLR3 +#define gte_C21 gteLG1 +#define gte_C22 gteLG2 +#define gte_C23 gteLG3 +#define gte_C31 gteLB1 +#define gte_C32 gteLB2 +#define gte_C33 gteLB3 + +#define _MVMVA_FUNC(_v0, _v1, _v2, mx) { \ + SSX = (_v0) * mx##11 + (_v1) * mx##12 + (_v2) * mx##13; \ + SSY = (_v0) * mx##21 + (_v1) * mx##22 + (_v2) * mx##23; \ + SSZ = (_v0) * mx##31 + (_v1) * mx##32 + (_v2) * mx##33; \ +} + +void gteMVMVA() { +// double SSX, SSY, SSZ; + s64 SSX, SSY, SSZ; + +#ifdef GTE_LOG + GTE_LOG("GTE_MVMVA %lx\n", psxRegs.code & 0x1ffffff); +#endif + + switch (psxRegs.code & 0x78000) { + case 0x00000: // V0 * R + _MVMVA_FUNC(gteVX0, gteVY0, gteVZ0, gteR); break; + case 0x08000: // V1 * R + _MVMVA_FUNC(gteVX1, gteVY1, gteVZ1, gteR); break; + case 0x10000: // V2 * R + _MVMVA_FUNC(gteVX2, gteVY2, gteVZ2, gteR); break; + case 0x18000: // IR * R + _MVMVA_FUNC((short)gteIR1, (short)gteIR2, (short)gteIR3, gteR); + break; + case 0x20000: // V0 * L + _MVMVA_FUNC(gteVX0, gteVY0, gteVZ0, gteL); break; + case 0x28000: // V1 * L + _MVMVA_FUNC(gteVX1, gteVY1, gteVZ1, gteL); break; + case 0x30000: // V2 * L + _MVMVA_FUNC(gteVX2, gteVY2, gteVZ2, gteL); break; + case 0x38000: // IR * L + _MVMVA_FUNC((short)gteIR1, (short)gteIR2, (short)gteIR3, gteL); break; + case 0x40000: // V0 * C + _MVMVA_FUNC(gteVX0, gteVY0, gteVZ0, gte_C); break; + case 0x48000: // V1 * C + _MVMVA_FUNC(gteVX1, gteVY1, gteVZ1, gte_C); break; + case 0x50000: // V2 * C + _MVMVA_FUNC(gteVX2, gteVY2, gteVZ2, gte_C); break; + case 0x58000: // IR * C + _MVMVA_FUNC((short)gteIR1, (short)gteIR2, (short)gteIR3, gte_C); break; + default: + SSX = SSY = SSZ = 0; + } + + if (psxRegs.code & 0x80000) { +// SSX /= 4096.0; SSY /= 4096.0; SSZ /= 4096.0; + SSX>>= 12; SSY>>= 12; SSZ>>= 12; + } + + switch (psxRegs.code & 0x6000) { + case 0x0000: // Add TR + SSX+= gteTRX; + SSY+= gteTRY; + SSZ+= gteTRZ; + break; + case 0x2000: // Add BK + SSX+= gteRBK; + SSY+= gteGBK; + SSZ+= gteBBK; + break; + case 0x4000: // Add FC + SSX+= gteRFC; + SSY+= gteGFC; + SSZ+= gteBFC; + break; + } + + gteFLAG = 0; + //gteMAC1 = (long)SSX; + //gteMAC2 = (long)SSY; + //gteMAC3 = (long)SSZ;//okay the follow lines are correct?? +/* gteMAC1 = NC_OVERFLOW1(SSX); + gteMAC2 = NC_OVERFLOW2(SSY); + gteMAC3 = NC_OVERFLOW3(SSZ);*/ + gteMAC1 = FNC_OVERFLOW1(SSX); + gteMAC2 = FNC_OVERFLOW2(SSY); + gteMAC3 = FNC_OVERFLOW3(SSZ); + if (psxRegs.code & 0x400) + MAC2IR1() + else MAC2IR() + + SUM_FLAG; +} + +void gteNCLIP() { +#ifdef GTE_DUMP + static int sample = 0; sample++; +#endif + +#ifdef GTE_LOG + GTE_LOG("GTE_NCLIP\n"); +#endif + + //gteLog +#ifdef GTE_DUMP + if(sample < 100) + { + G_OP("NCLIP", 8); + G_SD(12); + G_SD(13); + G_SD(14); + } +#endif + +/* gteFLAG = 0; + + gteMAC0 = (signed long)float2int(EDETEC4( + ((double)gteSX0*((double)gteSY1-(double)gteSY2))+ + ((double)gteSX1*((double)gteSY2-(double)gteSY0))+ + ((double)gteSX2*((double)gteSY0-(double)gteSY1)))); + + if (gteFLAG & 0x7f87e000) gteFLAG|=0x80000000;*/ + gteFLAG = 0; + + + gteMAC0 = gteSX0 * (gteSY1 - gteSY2) + + gteSX1 * (gteSY2 - gteSY0) + + gteSX2 * (gteSY0 - gteSY1); + + //gteMAC0 = (gteSX0 - gteSX1) * (gteSY0 - gteSY2) - (gteSX0 - gteSX2) * (gteSY0 - gteSY1); + + SUM_FLAG; + +#ifdef GTE_DUMP + if(sample < 100) + { + G_GD(24); + G_GC(31); + } +#endif +} + +void gteAVSZ3() { +// unsigned long SS; +// double SZ1,SZ2,SZ3; +// double ZSF3; +#ifdef GTE_DUMP + static int sample = 0; sample++; +#endif + +#ifdef GTE_LOG + GTE_LOG("GTE_AVSZ3\n"); +#endif + +#ifdef GTE_DUMP + if(sample < 100) + { + G_OP("AVSZ3", 5); + G_SD(16); + G_SD(17); + G_SD(18); + G_SD(19); + G_SC(29); + G_SC(30); + } +#endif + +/* gteFLAG = 0; + + SS = psxRegs.CP2D.r[17] & 0xffff; SZ1 = (double)SS; + SS = psxRegs.CP2D.r[18] & 0xffff; SZ2 = (double)SS; + SS = psxRegs.CP2D.r[19] & 0xffff; SZ3 = (double)SS; + SS = psxRegs.CP2C.r[29] & 0xffff; ZSF3 = (double)SS/(double)4096; + + psxRegs.CP2D.r[24] = (signed long)float2int(EDETEC4(((SZ1+SZ2+SZ3)*ZSF3))); + psxRegs.CP2D.r[7] = (unsigned short)float2int(LimitC(((SZ1+SZ2+SZ3)*ZSF3),18)); + + if (gteFLAG & 0x7f87e000) gteFLAG|=0x80000000;*/ + + + gteFLAG = 0; + + /* NC: OLD + gteMAC0 = ((gteSZ1 + gteSZ2 + gteSZx) * (gteZSF3/4096.0f)); + + gteOTZ = limC((double)gteMAC0); + */ +/* gteMAC0 = ((gteSZ1 + gteSZ2 + gteSZx) * (gteZSF3)); + + gteOTZ = limC((double)(gteMAC0 >> 12));*/ + gteMAC0 = ((gteSZ0 + gteSZ1 + gteSZ2) * (gteZSF3)) >> 12; + + gteOTZ = FlimC(gteMAC0); +// gteOTZ = limC((double)gteMAC0); + + SUM_FLAG + +#ifdef GTE_DUMP + if(sample < 100) + { + G_GD(7); + G_GD(24); + G_GC(31); + } +#endif +} + +void gteAVSZ4() { +// unsigned long SS; +// double SZ0,SZ1,SZ2,SZ3; +// double ZSF4; +#ifdef GTE_DUMP + static int sample = 0; sample++; +#endif + +#ifdef GTE_LOG + GTE_LOG("GTE_AVSZ4\n"); +#endif + +#ifdef GTE_DUMP + if(sample < 100) + { + G_OP("AVSZ4", 6); + G_SD(16); + G_SD(17); + G_SD(18); + G_SD(19); + G_SC(29); + G_SC(30); + } +#endif + +/* gteFLAG = 0; + + SS = psxRegs.CP2D.r[16] & 0xffff; SZ0 = (double)SS; + SS = psxRegs.CP2D.r[17] & 0xffff; SZ1 = (double)SS; + SS = psxRegs.CP2D.r[18] & 0xffff; SZ2 = (double)SS; + SS = psxRegs.CP2D.r[19] & 0xffff; SZ3 = (double)SS; + SS = psxRegs.CP2C.r[30] & 0xffff; ZSF4 = (double)SS/(double)4096; + + psxRegs.CP2D.r[24] = (signed long)float2int(EDETEC4(((SZ0+SZ1+SZ2+SZ3)*ZSF4))); + psxRegs.CP2D.r[7] = (unsigned short)float2int(LimitC(((SZ0+SZ1+SZ2+SZ3)*ZSF4),18)); + + if (gteFLAG & 0x7f87e000) gteFLAG|=0x80000000;*/ + gteFLAG = 0; + + /* NC: OLD + gteMAC0 = ((gteSZ0 + gteSZ1 + gteSZ2 + gteSZx) * (gteZSF4/4096.0f)); + + gteOTZ = limC((double)gteMAC0); + */ +/* gteMAC0 = ((gteSZ0 + gteSZ1 + gteSZ2 + gteSZx) * (gteZSF4)); + + gteOTZ = limC((double)(gteMAC0 >> 12)); +*/ + gteMAC0 = ((gteSZx + gteSZ0 + gteSZ1 + gteSZ2) * (gteZSF4))>> 12; + + gteOTZ = FlimC(gteMAC0); +// gteOTZ = limC((double)gteMAC0); + + SUM_FLAG + +#ifdef GTE_DUMP + if(sample < 100) + { + G_GD(7); + G_GD(24); + G_GC(31); + } +#endif +} + +void gteSQR() { + //double SSX0,SSY0,SSZ0; +#ifdef GTE_DUMP + static int sample = 0; sample++; +#endif + +#ifdef GTE_LOG + GTE_LOG("GTE_SQR %lx\n", psxRegs.code & 0x1ffffff); +#endif + +#ifdef GTE_DUMP + if(sample < 100) + { + G_OP("SQR", 5); + G_SD(9); + G_SD(10); + G_SD(11); + } +#endif + +/* gteFLAG = 0; + + SSX0 = (double)gteIR1 * gteIR1; + SSY0 = (double)gteIR2 * gteIR2; + SSZ0 = (double)gteIR3 * gteIR3; + + if (psxRegs.code & 0x80000) { + SSX0 /= 4096.0; SSY0 /= 4096.0; SSZ0 /= 4096.0; + } + + gteMAC1 = (long)SSX0; + gteMAC2 = (long)SSY0; + gteMAC3 = (long)SSZ0; + + MAC2IR1(); + + if (gteFLAG & 0x7f87e000) gteFLAG|=0x80000000;*/ + gteFLAG = 0; + +/* if (psxRegs.code & 0x80000) { + gteMAC1 = NC_OVERFLOW1((gteIR1 * gteIR1) / 4096.0f); + gteMAC2 = NC_OVERFLOW2((gteIR2 * gteIR2) / 4096.0f); + gteMAC3 = NC_OVERFLOW3((gteIR3 * gteIR3) / 4096.0f); + } else { + gteMAC1 = NC_OVERFLOW1(gteIR1 * gteIR1); + gteMAC2 = NC_OVERFLOW2(gteIR2 * gteIR2); + gteMAC3 = NC_OVERFLOW3(gteIR3 * gteIR3); + }*/ + if (psxRegs.code & 0x80000) { + gteMAC1 = FNC_OVERFLOW1((gteIR1 * gteIR1) >> 12); + gteMAC2 = FNC_OVERFLOW2((gteIR2 * gteIR2) >> 12); + gteMAC3 = FNC_OVERFLOW3((gteIR3 * gteIR3) >> 12); + } else { + gteMAC1 = FNC_OVERFLOW1(gteIR1 * gteIR1); + gteMAC2 = FNC_OVERFLOW2(gteIR2 * gteIR2); + gteMAC3 = FNC_OVERFLOW3(gteIR3 * gteIR3); + } + MAC2IR1(); + + SUM_FLAG + +#ifdef GTE_DUMP + if(sample < 100) + { + G_GD(9); + G_GD(10); + G_GD(11); + G_GD(25); + G_GD(26); + G_GD(27); + G_GC(31); + } +#endif +} +/* +#define GTE_NCCS(vn) { \ + RR0 = ((double)gteL11 * gteVX##vn + (double)gteL12 * gteVY##vn + (double)gteL13 * gteVZ##vn)/4096.0; \ + GG0 = ((double)gteL21 * gteVX##vn + (double)gteL22 * gteVY##vn + (double)gteL23 * gteVZ##vn)/4096.0; \ + BB0 = ((double)gteL31 * gteVX##vn + (double)gteL32 * gteVY##vn + (double)gteL33 * gteVZ##vn)/4096.0; \ + t1 = LimitAU(RR0,24); \ + t2 = LimitAU(GG0,23); \ + t3 = LimitAU(BB0,22); \ + \ + RR0 = (double)gteRBK + ((double)gteLR1 * t1 + (double)gteLR2 * t2 + (double)gteLR3 * t3)/4096.0; \ + GG0 = (double)gteGBK + ((double)gteLG1 * t1 + (double)gteLG2 * t2 + (double)gteLG3 * t3)/4096.0; \ + BB0 = (double)gteBBK + ((double)gteLB1 * t1 + (double)gteLB2 * t2 + (double)gteLB3 * t3)/4096.0; \ + t1 = LimitAU(RR0,24); \ + t2 = LimitAU(GG0,23); \ + t3 = LimitAU(BB0,22); \ + \ + RR0 = ((double)gteR * t1)/256.0; \ + GG0 = ((double)gteG * t2)/256.0; \ + BB0 = ((double)gteB * t3)/256.0; \ + \ + gteIR1 = (long)LimitAU(RR0,24); \ + gteIR2 = (long)LimitAU(GG0,23); \ + gteIR3 = (long)LimitAU(BB0,22); \ + \ + gteCODE0 = gteCODE1; gteCODE1 = gteCODE2; gteCODE2 = gteCODE; \ + gteR0 = gteR1; gteR1 = gteR2; gteR2 = (unsigned char)LimitB(RR0/16.0,21); \ + gteG0 = gteG1; gteG1 = gteG2; gteG2 = (unsigned char)LimitB(GG0/16.0,20); \ + gteB0 = gteB1; gteB1 = gteB2; gteB2 = (unsigned char)LimitB(BB0/16.0,19); \ + \ + gteMAC1 = (long)RR0; \ + gteMAC2 = (long)GG0; \ + gteMAC3 = (long)BB0; \ +} +*/ +/* +__forceinline double ncLIM1(double x) +{ + if(x > 8796093022207.0) + { + return 8796093022207.0; + } +} +*/ + + + +/* NC: OLD +#define GTE_NCCS(vn)\ +gte_LL1 = limA1U((gteL11*gteVX##vn + gteL12*gteVY##vn + gteL13*gteVZ##vn)/16777216.0f);\ +gte_LL2 = limA2U((gteL21*gteVX##vn + gteL22*gteVY##vn + gteL23*gteVZ##vn)/16777216.0f);\ +gte_LL3 = limA3U((gteL31*gteVX##vn + gteL32*gteVY##vn + gteL33*gteVZ##vn)/16777216.0f);\ +gte_RRLT= limA1U(gteRBK/4096.0f + (gteLR1/4096.0f*gte_LL1 + gteLR2/4096.0f*gte_LL2 + gteLR3/4096.0f*gte_LL3));\ +gte_GGLT= limA2U(gteGBK/4096.0f + (gteLG1/4096.0f*gte_LL1 + gteLG2/4096.0f*gte_LL2 + gteLG3/4096.0f*gte_LL3));\ +gte_BBLT= limA3U(gteBBK/4096.0f + (gteLB1/4096.0f*gte_LL1 + gteLB2/4096.0f*gte_LL2 + gteLB3/4096.0f*gte_LL3));\ +gte_RR0 = gteR*gte_RRLT;\ +gte_GG0 = gteG*gte_GGLT;\ +gte_BB0 = gteB*gte_BBLT;\ +gteIR1 = (long)limA1U(gte_RR0);\ +gteIR2 = (long)limA2U(gte_GG0);\ +gteIR3 = (long)limA3U(gte_BB0);\ +gteCODE0 = gteCODE1; gteCODE1 = gteCODE2; gteCODE2 = gteCODE;\ +gteR0 = gteR1; gteR1 = gteR2; gteR2 = (unsigned char)limB1(gte_RR0);\ +gteG0 = gteG1; gteG1 = gteG2; gteG2 = (unsigned char)limB2(gte_GG0);\ +gteB0 = gteB1; gteB1 = gteB2; gteB2 = (unsigned char)limB3(gte_BB0);\ +gteMAC1 = (long)gte_RR0;\ +gteMAC2 = (long)gte_GG0;\ +gteMAC3 = (long)gte_BB0;\ +*/ +/* +#define GTE_NCCS(vn)\ +gte_LL1 = limA1U((gteL11*gteVX##vn + gteL12*gteVY##vn + gteL13*gteVZ##vn)/16777216.0f);\ +gte_LL2 = limA2U((gteL21*gteVX##vn + gteL22*gteVY##vn + gteL23*gteVZ##vn)/16777216.0f);\ +gte_LL3 = limA3U((gteL31*gteVX##vn + gteL32*gteVY##vn + gteL33*gteVZ##vn)/16777216.0f);\ +gte_RRLT= limA1U(gteRBK/4096.0f + (gteLR1/4096.0f*gte_LL1 + gteLR2/4096.0f*gte_LL2 + gteLR3/4096.0f*gte_LL3));\ +gte_GGLT= limA2U(gteGBK/4096.0f + (gteLG1/4096.0f*gte_LL1 + gteLG2/4096.0f*gte_LL2 + gteLG3/4096.0f*gte_LL3));\ +gte_BBLT= limA3U(gteBBK/4096.0f + (gteLB1/4096.0f*gte_LL1 + gteLB2/4096.0f*gte_LL2 + gteLB3/4096.0f*gte_LL3));\ +gteMAC1 = (long)(gteR*gte_RRLT*16);\ +gteMAC2 = (long)(gteG*gte_GGLT*16);\ +gteMAC3 = (long)(gteB*gte_BBLT*16);\ +gteIR1 = (long)limA1U(gteMAC1);\ +gteIR2 = (long)limA2U(gteMAC2);\ +gteIR3 = (long)limA3U(gteMAC3);\ +gte_RR0 = gteMAC1>>4;\ +gte_GG0 = gteMAC2>>4;\ +gte_BB0 = gteMAC3>>4;\ +gteCODE0 = gteCODE1; gteCODE1 = gteCODE2; gteCODE2 = gteCODE;\ +gteR0 = gteR1; gteR1 = gteR2; gteR2 = (unsigned char)limB1(gte_RR0);\ +gteG0 = gteG1; gteG1 = gteG2; gteG2 = (unsigned char)limB2(gte_GG0);\ +gteB0 = gteB1; gteB1 = gteB2; gteB2 = (unsigned char)limB3(gte_BB0);*/ + + +/* + gte_LL1 = limA1U((gteL11*gteVX##vn + gteL12*gteVY##vn + gteL13*gteVZ##vn)/16777216.0f); \ + gte_LL2 = limA2U((gteL21*gteVX##vn + gteL22*gteVY##vn + gteL23*gteVZ##vn)/16777216.0f); \ + gte_LL3 = limA3U((gteL31*gteVX##vn + gteL32*gteVY##vn + gteL33*gteVZ##vn)/16777216.0f); \ + gte_RRLT= limA1U(gteRBK/4096.0f + (gteLR1/4096.0f*gte_LL1 + gteLR2/4096.0f*gte_LL2 + gteLR3/4096.0f*gte_LL3)); \ + gte_GGLT= limA2U(gteGBK/4096.0f + (gteLG1/4096.0f*gte_LL1 + gteLG2/4096.0f*gte_LL2 + gteLG3/4096.0f*gte_LL3)); \ + gte_BBLT= limA3U(gteBBK/4096.0f + (gteLB1/4096.0f*gte_LL1 + gteLB2/4096.0f*gte_LL2 + gteLB3/4096.0f*gte_LL3)); \ + \ + gteMAC1 = (long)(gteR*gte_RRLT*16); \ + gteMAC2 = (long)(gteG*gte_GGLT*16); \ + gteMAC3 = (long)(gteB*gte_BBLT*16); \ +*/ +#define GTE_NCCS(vn) \ + gte_LL1 = F12limA1U((gteL11*gteVX##vn + gteL12*gteVY##vn + gteL13*gteVZ##vn) >> 12); \ + gte_LL2 = F12limA2U((gteL21*gteVX##vn + gteL22*gteVY##vn + gteL23*gteVZ##vn) >> 12); \ + gte_LL3 = F12limA3U((gteL31*gteVX##vn + gteL32*gteVY##vn + gteL33*gteVZ##vn) >> 12); \ + gte_RRLT= F12limA1U(gteRBK + ((gteLR1*gte_LL1 + gteLR2*gte_LL2 + gteLR3*gte_LL3) >> 12)); \ + gte_GGLT= F12limA2U(gteGBK + ((gteLG1*gte_LL1 + gteLG2*gte_LL2 + gteLG3*gte_LL3) >> 12)); \ + gte_BBLT= F12limA3U(gteBBK + ((gteLB1*gte_LL1 + gteLB2*gte_LL2 + gteLB3*gte_LL3) >> 12)); \ + \ + gteMAC1 = (long)(((s64)((u32)gteR<<12)*gte_RRLT) >> 20);\ + gteMAC2 = (long)(((s64)((u32)gteG<<12)*gte_GGLT) >> 20);\ + gteMAC3 = (long)(((s64)((u32)gteB<<12)*gte_BBLT) >> 20); + + +void gteNCCS() { +// double RR0,GG0,BB0; +// double t1, t2, t3; +// double gte_LL1, gte_LL2, gte_LL3; +// double gte_RRLT, gte_GGLT, gte_BBLT; + s32 gte_LL1, gte_LL2, gte_LL3; + s32 gte_RRLT, gte_GGLT, gte_BBLT; + +#ifdef GTE_DUMP + static int sample = 0; sample++; +#endif + +#ifdef GTE_LOG + GTE_LOG("GTE_NCCS\n"); +#endif + +/* + gteFLAG = 0; + + GTE_NCCS(0); + + if (gteFLAG & 0x7f87e000) gteFLAG|=0x80000000;*/ + +#ifdef GTE_DUMP + if(sample < 100) + { + G_OP("NCCS", 17); + G_SD(0); + G_SD(1); + G_SD(6); + G_SC(8); + G_SC(9); + G_SC(10); + G_SC(11); + G_SC(12); + G_SC(13); + G_SC(14); + G_SC(15); + G_SC(16); + G_SC(17); + G_SC(18); + G_SC(19); + G_SC(20); + } +#endif + + gteFLAG = 0; + + GTE_NCCS(0); + + gteRGB0 = gteRGB1; + gteRGB1 = gteRGB2; + gteR2 = FlimB1(gteMAC1>>4); + gteG2 = FlimB2(gteMAC2>>4); + gteB2 = FlimB3(gteMAC3>>4); gteCODE2 = gteCODE; + + MAC2IR1(); + + SUM_FLAG + +#ifdef GTE_DUMP + if(sample < 100) + { + G_GD(9); + G_GD(10); + G_GD(11); + + //G_GD(20); + //G_GD(21); + G_GD(22); + + //G_GD(24); Doc must be wrong. PSX does not touch it. + G_GD(25); + G_GD(26); + G_GD(27); + + G_GC(31); + } +#endif +} + +void gteNCCT() { +// double RR0,GG0,BB0; +// double t1, t2, t3; +// double gte_LL1, gte_LL2, gte_LL3; +// double gte_RRLT, gte_GGLT, gte_BBLT; + s32 gte_LL1, gte_LL2, gte_LL3; + s32 gte_RRLT, gte_GGLT, gte_BBLT; + +#ifdef GTE_DUMP + static int sample = 0; sample++; +#endif + +#ifdef GTE_LOG + GTE_LOG("GTE_NCCT\n"); +#endif + + + /*gteFLAG = 0; + + GTE_NCCS(0); + GTE_NCCS(1); + GTE_NCCS(2); + + if (gteFLAG & 0x7f87e000) gteFLAG|=0x80000000;*/ + +#ifdef GTE_DUMP + if(sample < 100) + { + G_OP("NCCT", 39); + G_SD(0); + G_SD(1); + G_SD(2); + G_SD(3); + G_SD(4); + G_SD(5); + G_SD(6); + + G_SC(8); + G_SC(9); + G_SC(10); + G_SC(11); + G_SC(12); + G_SC(13); + G_SC(14); + G_SC(15); + G_SC(16); + G_SC(17); + G_SC(18); + G_SC(19); + G_SC(20); + } +#endif + + gteFLAG = 0; + + GTE_NCCS(0); + + gteR0 = FlimB1(gteMAC1>>4); + gteG0 = FlimB2(gteMAC2>>4); + gteB0 = FlimB3(gteMAC3>>4); gteCODE0 = gteCODE; + + GTE_NCCS(1); + + gteR1 = FlimB1(gteMAC1>>4); + gteG1 = FlimB2(gteMAC2>>4); + gteB1 = FlimB3(gteMAC3>>4); gteCODE1 = gteCODE; + + GTE_NCCS(2); + + gteR2 = FlimB1(gteMAC1>>4); + gteG2 = FlimB2(gteMAC2>>4); + gteB2 = FlimB3(gteMAC3>>4); gteCODE2 = gteCODE; + + MAC2IR1(); + + SUM_FLAG + +#ifdef GTE_DUMP + if(sample < 100) + { + G_GD(9); + G_GD(10); + G_GD(11); + + G_GD(20); + G_GD(21); + G_GD(22); + + //G_GD(24); Doc must be wrong. PSX does not touch it. + G_GD(25); + G_GD(26); + G_GD(27); + + G_GC(31); + } +#endif +} +/* +#define GTE_NCDS(vn) \ +gte_LL1 = limA1U((gteL11*gteVX##vn + gteL12*gteVY##vn + gteL13*gteVZ##vn)/16777216.0f);\ +gte_LL2 = limA2U((gteL21*gteVX##vn + gteL22*gteVY##vn + gteL23*gteVZ##vn)/16777216.0f);\ +gte_LL3 = limA3U((gteL31*gteVX##vn + gteL32*gteVY##vn + gteL33*gteVZ##vn)/16777216.0f);\ +gte_RRLT= limA1U(gteRBK/4096.0f + (gteLR1/4096.0f*gte_LL1 + gteLR2/4096.0f*gte_LL2 + gteLR3/4096.0f*gte_LL3));\ +gte_GGLT= limA2U(gteGBK/4096.0f + (gteLG1/4096.0f*gte_LL1 + gteLG2/4096.0f*gte_LL2 + gteLG3/4096.0f*gte_LL3));\ +gte_BBLT= limA3U(gteBBK/4096.0f + (gteLB1/4096.0f*gte_LL1 + gteLB2/4096.0f*gte_LL2 + gteLB3/4096.0f*gte_LL3));\ +gte_RR0 = (gteR*gte_RRLT) + (gteIR0/4096.0f * limA1S(gteRFC/16.0f - (gteR*gte_RRLT)));\ +gte_GG0 = (gteG*gte_GGLT) + (gteIR0/4096.0f * limA2S(gteGFC/16.0f - (gteG*gte_GGLT)));\ +gte_BB0 = (gteB*gte_BBLT) + (gteIR0/4096.0f * limA3S(gteBFC/16.0f - (gteB*gte_BBLT)));\ +gteMAC1= (long)(gte_RR0 * 16.0f); gteIR1 = (long)limA1U(gte_RR0*16.0f);\ +gteMAC2= (long)(gte_GG0 * 16.0f); gteIR2 = (long)limA2U(gte_GG0*16.0f);\ +gteMAC3= (long)(gte_BB0 * 16.0f); gteIR3 = (long)limA3U(gte_BB0*16.0f);\ +gteRGB0 = gteRGB1; \ +gteRGB1 = gteRGB2; \ +gteR2 = limB1(gte_RR0); \ +gteG2 = limB2(gte_GG0); \ +gteB2 = limB3(gte_BB0); gteCODE2 = gteCODE; +*/ +/* +#define GTE_NCDS(vn) \ +gte_LL1 = limA1U((gteL11*gteVX##vn + gteL12*gteVY##vn + gteL13*gteVZ##vn)/16777216.0f);\ +gte_LL2 = limA2U((gteL21*gteVX##vn + gteL22*gteVY##vn + gteL23*gteVZ##vn)/16777216.0f);\ +gte_LL3 = limA3U((gteL31*gteVX##vn + gteL32*gteVY##vn + gteL33*gteVZ##vn)/16777216.0f);\ +gte_RRLT= limA1U(gteRBK/4096.0f + (gteLR1/4096.0f*gte_LL1 + gteLR2/4096.0f*gte_LL2 + gteLR3/4096.0f*gte_LL3));\ +gte_GGLT= limA2U(gteGBK/4096.0f + (gteLG1/4096.0f*gte_LL1 + gteLG2/4096.0f*gte_LL2 + gteLG3/4096.0f*gte_LL3));\ +gte_BBLT= limA3U(gteBBK/4096.0f + (gteLB1/4096.0f*gte_LL1 + gteLB2/4096.0f*gte_LL2 + gteLB3/4096.0f*gte_LL3));\ + \ + gte_RR0 = (gteR*gte_RRLT) + (gteIR0/4096.0f * limA1S(gteRFC/16.0f - (gteR*gte_RRLT)));\ + gte_GG0 = (gteG*gte_GGLT) + (gteIR0/4096.0f * limA2S(gteGFC/16.0f - (gteG*gte_GGLT)));\ + gte_BB0 = (gteB*gte_BBLT) + (gteIR0/4096.0f * limA3S(gteBFC/16.0f - (gteB*gte_BBLT)));\ + gteMAC1 = (long)(gte_RR0 << 4); \ + gteMAC2 = (long)(gte_GG0 << 4); \ + gteMAC3 = (long)(gte_BB0 << 4); +*/ +#define GTE_NCDS(vn) \ + gte_LL1 = F12limA1U((gteL11*gteVX##vn + gteL12*gteVY##vn + gteL13*gteVZ##vn) >> 12); \ + gte_LL2 = F12limA2U((gteL21*gteVX##vn + gteL22*gteVY##vn + gteL23*gteVZ##vn) >> 12); \ + gte_LL3 = F12limA3U((gteL31*gteVX##vn + gteL32*gteVY##vn + gteL33*gteVZ##vn) >> 12); \ + gte_RRLT= F12limA1U(gteRBK + ((gteLR1*gte_LL1 + gteLR2*gte_LL2 + gteLR3*gte_LL3) >> 12)); \ + gte_GGLT= F12limA2U(gteGBK + ((gteLG1*gte_LL1 + gteLG2*gte_LL2 + gteLG3*gte_LL3) >> 12)); \ + gte_BBLT= F12limA3U(gteBBK + ((gteLB1*gte_LL1 + gteLB2*gte_LL2 + gteLB3*gte_LL3) >> 12)); \ + \ + gte_RR0 = (long)(((s64)((u32)gteR<<12)*gte_RRLT) >> 12);\ + gte_GG0 = (long)(((s64)((u32)gteG<<12)*gte_GGLT) >> 12);\ + gte_BB0 = (long)(((s64)((u32)gteB<<12)*gte_BBLT) >> 12);\ + gteMAC1 = (long)((gte_RR0 + (((s64)gteIR0 * F12limA1S((s64)(gteRFC << 8) - gte_RR0)) >> 12)) >> 8);\ + gteMAC2 = (long)((gte_GG0 + (((s64)gteIR0 * F12limA2S((s64)(gteGFC << 8) - gte_GG0)) >> 12)) >> 8);\ + gteMAC3 = (long)((gte_BB0 + (((s64)gteIR0 * F12limA3S((s64)(gteBFC << 8) - gte_BB0)) >> 12)) >> 8); + +void gteNCDS() { +/* double tRLT,tRRLT; + double tGLT,tGGLT; + double tBLT,tBBLT; + double tRR0,tL1,tLL1; + double tGG0,tL2,tLL2; + double tBB0,tL3,tLL3; + unsigned long C,R,G,B; */ +// double gte_LL1, gte_LL2, gte_LL3; +// double gte_RRLT, gte_GGLT, gte_BBLT; + s32 gte_LL1, gte_LL2, gte_LL3; + s32 gte_RRLT, gte_GGLT, gte_BBLT; + s32 gte_RR0, gte_GG0, gte_BB0; + +#ifdef GTE_DUMP + static int sample = 0; sample++; +#endif + +#ifdef GTE_LOG + GTE_LOG("GTE_NCDS\n"); +#endif + +/* gteFLAG = 0; + + R = ((gteRGB)&0xff); + G = ((gteRGB>> 8)&0xff); + B = ((gteRGB>>16)&0xff); + C = ((gteRGB>>24)&0xff); + + tLL1 = (gteL11/4096.0 * gteVX0/4096.0) + (gteL12/4096.0 * gteVY0/4096.0) + (gteL13/4096.0 * gteVZ0/4096.0); + tLL2 = (gteL21/4096.0 * gteVX0/4096.0) + (gteL22/4096.0 * gteVY0/4096.0) + (gteL23/4096.0 * gteVZ0/4096.0); + tLL3 = (gteL31/4096.0 * gteVX0/4096.0) + (gteL32/4096.0 * gteVY0/4096.0) + (gteL33/4096.0 * gteVZ0/4096.0); + + tL1 = LimitAU(tLL1,24); + tL2 = LimitAU(tLL2,23); + tL3 = LimitAU(tLL3,22); + + tRRLT = gteRBK/4096.0 + (gteLR1/4096.0 * tL1) + (gteLR2/4096.0 * tL2) + (gteLR3/4096.0 * tL3); + tGGLT = gteGBK/4096.0 + (gteLG1/4096.0 * tL1) + (gteLG2/4096.0 * tL2) + (gteLG3/4096.0 * tL3); + tBBLT = gteBBK/4096.0 + (gteLB1/4096.0 * tL1) + (gteLB2/4096.0 * tL2) + (gteLB3/4096.0 * tL3); + + tRLT = LimitAU(tRRLT,24); + tGLT = LimitAU(tGGLT,23); + tBLT = LimitAU(tBBLT,22); + + tRR0 = (R * tRLT) + (gteIR0/4096.0 * LimitAS(gteRFC/16.0 - (R * tRLT),24)); + tGG0 = (G * tGLT) + (gteIR0/4096.0 * LimitAS(gteGFC/16.0 - (G * tGLT),23)); + tBB0 = (B * tBLT) + (gteIR0/4096.0 * LimitAS(gteBFC/16.0 - (B * tBLT),22)); + + gteMAC1 = (long)(tRR0 * 16.0); gteIR1 = (long)LimitAU((tRR0*16.0),24); + gteMAC2 = (long)(tGG0 * 16.0); gteIR2 = (long)LimitAU((tGG0*16.0),23); + gteMAC3 = (long)(tBB0 * 16.0); gteIR3 = (long)LimitAU((tBB0*16.0),22); + + R = (unsigned long)LimitB(tRR0,21); if (R>255) R=255; else if (R<0) R=0; + G = (unsigned long)LimitB(tGG0,20); if (G>255) G=255; else if (G<0) G=0; + B = (unsigned long)LimitB(tBB0,19); if (B>255) B=255; else if (B<0) B=0; + + gteRGB0 = gteRGB1; + gteRGB1 = gteRGB2; + gteRGB2 = R|(G<<8)|(B<<16)|(C<<24); + + if (gteFLAG & 0x7f87e000) gteFLAG|=0x80000000;*/ + +#ifdef GTE_DUMP + if(sample < 100) + { + G_OP("NCDS", 19); + G_SD(0); + G_SD(1); + G_SD(6); + G_SD(8); + + G_SC(8); + G_SC(9); + G_SC(10); + G_SC(11); + G_SC(12); + G_SC(13); + G_SC(14); + G_SC(15); + G_SC(16); + G_SC(17); + G_SC(18); + G_SC(19); + G_SC(20); + G_SC(21); + G_SC(22); + G_SC(23); + } +#endif + + gteFLAG = 0; + GTE_NCDS(0); + + gteRGB0 = gteRGB1; + gteRGB1 = gteRGB2; + gteR2 = FlimB1(gteMAC1 >> 4); + gteG2 = FlimB2(gteMAC2 >> 4); + gteB2 = FlimB3(gteMAC3 >> 4); gteCODE2 = gteCODE; + + MAC2IR1(); + + SUM_FLAG; + +#ifdef GTE_DUMP + if(sample < 100) + { + G_GD(9); + G_GD(10); + G_GD(11); + + //G_GD(20); + //G_GD(21); + G_GD(22); + + G_GD(25); + G_GD(26); + G_GD(27); + + G_GC(31); + } +#endif +} + +void gteNCDT() { + /*double tRLT,tRRLT; + double tGLT,tGGLT; + double tBLT,tBBLT; + double tRR0,tL1,tLL1; + double tGG0,tL2,tLL2; + double tBB0,tL3,tLL3; + unsigned long C,R,G,B;*/ +// double gte_LL1, gte_LL2, gte_LL3; +// double gte_RRLT, gte_GGLT, gte_BBLT; + s32 gte_LL1, gte_LL2, gte_LL3; + s32 gte_RRLT, gte_GGLT, gte_BBLT; + s32 gte_RR0, gte_GG0, gte_BB0; + +#ifdef GTE_DUMP + static int sample = 0; sample++; +#endif + +#ifdef GTE_LOG + GTE_LOG("GTE_NCDT\n"); +#endif + +/* gteFLAG = 0; + + R = ((gteRGB)&0xff); + G = ((gteRGB>> 8)&0xff); + B = ((gteRGB>>16)&0xff); + C = ((gteRGB>>24)&0xff); + + tLL1 = (gteL11/4096.0 * gteVX0/4096.0) + (gteL12/4096.0 * gteVY0/4096.0) + (gteL13/4096.0 * gteVZ0/4096.0); + tLL2 = (gteL21/4096.0 * gteVX0/4096.0) + (gteL22/4096.0 * gteVY0/4096.0) + (gteL23/4096.0 * gteVZ0/4096.0); + tLL3 = (gteL31/4096.0 * gteVX0/4096.0) + (gteL32/4096.0 * gteVY0/4096.0) + (gteL33/4096.0 * gteVZ0/4096.0); + + tL1 = LimitAU(tLL1,24); + tL2 = LimitAU(tLL2,23); + tL3 = LimitAU(tLL3,22); + + tRRLT = gteRBK/4096.0 + (gteLR1/4096.0 * tL1) + (gteLR2/4096.0 * tL2) + (gteLR3/4096.0 * tL3); + tGGLT = gteGBK/4096.0 + (gteLG1/4096.0 * tL1) + (gteLG2/4096.0 * tL2) + (gteLG3/4096.0 * tL3); + tBBLT = gteBBK/4096.0 + (gteLB1/4096.0 * tL1) + (gteLB2/4096.0 * tL2) + (gteLB3/4096.0 * tL3); + + tRLT = LimitAU(tRRLT,24); + tGLT = LimitAU(tGGLT,23); + tBLT = LimitAU(tBBLT,22); + + tRR0 = (R * tRLT) + (gteIR0/4096.0 * LimitAS(gteRFC/16.0 - (R * tRLT),24)); + tGG0 = (G * tGLT) + (gteIR0/4096.0 * LimitAS(gteGFC/16.0 - (G * tGLT),23)); + tBB0 = (B * tBLT) + (gteIR0/4096.0 * LimitAS(gteBFC/16.0 - (B * tBLT),22)); + + gteMAC1 = (long)(tRR0 * 16.0); gteIR1 = (long)LimitAU((tRR0*16.0),24); + gteMAC2 = (long)(tGG0 * 16.0); gteIR2 = (long)LimitAU((tGG0*16.0),23); + gteMAC3 = (long)(tBB0 * 16.0); gteIR3 = (long)LimitAU((tBB0*16.0),22); + + R = (unsigned long)LimitB(tRR0,21); if (R>255) R=255; else if (R<0) R=0; + G = (unsigned long)LimitB(tGG0,20); if (G>255) G=255; else if (G<0) G=0; + B = (unsigned long)LimitB(tBB0,19); if (B>255) B=255; else if (B<0) B=0; + + gteRGB0 = gteRGB1; + gteRGB1 = gteRGB2; + gteRGB2 = R|(G<<8)|(B<<16)|(C<<24); + + R = ((gteRGB)&0xff); + G = ((gteRGB>> 8)&0xff); + B = ((gteRGB>>16)&0xff); + C = ((gteRGB>>24)&0xff); + + tLL1 = (gteL11/4096.0 * gteVX1/4096.0) + (gteL12/4096.0 * gteVY1/4096.0) + (gteL13/4096.0 * gteVZ1/4096.0); + tLL2 = (gteL21/4096.0 * gteVX1/4096.0) + (gteL22/4096.0 * gteVY1/4096.0) + (gteL23/4096.0 * gteVZ1/4096.0); + tLL3 = (gteL31/4096.0 * gteVX1/4096.0) + (gteL32/4096.0 * gteVY1/4096.0) + (gteL33/4096.0 * gteVZ1/4096.0); + + tL1 = LimitAU(tLL1,24); + tL2 = LimitAU(tLL2,23); + tL3 = LimitAU(tLL3,22); + + tRRLT = gteRBK/4096.0 + (gteLR1/4096.0 * tL1) + (gteLR2/4096.0 * tL2) + (gteLR3/4096.0 * tL3); + tGGLT = gteGBK/4096.0 + (gteLG1/4096.0 * tL1) + (gteLG2/4096.0 * tL2) + (gteLG3/4096.0 * tL3); + tBBLT = gteBBK/4096.0 + (gteLB1/4096.0 * tL1) + (gteLB2/4096.0 * tL2) + (gteLB3/4096.0 * tL3); + + tRLT = LimitAU(tRRLT,24); + tGLT = LimitAU(tGGLT,23); + tBLT = LimitAU(tBBLT,22); + + tRR0 = (R * tRLT) + (gteIR0/4096.0 * LimitAS(gteRFC/16.0 - (R * tRLT),24)); + tGG0 = (G * tGLT) + (gteIR0/4096.0 * LimitAS(gteGFC/16.0 - (G * tGLT),23)); + tBB0 = (B * tBLT) + (gteIR0/4096.0 * LimitAS(gteBFC/16.0 - (B * tBLT),22)); + + gteMAC1 = (long)(tRR0 * 16.0); gteIR1 = (long)LimitAU((tRR0*16.0),24); + gteMAC2 = (long)(tGG0 * 16.0); gteIR2 = (long)LimitAU((tGG0*16.0),23); + gteMAC3 = (long)(tBB0 * 16.0); gteIR3 = (long)LimitAU((tBB0*16.0),22); + + R = (unsigned long)LimitB(tRR0,21); if (R>255) R=255; else if (R<0) R=0; + G = (unsigned long)LimitB(tGG0,20); if (G>255) G=255; else if (G<0) G=0; + B = (unsigned long)LimitB(tBB0,19); if (B>255) B=255; else if (B<0) B=0; + + gteRGB0 = gteRGB1; + gteRGB1 = gteRGB2; + gteRGB2 = R|(G<<8)|(B<<16)|(C<<24); + + R = ((gteRGB)&0xff); + G = ((gteRGB>> 8)&0xff); + B = ((gteRGB>>16)&0xff); + C = ((gteRGB>>24)&0xff); + + tLL1 = (gteL11/4096.0 * gteVX2/4096.0) + (gteL12/4096.0 * gteVY2/4096.0) + (gteL13/4096.0 * gteVZ2/4096.0); + tLL2 = (gteL21/4096.0 * gteVX2/4096.0) + (gteL22/4096.0 * gteVY2/4096.0) + (gteL23/4096.0 * gteVZ2/4096.0); + tLL3 = (gteL31/4096.0 * gteVX2/4096.0) + (gteL32/4096.0 * gteVY2/4096.0) + (gteL33/4096.0 * gteVZ2/4096.0); + + tL1 = LimitAU(tLL1,24); + tL2 = LimitAU(tLL2,23); + tL3 = LimitAU(tLL3,22); + + tRRLT = gteRBK/4096.0 + (gteLR1/4096.0 * tL1) + (gteLR2/4096.0 * tL2) + (gteLR3/4096.0 * tL3); + tGGLT = gteGBK/4096.0 + (gteLG1/4096.0 * tL1) + (gteLG2/4096.0 * tL2) + (gteLG3/4096.0 * tL3); + tBBLT = gteBBK/4096.0 + (gteLB1/4096.0 * tL1) + (gteLB2/4096.0 * tL2) + (gteLB3/4096.0 * tL3); + + tRLT = LimitAU(tRRLT,24); + tGLT = LimitAU(tGGLT,23); + tBLT = LimitAU(tBBLT,22); + + tRR0 = (R * tRLT) + (gteIR0/4096.0 * LimitAS(gteRFC/16.0 - (R * tRLT),24)); + tGG0 = (G * tGLT) + (gteIR0/4096.0 * LimitAS(gteGFC/16.0 - (G * tGLT),23)); + tBB0 = (B * tBLT) + (gteIR0/4096.0 * LimitAS(gteBFC/16.0 - (B * tBLT),22)); + + gteMAC1 = (long)(tRR0 * 16.0); gteIR1 = (long)LimitAU((tRR0*16.0),24); + gteMAC2 = (long)(tGG0 * 16.0); gteIR2 = (long)LimitAU((tGG0*16.0),23); + gteMAC3 = (long)(tBB0 * 16.0); gteIR3 = (long)LimitAU((tBB0*16.0),22); + + R = (unsigned long)LimitB(tRR0,21); if (R>255) R=255; else if (R<0) R=0; + G = (unsigned long)LimitB(tGG0,20); if (G>255) G=255; else if (G<0) G=0; + B = (unsigned long)LimitB(tBB0,19); if (B>255) B=255; else if (B<0) B=0; + + gteRGB0 = gteRGB1; + gteRGB1 = gteRGB2; + gteRGB2 = R|(G<<8)|(B<<16)|(C<<24); + + if (gteFLAG & 0x7f87e000) gteFLAG|=0x80000000;*/ + +#ifdef GTE_DUMP + if(sample < 100) + { + G_OP("NCDT", 44); + G_SD(0); + G_SD(1); + G_SD(2); + G_SD(3); + G_SD(4); + G_SD(5); + G_SD(6); + G_SD(8); + + G_SC(8); + G_SC(9); + G_SC(10); + G_SC(11); + G_SC(12); + G_SC(13); + G_SC(14); + G_SC(15); + G_SC(16); + G_SC(17); + G_SC(18); + G_SC(19); + G_SC(20); + G_SC(21); + G_SC(22); + G_SC(23); + } +#endif + + gteFLAG = 0; + GTE_NCDS(0); + + gteR0 = FlimB1(gteMAC1 >> 4); + gteG0 = FlimB2(gteMAC2 >> 4); + gteB0 = FlimB3(gteMAC3 >> 4); gteCODE0 = gteCODE; + + GTE_NCDS(1); + + gteR1 = FlimB1(gteMAC1 >> 4); + gteG1 = FlimB2(gteMAC2 >> 4); + gteB1 = FlimB3(gteMAC3 >> 4); gteCODE1 = gteCODE; + + GTE_NCDS(2); + + gteR2 = FlimB1(gteMAC1 >> 4); + gteG2 = FlimB2(gteMAC2 >> 4); + gteB2 = FlimB3(gteMAC3 >> 4); gteCODE2 = gteCODE; + + MAC2IR1(); + + SUM_FLAG; + +#ifdef GTE_DUMP + if(sample < 100) + { + G_GD(9); + G_GD(10); + G_GD(11); + + G_GD(20); + G_GD(21); + G_GD(22); + + G_GD(25); + G_GD(26); + G_GD(27); + + G_GC(31); + } +#endif +} + +#define gteD1 (*(short *)>eR11) +#define gteD2 (*(short *)>eR22) +#define gteD3 (*(short *)>eR33) + +void gteOP() { +// double SSX0=0,SSY0=0,SSZ0=0; +#ifdef GTE_DUMP + static int sample = 0; sample++; +#endif + +#ifdef GTE_LOG + GTE_LOG("GTE_OP %lx\n", psxRegs.code & 0x1ffffff); +#endif + +#ifdef GTE_DUMP + if(sample < 100) + { + G_OP("OP", 6); + G_SD(9); + G_SD(10); + G_SD(11); + + G_SC(0); + G_SC(2); + G_SC(4); + } +#endif +/* gteFLAG=0; + + switch (psxRegs.code & 0x1ffffff) { + case 0x178000C://op12 + SSX0 = EDETEC1((gteR22*(short)gteIR3 - gteR33*(short)gteIR2)/(double)4096); + SSY0 = EDETEC2((gteR33*(short)gteIR1 - gteR11*(short)gteIR3)/(double)4096); + SSZ0 = EDETEC3((gteR11*(short)gteIR2 - gteR22*(short)gteIR1)/(double)4096); + break; + case 0x170000C: + SSX0 = EDETEC1((gteR22*(short)gteIR3 - gteR33*(short)gteIR2)); + SSY0 = EDETEC2((gteR33*(short)gteIR1 - gteR11*(short)gteIR3)); + SSZ0 = EDETEC3((gteR11*(short)gteIR2 - gteR22*(short)gteIR1)); + break; + } + + gteMAC1 = (long)float2int(SSX0); + gteMAC2 = (long)float2int(SSY0); + gteMAC3 = (long)float2int(SSZ0); + + MAC2IR(); + + if (gteIR1<0) gteIR1=0; + if (gteIR2<0) gteIR2=0; + if (gteIR3<0) gteIR3=0; + + if (gteFLAG & 0x7f87e000) gteFLAG|=0x80000000;*/ + gteFLAG = 0; + +/* if (psxRegs.code & 0x80000) { + + gteMAC1 = NC_OVERFLOW1((gteD2 * gteIR3 - gteD3 * gteIR2) / 4096.0f); + gteMAC2 = NC_OVERFLOW2((gteD3 * gteIR1 - gteD1 * gteIR3) / 4096.0f); + gteMAC3 = NC_OVERFLOW3((gteD1 * gteIR2 - gteD2 * gteIR1) / 4096.0f); + } else { + + gteMAC1 = NC_OVERFLOW1(gteD2 * gteIR3 - gteD3 * gteIR2); + gteMAC2 = NC_OVERFLOW2(gteD3 * gteIR1 - gteD1 * gteIR3); + gteMAC3 = NC_OVERFLOW3(gteD1 * gteIR2 - gteD2 * gteIR1); + }*/ + if (psxRegs.code & 0x80000) { + gteMAC1 = FNC_OVERFLOW1((gteD2 * gteIR3 - gteD3 * gteIR2) >> 12); + gteMAC2 = FNC_OVERFLOW2((gteD3 * gteIR1 - gteD1 * gteIR3) >> 12); + gteMAC3 = FNC_OVERFLOW3((gteD1 * gteIR2 - gteD2 * gteIR1) >> 12); + } else { + gteMAC1 = FNC_OVERFLOW1(gteD2 * gteIR3 - gteD3 * gteIR2); + gteMAC2 = FNC_OVERFLOW2(gteD3 * gteIR1 - gteD1 * gteIR3); + gteMAC3 = FNC_OVERFLOW3(gteD1 * gteIR2 - gteD2 * gteIR1); + } + + /* NC: old + MAC2IR1(); + */ + MAC2IR(); + + SUM_FLAG + +#ifdef GTE_DUMP + if(sample < 100) + { + G_GD(9); + G_GD(10); + G_GD(11); + + G_GD(25); + G_GD(26); + G_GD(27); + + G_GC(31); + } +#endif +} + +void gteDCPL() { +// unsigned long C,R,G,B; +#ifdef GTE_DUMP + static int sample = 0; sample++; +#endif +#ifdef GTE_LOG + GTE_LOG("GTE_DCPL\n"); +#endif + +#ifdef GTE_DUMP + if(sample < 100) + { + G_OP("DCPL", 8); + G_SD(6); + G_SD(8); + G_SD(9); + G_SD(10); + G_SD(11); + + G_SC(21); + G_SC(22); + G_SC(23); + } +#endif +/* R = ((gteRGB)&0xff); + G = ((gteRGB>> 8)&0xff); + B = ((gteRGB>>16)&0xff); + C = ((gteRGB>>24)&0xff); + + gteMAC1 = (signed long)((double)(R*gteIR1) + (double)(gteIR0*LimitAS(gteRFC-(double)(R*gteIR1),24))/4096.0); + gteMAC2 = (signed long)((double)(G*gteIR2) + (double)(gteIR0*LimitAS(gteGFC-(double)(G*gteIR2),23))/4096.0); + gteMAC3 = (signed long)((double)(B*gteIR3) + (double)(gteIR0*LimitAS(gteBFC-(double)(B*gteIR3),22))/4096.0); + + MAC2IR() + + R = (unsigned long)LimitB(gteMAC1,21); if (R>255) R=255; else if (R<0) R=0; + G = (unsigned long)LimitB(gteMAC2,20); if (G>255) G=255; else if (G<0) G=0; + B = (unsigned long)LimitB(gteMAC3,19); if (B>255) B=255; else if (B<0) B=0; + + gteRGB0 = gteRGB1; + gteRGB1 = gteRGB2; + gteRGB2 = R|(G<<8)|(B<<16)|(C<<24); + + if (gteFLAG & 0x7f87e000) gteFLAG|=0x80000000;*/ + +/* gteFLAG = 0; + + gteMAC1 = NC_OVERFLOW1((gteR * gteIR1) / 256.0f + (gteIR0 * limA1S(gteRFC - ((gteR * gteIR1) / 256.0f))) / 4096.0f); + gteMAC2 = NC_OVERFLOW2((gteG * gteIR1) / 256.0f + (gteIR0 * limA2S(gteGFC - ((gteG * gteIR1) / 256.0f))) / 4096.0f); + gteMAC3 = NC_OVERFLOW3((gteB * gteIR1) / 256.0f + (gteIR0 * limA3S(gteBFC - ((gteB * gteIR1) / 256.0f))) / 4096.0f); + */ +/* gteMAC1 = ( (signed long)(gteR)*gteIR1 + (gteIR0*(signed short)limA1S(gteRFC - ((gteR*gteIR1)>>12) )) ) >>6; + gteMAC2 = ( (signed long)(gteG)*gteIR2 + (gteIR0*(signed short)limA2S(gteGFC - ((gteG*gteIR2)>>12) )) ) >>6; + gteMAC3 = ( (signed long)(gteB)*gteIR3 + (gteIR0*(signed short)limA3S(gteBFC - ((gteB*gteIR3)>>12) )) ) >>6;*/ + +/* gteMAC1 = ( (signed long)(gteR)*gteIR1 + (gteIR0*(signed short)limA1S(gteRFC - ((gteR*gteIR1)>>12) )) ) >>8; + gteMAC2 = ( (signed long)(gteG)*gteIR2 + (gteIR0*(signed short)limA2S(gteGFC - ((gteG*gteIR2)>>12) )) ) >>8; + gteMAC3 = ( (signed long)(gteB)*gteIR3 + (gteIR0*(signed short)limA3S(gteBFC - ((gteB*gteIR3)>>12) )) ) >>8;*/ + gteMAC1 = ( (signed long)(gteR)*gteIR1 + (gteIR0*(signed short)FlimA1S(gteRFC - ((gteR*gteIR1)>>12) )) ) >>8; + gteMAC2 = ( (signed long)(gteG)*gteIR2 + (gteIR0*(signed short)FlimA2S(gteGFC - ((gteG*gteIR2)>>12) )) ) >>8; + gteMAC3 = ( (signed long)(gteB)*gteIR3 + (gteIR0*(signed short)FlimA3S(gteBFC - ((gteB*gteIR3)>>12) )) ) >>8; + + gteFLAG=0; + MAC2IR(); + + gteRGB0 = gteRGB1; + gteRGB1 = gteRGB2; + +/* gteR2 = limB1(gteMAC1 / 16.0f); + gteG2 = limB2(gteMAC2 / 16.0f); + gteB2 = limB3(gteMAC3 / 16.0f); gteCODE2 = gteCODE;*/ + gteR2 = FlimB1(gteMAC1 >> 4); + gteG2 = FlimB2(gteMAC2 >> 4); + gteB2 = FlimB3(gteMAC3 >> 4); gteCODE2 = gteCODE; + + SUM_FLAG + +#ifdef GTE_DUMP + if(sample < 100) + { + G_GD(9); + G_GD(10); + G_GD(11); + + //G_GD(20); + //G_GD(21); + G_GD(22); + + G_GD(25); + G_GD(26); + G_GD(27); + + G_GC(31); + } +#endif +} + +void gteGPF() { +// double ipx, ipy, ipz; +// s32 ipx, ipy, ipz; + +#ifdef GTE_DUMP + static int sample = 0; sample++; +#endif +#ifdef GTE_LOG + GTE_LOG("GTE_GPF %lx\n", psxRegs.code & 0x1ffffff); +#endif +#ifdef GTE_DUMP + if(sample < 100) + { + G_OP("GPF", 5); + G_SD(6); + G_SD(8); + G_SD(9); + G_SD(10); + G_SD(11); + } +#endif +/* gteFLAG = 0; + + ipx = (double)((short)gteIR0) * ((short)gteIR1); + ipy = (double)((short)gteIR0) * ((short)gteIR2); + ipz = (double)((short)gteIR0) * ((short)gteIR3); + + // same as mvmva + if (psxRegs.code & 0x80000) { + ipx /= 4096.0; ipy /= 4096.0; ipz /= 4096.0; + } + + gteMAC1 = (long)ipx; + gteMAC2 = (long)ipy; + gteMAC3 = (long)ipz; + + gteIR1 = (long)LimitAS(ipx,24); + gteIR2 = (long)LimitAS(ipy,23); + gteIR3 = (long)LimitAS(ipz,22); + + gteRGB0 = gteRGB1; + gteRGB1 = gteRGB2; + gteC2 = gteCODE; + gteR2 = (unsigned char)LimitB(ipx,21); + gteG2 = (unsigned char)LimitB(ipy,20); + gteB2 = (unsigned char)LimitB(ipz,19);*/ + + gteFLAG = 0; + +/* if (psxRegs.code & 0x80000) { + gteMAC1 = NC_OVERFLOW1((gteIR0 * gteIR1) / 4096.0f); + gteMAC2 = NC_OVERFLOW2((gteIR0 * gteIR2) / 4096.0f); + gteMAC3 = NC_OVERFLOW3((gteIR0 * gteIR3) / 4096.0f); + } else { + gteMAC1 = NC_OVERFLOW1(gteIR0 * gteIR1); + gteMAC2 = NC_OVERFLOW2(gteIR0 * gteIR2); + gteMAC3 = NC_OVERFLOW3(gteIR0 * gteIR3); + }*/ + if (psxRegs.code & 0x80000) { + gteMAC1 = FNC_OVERFLOW1((gteIR0 * gteIR1) >> 12); + gteMAC2 = FNC_OVERFLOW2((gteIR0 * gteIR2) >> 12); + gteMAC3 = FNC_OVERFLOW3((gteIR0 * gteIR3) >> 12); + } else { + gteMAC1 = FNC_OVERFLOW1(gteIR0 * gteIR1); + gteMAC2 = FNC_OVERFLOW2(gteIR0 * gteIR2); + gteMAC3 = FNC_OVERFLOW3(gteIR0 * gteIR3); + } + MAC2IR(); + + gteRGB0 = gteRGB1; + gteRGB1 = gteRGB2; + +/* gteR2 = limB1(gteMAC1 / 16.0f); + gteG2 = limB2(gteMAC2 / 16.0f); + gteB2 = limB3(gteMAC3 / 16.0f); gteCODE2 = gteCODE;*/ + gteR2 = FlimB1(gteMAC1 >> 4); + gteG2 = FlimB2(gteMAC2 >> 4); + gteB2 = FlimB3(gteMAC3 >> 4); gteCODE2 = gteCODE; + + SUM_FLAG + +#ifdef GTE_DUMP + if(sample < 100) + { + G_GD(9); + G_GD(10); + G_GD(11); + + //G_GD(20); + //G_GD(21); + G_GD(22); + + G_GD(25); + G_GD(26); + G_GD(27); + + G_GC(31); + } +#endif +} + +void gteGPL() { + // double IPX=0,IPY=0,IPZ=0; +// unsigned long C,R,G,B; +#ifdef GTE_DUMP + static int sample = 0; sample++; +#endif +#ifdef GTE_LOG + GTE_LOG("GTE_GPL %lx\n", psxRegs.code & 0x1ffffff); +#endif + +#ifdef GTE_DUMP + if(sample < 100) + { + G_OP("GPL", 5); + G_SD(6); + G_SD(8); + G_SD(9); + G_SD(10); + G_SD(11); + + G_SD(25); + G_SD(26); + G_SD(27); + } +#endif + +/* gteFLAG=0; + switch(psxRegs.code & 0x1ffffff) { + case 0x1A8003E: + IPX = EDETEC1((double)gteMAC1 + ((double)gteIR0*(double)gteIR1)/4096.0f); + IPY = EDETEC2((double)gteMAC2 + ((double)gteIR0*(double)gteIR2)/4096.0f); + IPZ = EDETEC3((double)gteMAC3 + ((double)gteIR0*(double)gteIR3)/4096.0f); + break; + + case 0x1A0003E: + IPX = EDETEC1((double)gteMAC1 + ((double)gteIR0*(double)gteIR1)); + IPY = EDETEC2((double)gteMAC2 + ((double)gteIR0*(double)gteIR2)); + IPZ = EDETEC3((double)gteMAC3 + ((double)gteIR0*(double)gteIR3)); + break; + } + gteIR1 = (short)float2int(LimitAS(IPX,24)); + gteIR2 = (short)float2int(LimitAS(IPY,23)); + gteIR3 = (short)float2int(LimitAS(IPZ,22)); + + gteMAC1 = (int)float2int(IPX); + gteMAC2 = (int)float2int(IPY); + gteMAC3 = (int)float2int(IPZ); + + C = gteRGB & 0xff000000; + R = float2int(ALIMIT(IPX,0,255)); + G = float2int(ALIMIT(IPY,0,255)); + B = float2int(ALIMIT(IPZ,0,255)); + + gteRGB0 = gteRGB1; + gteRGB1 = gteRGB2; + gteRGB2 = C|R|(G<<8)|(B<<16);*/ + gteFLAG = 0; + +/* if (psxRegs.code & 0x80000) { + gteMAC1 = NC_OVERFLOW1(gteMAC1 + (gteIR0 * gteIR1) / 4096.0f); + gteMAC2 = NC_OVERFLOW2(gteMAC2 + (gteIR0 * gteIR2) / 4096.0f); + gteMAC3 = NC_OVERFLOW3(gteMAC3 + (gteIR0 * gteIR3) / 4096.0f); + } else { + gteMAC1 = NC_OVERFLOW1(gteMAC1 + (gteIR0 * gteIR1)); + gteMAC2 = NC_OVERFLOW2(gteMAC2 + (gteIR0 * gteIR2)); + gteMAC3 = NC_OVERFLOW3(gteMAC3 + (gteIR0 * gteIR3)); + }*/ + if (psxRegs.code & 0x80000) { + gteMAC1 = FNC_OVERFLOW1(gteMAC1 + ((gteIR0 * gteIR1) >> 12)); + gteMAC2 = FNC_OVERFLOW2(gteMAC2 + ((gteIR0 * gteIR2) >> 12)); + gteMAC3 = FNC_OVERFLOW3(gteMAC3 + ((gteIR0 * gteIR3) >> 12)); + } else { + gteMAC1 = FNC_OVERFLOW1(gteMAC1 + (gteIR0 * gteIR1)); + gteMAC2 = FNC_OVERFLOW2(gteMAC2 + (gteIR0 * gteIR2)); + gteMAC3 = FNC_OVERFLOW3(gteMAC3 + (gteIR0 * gteIR3)); + } + MAC2IR(); + + gteRGB0 = gteRGB1; + gteRGB1 = gteRGB2; + +/* gteR2 = limB1(gteMAC1 / 16.0f); + gteG2 = limB2(gteMAC2 / 16.0f); + gteB2 = limB3(gteMAC3 / 16.0f); gteCODE2 = gteCODE;*/ + gteR2 = FlimB1(gteMAC1 >> 4); + gteG2 = FlimB2(gteMAC2 >> 4); + gteB2 = FlimB3(gteMAC3 >> 4); gteCODE2 = gteCODE; + + SUM_FLAG + +#ifdef GTE_DUMP + if(sample < 100) + { + G_GD(9); + G_GD(10); + G_GD(11); + + //G_GD(20); + //G_GD(21); + G_GD(22); + + G_GD(25); + G_GD(26); + G_GD(27); + + G_GC(31); + } +#endif +} + +/* +#define GTE_DPCS() { \ + RR0 = (double)R + (gteIR0*LimitAS((double)(gteRFC - R),24))/4096.0; \ + GG0 = (double)G + (gteIR0*LimitAS((double)(gteGFC - G),23))/4096.0; \ + BB0 = (double)B + (gteIR0*LimitAS((double)(gteBFC - B),22))/4096.0; \ + \ + gteIR1 = (long)LimitAS(RR0,24); \ + gteIR2 = (long)LimitAS(GG0,23); \ + gteIR3 = (long)LimitAS(BB0,22); \ + \ + gteRGB0 = gteRGB1; \ + gteRGB1 = gteRGB2; \ + gteC2 = C; \ + gteR2 = (unsigned char)LimitB(RR0/16.0,21); \ + gteG2 = (unsigned char)LimitB(GG0/16.0,20); \ + gteB2 = (unsigned char)LimitB(BB0/16.0,19); \ + \ + gteMAC1 = (long)RR0; \ + gteMAC2 = (long)GG0; \ + gteMAC3 = (long)BB0; \ +} +*/ +void gteDPCS() { +// unsigned long C,R,G,B; +// double RR0,GG0,BB0; +#ifdef GTE_DUMP + static int sample = 0; sample++; +#endif +#ifdef GTE_LOG + GTE_LOG("GTE_DPCS\n"); +#endif + +#ifdef GTE_DUMP + if(sample < 100) + { + G_OP("DPCS", 8); + G_SD(6); + G_SD(8); + + G_SC(21); + G_SC(22); + G_SC(23); + } +#endif + +/* gteFLAG = 0; + + C = gteCODE; + R = gteR * 16.0; + G = gteG * 16.0; + B = gteB * 16.0; + + GTE_DPCS(); + + if (gteFLAG & 0x7f87e000) gteFLAG|=0x80000000;*/ +/* gteFLAG = 0; + + gteMAC1 = NC_OVERFLOW1((gteR * 16.0f) + (gteIR0 * limA1S(gteRFC - (gteR * 16.0f))) / 4096.0f); + gteMAC2 = NC_OVERFLOW2((gteG * 16.0f) + (gteIR0 * limA2S(gteGFC - (gteG * 16.0f))) / 4096.0f); + gteMAC3 = NC_OVERFLOW3((gteB * 16.0f) + (gteIR0 * limA3S(gteBFC - (gteB * 16.0f))) / 4096.0f); + */ +/* gteMAC1 = (gteR<<4) + ( (gteIR0*(signed short)limA1S(gteRFC-(gteR<<4)) ) >>12); + gteMAC2 = (gteG<<4) + ( (gteIR0*(signed short)limA2S(gteGFC-(gteG<<4)) ) >>12); + gteMAC3 = (gteB<<4) + ( (gteIR0*(signed short)limA3S(gteBFC-(gteB<<4)) ) >>12);*/ + gteMAC1 = (gteR<<4) + ( (gteIR0*(signed short)FlimA1S(gteRFC-(gteR<<4)) ) >>12); + gteMAC2 = (gteG<<4) + ( (gteIR0*(signed short)FlimA2S(gteGFC-(gteG<<4)) ) >>12); + gteMAC3 = (gteB<<4) + ( (gteIR0*(signed short)FlimA3S(gteBFC-(gteB<<4)) ) >>12); + + gteFLAG = 0; + MAC2IR(); + + gteRGB0 = gteRGB1; + gteRGB1 = gteRGB2; + +/* gteR2 = limB1(gteMAC1 / 16.0f); + gteG2 = limB2(gteMAC2 / 16.0f); + gteB2 = limB3(gteMAC3 / 16.0f); gteCODE2 = gteCODE;*/ + gteR2 = FlimB1(gteMAC1 >> 4); + gteG2 = FlimB2(gteMAC2 >> 4); + gteB2 = FlimB3(gteMAC3 >> 4); gteCODE2 = gteCODE; + + SUM_FLAG + +#ifdef GTE_DUMP + if(sample < 100) + { + G_GD(9); + G_GD(10); + G_GD(11); + + //G_GD(20); + //G_GD(21); + G_GD(22); + + G_GD(25); + G_GD(26); + G_GD(27); + + G_GC(31); + } +#endif +} + +void gteDPCT() { +// unsigned long C,R,G,B; +// double RR0,GG0,BB0; +#ifdef GTE_DUMP + static int sample = 0; sample++; +#endif +#ifdef GTE_LOG + GTE_LOG("GTE_DPCT\n"); +#endif + +#ifdef GTE_DUMP + if(sample < 100) + { + G_OP("DPCT", 17); + G_SD(8); + + G_SD(20); + G_SD(21); + G_SD(22); + + G_SC(21); + G_SC(22); + G_SC(23); + } +#endif +/* gteFLAG = 0; + + C = gteCODE0; + R = gteR0 * 16.0; + G = gteG0 * 16.0; + B = gteB0 * 16.0; + + GTE_DPCS(); + + C = gteCODE0; + R = gteR0 * 16.0; + G = gteG0 * 16.0; + B = gteB0 * 16.0; + + GTE_DPCS(); + + C = gteCODE0; + R = gteR0 * 16.0; + G = gteG0 * 16.0; + B = gteB0 * 16.0; + + GTE_DPCS(); + + if (gteFLAG & 0x7f87e000) gteFLAG|=0x80000000;*/ +/* gteFLAG = 0; + + gteMAC1 = NC_OVERFLOW1((gteR0 * 16.0f) + gteIR0 * limA1S(gteRFC - (gteR0 * 16.0f))); + gteMAC2 = NC_OVERFLOW2((gteG0 * 16.0f) + gteIR0 * limA2S(gteGFC - (gteG0 * 16.0f))); + gteMAC3 = NC_OVERFLOW3((gteB0 * 16.0f) + gteIR0 * limA3S(gteBFC - (gteB0 * 16.0f))); + */ +/* gteMAC1 = (gteR0<<4) + ( (gteIR0*(signed short)limA1S(gteRFC-(gteR0<<4)) ) >>12); + gteMAC2 = (gteG0<<4) + ( (gteIR0*(signed short)limA2S(gteGFC-(gteG0<<4)) ) >>12); + gteMAC3 = (gteB0<<4) + ( (gteIR0*(signed short)limA3S(gteBFC-(gteB0<<4)) ) >>12);*/ + gteMAC1 = (gteR0<<4) + ( (gteIR0*(signed short)FlimA1S(gteRFC-(gteR0<<4)) ) >>12); + gteMAC2 = (gteG0<<4) + ( (gteIR0*(signed short)FlimA2S(gteGFC-(gteG0<<4)) ) >>12); + gteMAC3 = (gteB0<<4) + ( (gteIR0*(signed short)FlimA3S(gteBFC-(gteB0<<4)) ) >>12); +// MAC2IR(); + + gteRGB0 = gteRGB1; + gteRGB1 = gteRGB2; + +/* gteR2 = limB1(gteMAC1 / 16.0f); + gteG2 = limB2(gteMAC2 / 16.0f); + gteB2 = limB3(gteMAC3 / 16.0f); gteCODE2 = gteCODE;*/ + gteR2 = FlimB1(gteMAC1 >> 4); + gteG2 = FlimB2(gteMAC2 >> 4); + gteB2 = FlimB3(gteMAC3 >> 4); gteCODE2 = gteCODE; + +/* gteMAC1 = (gteR0<<4) + ( (gteIR0*(signed short)limA1S(gteRFC-(gteR0<<4)) ) >>12); + gteMAC2 = (gteG0<<4) + ( (gteIR0*(signed short)limA2S(gteGFC-(gteG0<<4)) ) >>12); + gteMAC3 = (gteB0<<4) + ( (gteIR0*(signed short)limA3S(gteBFC-(gteB0<<4)) ) >>12);*/ + gteMAC1 = (gteR0<<4) + ( (gteIR0*(signed short)FlimA1S(gteRFC-(gteR0<<4)) ) >>12); + gteMAC2 = (gteG0<<4) + ( (gteIR0*(signed short)FlimA2S(gteGFC-(gteG0<<4)) ) >>12); + gteMAC3 = (gteB0<<4) + ( (gteIR0*(signed short)FlimA3S(gteBFC-(gteB0<<4)) ) >>12); +// MAC2IR(); + gteRGB0 = gteRGB1; + gteRGB1 = gteRGB2; + +/* gteR2 = limB1(gteMAC1 / 16.0f); + gteG2 = limB2(gteMAC2 / 16.0f); + gteB2 = limB3(gteMAC3 / 16.0f); gteCODE2 = gteCODE;*/ + gteR2 = FlimB1(gteMAC1 >> 4); + gteG2 = FlimB2(gteMAC2 >> 4); + gteB2 = FlimB3(gteMAC3 >> 4); gteCODE2 = gteCODE; + +/* gteMAC1 = (gteR0<<4) + ( (gteIR0*(signed short)limA1S(gteRFC-(gteR0<<4)) ) >>12); + gteMAC2 = (gteG0<<4) + ( (gteIR0*(signed short)limA2S(gteGFC-(gteG0<<4)) ) >>12); + gteMAC3 = (gteB0<<4) + ( (gteIR0*(signed short)limA3S(gteBFC-(gteB0<<4)) ) >>12);*/ + gteMAC1 = (gteR0<<4) + ( (gteIR0*(signed short)FlimA1S(gteRFC-(gteR0<<4)) ) >>12); + gteMAC2 = (gteG0<<4) + ( (gteIR0*(signed short)FlimA2S(gteGFC-(gteG0<<4)) ) >>12); + gteMAC3 = (gteB0<<4) + ( (gteIR0*(signed short)FlimA3S(gteBFC-(gteB0<<4)) ) >>12); + gteFLAG = 0; + MAC2IR(); + gteRGB0 = gteRGB1; + gteRGB1 = gteRGB2; + +/* gteR2 = limB1(gteMAC1 / 16.0f); + gteG2 = limB2(gteMAC2 / 16.0f); + gteB2 = limB3(gteMAC3 / 16.0f); gteCODE2 = gteCODE;*/ + gteR2 = FlimB1(gteMAC1 >> 4); + gteG2 = FlimB2(gteMAC2 >> 4); + gteB2 = FlimB3(gteMAC3 >> 4); gteCODE2 = gteCODE; + + SUM_FLAG + +#ifdef GTE_DUMP + if(sample < 100) + { + G_GD(9); + G_GD(10); + G_GD(11); + + G_GD(20); + G_GD(21); + G_GD(22); + + G_GD(25); + G_GD(26); + G_GD(27); + + G_GC(31); + } +#endif +} + +/* +#define GTE_NCS(vn) { \ + RR0 = ((double)gteVX##vn * gteL11 + (double)gteVY##vn * (double)gteL12 + (double)gteVZ##vn * gteL13) / 4096.0; \ + GG0 = ((double)gteVX##vn * gteL21 + (double)gteVY##vn * (double)gteL22 + (double)gteVZ##vn * gteL23) / 4096.0; \ + BB0 = ((double)gteVX##vn * gteL31 + (double)gteVY##vn * (double)gteL32 + (double)gteVZ##vn * gteL33) / 4096.0; \ + t1 = LimitAU(RR0, 24); \ + t2 = LimitAU(GG0, 23); \ + t3 = LimitAU(BB0, 22); \ + \ + RR0 = (double)gteRBK + ((double)gteLR1 * t1 + (double)gteLR2 * t2 + (double)gteLR3 * t3) / 4096.0; \ + GG0 = (double)gteGBK + ((double)gteLG1 * t1 + (double)gteLG2 * t2 + (double)gteLG3 * t3) / 4096.0; \ + BB0 = (double)gteBBK + ((double)gteLB1 * t1 + (double)gteLB2 * t2 + (double)gteLB3 * t3) / 4096.0; \ + t1 = LimitAU(RR0, 24); \ + t2 = LimitAU(GG0, 23); \ + t3 = LimitAU(BB0, 22); \ + \ + gteRGB0 = gteRGB1; gteRGB1 = gteRGB2; \ + gteR2 = (unsigned char)LimitB(RR0/16.0, 21); \ + gteG2 = (unsigned char)LimitB(GG0/16.0, 20); \ + gteB2 = (unsigned char)LimitB(BB0/16.0, 19); \ + gteCODE2=gteCODE0; \ +}*/ + +#define LOW(a) (((a) < 0) ? 0 : (a)) +/* +#define GTE_NCS(vn) \ +RR0 = LOW((gteL11*gteVX##vn + gteL12*gteVY##vn + gteL13*gteVZ##vn)/4096.0f); \ +GG0 = LOW((gteL21*gteVX##vn + gteL22*gteVY##vn + gteL23*gteVZ##vn)/4096.0f); \ +BB0 = LOW((gteL31*gteVX##vn + gteL32*gteVY##vn + gteL33*gteVZ##vn)/4096.0f); \ +gteMAC1 = gteRBK + (gteLR1*RR0 + gteLR2*GG0 + gteLR3*BB0)/4096.0f; \ +gteMAC2 = gteGBK + (gteLG1*RR0 + gteLG2*GG0 + gteLG3*BB0)/4096.0f; \ +gteMAC3 = gteBBK + (gteLB1*RR0 + gteLB2*GG0 + gteLB3*BB0)/4096.0f; \ +gteRGB0 = gteRGB1; \ +gteRGB1 = gteRGB2; \ +gteR2 = FlimB1(gteMAC1 >> 4); \ +gteG2 = FlimB2(gteMAC2 >> 4); \ +gteB2 = FlimB3(gteMAC3 >> 4); gteCODE2 = gteCODE;*/ +/*gteR2 = limB1(gteMAC1 / 16.0f); \ +gteG2 = limB2(gteMAC2 / 16.0f); \ +gteB2 = limB3(gteMAC3 / 16.0f); gteCODE2 = gteCODE;*/ + +#define GTE_NCS(vn) \ + gte_LL1 = F12limA1U((gteL11*gteVX##vn + gteL12*gteVY##vn + gteL13*gteVZ##vn) >> 12); \ + gte_LL2 = F12limA2U((gteL21*gteVX##vn + gteL22*gteVY##vn + gteL23*gteVZ##vn) >> 12); \ + gte_LL3 = F12limA3U((gteL31*gteVX##vn + gteL32*gteVY##vn + gteL33*gteVZ##vn) >> 12); \ + gteMAC1 = F12limA1U(gteRBK + ((gteLR1*gte_LL1 + gteLR2*gte_LL2 + gteLR3*gte_LL3) >> 12)); \ + gteMAC2 = F12limA2U(gteGBK + ((gteLG1*gte_LL1 + gteLG2*gte_LL2 + gteLG3*gte_LL3) >> 12)); \ + gteMAC3 = F12limA3U(gteBBK + ((gteLB1*gte_LL1 + gteLB2*gte_LL2 + gteLB3*gte_LL3) >> 12)); + +void gteNCS() { +// double RR0,GG0,BB0; + s32 gte_LL1,gte_LL2,gte_LL3; +// s32 RR0,GG0,BB0; +// double t1, t2, t3; +#ifdef GTE_DUMP + static int sample = 0; sample++; +#endif + +#ifdef GTE_LOG + GTE_LOG("GTE_NCS\n"); +#endif + +#ifdef GTE_DUMP + if(sample < 100) + { + G_OP("NCS", 14); + G_SD(0); + G_SD(1); + G_SD(6); + + G_SC(8); + G_SC(9); + G_SC(10); + G_SC(11); + G_SC(12); + G_SC(13); + G_SC(14); + G_SC(15); + G_SC(16); + G_SC(17); + G_SC(18); + G_SC(19); + G_SC(20); + } +#endif +/* gteFLAG = 0; + + GTE_NCS(0); + + gteMAC1=(long)RR0; + gteMAC2=(long)GG0; + gteMAC3=(long)BB0; + + gteIR1=(long)t1; + gteIR2=(long)t2; + gteIR3=(long)t3; + + if (gteFLAG & 0x7f87e000) gteFLAG|=0x80000000;*/ + gteFLAG = 0; + + GTE_NCS(0); + + gteRGB0 = gteRGB1; + gteRGB1 = gteRGB2; + gteR2 = FlimB1(gteMAC1 >> 4); + gteG2 = FlimB2(gteMAC2 >> 4); + gteB2 = FlimB3(gteMAC3 >> 4); gteCODE2 = gteCODE; + + MAC2IR1(); + + SUM_FLAG + +#ifdef GTE_DUMP + if(sample < 100) + { + G_GD(9); + G_GD(10); + G_GD(11); + + //G_GD(20); + //G_GD(21); + G_GD(22); + + G_GD(25); + G_GD(26); + G_GD(27); + + G_GC(31); + } +#endif +} + +void gteNCT() { +// double RR0,GG0,BB0; + s32 gte_LL1,gte_LL2,gte_LL3; +// s32 RR0,GG0,BB0; +// double t1, t2, t3; +#ifdef GTE_DUMP + static int sample = 0; sample++; +#endif + +#ifdef GTE_LOG + GTE_LOG("GTE_NCT\n"); +#endif + +#ifdef GTE_DUMP + if(sample < 100) + { + G_OP("NCT", 30); + G_SD(0); + G_SD(1); + G_SD(2); + G_SD(3); + G_SD(4); + G_SD(5); + G_SD(6); + + G_SC(8); + G_SC(9); + G_SC(10); + G_SC(11); + G_SC(12); + G_SC(13); + G_SC(14); + G_SC(15); + G_SC(16); + G_SC(17); + G_SC(18); + G_SC(19); + G_SC(20); + } +#endif +/* + gteFLAG = 0; + +//V0 + GTE_NCS(0); +//V1 + GTE_NCS(1); +//V2 + GTE_NCS(2); + + gteMAC1=(long)RR0; + gteMAC2=(long)GG0; + gteMAC3=(long)BB0; + + gteIR1=(long)t1; + gteIR2=(long)t2; + gteIR3=(long)t3; + + if (gteFLAG & 0x7f87e000) gteFLAG|=0x80000000;*/ + gteFLAG = 0; + + GTE_NCS(0); + + gteR0 = FlimB1(gteMAC1 >> 4); + gteG0 = FlimB2(gteMAC2 >> 4); + gteB0 = FlimB3(gteMAC3 >> 4); gteCODE0 = gteCODE; + + GTE_NCS(1); + gteR1 = FlimB1(gteMAC1 >> 4); + gteG1 = FlimB2(gteMAC2 >> 4); + gteB1 = FlimB3(gteMAC3 >> 4); gteCODE1 = gteCODE; + + GTE_NCS(2); + gteR2 = FlimB1(gteMAC1 >> 4); + gteG2 = FlimB2(gteMAC2 >> 4); + gteB2 = FlimB3(gteMAC3 >> 4); gteCODE2 = gteCODE; + + MAC2IR1(); + + SUM_FLAG + +#ifdef GTE_DUMP + if(sample < 100) + { + G_GD(9); + G_GD(10); + G_GD(11); + + G_GD(20); + G_GD(21); + G_GD(22); + + G_GD(25); + G_GD(26); + G_GD(27); + + G_GC(31); + } +#endif +} + +void gteCC() { +// double RR0,GG0,BB0; + s32 RR0,GG0,BB0; +// double t1,t2,t3; +#ifdef GTE_DUMP + static int sample = 0; sample++; +#endif +#ifdef GTE_LOG + GTE_LOG("GTE_CC\n"); +#endif + +#ifdef GTE_DUMP + if(sample < 100) + { + G_OP("CC", 11); + G_SD(6); + G_SD(9); + G_SD(10); + G_SD(11); + + G_SC(13); + G_SC(14); + G_SC(15); + G_SC(16); + G_SC(17); + G_SC(18); + G_SC(19); + } +#endif +/* gteFLAG = 0; + + RR0 = (double)gteRBK + ((double)gteLR1 * gteIR1 + (double)gteLR2 * gteIR2 + (double)gteLR3 * gteIR3) / 4096.0; + GG0 = (double)gteGBK + ((double)gteLG1 * gteIR1 + (double)gteLG2 * gteIR2 + (double)gteLG3 * gteIR3) / 4096.0; + BB0 = (double)gteBBK + ((double)gteLB1 * gteIR1 + (double)gteLB2 * gteIR2 + (double)gteLB3 * gteIR3) / 4096.0; + t1 = LimitAU(RR0, 24); + t2 = LimitAU(GG0, 23); + t3 = LimitAU(BB0, 22); + + RR0=((double)gteR * t1)/256.0; + GG0=((double)gteG * t2)/256.0; + BB0=((double)gteB * t3)/256.0; + gteIR1 = (long)LimitAU(RR0,24); + gteIR2 = (long)LimitAU(GG0,23); + gteIR3 = (long)LimitAU(BB0,22); + + gteCODE0=gteCODE1; gteCODE1=gteCODE2; + gteC2 = gteCODE0; + gteR2 = (unsigned char)LimitB(RR0/16.0, 21); + gteG2 = (unsigned char)LimitB(GG0/16.0, 20); + gteB2 = (unsigned char)LimitB(BB0/16.0, 19); + + if (gteFLAG & 0x7f87e000) gteFLAG|=0x80000000;*/ + gteFLAG = 0; + +/* RR0 = NC_OVERFLOW1(gteRBK + (gteLR1*gteIR1 + gteLR2*gteIR2 + gteLR3*gteIR3) / 4096.0f); + GG0 = NC_OVERFLOW2(gteGBK + (gteLG1*gteIR1 + gteLG2*gteIR2 + gteLG3*gteIR3) / 4096.0f); + BB0 = NC_OVERFLOW3(gteBBK + (gteLB1*gteIR1 + gteLB2*gteIR2 + gteLB3*gteIR3) / 4096.0f); + + gteMAC1 = gteR * RR0 / 256.0f; + gteMAC2 = gteG * GG0 / 256.0f; + gteMAC3 = gteB * BB0 / 256.0f;*/ + RR0 = FNC_OVERFLOW1(gteRBK + ((gteLR1*gteIR1 + gteLR2*gteIR2 + gteLR3*gteIR3) >> 12)); + GG0 = FNC_OVERFLOW2(gteGBK + ((gteLG1*gteIR1 + gteLG2*gteIR2 + gteLG3*gteIR3) >> 12)); + BB0 = FNC_OVERFLOW3(gteBBK + ((gteLB1*gteIR1 + gteLB2*gteIR2 + gteLB3*gteIR3) >> 12)); + + gteMAC1 = (gteR * RR0) >> 8; + gteMAC2 = (gteG * GG0) >> 8; + gteMAC3 = (gteB * BB0) >> 8; + + MAC2IR1(); + + gteRGB0 = gteRGB1; + gteRGB1 = gteRGB2; + +/* gteR2 = limB1(gteMAC1 / 16.0f); + gteG2 = limB2(gteMAC2 / 16.0f); + gteB2 = limB3(gteMAC3 / 16.0f); gteCODE2 = gteCODE;*/ + gteR2 = FlimB1(gteMAC1 >> 4); + gteG2 = FlimB2(gteMAC2 >> 4); + gteB2 = FlimB3(gteMAC3 >> 4); gteCODE2 = gteCODE; + + SUM_FLAG + +#ifdef GTE_DUMP + if(sample < 100) + { + G_GD(9); + G_GD(10); + G_GD(11); + + //G_GD(20); + //G_GD(21); + G_GD(22); + + G_GD(25); + G_GD(26); + G_GD(27); + + G_GC(31); + } +#endif +} + +void gteINTPL() { //test opcode +#ifdef GTE_DUMP + static int sample = 0; sample++; +#endif +#ifdef GTE_LOG + GTE_LOG("GTE_INTP\n"); +#endif + +#ifdef GTE_DUMP + if(sample < 100) + { + G_OP("INTPL", 8); + G_SD(6); + G_SD(8); + G_SD(9); + G_SD(10); + G_SD(11); + + G_SC(21); + G_SC(22); + G_SC(23); + } +#endif + /* NC: old + gteFLAG=0; + gteMAC1 = gteIR1 + gteIR0*limA1S(gteRFC-gteIR1); + gteMAC2 = gteIR2 + gteIR0*limA2S(gteGFC-gteIR2); + gteMAC3 = gteIR3 + gteIR0*limA3S(gteBFC-gteIR3); + //gteFLAG = 0; + MAC2IR(); + gteRGB0 = gteRGB1; + gteRGB1 = gteRGB2; + + gteR2 = limB1(gteMAC1 / 16.0f); + gteG2 = limB2(gteMAC2 / 16.0f); + gteB2 = limB3(gteMAC3 / 16.0f); gteCODE2 = gteCODE; + */ + +/* gteFLAG=0; + gteMAC1 = gteIR1 + gteIR0*(gteRFC-gteIR1)/4096.0; + gteMAC2 = gteIR2 + gteIR0*(gteGFC-gteIR2)/4096.0; + gteMAC3 = gteIR3 + gteIR0*(gteBFC-gteIR3)/4096.0; + + //gteMAC3 = (int)((((psxRegs).CP2D).n).ir3+(((psxRegs).CP2D).n).ir0 * ((((psxRegs).CP2C).n).bfc-(((psxRegs).CP2D).n).ir3)/4096.0); + + if(gteMAC3 > gteIR1 && gteMAC3 > gteBFC) + { + gteMAC3 = gteMAC3; + } + //gteFLAG = 0;*/ + //NEW CODE +/* gteMAC1 = gteIR1 + ((gteIR0*(signed short)limA1S(gteRFC-gteIR1))>>12); + gteMAC2 = gteIR2 + ((gteIR0*(signed short)limA2S(gteGFC-gteIR2))>>12); + gteMAC3 = gteIR3 + ((gteIR0*(signed short)limA3S(gteBFC-gteIR3))>>12);*/ + gteMAC1 = gteIR1 + ((gteIR0*(signed short)FlimA1S(gteRFC-gteIR1))>>12); + gteMAC2 = gteIR2 + ((gteIR0*(signed short)FlimA2S(gteGFC-gteIR2))>>12); + gteMAC3 = gteIR3 + ((gteIR0*(signed short)FlimA3S(gteBFC-gteIR3))>>12); + gteFLAG = 0; + + MAC2IR(); + gteRGB0 = gteRGB1; + gteRGB1 = gteRGB2; + +/* gteR2 = limB1(gteMAC1 / 16.0f); + gteG2 = limB2(gteMAC2 / 16.0f); + gteB2 = limB3(gteMAC3 / 16.0f); gteCODE2 = gteCODE;*/ + gteR2 = FlimB1(gteMAC1 >> 4); + gteG2 = FlimB2(gteMAC2 >> 4); + gteB2 = FlimB3(gteMAC3 >> 4); gteCODE2 = gteCODE; + + SUM_FLAG + +#ifdef GTE_DUMP + if(sample < 100) + { + G_GD(9); + G_GD(10); + G_GD(11); + + //G_GD(20); + //G_GD(21); + G_GD(22); + + G_GD(25); + G_GD(26); + G_GD(27); + + G_GC(31); + } +#endif +} + +void gteCDP() { //test opcode + double RR0,GG0,BB0; +// s32 RR0,GG0,BB0; +#ifdef GTE_DUMP + static int sample = 0; sample++; +#endif + +#ifdef GTE_LOG + GTE_LOG("GTE_CDP\n"); +#endif + +#ifdef GTE_DUMP + if(sample < 100) + { + G_OP("CDP", 13); + G_SD(6); + G_SD(8); + G_SD(9); + G_SD(10); + G_SD(11); + + G_SC(13); + G_SC(14); + G_SC(15); + G_SC(16); + G_SC(17); + G_SC(18); + G_SC(19); + G_SC(20); + G_SC(21); + G_SC(22); + G_SC(23); + } +#endif + + gteFLAG = 0; + + RR0 = NC_OVERFLOW1(gteRBK + (gteLR1*gteIR1 +gteLR2*gteIR2 + gteLR3*gteIR3)); + GG0 = NC_OVERFLOW2(gteGBK + (gteLG1*gteIR1 +gteLG2*gteIR2 + gteLG3*gteIR3)); + BB0 = NC_OVERFLOW3(gteBBK + (gteLB1*gteIR1 +gteLB2*gteIR2 + gteLB3*gteIR3)); + gteMAC1 = gteR*RR0 + gteIR0*limA1S(gteRFC-gteR*RR0); + gteMAC2 = gteG*GG0 + gteIR0*limA2S(gteGFC-gteG*GG0); + gteMAC3 = gteB*BB0 + gteIR0*limA3S(gteBFC-gteB*BB0); + +/* RR0 = FNC_OVERFLOW1(gteRBK + (gteLR1*gteIR1 +gteLR2*gteIR2 + gteLR3*gteIR3)); + GG0 = FNC_OVERFLOW2(gteGBK + (gteLG1*gteIR1 +gteLG2*gteIR2 + gteLG3*gteIR3)); + BB0 = FNC_OVERFLOW3(gteBBK + (gteLB1*gteIR1 +gteLB2*gteIR2 + gteLB3*gteIR3)); + gteMAC1 = gteR*RR0 + gteIR0*FlimA1S(gteRFC-gteR*RR0); + gteMAC2 = gteG*GG0 + gteIR0*FlimA2S(gteGFC-gteG*GG0); + gteMAC3 = gteB*BB0 + gteIR0*FlimA3S(gteBFC-gteB*BB0);*/ + + MAC2IR1(); + gteRGB0 = gteRGB1; + gteRGB1 = gteRGB2; + +/* gteR2 = limB1(gteMAC1 / 16.0f); + gteG2 = limB2(gteMAC2 / 16.0f); + gteB2 = limB3(gteMAC3 / 16.0f); gteCODE2 = gteCODE;*/ + gteR2 = FlimB1(gteMAC1 >> 4); + gteG2 = FlimB2(gteMAC2 >> 4); + gteB2 = FlimB3(gteMAC3 >> 4); gteCODE2 = gteCODE; + + SUM_FLAG + +#ifdef GTE_DUMP + if(sample < 100) + { + G_GD(9); + G_GD(10); + G_GD(11); + + //G_GD(20); + //G_GD(21); + G_GD(22); + + G_GD(25); + G_GD(26); + G_GD(27); + + G_GC(31); + } +#endif +} diff --git a/libpcsxcore/gte.h b/libpcsxcore/gte.h new file mode 100644 index 00000000..b369eaae --- /dev/null +++ b/libpcsxcore/gte.h @@ -0,0 +1,57 @@ +/*************************************************************************** + * Copyright (C) 2007 Ryan Schultz, PCSX-df Team, PCSX team * + * schultz.ryan@gmail.com, http://rschultz.ath.cx/code.php * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You 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 Steet, Fifth Floor, Boston, MA 02111-1307 USA. * + ***************************************************************************/ + +#ifndef __GTE_H__ +#define __GTE_H__ + +#include "psxcommon.h" +#include "r3000a.h" + +void gteMFC2(); +void gteCFC2(); +void gteMTC2(); +void gteCTC2(); +void gteLWC2(); +void gteSWC2(); + +void gteRTPS(); +void gteOP(); +void gteNCLIP(); +void gteDPCS(); +void gteINTPL(); +void gteMVMVA(); +void gteNCDS(); +void gteNCDT(); +void gteCDP(); +void gteNCCS(); +void gteCC(); +void gteNCS(); +void gteNCT(); +void gteSQR(); +void gteDCPL(); +void gteDPCT(); +void gteAVSZ3(); +void gteAVSZ4(); +void gteRTPT(); +void gteGPF(); +void gteGPL(); +void gteNCCT(); + +#endif /* __GTE_H__ */ diff --git a/libpcsxcore/ix86/iGte.h b/libpcsxcore/ix86/iGte.h new file mode 100644 index 00000000..f9b42879 --- /dev/null +++ b/libpcsxcore/ix86/iGte.h @@ -0,0 +1,663 @@ +/*************************************************************************** + * Copyright (C) 2007 Ryan Schultz, PCSX-df Team, PCSX team * + * schultz.ryan@gmail.com, http://rschultz.ath.cx/code.php * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You 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 Steet, Fifth Floor, Boston, MA 02111-1307 USA. * + ***************************************************************************/ + +#ifndef __IGTE_H__ +#define __IGTE_H__ + +#include "../r3000a.h" +#include "../psxmem.h" + +#define CP2_FUNC(f) \ +void gte##f(); \ +static void rec##f() { \ + iFlushRegs(); \ + MOV32ItoM((u32)&psxRegs.code, (u32)psxRegs.code); \ + CALLFunc ((u32)gte##f); \ +/* branch = 2; */\ +} + +#define CP2_FUNCNC(f) \ +void gte##f(); \ +static void rec##f() { \ + iFlushRegs(); \ + CALLFunc ((u32)gte##f); \ +/* branch = 2; */\ +} + +/*CP2_FUNC(MFC2); +CP2_FUNC(MTC2); +CP2_FUNC(CFC2); +CP2_FUNC(CTC2); +CP2_FUNC(LWC2); +CP2_FUNC(SWC2);*/ + +void gteMFC2(); +static void recMFC2() { +// Rt = Cop2D->Rd + if (!_Rt_) return; + + iRegs[_Rt_].state = ST_UNK; + + switch (_Rd_) { + case 29: + MOV32ItoM((u32)&psxRegs.code, (u32)psxRegs.code); + CALLFunc ((u32)gteMFC2); + break; + + default: + MOV32MtoR(EAX, (u32)&psxRegs.CP2D.r[_Rd_]); + MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX); + break; + } +} + +void gteMTC2(); +static void recMTC2() { +// Cop2D->Rd = Rt + int fixt = 0; + +// iFlushRegs(); + + switch (_Rd_) { + case 8: case 9: case 10: case 11: + fixt = 1; break; + + case 16: case 17: case 18: case 19: + fixt = 2; break; + + case 15: + case 28: + case 30: + MOV32ItoM((u32)&psxRegs.code, (u32)psxRegs.code); + CALLFunc ((u32)gteMTC2); + break; + } + + if (IsConst(_Rt_)) { + if (fixt == 1) MOV32ItoM((u32)&psxRegs.CP2D.r[_Rd_], (s16)iRegs[_Rt_].k); + else if (fixt == 2) MOV32ItoM((u32)&psxRegs.CP2D.r[_Rd_], iRegs[_Rt_].k & 0xffff); + else MOV32ItoM((u32)&psxRegs.CP2D.r[_Rd_], iRegs[_Rt_].k); + } else { + MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]); + if (fixt == 1) MOVSX32R16toR(EAX, EAX); + else if (fixt == 2) AND32ItoR(EAX, 0xffff); + MOV32RtoM((u32)&psxRegs.CP2D.r[_Rd_], EAX); + } +} + +void gteLWC2(); +static void recLWC2() { +// Cop2D->Rt = mem[Rs + Im] (unsigned) + int fixt = 0; + + switch (_Rt_) { + case 8: case 9: case 10: case 11: + fixt = 1; break; + + case 16: case 17: case 18: case 19: + fixt = 2; break; + + case 15: + case 28: + case 30: + iFlushRegs(); + MOV32ItoM((u32)&psxRegs.code, (u32)psxRegs.code); + CALLFunc ((u32)gteLWC2); + return; + } + + 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 & 0x1fffff]); + if (fixt == 1) MOVSX32R16toR(EAX, EAX); + else if (fixt == 2) AND32ItoR(EAX, 0xffff); + MOV32RtoM((u32)&psxRegs.CP2D.r[_Rt_], EAX); + return; + } + if (t == 0x1f80 && addr < 0x1f801000) { + MOV32MtoR(EAX, (u32)&psxH[addr & 0xfff]); + if (fixt == 1) MOVSX32R16toR(EAX, EAX); + else if (fixt == 2) AND32ItoR(EAX, 0xffff); + MOV32RtoM((u32)&psxRegs.CP2D.r[_Rt_], EAX); + return; + } + } + + iPushOfB(); + CALLFunc((u32)psxMemRead32); + if (fixt == 1) MOVSX32R16toR(EAX, EAX); + else if (fixt == 2) AND32ItoR(EAX, 0xffff); + MOV32RtoM((u32)&psxRegs.CP2D.r[_Rt_], EAX); +// ADD32ItoR(ESP, 4); + resp+= 4; +} + +void gteSWC2(); +static void recSWC2() { +// mem[Rs + Im] = Rt + + switch (_Rt_) { + case 29: + iFlushRegs(); + MOV32ItoM((u32)&psxRegs.code, (u32)psxRegs.code); + CALLFunc ((u32)gteSWC2); + return; + } + + if (IsConst(_Rs_)) { + u32 addr = iRegs[_Rs_].k + _Imm_; + int t = addr >> 16; + + if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) { + MOV32MtoR(EAX, (u32)&psxRegs.CP2D.r[_Rt_]); + MOV32RtoM((u32)&psxM[addr & 0x1fffff], EAX); + return; + } + if (t == 0x1f80 && addr < 0x1f801000) { + MOV32MtoR(EAX, (u32)&psxRegs.CP2D.r[_Rt_]); + MOV32RtoM((u32)&psxH[addr & 0xfff], EAX); + return; + } + } + + PUSH32M ((u32)&psxRegs.CP2D.r[_Rt_]); + iPushOfB(); + CALLFunc((u32)psxMemWrite32); +// ADD32ItoR(ESP, 8); + resp+= 8; +} + +static void recCFC2() { +// Rt = Cop2C->Rd + if (!_Rt_) return; + + iRegs[_Rt_].state = ST_UNK; + MOV32MtoR(EAX, (u32)&psxRegs.CP2C.r[_Rd_]); + MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX); +} + +static void recCTC2() { +// Cop2C->Rd = Rt + + if (IsConst(_Rt_)) { + MOV32ItoM((u32)&psxRegs.CP2C.r[_Rd_], iRegs[_Rt_].k); + } else { + MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]); + MOV32RtoM((u32)&psxRegs.CP2C.r[_Rd_], EAX); + } +} + +CP2_FUNCNC(RTPS); +CP2_FUNC(OP); +CP2_FUNCNC(NCLIP); +CP2_FUNCNC(DPCS); +CP2_FUNCNC(INTPL); +CP2_FUNC(MVMVA); +CP2_FUNCNC(NCDS); +CP2_FUNCNC(NCDT); +CP2_FUNCNC(CDP); +CP2_FUNCNC(NCCS); +CP2_FUNCNC(CC); +CP2_FUNCNC(NCS); +CP2_FUNCNC(NCT); +CP2_FUNC(SQR); +CP2_FUNCNC(DCPL); +CP2_FUNCNC(DPCT); +CP2_FUNCNC(AVSZ3); +CP2_FUNCNC(AVSZ4); +CP2_FUNCNC(RTPT); +CP2_FUNC(GPF); +CP2_FUNC(GPL); +CP2_FUNCNC(NCCT); + +#if 0 + +#define gteVX0 ((s16*)psxRegs.CP2D.r)[0] +#define gteVY0 ((s16*)psxRegs.CP2D.r)[1] +#define gteVZ0 ((s16*)psxRegs.CP2D.r)[2] +#define gteVX1 ((s16*)psxRegs.CP2D.r)[4] +#define gteVY1 ((s16*)psxRegs.CP2D.r)[5] +#define gteVZ1 ((s16*)psxRegs.CP2D.r)[6] +#define gteVX2 ((s16*)psxRegs.CP2D.r)[8] +#define gteVY2 ((s16*)psxRegs.CP2D.r)[9] +#define gteVZ2 ((s16*)psxRegs.CP2D.r)[10] +#define gteRGB psxRegs.CP2D.r[6] +#define gteOTZ ((s16*)psxRegs.CP2D.r)[7*2] +#define gteIR0 ((s32*)psxRegs.CP2D.r)[8] +#define gteIR1 ((s32*)psxRegs.CP2D.r)[9] +#define gteIR2 ((s32*)psxRegs.CP2D.r)[10] +#define gteIR3 ((s32*)psxRegs.CP2D.r)[11] +#define gteSX0 ((s16*)psxRegs.CP2D.r)[12*2] +#define gteSY0 ((s16*)psxRegs.CP2D.r)[12*2+1] +#define gteSX1 ((s16*)psxRegs.CP2D.r)[13*2] +#define gteSY1 ((s16*)psxRegs.CP2D.r)[13*2+1] +#define gteSX2 ((s16*)psxRegs.CP2D.r)[14*2] +#define gteSY2 ((s16*)psxRegs.CP2D.r)[14*2+1] +#define gteSXP ((s16*)psxRegs.CP2D.r)[15*2] +#define gteSYP ((s16*)psxRegs.CP2D.r)[15*2+1] +#define gteSZx ((u16*)psxRegs.CP2D.r)[16*2] +#define gteSZ0 ((u16*)psxRegs.CP2D.r)[17*2] +#define gteSZ1 ((u16*)psxRegs.CP2D.r)[18*2] +#define gteSZ2 ((u16*)psxRegs.CP2D.r)[19*2] +#define gteRGB0 psxRegs.CP2D.r[20] +#define gteRGB1 psxRegs.CP2D.r[21] +#define gteRGB2 psxRegs.CP2D.r[22] +#define gteMAC0 psxRegs.CP2D.r[24] +#define gteMAC1 ((s32*)psxRegs.CP2D.r)[25] +#define gteMAC2 ((s32*)psxRegs.CP2D.r)[26] +#define gteMAC3 ((s32*)psxRegs.CP2D.r)[27] +#define gteIRGB psxRegs.CP2D.r[28] +#define gteORGB psxRegs.CP2D.r[29] +#define gteLZCS psxRegs.CP2D.r[30] +#define gteLZCR psxRegs.CP2D.r[31] + +#define gteR ((u8 *)psxRegs.CP2D.r)[6*4] +#define gteG ((u8 *)psxRegs.CP2D.r)[6*4+1] +#define gteB ((u8 *)psxRegs.CP2D.r)[6*4+2] +#define gteCODE ((u8 *)psxRegs.CP2D.r)[6*4+3] +#define gteC gteCODE + +#define gteR0 ((u8 *)psxRegs.CP2D.r)[20*4] +#define gteG0 ((u8 *)psxRegs.CP2D.r)[20*4+1] +#define gteB0 ((u8 *)psxRegs.CP2D.r)[20*4+2] +#define gteCODE0 ((u8 *)psxRegs.CP2D.r)[20*4+3] +#define gteC0 gteCODE0 + +#define gteR1 ((u8 *)psxRegs.CP2D.r)[21*4] +#define gteG1 ((u8 *)psxRegs.CP2D.r)[21*4+1] +#define gteB1 ((u8 *)psxRegs.CP2D.r)[21*4+2] +#define gteCODE1 ((u8 *)psxRegs.CP2D.r)[21*4+3] +#define gteC1 gteCODE1 + +#define gteR2 ((u8 *)psxRegs.CP2D.r)[22*4] +#define gteG2 ((u8 *)psxRegs.CP2D.r)[22*4+1] +#define gteB2 ((u8 *)psxRegs.CP2D.r)[22*4+2] +#define gteCODE2 ((u8 *)psxRegs.CP2D.r)[22*4+3] +#define gteC2 gteCODE2 + + + +#define gteR11 ((s16*)psxRegs.CP2C.r)[0] +#define gteR12 ((s16*)psxRegs.CP2C.r)[1] +#define gteR13 ((s16*)psxRegs.CP2C.r)[2] +#define gteR21 ((s16*)psxRegs.CP2C.r)[3] +#define gteR22 ((s16*)psxRegs.CP2C.r)[4] +#define gteR23 ((s16*)psxRegs.CP2C.r)[5] +#define gteR31 ((s16*)psxRegs.CP2C.r)[6] +#define gteR32 ((s16*)psxRegs.CP2C.r)[7] +#define gteR33 ((s16*)psxRegs.CP2C.r)[8] +#define gteTRX ((s32*)psxRegs.CP2C.r)[5] +#define gteTRY ((s32*)psxRegs.CP2C.r)[6] +#define gteTRZ ((s32*)psxRegs.CP2C.r)[7] +#define gteL11 ((s16*)psxRegs.CP2C.r)[16] +#define gteL12 ((s16*)psxRegs.CP2C.r)[17] +#define gteL13 ((s16*)psxRegs.CP2C.r)[18] +#define gteL21 ((s16*)psxRegs.CP2C.r)[19] +#define gteL22 ((s16*)psxRegs.CP2C.r)[20] +#define gteL23 ((s16*)psxRegs.CP2C.r)[21] +#define gteL31 ((s16*)psxRegs.CP2C.r)[22] +#define gteL32 ((s16*)psxRegs.CP2C.r)[23] +#define gteL33 ((s16*)psxRegs.CP2C.r)[24] +#define gteRBK ((s32*)psxRegs.CP2C.r)[13] +#define gteGBK ((s32*)psxRegs.CP2C.r)[14] +#define gteBBK ((s32*)psxRegs.CP2C.r)[15] +#define gteLR1 ((s16*)psxRegs.CP2C.r)[32] +#define gteLR2 ((s16*)psxRegs.CP2C.r)[33] +#define gteLR3 ((s16*)psxRegs.CP2C.r)[34] +#define gteLG1 ((s16*)psxRegs.CP2C.r)[35] +#define gteLG2 ((s16*)psxRegs.CP2C.r)[36] +#define gteLG3 ((s16*)psxRegs.CP2C.r)[37] +#define gteLB1 ((s16*)psxRegs.CP2C.r)[38] +#define gteLB2 ((s16*)psxRegs.CP2C.r)[39] +#define gteLB3 ((s16*)psxRegs.CP2C.r)[40] +#define gteRFC ((s32*)psxRegs.CP2C.r)[21] +#define gteGFC ((s32*)psxRegs.CP2C.r)[22] +#define gteBFC ((s32*)psxRegs.CP2C.r)[23] +#define gteOFX ((s32*)psxRegs.CP2C.r)[24] +#define gteOFY ((s32*)psxRegs.CP2C.r)[25] +#define gteH ((u16*)psxRegs.CP2C.r)[52] +#define gteDQA ((s16*)psxRegs.CP2C.r)[54] +#define gteDQB ((s32*)psxRegs.CP2C.r)[28] +#define gteZSF3 ((s16*)psxRegs.CP2C.r)[58] +#define gteZSF4 ((s16*)psxRegs.CP2C.r)[60] +#define gteFLAG psxRegs.CP2C.r[31] + +//#define SUM_FLAG if(gteFLAG & 0x7F87E000) gteFLAG |= 0x80000000; + +#define SUM_FLAG() { \ + TEST32ItoM((u32)>eFLAG, 0x7F87E000); \ + j8Ptr[0] = JZ8(0); \ + OR32ItoM((u32)>eFLAG, 0x80000000); \ + \ + x86SetJ8(j8Ptr[0]); \ +} + +#define LIM32X8(reg, gteout, negv, posv, flagb) { \ + CMP32ItoR(reg, negv); \ + j8Ptr[0] = JL8(0); \ + CMP32ItoR(reg, posv); \ + j8Ptr[1] = JG8(0); \ + \ + MOV8RtoM((u32)>eout, reg); \ + j8Ptr[2] = JMP8(0); \ + \ + x86SetJ8(j8Ptr[0]); \ + MOV8ItoM((u32)>eout, negv); \ + j8Ptr[3] = JMP8(0); \ + \ + x86SetJ8(j8Ptr[1]); \ + MOV8ItoM((u32)>eout, posv); \ + \ + x86SetJ8(j8Ptr[3]); \ + OR32ItoM((u32)>eFLAG, 1<<flagb); \ + \ + x86SetJ8(j8Ptr[2]); \ +} + +#define _LIM_B1(reg, gteout) LIM32X8(reg, gteout, 0, 255, 21); +#define _LIM_B2(reg, gteout) LIM32X8(reg, gteout, 0, 255, 20); +#define _LIM_B3(reg, gteout) LIM32X8(reg, gteout, 0, 255, 19); + +#define MAC2IRn(reg, ir, flagb, negv, posv) { \ +/* CMP32ItoR(reg, negv);*/ \ +/* j8Ptr[0] = JL8(0); */\ +/* CMP32ItoR(reg, posv);*/ \ +/* j8Ptr[1] = JG8(0);*/ \ + \ + MOV32RtoM((u32)&ir, reg); \ +/* j8Ptr[2] = JMP8(0);*/ \ + \ +/* x86SetJ8(j8Ptr[0]);*/ \ +/* MOV32ItoM((u32)&ir, negv);*/ \ +/* j8Ptr[3] = JMP8(0);*/ \ + \ +/* x86SetJ8(j8Ptr[1]);*/ \ +/* MOV32ItoM((u32)&ir, posv);*/ \ + \ +/* x86SetJ8(j8Ptr[3]);*/ \ +/* OR32ItoR((u32)>eFLAG, 1<<flagb);*/ \ + \ +/* x86SetJ8(j8Ptr[2]);*/ \ +} + + + +#define gte_C11 gteLR1 +#define gte_C12 gteLR2 +#define gte_C13 gteLR3 +#define gte_C21 gteLG1 +#define gte_C22 gteLG2 +#define gte_C23 gteLG3 +#define gte_C31 gteLB1 +#define gte_C32 gteLB2 +#define gte_C33 gteLB3 + + +#define _MVMVA_FUNC(vn, mx) { \ + MOVSX32M16toR(EAX, (u32)&mx##vn##1); \ + IMUL32R(EBX); \ +/* j8Ptr[0] = JO8(0);*/ \ + MOV32RtoR(ECX, EAX); \ + \ + MOVSX32M16toR(EAX, (u32)&mx##vn##2); \ + IMUL32R(EDI); \ +/* j8Ptr[1] = JO8(0);*/ \ + ADD32RtoR(ECX, EAX); \ +/* j8Ptr[2] = JO8(0);*/ \ + \ + MOVSX32M16toR(EAX, (u32)&mx##vn##3); \ + IMUL32R(ESI); \ +/* j8Ptr[3] = JO8(0);*/ \ + ADD32RtoR(ECX, EAX); \ +/* j8Ptr[4] = JO8(0);*/ \ +} + +/* SSX = (_v0) * mx##11 + (_v1) * mx##12 + (_v2) * mx##13; + SSY = (_v0) * mx##21 + (_v1) * mx##22 + (_v2) * mx##23; + SSZ = (_v0) * mx##31 + (_v1) * mx##32 + (_v2) * mx##33; */ + +#define _MVMVA_ADD(_vx, jn) { \ + ADD32MtoR(ECX, (u32)&_vx); \ +/* j8Ptr[jn] = JO8(0);*/ \ +} +/* SSX+= gteRFC; + SSY+= gteGFC; + SSZ+= gteBFC;*/ + +#define _MVMVA1(vn) { \ + switch (psxRegs.code & 0x60000) { \ + case 0x00000: /* R */ \ + _MVMVA_FUNC(vn, gteR); break; \ + case 0x20000: /* L */ \ + _MVMVA_FUNC(vn, gteL); break; \ + case 0x40000: /* C */ \ + _MVMVA_FUNC(vn, gte_C); break; \ + default: \ + return; \ + } \ +} + +#define _MVMVA_LOAD(_v0, _v1, _v2) { \ + MOVSX32M16toR(EBX, (u32)&_v0); \ + MOVSX32M16toR(EDI, (u32)&_v1); \ + MOVSX32M16toR(ESI, (u32)&_v2); \ +} + +static void recMVMVA() { + int i; + +// SysPrintf("GTE_MVMVA %lx\n", psxRegs.code & 0x1ffffff); + +/* PUSH32R(ESI); + PUSH32R(EDI); + PUSH32R(EBX); +*/ + XOR32RtoR(EAX, EAX); /* gteFLAG = 0 */ + MOV32RtoM((u32)>eFLAG, EAX); + + switch (psxRegs.code & 0x18000) { + case 0x00000: /* V0 */ + _MVMVA_LOAD(gteVX0, gteVY0, gteVZ0); break; + case 0x08000: /* V1 */ + _MVMVA_LOAD(gteVX1, gteVY1, gteVZ1); break; + case 0x10000: /* V2 */ + _MVMVA_LOAD(gteVX2, gteVY2, gteVZ2); break; + case 0x18000: /* IR */ + _MVMVA_LOAD(gteIR1, gteIR2, gteIR3); break; + } + +// MAC1 + for (i=5; i<8; i++) j8Ptr[i] = 0; + _MVMVA1(1); + + if (psxRegs.code & 0x80000) { + SAR32ItoR(ECX, 12); +// SSX /= 4096.0; SSY /= 4096.0; SSZ /= 4096.0; + } + + switch (psxRegs.code & 0x6000) { + case 0x0000: // Add TR + _MVMVA_ADD(gteTRX, 5); break; + case 0x2000: // Add BK + _MVMVA_ADD(gteRBK, 6); break; + case 0x4000: // Add FC + _MVMVA_ADD(gteRFC, 7); break; + } +/* + j8Ptr[9] = JMP8(0); + for (i=0; i<5; i++) x86SetJ8(j8Ptr[i]); + for (i=5; i<8; i++) if (j8Ptr[i]) x86SetJ8(j8Ptr[i]); + +// TEST32ItoR(EDX, 0x80000000); + OR32ItoM((u32)>eFLAG, 1<<29); + x86SetJ8(j8Ptr[9]);*/ + MOV32RtoM((u32)>eMAC1, ECX); + + if (psxRegs.code & 0x400) { + MAC2IRn(ECX, gteIR1, 24, 0, 32767); + } else { + MAC2IRn(ECX, gteIR1, 24, -32768, 32767); + } + +// MAC2 + _MVMVA1(2); + + if (psxRegs.code & 0x80000) { + SAR32ItoR(ECX, 12); +// SSX /= 4096.0; SSY /= 4096.0; SSZ /= 4096.0; + } + + switch (psxRegs.code & 0x6000) { + case 0x0000: // Add TR + _MVMVA_ADD(gteTRY, 5); break; + case 0x2000: // Add BK + _MVMVA_ADD(gteGBK, 6); break; + case 0x4000: // Add FC + _MVMVA_ADD(gteGFC, 7); break; + } + +/* for (i=0; i<5; i++) x86SetJ8(j8Ptr[i]); + for (i=5; i<8; i++) if (j8Ptr[i]) x86SetJ8(j8Ptr[i]);*/ + MOV32RtoM((u32)>eMAC2, ECX); + + if (psxRegs.code & 0x400) { + MAC2IRn(ECX, gteIR2, 23, 0, 32767); + } else { + MAC2IRn(ECX, gteIR2, 23, -32768, 32767); + } + +// MAC3 + _MVMVA1(3); + + if (psxRegs.code & 0x80000) { + SAR32ItoR(ECX, 12); +// SSX /= 4096.0; SSY /= 4096.0; SSZ /= 4096.0; + } + + switch (psxRegs.code & 0x6000) { + case 0x0000: // Add TR + _MVMVA_ADD(gteTRZ, 5); break; + case 0x2000: // Add BK + _MVMVA_ADD(gteBBK, 6); break; + case 0x4000: // Add FC + _MVMVA_ADD(gteBFC, 7); break; + } + +/* for (i=0; i<5; i++) x86SetJ8(j8Ptr[i]); + for (i=5; i<8; i++) if (j8Ptr[i]) x86SetJ8(j8Ptr[i]);*/ + MOV32RtoM((u32)>eMAC3, ECX); + + if (psxRegs.code & 0x400) { + MAC2IRn(ECX, gteIR3, 22, 0, 32767); + } else { + MAC2IRn(ECX, gteIR3, 22, -32768, 32767); + } +/* MAC2IR1() + else MAC2IR()*/ + +// SUM_FLAG(); + +/* POP32R(EBX); + POP32R(EDI); + POP32R(ESI);*/ +} + +#if 0 + +#define _GPF1(vn) { \ + MOV32MtoR(EAX, (u32)>eIR##vn); \ + IMUL32R(ECX); \ +/* MOV32RtoR(ECX, EAX); */\ +} + +static void recGPF() { +// SysPrintf("GTE_GPF %lx\n", psxRegs.code & 0x1ffffff); + + PUSH32R(EBX); + + XOR32RtoR(EBX, EBX); /* gteFLAG = 0 */ + +/* gteMAC1 = NC_OVERFLOW1(gteIR0 * gteIR1); + gteMAC2 = NC_OVERFLOW2(gteIR0 * gteIR2); + gteMAC3 = NC_OVERFLOW3(gteIR0 * gteIR3);*/ + MOV32MtoR(ECX, (u32)>eIR0); +// MAC1 + _GPF1(1); + + if (psxRegs.code & 0x80000) { + SAR32ItoR(EAX, 12); + } + MAC2IRn(EAX, gteIR1, 24, -32768, 32767); + PUSH32R(EAX); + +// MAC2 + _GPF1(2); + + if (psxRegs.code & 0x80000) { + SAR32ItoR(EAX, 12); + } + MAC2IRn(EAX, gteIR2, 23, -32768, 32767); + PUSH32R(EAX); + +// MAC3 + _GPF1(3); + + if (psxRegs.code & 0x80000) { + SAR32ItoR(EAX, 12); + } + MAC2IRn(EAX, gteIR3, 22, -32768, 32767); +// MAC2IR(); + +// gteRGB0 = gteRGB1; +// gteRGB1 = gteRGB2; + MOV32MtoR(EDX, (u32)>eRGB1); + MOV32MtoR(ECX, (u32)>eRGB2); + MOV32RtoM((u32)>eRGB0, EDX); + MOV32RtoM((u32)>eRGB1, ECX); + + POP32R(EDX); + POP32R(ECX); + SAR32ItoR(ECX, 4); + SAR32ItoR(EDX, 4); + SAR32ItoR(EAX, 4); + + _LIM_B1(ECX, gteR2); + _LIM_B2(EDX, gteG2); + _LIM_B3(EAX, gteB2); + MOV8MtoR(EAX, (u32)>eCODE); + MOV8RtoM((u32)>eCODE2, EAX); + +/* gteR2 = limB1(gteMAC1 / 16.0f); + gteG2 = limB2(gteMAC2 / 16.0f); + gteB2 = limB3(gteMAC3 / 16.0f); gteCODE2 = gteCODE;*/ + + SUM_FLAG(); + MOV32RtoM((u32)>eFLAG, EBX); + +// POP32R(EBX); +} +#endif +#endif + + +#endif /* __IGTE_H__ */ diff --git a/libpcsxcore/ix86/iR3000A.c b/libpcsxcore/ix86/iR3000A.c new file mode 100644 index 00000000..ad2e3c6e --- /dev/null +++ b/libpcsxcore/ix86/iR3000A.c @@ -0,0 +1,2898 @@ +/*************************************************************************** + * Copyright (C) 2007 Ryan Schultz, PCSX-df Team, PCSX team * + * schultz.ryan@gmail.com, http://rschultz.ath.cx/code.php * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You 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 Steet, Fifth Floor, Boston, MA 02111-1307 USA. * + ***************************************************************************/ + +/* +* i386 assembly functions for R3000A core. +*/ + +#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])(); + +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; + 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; + ADD32ItoM((u32)&psxRegs.cycle, count); + if (resp) ADD32ItoR(ESP, resp); + + PUSH32M((u32)&target); + PUSH32I(_Rt_); + CALLFunc((u32)psxDelayTest); + ADD32ItoR(ESP, 2*4); + + RET(); + return; + } + + recBSC[psxRegs.code>>26](); + + 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; + 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; + 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; + 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; + 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); +} + +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, 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 = (char*) malloc(RECMEM_SIZE); + 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); + //free(recMem); + 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) { + 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... + +/********************************************************* +* 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) 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_)) { + x86SetJ8(j8Ptr[0]); + } +} + +static void recDIVU() { +// Lo/Hi = Rs / Rt (unsigned) + +// iFlushRegs(); + + if (IsConst(_Rt_)) { + if (iRegs[_Rt_].k == 0) 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_)) { + x86SetJ8(j8Ptr[0]); + } +} +//#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 && (t & 0x1fff) != 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 && (t & 0x1fff) != 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 && (t & 0x1fff) != 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 && (t & 0x1fff) != 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; + + MOVZX32M16toR(EAX, (u32)&psxCounters[(addr >> 4) & 0x3].mode); + MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX); + return; + + case 0x1f801108: case 0x1f801118: case 0x1f801128: + if (!_Rt_) return; + iRegs[_Rt_].state = ST_UNK; + + MOVZX32M16toR(EAX, (u32)&psxCounters[(addr >> 4) & 0x3].target); + MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX); + 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 && (t & 0x1fff) != 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 && (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 = (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 && (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 = (u32 *)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 + +// 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); + } + 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); + } + 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); + } + 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 + } + } +// 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 + +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; +} + +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; +} + +/*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 (_Rd_ == 12) + OR32ItoM((u32)&psxRegs.interrupt, 0x80000000); + 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 < 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((u32)&psxRegs.pc, pc); + + iRet(); +} + +R3000Acpu psxRec = { + recInit, + recReset, + recExecute, + recExecuteBlock, + recClear, + recShutdown +}; diff --git a/libpcsxcore/ix86/ix86.c b/libpcsxcore/ix86/ix86.c new file mode 100644 index 00000000..63909be4 --- /dev/null +++ b/libpcsxcore/ix86/ix86.c @@ -0,0 +1,1759 @@ +/*************************************************************************** + * Copyright (C) 2007 Ryan Schultz, PCSX-df Team, PCSX team * + * schultz.ryan@gmail.com, http://rschultz.ath.cx/code.php * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You 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 Steet, Fifth Floor, Boston, MA 02111-1307 USA. * + ***************************************************************************/ + +/* + * ix86 core v0.5.1 + * Authors: linuzappz <linuzappz@pcsx.net> + * alexey silinov + */ + +#include "ix86.h" + +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); +} diff --git a/libpcsxcore/ix86/ix86.h b/libpcsxcore/ix86/ix86.h new file mode 100644 index 00000000..8a5550ee --- /dev/null +++ b/libpcsxcore/ix86/ix86.h @@ -0,0 +1,667 @@ +/*************************************************************************** + * Copyright (C) 2007 Ryan Schultz, PCSX-df Team, PCSX team * + * schultz.ryan@gmail.com, http://rschultz.ath.cx/code.php * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You 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 Steet, Fifth Floor, Boston, MA 02111-1307 USA. * + ***************************************************************************/ + +/* + * ix86 definitions v0.5.1 + * Authors: linuzappz <linuzappz@pcsx.net> + * alexey silinov + */ + +#ifndef __IX86_H__ +#define __IX86_H__ + +// include basic types +#include "../psxcommon.h" +#include "../r3000a.h" +#include "../psxhle.h" + +// x86Flags defines +#define X86FLAG_FPU 0x00000001 +#define X86FLAG_VME 0x00000002 +#define X86FLAG_DEBUGEXT 0x00000004 +#define X86FLAG_4MPAGE 0x00000008 +#define X86FLAG_TSC 0x00000010 +#define X86FLAG_MSR 0x00000020 +#define X86FLAG_PAE 0x00000040 +#define X86FLAG_MCHKXCP 0x00000080 +#define X86FLAG_CMPXCHG8B 0x00000100 +#define X86FLAG_APIC 0x00000200 +#define X86FLAG_SYSENTER 0x00000800 +#define X86FLAG_MTRR 0x00001000 +#define X86FLAG_GPE 0x00002000 +#define X86FLAG_MCHKARCH 0x00004000 +#define X86FLAG_CMOV 0x00008000 +#define X86FLAG_PAT 0x00010000 +#define X86FLAG_PSE36 0x00020000 +#define X86FLAG_PN 0x00040000 +#define X86FLAG_MMX 0x00800000 +#define X86FLAG_FXSAVE 0x01000000 +#define X86FLAG_SSE 0x02000000 + +// x86EFlags defines + +#define X86EFLAG_MMXEXT 0x00400000 +#define X86EFLAG_3DNOWEXT 0x40000000 +#define X86EFLAG_3DNOW 0x80000000 + +/* general defines */ +#define write8(val) *(u8 *)x86Ptr = val; x86Ptr++; +#define write16(val) *(u16*)x86Ptr = val; x86Ptr+=2; +#define write32(val) *(u32*)x86Ptr = val; x86Ptr+=4; +#define write64(val) *(u64*)x86Ptr = val; x86Ptr+=8; + +#define EAX 0 +#define EBX 3 +#define ECX 1 +#define EDX 2 +#define ESI 6 +#define EDI 7 +#define EBP 5 +#define ESP 4 + +#define MM0 0 +#define MM1 1 +#define MM2 2 +#define MM3 3 +#define MM4 4 +#define MM5 5 +#define MM6 6 +#define MM7 7 + +#define XMM0 0 +#define XMM1 1 +#define XMM2 2 +#define XMM3 3 +#define XMM4 4 +#define XMM5 5 +#define XMM6 6 +#define XMM7 7 + +s8 *x86Ptr; +u8 *j8Ptr[32]; +u32 *j32Ptr[32]; + +void x86Init(); +void x86SetPtr(char *ptr); +void x86Shutdown(); + +void x86SetJ8(u8 *j8); +void x86SetJ32(u32 *j32); +void x86Align(int bytes); + + +/********************/ +/* IX86 intructions */ +/********************/ + +/* + * scale values: + * 0 - *1 + * 1 - *2 + * 2 - *4 + * 3 - *8 + */ + +//////////////////////////////////// +// mov instructions / +//////////////////////////////////// + +/* mov r32 to r32 */ +void MOV32RtoR(int to, int from); +/* mov r32 to m32 */ +void MOV32RtoM(u32 to, int from); +/* mov m32 to r32 */ +void MOV32MtoR(int to, u32 from); +/* mov [r32] to r32 */ +void MOV32RmtoR(int to, int from); +/* mov [r32][r32*scale] to r32 */ +void MOV32RmStoR(int to, int from, int from2, int scale); +/* mov r32 to [r32] */ +void MOV32RtoRm(int to, int from); +/* mov r32 to [r32][r32*scale] */ +void MOV32RtoRmS(int to, int to2, int scale, int from); +/* mov imm32 to r32 */ +void MOV32ItoR(int to, u32 from); +/* mov imm32 to m32 */ +void MOV32ItoM(u32 to, u32 from); + +/* mov r16 to m16 */ +void MOV16RtoM(u32 to, int from); +/* mov m16 to r16 */ +void MOV16MtoR(int to, u32 from); +/* mov imm16 to m16 */ +void MOV16ItoM(u32 to, u16 from); + +/* mov r8 to m8 */ +void MOV8RtoM(u32 to, int from); +/* mov m8 to r8 */ +void MOV8MtoR(int to, u32 from); +/* mov imm8 to m8 */ +void MOV8ItoM(u32 to, u8 from); + +/* movsx r8 to r32 */ +void MOVSX32R8toR(int to, int from); +/* movsx m8 to r32 */ +void MOVSX32M8toR(int to, u32 from); +/* movsx r16 to r32 */ +void MOVSX32R16toR(int to, int from); +/* movsx m16 to r32 */ +void MOVSX32M16toR(int to, u32 from); + +/* movzx r8 to r32 */ +void MOVZX32R8toR(int to, int from); +/* movzx m8 to r32 */ +void MOVZX32M8toR(int to, u32 from); +/* movzx r16 to r32 */ +void MOVZX32R16toR(int to, int from); +/* movzx m16 to r32 */ +void MOVZX32M16toR(int to, u32 from); + +/* cmovne r32 to r32 */ +void CMOVNE32RtoR(int to, int from); +/* cmovne m32 to r32*/ +void CMOVNE32MtoR(int to, u32 from); +/* cmove r32 to r32*/ +void CMOVE32RtoR(int to, int from); +/* cmove m32 to r32*/ +void CMOVE32MtoR(int to, u32 from); +/* cmovg r32 to r32*/ +void CMOVG32RtoR(int to, int from); +/* cmovg m32 to r32*/ +void CMOVG32MtoR(int to, u32 from); +/* cmovge r32 to r32*/ +void CMOVGE32RtoR(int to, int from); +/* cmovge m32 to r32*/ +void CMOVGE32MtoR(int to, u32 from); +/* cmovl r32 to r32*/ +void CMOVL32RtoR(int to, int from); +/* cmovl m32 to r32*/ +void CMOVL32MtoR(int to, u32 from); +/* cmovle r32 to r32*/ +void CMOVLE32RtoR(int to, int from); +/* cmovle m32 to r32*/ +void CMOVLE32MtoR(int to, u32 from); + +//////////////////////////////////// +// arithmetic instructions / +//////////////////////////////////// + +/* add imm32 to r32 */ +void ADD32ItoR(int to, u32 from); +/* add imm32 to m32 */ +void ADD32ItoM(u32 to, u32 from); +/* add r32 to r32 */ +void ADD32RtoR(int to, int from); +/* add r32 to m32 */ +void ADD32RtoM(u32 to, int from); +/* add m32 to r32 */ +void ADD32MtoR(int to, u32 from); + +/* adc imm32 to r32 */ +void ADC32ItoR(int to, u32 from); +/* adc r32 to r32 */ +void ADC32RtoR(int to, int from); +/* adc m32 to r32 */ +void ADC32MtoR(int to, u32 from); + +/* inc r32 */ +void INC32R(int to); +/* inc m32 */ +void INC32M(u32 to); + +/* sub imm32 to r32 */ +void SUB32ItoR(int to, u32 from); +/* sub r32 to r32 */ +void SUB32RtoR(int to, int from); +/* sub m32 to r32 */ +void SUB32MtoR(int to, u32 from); + +/* sbb imm32 to r32 */ +void SBB32ItoR(int to, u32 from); +/* sbb r32 to r32 */ +void SBB32RtoR(int to, int from); +/* sbb m32 to r32 */ +void SBB32MtoR(int to, u32 from); + +/* dec r32 */ +void DEC32R(int to); +/* dec m32 */ +void DEC32M(u32 to); + +/* mul eax by r32 to edx:eax */ +void MUL32R(int from); +/* mul eax by m32 to edx:eax */ +void MUL32M(u32 from); + +/* imul eax by r32 to edx:eax */ +void IMUL32R(int from); +/* imul eax by m32 to edx:eax */ +void IMUL32M(u32 from); +/* imul r32 by r32 to r32 */ +void IMUL32RtoR(int to, int from); + +/* div eax by r32 to edx:eax */ +void DIV32R(int from); +/* div eax by m32 to edx:eax */ +void DIV32M(u32 from); + +/* idiv eax by r32 to edx:eax */ +void IDIV32R(int from); +/* idiv eax by m32 to edx:eax */ +void IDIV32M(u32 from); + +//////////////////////////////////// +// shifting instructions / +//////////////////////////////////// + +/* shl imm8 to r32 */ +void SHL32ItoR(int to, u8 from); +/* shl cl to r32 */ +void SHL32CLtoR(int to); + +/* shr imm8 to r32 */ +void SHR32ItoR(int to, u8 from); +/* shr cl to r32 */ +void SHR32CLtoR(int to); + +/* sar imm8 to r32 */ +void SAR32ItoR(int to, u8 from); +/* sar cl to r32 */ +void SAR32CLtoR(int to); + +/* sal imm8 to r32 */ +#define SAL32ItoR SHL32ItoR +/* sal cl to r32 */ +#define SAL32CLtoR SHL32CLtoR + +// logical instructions + +/* or imm32 to r32 */ +void OR32ItoR(int to, u32 from); +/* or imm32 to m32 */ +void OR32ItoM(u32 to, u32 from); +/* or r32 to r32 */ +void OR32RtoR(int to, int from); +/* or r32 to m32 */ +void OR32RtoM(u32 to, int from); +/* or m32 to r32 */ +void OR32MtoR(int to, u32 from); + +/* xor imm32 to r32 */ +void XOR32ItoR(int to, u32 from); +/* xor imm32 to m32 */ +void XOR32ItoM(u32 to, u32 from); +/* xor r32 to r32 */ +void XOR32RtoR(int to, int from); +/* xor r32 to m32 */ +void XOR32RtoM(u32 to, int from); +/* xor m32 to r32 */ +void XOR32MtoR(int to, u32 from); + +/* and imm32 to r32 */ +void AND32ItoR(int to, u32 from); +/* and imm32 to m32 */ +void AND32ItoM(u32 to, u32 from); +/* and r32 to r32 */ +void AND32RtoR(int to, int from); +/* and r32 to m32 */ +void AND32RtoM(u32 to, int from); +/* and m32 to r32 */ +void AND32MtoR(int to, u32 from); + +/* not r32 */ +void NOT32R(int from); +/* neg r32 */ +void NEG32R(int from); + +//////////////////////////////////// +// jump instructions / +//////////////////////////////////// + +/* jmp rel8 */ +u8* JMP8(u8 to); + +/* jmp rel32 */ +u32* JMP32(u32 to); +/* jmp r32 */ +void JMP32R(int 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); +/* jl rel8 */ +u8* JL8(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); + +/* 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); +/* 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); + +/* call func */ +void CALLFunc(u32 func); // based on CALL32 +/* call rel32 */ +void CALL32(u32 to); +/* call r32 */ +void CALL32R(int to); +/* call m32 */ +void CALL32M(u32 to); + +//////////////////////////////////// +// misc instructions / +//////////////////////////////////// + +/* cmp imm32 to r32 */ +void CMP32ItoR(int to, u32 from); +/* cmp imm32 to m32 */ +void CMP32ItoM(u32 to, u32 from); +/* cmp r32 to r32 */ +void CMP32RtoR(int to, int from); +/* cmp m32 to r32 */ +void CMP32MtoR(int to, u32 from); + +/* test imm32 to r32 */ +void TEST32ItoR(int to, u32 from); +/* test r32 to r32 */ +void TEST32RtoR(int to, int from); +/* sets r8 */ +void SETS8R(int to); +/* setl r8 */ +void SETL8R(int to); +/* setb r8 */ +void SETB8R(int to); + +/* cbw */ +void CBW(); +/* cwd */ +void CWD(); +/* cdq */ +void CDQ(); + +/* push r32 */ +void PUSH32R(int from); +/* push m32 */ +void PUSH32M(u32 from); +/* push imm32 */ +void PUSH32I(u32 from); + +/* pop r32 */ +void POP32R(int from); + +/* pushad */ +void PUSHA32(); +/* popad */ +void POPA32(); + +/* ret */ +void RET(); + +/********************/ +/* FPU instructions */ +/********************/ + +/* fild m32 to fpu reg stack */ +void FILD32(u32 from); +/* fistp m32 from fpu reg stack */ +void FISTP32(u32 from); +/* fld m32 to fpu reg stack */ +void FLD32(u32 from); +/* fstp m32 from fpu reg stack */ +void FSTP32(u32 to); + +/* fldcw fpu control word from m16 */ +void FLDCW(u32 from); +/* fstcw fpu control word to m16 */ +void FNSTCW(u32 to); + +/* fadd m32 to fpu reg stack */ +void FADD32(u32 from); +/* fsub m32 to fpu reg stack */ +void FSUB32(u32 from); +/* fmul m32 to fpu reg stack */ +void FMUL32(u32 from); +/* fdiv m32 to fpu reg stack */ +void FDIV32(u32 from); +/* fabs fpu reg stack */ +void FABS(); +/* fsqrt fpu reg stack */ +void FSQRT(); +/* fchs fpu reg stack */ +void FCHS(); + +/********************/ +/* MMX instructions */ +/********************/ + +// r64 = mm + +/* movq m64 to r64 */ +void MOVQMtoR(int to, u32 from); +/* movq r64 to m64 */ +void MOVQRtoM(u32 to, int from); + +/* pand r64 to r64 */ +void PANDRtoR(int to, int from); +/* pand m64 to r64 */ +void PANDMtoR(int to, u32 from); + +/* pandn r64 to r64 */ +void PANDNRtoR(int to, int from); + +/* pandn r64 to r64 */ +void PANDNMtoR(int to, u32 from); + +/* por r64 to r64 */ +void PORRtoR(int to, int from); +/* por m64 to r64 */ +void PORMtoR(int to, u32 from); + +/* pxor r64 to r64 */ +void PXORRtoR(int to, int from); +/* pxor m64 to r64 */ +void PXORMtoR(int to, u32 from); + +/* psllq r64 to r64 */ +void PSLLQRtoR(int to, int from); +/* psllq m64 to r64 */ +void PSLLQMtoR(int to, u32 from); +/* psllq imm8 to r64 */ +void PSLLQItoR(int to, u8 from); + +/* psrlq r64 to r64 */ +void PSRLQRtoR(int to, int from); +/* psrlq m64 to r64 */ +void PSRLQMtoR(int to, u32 from); +/* psrlq imm8 to r64 */ +void PSRLQItoR(int to, u8 from); + +/* paddusb r64 to r64 */ +void PADDUSBRtoR(int to, int from); +/* paddusb m64 to r64 */ +void PADDUSBMtoR(int to, u32 from); +/* paddusw r64 to r64 */ +void PADDUSWRtoR(int to, int from); +/* paddusw m64 to r64 */ +void PADDUSWMtoR(int to, u32 from); + +/* paddb r64 to r64 */ +void PADDBRtoR(int to, int from); +/* paddb m64 to r64 */ +void PADDBMtoR(int to, u32 from); +/* paddw r64 to r64 */ +void PADDWRtoR(int to, int from); +/* paddw m64 to r64 */ +void PADDWMtoR(int to, u32 from); +/* paddd r64 to r64 */ +void PADDDRtoR(int to, int from); +/* paddd m64 to r64 */ +void PADDDMtoR(int to, u32 from); + +/* emms */ +void EMMS(); +void FEMMS(); +void BT32ItoR(int to,int from); +void RCR32ItoR(int to,int from); + +//Basara:changed +void PADDSBRtoR(int to, int from); +void PADDSWRtoR(int to, int from); +void PADDSDRtoR(int to, int from); +void PSUBSBRtoR(int to, int from); +void PSUBSWRtoR(int to, int from); +void PSUBSDRtoR(int to, int from); + +void PSUBBRtoR(int to, int from); +void PSUBWRtoR(int to, int from); +void PSUBDRtoR(int to, int from); + +void MOVQ64ItoR(int reg,u64 i); //Prototype.Todo add all consts to end of block.not after jr $+8 + +void PMAXSWRtoR(int to,int from); +void PMINSWRtoR(int to,int from); + +void PCMPEQBRtoR(int to,int from); +void PCMPEQWRtoR(int to,int from); +void PCMPEQDRtoR(int to,int from); + +void PCMPGTBRtoR(int to,int from); +void PCMPGTWRtoR(int to,int from); +void PCMPGTDRtoR(int to,int from); + +void PSRLWItoR(int to,int from); +void PSRLDItoR(int to,int from); +void PSLLWItoR(int to,int from); +void PSLLDItoR(int to,int from); +void PSRAWItoR(int to,int from); +void PSRADItoR(int to,int from); + +//Added:basara 11.01.2003 +void FCOMP32(u32 from); +void FNSTSWtoAX(); +void SETNZ8R(int to); + +//Added:basara 14.01.2003 +void PFCMPEQMtoR(int to,int from); +void PFCMPGTMtoR(int to,int from); +void PFCMPGEMtoR(int to,int from); + +void PFADDMtoR(int to,int from); +void PFADDRtoR(int to,int from); + +void PFSUBMtoR(int to,int from); +void PFSUBRtoR(int to,int from); + +void PFMULMtoR(int to,int from); +void PFMULRtoR(int to,int from); + +void PFRCPMtoR(int to,int from); +void PFRCPRtoR(int to,int from); +void PFRCPIT1RtoR(int to,int from); +void PFRCPIT2RtoR(int to,int from); + +void PFRSQRTRtoR(int to,int from); +void PFRSQIT1RtoR(int to,int from); + +void PF2IDMtoR(int to,int from); +void PF2IDRtoR(int to,int from); +void PI2FDMtoR(int to,int from); +void PI2FDRtoR(int to,int from); + +void PFMAXMtoR(int to,int from); +void PFMAXRtoR(int to,int from); +void PFMINMtoR(int to,int from); +void PFMINRtoR(int to,int from); + +void MOVDMtoR(int to, u32 from); +void MOVDRtoM(u32 to, int from); +void MOVD32RtoR(int to, int from); +void MOVD64RtoR(int to, int from); + +void MOVQRtoR(int to,int from); + +//if to==from MMLO=MMHI +void PUNPCKHDQRtoR(int to,int from); + +//if to==from MMHI=MMLO +void PUNPCKLDQRtoR(int to,int from); + +/* + SSE intructions +*/ +void MOVAPSMtoR(int to,int from); +void MOVAPSRtoM(int to,int from); +void MOVAPSRtoR(int to,int from); + +void ORPSMtoR(int to,int from); +void ORPSRtoR(int to,int from); + +void XORPSMtoR(int to,int from); +void XORPSRtoR(int to,int from); + +void ANDPSMtoR(int to,int from); +void ANDPSRtoR(int to,int from); + +#endif /* __IX86_H__ */ diff --git a/libpcsxcore/ix86_64/README b/libpcsxcore/ix86_64/README new file mode 100644 index 00000000..23a798bf --- /dev/null +++ b/libpcsxcore/ix86_64/README @@ -0,0 +1,4 @@ +This is the AMD64 dynamic recompiler. +Made from opcodes from PCSX2 0.9.3 and the x86 recompiler modified to fit. ie. currently no AMD64/SSE specific code advantages. + +Note that this recompiler currently requires all variables, data heaps, function pointers, etc to be within a 4 Gig range of each other. While this is currently the case through luck and dirty hacks, a proper fix should be implemented. diff --git a/libpcsxcore/ix86_64/iGte.h b/libpcsxcore/ix86_64/iGte.h new file mode 100644 index 00000000..07f55542 --- /dev/null +++ b/libpcsxcore/ix86_64/iGte.h @@ -0,0 +1,672 @@ +/*************************************************************************** + * Copyright (C) 2007 Ryan Schultz, PCSX-df Team, PCSX team * + * schultz.ryan@gmail.com, http://rschultz.ath.cx/code.php * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You 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 Steet, Fifth Floor, Boston, MA 02111-1307 USA. * + ***************************************************************************/ + +#ifndef __IGTE_H__ +#define __IGTE_H__ + +#include "../r3000a.h" +#include "../psxmem.h" + +#define CP2_FUNC(f) \ +void gte##f(); \ +static void rec##f() { \ + iFlushRegs(); \ + MOV32ItoM((uptr)&psxRegs.code, (u32)psxRegs.code); \ + CALLFunc((uptr)gte##f); \ +/* branch = 2; */\ +} + +#define CP2_FUNCNC(f) \ +void gte##f(); \ +static void rec##f() { \ + iFlushRegs(); \ + CALLFunc((uptr)gte##f); \ +/* branch = 2; */\ +} + + +#if 0 +CP2_FUNC(MFC2); +CP2_FUNC(MTC2); +CP2_FUNC(CFC2); +CP2_FUNC(CTC2); +CP2_FUNC(LWC2); +CP2_FUNC(SWC2); +#endif + +#if 1 +void gteMFC2(); +static void recMFC2() { +// Rt = Cop2D->Rd + if (!_Rt_) return; + + iRegs[_Rt_].state = ST_UNK; + + switch (_Rd_) { + case 29: + MOV32ItoM((uptr)&psxRegs.code, (u32)psxRegs.code); + CALLFunc((uptr)gteMFC2); + break; + + default: + MOV32MtoR(EAX, (uptr)&psxRegs.CP2D.r[_Rd_]); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX); + break; + } +} + +void gteMTC2(); +static void recMTC2() { +// Cop2D->Rd = Rt + int fixt = 0; + +// iFlushRegs(); + + switch (_Rd_) { + case 8: case 9: case 10: case 11: + fixt = 1; break; + + case 16: case 17: case 18: case 19: + fixt = 2; break; + + case 15: + case 28: + case 30: + MOV32ItoM((uptr)&psxRegs.code, (u32)psxRegs.code); + CALLFunc((uptr)gteMTC2); + break; + } + + if (IsConst(_Rt_)) { + if (fixt == 1) MOV32ItoM((uptr)&psxRegs.CP2D.r[_Rd_], (s16)iRegs[_Rt_].k); + else if (fixt == 2) MOV32ItoM((uptr)&psxRegs.CP2D.r[_Rd_], iRegs[_Rt_].k & 0xffff); + else MOV32ItoM((uptr)&psxRegs.CP2D.r[_Rd_], iRegs[_Rt_].k); + } else { + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]); + if (fixt == 1) MOVSX32R16toR(EAX, EAX); + else if (fixt == 2) AND32ItoR(EAX, 0xffff); + MOV32RtoM((uptr)&psxRegs.CP2D.r[_Rd_], EAX); + } +} + +void gteLWC2(); +static void recLWC2() { +// Cop2D->Rt = mem[Rs + Im] (unsigned) + int fixt = 0; + + switch (_Rt_) { + case 8: case 9: case 10: case 11: + fixt = 1; break; + + case 16: case 17: case 18: case 19: + fixt = 2; break; + + case 15: + case 28: + case 30: + iFlushRegs(); + MOV32ItoM((uptr)&psxRegs.code, (u32)psxRegs.code); + CALLFunc((uptr)gteLWC2); + return; + } + + 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 & 0x1fffff]); + if (fixt == 1) MOVSX32R16toR(EAX, EAX); + else if (fixt == 2) AND32ItoR(EAX, 0xffff); + MOV32RtoM((uptr)&psxRegs.CP2D.r[_Rt_], EAX); + return; + } + if (t == 0x1f80 && addr < 0x1f801000) { + MOV32MtoR(EAX, (uptr)&psxH[addr & 0xfff]); + if (fixt == 1) MOVSX32R16toR(EAX, EAX); + else if (fixt == 2) AND32ItoR(EAX, 0xffff); + MOV32RtoM((uptr)&psxRegs.CP2D.r[_Rt_], EAX); + return; + } + } + + //iPushOfB(); + SetArg_OfB(X86ARG1); + CALLFunc((uptr)psxMemRead32); + if (fixt == 1) MOVSX32R16toR(EAX, EAX); + else if (fixt == 2) AND32ItoR(EAX, 0xffff); + MOV32RtoM((uptr)&psxRegs.CP2D.r[_Rt_], EAX); +// ADD32ItoR(ESP, 4); + //resp+= 4; +} + +void gteSWC2(); +static void recSWC2() { +// mem[Rs + Im] = Rt + + switch (_Rt_) { + case 29: + iFlushRegs(); + MOV32ItoM((uptr)&psxRegs.code, (u32)psxRegs.code); + CALLFunc((uptr)gteSWC2); + return; + } + + if (IsConst(_Rs_)) { + u32 addr = iRegs[_Rs_].k + _Imm_; + int t = addr >> 16; + + if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) { + MOV32MtoR(EAX, (uptr)&psxRegs.CP2D.r[_Rt_]); + MOV32RtoM((uptr)&psxM[addr & 0x1fffff], EAX); + return; + } + if (t == 0x1f80 && addr < 0x1f801000) { + MOV32MtoR(EAX, (uptr)&psxRegs.CP2D.r[_Rt_]); + MOV32RtoM((uptr)&psxH[addr & 0xfff], EAX); + return; + } + } + + //PUSH64M ((uptr)&psxRegs.CP2D.r[_Rt_]); + MOV32MtoR(X86ARG2, (uptr)&psxRegs.CP2D.r[_Rt_]); + //iPushOfB(); + SetArg_OfB(X86ARG1); + CALLFunc((uptr)psxMemWrite32); +// ADD32ItoR(ESP, 8); + //resp+= 8; +} + +static void recCFC2() { +// Rt = Cop2C->Rd + if (!_Rt_) return; + + iRegs[_Rt_].state = ST_UNK; + MOV32MtoR(EAX, (uptr)&psxRegs.CP2C.r[_Rd_]); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX); +} + +static void recCTC2() { +// Cop2C->Rd = Rt + + if (IsConst(_Rt_)) { + MOV32ItoM((uptr)&psxRegs.CP2C.r[_Rd_], iRegs[_Rt_].k); + } else { + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]); + MOV32RtoM((uptr)&psxRegs.CP2C.r[_Rd_], EAX); + } +} + +#endif + +CP2_FUNCNC(RTPS); +CP2_FUNC(OP); +CP2_FUNCNC(NCLIP); +CP2_FUNCNC(DPCS); +CP2_FUNCNC(INTPL); +CP2_FUNC(MVMVA); +CP2_FUNCNC(NCDS); +CP2_FUNCNC(NCDT); +CP2_FUNCNC(CDP); +CP2_FUNCNC(NCCS); +CP2_FUNCNC(CC); +CP2_FUNCNC(NCS); +CP2_FUNCNC(NCT); +CP2_FUNC(SQR); +CP2_FUNCNC(DCPL); +CP2_FUNCNC(DPCT); +CP2_FUNCNC(AVSZ3); +CP2_FUNCNC(AVSZ4); +CP2_FUNCNC(RTPT); +CP2_FUNC(GPF); +CP2_FUNC(GPL); +CP2_FUNCNC(NCCT); + +#if 0 + +#define gteVX0 ((s16*)psxRegs.CP2D.r)[0] +#define gteVY0 ((s16*)psxRegs.CP2D.r)[1] +#define gteVZ0 ((s16*)psxRegs.CP2D.r)[2] +#define gteVX1 ((s16*)psxRegs.CP2D.r)[4] +#define gteVY1 ((s16*)psxRegs.CP2D.r)[5] +#define gteVZ1 ((s16*)psxRegs.CP2D.r)[6] +#define gteVX2 ((s16*)psxRegs.CP2D.r)[8] +#define gteVY2 ((s16*)psxRegs.CP2D.r)[9] +#define gteVZ2 ((s16*)psxRegs.CP2D.r)[10] +#define gteRGB psxRegs.CP2D.r[6] +#define gteOTZ ((s16*)psxRegs.CP2D.r)[7*2] +#define gteIR0 ((s32*)psxRegs.CP2D.r)[8] +#define gteIR1 ((s32*)psxRegs.CP2D.r)[9] +#define gteIR2 ((s32*)psxRegs.CP2D.r)[10] +#define gteIR3 ((s32*)psxRegs.CP2D.r)[11] +#define gteSX0 ((s16*)psxRegs.CP2D.r)[12*2] +#define gteSY0 ((s16*)psxRegs.CP2D.r)[12*2+1] +#define gteSX1 ((s16*)psxRegs.CP2D.r)[13*2] +#define gteSY1 ((s16*)psxRegs.CP2D.r)[13*2+1] +#define gteSX2 ((s16*)psxRegs.CP2D.r)[14*2] +#define gteSY2 ((s16*)psxRegs.CP2D.r)[14*2+1] +#define gteSXP ((s16*)psxRegs.CP2D.r)[15*2] +#define gteSYP ((s16*)psxRegs.CP2D.r)[15*2+1] +#define gteSZx ((u16*)psxRegs.CP2D.r)[16*2] +#define gteSZ0 ((u16*)psxRegs.CP2D.r)[17*2] +#define gteSZ1 ((u16*)psxRegs.CP2D.r)[18*2] +#define gteSZ2 ((u16*)psxRegs.CP2D.r)[19*2] +#define gteRGB0 psxRegs.CP2D.r[20] +#define gteRGB1 psxRegs.CP2D.r[21] +#define gteRGB2 psxRegs.CP2D.r[22] +#define gteMAC0 psxRegs.CP2D.r[24] +#define gteMAC1 ((s32*)psxRegs.CP2D.r)[25] +#define gteMAC2 ((s32*)psxRegs.CP2D.r)[26] +#define gteMAC3 ((s32*)psxRegs.CP2D.r)[27] +#define gteIRGB psxRegs.CP2D.r[28] +#define gteORGB psxRegs.CP2D.r[29] +#define gteLZCS psxRegs.CP2D.r[30] +#define gteLZCR psxRegs.CP2D.r[31] + +#define gteR ((u8 *)psxRegs.CP2D.r)[6*4] +#define gteG ((u8 *)psxRegs.CP2D.r)[6*4+1] +#define gteB ((u8 *)psxRegs.CP2D.r)[6*4+2] +#define gteCODE ((u8 *)psxRegs.CP2D.r)[6*4+3] +#define gteC gteCODE + +#define gteR0 ((u8 *)psxRegs.CP2D.r)[20*4] +#define gteG0 ((u8 *)psxRegs.CP2D.r)[20*4+1] +#define gteB0 ((u8 *)psxRegs.CP2D.r)[20*4+2] +#define gteCODE0 ((u8 *)psxRegs.CP2D.r)[20*4+3] +#define gteC0 gteCODE0 + +#define gteR1 ((u8 *)psxRegs.CP2D.r)[21*4] +#define gteG1 ((u8 *)psxRegs.CP2D.r)[21*4+1] +#define gteB1 ((u8 *)psxRegs.CP2D.r)[21*4+2] +#define gteCODE1 ((u8 *)psxRegs.CP2D.r)[21*4+3] +#define gteC1 gteCODE1 + +#define gteR2 ((u8 *)psxRegs.CP2D.r)[22*4] +#define gteG2 ((u8 *)psxRegs.CP2D.r)[22*4+1] +#define gteB2 ((u8 *)psxRegs.CP2D.r)[22*4+2] +#define gteCODE2 ((u8 *)psxRegs.CP2D.r)[22*4+3] +#define gteC2 gteCODE2 + + + +#define gteR11 ((s16*)psxRegs.CP2C.r)[0] +#define gteR12 ((s16*)psxRegs.CP2C.r)[1] +#define gteR13 ((s16*)psxRegs.CP2C.r)[2] +#define gteR21 ((s16*)psxRegs.CP2C.r)[3] +#define gteR22 ((s16*)psxRegs.CP2C.r)[4] +#define gteR23 ((s16*)psxRegs.CP2C.r)[5] +#define gteR31 ((s16*)psxRegs.CP2C.r)[6] +#define gteR32 ((s16*)psxRegs.CP2C.r)[7] +#define gteR33 ((s16*)psxRegs.CP2C.r)[8] +#define gteTRX ((s32*)psxRegs.CP2C.r)[5] +#define gteTRY ((s32*)psxRegs.CP2C.r)[6] +#define gteTRZ ((s32*)psxRegs.CP2C.r)[7] +#define gteL11 ((s16*)psxRegs.CP2C.r)[16] +#define gteL12 ((s16*)psxRegs.CP2C.r)[17] +#define gteL13 ((s16*)psxRegs.CP2C.r)[18] +#define gteL21 ((s16*)psxRegs.CP2C.r)[19] +#define gteL22 ((s16*)psxRegs.CP2C.r)[20] +#define gteL23 ((s16*)psxRegs.CP2C.r)[21] +#define gteL31 ((s16*)psxRegs.CP2C.r)[22] +#define gteL32 ((s16*)psxRegs.CP2C.r)[23] +#define gteL33 ((s16*)psxRegs.CP2C.r)[24] +#define gteRBK ((s32*)psxRegs.CP2C.r)[13] +#define gteGBK ((s32*)psxRegs.CP2C.r)[14] +#define gteBBK ((s32*)psxRegs.CP2C.r)[15] +#define gteLR1 ((s16*)psxRegs.CP2C.r)[32] +#define gteLR2 ((s16*)psxRegs.CP2C.r)[33] +#define gteLR3 ((s16*)psxRegs.CP2C.r)[34] +#define gteLG1 ((s16*)psxRegs.CP2C.r)[35] +#define gteLG2 ((s16*)psxRegs.CP2C.r)[36] +#define gteLG3 ((s16*)psxRegs.CP2C.r)[37] +#define gteLB1 ((s16*)psxRegs.CP2C.r)[38] +#define gteLB2 ((s16*)psxRegs.CP2C.r)[39] +#define gteLB3 ((s16*)psxRegs.CP2C.r)[40] +#define gteRFC ((s32*)psxRegs.CP2C.r)[21] +#define gteGFC ((s32*)psxRegs.CP2C.r)[22] +#define gteBFC ((s32*)psxRegs.CP2C.r)[23] +#define gteOFX ((s32*)psxRegs.CP2C.r)[24] +#define gteOFY ((s32*)psxRegs.CP2C.r)[25] +#define gteH ((u16*)psxRegs.CP2C.r)[52] +#define gteDQA ((s16*)psxRegs.CP2C.r)[54] +#define gteDQB ((s32*)psxRegs.CP2C.r)[28] +#define gteZSF3 ((s16*)psxRegs.CP2C.r)[58] +#define gteZSF4 ((s16*)psxRegs.CP2C.r)[60] +#define gteFLAG psxRegs.CP2C.r[31] + +//#define SUM_FLAG if(gteFLAG & 0x7F87E000) gteFLAG |= 0x80000000; + +#define SUM_FLAG() { \ + TEST32ItoM((uptr)>eFLAG, 0x7F87E000); \ + j8Ptr[0] = JZ8(0); \ + OR32ItoM((uptr)>eFLAG, 0x80000000); \ + \ + x86SetJ8(j8Ptr[0]); \ +} + +#define LIM32X8(reg, gteout, negv, posv, flagb) { \ + CMP32ItoR(reg, negv); \ + j8Ptr[0] = JL8(0); \ + CMP32ItoR(reg, posv); \ + j8Ptr[1] = JG8(0); \ + \ + MOV8RtoM((uptr)>eout, reg); \ + j8Ptr[2] = JMP8(0); \ + \ + x86SetJ8(j8Ptr[0]); \ + MOV8ItoM((uptr)>eout, negv); \ + j8Ptr[3] = JMP8(0); \ + \ + x86SetJ8(j8Ptr[1]); \ + MOV8ItoM((uptr)>eout, posv); \ + \ + x86SetJ8(j8Ptr[3]); \ + OR32ItoM((uptr)>eFLAG, 1<<flagb); \ + \ + x86SetJ8(j8Ptr[2]); \ +} + +#define _LIM_B1(reg, gteout) LIM32X8(reg, gteout, 0, 255, 21); +#define _LIM_B2(reg, gteout) LIM32X8(reg, gteout, 0, 255, 20); +#define _LIM_B3(reg, gteout) LIM32X8(reg, gteout, 0, 255, 19); + +#define MAC2IRn(reg, ir, flagb, negv, posv) { \ +/* CMP32ItoR(reg, negv);*/ \ +/* j8Ptr[0] = JL8(0); */\ +/* CMP32ItoR(reg, posv);*/ \ +/* j8Ptr[1] = JG8(0);*/ \ + \ + MOV32RtoM((uptr)&ir, reg); \ +/* j8Ptr[2] = JMP8(0);*/ \ + \ +/* x86SetJ8(j8Ptr[0]);*/ \ +/* MOV32ItoM((uptr)&ir, negv);*/ \ +/* j8Ptr[3] = JMP8(0);*/ \ + \ +/* x86SetJ8(j8Ptr[1]);*/ \ +/* MOV32ItoM((uptr)&ir, posv);*/ \ + \ +/* x86SetJ8(j8Ptr[3]);*/ \ +/* OR32ItoR((uptr)>eFLAG, 1<<flagb);*/ \ + \ +/* x86SetJ8(j8Ptr[2]);*/ \ +} + + + +#define gte_C11 gteLR1 +#define gte_C12 gteLR2 +#define gte_C13 gteLR3 +#define gte_C21 gteLG1 +#define gte_C22 gteLG2 +#define gte_C23 gteLG3 +#define gte_C31 gteLB1 +#define gte_C32 gteLB2 +#define gte_C33 gteLB3 + + +#define _MVMVA_FUNC(vn, mx) { \ + MOVSX32M16toR(EAX, (uptr)&mx##vn##1); \ + IMUL32R(EBX); \ +/* j8Ptr[0] = JO8(0);*/ \ + MOV32RtoR(ECX, EAX); \ + \ + MOVSX32M16toR(EAX, (uptr)&mx##vn##2); \ + IMUL32R(EDI); \ +/* j8Ptr[1] = JO8(0);*/ \ + ADD32RtoR(ECX, EAX); \ +/* j8Ptr[2] = JO8(0);*/ \ + \ + MOVSX32M16toR(EAX, (uptr)&mx##vn##3); \ + IMUL32R(ESI); \ +/* j8Ptr[3] = JO8(0);*/ \ + ADD32RtoR(ECX, EAX); \ +/* j8Ptr[4] = JO8(0);*/ \ +} + +/* SSX = (_v0) * mx##11 + (_v1) * mx##12 + (_v2) * mx##13; + SSY = (_v0) * mx##21 + (_v1) * mx##22 + (_v2) * mx##23; + SSZ = (_v0) * mx##31 + (_v1) * mx##32 + (_v2) * mx##33; */ + +#define _MVMVA_ADD(_vx, jn) { \ + ADD32MtoR(ECX, (uptr)&_vx); \ +/* j8Ptr[jn] = JO8(0);*/ \ +} +/* SSX+= gteRFC; + SSY+= gteGFC; + SSZ+= gteBFC;*/ + +#define _MVMVA1(vn) { \ + switch (psxRegs.code & 0x60000) { \ + case 0x00000: /* R */ \ + _MVMVA_FUNC(vn, gteR); break; \ + case 0x20000: /* L */ \ + _MVMVA_FUNC(vn, gteL); break; \ + case 0x40000: /* C */ \ + _MVMVA_FUNC(vn, gte_C); break; \ + default: \ + return; \ + } \ +} + +#define _MVMVA_LOAD(_v0, _v1, _v2) { \ + MOVSX32M16toR(EBX, (uptr)&_v0); \ + MOVSX32M16toR(EDI, (uptr)&_v1); \ + MOVSX32M16toR(ESI, (uptr)&_v2); \ +} + +static void recMVMVA() { + int i; + +// SysPrintf("GTE_MVMVA %lx\n", psxRegs.code & 0x1ffffff); + +/* PUSH32R(ESI); + PUSH32R(EDI); + PUSH32R(EBX); +*/ + XOR32RtoR(EAX, EAX); /* gteFLAG = 0 */ + MOV32RtoM((uptr)>eFLAG, EAX); + + switch (psxRegs.code & 0x18000) { + case 0x00000: /* V0 */ + _MVMVA_LOAD(gteVX0, gteVY0, gteVZ0); break; + case 0x08000: /* V1 */ + _MVMVA_LOAD(gteVX1, gteVY1, gteVZ1); break; + case 0x10000: /* V2 */ + _MVMVA_LOAD(gteVX2, gteVY2, gteVZ2); break; + case 0x18000: /* IR */ + _MVMVA_LOAD(gteIR1, gteIR2, gteIR3); break; + } + +// MAC1 + for (i=5; i<8; i++) j8Ptr[i] = 0; + _MVMVA1(1); + + if (psxRegs.code & 0x80000) { + SAR32ItoR(ECX, 12); +// SSX /= 4096.0; SSY /= 4096.0; SSZ /= 4096.0; + } + + switch (psxRegs.code & 0x6000) { + case 0x0000: // Add TR + _MVMVA_ADD(gteTRX, 5); break; + case 0x2000: // Add BK + _MVMVA_ADD(gteRBK, 6); break; + case 0x4000: // Add FC + _MVMVA_ADD(gteRFC, 7); break; + } +/* + j8Ptr[9] = JMP8(0); + for (i=0; i<5; i++) x86SetJ8(j8Ptr[i]); + for (i=5; i<8; i++) if (j8Ptr[i]) x86SetJ8(j8Ptr[i]); + +// TEST32ItoR(EDX, 0x80000000); + OR32ItoM((uptr)>eFLAG, 1<<29); + x86SetJ8(j8Ptr[9]);*/ + MOV32RtoM((uptr)>eMAC1, ECX); + + if (psxRegs.code & 0x400) { + MAC2IRn(ECX, gteIR1, 24, 0, 32767); + } else { + MAC2IRn(ECX, gteIR1, 24, -32768, 32767); + } + +// MAC2 + _MVMVA1(2); + + if (psxRegs.code & 0x80000) { + SAR32ItoR(ECX, 12); +// SSX /= 4096.0; SSY /= 4096.0; SSZ /= 4096.0; + } + + switch (psxRegs.code & 0x6000) { + case 0x0000: // Add TR + _MVMVA_ADD(gteTRY, 5); break; + case 0x2000: // Add BK + _MVMVA_ADD(gteGBK, 6); break; + case 0x4000: // Add FC + _MVMVA_ADD(gteGFC, 7); break; + } + +/* for (i=0; i<5; i++) x86SetJ8(j8Ptr[i]); + for (i=5; i<8; i++) if (j8Ptr[i]) x86SetJ8(j8Ptr[i]);*/ + MOV32RtoM((uptr)>eMAC2, ECX); + + if (psxRegs.code & 0x400) { + MAC2IRn(ECX, gteIR2, 23, 0, 32767); + } else { + MAC2IRn(ECX, gteIR2, 23, -32768, 32767); + } + +// MAC3 + _MVMVA1(3); + + if (psxRegs.code & 0x80000) { + SAR32ItoR(ECX, 12); +// SSX /= 4096.0; SSY /= 4096.0; SSZ /= 4096.0; + } + + switch (psxRegs.code & 0x6000) { + case 0x0000: // Add TR + _MVMVA_ADD(gteTRZ, 5); break; + case 0x2000: // Add BK + _MVMVA_ADD(gteBBK, 6); break; + case 0x4000: // Add FC + _MVMVA_ADD(gteBFC, 7); break; + } + +/* for (i=0; i<5; i++) x86SetJ8(j8Ptr[i]); + for (i=5; i<8; i++) if (j8Ptr[i]) x86SetJ8(j8Ptr[i]);*/ + MOV32RtoM((uptr)>eMAC3, ECX); + + if (psxRegs.code & 0x400) { + MAC2IRn(ECX, gteIR3, 22, 0, 32767); + } else { + MAC2IRn(ECX, gteIR3, 22, -32768, 32767); + } +/* MAC2IR1() + else MAC2IR()*/ + +// SUM_FLAG(); + +/* POP32R(EBX); + POP32R(EDI); + POP32R(ESI);*/ +} + +#if 0 + +#define _GPF1(vn) { \ + MOV32MtoR(EAX, (uptr)>eIR##vn); \ + IMUL32R(ECX); \ +/* MOV32RtoR(ECX, EAX); */\ +} + +static void recGPF() { +// SysPrintf("GTE_GPF %lx\n", psxRegs.code & 0x1ffffff); + + PUSH32R(EBX); + + XOR32RtoR(EBX, EBX); /* gteFLAG = 0 */ + +/* gteMAC1 = NC_OVERFLOW1(gteIR0 * gteIR1); + gteMAC2 = NC_OVERFLOW2(gteIR0 * gteIR2); + gteMAC3 = NC_OVERFLOW3(gteIR0 * gteIR3);*/ + MOV32MtoR(ECX, (uptr)>eIR0); +// MAC1 + _GPF1(1); + + if (psxRegs.code & 0x80000) { + SAR32ItoR(EAX, 12); + } + MAC2IRn(EAX, gteIR1, 24, -32768, 32767); + PUSH32R(EAX); + +// MAC2 + _GPF1(2); + + if (psxRegs.code & 0x80000) { + SAR32ItoR(EAX, 12); + } + MAC2IRn(EAX, gteIR2, 23, -32768, 32767); + PUSH32R(EAX); + +// MAC3 + _GPF1(3); + + if (psxRegs.code & 0x80000) { + SAR32ItoR(EAX, 12); + } + MAC2IRn(EAX, gteIR3, 22, -32768, 32767); +// MAC2IR(); + +// gteRGB0 = gteRGB1; +// gteRGB1 = gteRGB2; + MOV32MtoR(EDX, (uptr)>eRGB1); + MOV32MtoR(ECX, (uptr)>eRGB2); + MOV32RtoM((uptr)>eRGB0, EDX); + MOV32RtoM((uptr)>eRGB1, ECX); + + POP32R(EDX); + POP32R(ECX); + SAR32ItoR(ECX, 4); + SAR32ItoR(EDX, 4); + SAR32ItoR(EAX, 4); + + _LIM_B1(ECX, gteR2); + _LIM_B2(EDX, gteG2); + _LIM_B3(EAX, gteB2); + MOV8MtoR(EAX, (uptr)>eCODE); + MOV8RtoM((uptr)>eCODE2, EAX); + +/* gteR2 = limB1(gteMAC1 / 16.0f); + gteG2 = limB2(gteMAC2 / 16.0f); + gteB2 = limB3(gteMAC3 / 16.0f); gteCODE2 = gteCODE;*/ + + SUM_FLAG(); + MOV32RtoM((uptr)>eFLAG, EBX); + +// POP32R(EBX); +} +#endif +#endif + + +#endif /* __IGTE_H__ */ diff --git a/libpcsxcore/ix86_64/iR3000A-64.c b/libpcsxcore/ix86_64/iR3000A-64.c new file mode 100644 index 00000000..326ee938 --- /dev/null +++ b/libpcsxcore/ix86_64/iR3000A-64.c @@ -0,0 +1,2966 @@ +/*************************************************************************** + * Copyright (C) 2007 Ryan Schultz, PCSX-df Team, PCSX team * + * schultz.ryan@gmail.com, http://rschultz.ath.cx/code.php * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You 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 Steet, Fifth Floor, Boston, MA 02111-1307 USA. * + ***************************************************************************/ + +/* +* i386 assembly functions for R3000A core. +*/ + +#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; + 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; + 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; + 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; + 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; + 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; + 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); +} + +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, 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); + //recRAM = (uptr*) malloc(0x200000 * sizeof(void*)); + //recROM = (uptr*) malloc(0x080000 * sizeof(void*)); + 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); + //free(recMem); + munmap(recMem, RECMEM_SIZE + PTRMULT*0x1000); + //free(recRAM); + munmap(recRAM, 0x280000*PTRMULT); + //free(recROM); + 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() { + recCP2[_Funct_](); +} +#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) 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_)) { + x86SetJ8(j8Ptr[0]); + } +} + +static void recDIVU() { +// Lo/Hi = Rs / Rt (unsigned) + +// iFlushRegs(); + + if (IsConst(_Rt_)) { + if (iRegs[_Rt_].k == 0) 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_)) { + x86SetJ8(j8Ptr[0]); + } +} +#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 && (t & 0x1fff) != 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 && (t & 0x1fff) != 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 && (t & 0x1fff) != 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 && (t & 0x1fff) != 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; + + MOVZX32M16toR(EAX, (uptr)&psxCounters[(addr >> 4) & 0x3].mode); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX); + return; + + case 0x1f801108: case 0x1f801118: case 0x1f801128: + if (!_Rt_) return; + iRegs[_Rt_].state = ST_UNK; + + MOVZX32M16toR(EAX, (uptr)&psxCounters[(addr >> 4) & 0x3].target); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX); + 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 && (t & 0x1fff) != 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 && (t & 0x1fff) != 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 && (t & 0x1fff) != 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 && (t & 0x1fff) != 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); + } + 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); + } + 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); + } + 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; + +#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 (_Rd_ == 12) + OR32ItoM((uptr)&psxRegs.interrupt, 0x80000000); + 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) = 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 +}; + diff --git a/libpcsxcore/ix86_64/ix86-64.c b/libpcsxcore/ix86_64/ix86-64.c new file mode 100644 index 00000000..a4399ab5 --- /dev/null +++ b/libpcsxcore/ix86_64/ix86-64.c @@ -0,0 +1,3141 @@ +/* + * ix86 core v0.6.2 + * Authors: linuzappz <linuzappz@pcsx.net> + * alexey silinov + * goldfinger + * zerofrog(@gmail.com) + */ + +// 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]; + +extern void SysPrintf(char *fmt, ...); + +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 ) { + assert(0); + SysPrintf( "j8 greater than 0x7f!!\n" ); + } + *j8 = (u8)jump; +} + +void x86SetJ8A( u8* j8 ) +{ + u32 jump = ( x86Ptr - (s8*)j8 ) - 1; + + if ( jump > 0x7f ) { + assert(0); + SysPrintf( "j8 greater than 0x7f!!\n" ); + } + + if( ((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 ) { + assert(0); + SysPrintf( "j16 greater than 0x7fff!!\n" ); + } + *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 diff --git a/libpcsxcore/ix86_64/ix86-64.h b/libpcsxcore/ix86_64/ix86-64.h new file mode 100644 index 00000000..009fa5a1 --- /dev/null +++ b/libpcsxcore/ix86_64/ix86-64.h @@ -0,0 +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__ diff --git a/libpcsxcore/ix86_64/ix86_3dnow.c b/libpcsxcore/ix86_64/ix86_3dnow.c new file mode 100644 index 00000000..8fd42333 --- /dev/null +++ b/libpcsxcore/ix86_64/ix86_3dnow.c @@ -0,0 +1,178 @@ +// stop compiling if NORECBUILD build (only for Visual Studio) +#if !(defined(_MSC_VER) && defined(PCSX2_NORECBUILD)) + +#include "ix86-64.h" + +/**********************/ +/* 3DNOW instructions */ +/**********************/ + +/* femms */ +void FEMMS( void ) +{ + write16( 0x0E0F ); +} + +void PFCMPEQMtoR( x86IntRegType to, uptr from ) +{ + MEMADDR_OP(0, VAROP2(0x0F, 0x0F), true, to, from, 1); + write8( 0xB0 ); +} + +void PFCMPGTMtoR( x86IntRegType to, uptr from ) +{ + MEMADDR_OP(0, VAROP2(0x0F, 0x0F), true, to, from, 1); + write8( 0xA0 ); +} + +void PFCMPGEMtoR( x86IntRegType to, uptr from ) +{ + MEMADDR_OP(0, VAROP2(0x0F, 0x0F), true, to, from, 1); + write8( 0x90 ); +} + +void PFADDMtoR( x86IntRegType to, uptr from ) +{ + MEMADDR_OP(0, VAROP2(0x0F, 0x0F), true, to, from, 1); + write8( 0x9E ); +} + +void PFADDRtoR( x86IntRegType to, x86IntRegType from ) +{ + RexRB(0, to, from); + write16( 0x0F0F ); + ModRM( 3, to, from ); + write8( 0x9E ); +} + +void PFSUBMtoR( x86IntRegType to, uptr from ) +{ + MEMADDR_OP(0, VAROP2(0x0F, 0x0F), true, to, from, 1); + write8( 0x9A ); +} + +void PFSUBRtoR( x86IntRegType to, x86IntRegType from ) +{ + RexRB(0, to, from); + write16( 0x0F0F ); + ModRM( 3, to, from ); + write8( 0x9A ); +} + +void PFMULMtoR( x86IntRegType to, uptr from ) +{ + MEMADDR_OP(0, VAROP2(0x0F, 0x0F), true, to, from, 1); + write8( 0xB4 ); +} + +void PFMULRtoR( x86IntRegType to, x86IntRegType from ) +{ + RexRB(0, to, from); + write16( 0x0F0F ); + ModRM( 3, to, from ); + write8( 0xB4 ); +} + +void PFRCPMtoR( x86IntRegType to, uptr from ) +{ + MEMADDR_OP(0, VAROP2(0x0F, 0x0F), true, to, from, 1); + write8( 0x96 ); +} + +void PFRCPRtoR( x86IntRegType to, x86IntRegType from ) +{ + RexRB(0, to, from); + write16( 0x0F0F ); + ModRM( 3, to, from ); + write8( 0x96 ); +} + +void PFRCPIT1RtoR( x86IntRegType to, x86IntRegType from ) +{ + RexRB(0, to, from); + write16( 0x0F0F ); + ModRM( 3, to, from ); + write8( 0xA6 ); +} + +void PFRCPIT2RtoR( x86IntRegType to, x86IntRegType from ) +{ + RexRB(0, to, from); + write16( 0x0F0F ); + ModRM( 3, to, from ); + write8( 0xB6 ); +} + +void PFRSQRTRtoR( x86IntRegType to, x86IntRegType from ) +{ + RexRB(0, to, from); + write16( 0x0F0F ); + ModRM( 3, to, from ); + write8( 0x97 ); +} + +void PFRSQIT1RtoR( x86IntRegType to, x86IntRegType from ) +{ + RexRB(0, to, from); + write16( 0x0F0F ); + ModRM( 3, to, from ); + write8( 0xA7 ); +} + +void PF2IDMtoR( x86IntRegType to, uptr from ) +{ + MEMADDR_OP(0, VAROP2(0x0F, 0x0F), true, to, from, 1); + write8( 0x1D ); +} + +void PF2IDRtoR( x86IntRegType to, x86IntRegType from ) +{ + RexRB(0, to, from); + write16( 0x0F0F ); + ModRM( 3, to, from ); + write8( 0x1D ); +} + +void PI2FDMtoR( x86IntRegType to, uptr from ) +{ + MEMADDR_OP(0, VAROP2(0x0F, 0x0F), true, to, from, 1); + write8( 0x0D ); +} + +void PI2FDRtoR( x86IntRegType to, x86IntRegType from ) +{ + RexRB(0, to, from); + write16( 0x0F0F ); + ModRM( 3, to, from ); + write8( 0x0D ); +} + +void PFMAXMtoR( x86IntRegType to, uptr from ) +{ + MEMADDR_OP(0, VAROP2(0x0F, 0x0F), true, to, from, 1); + write8( 0xA4 ); +} + +void PFMAXRtoR( x86IntRegType to, x86IntRegType from ) +{ + RexRB(0, to, from); + write16( 0x0F0F ); + ModRM( 3, to, from ); + write8( 0xA4 ); +} + +void PFMINMtoR( x86IntRegType to, uptr from ) +{ + MEMADDR_OP(0, VAROP2(0x0F, 0x0F), true, to, from, 1); + write8( 0x94 ); +} + +void PFMINRtoR( x86IntRegType to, x86IntRegType from ) +{ + RexRB(0, to, from); + write16( 0x0F0F ); + ModRM( 3, to, from ); + write8( 0x94 ); +} + +#endif diff --git a/libpcsxcore/ix86_64/ix86_cpudetect.c b/libpcsxcore/ix86_64/ix86_cpudetect.c new file mode 100644 index 00000000..f34292a6 --- /dev/null +++ b/libpcsxcore/ix86_64/ix86_cpudetect.c @@ -0,0 +1,487 @@ +/* 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 Steet, Fifth Floor, Boston, MA 02111-1307 USA
+ */
+#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__
+
+#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;
+ u32 x86_64_12BITBRANDID;
+ memset( cpuinfo.x86ID, 0, sizeof( cpuinfo.x86ID ) );
+ cpuinfo.x86Family = 0;
+ cpuinfo.x86Model = 0;
+ cpuinfo.x86PType = 0;
+ cpuinfo.x86StepID = 0;
+ cpuinfo.x86Flags = 0;
+ cpuinfo.x86EFlags = 0;
+
+ if ( iCpuId( 0, regs ) == -1 ) return;
+
+ cmds = regs[ 0 ];
+ ((u32*)cpuinfo.x86ID)[ 0 ] = regs[ 1 ];
+ ((u32*)cpuinfo.x86ID)[ 1 ] = regs[ 3 ];
+ ((u32*)cpuinfo.x86ID)[ 2 ] = regs[ 2 ];
+ if ( cmds >= 0x00000001 )
+ {
+ if ( iCpuId( 0x00000001, regs ) != -1 )
+ {
+ cpuinfo.x86StepID = regs[ 0 ] & 0xf;
+ cpuinfo.x86Model = (regs[ 0 ] >> 4) & 0xf;
+ cpuinfo.x86Family = (regs[ 0 ] >> 8) & 0xf;
+ cpuinfo.x86PType = (regs[ 0 ] >> 12) & 0x3;
+ x86_64_8BITBRANDID = regs[1] & 0xff;
+ cpuinfo.x86Flags = regs[ 3 ];
+ }
+ }
+ if ( iCpuId( 0x80000000, regs ) != -1 )
+ {
+ cmds = regs[ 0 ];
+ if ( cmds >= 0x80000001 )
+ {
+ if ( iCpuId( 0x80000001, regs ) != -1 )
+ {
+ x86_64_12BITBRANDID = regs[1] & 0xfff;
+ cpuinfo.x86EFlags = regs[ 3 ];
+
+ }
+ }
+ }
+ switch(cpuinfo.x86PType)
+ {
+ case 0:
+ strcpy( cpuinfo.x86Type, "Standard OEM");
+ break;
+ case 1:
+ strcpy( cpuinfo.x86Type, "Overdrive");
+ break;
+ case 2:
+ strcpy( cpuinfo.x86Type, "Dual");
+ break;
+ case 3:
+ strcpy( cpuinfo.x86Type, "Reserved");
+ break;
+ default:
+ strcpy( cpuinfo.x86Type, "Unknown");
+ break;
+ }
+ if ( cpuinfo.x86ID[ 0 ] == 'G' ){ cputype=0;}//trick lines but if you know a way better ;p
+ if ( cpuinfo.x86ID[ 0 ] == 'A' ){ cputype=1;}
+
+ if ( cputype == 0 ) //intel cpu
+ {
+ if( ( cpuinfo.x86Family >= 7 ) && ( cpuinfo.x86Family < 15 ) )
+ {
+ strcpy( cpuinfo.x86Fam, "Intel P6 family (Not PIV and Higher then PPro" );
+ }
+ else
+ {
+ switch( cpuinfo.x86Family )
+ {
+ // Start at 486 because if it's below 486 there is no cpuid instruction
+ case 4:
+ strcpy( cpuinfo.x86Fam, "Intel 486" );
+ break;
+ case 5:
+ switch( cpuinfo.x86Model )
+ {
+ case 4:
+ case 8: // 0.25 µm
+ strcpy( cpuinfo.x86Fam, "Intel Pentium (MMX)");
+ break;
+ default:
+ strcpy( cpuinfo.x86Fam, "Intel Pentium" );
+ }
+ break;
+ case 6:
+ switch( cpuinfo.x86Model )
+ {
+ case 0: // Pentium pro (P6 A-Step)
+ case 1: // Pentium pro
+ strcpy( cpuinfo.x86Fam, "Intel Pentium Pro" );
+ break;
+
+ case 2: // 66 MHz FSB
+ case 5: // Xeon/Celeron (0.25 µm)
+ case 6: // Internal L2 cache
+ strcpy( cpuinfo.x86Fam, "Intel Pentium II" );
+ break;
+
+ case 7: // Xeon external L2 cache
+ case 8: // Xeon/Celeron with 256 KB on-die L2 cache
+ case 10: // Xeon/Celeron with 1 or 2 MB on-die L2 cache
+ case 11: // Xeon/Celeron with Tualatin core, on-die cache
+ strcpy( cpuinfo.x86Fam, "Intel Pentium III" );
+ break;
+ 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);
+}
diff --git a/libpcsxcore/ix86_64/ix86_fpu.c b/libpcsxcore/ix86_64/ix86_fpu.c new file mode 100644 index 00000000..ca49eb7c --- /dev/null +++ b/libpcsxcore/ix86_64/ix86_fpu.c @@ -0,0 +1,248 @@ +// stop compiling if NORECBUILD build (only for Visual Studio) +#if !(defined(_MSC_VER) && defined(PCSX2_NORECBUILD)) + +#include <stdio.h> +#include <string.h> +#include "ix86-64.h" + +/********************/ +/* FPU instructions */ +/********************/ + +/* fild m32 to fpu reg stack */ +void FILD32( uptr from ) +{ + MEMADDR_OP(0, VAROP1(0xDB), false, 0, from, 0); +} + +/* fistp m32 from fpu reg stack */ +void FISTP32( uptr from ) +{ + MEMADDR_OP(0, VAROP1(0xDB), false, 3, from, 0); +} + +/* fld m32 to fpu reg stack */ +void FLD32( uptr from ) +{ + MEMADDR_OP(0, VAROP1(0xD9), false, 0, from, 0); +} + +// fld st(i) +void FLD(int st) { write16(0xc0d9+(st<<8)); } + +void FLD1() { write16(0xe8d9); } +void FLDL2E() { write16(0xead9); } + +/* fst m32 from fpu reg stack */ +void FST32( uptr to ) +{ + MEMADDR_OP(0, VAROP1(0xD9), false, 2, to, 0); +} + +/* fstp m32 from fpu reg stack */ +void FSTP32( uptr to ) +{ + MEMADDR_OP(0, VAROP1(0xD9), false, 3, to, 0); +} + +// fstp st(i) +void FSTP(int st) { write16(0xd8dd+(st<<8)); } + +/* fldcw fpu control word from m16 */ +void FLDCW( uptr from ) +{ + MEMADDR_OP(0, VAROP1(0xD9), false, 5, from, 0); +} + +/* fnstcw fpu control word to m16 */ +void FNSTCW( uptr to ) +{ + MEMADDR_OP(0, VAROP1(0xD9), false, 7, to, 0); +} + +void FNSTSWtoAX( void ) +{ + write16( 0xE0DF ); +} + +void FXAM() +{ + write16(0xe5d9); +} + +void FDECSTP() { write16(0xf6d9); } +void FRNDINT() { write16(0xfcd9); } +void FXCH(int st) { write16(0xc8d9+(st<<8)); } +void F2XM1() { write16(0xf0d9); } +void FSCALE() { write16(0xfdd9); } + +/* fadd ST(src) to fpu reg stack ST(0) */ +void FADD32Rto0( x86IntRegType src ) +{ + write8( 0xD8 ); + write8( 0xC0 + src ); +} + +/* fadd ST(0) to fpu reg stack ST(src) */ +void FADD320toR( x86IntRegType src ) +{ + write8( 0xDC ); + write8( 0xC0 + src ); +} + +/* fsub ST(src) to fpu reg stack ST(0) */ +void FSUB32Rto0( x86IntRegType src ) +{ + write8( 0xD8 ); + write8( 0xE0 + src ); +} + +/* fsub ST(0) to fpu reg stack ST(src) */ +void FSUB320toR( x86IntRegType src ) +{ + write8( 0xDC ); + write8( 0xE8 + src ); +} + +/* fsubp -> substract ST(0) from ST(1), store in ST(1) and POP stack */ +void FSUBP( void ) +{ + write8( 0xDE ); + write8( 0xE9 ); +} + +/* fmul ST(src) to fpu reg stack ST(0) */ +void FMUL32Rto0( x86IntRegType src ) +{ + write8( 0xD8 ); + write8( 0xC8 + src ); +} + +/* fmul ST(0) to fpu reg stack ST(src) */ +void FMUL320toR( x86IntRegType src ) +{ + write8( 0xDC ); + write8( 0xC8 + src ); +} + +/* fdiv ST(src) to fpu reg stack ST(0) */ +void FDIV32Rto0( x86IntRegType src ) +{ + write8( 0xD8 ); + write8( 0xF0 + src ); +} + +/* fdiv ST(0) to fpu reg stack ST(src) */ +void FDIV320toR( x86IntRegType src ) +{ + write8( 0xDC ); + write8( 0xF8 + src ); +} + +void FDIV320toRP( x86IntRegType src ) +{ + write8( 0xDE ); + write8( 0xF8 + src ); +} + +/* fadd m32 to fpu reg stack */ +void FADD32( uptr from ) +{ + MEMADDR_OP(0, VAROP1(0xD8), false, 0, from, 0); +} + +/* fsub m32 to fpu reg stack */ +void FSUB32( uptr from ) +{ + MEMADDR_OP(0, VAROP1(0xD8), false, 4, from, 0); +} + +/* fmul m32 to fpu reg stack */ +void FMUL32( uptr from ) +{ + MEMADDR_OP(0, VAROP1(0xD8), false, 1, from, 0); +} + +/* fdiv m32 to fpu reg stack */ +void FDIV32( uptr from ) +{ + MEMADDR_OP(0, VAROP1(0xD8), false, 6, from, 0); +} + +/* fabs fpu reg stack */ +void FABS( void ) +{ + write16( 0xE1D9 ); +} + +/* fsqrt fpu reg stack */ +void FSQRT( void ) +{ + write16( 0xFAD9 ); +} + +void FPATAN(void) { write16(0xf3d9); } +void FSIN(void) { write16(0xfed9); } + +/* fchs fpu reg stack */ +void FCHS( void ) +{ + write16( 0xE0D9 ); +} + +/* fcomi st, st(i) */ +void FCOMI( x86IntRegType src ) +{ + write8( 0xDB ); + write8( 0xF0 + src ); +} + +/* fcomip st, st(i) */ +void FCOMIP( x86IntRegType src ) +{ + write8( 0xDF ); + write8( 0xF0 + src ); +} + +/* fucomi st, st(i) */ +void FUCOMI( x86IntRegType src ) +{ + write8( 0xDB ); + write8( 0xE8 + src ); +} + +/* fucomip st, st(i) */ +void FUCOMIP( x86IntRegType src ) +{ + write8( 0xDF ); + write8( 0xE8 + src ); +} + +/* fcom m32 to fpu reg stack */ +void FCOM32( uptr from ) +{ + MEMADDR_OP(0, VAROP1(0xD8), false, 2, from, 0); +} + +/* fcomp m32 to fpu reg stack */ +void FCOMP32( uptr from ) +{ + MEMADDR_OP(0, VAROP1(0xD8), false, 3, from, 0); +} + +#define FCMOV32( low, high ) \ + { \ + write8( low ); \ + write8( high + from ); \ + } + +void FCMOVB32( x86IntRegType from ) { FCMOV32( 0xDA, 0xC0 ); } +void FCMOVE32( x86IntRegType from ) { FCMOV32( 0xDA, 0xC8 ); } +void FCMOVBE32( x86IntRegType from ) { FCMOV32( 0xDA, 0xD0 ); } +void FCMOVU32( x86IntRegType from ) { FCMOV32( 0xDA, 0xD8 ); } +void FCMOVNB32( x86IntRegType from ) { FCMOV32( 0xDB, 0xC0 ); } +void FCMOVNE32( x86IntRegType from ) { FCMOV32( 0xDB, 0xC8 ); } +void FCMOVNBE32( x86IntRegType from ) { FCMOV32( 0xDB, 0xD0 ); } +void FCMOVNU32( x86IntRegType from ) { FCMOV32( 0xDB, 0xD8 ); } + +#endif diff --git a/libpcsxcore/ix86_64/ix86_mmx.c b/libpcsxcore/ix86_64/ix86_mmx.c new file mode 100644 index 00000000..eddbbfcc --- /dev/null +++ b/libpcsxcore/ix86_64/ix86_mmx.c @@ -0,0 +1,646 @@ +// stop compiling if NORECBUILD build (only for Visual Studio) +#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 diff --git a/libpcsxcore/ix86_64/ix86_sse.c b/libpcsxcore/ix86_64/ix86_sse.c new file mode 100644 index 00000000..cb391dca --- /dev/null +++ b/libpcsxcore/ix86_64/ix86_sse.c @@ -0,0 +1,1455 @@ +// stop compiling if NORECBUILD build (only for Visual Studio) +#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 diff --git a/libpcsxcore/mdec.c b/libpcsxcore/mdec.c new file mode 100644 index 00000000..8ab8f4bf --- /dev/null +++ b/libpcsxcore/mdec.c @@ -0,0 +1,522 @@ +/*************************************************************************** + * Copyright (C) 2007 Ryan Schultz, PCSX-df Team, PCSX team * + * schultz.ryan@gmail.com, http://rschultz.ath.cx/code.php * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You 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 Steet, Fifth Floor, Boston, MA 02111-1307 USA. * + ***************************************************************************/ + +/* +* Movie decoder. Based on the FPSE v0.08 Mdec decoder. +*/ + +#include "mdec.h" + +#define FIXED + +#define CONST_BITS 8 +#define PASS1_BITS 2 + +#define FIX_1_082392200 (277) +#define FIX_1_414213562 (362) +#define FIX_1_847759065 (473) +#define FIX_2_613125930 (669) + +#define MULTIPLY(var,const) (DESCALE((var) * (const), CONST_BITS)) + +#define DEQUANTIZE(coef,quantval) (coef) + +#define DESCALE(x,n) ((x)>>(n)) +#define RANGE(n) (n) + +#define DCTSIZE 8 +#define DCTSIZE2 64 + +static void idct1(int *block) +{ + int val = RANGE(DESCALE(block[0], PASS1_BITS+3)); + int i; + for(i=0;i<DCTSIZE2;i++) block[i]=val; +} + +void idct(int *block,int k) +{ + int tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + int z5, z10, z11, z12, z13; + int *ptr; + int i; + + if (!k) { idct1(block); return; } + + ptr = block; + for (i = 0; i< DCTSIZE; i++,ptr++) { + + if ((ptr[DCTSIZE*1] | ptr[DCTSIZE*2] | ptr[DCTSIZE*3] | + ptr[DCTSIZE*4] | ptr[DCTSIZE*5] | ptr[DCTSIZE*6] | + ptr[DCTSIZE*7]) == 0) { + ptr[DCTSIZE*0] = + ptr[DCTSIZE*1] = + ptr[DCTSIZE*2] = + ptr[DCTSIZE*3] = + ptr[DCTSIZE*4] = + ptr[DCTSIZE*5] = + ptr[DCTSIZE*6] = + ptr[DCTSIZE*7] = + ptr[DCTSIZE*0]; + + continue; + } + + z10 = ptr[DCTSIZE*0] + ptr[DCTSIZE*4]; + z11 = ptr[DCTSIZE*0] - ptr[DCTSIZE*4]; + z13 = ptr[DCTSIZE*2] + ptr[DCTSIZE*6]; + z12 = MULTIPLY(ptr[DCTSIZE*2] - ptr[DCTSIZE*6], FIX_1_414213562) - z13; + + tmp0 = z10 + z13; + tmp3 = z10 - z13; + tmp1 = z11 + z12; + tmp2 = z11 - z12; + + z13 = ptr[DCTSIZE*3] + ptr[DCTSIZE*5]; + z10 = ptr[DCTSIZE*3] - ptr[DCTSIZE*5]; + z11 = ptr[DCTSIZE*1] + ptr[DCTSIZE*7]; + z12 = ptr[DCTSIZE*1] - ptr[DCTSIZE*7]; + + z5 = MULTIPLY(z12 - z10, FIX_1_847759065); + tmp7 = z11 + z13; + tmp6 = MULTIPLY(z10, FIX_2_613125930) + z5 - tmp7; + tmp5 = MULTIPLY(z11 - z13, FIX_1_414213562) - tmp6; + tmp4 = MULTIPLY(z12, FIX_1_082392200) - z5 + tmp5; + + ptr[DCTSIZE*0] = (tmp0 + tmp7); + ptr[DCTSIZE*7] = (tmp0 - tmp7); + ptr[DCTSIZE*1] = (tmp1 + tmp6); + ptr[DCTSIZE*6] = (tmp1 - tmp6); + ptr[DCTSIZE*2] = (tmp2 + tmp5); + ptr[DCTSIZE*5] = (tmp2 - tmp5); + ptr[DCTSIZE*4] = (tmp3 + tmp4); + ptr[DCTSIZE*3] = (tmp3 - tmp4); + + } + + ptr = block; + for (i = 0; i < DCTSIZE; i++ ,ptr+=DCTSIZE) { + + if ((ptr[1] | ptr[2] | ptr[3] | ptr[4] | ptr[5] | ptr[6] | + ptr[7]) == 0) { + ptr[0] = + ptr[1] = + ptr[2] = + ptr[3] = + ptr[4] = + ptr[5] = + ptr[6] = + ptr[7] = + RANGE(DESCALE(ptr[0], PASS1_BITS+3));; + + continue; + } + + z10 = ptr[0] + ptr[4]; + z11 = ptr[0] - ptr[4]; + z13 = ptr[2] + ptr[6]; + z12 = MULTIPLY(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]; + + z5 = MULTIPLY(z12 - z10, FIX_1_847759065); + tmp7 = z11 + z13; + tmp6 = MULTIPLY(z10, FIX_2_613125930) + z5 - tmp7; + tmp5 = MULTIPLY(z11 - z13, FIX_1_414213562) - tmp6; + tmp4 = MULTIPLY(z12, FIX_1_082392200) - z5 + tmp5; + + ptr[0] = RANGE(DESCALE(tmp0 + tmp7, PASS1_BITS+3));; + ptr[7] = RANGE(DESCALE(tmp0 - tmp7, PASS1_BITS+3));; + ptr[1] = RANGE(DESCALE(tmp1 + tmp6, PASS1_BITS+3));; + ptr[6] = RANGE(DESCALE(tmp1 - tmp6, PASS1_BITS+3));; + ptr[2] = RANGE(DESCALE(tmp2 + tmp5, PASS1_BITS+3));; + ptr[5] = RANGE(DESCALE(tmp2 - tmp5, PASS1_BITS+3));; + ptr[4] = RANGE(DESCALE(tmp3 + tmp4, PASS1_BITS+3));; + ptr[3] = RANGE(DESCALE(tmp3 - tmp4, PASS1_BITS+3));; + + } +} + +unsigned short* rl2blk(int *blk,unsigned short *mdec_rl); +void iqtab_init(int *iqtab,unsigned char *iq_y); +void yuv2rgb24(int *blk,unsigned char *image); +void yuv2rgb15(int *blk,unsigned short *image); + +struct { + u32 command; + u32 status; + unsigned short *rl; + int rlsize; +} mdec; + +int iq_y[DCTSIZE2],iq_uv[DCTSIZE2]; + +void mdecInit(void) { + mdec.rl = (u16*)&psxM[0x100000]; + mdec.command = 0; + mdec.status = 0; +} + + +void mdecWrite0(u32 data) { +#ifdef CDR_LOG + CDR_LOG("mdec0 write %lx\n", data); +#endif + mdec.command = data; + if ((data&0xf5ff0000)==0x30000000) { + mdec.rlsize = data&0xffff; + } +} + +void mdecWrite1(u32 data) { +#ifdef CDR_LOG + CDR_LOG("mdec1 write %lx\n", data); +#endif + if (data&0x80000000) { // mdec reset + mdec.command = 0; + mdec.status = 0; + } +} + +u32 mdecRead0(void) { +#ifdef CDR_LOG + CDR_LOG("mdec0 read %lx\n", mdec.command); +#endif + return mdec.command; +} + +// mdec status: +#define MDEC_BUSY 0x20000000 +#define MDEC_DREQ 0x18000000 +#define MDEC_FIFO 0xc0000000 +#define MDEC_RGB24 0x02000000 +#define MDEC_STP 0x00800000 + +u32 mdecRead1(void) { +#ifdef CDR_LOG + CDR_LOG("mdec1 read %lx\n", mdec.status); +#endif + return mdec.status; +} + +void psxDma0(u32 adr, u32 bcr, u32 chcr) { + int cmd = mdec.command; + int size; + +#ifdef CDR_LOG + CDR_LOG("DMA0 %lx %lx %lx\n", adr, bcr, chcr); +#endif + + if (chcr!=0x01000201) return; + + size = (bcr>>16)*(bcr&0xffff); + + if (cmd==0x60000000) { + } else + if (cmd==0x40000001) { + u8 *p = (u8*)PSXM(adr); + iqtab_init(iq_y,p); + iqtab_init(iq_uv,p+64); + } else + if ((cmd&0xf5ff0000)==0x30000000) { + mdec.rl = (u16*)PSXM(adr); + } + else { + } + + HW_DMA0_CHCR &= SWAP32(~0x01000000); + DMA_INTERRUPT(0); +} + +void psxDma1(u32 adr, u32 bcr, u32 chcr) { + int blk[DCTSIZE2*6]; + unsigned short *image; + int size; + +#ifdef CDR_LOG + CDR_LOG("DMA1 %lx %lx %lx (cmd = %lx)\n", adr, bcr, chcr, mdec.command); +#endif + + if (chcr!=0x01000200) return; + + size = (bcr>>16)*(bcr&0xffff); + + image = (u16*)PSXM(adr); + if (mdec.command&0x08000000) { +// MDECOUTDMA_INT(((size * (1000000 / 9000)) / 4) /** 4*/ / BIAS); + MDECOUTDMA_INT((size / 4) / BIAS); + size = size / ((16*16)/2); + for (;size>0;size--,image+=(16*16)) { + mdec.rl = rl2blk(blk,mdec.rl); + yuv2rgb15(blk,image); + } + } else { +// MDECOUTDMA_INT(((size * (1000000 / 9000)) / 4) /** 4*/ / BIAS); + MDECOUTDMA_INT((size / 4) / BIAS); + size = size / ((24*16)/2); + for (;size>0;size--,image+=(24*16)) { + mdec.rl = rl2blk(blk,mdec.rl); + yuv2rgb24(blk,(u8 *)image); + } + } + mdec.status|= MDEC_BUSY; +} + +void mdec1Interrupt() { +#ifdef CDR_LOG + CDR_LOG("mdec1Interrupt\n"); +#endif + if (HW_DMA1_CHCR & SWAP32(0x01000000)) { + // Set a fixed value totaly arbitrarie + // another sound value is PSXCLK / 60 or + // PSXCLK / 50 since the bug happend + // at end of frame. PSXCLK / 1000 seems + // good for FF9. + // (for FF9 need < ~28000) + // CAUTION: commented interrupt-handling may lead to problems, keep an eye ;-) + MDECOUTDMA_INT(PSXCLK / 1000); + //psxRegs.interrupt|= 0x02000000; + //psxRegs.intCycle[5+24+1] *= 8; + //psxRegs.intCycle[5+24] = psxRegs.cycle; + HW_DMA1_CHCR&= SWAP32(~0x01000000); + DMA_INTERRUPT(1); + } else { + mdec.status&= ~MDEC_BUSY; + } +} + +#define RUNOF(a) ((a)>>10) +#define VALOF(a) (((int)(a)<<(32-10))>>(32-10)) + +static int zscan[DCTSIZE2] = { + 0 ,1 ,8 ,16,9 ,2 ,3 ,10, + 17,24,32,25,18,11,4 ,5 , + 12,19,26,33,40,48,41,34, + 27,20,13,6 ,7 ,14,21,28, + 35,42,49,56,57,50,43,36, + 29,22,15,23,30,37,44,51, + 58,59,52,45,38,31,39,46, + 53,60,61,54,47,55,62,63 +}; + +static int aanscales[DCTSIZE2] = { + 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, + 22725, 31521, 29692, 26722, 22725, 17855, 12299, 6270, + 21407, 29692, 27969, 25172, 21407, 16819, 11585, 5906, + 19266, 26722, 25172, 22654, 19266, 15137, 10426, 5315, + 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, + 12873, 17855, 16819, 15137, 12873, 10114, 6967, 3552, + 8867, 12299, 11585, 10426, 8867, 6967, 4799, 2446, + 4520, 6270, 5906, 5315, 4520, 3552, 2446, 1247 +}; + +void iqtab_init(int *iqtab,unsigned char *iq_y) { +#define CONST_BITS14 14 +#define IFAST_SCALE_BITS 2 + int i; + + for(i=0;i<DCTSIZE2;i++) { + iqtab[i] =iq_y[i] *aanscales[zscan[i]]>>(CONST_BITS14-IFAST_SCALE_BITS); + } +} + +#define NOP 0xfe00 +unsigned short* rl2blk(int *blk,unsigned short *mdec_rl) { + int i,k,q_scale,rl; + int *iqtab; + + memset (blk, 0, 6*DCTSIZE2*4); + iqtab = iq_uv; + for(i=0;i<6;i++) { // decode blocks (Cr,Cb,Y1,Y2,Y3,Y4) + if (i>1) iqtab = iq_y; + + // zigzag transformation + rl = SWAP16(*mdec_rl); mdec_rl++; + q_scale = RUNOF(rl); + blk[0] = iqtab[0]*VALOF(rl); + for(k = 0;;) { + rl = SWAP16(*mdec_rl); mdec_rl++; + if (rl==NOP) break; + k += RUNOF(rl)+1; // skip level zero-coefficients + if (k > 63) break; + blk[zscan[k]] = (VALOF(rl) * iqtab[k] * q_scale) / 8; // / 16; + } +// blk[0] = (blk[0] * iq_t[0] * 8) / 16; +// for(int j=1;j<64;j++) +// blk[j] = blk[j] * iq_t[j] * q_scale; + + // idct + idct(blk,k+1); + + blk+=DCTSIZE2; + } + return mdec_rl; +} + +#ifdef FIXED +#define MULR(a) ((((int)0x0000059B) * (a)) >> 10) +#define MULG(a) ((((int)0xFFFFFEA1) * (a)) >> 10) +#define MULG2(a) ((((int)0xFFFFFD25) * (a)) >> 10) +#define MULB(a) ((((int)0x00000716) * (a)) >> 10) +#else +#define MULR(a) ((int)((float)1.40200 * (a))) +#define MULG(a) ((int)((float)-0.3437 * (a))) +#define MULG2(a) ((int)((float)-0.7143 * (a))) +#define MULB(a) ((int)((float)1.77200 * (a))) +#endif + +#define MAKERGB15(r, g, b) ( SWAP16((((r) >> 3) << 10)|(((g) >> 3) << 5)|((b) >> 3)) ) +#define ROUND(c) ( ((c) < -128) ? 0 : (((c) > (255 - 128)) ? 255 : ((c) + 128)) ) + +#define RGB15(n, Y) \ + image[n] = MAKERGB15(ROUND(Y + R),ROUND(Y + G),ROUND(Y + B)); + +#define RGB15BW(n, Y) \ + image[n] = MAKERGB15(ROUND(Y),ROUND(Y),ROUND(Y)); + +#define RGB24(n, Y) \ + image[n+2] = ROUND(Y + R); \ + image[n+1] = ROUND(Y + G); \ + image[n+0] = ROUND(Y + B); + +#define RGB24BW(n, Y) \ + image[n+2] = ROUND(Y); \ + image[n+1] = ROUND(Y); \ + image[n+0] = ROUND(Y); + +void yuv2rgb15(int *blk,unsigned short *image) { + int x,y; + int *Yblk = blk+DCTSIZE2*2; + int Cb,Cr,R,G,B; + int *Cbblk = blk; + int *Crblk = blk+DCTSIZE2; + + if (!Config.Mdec) + for (y=0;y<16;y+=2,Crblk+=4,Cbblk+=4,Yblk+=8,image+=24) { + if (y==8) Yblk+=DCTSIZE2; + for (x=0;x<4;x++,image+=2,Crblk++,Cbblk++,Yblk+=2) { + Cr = *Crblk; + Cb = *Cbblk; + R = MULR(Cr); + G = MULG(Cb) + MULG2(Cr); + B = MULB(Cb); + + RGB15(0, Yblk[0]); + RGB15(1, Yblk[1]); + RGB15(16, Yblk[8]); + RGB15(17, Yblk[9]); + + Cr = *(Crblk+4); + Cb = *(Cbblk+4); + R = MULR(Cr); + G = MULG(Cb) + MULG2(Cr); + B = MULB(Cb); + + RGB15(8, Yblk[DCTSIZE2+0]); + RGB15(9, Yblk[DCTSIZE2+1]); + RGB15(24, Yblk[DCTSIZE2+8]); + RGB15(25, Yblk[DCTSIZE2+9]); + } + } else + for (y=0;y<16;y+=2,Yblk+=8,image+=24) { + if (y==8) Yblk+=DCTSIZE2; + for (x=0;x<4;x++,image+=2,Yblk+=2) { + RGB15BW(0, Yblk[0]); + RGB15BW(1, Yblk[1]); + RGB15BW(16, Yblk[8]); + RGB15BW(17, Yblk[9]); + + RGB15BW(8, Yblk[DCTSIZE2+0]); + RGB15BW(9, Yblk[DCTSIZE2+1]); + RGB15BW(24, Yblk[DCTSIZE2+8]); + RGB15BW(25, Yblk[DCTSIZE2+9]); + } + } +} + +void yuv2rgb24(int *blk,unsigned char *image) { + int x,y; + int *Yblk = blk+DCTSIZE2*2; + int Cb,Cr,R,G,B; + int *Cbblk = blk; + int *Crblk = blk+DCTSIZE2; + + if (!Config.Mdec) + for (y=0;y<16;y+=2,Crblk+=4,Cbblk+=4,Yblk+=8,image+=24*3) { + if (y==8) Yblk+=DCTSIZE2; + for (x=0;x<4;x++,image+=6,Crblk++,Cbblk++,Yblk+=2) { + Cr = *Crblk; + Cb = *Cbblk; + R = MULR(Cr); + G = MULG(Cb) + MULG2(Cr); + B = MULB(Cb); + + RGB24(0, Yblk[0]); + RGB24(1*3, Yblk[1]); + RGB24(16*3, Yblk[8]); + RGB24(17*3, Yblk[9]); + + Cr = *(Crblk+4); + Cb = *(Cbblk+4); + R = MULR(Cr); + G = MULG(Cb) + MULG2(Cr); + B = MULB(Cb); + + RGB24(8*3, Yblk[DCTSIZE2+0]); + RGB24(9*3, Yblk[DCTSIZE2+1]); + RGB24(24*3, Yblk[DCTSIZE2+8]); + RGB24(25*3, Yblk[DCTSIZE2+9]); + } + } else + for (y=0;y<16;y+=2,Yblk+=8,image+=24*3) { + if (y==8) Yblk+=DCTSIZE2; + for (x=0;x<4;x++,image+=6,Yblk+=2) { + RGB24BW(0, Yblk[0]); + RGB24BW(1*3, Yblk[1]); + RGB24BW(16*3, Yblk[8]); + RGB24BW(17*3, Yblk[9]); + + RGB24BW(8*3, Yblk[DCTSIZE2+0]); + RGB24BW(9*3, Yblk[DCTSIZE2+1]); + RGB24BW(24*3, Yblk[DCTSIZE2+8]); + RGB24BW(25*3, Yblk[DCTSIZE2+9]); + } + } +} + +int mdecFreeze(gzFile f, int Mode) { + char Unused[4096]; + + gzfreeze(&mdec, sizeof(mdec)); + gzfreezel(iq_y); + gzfreezel(iq_uv); + gzfreezel(Unused); + + return 0; +} + diff --git a/libpcsxcore/mdec.h b/libpcsxcore/mdec.h new file mode 100644 index 00000000..22484fb1 --- /dev/null +++ b/libpcsxcore/mdec.h @@ -0,0 +1,39 @@ +/*************************************************************************** + * Copyright (C) 2007 Ryan Schultz, PCSX-df Team, PCSX team * + * schultz.ryan@gmail.com, http://rschultz.ath.cx/code.php * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You 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 Steet, Fifth Floor, Boston, MA 02111-1307 USA. * + ***************************************************************************/ + +#ifndef __MDEC_H__ +#define __MDEC_H__ + +#include "psxcommon.h" +#include "r3000a.h" +#include "psxhw.h" +#include "psxdma.h" + +void mdecInit(); +void mdecWrite0(u32 data); +void mdecWrite1(u32 data); +u32 mdecRead0(); +u32 mdecRead1(); +void psxDma0(u32 madr, u32 bcr, u32 chcr); +void psxDma1(u32 madr, u32 bcr, u32 chcr); +void mdec1Interrupt(); +int mdecFreeze(gzFile f, int Mode); + +#endif /* __MDEC_H__ */ diff --git a/libpcsxcore/misc.c b/libpcsxcore/misc.c new file mode 100644 index 00000000..400f9e7a --- /dev/null +++ b/libpcsxcore/misc.c @@ -0,0 +1,627 @@ +/*************************************************************************** + * Copyright (C) 2007 Ryan Schultz, PCSX-df Team, PCSX team * + * schultz.ryan@gmail.com, http://rschultz.ath.cx/code.php * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You 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 Steet, Fifth Floor, Boston, MA 02111-1307 USA. * + ***************************************************************************/ + +/* +* Miscellaneous functions, including savesates and CD-ROM loading. +*/ + +#include "misc.h" +#include "cdrom.h" +#include "mdec.h" + +int Log = 0; + +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]; +}; + +#define btoi(b) ((b)/16*10 + (b)%16) /* BCD to u_char */ +#define itob(i) ((i)/10*16 + (i)%10) /* u_char to BCD */ + +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; // minuten + block = block - m * 4500; // minuten rest + s = block / 75; // sekunden + d = block - s * 75; // sekunden 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; + +#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; + } + } 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) { + 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) { + strncpy(exename, ptr, 256); + if (GetCdromFile(mdir, time, exename) == -1) + 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(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; + + 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 + for (i=0; i<32; i++) { + if (ptr[i] == ' ') continue; + if (ptr[i] == '\\') continue; + } + if(ptr) { + strncpy(exename, ptr, 256); + if (GetCdromFile(mdir, time, exename) == -1) + return -1; // main executable not found + } + } + } + } else + return -1; // SYSTEM.CNF not found + + 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 (strstr(exename, "ES") != NULL) + Config.PsxType = 1; // pal + else Config.PsxType = 0; // ntsc + } + psxUpdateVSyncRate(); + if (CdromLabel[0] == ' ') { + strncpy(CdromLabel, CdromId, 9); + } + SysPrintf("CD-ROM Label: %.32s\n", CdromLabel); + SysPrintf("CD-ROM ID: %.9s\n", CdromId); + + return 0; +} + +static int PSXGetFileType(FILE *f) { + unsigned long current; + u32 mybuf[2048]; + EXE_HEADER *exe_hdr; + FILHDR *coff_hdr; + + current = ftell(f); + fseek(f,0L,SEEK_SET); + fread(mybuf,2048,1,f); + fseek(f,current,SEEK_SET); + + exe_hdr = (EXE_HEADER *)mybuf; + if (memcmp(exe_hdr->id,"PS-X EXE",8)==0) + return PSX_EXE; + + if (mybuf[0]=='C' && mybuf[1]=='P' && mybuf[2]=='E') + return CPE_EXE; + + coff_hdr = (FILHDR *)mybuf; + if (coff_hdr->f_magic == 0x0162) + return COFF_EXE; + + return INVALID_EXE; +} + +/* TODO Error handling - return integer for each error case below, defined in an enum. Pass variable on return */ +int Load(char *ExePath) { + FILE *tmpFile; + EXE_HEADER tmpHead; + int type; + int retval = 0; + + strncpy(CdromId, "SLUS99999", 9); + strncpy(CdromLabel, "SLUS_999.99", 11); + + tmpFile = fopen(ExePath,"rb"); + if (tmpFile == NULL) { + SysMessage(_("Error opening file: %s"), ExePath); + retval = 0; + } else { + type = PSXGetFileType(tmpFile); + switch (type) { + case PSX_EXE: + fread(&tmpHead,sizeof(EXE_HEADER),1,tmpFile); + fseek(tmpFile, 0x800, SEEK_SET); + fread((void *)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: + SysMessage(_("CPE files not supported.")); + retval = -1; + break; + case COFF_EXE: + SysMessage(_("COFF files not supported.")); + retval = -1; + break; + case INVALID_EXE: + SysMessage(_("This file does not appear to be a valid PSX file.")); + retval = -1; + break; + } + } + return retval; +} + +// STATES + +const char PcsxHeader[32] = "STv3 PCSX v" PACKAGE_VERSION; + +int SaveState(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*)PcsxHeader, 32); + + 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(char *file) { + gzFile f; + GPUFreeze_t *gpufP; + SPUFreeze_t *spufP; + int Size; + char header[32]; + + f = gzopen(file, "rb"); + if (f == NULL) return -1; + + psxCpu->Reset(); + + gzread(f, header, 32); + + if (strncmp("STv3 PCSX", header, 9)) { gzclose(f); return -1; } + + 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(char *file) { + gzFile f; + char header[32]; + + f = gzopen(file, "rb"); + if (f == NULL) return -1; + + psxCpu->Reset(); + + gzread(f, header, 32); + + gzclose(f); + + if (strncmp("STv3 PCSX", header, 9)) return -1; + + return 0; +} + +// NET Function Helpers + +int SendPcsxInfo() { + if (NET_recvData == NULL || NET_sendData == NULL) + return 0; + +// SysPrintf("SendPcsxInfo\n"); + + 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); + +// SysPrintf("Send OK\n"); + + return 0; +} + +int RecvPcsxInfo() { + int tmp; + + if (NET_recvData == NULL || NET_sendData == NULL) + return 0; + +// SysPrintf("RecvPcsxInfo\n"); + + 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); + psxUpdateVSyncRate(); + + 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) + psxCpu = &psxInt; + else psxCpu = &psxRec; +#else + psxCpu = &psxInt; +#endif + if (psxCpu->Init() == -1) { + SysClose(); return -1; + } + psxCpu->Reset(); + } + +// SysPrintf("Recv OK\n"); + + return 0; +} + + +void __Log(char *fmt, ...) { + va_list list; +#ifdef LOG_STDOUT + char tmp[1024]; +#endif + + va_start(list, fmt); +#ifndef LOG_STDOUT + vfprintf(emuLog, fmt, list); +#else + vsprintf(tmp, fmt, list); + SysPrintf(tmp); +#endif + va_end(list); +} + +// 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'; +} diff --git a/libpcsxcore/misc.h b/libpcsxcore/misc.h new file mode 100644 index 00000000..a71dfecd --- /dev/null +++ b/libpcsxcore/misc.h @@ -0,0 +1,73 @@ +/*************************************************************************** + * Copyright (C) 2007 Ryan Schultz, PCSX-df Team, PCSX team * + * schultz.ryan@gmail.com, http://rschultz.ath.cx/code.php * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You 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 Steet, Fifth Floor, Boston, MA 02111-1307 USA. * + ***************************************************************************/ + +#ifndef __MISC_H__ +#define __MISC_H__ + +#include "psxcommon.h" +#include "coff.h" +#include "plugins.h" +#include "r3000a.h" +#include "psxmem.h" + +#undef s_addr + +typedef struct { + unsigned char id[8]; + u32 text; + u32 data; + 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 SavedSP; + u32 SavedFP; + u32 SavedGP; + u32 SavedRA; + u32 SavedS0; +} EXE_HEADER; + +extern char CdromId[10]; +extern char CdromLabel[33]; + +int LoadCdrom(); +int LoadCdromFile(char *filename, EXE_HEADER *head); +int CheckCdrom(); +int Load(char *ExePath); + +int SaveState(char *file); +int LoadState(char *file); +int CheckState(char *file); + +int SendPcsxInfo(); +int RecvPcsxInfo(); + +void trim(char *str); + +extern char *LabelAuthors; +extern char *LabelGreets; + +#endif /* __MISC_H__ */ diff --git a/libpcsxcore/plugins.c b/libpcsxcore/plugins.c new file mode 100644 index 00000000..574f07e4 --- /dev/null +++ b/libpcsxcore/plugins.c @@ -0,0 +1,820 @@ +/*************************************************************************** + * Copyright (C) 2007 Ryan Schultz, PCSX-df Team, PCSX team * + * schultz.ryan@gmail.com, http://rschultz.ath.cx/code.php * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You 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 Steet, Fifth Floor, Boston, MA 02111-1307 USA. * + ***************************************************************************/ + +/* +* Plugin library callback/access functions. +*/ + +#include "plugins.h" +#include "cdriso.h" + +char cdrfilename[MAXPATHLEN] = ""; +int cdOpenCase = 0; + +#define CheckErr(func) \ + err = SysLibError(); \ + if (err != NULL) { SysMessage(_("Error loading %s: %s"), func, err); return -1; } + +#if defined (__MACOSX__) +#define LoadSym(dest, src, name, checkerr) \ + dest = (src) SysLoadSym(drv, "_" name); \ + if (checkerr == 0) { SysLibError(); /*clean error*/ } \ + if (checkerr == 1) CheckErr(name); \ + if (checkerr == 2) { err = SysLibError(); if (err != NULL) errval = 1; } +#else +#define LoadSym(dest, src, name, checkerr) \ + dest = (src) SysLoadSym(drv, name); if (checkerr == 1) CheckErr(name); \ + if (checkerr == 2) { err = SysLibError(); if (err != NULL) errval = 1; } +#endif + +static const char *err; +static int errval; + +void *hGPUDriver = NULL; + +void CALLBACK GPU__readDataMem(uint32_t *pMem, int iSize) { + while (iSize > 0) { + *pMem = SWAP32(GPU_readData()); + iSize--; + pMem++; + } +} + +void CALLBACK GPU__writeDataMem(uint32_t *pMem, int iSize) { + while (iSize > 0) { + GPU_writeData(SWAP32(*pMem)); + iSize--; + pMem++; + } +} + +void CALLBACK GPU__displayText(char *pText) { + SysPrintf("%s\n", pText); +} + +extern int StatesC; +long CALLBACK GPU__freeze(uint32_t ulGetFreezeData, GPUFreeze_t *pF) { + pF->ulFreezeVersion = 1; + if (ulGetFreezeData == 0) { + int val; + + val = GPU_readStatus(); + val = 0x04000000 | ((val >> 29) & 0x3); + GPU_writeStatus(0x04000003); + GPU_writeStatus(0x01000000); + GPU_writeData(0xa0000000); + GPU_writeData(0x00000000); + GPU_writeData(0x02000400); + GPU_writeDataMem((uint32_t*)pF->psxVRam, 0x100000/4); + GPU_writeStatus(val); + + val = pF->ulStatus; + GPU_writeStatus(0x00000000); + GPU_writeData(0x01000000); + GPU_writeStatus(0x01000000); + GPU_writeStatus(0x03000000 | ((val>>24)&0x1)); + GPU_writeStatus(0x04000000 | ((val>>29)&0x3)); + GPU_writeStatus(0x08000000 | ((val>>17)&0x3f) | ((val>>10)&0x40)); + GPU_writeData(0xe1000000 | (val&0x7ff)); + GPU_writeData(0xe6000000 | ((val>>11)&3)); + +/* GPU_writeData(0xe3000000 | pF->ulControl[0] & 0xffffff); + GPU_writeData(0xe4000000 | pF->ulControl[1] & 0xffffff); + GPU_writeData(0xe5000000 | pF->ulControl[2] & 0xffffff);*/ + return 1; + } + if (ulGetFreezeData == 1) { + int val; + + val = GPU_readStatus(); + val = 0x04000000 | ((val >> 29) & 0x3); + GPU_writeStatus(0x04000003); + GPU_writeStatus(0x01000000); + GPU_writeData(0xc0000000); + GPU_writeData(0x00000000); + GPU_writeData(0x02000400); + GPU_readDataMem((uint32_t*)pF->psxVRam, 0x100000/4); + GPU_writeStatus(val); + + pF->ulStatus = GPU_readStatus(); + +/* GPU_writeStatus(0x10000003); + pF->ulControl[0] = GPU_readData(); + GPU_writeStatus(0x10000004); + pF->ulControl[1] = GPU_readData(); + GPU_writeStatus(0x10000005); + pF->ulControl[2] = GPU_readData();*/ + return 1; + } + if(ulGetFreezeData==2) { + long lSlotNum=*((long *)pF); + char Text[32]; + + sprintf (Text, "Selected state %ld", lSlotNum+1); + GPU_displayText(Text); + return 1; + } + return 0; +} + +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)) { } + +#define LoadGpuSym1(dest, name) \ + LoadSym(GPU_##dest, GPU##dest, name, 1); + +#define LoadGpuSym0(dest, name) \ + LoadSym(GPU_##dest, GPU##dest, name, 0); \ + if (GPU_##dest == NULL) GPU_##dest = (GPU##dest) GPU__##dest; + +#define LoadGpuSymN(dest, name) \ + LoadSym(GPU_##dest, GPU##dest, name, 0); + +int LoadGPUplugin(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"); + LoadGpuSym0(readDataMem, "GPUreadDataMem"); + LoadGpuSym1(readStatus, "GPUreadStatus"); + LoadGpuSym1(writeData, "GPUwriteData"); + LoadGpuSym0(writeDataMem, "GPUwriteDataMem"); + LoadGpuSym1(writeStatus, "GPUwriteStatus"); + LoadGpuSym1(dmaChain, "GPUdmaChain"); + LoadGpuSym1(updateLace, "GPUupdateLace"); + LoadGpuSym0(keypressed, "GPUkeypressed"); + LoadGpuSym0(displayText, "GPUdisplayText"); + LoadGpuSym0(makeSnapshot, "GPUmakeSnapshot"); + LoadGpuSym0(freeze, "GPUfreeze"); + LoadGpuSym0(getScreenPic, "GPUgetScreenPic"); + LoadGpuSym0(showScreenPic, "GPUshowScreenPic"); + LoadGpuSym0(clearDynarec, "GPUclearDynarec"); + 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 (cdOpenCase < 0 || cdOpenCase > time(NULL)) + stat->Status = 0x10; + else + stat->Status = 0; + + return 0; +} + +char* CALLBACK CDR__getDriveLetter(void) { return NULL; } +unsigned char* CALLBACK CDR__getBufferSub(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, 1); + +#define LoadCdrSym0(dest, name) \ + LoadSym(CDR_##dest, CDR##dest, name, 0); \ + if (CDR_##dest == NULL) CDR_##dest = (CDR##dest) CDR__##dest; + +#define LoadCdrSymN(dest, name) \ + LoadSym(CDR_##dest, CDR##dest, name, 0); + +int LoadCDRplugin(char *CDRdll) { + void *drv; + + 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"); + LoadCdrSym0(play, "CDRplay"); + LoadCdrSym0(stop, "CDRstop"); + LoadCdrSym0(getStatus, "CDRgetStatus"); + LoadCdrSym0(getDriveLetter, "CDRgetDriveLetter"); + LoadCdrSym0(getBufferSub, "CDRgetBufferSub"); + LoadCdrSym0(configure, "CDRconfigure"); + LoadCdrSym0(test, "CDRtest"); + LoadCdrSym0(about, "CDRabout"); + LoadCdrSym0(setfilename, "CDRsetfilename"); + + return 0; +} + +void *hSPUDriver = NULL; + +long CALLBACK SPU__configure(void) { return 0; } +void CALLBACK SPU__about(void) {} +long CALLBACK SPU__test(void) { return 0; } + +unsigned short regArea[10000]; +unsigned short spuCtrl,spuStat,spuIrq; +unsigned long spuAddr; + +void CALLBACK SPU__writeRegister(uint32_t add,unsigned short value) { // Old Interface + uint32_t r=add&0xfff; + regArea[(r-0xc00)/2] = value; + + if(r>=0x0c00 && r<0x0d80) { + unsigned char ch=(r>>4)-0xc0; + switch(r&0x0f) {//switch voices + case 0: //left volume + SPU_setVolumeL(ch,value); + return; + case 2: //right volume + SPU_setVolumeR(ch,value); + return; + case 4: //frequency + SPU_setPitch(ch,value); + return; + case 6://start address + SPU_setAddr(ch,value); + return; + //------------------------------------------------// level +// case 8: +// s_chan[ch].ADSRX.AttackModeExp = (val&0x8000)?TRUE:FALSE; +// s_chan[ch].ADSRX.AttackRate = (float)((val>>8) & 0x007f)*1000.0f/240.0f; +// s_chan[ch].ADSRX.DecayRate = (float)((val>>4) & 0x000f)*1000.0f/240.0f; +// s_chan[ch].ADSRX.SustainLevel = (float)((val) & 0x000f); + +// return; +// case 10: +// s_chan[ch].ADSRX.SustainModeExp = (val&0x8000)?TRUE:FALSE; +// s_chan[ch].ADSRX.ReleaseModeExp = (val&0x0020)?TRUE:FALSE; +// s_chan[ch].ADSRX.SustainRate = ((float)((val>>6) & 0x007f))*R_SUSTAIN; +// s_chan[ch].ADSRX.ReleaseRate = ((float)((val) & 0x001f))*R_RELEASE; +// if(val & 0x4000) s_chan[ch].ADSRX.SustainModeDec=-1.0f; +// else s_chan[ch].ADSRX.SustainModeDec=1.0f; +// return; +// case 12: +// return; +// case 14: +// s_chan[ch].pRepeat=spuMemC+((unsigned long) val<<3); +// return; + } + return; + } + + switch(r) { + case H_SPUaddr://SPU-memory address + spuAddr = (uint32_t) value<<3; + // spuAddr=value * 8; + return; + case H_SPUdata://DATA to SPU +// spuMem[spuAddr/2] = value; +// spuAddr+=2; +// if(spuAddr>0x7ffff) spuAddr=0; + SPU_putOne(spuAddr,value); + spuAddr+=2; + return; + case H_SPUctrl://SPU control 1 + spuCtrl=value; + return; + case H_SPUstat://SPU status + spuStat=value & 0xf800; + return; + case H_SPUirqAddr://SPU irq + spuIrq = value; + return; + case H_SPUon1://start sound play channels 0-16 + SPU_startChannels1(value); + return; + case H_SPUon2://start sound play channels 16-24 + SPU_startChannels2(value); + return; + case H_SPUoff1://stop sound play channels 0-16 + SPU_stopChannels1(value); + return; + case H_SPUoff2://stop sound play channels 16-24 + SPU_stopChannels2(value); + return; + } +} + +unsigned short CALLBACK SPU__readRegister(uint32_t add) { + switch(add&0xfff) {// Old Interface + case H_SPUctrl://spu control + return spuCtrl; + case H_SPUstat://spu status + return spuStat; + case H_SPUaddr://SPU-memory address + return (unsigned short)(spuAddr>>3); + case H_SPUdata://DATA to SPU + spuAddr+=2; +// if(spuAddr>0x7ffff) spuAddr=0; +// return spuMem[spuAddr/2]; + return SPU_getOne(spuAddr); + case H_SPUirqAddr://spu irq + return spuIrq; + //case H_SPUIsOn1: + //return IsSoundOn(0,16); + //case H_SPUIsOn2: + //return IsSoundOn(16,24); + } + return regArea[((add&0xfff)-0xc00)/2]; +} + +void CALLBACK SPU__writeDMA(unsigned short val) { + SPU_putOne(spuAddr, val); + spuAddr += 2; + if (spuAddr > 0x7ffff) spuAddr = 0; +} + +unsigned short CALLBACK SPU__readDMA(void) { + unsigned short tmp = SPU_getOne(spuAddr); + spuAddr += 2; + if (spuAddr > 0x7ffff) spuAddr = 0; + return tmp; +} + +void CALLBACK SPU__writeDMAMem(unsigned short *pMem, int iSize) { + while (iSize > 0) { + SPU_writeDMA(*pMem); + iSize--; + pMem++; + } +} + +void CALLBACK SPU__readDMAMem(unsigned short *pMem, int iSize) { + while (iSize > 0) { + *pMem = SPU_readDMA(); + iSize--; + pMem++; + } +} + +void CALLBACK SPU__playADPCMchannel(xa_decode_t *xap) {} + +long CALLBACK SPU__freeze(uint32_t ulFreezeMode, SPUFreeze_t *pF) { + if (ulFreezeMode == 2) { + memset(pF, 0, 16); + strcpy((char *)pF->PluginName, "Pcsx"); + pF->PluginVersion = 1; + pF->Size = 0x200 + 0x80000 + 16 + sizeof(xa_decode_t); + + return 1; + } + if (ulFreezeMode == 1) { + uint32_t addr; + unsigned short val; + + val = SPU_readRegister(0x1f801da6); + SPU_writeRegister(0x1f801da6, 0); + SPU_readDMAMem((unsigned short *)pF->SPURam, 0x80000/2); + SPU_writeRegister(0x1f801da6, val); + + for (addr = 0x1f801c00; addr < 0x1f801e00; addr+=2) { + if (addr == 0x1f801da8) { pF->SPUPorts[addr - 0x1f801c00] = 0; continue; } + pF->SPUPorts[addr - 0x1f801c00] = SPU_readRegister(addr); + } + + return 1; + } + if (ulFreezeMode == 0) { + uint32_t addr; + unsigned short val; + unsigned short *regs = (unsigned short *)pF->SPUPorts; + + val = SPU_readRegister(0x1f801da6); + SPU_writeRegister(0x1f801da6, 0); + SPU_writeDMAMem((unsigned short *)pF->SPURam, 0x80000/2); + SPU_writeRegister(0x1f801da6, val); + + for (addr = 0x1f801c00; addr < 0x1f801e00; addr+=2) { + if (addr == 0x1f801da8) { regs++; continue; } + SPU_writeRegister(addr, *(regs++)); + } + + return 1; + } + + return 0; +} + +void CALLBACK SPU__registerCallback(void (CALLBACK *callback)(void)) {} + +#define LoadSpuSym1(dest, name) \ + LoadSym(SPU_##dest, SPU##dest, name, 1); + +#define LoadSpuSym2(dest, name) \ + LoadSym(SPU_##dest, SPU##dest, name, 2); + +#define LoadSpuSym0(dest, name) \ + LoadSym(SPU_##dest, SPU##dest, name, 0); \ + if (SPU_##dest == NULL) SPU_##dest = (SPU##dest) SPU__##dest; + +#define LoadSpuSymE(dest, name) \ + LoadSym(SPU_##dest, SPU##dest, name, errval); \ + if (SPU_##dest == NULL) SPU_##dest = (SPU##dest) SPU__##dest; + +#define LoadSpuSymN(dest, name) \ + LoadSym(SPU_##dest, SPU##dest, name, 0); \ + +int LoadSPUplugin(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"); + errval = 0; + LoadSpuSym2(startChannels1, "SPUstartChannels1"); + LoadSpuSym2(startChannels2, "SPUstartChannels2"); + LoadSpuSym2(stopChannels1, "SPUstopChannels1"); + LoadSpuSym2(stopChannels2, "SPUstopChannels2"); + LoadSpuSym2(putOne, "SPUputOne"); + LoadSpuSym2(getOne, "SPUgetOne"); + LoadSpuSym2(setAddr, "SPUsetAddr"); + LoadSpuSym2(setPitch, "SPUsetPitch"); + LoadSpuSym2(setVolumeL, "SPUsetVolumeL"); + LoadSpuSym2(setVolumeR, "SPUsetVolumeR"); + LoadSpuSymE(writeRegister, "SPUwriteRegister"); + LoadSpuSymE(readRegister, "SPUreadRegister"); + LoadSpuSymE(writeDMA, "SPUwriteDMA"); + LoadSpuSymE(readDMA, "SPUreadDMA"); + LoadSpuSym0(writeDMAMem, "SPUwriteDMAMem"); + LoadSpuSym0(readDMAMem, "SPUreadDMAMem"); + LoadSpuSym0(playADPCMchannel, "SPUplayADPCMchannel"); + LoadSpuSym0(freeze, "SPUfreeze"); + LoadSpuSym0(registerCallback, "SPUregisterCallback"); + LoadSpuSymN(async, "SPUasync"); + + 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; } + +#define LoadPad1Sym1(dest, name) \ + LoadSym(PAD1_##dest, PAD##dest, name, 1); + +#define LoadPad1SymN(dest, name) \ + LoadSym(PAD1_##dest, PAD##dest, name, 0); + +#define LoadPad1Sym0(dest, name) \ + LoadSym(PAD1_##dest, PAD##dest, name, 0); \ + if (PAD1_##dest == NULL) PAD1_##dest = (PAD##dest) PAD1__##dest; + +int LoadPAD1plugin(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"); + + 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 3; } +long CALLBACK PAD2__keypressed() { return 0; } + +#define LoadPad2Sym1(dest, name) \ + LoadSym(PAD2_##dest, PAD##dest, name, 1); + +#define LoadPad2Sym0(dest, name) \ + LoadSym(PAD2_##dest, PAD##dest, name, 0); \ + if (PAD2_##dest == NULL) PAD2_##dest = (PAD##dest) PAD2__##dest; + +#define LoadPad2SymN(dest, name) \ + LoadSym(PAD2_##dest, PAD##dest, name, 0); + +int LoadPAD2plugin(char *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"); + + 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, 1); + +#define LoadNetSymN(dest, name) \ + LoadSym(NET_##dest, NET##dest, name, 0); + +#define LoadNetSym0(dest, name) \ + LoadSym(NET_##dest, NET##dest, name, 0); \ + if (NET_##dest == NULL) NET_##dest = (NET##dest) NET__##dest; + +int LoadNETplugin(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; +} + +void CALLBACK clearDynarec(void) { + psxCpu->Reset(); +} + +/* TODO If there's an error, need to notify user which plugin failed, rather than silently fail */ +int LoadPlugins() { + int ret; + char Plugin[MAXPATHLEN]; + + ReleasePlugins(); + + if (cdrfilename[0] != '\0') { + imageReaderInit(); + } 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 = 0; + else { + Config.UseNet = 1; + sprintf(Plugin, "%s/%s", Config.PluginsDir, Config.Net); + if (LoadNETplugin(Plugin) == -1) Config.UseNet = 0; + } + + /* TODO Proper error code handling - report the appropriate error */ + 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; } + } + + SysPrintf(_("Plugins loaded.\n")); + return 0; +} + +void ReleasePlugins() { + extern FILE *cdHandle; + + if (Config.UseNet) { + int ret = NET_close(); + if (ret < 0) Config.UseNet = 0; + NetOpened = 0; + } + + if (hCDRDriver != NULL || cdHandle != NULL) 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; + } +} diff --git a/libpcsxcore/plugins.h b/libpcsxcore/plugins.h new file mode 100644 index 00000000..7402a9bb --- /dev/null +++ b/libpcsxcore/plugins.h @@ -0,0 +1,348 @@ +/***************************************************************************
+ * Copyright (C) 2007 Ryan Schultz, PCSX-df Team, PCSX team *
+ * schultz.ryan@gmail.com, http://rschultz.ath.cx/code.php *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You 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 Steet, Fifth Floor, Boston, MA 02111-1307 USA. *
+ ***************************************************************************/
+
+#ifndef __PLUGINS_H__
+#define __PLUGINS_H__
+
+#include "psxcommon.h"
+#include "spu.h"
+
+#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 *);
+
+#else
+
+#include <windows.h>
+
+typedef long (CALLBACK* GPUopen)(HWND);
+typedef long (CALLBACK* SPUopen)(HWND);
+typedef long (CALLBACK* PADopen)(HWND);
+typedef long (CALLBACK* NETopen)(HWND);
+
+#endif
+
+#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 PLUGIN STUFF
+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));
+
+//plugin stuff From Shadow
+// *** walking in the valley of your darking soul i realize that i was alone
+//Gpu function pointers
+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;
+
+//cd rom plugin ;)
+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 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[11];
+ unsigned char ControlAndADR;
+ unsigned char TrackNumber;
+ unsigned char IndexNumber;
+ unsigned char TrackRelativeAddress[3];
+ unsigned char Filler;
+ unsigned char AbsoluteAddress[3];
+ char res1[72];
+};
+typedef unsigned char* (CALLBACK* CDRgetBufferSub)(void);
+
+//cd rom function pointers
+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;
+
+// spu plugin
+typedef long (CALLBACK* SPUinit)(void);
+typedef long (CALLBACK* SPUshutdown)(void);
+typedef long (CALLBACK* SPUclose)(void);
+typedef void (CALLBACK* SPUplaySample)(unsigned char);
+typedef void (CALLBACK* SPUstartChannels1)(unsigned short);
+typedef void (CALLBACK* SPUstartChannels2)(unsigned short);
+typedef void (CALLBACK* SPUstopChannels1)(unsigned short);
+typedef void (CALLBACK* SPUstopChannels2)(unsigned short);
+typedef void (CALLBACK* SPUputOne)(uint32_t,unsigned short);
+typedef unsigned short (CALLBACK* SPUgetOne)(uint32_t);
+typedef void (CALLBACK* SPUsetAddr)(unsigned char, unsigned short);
+typedef void (CALLBACK* SPUsetPitch)(unsigned char, unsigned short);
+typedef void (CALLBACK* SPUsetVolumeL)(unsigned char, short);
+typedef void (CALLBACK* SPUsetVolumeR)(unsigned char, short);
+//psemu pro 2 functions from now..
+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);
+
+//SPU POINTERS
+SPUconfigure SPU_configure;
+SPUabout SPU_about;
+SPUinit SPU_init;
+SPUshutdown SPU_shutdown;
+SPUtest SPU_test;
+SPUopen SPU_open;
+SPUclose SPU_close;
+SPUplaySample SPU_playSample;
+SPUstartChannels1 SPU_startChannels1;
+SPUstartChannels2 SPU_startChannels2;
+SPUstopChannels1 SPU_stopChannels1;
+SPUstopChannels2 SPU_stopChannels2;
+SPUputOne SPU_putOne;
+SPUgetOne SPU_getOne;
+SPUsetAddr SPU_setAddr;
+SPUsetPitch SPU_setPitch;
+SPUsetVolumeL SPU_setVolumeL;
+SPUsetVolumeR SPU_setVolumeR;
+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;
+
+// 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);
+
+//PAD POINTERS
+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;
+
+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;
+
+// NET plugin
+
+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
+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;
+
+int LoadCDRplugin(char *CDRdll);
+int LoadGPUplugin(char *GPUdll);
+int LoadSPUplugin(char *SPUdll);
+int LoadPAD1plugin(char *PAD1dll);
+int LoadPAD2plugin(char *PAD2dll);
+int LoadNETplugin(char *NETdll);
+
+void CALLBACK clearDynarec(void);
+
+extern char cdrfilename[MAXPATHLEN];
+
+#endif /* __PLUGINS_H__ */
diff --git a/libpcsxcore/ppc/pGte.h b/libpcsxcore/ppc/pGte.h new file mode 100644 index 00000000..27894374 --- /dev/null +++ b/libpcsxcore/ppc/pGte.h @@ -0,0 +1,670 @@ +/* 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 Steet, Fifth Floor, Boston, MA 02111-1307 USA + */ + +int psxCP2time[64] = { + 2, 16 , 1 , 1, 1, 1 , 8, 1, // 00 + 1 , 1 , 1 , 1, 6 , 1 , 1 , 1, // 08 + 8 , 8, 8, 19, 13 , 1 , 44 , 1, // 10 + 1 , 1 , 1 , 17, 11 , 1 , 14 , 1, // 18 + 30 , 1 , 1 , 1, 1, 1 , 1 , 1, // 20 + 5 , 8 , 17 , 1, 1, 5, 6, 1, // 28 + 23 , 1 , 1 , 1, 1, 1 , 1 , 1, // 30 + 1 , 1 , 1 , 1, 1, 6 , 5 , 39 // 38 +}; + +#define CP2_FUNC(f) \ +void gte##f(); \ +static void rec##f() { \ + if (pc < cop2readypc) idlecyclecount += (cop2readypc - pc)>>2; \ + iFlushRegs(0); \ + LIW(0, (u32)psxRegs.code); \ + STW(0, OFFSET(&psxRegs, &psxRegs.code), GetHWRegSpecial(PSXREGS)); \ + FlushAllHWReg(); \ + CALLFunc ((u32)gte##f); \ + cop2readypc = pc + psxCP2time[_fFunct_(psxRegs.code)]<<2; \ +} + +#define CP2_FUNCNC(f) \ +void gte##f(); \ +static void rec##f() { \ + if (pc < cop2readypc) idlecyclecount += (cop2readypc - pc)>>2; \ + iFlushRegs(0); \ + CALLFunc ((u32)gte##f); \ +/* branch = 2; */\ + cop2readypc = pc + psxCP2time[_fFunct_(psxRegs.code)]; \ +} + +CP2_FUNC(MFC2); +CP2_FUNC(MTC2); +CP2_FUNC(CFC2); +CP2_FUNC(CTC2); +CP2_FUNC(LWC2); +CP2_FUNC(SWC2); + +#if 0 +void gteMFC2(); +static void recMFC2() { +// Rt = Cop2D->Rd + if (!_Rt_) return; + + iRegs[_Rt_].state = ST_UNK; + + switch (_Rd_) { + case 29: + MOV32ItoM((u32)&psxRegs.code, (u32)psxRegs.code); + CALLFunc ((u32)gteMFC2); + break; + + default: + MOV32MtoR(EAX, (u32)&psxRegs.CP2D.r[_Rd_]); + MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX); + break; + } +} + +void gteMTC2(); +static void recMTC2() { +// Cop2D->Rd = Rt + int fixt = 0; + +// iFlushRegs(); + + switch (_Rd_) { + case 8: case 9: case 10: case 11: + fixt = 1; break; + + case 16: case 17: case 18: case 19: + fixt = 2; break; + + case 15: + case 28: + case 30: + MOV32ItoM((u32)&psxRegs.code, (u32)psxRegs.code); + CALLFunc ((u32)gteMTC2); + break; + } + + if (IsConst(_Rt_)) { + if (fixt == 1) MOV32ItoM((u32)&psxRegs.CP2D.r[_Rd_], (s16)iRegs[_Rt_].k); + else if (fixt == 2) MOV32ItoM((u32)&psxRegs.CP2D.r[_Rd_], iRegs[_Rt_].k & 0xffff); + else MOV32ItoM((u32)&psxRegs.CP2D.r[_Rd_], iRegs[_Rt_].k); + } else { + MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]); + if (fixt == 1) MOVSX32R16toR(EAX, EAX); + else if (fixt == 2) AND32ItoR(EAX, 0xffff); + MOV32RtoM((u32)&psxRegs.CP2D.r[_Rd_], EAX); + } +} + +void gteLWC2(); +static void recLWC2() { +// Cop2D->Rt = mem[Rs + Im] (unsigned) + int fixt = 0; + + switch (_Rt_) { + case 8: case 9: case 10: case 11: + fixt = 1; break; + + case 16: case 17: case 18: case 19: + fixt = 2; break; + + case 15: + case 28: + case 30: + iFlushRegs(); + MOV32ItoM((u32)&psxRegs.code, (u32)psxRegs.code); + CALLFunc ((u32)gteLWC2); + return; + } + + 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 & 0x1fffff]); + if (fixt == 1) MOVSX32R16toR(EAX, EAX); + else if (fixt == 2) AND32ItoR(EAX, 0xffff); + MOV32RtoM((u32)&psxRegs.CP2D.r[_Rt_], EAX); + return; + } + if (t == 0x1f80 && addr < 0x1f801000) { + MOV32MtoR(EAX, (u32)&psxH[addr & 0xfff]); + if (fixt == 1) MOVSX32R16toR(EAX, EAX); + else if (fixt == 2) AND32ItoR(EAX, 0xffff); + MOV32RtoM((u32)&psxRegs.CP2D.r[_Rt_], EAX); + return; + } + } + + iPushOfB(); + CALLFunc((u32)psxMemRead32); + if (fixt == 1) MOVSX32R16toR(EAX, EAX); + else if (fixt == 2) AND32ItoR(EAX, 0xffff); + MOV32RtoM((u32)&psxRegs.CP2D.r[_Rt_], EAX); +// ADD32ItoR(ESP, 4); + resp+= 4; +} + +void gteSWC2(); +static void recSWC2() { +// mem[Rs + Im] = Rt + + switch (_Rt_) { + case 29: + iFlushRegs(); + MOV32ItoM((u32)&psxRegs.code, (u32)psxRegs.code); + CALLFunc ((u32)gteSWC2); + return; + } + + if (IsConst(_Rs_)) { + u32 addr = iRegs[_Rs_].k + _Imm_; + int t = addr >> 16; + + if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) { + MOV32MtoR(EAX, (u32)&psxRegs.CP2D.r[_Rt_]); + MOV32RtoM((u32)&psxM[addr & 0x1fffff], EAX); + return; + } + if (t == 0x1f80 && addr < 0x1f801000) { + MOV32MtoR(EAX, (u32)&psxRegs.CP2D.r[_Rt_]); + MOV32RtoM((u32)&psxH[addr & 0xfff], EAX); + return; + } + } + + PUSH32M ((u32)&psxRegs.CP2D.r[_Rt_]); + iPushOfB(); + CALLFunc((u32)psxMemWrite32); +// ADD32ItoR(ESP, 8); + resp+= 8; +} + +static void recCFC2() { +// Rt = Cop2C->Rd + if (!_Rt_) return; + + iRegs[_Rt_].state = ST_UNK; + MOV32MtoR(EAX, (u32)&psxRegs.CP2C.r[_Rd_]); + MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX); +} + +static void recCTC2() { +// Cop2C->Rd = Rt + + if (IsConst(_Rt_)) { + MOV32ItoM((u32)&psxRegs.CP2C.r[_Rd_], iRegs[_Rt_].k); + } else { + MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]); + MOV32RtoM((u32)&psxRegs.CP2C.r[_Rd_], EAX); + } +} +#endif + +CP2_FUNCNC(RTPS); +CP2_FUNC(OP); +CP2_FUNCNC(NCLIP); +CP2_FUNCNC(DPCS); +CP2_FUNCNC(INTPL); +CP2_FUNC(MVMVA); +CP2_FUNCNC(NCDS); +CP2_FUNCNC(NCDT); +CP2_FUNCNC(CDP); +CP2_FUNCNC(NCCS); +CP2_FUNCNC(CC); +CP2_FUNCNC(NCS); +CP2_FUNCNC(NCT); +CP2_FUNC(SQR); +CP2_FUNCNC(DCPL); +CP2_FUNCNC(DPCT); +CP2_FUNCNC(AVSZ3); +CP2_FUNCNC(AVSZ4); +CP2_FUNCNC(RTPT); +CP2_FUNC(GPF); +CP2_FUNC(GPL); +CP2_FUNCNC(NCCT); + +#if 0 + +#define gteVX0 ((s16*)psxRegs.CP2D.r)[0] +#define gteVY0 ((s16*)psxRegs.CP2D.r)[1] +#define gteVZ0 ((s16*)psxRegs.CP2D.r)[2] +#define gteVX1 ((s16*)psxRegs.CP2D.r)[4] +#define gteVY1 ((s16*)psxRegs.CP2D.r)[5] +#define gteVZ1 ((s16*)psxRegs.CP2D.r)[6] +#define gteVX2 ((s16*)psxRegs.CP2D.r)[8] +#define gteVY2 ((s16*)psxRegs.CP2D.r)[9] +#define gteVZ2 ((s16*)psxRegs.CP2D.r)[10] +#define gteRGB psxRegs.CP2D.r[6] +#define gteOTZ ((s16*)psxRegs.CP2D.r)[7*2] +#define gteIR0 ((s32*)psxRegs.CP2D.r)[8] +#define gteIR1 ((s32*)psxRegs.CP2D.r)[9] +#define gteIR2 ((s32*)psxRegs.CP2D.r)[10] +#define gteIR3 ((s32*)psxRegs.CP2D.r)[11] +#define gteSX0 ((s16*)psxRegs.CP2D.r)[12*2] +#define gteSY0 ((s16*)psxRegs.CP2D.r)[12*2+1] +#define gteSX1 ((s16*)psxRegs.CP2D.r)[13*2] +#define gteSY1 ((s16*)psxRegs.CP2D.r)[13*2+1] +#define gteSX2 ((s16*)psxRegs.CP2D.r)[14*2] +#define gteSY2 ((s16*)psxRegs.CP2D.r)[14*2+1] +#define gteSXP ((s16*)psxRegs.CP2D.r)[15*2] +#define gteSYP ((s16*)psxRegs.CP2D.r)[15*2+1] +#define gteSZx ((u16*)psxRegs.CP2D.r)[16*2] +#define gteSZ0 ((u16*)psxRegs.CP2D.r)[17*2] +#define gteSZ1 ((u16*)psxRegs.CP2D.r)[18*2] +#define gteSZ2 ((u16*)psxRegs.CP2D.r)[19*2] +#define gteRGB0 psxRegs.CP2D.r[20] +#define gteRGB1 psxRegs.CP2D.r[21] +#define gteRGB2 psxRegs.CP2D.r[22] +#define gteMAC0 psxRegs.CP2D.r[24] +#define gteMAC1 ((s32*)psxRegs.CP2D.r)[25] +#define gteMAC2 ((s32*)psxRegs.CP2D.r)[26] +#define gteMAC3 ((s32*)psxRegs.CP2D.r)[27] +#define gteIRGB psxRegs.CP2D.r[28] +#define gteORGB psxRegs.CP2D.r[29] +#define gteLZCS psxRegs.CP2D.r[30] +#define gteLZCR psxRegs.CP2D.r[31] + +#define gteR ((u8 *)psxRegs.CP2D.r)[6*4] +#define gteG ((u8 *)psxRegs.CP2D.r)[6*4+1] +#define gteB ((u8 *)psxRegs.CP2D.r)[6*4+2] +#define gteCODE ((u8 *)psxRegs.CP2D.r)[6*4+3] +#define gteC gteCODE + +#define gteR0 ((u8 *)psxRegs.CP2D.r)[20*4] +#define gteG0 ((u8 *)psxRegs.CP2D.r)[20*4+1] +#define gteB0 ((u8 *)psxRegs.CP2D.r)[20*4+2] +#define gteCODE0 ((u8 *)psxRegs.CP2D.r)[20*4+3] +#define gteC0 gteCODE0 + +#define gteR1 ((u8 *)psxRegs.CP2D.r)[21*4] +#define gteG1 ((u8 *)psxRegs.CP2D.r)[21*4+1] +#define gteB1 ((u8 *)psxRegs.CP2D.r)[21*4+2] +#define gteCODE1 ((u8 *)psxRegs.CP2D.r)[21*4+3] +#define gteC1 gteCODE1 + +#define gteR2 ((u8 *)psxRegs.CP2D.r)[22*4] +#define gteG2 ((u8 *)psxRegs.CP2D.r)[22*4+1] +#define gteB2 ((u8 *)psxRegs.CP2D.r)[22*4+2] +#define gteCODE2 ((u8 *)psxRegs.CP2D.r)[22*4+3] +#define gteC2 gteCODE2 + + + +#define gteR11 ((s16*)psxRegs.CP2C.r)[0] +#define gteR12 ((s16*)psxRegs.CP2C.r)[1] +#define gteR13 ((s16*)psxRegs.CP2C.r)[2] +#define gteR21 ((s16*)psxRegs.CP2C.r)[3] +#define gteR22 ((s16*)psxRegs.CP2C.r)[4] +#define gteR23 ((s16*)psxRegs.CP2C.r)[5] +#define gteR31 ((s16*)psxRegs.CP2C.r)[6] +#define gteR32 ((s16*)psxRegs.CP2C.r)[7] +#define gteR33 ((s16*)psxRegs.CP2C.r)[8] +#define gteTRX ((s32*)psxRegs.CP2C.r)[5] +#define gteTRY ((s32*)psxRegs.CP2C.r)[6] +#define gteTRZ ((s32*)psxRegs.CP2C.r)[7] +#define gteL11 ((s16*)psxRegs.CP2C.r)[16] +#define gteL12 ((s16*)psxRegs.CP2C.r)[17] +#define gteL13 ((s16*)psxRegs.CP2C.r)[18] +#define gteL21 ((s16*)psxRegs.CP2C.r)[19] +#define gteL22 ((s16*)psxRegs.CP2C.r)[20] +#define gteL23 ((s16*)psxRegs.CP2C.r)[21] +#define gteL31 ((s16*)psxRegs.CP2C.r)[22] +#define gteL32 ((s16*)psxRegs.CP2C.r)[23] +#define gteL33 ((s16*)psxRegs.CP2C.r)[24] +#define gteRBK ((s32*)psxRegs.CP2C.r)[13] +#define gteGBK ((s32*)psxRegs.CP2C.r)[14] +#define gteBBK ((s32*)psxRegs.CP2C.r)[15] +#define gteLR1 ((s16*)psxRegs.CP2C.r)[32] +#define gteLR2 ((s16*)psxRegs.CP2C.r)[33] +#define gteLR3 ((s16*)psxRegs.CP2C.r)[34] +#define gteLG1 ((s16*)psxRegs.CP2C.r)[35] +#define gteLG2 ((s16*)psxRegs.CP2C.r)[36] +#define gteLG3 ((s16*)psxRegs.CP2C.r)[37] +#define gteLB1 ((s16*)psxRegs.CP2C.r)[38] +#define gteLB2 ((s16*)psxRegs.CP2C.r)[39] +#define gteLB3 ((s16*)psxRegs.CP2C.r)[40] +#define gteRFC ((s32*)psxRegs.CP2C.r)[21] +#define gteGFC ((s32*)psxRegs.CP2C.r)[22] +#define gteBFC ((s32*)psxRegs.CP2C.r)[23] +#define gteOFX ((s32*)psxRegs.CP2C.r)[24] +#define gteOFY ((s32*)psxRegs.CP2C.r)[25] +#define gteH ((u16*)psxRegs.CP2C.r)[52] +#define gteDQA ((s16*)psxRegs.CP2C.r)[54] +#define gteDQB ((s32*)psxRegs.CP2C.r)[28] +#define gteZSF3 ((s16*)psxRegs.CP2C.r)[58] +#define gteZSF4 ((s16*)psxRegs.CP2C.r)[60] +#define gteFLAG psxRegs.CP2C.r[31] + +//#define SUM_FLAG if(gteFLAG & 0x7F87E000) gteFLAG |= 0x80000000; + +#define SUM_FLAG() { \ + TEST32ItoM((u32)>eFLAG, 0x7F87E000); \ + j8Ptr[0] = JZ8(0); \ + OR32ItoM((u32)>eFLAG, 0x80000000); \ + \ + x86SetJ8(j8Ptr[0]); \ +} + +#define LIM32X8(reg, gteout, negv, posv, flagb) { \ + CMP32ItoR(reg, negv); \ + j8Ptr[0] = JL8(0); \ + CMP32ItoR(reg, posv); \ + j8Ptr[1] = JG8(0); \ + \ + MOV8RtoM((u32)>eout, reg); \ + j8Ptr[2] = JMP8(0); \ + \ + x86SetJ8(j8Ptr[0]); \ + MOV8ItoM((u32)>eout, negv); \ + j8Ptr[3] = JMP8(0); \ + \ + x86SetJ8(j8Ptr[1]); \ + MOV8ItoM((u32)>eout, posv); \ + \ + x86SetJ8(j8Ptr[3]); \ + OR32ItoM((u32)>eFLAG, 1<<flagb); \ + \ + x86SetJ8(j8Ptr[2]); \ +} + +#define _LIM_B1(reg, gteout) LIM32X8(reg, gteout, 0, 255, 21); +#define _LIM_B2(reg, gteout) LIM32X8(reg, gteout, 0, 255, 20); +#define _LIM_B3(reg, gteout) LIM32X8(reg, gteout, 0, 255, 19); + +#define MAC2IRn(reg, ir, flagb, negv, posv) { \ +/* CMP32ItoR(reg, negv);*/ \ +/* j8Ptr[0] = JL8(0); */\ +/* CMP32ItoR(reg, posv);*/ \ +/* j8Ptr[1] = JG8(0);*/ \ + \ + MOV32RtoM((u32)&ir, reg); \ +/* j8Ptr[2] = JMP8(0);*/ \ + \ +/* x86SetJ8(j8Ptr[0]);*/ \ +/* MOV32ItoM((u32)&ir, negv);*/ \ +/* j8Ptr[3] = JMP8(0);*/ \ + \ +/* x86SetJ8(j8Ptr[1]);*/ \ +/* MOV32ItoM((u32)&ir, posv);*/ \ + \ +/* x86SetJ8(j8Ptr[3]);*/ \ +/* OR32ItoR((u32)>eFLAG, 1<<flagb);*/ \ + \ +/* x86SetJ8(j8Ptr[2]);*/ \ +} + + + +#define gte_C11 gteLR1 +#define gte_C12 gteLR2 +#define gte_C13 gteLR3 +#define gte_C21 gteLG1 +#define gte_C22 gteLG2 +#define gte_C23 gteLG3 +#define gte_C31 gteLB1 +#define gte_C32 gteLB2 +#define gte_C33 gteLB3 + + +#define _MVMVA_FUNC(vn, mx) { \ + MOVSX32M16toR(EAX, (u32)&mx##vn##1); \ + IMUL32R(EBX); \ +/* j8Ptr[0] = JO8(0);*/ \ + MOV32RtoR(ECX, EAX); \ + \ + MOVSX32M16toR(EAX, (u32)&mx##vn##2); \ + IMUL32R(EDI); \ +/* j8Ptr[1] = JO8(0);*/ \ + ADD32RtoR(ECX, EAX); \ +/* j8Ptr[2] = JO8(0);*/ \ + \ + MOVSX32M16toR(EAX, (u32)&mx##vn##3); \ + IMUL32R(ESI); \ +/* j8Ptr[3] = JO8(0);*/ \ + ADD32RtoR(ECX, EAX); \ +/* j8Ptr[4] = JO8(0);*/ \ +} + +/* SSX = (_v0) * mx##11 + (_v1) * mx##12 + (_v2) * mx##13; + SSY = (_v0) * mx##21 + (_v1) * mx##22 + (_v2) * mx##23; + SSZ = (_v0) * mx##31 + (_v1) * mx##32 + (_v2) * mx##33; */ + +#define _MVMVA_ADD(_vx, jn) { \ + ADD32MtoR(ECX, (u32)&_vx); \ +/* j8Ptr[jn] = JO8(0);*/ \ +} +/* SSX+= gteRFC; + SSY+= gteGFC; + SSZ+= gteBFC;*/ + +#define _MVMVA1(vn) { \ + switch (psxRegs.code & 0x60000) { \ + case 0x00000: /* R */ \ + _MVMVA_FUNC(vn, gteR); break; \ + case 0x20000: /* L */ \ + _MVMVA_FUNC(vn, gteL); break; \ + case 0x40000: /* C */ \ + _MVMVA_FUNC(vn, gte_C); break; \ + default: \ + return; \ + } \ +} + +#define _MVMVA_LOAD(_v0, _v1, _v2) { \ + MOVSX32M16toR(EBX, (u32)&_v0); \ + MOVSX32M16toR(EDI, (u32)&_v1); \ + MOVSX32M16toR(ESI, (u32)&_v2); \ +} + +static void recMVMVA() { + int i; + +// SysPrintf("GTE_MVMVA %lx\n", psxRegs.code & 0x1ffffff); + +/* PUSH32R(ESI); + PUSH32R(EDI); + PUSH32R(EBX); +*/ + XOR32RtoR(EAX, EAX); /* gteFLAG = 0 */ + MOV32RtoM((u32)>eFLAG, EAX); + + switch (psxRegs.code & 0x18000) { + case 0x00000: /* V0 */ + _MVMVA_LOAD(gteVX0, gteVY0, gteVZ0); break; + case 0x08000: /* V1 */ + _MVMVA_LOAD(gteVX1, gteVY1, gteVZ1); break; + case 0x10000: /* V2 */ + _MVMVA_LOAD(gteVX2, gteVY2, gteVZ2); break; + case 0x18000: /* IR */ + _MVMVA_LOAD(gteIR1, gteIR2, gteIR3); break; + } + +// MAC1 + for (i=5; i<8; i++) j8Ptr[i] = 0; + _MVMVA1(1); + + if (psxRegs.code & 0x80000) { + SAR32ItoR(ECX, 12); +// SSX /= 4096.0; SSY /= 4096.0; SSZ /= 4096.0; + } + + switch (psxRegs.code & 0x6000) { + case 0x0000: // Add TR + _MVMVA_ADD(gteTRX, 5); break; + case 0x2000: // Add BK + _MVMVA_ADD(gteRBK, 6); break; + case 0x4000: // Add FC + _MVMVA_ADD(gteRFC, 7); break; + } +/* + j8Ptr[9] = JMP8(0); + for (i=0; i<5; i++) x86SetJ8(j8Ptr[i]); + for (i=5; i<8; i++) if (j8Ptr[i]) x86SetJ8(j8Ptr[i]); + +// TEST32ItoR(EDX, 0x80000000); + OR32ItoM((u32)>eFLAG, 1<<29); + x86SetJ8(j8Ptr[9]);*/ + MOV32RtoM((u32)>eMAC1, ECX); + + if (psxRegs.code & 0x400) { + MAC2IRn(ECX, gteIR1, 24, 0, 32767); + } else { + MAC2IRn(ECX, gteIR1, 24, -32768, 32767); + } + +// MAC2 + _MVMVA1(2); + + if (psxRegs.code & 0x80000) { + SAR32ItoR(ECX, 12); +// SSX /= 4096.0; SSY /= 4096.0; SSZ /= 4096.0; + } + + switch (psxRegs.code & 0x6000) { + case 0x0000: // Add TR + _MVMVA_ADD(gteTRY, 5); break; + case 0x2000: // Add BK + _MVMVA_ADD(gteGBK, 6); break; + case 0x4000: // Add FC + _MVMVA_ADD(gteGFC, 7); break; + } + +/* for (i=0; i<5; i++) x86SetJ8(j8Ptr[i]); + for (i=5; i<8; i++) if (j8Ptr[i]) x86SetJ8(j8Ptr[i]);*/ + MOV32RtoM((u32)>eMAC2, ECX); + + if (psxRegs.code & 0x400) { + MAC2IRn(ECX, gteIR2, 23, 0, 32767); + } else { + MAC2IRn(ECX, gteIR2, 23, -32768, 32767); + } + +// MAC3 + _MVMVA1(3); + + if (psxRegs.code & 0x80000) { + SAR32ItoR(ECX, 12); +// SSX /= 4096.0; SSY /= 4096.0; SSZ /= 4096.0; + } + + switch (psxRegs.code & 0x6000) { + case 0x0000: // Add TR + _MVMVA_ADD(gteTRZ, 5); break; + case 0x2000: // Add BK + _MVMVA_ADD(gteBBK, 6); break; + case 0x4000: // Add FC + _MVMVA_ADD(gteBFC, 7); break; + } + +/* for (i=0; i<5; i++) x86SetJ8(j8Ptr[i]); + for (i=5; i<8; i++) if (j8Ptr[i]) x86SetJ8(j8Ptr[i]);*/ + MOV32RtoM((u32)>eMAC3, ECX); + + if (psxRegs.code & 0x400) { + MAC2IRn(ECX, gteIR3, 22, 0, 32767); + } else { + MAC2IRn(ECX, gteIR3, 22, -32768, 32767); + } +/* MAC2IR1() + else MAC2IR()*/ + +// SUM_FLAG(); + +/* POP32R(EBX); + POP32R(EDI); + POP32R(ESI);*/ +} + +#if 0 + +#define _GPF1(vn) { \ + MOV32MtoR(EAX, (u32)>eIR##vn); \ + IMUL32R(ECX); \ +/* MOV32RtoR(ECX, EAX); */\ +} + +static void recGPF() { +// SysPrintf("GTE_GPF %lx\n", psxRegs.code & 0x1ffffff); + + PUSH32R(EBX); + + XOR32RtoR(EBX, EBX); /* gteFLAG = 0 */ + +/* gteMAC1 = NC_OVERFLOW1(gteIR0 * gteIR1); + gteMAC2 = NC_OVERFLOW2(gteIR0 * gteIR2); + gteMAC3 = NC_OVERFLOW3(gteIR0 * gteIR3);*/ + MOV32MtoR(ECX, (u32)>eIR0); +// MAC1 + _GPF1(1); + + if (psxRegs.code & 0x80000) { + SAR32ItoR(EAX, 12); + } + MAC2IRn(EAX, gteIR1, 24, -32768, 32767); + PUSH32R(EAX); + +// MAC2 + _GPF1(2); + + if (psxRegs.code & 0x80000) { + SAR32ItoR(EAX, 12); + } + MAC2IRn(EAX, gteIR2, 23, -32768, 32767); + PUSH32R(EAX); + +// MAC3 + _GPF1(3); + + if (psxRegs.code & 0x80000) { + SAR32ItoR(EAX, 12); + } + MAC2IRn(EAX, gteIR3, 22, -32768, 32767); +// MAC2IR(); + +// gteRGB0 = gteRGB1; +// gteRGB1 = gteRGB2; + MOV32MtoR(EDX, (u32)>eRGB1); + MOV32MtoR(ECX, (u32)>eRGB2); + MOV32RtoM((u32)>eRGB0, EDX); + MOV32RtoM((u32)>eRGB1, ECX); + + POP32R(EDX); + POP32R(ECX); + SAR32ItoR(ECX, 4); + SAR32ItoR(EDX, 4); + SAR32ItoR(EAX, 4); + + _LIM_B1(ECX, gteR2); + _LIM_B2(EDX, gteG2); + _LIM_B3(EAX, gteB2); + MOV8MtoR(EAX, (u32)>eCODE); + MOV8RtoM((u32)>eCODE2, EAX); + +/* gteR2 = limB1(gteMAC1 / 16.0f); + gteG2 = limB2(gteMAC2 / 16.0f); + gteB2 = limB3(gteMAC3 / 16.0f); gteCODE2 = gteCODE;*/ + + SUM_FLAG(); + MOV32RtoM((u32)>eFLAG, EBX); + +// POP32R(EBX); +} +#endif +#endif diff --git a/libpcsxcore/ppc/pR3000A.c b/libpcsxcore/ppc/pR3000A.c new file mode 100644 index 00000000..60225f98 --- /dev/null +++ b/libpcsxcore/ppc/pR3000A.c @@ -0,0 +1,3528 @@ +/* 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 Steet, Fifth Floor, Boston, MA 02111-1307 USA + */ + +#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; + 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; + 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; + 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; + 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; + //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; + 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; + //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; + + LIW(PutHWReg32(_Rt_), (u32)&psxCounters[(addr >> 4) & 0x3].mode); + LWZ(PutHWReg32(_Rt_), 0, GetHWReg32(_Rt_)); + return; + + case 0x1f801108: case 0x1f801118: case 0x1f801128: + if (!_Rt_) return; + + LIW(PutHWReg32(_Rt_), (u32)&psxCounters[(addr >> 4) & 0x3].target); + LWZ(PutHWReg32(_Rt_), 0, GetHWReg32(_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; + 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 +}; + diff --git a/libpcsxcore/ppc/pasm.s b/libpcsxcore/ppc/pasm.s new file mode 100644 index 00000000..96891b42 --- /dev/null +++ b/libpcsxcore/ppc/pasm.s @@ -0,0 +1,124 @@ + + +#define OLD_REGISTER_OFFSET (19*4) +#define SP_SIZE (OLD_REGISTER_OFFSET+4+8) + +/*asm void recRun(register void (*func)(), register u32 hw1, register u32 hw2)*/ + .text + .align 4 + .globl recRun +recRun: + /* prologue code */ + mflr r0 + stmw r13, -(32-13)*4(r1) + stw r0, 4(r1) + stwu r1, -((32-13)*4+8)(r1) + + /* execute code */ + mtctr r3 + mr r31, r4 + mr r30, r5 + bctrl +/* +} +asm void returnPC() +{*/ + .text + .align 4 + .globl returnPC +returnPC: + // end code + lwz r0, (32-13)*4+8+4(r1) + addi r1, r1, (32-13)*4+8 + mtlr r0 + lmw r13, -(32-13)*4(r1) + blr +//}*/ + +// Memory functions that only works with a linear memory + + .text + .align 4 + .globl dynMemRead8 +dynMemRead8: +// assumes that memory pointer is in r30 + addis r2,r3,-0x1f80 + srwi. r4,r2,16 + bne+ .norm8 + cmplwi r2,0x1000 + blt- .norm8 + b psxHwRead8 +.norm8: + clrlwi r5,r3,3 + lbzx r3,r5,r30 + blr + + .text + .align 4 + .globl dynMemRead16 +dynMemRead16: +// assumes that memory pointer is in r30 + addis r2,r3,-0x1f80 + srwi. r4,r2,16 + bne+ .norm16 + cmplwi r2,0x1000 + blt- .norm16 + b psxHwRead16 +.norm16: + clrlwi r5,r3,3 + lhbrx r3,r5,r30 + blr + + .text + .align 4 + .globl dynMemRead32 +dynMemRead32: +// assumes that memory pointer is in r30 + addis r2,r3,-0x1f80 + srwi. r4,r2,16 + bne+ .norm32 + cmplwi r2,0x1000 + blt- .norm32 + b psxHwRead32 +.norm32: + clrlwi r5,r3,3 + lwbrx r3,r5,r30 + blr + +/* + N P Z + 0 0 0 X +- 0 0 1 X + 1 0 0 X + 1 0 1 X + +P | (!N & Z) +P | !(N | !Z) +*/ + + .text + .align 4 + .globl dynMemWrite32 +dynMemWrite32: +// assumes that memory pointer is in r30 + addis r2,r3,-0x1f80 + srwi. r5,r2,16 + bne+ .normw32 + cmplwi r2,0x1000 + blt .normw32 + b psxHwWrite32 +.normw32: + mtcrf 0xFF, r3 + clrlwi r5,r3,3 + crandc 0, 2, 0 + cror 2, 1, 0 + bne+ .okw32 + // write test + li r2,0x0130 + addis r2,r2,0xfffe + cmplw r3,r2 + bnelr +.okw32: + stwbrx r4,r5,r30 + blr + diff --git a/libpcsxcore/ppc/ppc.c b/libpcsxcore/ppc/ppc.c new file mode 100644 index 00000000..efaf8b6d --- /dev/null +++ b/libpcsxcore/ppc/ppc.c @@ -0,0 +1,32 @@ +/* + * ix86 core v0.5.1 + * Authors: linuzappz <linuzappz@pcsx.net> + * alexey silinov + */ + +#include <stdio.h> +#include <string.h> + +#include "ppc.h" + +// General Purpose hardware registers +int cpuHWRegisters[NUM_HW_REGISTERS] = { + 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, + 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 +}; + +u32 *ppcPtr; + +void ppcInit() { +} +void ppcSetPtr(u32 *ptr) { + ppcPtr = ptr; +} +void ppcAlign(int bytes) { + // forward align + ppcPtr = (u32*)(((u32)ppcPtr + bytes) & ~(bytes - 1)); +} + +void ppcShutdown() { +} + diff --git a/libpcsxcore/ppc/ppc.h b/libpcsxcore/ppc/ppc.h new file mode 100644 index 00000000..8385da5b --- /dev/null +++ b/libpcsxcore/ppc/ppc.h @@ -0,0 +1,74 @@ +/* + * ppc definitions v0.5.1 + * Authors: linuzappz <linuzappz@pcsx.net> + * alexey silinov + */ + +#ifndef __PPC_H__ +#define __PPC_H__ + +// include basic types +#include "../psxcommon.h" +#include "ppc_mnemonics.h" + +#define NUM_HW_REGISTERS 29 + +/* general defines */ +#define write8(val) *(u8 *)ppcPtr = val; ppcPtr++; +#define write16(val) *(u16*)ppcPtr = val; ppcPtr+=2; +#define write32(val) *(u32*)ppcPtr = val; ppcPtr+=4; +#define write64(val) *(u64*)ppcPtr = val; ppcPtr+=8; + +#define CALLFunc(FUNC) \ +{ \ + u32 _func = (FUNC); \ + ReleaseArgs(); \ + if ((_func & 0x1fffffc) == _func) { \ + BLA(_func); \ + } else { \ + LIW(0, _func); \ + MTCTR(0); \ + BCTRL(); \ + } \ +} + +extern int cpuHWRegisters[NUM_HW_REGISTERS]; + +extern u32 *ppcPtr; +extern u8 *j8Ptr[32]; +extern u32 *j32Ptr[32]; + +void ppcInit(); +void ppcSetPtr(u32 *ptr); +void ppcShutdown(); + +void ppcAlign(int bytes); +void returnPC(); +void recRun(void (*func)(), u32 hw1, u32 hw2); +u8 dynMemRead8(u32 mem); +u16 dynMemRead16(u32 mem); +u32 dynMemRead32(u32 mem); +void dynMemWrite32(u32 mem, u32 val); + +#endif /* __PPC_H__ */ + + + + + + + + + + + + + + + + + + + + + diff --git a/libpcsxcore/ppc/ppc_mnemonics.h b/libpcsxcore/ppc/ppc_mnemonics.h new file mode 100644 index 00000000..3cc65258 --- /dev/null +++ b/libpcsxcore/ppc/ppc_mnemonics.h @@ -0,0 +1,529 @@ +// ppc_mnemonics.h + +#define INSTR (*(ppcPtr)++) + +/* Link register related */ +#define MFLR(REG) \ + {int _reg = (REG); \ + INSTR = (0x7C0802A6 | (_reg << 21));} + +#define MTLR(REG) \ + {int _reg = (REG); \ + INSTR = (0x7C0803A6 | (_reg << 21));} + +#define MTCTR(REG) \ + {int _reg = (REG); \ + INSTR = (0x7C0903A6 | (_reg << 21));} + +#define BLR() \ + {INSTR = (0x4E800020);} + +#define BGTLR() \ + {INSTR = (0x4D810020);} + + +/* Load ops */ +#define LI(REG, IMM) \ + {int _reg = (REG); \ + INSTR = (0x38000000 | (_reg << 21) | ((IMM) & 0xffff));} + +#define LIS(REG_DST, IMM) \ + {int _dst = (REG_DST); \ + INSTR = (0x3C000000 | (_dst << 21) | ((IMM) & 0xffff));} + +#define LWZ(REG_DST, OFFSET, REG) \ + {int _reg = (REG); int _dst=(REG_DST); \ + INSTR = (0x80000000 | (_dst << 21) | (_reg << 16) | ((OFFSET) & 0xffff));} + +#define LWZX(REG_DST, REG, REG_OFF) \ + {int _reg = (REG), _off = (REG_OFF); int _dst=(REG_DST); \ + INSTR = (0x7C00002E | (_dst << 21) | (_reg << 16) | (_off << 11));} + +#define LWBRX(REG_DST, REG, REG_OFF) \ + {int _reg = (REG), _off = (REG_OFF); int _dst=(REG_DST); \ + INSTR = (0x7C00042C | (_dst << 21) | (_reg << 16) | (_off << 11));} + +#define LHZ(REG_DST, OFFSET, REG) \ + {int _reg = (REG); int _dst=(REG_DST); \ + INSTR = (0xA0000000 | (_dst << 21) | (_reg << 16) | ((OFFSET) & 0xffff));} + +#define LHA(REG_DST, OFFSET, REG) \ + {int _reg = (REG); int _dst=(REG_DST); \ + INSTR = (0xA8000000 | (_dst << 21) | (_reg << 16) | ((OFFSET) & 0xffff));} + +#define LHBRX(REG_DST, REG, REG_OFF) \ + {int _reg = (REG), _off = (REG_OFF); int _dst=(REG_DST); \ + INSTR = (0x7C00062C | (_dst << 21) | (_reg << 16) | (_off << 11));} + +#define LBZ(REG_DST, OFFSET, REG) \ + {int _reg = (REG); int _dst=(REG_DST); \ + INSTR = (0x88000000 | (_dst << 21) | (_reg << 16) | ((OFFSET) & 0xffff));} + +#define LMW(REG_DST, OFFSET, REG) \ + {int _reg = (REG); int _dst=(REG_DST); \ + INSTR = (0xB8000000 | (_dst << 21) | (_reg << 16) | ((OFFSET) & 0xffff));} + + + +/* Store ops */ +#define STMW(REG_SRC, OFFSET, REG) \ + {int _reg = (REG), _src=(REG_SRC); \ + INSTR = (0xBC000000 | (_src << 21) | (_reg << 16) | ((OFFSET) & 0xffff));} + +#define STW(REG_SRC, OFFSET, REG) \ + {int _reg = (REG), _src=(REG_SRC); \ + INSTR = (0x90000000 | (_src << 21) | (_reg << 16) | ((OFFSET) & 0xffff));} + +#define STWBRX(REG_SRC, REG, REG_OFF) \ + {int _reg = (REG), _src=(REG_SRC), _off = (REG_OFF); \ + INSTR = (0x7C00052C | (_src << 21) | (_reg << 16) | (_off << 11));} + +#define STH(REG_SRC, OFFSET, REG) \ + {int _reg = (REG), _src=(REG_SRC); \ + INSTR = (0xB0000000 | (_src << 21) | (_reg << 16) | ((OFFSET) & 0xffff));} + +#define STHBRX(REG_SRC, REG, REG_OFF) \ + {int _reg = (REG), _src=(REG_SRC), _off = (REG_OFF); \ + INSTR = (0x7C00072C | (_src << 21) | (_reg << 16) | (_off << 11));} + +#define STB(REG_SRC, OFFSET, REG) \ + {int _reg = (REG), _src=(REG_SRC); \ + INSTR = (0x98000000 | (_src << 21) | (_reg << 16) | ((OFFSET) & 0xffff));} + +#define STWU(REG_SRC, OFFSET, REG) \ + {int _reg = (REG), _src=(REG_SRC); \ + INSTR = (0x94000000 | (_src << 21) | (_reg << 16) | ((OFFSET) & 0xffff));} + + +/* Arithmic ops */ +#define ADDI(REG_DST, REG_SRC, IMM) \ + {int _src = (REG_SRC); int _dst=(REG_DST); \ + INSTR = (0x38000000 | (_dst << 21) | (_src << 16) | ((IMM) & 0xffff));} + +#define ADDIS(REG_DST, REG_SRC, IMM) \ + {int _src = (REG_SRC); int _dst=(REG_DST); \ + INSTR = (0x3C000000 | (_dst << 21) | (_src << 16) | ((IMM) & 0xffff));} + +#define MR(REG_DST, REG_SRC) \ + {int __src = (REG_SRC); int __dst=(REG_DST); \ + if (__src != __dst) {ADDI(__dst, __src, 0)}} + +#define ADD(REG_DST, REG1, REG2) \ + {int _reg1 = (REG1), _reg2 = (REG2); int _dst=(REG_DST); \ + INSTR = (0x7C000214 | (_dst << 21) | (_reg1 << 16) | (_reg2 << 11));} + +#define ADDO(REG_DST, REG1, REG2) \ + {int _reg1 = (REG1), _reg2 = (REG2); int _dst=(REG_DST); \ + INSTR = (0x7C000614 | (_dst << 21) | (_reg1 << 16) | (_reg2 << 11));} + +#define ADDEO(REG_DST, REG1, REG2) \ + {int _reg1 = (REG1), _reg2 = (REG2); int _dst=(REG_DST); \ + INSTR = (0x7C000514 | (_dst << 21) | (_reg1 << 16) | (_reg2 << 11));} + +#define ADDE(REG_DST, REG1, REG2) \ + {int _reg1 = (REG1), _reg2 = (REG2); int _dst=(REG_DST); \ + INSTR = (0x7C000114 | (_dst << 21) | (_reg1 << 16) | (_reg2 << 11));} + +#define ADDCO(REG_DST, REG1, REG2) \ + {int _reg1 = (REG1), _reg2 = (REG2); int _dst=(REG_DST); \ + INSTR = (0x7C000414 | (_dst << 21) | (_reg1 << 16) | (_reg2 << 11));} + +#define ADDIC(REG_DST, REG_SRC, IMM) \ + {int _src = (REG_SRC); int _dst=(REG_DST); \ + INSTR = (0x30000000 | (_dst << 21) | (_src << 16) | ((IMM) & 0xffff));} + +#define ADDIC_(REG_DST, REG_SRC, IMM) \ + {int _src = (REG_SRC); int _dst=(REG_DST); \ + INSTR = (0x34000000 | (_dst << 21) | (_src << 16) | ((IMM) & 0xffff));} + +#define ADDZE(REG_DST, REG_SRC) \ + {int _src = (REG_SRC); int _dst=(REG_DST); \ + INSTR = (0x7C000194 | (_dst << 21) | (_src << 16));} + +#define SUBF(REG_DST, REG1, REG2) \ + {int _reg1 = (REG1), _reg2 = (REG2); int _dst=(REG_DST); \ + INSTR = (0x7C000050 | (_dst << 21) | (_reg1 << 16) | (_reg2 << 11));} + +#define SUBFO(REG_DST, REG1, REG2) \ + {int _reg1 = (REG1), _reg2 = (REG2); int _dst=(REG_DST); \ + INSTR = (0x7C000450 | (_dst << 21) | (_reg1 << 16) | (_reg2 << 11));} + +#define SUBFC(REG_DST, REG1, REG2) \ + {int _reg1 = (REG1), _reg2 = (REG2); int _dst=(REG_DST); \ + INSTR = (0x7C000010 | (_dst << 21) | (_reg1 << 16) | (_reg2 << 11));} + +#define SUBFE(REG_DST, REG1, REG2) \ + {int _reg1 = (REG1), _reg2 = (REG2); int _dst=(REG_DST); \ + INSTR = (0x7C000110 | (_dst << 21) | (_reg1 << 16) | (_reg2 << 11));} + +#define SUBFCO(REG_DST, REG1, REG2) \ + {int _reg1 = (REG1), _reg2 = (REG2); int _dst=(REG_DST); \ + INSTR = (0x7C000410 | (_dst << 21) | (_reg1 << 16) | (_reg2 << 11));} + +#define SUBFCO_(REG_DST, REG1, REG2) \ + {int _reg1 = (REG1), _reg2 = (REG2); int _dst=(REG_DST); \ + INSTR = (0x7C000411 | (_dst << 21) | (_reg1 << 16) | (_reg2 << 11));} + +#define SUB(REG_DST, REG1, REG2) \ + {SUBF(REG_DST, REG2, REG1)} + +#define SUBO(REG_DST, REG1, REG2) \ + {SUBFO(REG_DST, REG2, REG1)} + +#define SUBCO(REG_DST, REG1, REG2) \ + {SUBFCO(REG_DST, REG2, REG1)} + +#define SUBCO_(REG_DST, REG1, REG2) \ + {SUBFCO_(REG_DST, REG2, REG1)} + +#define SRAWI(REG_DST, REG_SRC, SHIFT) \ + {int _src = (REG_SRC); int _dst=(REG_DST); \ + INSTR = (0x7C000670 | (_src << 21) | (_dst << 16) | (SHIFT << 11));} + +#define MULHW(REG_DST, REG1, REG2) \ + {int _reg1 = (REG1), _reg2 = (REG2); int _dst=(REG_DST); \ + INSTR = (0x7C000096 | (_dst << 21) | (_reg1 << 16) | (_reg2 << 11));} + +#define MULLW(REG_DST, REG1, REG2) \ + {int _reg1 = (REG1), _reg2 = (REG2); int _dst=(REG_DST); \ + INSTR = (0x7C0001D6 | (_dst << 21) | (_reg1 << 16) | (_reg2 << 11));} + +#define MULHWU(REG_DST, REG1, REG2) \ + {int _reg1 = (REG1), _reg2 = (REG2); int _dst=(REG_DST); \ + INSTR = (0x7C000016 | (_dst << 21) | (_reg1 << 16) | (_reg2 << 11));} + +#define MULLI(REG_DST, REG_SRC, IMM) \ + {int _src = (REG_SRC); int _dst=(REG_DST); \ + INSTR = (0x1C000000 | (_dst << 21) | (_src << 16) | ((IMM) & 0xffff));} + +#define DIVW(REG_DST, REG1, REG2) \ + {int _reg1 = (REG1), _reg2 = (REG2); int _dst=(REG_DST); \ + INSTR = (0x7C0003D6 | (_dst << 21) | (_reg1 << 16) | (_reg2 << 11));} + +#define DIVWU(REG_DST, REG1, REG2) \ + {int _reg1 = (REG1), _reg2 = (REG2); int _dst=(REG_DST); \ + INSTR = (0x7C000396 | (_dst << 21) | (_reg1 << 16) | (_reg2 << 11));} + + +/* Branch ops */ +#define B_FROM(VAR) VAR = ppcPtr +#define B_DST(VAR) *VAR = *VAR | (((s16)((u32)ppcPtr - (u32)VAR)) & 0xfffc) + +#define B(DST) \ + {INSTR = (0x48000000 | (((s32)(((DST)+1)<<2)) & 0x3fffffc));} + +#define B_L(VAR) \ + {B_FROM(VAR); INSTR = (0x48000000);} + +#define BA(DST) \ + {INSTR = (0x48000002 | ((s32)((DST) & 0x3fffffc)));} + +#define BLA(DST) \ + {INSTR = (0x48000003 | ((s32)((DST) & 0x3fffffc)));} + +#define BNS(DST) \ + {INSTR = (0x40830000 | (((s16)(((DST)+1)<<2)) & 0xfffc));} + +#define BNE(DST) \ + {INSTR = (0x40820000 | (((s16)(((DST)+1)<<2)) & 0xfffc));} + +#define BNE_L(VAR) \ + {B_FROM(VAR); INSTR = (0x40820000);} + +#define BEQ(DST) \ + {INSTR = (0x41820000 | (((s16)(((DST)+1)<<2)) & 0xfffc));} + +#define BEQ_L(VAR) \ + {B_FROM(VAR); INSTR = (0x41820000);} + +#define BLT(DST) \ + {INSTR = (0x41800000 | (((s16)(((DST)+1)<<2)) & 0xfffc));} + +#define BLT_L(VAR) \ + {B_FROM(VAR); INSTR = (0x41800000);} + +#define BGT(DST) \ + {INSTR = (0x41810000 | (((s16)(((DST)+1)<<2)) & 0xfffc));} + +#define BGT_L(VAR) \ + {B_FROM(VAR); INSTR = (0x41810000);} + +#define BGE(DST) \ + {INSTR = (0x40800000 | (((s16)(((DST)+1)<<2)) & 0xfffc));} + +#define BGE_L(VAR) \ + {B_FROM(VAR); INSTR = (0x40800000);} + +#define BLE(DST) \ + {INSTR = (0x40810000 | (((s16)(((DST)+1)<<2)) & 0xfffc));} + +#define BLE_L(VAR) \ + {B_FROM(VAR); INSTR = (0x40810000);} + +#define BCTRL() \ + {INSTR = (0x4E800421);} + +#define BCTR() \ + {INSTR = (0x4E800420);} + + +/* compare ops */ +#define CMPLWI(REG, IMM) \ + {int _reg = (REG); \ + INSTR = (0x28000000 | (_reg << 16) | ((IMM) & 0xffff));} + +#define CMPLWI2(REG, IMM) \ + {int _reg = (REG); \ + INSTR = (0x29000000 | (_reg << 16) | ((IMM) & 0xffff));} + +#define CMPLWI7(REG, IMM) \ + {int _reg = (REG); \ + INSTR = (0x2B800000 | (_reg << 16) | ((IMM) & 0xffff));} + +#define CMPLW(REG1, REG2) \ + {int _reg1 = (REG1), _reg2 = (REG2); \ + INSTR = (0x7C000040 | (_reg1 << 16) | (_reg2 << 11));} + +#define CMPLW1(REG1, REG2) \ + {int _reg1 = (REG1), _reg2 = (REG2); \ + INSTR = (0x7C800040 | (_reg1 << 16) | (_reg2 << 11));} + +#define CMPLW2(REG1, REG2) \ + {int _reg1 = (REG1), _reg2 = (REG2); \ + INSTR = (0x7D000040 | (_reg1 << 16) | (_reg2 << 11));} + +#define CMPW(REG1, REG2) \ + {int _reg1 = (REG1), _reg2 = (REG2); \ + INSTR = (0x7C000000 | (_reg1 << 16) | (_reg2 << 11));} + +#define CMPW1(REG1, REG2) \ + {int _reg1 = (REG1), _reg2 = (REG2); \ + INSTR = (0x7C800000 | (_reg1 << 16) | (_reg2 << 11));} + +#define CMPW2(REG1, REG2) \ + {int _reg1 = (REG1), _reg2 = (REG2); \ + INSTR = (0x7D000000 | (_reg1 << 16) | (_reg2 << 11));} + +#define CMPWI(REG, IMM) \ + {int _reg = (REG); \ + INSTR = (0x2C000000 | (_reg << 16) | ((IMM) & 0xffff));} + +#define CMPWI2(REG, IMM) \ + {int _reg = (REG); \ + INSTR = (0x2D000000 | (_reg << 16) | ((IMM) & 0xffff));} + +#define MTCRF(MASK, REG) \ + {int _reg = (REG); \ + INSTR = (0x7C000120 | (_reg << 21) | (((MASK)&0xff)<<12));} + +#define MFCR(REG) \ + {int _reg = (REG); \ + INSTR = (0x7C000026 | (_reg << 21));} + +#define CROR(CR_DST, CR1, CR2) \ + {INSTR = (0x4C000382 | ((CR_DST) << 21) | ((CR1) << 16) | ((CR2) << 11));} + +#define CRXOR(CR_DST, CR1, CR2) \ + {INSTR = (0x4C000182 | ((CR_DST) << 21) | ((CR1) << 16) | ((CR2) << 11));} + +#define CRNAND(CR_DST, CR1, CR2) \ + {INSTR = (0x4C0001C2 | ((CR_DST) << 21) | ((CR1) << 16) | ((CR2) << 11));} + +#define CRANDC(CR_DST, CR1, CR2) \ + {INSTR = (0x4C000102 | ((CR_DST) << 21) | ((CR1) << 16) | ((CR2) << 11));} + + +/* shift ops */ +#define RLWINM(REG_DST, REG_SRC, SHIFT, START, END) \ + {int _src = (REG_SRC); int _dst = (REG_DST); \ + INSTR = (0x54000000 | (_src << 21) | (_dst << 16) | (SHIFT << 11) | (START << 6) | (END << 1));} + +#define RLWINM_(REG_DST, REG_SRC, SHIFT, START, END) \ + {int _src = (REG_SRC); int _dst = (REG_DST); \ + INSTR = (0x54000001 | (_src << 21) | (_dst << 16) | (SHIFT << 11) | (START << 6) | (END << 1));} + +#define CLRRWI(REG_DST, REG_SRC, LEN) \ + RLWINM(REG_DST, REG_SRC, 0, 0, 31-LEN) + +#define SLWI(REG_DST, REG_SRC, SHIFT) \ + {int _shift = (SHIFT); \ + if (_shift==0) {MR(REG_DST, REG_SRC)} else \ + {RLWINM(REG_DST, REG_SRC, _shift, 0, 31-_shift)}} + +#define SRWI(REG_DST, REG_SRC, SHIFT) \ + {int _shift = (SHIFT); \ + if (_shift==0) {MR(REG_DST, REG_SRC)} else \ + RLWINM(REG_DST, REG_SRC, 32-_shift, _shift, 31)} + +#define SLW(REG_DST, REG_SRC, REG_SHIFT) \ + {int _src = (REG_SRC), _shift = (REG_SHIFT); int _dst = (REG_DST); \ + INSTR = (0x7C000030 | (_src << 21) | (_dst << 16) | (_shift << 11));} + +#define SRW(REG_DST, REG_SRC, REG_SHIFT) \ + {int _src = (REG_SRC), _shift = (REG_SHIFT); int _dst = (REG_DST); \ + INSTR = (0x7C000430 | (_src << 21) | (_dst << 16) | (_shift << 11));} + +#define SRAW(REG_DST, REG_SRC, REG_SHIFT) \ + {int _src = (REG_SRC), _shift = (REG_SHIFT); int _dst = (REG_DST); \ + INSTR = (0x7C000630 | (_src << 21) | (_dst << 16) | (_shift << 11));} + +#define SRAWI(REG_DST, REG_SRC, SHIFT) \ + {int _src = (REG_SRC); int _dst = (REG_DST); int _shift = (SHIFT); \ + if (_shift==0) {MR(REG_DST, REG_SRC)} else \ + INSTR = (0x7C000670 | (_src << 21) | (_dst << 16) | (_shift << 11));} + +#define RLWNM(REG_DST, REG_SRC, REG_SHIFT, START, END) \ + {int _src = (REG_SRC), _shift = (REG_SHIFT); int _dst = (REG_DST); \ + INSTR = (0x5C000000 | (_src << 21) | (_dst << 16) | (_shift << 11) | (START << 6) | (END << 1));} + +/* other ops */ +#define ORI(REG_DST, REG_SRC, IMM) \ + {int _src = (REG_SRC), _imm = (IMM); int _dst = (REG_DST); \ + if (!((_imm == 0) && ((_src^_dst) == 0))) \ + INSTR = (0x60000000 | (_src << 21) | (_dst << 16) | (_imm & 0xffff));} + +#define ORIS(REG_DST, REG_SRC, IMM) \ + {int _src = (REG_SRC), _imm = (IMM); int _dst = (REG_DST); \ + if (!((_imm == 0) && ((_src^_dst) == 0))) \ + INSTR = (0x64000000 | (_src << 21) | (_dst << 16) | (_imm & 0xffff));} + +#define OR(REG_DST, REG1, REG2) \ + {int _reg1 = (REG1), _reg2 = (REG2); int _dst=(REG_DST); \ + INSTR = (0x7C000378 | (_reg1 << 21) | (_dst << 16) | (_reg2 << 11));} + +#define OR_(REG_DST, REG1, REG2) \ + {int _reg1 = (REG1), _reg2 = (REG2); int _dst=(REG_DST); \ + INSTR = (0x7C000379 | (_reg1 << 21) | (_dst << 16) | (_reg2 << 11));} + +#define XORI(REG_DST, REG_SRC, IMM) \ + {int _src = (REG_SRC); int _dst=(REG_DST); \ + INSTR = (0x68000000 | (_src << 21) | (_dst << 16) | ((IMM) & 0xffff));} + +#define XOR(REG_DST, REG1, REG2) \ + {int _reg1 = (REG1), _reg2 = (REG2); int _dst=(REG_DST); \ + INSTR = (0x7C000278 | (_reg1 << 21) | (_dst << 16) | (_reg2 << 11));} + +#define XOR_(REG_DST, REG1, REG2) \ + {int _reg1 = (REG1), _reg2 = (REG2); int _dst=(REG_DST); \ + INSTR = (0x7C000279 | (_reg1 << 21) | (_dst << 16) | (_reg2 << 11));} + +#define ANDI_(REG_DST, REG_SRC, IMM) \ + {int _src = (REG_SRC); int _dst=(REG_DST); \ + INSTR = (0x70000000 | (_src << 21) | (_dst << 16) | ((IMM) & 0xffff));} + +#define AND(REG_DST, REG1, REG2) \ + {int _reg1 = (REG1), _reg2 = (REG2); int _dst=(REG_DST); \ + INSTR = (0x7C000038 | (_reg1 << 21) | (_dst << 16) | (_reg2 << 11));} + +#define NOR(REG_DST, REG1, REG2) \ + {int _reg1 = (REG1), _reg2 = (REG2); int _dst=(REG_DST); \ + INSTR = (0x7C0000f8 | (_reg1 << 21) | (_dst << 16) | (_reg2 << 11));} + +#define NEG(REG_DST, REG_SRC) \ + {int _src = (REG_SRC); int _dst=(REG_DST); \ + INSTR = (0x7C0000D0 | (_dst << 21) | (_src << 16));} + +#define NOP() \ + {INSTR = 0x60000000;} + +#define MCRXR(CR_DST) \ + {INSTR = (0x7C000400 | (CR_DST << 23));} + +#define EXTSB(REG_DST, REG_SRC) \ + {int _src = (REG_SRC); int _dst=(REG_DST); \ + INSTR = (0x7C000774 | (_src << 21) | (_dst << 16));} + +#define EXTSH(REG_DST, REG_SRC) \ + {int _src = (REG_SRC); int _dst=(REG_DST); \ + INSTR = (0x7C000734 | (_src << 21) | (_dst << 16));} + + +/* floating point ops */ +#define FDIVS(FPR_DST, FPR1, FPR2) \ + {INSTR = (0xEC000024 | (FPR_DST << 21) | (FPR1 << 16) | (FPR2 << 11));} + +#define FDIV(FPR_DST, FPR1, FPR2) \ + {INSTR = (0xFC000024 | (FPR_DST << 21) | (FPR1 << 16) | (FPR2 << 11));} + +#define FMULS(FPR_DST, FPR1, FPR2) \ + {INSTR = (0xEC000032 | (FPR_DST << 21) | (FPR1 << 16) | (FPR2 << 11));} + +#define FMUL(FPR_DST, FPR1, FPR2) \ + {INSTR = (0xFC000032 | (FPR_DST << 21) | (FPR1 << 16) | (FPR2 << 11));} + +#define FADDS(FPR_DST, FPR1, FPR2) \ + {INSTR = (0xEC00002A | (FPR_DST << 21) | (FPR1 << 16) | (FPR2 << 11));} + +#define FADD(FPR_DST, FPR1, FPR2) \ + {INSTR = (0xFC00002A | (FPR_DST << 21) | (FPR1 << 16) | (FPR2 << 11));} + +#define FRSP(FPR_DST, FPR_SRC) \ + {INSTR = (0xFC000018 | (FPR_DST << 21) | (FPR_SRC << 11));} + +#define FCTIW(FPR_DST, FPR_SRC) \ + {INSTR = (0xFC00001C | (FPR_DST << 21) | (FPR_SRC << 11));} + + +#define LFS(FPR_DST, OFFSET, REG) \ + {INSTR = (0xC0000000 | (FPR_DST << 21) | (REG << 16) | ((OFFSET) & 0xffff));} + +#define STFS(FPR_DST, OFFSET, REG) \ + {INSTR = (0xD0000000 | (FPR_DST << 21) | (REG << 16) | ((OFFSET) & 0xffff));} + +#define LFD(FPR_DST, OFFSET, REG) \ + {INSTR = (0xC8000000 | (FPR_DST << 21) | (REG << 16) | ((OFFSET) & 0xffff));} + +#define STFD(FPR_DST, OFFSET, REG) \ + {INSTR = (0xD8000000 | (FPR_DST << 21) | (REG << 16) | ((OFFSET) & 0xffff));} + + + +/* extra combined opcodes */ +#if 1 +#define LIW(REG, IMM) /* Load Immidiate Word */ \ +{ \ + int __reg = (REG); u32 __imm = (u32)(IMM); \ + if ((s32)__imm == (s32)((s16)__imm)) \ + { \ + LI(__reg, (s32)((s16)__imm)); \ + } else if (__reg == 0) { \ + LIS(__reg, (((u32)__imm)>>16)); \ + if ((((u32)__imm) & 0xffff) != 0) \ + { \ + ORI(__reg, __reg, __imm); \ + } \ + } else { \ + if ((((u32)__imm) & 0xffff) == 0) { \ + LIS(__reg, (((u32)__imm)>>16)); \ + } else { \ + LI(__reg, __imm); \ + if ((__imm & 0x8000) == 0) { \ + ADDIS(__reg, __reg, ((u32)__imm)>>16); \ + } else { \ + ADDIS(__reg, __reg, ((((u32)__imm)>>16) & 0xffff) + 1); \ + } \ + } \ + /*if ((((u32)__imm) & 0xffff) != 0) \ + { \ + ORI(__reg, __reg, __imm); \ + }*/ \ + } \ +} +#else +#define LIW(REG, IMM) /* Load Immidiate Word */ \ +{ \ + int __reg = (REG); u32 __imm = (u32)(IMM); \ + if ((s32)__imm == (s32)((s16)__imm)) \ + { \ + LI(__reg, (s32)((s16)__imm)); \ + } \ + else \ + { \ + LIS(__reg, (((u32)__imm)>>16)); \ + if ((((u32)__imm) & 0xffff) != 0) \ + { \ + ORI(__reg, __reg, __imm); \ + } \ + } \ +} +#endif diff --git a/libpcsxcore/ppc/reguse.c b/libpcsxcore/ppc/reguse.c new file mode 100644 index 00000000..47d70a54 --- /dev/null +++ b/libpcsxcore/ppc/reguse.c @@ -0,0 +1,419 @@ + +#include "../psxcommon.h" +#include "reguse.h" + +#include "../r3000a.h" + +//#define SAME_CYCLE_MODE + +static const int useBSC[64] = { + /*recSPECIAL*/ REGUSE_SUB | REGUSE_SPECIAL, + /*recREGIMM*/ REGUSE_SUB | REGUSE_REGIMM, + /*recJ*/ REGUSE_JUMP, + /*recJAL*/ REGUSE_JUMP | REGUSE_R31_W, + /*recBEQ*/ REGUSE_BRANCH | REGUSE_RS_R | REGUSE_RT_R, + /*recBNE*/ REGUSE_BRANCH | REGUSE_RS_R | REGUSE_RT_R, + /*recBLEZ*/ REGUSE_BRANCH | REGUSE_RS_R, + /*recBGTZ*/ REGUSE_BRANCH | REGUSE_RS_R, + /*recADDI*/ REGUSE_ACC | REGUSE_RS_R | REGUSE_RT_W, + /*recADDIU*/ REGUSE_ACC | REGUSE_RS_R | REGUSE_RT_W, + /*recSLTI*/ REGUSE_ACC | REGUSE_RS_R | REGUSE_RT_W, + /*recSLTIU*/ REGUSE_ACC | REGUSE_RS_R | REGUSE_RT_W, + /*recANDI*/ REGUSE_LOGIC | REGUSE_RS_R | REGUSE_RT_W, + /*recORI*/ REGUSE_LOGIC | REGUSE_RS_R | REGUSE_RT_W, + /*recXORI*/ REGUSE_LOGIC | REGUSE_RS_R | REGUSE_RT_W, + /*recLUI*/ REGUSE_ACC | REGUSE_RT_W, + /*recCOP0*/ REGUSE_SUB | REGUSE_COP0, + REGUSE_NONE, + /*recCOP2*/ REGUSE_SUB | REGUSE_COP2, + REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, + REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, + REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, + /*recLB*/ REGUSE_MEM_R | REGUSE_RS_R | REGUSE_RT_W, + /*recLH*/ REGUSE_MEM_R | REGUSE_RS_R | REGUSE_RT_W, + /*recLWL*/ REGUSE_MEM_R | REGUSE_RS_R | REGUSE_RT, + /*recLW*/ REGUSE_MEM_R | REGUSE_RS_R | REGUSE_RT_W, + /*recLBU*/ REGUSE_MEM_R | REGUSE_RS_R | REGUSE_RT_W, + /*recLHU*/ REGUSE_MEM_R | REGUSE_RS_R | REGUSE_RT_W, + /*recLWR*/ REGUSE_MEM_R | REGUSE_RS_R | REGUSE_RT, + REGUSE_NONE, + /*recSB*/ REGUSE_MEM_W | REGUSE_RS_R | REGUSE_RT_R, + /*recSH*/ REGUSE_MEM_W | REGUSE_RS_R | REGUSE_RT_R, + /*recSWL*/ REGUSE_MEM | REGUSE_RS_R | REGUSE_RT_R, + /*recSW*/ REGUSE_MEM_W | REGUSE_RS_R | REGUSE_RT_R, + REGUSE_NONE, REGUSE_NONE, + /*recSWR*/ REGUSE_MEM | REGUSE_RS_R | REGUSE_RT_R, + REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, + /*recLWC2*/ REGUSE_MEM_R | REGUSE_RS_R | REGUSE_COP2_RT_W, + REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, + REGUSE_NONE, REGUSE_NONE, + /*recSWC2*/ REGUSE_MEM_W | REGUSE_RS_R | REGUSE_COP2_RT_R, + /*recHLE*/ REGUSE_UNKNOWN, // TODO: can this be done in a better way + REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, REGUSE_NONE +}; + +static const int useSPC[64] = { + /*recSLL*/ REGUSE_ACC | REGUSE_RT_R | REGUSE_RD_W, + REGUSE_NONE, + /*recSRL*/ REGUSE_ACC | REGUSE_RT_R | REGUSE_RD_W, + /*recSRA*/ REGUSE_ACC | REGUSE_RT_R | REGUSE_RD_W, + /*recSLLV*/ REGUSE_ACC | REGUSE_RS_R | REGUSE_RT_R | REGUSE_RD_W, + REGUSE_NONE, + /*recSRLV*/ REGUSE_ACC | REGUSE_RS_R | REGUSE_RT_R | REGUSE_RD_W, + /*recSRAV*/ REGUSE_ACC | REGUSE_RS_R | REGUSE_RT_R | REGUSE_RD_W, + /*recJR*/ REGUSE_JUMPR | REGUSE_RS_R, + /*recJALR*/ REGUSE_JUMPR | REGUSE_RS_R | REGUSE_RD_W, + REGUSE_NONE, REGUSE_NONE, + /*rSYSCALL*/ REGUSE_SYS | REGUSE_PC | REGUSE_COP0_STATUS | REGUSE_EXCEPTION, + /*recBREAK*/ REGUSE_NONE, + REGUSE_NONE, REGUSE_NONE, + /*recMFHI*/ REGUSE_LOGIC | REGUSE_RD_W | REGUSE_HI_R, + /*recMTHI*/ REGUSE_LOGIC | REGUSE_RS_R | REGUSE_HI_W, + /*recMFLO*/ REGUSE_LOGIC | REGUSE_RD_W | REGUSE_LO_R, + /*recMTLO*/ REGUSE_LOGIC | REGUSE_RS_R | REGUSE_LO_W, + REGUSE_NONE, REGUSE_NONE , REGUSE_NONE, REGUSE_NONE, + /*recMULT*/ REGUSE_MULT | REGUSE_RS_R | REGUSE_RT_R | REGUSE_LO_W | REGUSE_HI_W, + /*recMULTU*/ REGUSE_MULT | REGUSE_RS_R | REGUSE_RT_R | REGUSE_LO_W | REGUSE_HI_W, + /*recDIV*/ REGUSE_MULT | REGUSE_RS_R | REGUSE_RT_R | REGUSE_LO_W | REGUSE_HI_W, + /*recDIVU*/ REGUSE_MULT | REGUSE_RS_R | REGUSE_RT_R | REGUSE_LO_W | REGUSE_HI_W, + REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, + /*recADD*/ REGUSE_ACC | REGUSE_RS_R | REGUSE_RT_R | REGUSE_RD_W, + /*recADDU*/ REGUSE_ACC | REGUSE_RS_R | REGUSE_RT_R | REGUSE_RD_W, + /*recSUB*/ REGUSE_ACC | REGUSE_RS_R | REGUSE_RT_R | REGUSE_RD_W, + /*recSUBU*/ REGUSE_ACC | REGUSE_RS_R | REGUSE_RT_R | REGUSE_RD_W, + /*recAND*/ REGUSE_LOGIC | REGUSE_RS_R | REGUSE_RT_R | REGUSE_RD_W, + /*recOR*/ REGUSE_LOGIC | REGUSE_RS_R | REGUSE_RT_R | REGUSE_RD_W, + /*recXOR*/ REGUSE_LOGIC | REGUSE_RS_R | REGUSE_RT_R | REGUSE_RD_W, + /*recNOR*/ REGUSE_LOGIC | REGUSE_RS_R | REGUSE_RT_R | REGUSE_RD_W, + REGUSE_NONE, REGUSE_NONE, + /*recSLT*/ REGUSE_ACC | REGUSE_RS_R | REGUSE_RT_R | REGUSE_RD_W, + /*recSLTU*/ REGUSE_ACC | REGUSE_RS_R | REGUSE_RT_R | REGUSE_RD_W, + REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, + REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, + REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, + REGUSE_NONE, REGUSE_NONE +}; + +static const int useREGIMM[32] = { + /*recBLTZ*/ REGUSE_BRANCH | REGUSE_RS_R, + /*recBGEZ*/ REGUSE_BRANCH | REGUSE_RS_R, + REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, + REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, + REGUSE_NONE, REGUSE_NONE, + /*recBLTZAL*/REGUSE_BRANCH | REGUSE_RS_R | REGUSE_R31_W, + /*recBGEZAL*/REGUSE_BRANCH | REGUSE_RS_R | REGUSE_R31_W, + REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, + REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, + REGUSE_NONE, REGUSE_NONE +}; + +static const int useCP0[32] = { + /*recMFC0*/ REGUSE_LOGIC | REGUSE_RT_W | REGUSE_COP0_RD_R, + REGUSE_NONE, + /*recCFC0*/ REGUSE_LOGIC | REGUSE_RT_W | REGUSE_COP0_RD_R, + REGUSE_NONE, + /*recMTC0*/ REGUSE_LOGIC | REGUSE_RT_R | REGUSE_COP0_RD_W, + REGUSE_NONE, + /*recCTC0*/ REGUSE_LOGIC | REGUSE_RT_R | REGUSE_COP0_RD_W, + REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, + REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, + /*recRFE*/ REGUSE_LOGIC | REGUSE_COP0_STATUS, + REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, + REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, + REGUSE_NONE, REGUSE_NONE, REGUSE_NONE +}; + +// TODO: make more explicit +static const int useCP2[64] = { + /*recBASIC*/ REGUSE_SUB | REGUSE_BASIC, + /*recRTPS*/ REGUSE_GTE, + REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, + /*recNCLIP*/ REGUSE_GTE, + REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, + /*recOP*/ REGUSE_GTE, + REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, + /*recDPCS*/ REGUSE_GTE, + /*recINTPL*/ REGUSE_GTE, + /*recMVMVA*/ REGUSE_GTE, + /*recNCDS*/ REGUSE_GTE, + /*recCDP*/ REGUSE_GTE, + REGUSE_NONE, + /*recNCDT*/ REGUSE_GTE, + REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, + /*recNCCS*/ REGUSE_GTE, + /*recCC*/ REGUSE_GTE, + REGUSE_NONE, + /*recNCS*/ REGUSE_GTE, + REGUSE_NONE, + /*recNCT*/ REGUSE_GTE, + REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, + REGUSE_NONE, + /*recSQR*/ REGUSE_GTE, + /*recDCPL*/ REGUSE_GTE, + /*recDPCT*/ REGUSE_GTE, + REGUSE_NONE, REGUSE_NONE, + /*recAVSZ3*/ REGUSE_GTE, + /*recAVSZ4*/ REGUSE_GTE, + REGUSE_NONE, + /*recRTPT*/ REGUSE_GTE, + REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, + REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, + /*recGPF*/ REGUSE_GTE, + /*recGPL*/ REGUSE_GTE, + /*recNCCT*/ REGUSE_GTE +}; + +static const int useCP2BSC[32] = { + /*recMFC2*/ REGUSE_LOGIC | REGUSE_RT_W | REGUSE_COP2_RD_R, + REGUSE_NONE, + /*recCFC2*/ REGUSE_LOGIC | REGUSE_RT_W | REGUSE_COP2_RD_R, + REGUSE_NONE, + /*recMTC2*/ REGUSE_LOGIC | REGUSE_RT_R | REGUSE_COP2_RD_W, + REGUSE_NONE, + /*recCTC2*/ REGUSE_LOGIC | REGUSE_RT_R | REGUSE_COP2_RD_W, + REGUSE_NONE, + REGUSE_NONE, + REGUSE_NONE, + REGUSE_NONE, + REGUSE_NONE, + REGUSE_NONE, + REGUSE_NONE, + REGUSE_NONE, + REGUSE_NONE, + REGUSE_NONE, + REGUSE_NONE, + REGUSE_NONE, + REGUSE_NONE, + REGUSE_NONE, + REGUSE_NONE, + REGUSE_NONE, + REGUSE_NONE, + REGUSE_NONE, + REGUSE_NONE, + REGUSE_NONE, + REGUSE_NONE, + REGUSE_NONE, + REGUSE_NONE, + REGUSE_NONE, + REGUSE_NONE +}; + +static int getRegUse(u32 code) __attribute__ ((__pure__)); +static int getRegUse(u32 code) +{ + int use = useBSC[code>>26]; + + switch (use & REGUSE_SUBMASK) { + case REGUSE_NONE: + break; + case REGUSE_SPECIAL: + use = useSPC[_fFunct_(code)]; + break; + case REGUSE_REGIMM: + use = useREGIMM[_fRt_(code)]; + break; + case REGUSE_COP0: + use = useCP0[_fRs_(code)]; + break; + case REGUSE_COP2: + use = useCP2[_fFunct_(code)]; + if ((use & REGUSE_SUBMASK) == REGUSE_BASIC) + use = useCP2BSC[_fRs_(code)]; + break; + default: + use = REGUSE_UNKNOWN; + break; + } + + if ((use & REGUSE_COP0_RD_W)) { + if (_fRd_(code) == 12 || _fRd_(code) == 13) { + use = REGUSE_UNKNOWN; + } + } + + return use; +} + +/* returns how psxreg is used in the code instruction */ +int useOfPsxReg(u32 code, int use, int psxreg) +{ + int retval = REGUSE_NONE; + + // get use if it wasn't supplied + if (-1 == use) use = getRegUse(code); + + // if we don't know what the usage is, assume it's read from + if (REGUSE_UNKNOWN == use) return REGUSE_READ; + + if (psxreg < 32) { + // check for 3 standard types + if ((use & REGUSE_RT) && _fRt_(code) == (u32)psxreg) { + retval |= ((use & REGUSE_RT_R) ? REGUSE_READ:0) | ((use & REGUSE_RT_W) ? REGUSE_WRITE:0); + } + if ((use & REGUSE_RS) && _fRs_(code) == (u32)psxreg) { + retval |= ((use & REGUSE_RS_R) ? REGUSE_READ:0) | ((use & REGUSE_RS_W) ? REGUSE_WRITE:0); + } + if ((use & REGUSE_RD) && _fRd_(code) == (u32)psxreg) { + retval |= ((use & REGUSE_RD_R) ? REGUSE_READ:0) | ((use & REGUSE_RD_W) ? REGUSE_WRITE:0); + } + // some instructions explicitly writes to r31 + if ((use & REGUSE_R31_W) && 31 == psxreg) { + retval |= REGUSE_WRITE; + } + } else if (psxreg == 32) { // Special register LO + retval |= ((use & REGUSE_LO_R) ? REGUSE_READ:0) | ((use & REGUSE_LO_W) ? REGUSE_WRITE:0); + } else if (psxreg == 33) { // Special register HI + retval |= ((use & REGUSE_HI_R) ? REGUSE_READ:0) | ((use & REGUSE_HI_W) ? REGUSE_WRITE:0); + } + + return retval; +} + +//#define NOREGUSE_FOLLOW + +static int _nextPsxRegUse(u32 pc, int psxreg, int numInstr) __attribute__ ((__pure__, __unused__)); +static int _nextPsxRegUse(u32 pc, int psxreg, int numInstr) +{ + u32 *ptr, code, bPC = 0; + int i, use, reguse = 0; + + for (i=0; i<numInstr; ) { + // load current instruction + ptr = PSXM(pc); + if (ptr==NULL) { + // going nowhere... might as well assume a write, since we will hopefully never reach here + reguse = REGUSE_WRITE; + break; + } + code = SWAP32(*ptr); + // get usage patterns for instruction + use = getRegUse(code); + // find the use of psxreg in the instruction + reguse = useOfPsxReg(code, use, psxreg); + + // return if we have found a use + if (reguse != REGUSE_NONE) + break; + + // goto next instruction + pc += 4; + i++; + + // check for code branches/jumps + if (i != numInstr) { + if ((use & REGUSE_TYPEM) == REGUSE_BRANCH) { +#ifndef NOREGUSE_FOLLOW + // check delay slot + reguse = _nextPsxRegUse(pc, psxreg, 1); + if (reguse != REGUSE_NONE) break; + + bPC = _fImm_(code) * 4 + pc; + reguse = _nextPsxRegUse(pc+4, psxreg, (numInstr-i-1)/2); + if (reguse != REGUSE_NONE) { + int reguse2 = _nextPsxRegUse(bPC, psxreg, (numInstr-i-1)/2); + if (reguse2 != REGUSE_NONE) + reguse |= reguse2; + else + reguse = REGUSE_NONE; + } +#endif + break; + } else if ((use & REGUSE_TYPEM) == REGUSE_JUMP) { +#ifndef NOREGUSE_FOLLOW + // check delay slot + reguse = _nextPsxRegUse(pc, psxreg, 1); + if (reguse != REGUSE_NONE) break; + + bPC = _fTarget_(code) * 4 + (pc & 0xf0000000); + reguse = _nextPsxRegUse(bPC, psxreg, numInstr-i-1); +#endif + break; + } else if ((use & REGUSE_TYPEM) == REGUSE_JUMPR) { +#ifndef NOREGUSE_FOLLOW + // jump to unknown location - bail after checking delay slot + reguse = _nextPsxRegUse(pc, psxreg, 1); +#endif + break; + } else if ((use & REGUSE_TYPEM) == REGUSE_SYS) { + break; + } + } + } + + return reguse; +} + + +int nextPsxRegUse(u32 pc, int psxreg) +{ +#if 1 + if (psxreg == 0) + return REGUSE_WRITE; // pretend we are writing to it to fool compiler + +#ifdef SAME_CYCLE_MODE + return REGUSE_READ; +#else + return _nextPsxRegUse(pc, psxreg, 80); +#endif +#else + u32 code, bPC = 0; + int use, reguse = 0, reguse1 = 0, b = 0, i, index = 0; + +retry: + for (i=index; i<80; i++) { + code = PSXMu32(pc); + use = getRegUse(code); + reguse = useOfPsxReg(code, use, psxreg); + + if (reguse != REGUSE_NONE) break; + + pc += 4; + if ((use & REGUSE_TYPEM) == REGUSE_BRANCH) { + if (b == 0) { + bPC = _fImm_(code) * 4 + pc; + index = i+1; + } + b += 1; // TODO: follow branches + continue; + } else if ((use & REGUSE_TYPEM) == REGUSE_JUMP) { + if (b == 0) { + bPC = _fTarget_(code) * 4 + (pc & 0xf0000000); + } + b = 2; + continue; + } else if ((use & REGUSE_TYPEM) == REGUSE_JUMPR || + (use & REGUSE_TYPEM) == REGUSE_SYS) { + b = 2; + continue; + } + + if (b == 2 && bPC && index == 0) { + pc = bPC; bPC = 0; + b = 1; + } + if (b >= 2) break; // only follow 1 branch + } + if (reguse == REGUSE_NONE) return reguse; + + if (bPC) { + reguse1 = reguse; + pc = bPC; bPC = 0; + b = 1; + goto retry; + } + + return reguse1 | reguse; +#endif +} + +int isPsxRegUsed(u32 pc, int psxreg) +{ + int use = nextPsxRegUse(pc, psxreg); + + if (use == REGUSE_NONE) + return 2; // unknown use - assume it is used + else if (use & REGUSE_READ) + return 1; // the next use is a read + else + return 0; // the next use is a write, i.e. current value is not important +} diff --git a/libpcsxcore/ppc/reguse.h b/libpcsxcore/ppc/reguse.h new file mode 100644 index 00000000..69001ef3 --- /dev/null +++ b/libpcsxcore/ppc/reguse.h @@ -0,0 +1,77 @@ + +#ifndef __REGUSE_H__ +#define __REGUSE_H__ + +// include basic types +#include "../psxcommon.h" + +#define REGUSE_NONE 0x0000 +#define REGUSE_UNKNOWN 0x0001 + +//sub functions +#define REGUSE_SPECIAL 0x0002 +#define REGUSE_REGIMM 0x0004 +#define REGUSE_COP0 0x0006 +#define REGUSE_COP2 0x0008 +#define REGUSE_BASIC 0x000a +#define REGUSE_SUBMASK 0x000e /* sub function mask */ + +#define REGUSE_ACC 0x0010 /* accumulator */ +#define REGUSE_LOGIC 0x0020 /* logic operations */ +#define REGUSE_MULT 0x0030 /* multiplier */ +#define REGUSE_JUMP 0x0040 /* jump to dest */ +#define REGUSE_JUMPR 0x0050 /* jump to reg */ +#define REGUSE_BRANCH 0x0060 /* branch */ +#define REGUSE_MEM_R 0x0070 /* read from memory */ +#define REGUSE_MEM_W 0x0080 /* write to memory */ +#define REGUSE_MEM 0x0090 /* read and write to memory */ +#define REGUSE_SYS 0x00a0 /* syscall */ +#define REGUSE_GTE 0x00b0 /* gte operation */ +#define REGUSE_SUB 0x00f0 /* sub usage */ +#define REGUSE_TYPEM 0x00f0 /* type mask */ + + +#define REGUSE_RS_R 0x0100 +#define REGUSE_RS_W 0x0200 +#define REGUSE_RS (REGUSE_RS_R | REGUSE_RS_W) +#define REGUSE_RT_R 0x0400 +#define REGUSE_RT_W 0x0800 +#define REGUSE_RT (REGUSE_RT_R | REGUSE_RT_W) +#define REGUSE_RD_R 0x1000 +#define REGUSE_RD_W 0x2000 +#define REGUSE_RD (REGUSE_RD_R | REGUSE_RD_W) + +#define REGUSE_R31_W 0x4000 /* writes to link register (r31) */ +#define REGUSE_PC 0x8000 /* reads pc */ + +#define REGUSE_LO_R 0x10000 +#define REGUSE_LO_W 0x20000 +#define REGUSE_LO (REGUSE_LO_R | REGUSE_LO_W) +#define REGUSE_HI_R 0x40000 +#define REGUSE_HI_W 0x80000 +#define REGUSE_HI (REGUSE_HI_R | REGUSE_HI_W) + +#define REGUSE_COP0_RD_R 0x100000 +#define REGUSE_COP0_RD_W 0x200000 +#define REGUSE_COP0_RD (REGUSE_COP0_RD_R | REGUSE_COP0_RD_W) +#define REGUSE_COP0_STATUS 0x400000 +#define REGUSE_EXCEPTION 0x800000 + +#define REGUSE_COP2_RT_R 0x1000000 +#define REGUSE_COP2_RT_W 0x2000000 +#define REGUSE_COP2_RT (REGUSE_COP2_RT_R | REGUSE_COP2_RT_W) +#define REGUSE_COP2_RD_R 0x4000000 +#define REGUSE_COP2_RD_W 0x8000000 +#define REGUSE_COP2_RD (REGUSE_COP2_RD_R | REGUSE_COP2_RD_W) + + +// specific register use +#define REGUSE_READ 1 +#define REGUSE_WRITE 2 +#define REGUSE_RW 3 + +int useOfPsxReg(u32 code, int use, int psxreg) __attribute__ ((__pure__));; +int nextPsxRegUse(u32 pc, int psxreg) __attribute__ ((__pure__));; +int isPsxRegUsed(u32 pc, int psxreg) __attribute__ ((__pure__));; + +#endif /* __REGUSE_H__ */ diff --git a/libpcsxcore/psemu_plugin_defs.h b/libpcsxcore/psemu_plugin_defs.h new file mode 100644 index 00000000..baaf7836 --- /dev/null +++ b/libpcsxcore/psemu_plugin_defs.h @@ -0,0 +1,279 @@ +#ifndef _PSEMU_PLUGIN_DEFS_H +#define _PSEMU_PLUGIN_DEFS_H + +// 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); + + long PADreadPort1(PadDataS *); + long PADreadPort2(PadDataS *); + +*/ + +// 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 (must support PADreadPort1() function) +#define PSE_PAD_USE_PORT1 1 +// might be used in port 2 (must support PADreadPort2() function) +#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 128 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. +*/ + + +#endif // _PSEMU_PLUGIN_DEFS_H diff --git a/libpcsxcore/psxbios.c b/libpcsxcore/psxbios.c new file mode 100644 index 00000000..38e7649e --- /dev/null +++ b/libpcsxcore/psxbios.c @@ -0,0 +1,2399 @@ +/*************************************************************************** + * Copyright (C) 2007 Ryan Schultz, PCSX-df Team, PCSX team * + * schultz.ryan@gmail.com, http://rschultz.ath.cx/code.php * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You 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 Steet, Fifth Floor, Boston, MA 02111-1307 USA. * + ***************************************************************************/ + +/* +* Internal emulated HLE BIOS. +*/ + +#include "psxbios.h" +#include "psxhw.h" + +//We try to emulate bios :) HELP US :P + +char *biosA0n[256] = { +// 0x00 + "open", "lseek", "read", "write", + "close", "ioctl", "exit", "sys_a0_07", + "getc", "putc", "todigit", "atof", + "strtoul", "strtol", "abs", "labs", +// 0x10 + "atoi", "atol", "atob", "setjmp", + "longjmp", "strcat", "strncat", "strcmp", + "strncmp", "strcpy", "strncpy", "strlen", + "index", "rindex", "strchr", "strrchr", +// 0x20 + "strpbrk", "strspn", "strcspn", "strtok", + "strstr", "toupper", "tolower", "bcopy", + "bzero", "bcmp", "memcpy", "memset", + "memmove", "memcmp", "memchr", "rand", +// 0x30 + "srand", "qsort", "strtod", "malloc", + "free", "lsearch", "bsearch", "calloc", + "realloc", "InitHeap", "_exit", "getchar", + "putchar", "gets", "puts", "printf", +// 0x40 + "sys_a0_40", "LoadTest", "Load", "Exec", + "FlushCache", "InstallInterruptHandler", "GPU_dw", "mem2vram", + "SendGPUStatus", "GPU_cw", "GPU_cwb", "SendPackets", + "sys_a0_4c", "GetGPUStatus", "GPU_sync", "sys_a0_4f", +// 0x50 + "sys_a0_50", "LoadExec", "GetSysSp", "sys_a0_53", + "_96_init()", "_bu_init()", "_96_remove()", "sys_a0_57", + "sys_a0_58", "sys_a0_59", "sys_a0_5a", "dev_tty_init", + "dev_tty_open", "sys_a0_5d", "dev_tty_ioctl","dev_cd_open", +// 0x60 + "dev_cd_read", "dev_cd_close", "dev_cd_firstfile", "dev_cd_nextfile", + "dev_cd_chdir", "dev_card_open", "dev_card_read", "dev_card_write", + "dev_card_close", "dev_card_firstfile", "dev_card_nextfile","dev_card_erase", + "dev_card_undelete","dev_card_format", "dev_card_rename", "dev_card_6f", +// 0x70 + "_bu_init", "_96_init", "_96_remove", "sys_a0_73", + "sys_a0_74", "sys_a0_75", "sys_a0_76", "sys_a0_77", + "_96_CdSeekL", "sys_a0_79", "sys_a0_7a", "sys_a0_7b", + "_96_CdGetStatus", "sys_a0_7d", "_96_CdRead", "sys_a0_7f", +// 0x80 + "sys_a0_80", "sys_a0_81", "sys_a0_82", "sys_a0_83", + "sys_a0_84", "_96_CdStop", "sys_a0_86", "sys_a0_87", + "sys_a0_88", "sys_a0_89", "sys_a0_8a", "sys_a0_8b", + "sys_a0_8c", "sys_a0_8d", "sys_a0_8e", "sys_a0_8f", +// 0x90 + "sys_a0_90", "sys_a0_91", "sys_a0_92", "sys_a0_93", + "sys_a0_94", "sys_a0_95", "AddCDROMDevice", "AddMemCardDevide", + "DisableKernelIORedirection", "EnableKernelIORedirection", "sys_a0_9a", "sys_a0_9b", + "SetConf", "GetConf", "sys_a0_9e", "SetMem", +// 0xa0 + "_boot", "SystemError", "EnqueueCdIntr", "DequeueCdIntr", + "sys_a0_a4", "ReadSector", "get_cd_status", "bufs_cb_0", + "bufs_cb_1", "bufs_cb_2", "bufs_cb_3", "_card_info", + "_card_load", "_card_auto", "bufs_cd_4", "sys_a0_af", +// 0xb0 + "sys_a0_b0", "sys_a0_b1", "do_a_long_jmp", "sys_a0_b3", + "?? sub_function", +}; + +char *biosB0n[256] = { +// 0x00 + "SysMalloc", "sys_b0_01", "sys_b0_02", "sys_b0_03", + "sys_b0_04", "sys_b0_05", "sys_b0_06", "DeliverEvent", + "OpenEvent", "CloseEvent", "WaitEvent", "TestEvent", + "EnableEvent", "DisableEvent", "OpenTh", "CloseTh", +// 0x10 + "ChangeTh", "sys_b0_11", "InitPAD", "StartPAD", + "StopPAD", "PAD_init", "PAD_dr", "ReturnFromExecption", + "ResetEntryInt", "HookEntryInt", "sys_b0_1a", "sys_b0_1b", + "sys_b0_1c", "sys_b0_1d", "sys_b0_1e", "sys_b0_1f", +// 0x20 + "UnDeliverEvent", "sys_b0_21", "sys_b0_22", "sys_b0_23", + "sys_b0_24", "sys_b0_25", "sys_b0_26", "sys_b0_27", + "sys_b0_28", "sys_b0_29", "sys_b0_2a", "sys_b0_2b", + "sys_b0_2c", "sys_b0_2d", "sys_b0_2e", "sys_b0_2f", +// 0x30 + "sys_b0_30", "sys_b0_31", "open", "lseek", + "read", "write", "close", "ioctl", + "exit", "sys_b0_39", "getc", "putc", + "getchar", "putchar", "gets", "puts", +// 0x40 + "cd", "format", "firstfile", "nextfile", + "rename", "delete", "undelete", "AddDevice", + "RemoteDevice", "PrintInstalledDevices", "InitCARD", "StartCARD", + "StopCARD", "sys_b0_4d", "_card_write", "_card_read", +// 0x50 + "_new_card", "Krom2RawAdd", "sys_b0_52", "sys_b0_53", + "_get_errno", "_get_error", "GetC0Table", "GetB0Table", + "_card_chan", "sys_b0_59", "sys_b0_5a", "ChangeClearPAD", + "_card_status", "_card_wait", +}; + +char *biosC0n[256] = { +// 0x00 + "InitRCnt", "InitException", "SysEnqIntRP", "SysDeqIntRP", + "get_free_EvCB_slot", "get_free_TCB_slot", "ExceptionHandler", "InstallExeptionHandler", + "SysInitMemory", "SysInitKMem", "ChangeClearRCnt", "SystemError", + "InitDefInt", "sys_c0_0d", "sys_c0_0e", "sys_c0_0f", +// 0x10 + "sys_c0_10", "sys_c0_11", "InstallDevices", "FlushStfInOutPut", + "sys_c0_14", "_cdevinput", "_cdevscan", "_circgetc", + "_circputc", "ioabort", "sys_c0_1a", "KernelRedirect", + "PatchAOTable", +}; + +//#define r0 (psxRegs.GPR.n.r0) +#define at (psxRegs.GPR.n.at) +#define v0 (psxRegs.GPR.n.v0) +#define v1 (psxRegs.GPR.n.v1) +#define a0 (psxRegs.GPR.n.a0) +#define a1 (psxRegs.GPR.n.a1) +#define a2 (psxRegs.GPR.n.a2) +#define a3 (psxRegs.GPR.n.a3) +#define t0 (psxRegs.GPR.n.t0) +#define t1 (psxRegs.GPR.n.t1) +#define t2 (psxRegs.GPR.n.t2) +#define t3 (psxRegs.GPR.n.t3) +#define t4 (psxRegs.GPR.n.t4) +#define t5 (psxRegs.GPR.n.t5) +#define t6 (psxRegs.GPR.n.t6) +#define t7 (psxRegs.GPR.n.t7) +#define s0 (psxRegs.GPR.n.s0) +#define s1 (psxRegs.GPR.n.s1) +#define s2 (psxRegs.GPR.n.s2) +#define s3 (psxRegs.GPR.n.s3) +#define s4 (psxRegs.GPR.n.s4) +#define s5 (psxRegs.GPR.n.s5) +#define s6 (psxRegs.GPR.n.s6) +#define s7 (psxRegs.GPR.n.s7) +#define t8 (psxRegs.GPR.n.t6) +#define t9 (psxRegs.GPR.n.t7) +#define k0 (psxRegs.GPR.n.k0) +#define k1 (psxRegs.GPR.n.k1) +#define gp (psxRegs.GPR.n.gp) +#define sp (psxRegs.GPR.n.sp) +#define fp (psxRegs.GPR.n.s8) +#define ra (psxRegs.GPR.n.ra) +#define pc0 (psxRegs.pc) + +#define Ra0 ((char*)PSXM(a0)) +#define Ra1 ((char*)PSXM(a1)) +#define Ra2 ((char*)PSXM(a2)) +#define Ra3 ((char*)PSXM(a3)) +#define Rv0 ((char*)PSXM(v0)) +#define Rsp ((char*)PSXM(sp)) + + +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 { + long next; + long func1; + long func2; + long 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]; + long attr; + long size; + struct DIRENTRY *next; + long 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, *pad_buf2;//shadow add +static int pad_buf1len, pad_buf2len;//shadow add + +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 __inline void softCall(u32 pc) { + pc0 = pc; + ra = 0x80001000; + while (pc0 != 0x80001000) psxCpu->ExecuteBlock(); +} + +static __inline void softCall2(u32 pc) { + u32 sra = ra; + pc0 = pc; + ra = 0x80001000; + while (pc0 != 0x80001000) psxCpu->ExecuteBlock(); + ra = sra; +} + +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; +} + +/* * +// * +// * +// System calls A0 */ + + +void psxBios_abs() { // 0x0e + v0 = abs(a0); + pc0 = ra; +} + +void psxBios_labs() { // 0x0f + v0 = labs(a0); + pc0 = ra; +} + +void psxBios_atoi() { // 0x10 + v0 = atoi((char *)Ra0); + pc0 = ra; +} + +void psxBios_atol() { // 0x11 + v0 = atoi((char *)Ra0); + pc0 = ra; +} + +void psxBios_setjmp() { // 13 + 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() { //14 + 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 +#ifdef PSXBIOS_LOG + PSXBIOS_LOG("psxBios_%s: %s, %s\n", biosA0n[0x15], Ra0, Ra1); +#endif + + strcat(Ra0, Ra1); + v0 = a0; pc0 = ra; +} + +/*0x16*/void psxBios_strncat() { strncat(Ra0, Ra1, a2); v0 = a0; pc0 = ra;} + +void psxBios_strcmp() { // 0x17 +#ifdef PSXBIOS_LOG + PSXBIOS_LOG("psxBios_%s: %s (%lx), %s (%lx)\n", biosA0n[0x17], Ra0, a0, Ra1, a1); +#endif + + v0 = strcmp(Ra0, Ra1); + pc0 = ra; +} + +void psxBios_strncmp() { // 0x18 +#ifdef PSXBIOS_LOG + PSXBIOS_LOG("psxBios_%s: %s (%lx), %s (%lx), %d\n", biosA0n[0x18], Ra0, a0, Ra1, a1, a2); +#endif + + v0 = strncmp(Ra0, Ra1, a2); + pc0 = ra; +} + +/*0x19*/void psxBios_strcpy() { strcpy(Ra0, Ra1); v0 = a0; pc0 = ra;} +/*0x1a*/void psxBios_strncpy() { strncpy(Ra0, Ra1, a2); v0 = a0; pc0 = ra;} +/*0x1b*/void psxBios_strlen() { v0 = strlen(Ra0); pc0 = ra;} + +void psxBios_index() { // 0x1c + char *pcA0 = (char *)Ra0; + char *pcRet = strchr(pcA0, a1); + if(pcRet) + v0 = a0 + pcRet - pcA0; + else + v0 = 0; + pc0 = ra; +} + +void psxBios_rindex() { // 0x1d + char *pcA0 = (char *)Ra0; + char *pcRet = strrchr(pcA0, a1); + if(pcRet) + v0 = a0 + pcRet - pcA0; + else + v0 = 0; + pc0 = ra; +} + +void psxBios_strchr() { // 0x1e + char *pcA0 = (char *)Ra0; + char *pcRet = strchr(pcA0, a1); + if(pcRet) + v0 = a0 + pcRet - pcA0; + else + v0 = 0; + pc0 = ra; +} + +void psxBios_strrchr() { // 0x1f + char *pcA0 = (char *)Ra0; + char *pcRet = strrchr(pcA0, a1); + if(pcRet) + v0 = a0 + pcRet - pcA0; + else + v0 = 0; + pc0 = ra; +} + +void psxBios_strpbrk() { // 0x20 + char *pcA0 = (char *)Ra0; + char *pcRet = strpbrk(pcA0, (char *)Ra1); + if(pcRet) + v0 = a0 + pcRet - pcA0; + else + v0 = 0; + pc0 = ra; +} + +void psxBios_strspn() { v0 = strspn ((char *)Ra0, (char *)Ra1); pc0 = ra;}/*21*/ +void psxBios_strcspn() { v0 = strcspn((char *)Ra0, (char *)Ra1); pc0 = ra;}/*22*/ + +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 *pcA0 = (char *)Ra0; + char *pcRet = strstr(pcA0, (char *)Ra1); + if(pcRet) + v0 = a0 + pcRet - pcA0; + else + v0 = 0; + pc0 = ra; +} + +/*0x25*/void psxBios_toupper() {v0 = toupper(a0); pc0 = ra;} +/*0x26*/void psxBios_tolower() {v0 = tolower(a0); pc0 = ra;} +/*0x27*/void psxBios_bcopy() {memcpy(Ra1,Ra0,a2); pc0=ra;} +/*0x28*/void psxBios_bzero() {memset(Ra0,0,a1); pc0=ra;} +/*0x29*/void psxBios_bcmp() {v0 = memcmp(Ra0,Ra1,a2); pc0=ra; } +/*0x2a*/void psxBios_memcpy() {memcpy(Ra0, Ra1, a2); v0 = a0; pc0 = ra;} +/*0x2b*/void psxBios_memset() {memset(Ra0, a1, a2); v0 = a0; pc0 = ra;} +/*0x2c*/void psxBios_memmove() {memmove(Ra0, Ra1, a2); v0 = a0; pc0 = ra;} +/*0x2d*/void psxBios_memcmp() {v0 = memcmp(Ra0, Ra1, a2); pc0 = ra;} + +void psxBios_memchr() { // 2e + void *ret = memchr(Ra0, a1, a2); + if (ret != NULL) v0 = (u32)((char*)ret - Ra0) + a0; + else v0 = 0; + pc0 = ra; +} + +void psxBios_rand() { // 2f + v0 = 1+(int) (32767.0*rand()/(RAND_MAX+1.0)); + pc0 = ra; +} + +void psxBios_srand() { // 30 + srand(a0); pc0 = ra; +} + + +void psxBios_malloc() { // 33 +#ifdef PSXBIOS_LOG + PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x33]); +#endif + unsigned int *chunk, *newchunk; + unsigned int dsize, csize, cstat; + int colflag; + + // 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 %lx,%lx: 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 %lx,%lx: 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 %lx,%lx\n", v0, a0); + pc0 = ra; +} + +void psxBios_free() { // 34 + +#ifdef PSXBIOS_LOG + PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x34]); +#endif + + SysPrintf("free %lx: %lx bytes\n", a0, *(u32*)(Ra0-4)); + + *(u32*)(Ra0-4) |= 1; // set chunk to free + pc0 = ra; +} + +void psxBios_calloc() { // 37 +#ifdef PSXBIOS_LOG + PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x37]); +#endif + + a0 = a0 * a1; + psxBios_malloc(); + memset(Rv0, 0, a0); +} + +void psxBios_realloc() { // 38 +#ifdef PSXBIOS_LOG + PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x38]); +#endif + + u32 block = a0; + u32 size = a1; + + a0 = block; + psxBios_free(); + a0 = size; + psxBios_malloc(); +} + + +/* InitHeap(void *block , int n) */ +void psxBios_InitHeap() { // 39 + +#ifdef PSXBIOS_LOG + PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x39]); +#endif + + unsigned int size; + + if (((a0 & 0x1fffff) + a1)>= 0x200000) size = 0x1ffffc - (a0 & 0x1fffff); + else size = a1; + + size &= 0xfffffffc; + + heap_addr = (u32*)Ra0; + heap_end = (u32*)((u32)heap_addr + size); + *heap_addr = SWAP32(size | 1); + + SysPrintf("InitHeap %lx,%lx : %lx %lx\n",a0,a1, (uptr)heap_addr-(uptr)psxM, size); + + pc0 = ra; +} + +void psxBios_getchar(){ v0 = getchar(); pc0=ra;} //0x3b + +void psxBios_printf() { // 3f + 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() { // 42 + 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 + + 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 +#ifdef PSXBIOS_LOG + PSXBIOS_LOG("psxBios_%s: %x, %x\n", biosA0n[0x9f], a0, a1); +#endif + + u32 new = psxHu32(0x1060); + 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 + +// 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 + +// 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 + memcpy(psxRegs.GPR.r, regs, 32*4); + psxRegs.GPR.n.lo = regs[32]; + psxRegs.GPR.n.hi = regs[33]; + + 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; \ + 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); \ + 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; \ + 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); + v0 = _dir; + } + + if (!strncmp(Ra0, "bu10", 4)) { + bufile(2); + v0 = _dir; + } + + 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 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; \ + 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 + + 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 + + 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_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_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 %lx call: %lx\n", pc0 & 0x1fffff, t1); +#endif + pc0 = ra; +} + +void (*biosA0[256])(); +void (*biosB0[256])(); +void (*biosC0[256])(); + +void psxBiosInit() { + u32 base, size; + u32 *ptr; + int i; + + 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 + + psxMu32ref(0x0150) = SWAPu32(0x160); + psxMu32ref(0x0154) = SWAPu32(0x320); + psxMu32ref(0x0160) = SWAPu32(0x248); + strcpy(&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); + + // memory size 2 MB + psxHu32ref(0x1060) = SWAPu32(0x00000b88); +} + +void psxBiosShutdown() { +} + +__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; +} + +__inline void LoadRegs() { + memcpy(psxRegs.GPR.r, regs, 32*4); + psxRegs.GPR.n.lo = regs[32]; + psxRegs.GPR.n.hi = regs[33]; +} + + +#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 netError(); + +void biosInterrupt() { + int i, bufcount; + +// if (psxHu32(0x1070) & 0x1) { // Vsync + if (pad_buf) { + 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 && pad_buf2) { + 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(); + + 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 bfreezel(ptr) bfreeze(ptr, sizeof(uintptr_t)) + +#define bfreezepsxMptr(ptr) \ + if (Mode == 1) { \ + if (ptr) psxRu32ref(base) = SWAPu32((uintptr_t)ptr - (uintptr_t)psxM); \ + else psxRu32ref(base) = 0; \ + } else { \ + if (psxRu32(base)) *(u8**)&ptr = (u8*)(psxM + psxRu32(base)); \ + else ptr = NULL; \ + } \ + base += sizeof(uintptr_t); + +void psxBiosFreeze(int Mode) { + u32 base = 0x40000; + + bfreezepsxMptr(jmp_int); + bfreezepsxMptr(pad_buf); + bfreezepsxMptr(pad_buf1); + bfreezepsxMptr(pad_buf2); + bfreezepsxMptr(heap_addr); + bfreezel(&pad_buf1len); + bfreezel(&pad_buf2len); + bfreezes(regs); + bfreezes(SysIntRP); + bfreezel(&CardState); + bfreezes(Thread); + bfreezel(&CurThread); + bfreezes(FDesc); +} + + + diff --git a/libpcsxcore/psxbios.h b/libpcsxcore/psxbios.h new file mode 100644 index 00000000..86d22663 --- /dev/null +++ b/libpcsxcore/psxbios.h @@ -0,0 +1,43 @@ +/*************************************************************************** + * Copyright (C) 2007 Ryan Schultz, PCSX-df Team, PCSX team * + * schultz.ryan@gmail.com, http://rschultz.ath.cx/code.php * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You 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 Steet, Fifth Floor, Boston, MA 02111-1307 USA. * + ***************************************************************************/ + +#ifndef __PSXBIOS_H__ +#define __PSXBIOS_H__ + +#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])(); + +#endif /* __PSXBIOS_H__ */ diff --git a/libpcsxcore/psxcommon.h b/libpcsxcore/psxcommon.h new file mode 100644 index 00000000..c3f21ffe --- /dev/null +++ b/libpcsxcore/psxcommon.h @@ -0,0 +1,148 @@ +/*************************************************************************** + * Copyright (C) 2007 Ryan Schultz, PCSX-df Team, PCSX team * + * schultz.ryan@gmail.com, http://rschultz.ath.cx/code.php * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You 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 Steet, Fifth Floor, Boston, MA 02111-1307 USA. * + ***************************************************************************/ + +/* +* This file contains common definitions and includes for all parts of the +* emulator core. +*/ + +#ifndef __PSXCOMMON_H__ +#define __PSXCOMMON_H__ + +#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; + +/* Local includes */ +#include "system.h" +#include "debug.h" + +/* Ryan TODO WTF is this? */ +#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 + +#else + +#define _(msgid) msgid +#define N_(msgid) msgid + +#endif + +extern int Log; +void __Log(char *fmt, ...); + +typedef struct { + char Gpu[256]; + char Spu[256]; + char Cdr[256]; + char Pad1[256]; + char Pad2[256]; + char Net[256]; + char Mcd1[256]; + char Mcd2[256]; + char Bios[256]; + char BiosDir[MAXPATHLEN]; + char PluginsDir[MAXPATHLEN]; + long Xa; + long Sio; + long Mdec; + long PsxAuto; + long PsxType; /* NTSC or PAL */ + long Cdda; + long HLE; + long Cpu; + long Dbg; + long PsxOut; + long SpuIrq; + long RCntFix; + long UseNet; + long VSyncWA; +#ifdef _WIN32 + char Lang[256]; +#endif +} PcsxConfig; + +PcsxConfig Config; + +extern int StatesC; +extern int cdOpenCase; +extern int NetOpened; + +#define gzfreeze(ptr, size) \ + if (Mode == 1) gzwrite(f, ptr, size); \ + if (Mode == 0) gzread(f, ptr, size); + +#define gzfreezel(ptr) gzfreeze(ptr, sizeof(ptr)) + +//#define BIAS 4 +#define BIAS 2 +#define PSXCLK 33868800 /* 33.8688 Mhz */ + +enum { + BIOS_USER_DEFINED, + BIOS_HLE +}; /* BIOS Types */ + +enum { + PSX_TYPE_NTSC, + PSX_TYPE_PAL +}; /* PSX Type */ + + +#endif /* __PSXCOMMON_H__ */ diff --git a/libpcsxcore/psxcounters.c b/libpcsxcore/psxcounters.c new file mode 100644 index 00000000..0daf3cb8 --- /dev/null +++ b/libpcsxcore/psxcounters.c @@ -0,0 +1,247 @@ +/*************************************************************************** + * Copyright (C) 2007 Ryan Schultz, PCSX-df Team, PCSX team * + * schultz.ryan@gmail.com, http://rschultz.ath.cx/code.php * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You 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 Steet, Fifth Floor, Boston, MA 02111-1307 USA. * + ***************************************************************************/ + +/* +* Internal PSX counters. +*/ + +#include "psxcounters.h" +#include "cheat.h" + +static int cnts = 4; +psxCounter psxCounters[5]; + +static void psxRcntUpd(unsigned long index) { + psxCounters[index].sCycle = psxRegs.cycle; + if (((!(psxCounters[index].mode & 1)) || (index!=2)) && + psxCounters[index].mode & 0x30) { + if (psxCounters[index].mode & 0x10) { // Interrupt on target + psxCounters[index].Cycle = ((psxCounters[index].target - psxCounters[index].count) * psxCounters[index].rate) / BIAS; + } else { // Interrupt on 0xffff + psxCounters[index].Cycle = ((0xffff - psxCounters[index].count) * psxCounters[index].rate) / BIAS; + } + } else psxCounters[index].Cycle = 0xffffffff; +// if (index == 2) SysPrintf("Cycle %x\n", psxCounters[index].Cycle); +} + +static void psxRcntReset(unsigned long index) { +// SysPrintf("psxRcntReset %x (mode=%x)\n", index, psxCounters[index].mode); + psxCounters[index].count = 0; + psxRcntUpd(index); + +// if (index == 2) SysPrintf("rcnt2 %x\n", psxCounters[index].mode); + psxHu32ref(0x1070)|= SWAPu32(psxCounters[index].interrupt); + psxRegs.interrupt|= 0x80000000; + if (!(psxCounters[index].mode & 0x40)) { // Only 1 interrupt + psxCounters[index].Cycle = 0xffffffff; + } // else Continuos interrupt mode +} + +static void psxRcntSet() { + int i; + + psxNextCounter = 0x7fffffff; + psxNextsCounter = psxRegs.cycle; + + for (i=0; i<cnts; i++) { + s32 count; + + if (psxCounters[i].Cycle == 0xffffffff) continue; + + count = psxCounters[i].Cycle - (psxRegs.cycle - psxCounters[i].sCycle); + + if (count < 0) { + psxNextCounter = 0; break; + } + + if (count < (s32)psxNextCounter) { + psxNextCounter = count; + } + } +} + +void psxRcntInit() { + + memset(psxCounters, 0, sizeof(psxCounters)); + + psxCounters[0].rate = 1; psxCounters[0].interrupt = 0x10; + psxCounters[1].rate = 1; psxCounters[1].interrupt = 0x20; + psxCounters[2].rate = 1; psxCounters[2].interrupt = 0x40; + + psxCounters[3].interrupt = 1; + psxCounters[3].mode = 0x58; // The VSync counter mode + psxCounters[3].target = 1; + psxUpdateVSyncRate(); + + if (SPU_async != NULL) { + cnts = 5; + + psxCounters[4].rate = 768 * 64; + psxCounters[4].target = 1; + psxCounters[4].mode = 0x58; + } else cnts = 4; + + psxRcntUpd(0); psxRcntUpd(1); psxRcntUpd(2); psxRcntUpd(3); + psxRcntSet(); +} + +void psxUpdateVSyncRate() { + if (Config.PsxType) // ntsc - 0 | pal - 1 + psxCounters[3].rate = (PSXCLK / 50);// / BIAS; + else psxCounters[3].rate = (PSXCLK / 60);// / BIAS; + psxCounters[3].rate-= (psxCounters[3].rate / 262) * 22; + if (Config.VSyncWA) psxCounters[3].rate/= 2; +} + +void psxUpdateVSyncRateEnd() { + if (Config.PsxType) // ntsc - 0 | pal - 1 + psxCounters[3].rate = (PSXCLK / 50);// / BIAS; + else psxCounters[3].rate = (PSXCLK / 60);// / BIAS; + psxCounters[3].rate = (psxCounters[3].rate / 262) * 22; + if (Config.VSyncWA) psxCounters[3].rate/= 2; +} + +void psxRcntUpdate() { + if ((psxRegs.cycle - psxCounters[3].sCycle) >= psxCounters[3].Cycle) { + if (psxCounters[3].mode & 0x10000) { // VSync End (22 hsyncs) + psxCounters[3].mode&=~0x10000; + psxUpdateVSyncRate(); + psxRcntUpd(3); + GPU_updateLace(); // updateGPU + SysUpdate(); + ApplyCheats(); +#ifdef GTE_LOG + GTE_LOG("VSync\n"); +#endif + } else { // VSync Start (240 hsyncs) + psxCounters[3].mode|= 0x10000; + psxUpdateVSyncRateEnd(); + psxRcntUpd(3); + psxHu32ref(0x1070)|= SWAPu32(1); + psxRegs.interrupt|= 0x80000000; + } + } + + if ((psxRegs.cycle - psxCounters[0].sCycle) >= psxCounters[0].Cycle) { + psxRcntReset(0); + } + + if ((psxRegs.cycle - psxCounters[1].sCycle) >= psxCounters[1].Cycle) { + psxRcntReset(1); + } + + if ((psxRegs.cycle - psxCounters[2].sCycle) >= psxCounters[2].Cycle) { + psxRcntReset(2); + } + + if (cnts >= 5) { + if ((psxRegs.cycle - psxCounters[4].sCycle) >= psxCounters[4].Cycle) { + SPU_async((psxRegs.cycle - psxCounters[4].sCycle) * BIAS); + psxRcntReset(4); + } + } + + psxRcntSet(); +} + +void psxRcntWcount(u32 index, u32 value) { +// SysPrintf("writeCcount[%d] = %x\n", index, value); +// PSXCPU_LOG("writeCcount[%d] = %x\n", index, value); + psxCounters[index].count = value; + psxRcntUpd(index); + psxRcntSet(); +} + +void psxRcntWmode(u32 index, u32 value) { +// SysPrintf("writeCmode[%ld] = %lx\n", index, value); + psxCounters[index].mode = value; + psxCounters[index].count = 0; + if(index == 0) { + switch (value & 0x300) { + case 0x100: + psxCounters[index].rate = ((psxCounters[3].rate /** BIAS*/) / 386) / 262; // seems ok + break; + default: + psxCounters[index].rate = 1; + } + } + else if(index == 1) { + switch (value & 0x300) { + case 0x100: + psxCounters[index].rate = (psxCounters[3].rate /** BIAS*/) / 262; // seems ok + break; + default: + psxCounters[index].rate = 1; + } + } + else if(index == 2) { + switch (value & 0x300) { + case 0x200: + psxCounters[index].rate = 8; // 1/8 speed + break; + default: + psxCounters[index].rate = 1; // normal speed + } + } + + // Need to set a rate and target + psxRcntUpd(index); + psxRcntSet(); +} + +void psxRcntWtarget(u32 index, u32 value) { +// SysPrintf("writeCtarget[%ld] = %lx\n", index, value); + psxCounters[index].target = value; + psxRcntUpd(index); + psxRcntSet(); +} + +u32 psxRcntRcount(u32 index) { + u32 ret; + +// if ((!(psxCounters[index].mode & 1)) || (index!=2)) { + if (psxCounters[index].mode & 0x08) { // Wrap at target + if (Config.RCntFix) { // Parasite Eve 2 + ret = (psxCounters[index].count + /*BIAS **/ ((psxRegs.cycle - psxCounters[index].sCycle) / psxCounters[index].rate)) & 0xffff; + } else { + ret = (psxCounters[index].count + BIAS * ((psxRegs.cycle - psxCounters[index].sCycle) / psxCounters[index].rate)) & 0xffff; + } + } else { // Wrap at 0xffff + ret = (psxCounters[index].count + BIAS * (psxRegs.cycle / psxCounters[index].rate)) & 0xffff; + if (Config.RCntFix) { // Vandal Hearts 1/2 + ret/= 16; + } + } +// return (psxCounters[index].count + BIAS * ((psxRegs.cycle - psxCounters[index].sCycle) / psxCounters[index].rate)) & 0xffff; +// } else return 0; + +// SysPrintf("readCcount[%ld] = %lx (mode %lx, target %lx, cycle %lx)\n", index, ret, psxCounters[index].mode, psxCounters[index].target, psxRegs.cycle); + + return ret; +} + +int psxRcntFreeze(gzFile f, int Mode) { + char Unused[4096 - sizeof(psxCounter)]; + + gzfreezel(psxCounters); + gzfreezel(Unused); + + return 0; +} diff --git a/libpcsxcore/psxcounters.h b/libpcsxcore/psxcounters.h new file mode 100644 index 00000000..de7a5cdd --- /dev/null +++ b/libpcsxcore/psxcounters.h @@ -0,0 +1,48 @@ +/*************************************************************************** + * Copyright (C) 2007 Ryan Schultz, PCSX-df Team, PCSX team * + * schultz.ryan@gmail.com, http://rschultz.ath.cx/code.php * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You 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 Steet, Fifth Floor, Boston, MA 02111-1307 USA. * + ***************************************************************************/ + +#ifndef __PSXCOUNTERS_H__ +#define __PSXCOUNTERS_H__ + +#include "psxcommon.h" +#include "r3000a.h" +#include "psxmem.h" +#include "plugins.h" + +typedef struct { + u32 count, mode, target; + u32 sCycle, Cycle, rate, interrupt; +} psxCounter; + +extern psxCounter psxCounters[5]; + +u32 psxNextCounter, psxNextsCounter; + +void psxRcntInit(); +void psxRcntUpdate(); +void psxRcntWcount(u32 index, u32 value); +void psxRcntWmode(u32 index, u32 value); +void psxRcntWtarget(u32 index, u32 value); +u32 psxRcntRcount(u32 index); +int psxRcntFreeze(gzFile f, int Mode); + +void psxUpdateVSyncRate(); + +#endif /* __PSXCOUNTERS_H__ */ diff --git a/libpcsxcore/psxdma.c b/libpcsxcore/psxdma.c new file mode 100644 index 00000000..1a004d8f --- /dev/null +++ b/libpcsxcore/psxdma.c @@ -0,0 +1,170 @@ +/*************************************************************************** + * Copyright (C) 2007 Ryan Schultz, PCSX-df Team, PCSX team * + * schultz.ryan@gmail.com, http://rschultz.ath.cx/code.php * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You 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 Steet, Fifth Floor, Boston, MA 02111-1307 USA. * + ***************************************************************************/ + +/* +* Handles PSX DMA functions. +*/ + +#include "psxdma.h" + +// Dma0/1 in Mdec.c +// Dma3 in CdRom.c + +void psxDma4(u32 madr, u32 bcr, u32 chcr) { // SPU + u16 *ptr; + u32 size; + + switch (chcr) { + case 0x01000201: //cpu to spu transfer +#ifdef PSXDMA_LOG + PSXDMA_LOG("*** DMA4 SPU - mem2spu *** %lx addr = %lx size = %lx\n", chcr, madr, bcr); +#endif + ptr = (u16 *)PSXM(madr); + if (ptr == NULL) { +#ifdef CPU_LOG + CPU_LOG("*** DMA4 SPU - mem2spu *** NULL Pointer!!!\n"); +#endif + break; + } + SPU_writeDMAMem(ptr, (bcr >> 16) * (bcr & 0xffff) * 2); + break; + + case 0x01000200: //spu to cpu transfer +#ifdef PSXDMA_LOG + PSXDMA_LOG("*** DMA4 SPU - spu2mem *** %lx addr = %lx size = %lx\n", chcr, madr, bcr); +#endif + ptr = (u16 *)PSXM(madr); + if (ptr == NULL) { +#ifdef CPU_LOG + CPU_LOG("*** DMA4 SPU - spu2mem *** NULL Pointer!!!\n"); +#endif + break; + } + size = (bcr >> 16) * (bcr & 0xffff) * 2; + SPU_readDMAMem(ptr, size); + psxCpu->Clear(madr, size); + break; + +#ifdef PSXDMA_LOG + default: + PSXDMA_LOG("*** DMA4 SPU - unknown *** %lx addr = %lx size = %lx\n", chcr, madr, bcr); + break; +#endif + } + + HW_DMA4_CHCR &= SWAP32(~0x01000000); + DMA_INTERRUPT(4); +} + +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; + } + size = (bcr >> 16) * (bcr & 0xffff); + GPU_readDataMem(ptr, size); + psxCpu->Clear(madr, size); + break; + + 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; + } + size = (bcr >> 16) * (bcr & 0xffff); + GPU_writeDataMem(ptr, size); + GPUDMA_INT((size / 4) / BIAS); + return; +// break; + + case 0x01000401: // dma chain +#ifdef PSXDMA_LOG + PSXDMA_LOG("*** DMA 2 - GPU dma chain *** %lx addr = %lx size = %lx\n", chcr, madr, bcr); +#endif + GPU_dmaChain((u32 *)psxM, madr & 0x1fffff); + break; + +#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); +} + +void psxDma6(u32 madr, u32 bcr, u32 chcr) { + u32 *mem = (u32 *)PSXM(madr); + +#ifdef PSXDMA_LOG + PSXDMA_LOG("*** DMA6 OT *** %lx addr = %lx size = %lx\n", chcr, madr, bcr); +#endif + + if (chcr == 0x11000002) { + if (mem == NULL) { +#ifdef CPU_LOG + CPU_LOG("*** DMA6 OT *** NULL Pointer!!!\n"); +#endif + HW_DMA6_CHCR &= SWAP32(~0x01000000); + DMA_INTERRUPT(6); + return; + } + + while (bcr--) { + *mem-- = SWAP32((madr - 4) & 0xffffff); + madr -= 4; + } + mem++; *mem = 0xffffff; + } +#ifdef PSXDMA_LOG + else { + // Unknown option + PSXDMA_LOG("*** DMA6 OT - unknown *** %lx addr = %lx size = %lx\n", chcr, madr, bcr); + } +#endif + + HW_DMA6_CHCR &= SWAP32(~0x01000000); + DMA_INTERRUPT(6); +} + diff --git a/libpcsxcore/psxdma.h b/libpcsxcore/psxdma.h new file mode 100644 index 00000000..404aee06 --- /dev/null +++ b/libpcsxcore/psxdma.h @@ -0,0 +1,47 @@ +/*************************************************************************** + * Copyright (C) 2007 Ryan Schultz, PCSX-df Team, PCSX team * + * schultz.ryan@gmail.com, http://rschultz.ath.cx/code.php * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You 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 Steet, Fifth Floor, Boston, MA 02111-1307 USA. * + ***************************************************************************/ + +#ifndef __PSXDMA_H__ +#define __PSXDMA_H__ + +#include "psxcommon.h" +#include "r3000a.h" +#include "psxhw.h" +#include "psxmem.h" + +#define GPUDMA_INT(eCycle) { \ + psxRegs.interrupt |= 0x01000000; \ + psxRegs.intCycle[3+24+1] = eCycle; \ + psxRegs.intCycle[3+24] = psxRegs.cycle; \ +} + +#define MDECOUTDMA_INT(eCycle) { \ + psxRegs.interrupt |= 0x02000000; \ + psxRegs.intCycle[5+24+1] = eCycle; \ + psxRegs.intCycle[5+24] = psxRegs.cycle; \ +} + +void psxDma2(u32 madr, u32 bcr, u32 chcr); +void psxDma3(u32 madr, u32 bcr, u32 chcr); +void psxDma4(u32 madr, u32 bcr, u32 chcr); +void psxDma6(u32 madr, u32 bcr, u32 chcr); +void gpuInterrupt(); + +#endif /* __PSXDMA_H__ */ diff --git a/libpcsxcore/psxhle.c b/libpcsxcore/psxhle.c new file mode 100644 index 00000000..816e94bc --- /dev/null +++ b/libpcsxcore/psxhle.c @@ -0,0 +1,97 @@ +/*************************************************************************** + * Copyright (C) 2007 Ryan Schultz, PCSX-df Team, PCSX team * + * schultz.ryan@gmail.com, http://rschultz.ath.cx/code.php * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You 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 Steet, Fifth Floor, Boston, MA 02111-1307 USA. * + ***************************************************************************/ + +/* +* Internal PSX HLE functions. +*/ + +#include "psxhle.h" + +static void hleDummy() { + psxRegs.pc = psxRegs.GPR.n.ra; + + psxBranchTest(); +} + +static void hleA0() { + u32 call = psxRegs.GPR.n.t1 & 0xff; + + if (biosA0[call]) biosA0[call](); + + psxBranchTest(); +} + +static void hleB0() { + u32 call = psxRegs.GPR.n.t1 & 0xff; + + if (biosB0[call]) biosB0[call](); + + psxBranchTest(); +} + +static void hleC0() { + u32 call = psxRegs.GPR.n.t1 & 0xff; + + if (biosC0[call]) biosC0[call](); + + psxBranchTest(); +} + +static void hleBootstrap() { // 0xbfc00000 + SysPrintf("hleBootstrap\n"); + CheckCdrom(); + LoadCdrom(); + SysPrintf("CdromLabel: \"%s\": PC = %8.8lx (SP = %8.8lx)\n", CdromLabel, psxRegs.pc, psxRegs.GPR.n.sp); +} + +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; + +static void hleExecRet() { + EXEC *header = (EXEC*)PSXM(psxRegs.GPR.n.s0); + + SysPrintf("ExecRet %x: %x\n", psxRegs.GPR.n.s0, header->ret); + + psxRegs.GPR.n.ra = header->ret; + psxRegs.GPR.n.sp = header->_sp; + psxRegs.GPR.n.s8 = header->_fp; + psxRegs.GPR.n.gp = header->_gp; + psxRegs.GPR.n.s0 = header->base; + + psxRegs.GPR.n.v0 = 1; + psxRegs.pc = psxRegs.GPR.n.ra; +} + +void (*psxHLEt[256])() = { + hleDummy, hleA0, hleB0, hleC0, + hleBootstrap, hleExecRet, + hleDummy, hleDummy +}; diff --git a/libpcsxcore/psxhle.h b/libpcsxcore/psxhle.h new file mode 100644 index 00000000..16b37c86 --- /dev/null +++ b/libpcsxcore/psxhle.h @@ -0,0 +1,30 @@ +/*************************************************************************** + * Copyright (C) 2007 Ryan Schultz, PCSX-df Team, PCSX team * + * schultz.ryan@gmail.com, http://rschultz.ath.cx/code.php * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You 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 Steet, Fifth Floor, Boston, MA 02111-1307 USA. * + ***************************************************************************/ + +#ifndef __PSXHLE_H__ +#define __PSXHLE_H__ + +#include "psxcommon.h" +#include "r3000a.h" +#include "plugins.h" + +extern void (*psxHLEt[256])(); + +#endif /* __PSXHLE_H__ */ diff --git a/libpcsxcore/psxhw.c b/libpcsxcore/psxhw.c new file mode 100644 index 00000000..27e69ec8 --- /dev/null +++ b/libpcsxcore/psxhw.c @@ -0,0 +1,723 @@ +/*************************************************************************** + * Copyright (C) 2007 Ryan Schultz, PCSX-df Team, PCSX team * + * schultz.ryan@gmail.com, http://rschultz.ath.cx/code.php * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You 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 Steet, Fifth Floor, Boston, MA 02111-1307 USA. * + ***************************************************************************/ + +/* +* Functions for PSX hardware control. +*/ + +#include "psxhw.h" +#include "mdec.h" +#include "cdrom.h" + +void psxHwReset() { + if (Config.Sio) psxHu32ref(0x1070) |= SWAP32(0x80); + if (Config.SpuIrq) psxHu32ref(0x1070) |= SWAP32(0x200); + + memset(psxH, 0, 0x10000); + + mdecInit(); //intialize mdec decoder + cdrReset(); + psxRcntInit(); +} + +u8 psxHwRead8(u32 add) { + unsigned char hard; + + switch (add) { + case 0x1f801040: hard = sioRead8();break; + // case 0x1f801050: hard = serial_read8(); break;//for use of serial port ignore for now + case 0x1f801800: hard = cdrRead0(); break; + case 0x1f801801: hard = cdrRead1(); break; + case 0x1f801802: hard = cdrRead2(); break; + case 0x1f801803: hard = cdrRead3(); break; + default: + hard = psxHu8(add); +#ifdef PSXHW_LOG + PSXHW_LOG("*Unkwnown 8bit read at address %lx\n", add); +#endif + return hard; + } + +#ifdef PSXHW_LOG + PSXHW_LOG("*Known 8bit read at address %lx value %x\n", add, hard); +#endif + return hard; +} + +u16 psxHwRead16(u32 add) { + unsigned short hard; + + switch (add) { +#ifdef PSXHW_LOG + case 0x1f801070: PSXHW_LOG("IREG 16bit read %x\n", psxHu16(0x1070)); + return psxHu16(0x1070); +#endif +#ifdef PSXHW_LOG + case 0x1f801074: PSXHW_LOG("IMASK 16bit read %x\n", psxHu16(0x1074)); + return psxHu16(0x1074); +#endif + + case 0x1f801040: + hard = sioRead8(); + hard|= sioRead8() << 8; +#ifdef PAD_LOG + PAD_LOG("sio read16 %lx; ret = %x\n", add&0xf, hard); +#endif + return hard; + case 0x1f801044: + hard = StatReg; +#ifdef PAD_LOG + PAD_LOG("sio read16 %lx; ret = %x\n", add&0xf, hard); +#endif + return hard; + case 0x1f801048: + hard = ModeReg; +#ifdef PAD_LOG + PAD_LOG("sio read16 %lx; ret = %x\n", add&0xf, hard); +#endif + return hard; + case 0x1f80104a: + hard = CtrlReg; +#ifdef PAD_LOG + PAD_LOG("sio read16 %lx; ret = %x\n", add&0xf, hard); +#endif + return hard; + case 0x1f80104e: + hard = BaudReg; +#ifdef PAD_LOG + PAD_LOG("sio read16 %lx; ret = %x\n", add&0xf, hard); +#endif + return hard; + + //Serial port stuff not support now ;P + // case 0x1f801050: hard = serial_read16(); break; + // case 0x1f801054: hard = serial_status_read(); break; + // case 0x1f80105a: hard = serial_control_read(); break; + // case 0x1f80105e: hard = serial_baud_read(); break; + + case 0x1f801100: + hard = psxRcntRcount(0); +#ifdef PSXHW_LOG + PSXHW_LOG("T0 count read16: %x\n", hard); +#endif + return hard; + case 0x1f801104: + hard = psxCounters[0].mode; +#ifdef PSXHW_LOG + PSXHW_LOG("T0 mode read16: %x\n", hard); +#endif + return hard; + case 0x1f801108: + hard = psxCounters[0].target; +#ifdef PSXHW_LOG + PSXHW_LOG("T0 target read16: %x\n", hard); +#endif + return hard; + case 0x1f801110: + hard = psxRcntRcount(1); +#ifdef PSXHW_LOG + PSXHW_LOG("T1 count read16: %x\n", hard); +#endif + return hard; + case 0x1f801114: + hard = psxCounters[1].mode; +#ifdef PSXHW_LOG + PSXHW_LOG("T1 mode read16: %x\n", hard); +#endif + return hard; + case 0x1f801118: + hard = psxCounters[1].target; +#ifdef PSXHW_LOG + PSXHW_LOG("T1 target read16: %x\n", hard); +#endif + return hard; + case 0x1f801120: + hard = psxRcntRcount(2); +#ifdef PSXHW_LOG + PSXHW_LOG("T2 count read16: %x\n", hard); +#endif + return hard; + case 0x1f801124: + hard = psxCounters[2].mode; +#ifdef PSXHW_LOG + PSXHW_LOG("T2 mode read16: %x\n", hard); +#endif + return hard; + case 0x1f801128: + hard = psxCounters[2].target; +#ifdef PSXHW_LOG + PSXHW_LOG("T2 target read16: %x\n", hard); +#endif + return hard; + + //case 0x1f802030: hard = //int_2000???? + //case 0x1f802040: hard =//dip switches...?? + + default: + if (add>=0x1f801c00 && add<0x1f801e00) { + hard = SPU_readRegister(add); + } else { + hard = psxHu16(add); +#ifdef PSXHW_LOG + PSXHW_LOG("*Unkwnown 16bit read at address %lx\n", add); +#endif + } + return hard; + } + +#ifdef PSXHW_LOG + PSXHW_LOG("*Known 16bit read at address %lx value %x\n", add, hard); +#endif + return hard; +} + +u32 psxHwRead32(u32 add) { + u32 hard; + + switch (add) { + case 0x1f801040: + hard = sioRead8(); + hard|= sioRead8() << 8; + hard|= sioRead8() << 16; + hard|= sioRead8() << 24; +#ifdef PAD_LOG + PAD_LOG("sio read32 ;ret = %lx\n", hard); +#endif + return hard; + + // case 0x1f801050: hard = serial_read32(); break;//serial port +#ifdef PSXHW_LOG + case 0x1f801060: + PSXHW_LOG("RAM size read %lx\n", psxHu32(0x1060)); + return psxHu32(0x1060); +#endif +#ifdef PSXHW_LOG + case 0x1f801070: PSXHW_LOG("IREG 32bit read %x\n", psxHu32(0x1070)); + return psxHu32(0x1070); +#endif +#ifdef PSXHW_LOG + case 0x1f801074: PSXHW_LOG("IMASK 32bit read %x\n", psxHu32(0x1074)); + return psxHu32(0x1074); +#endif + + case 0x1f801810: + hard = GPU_readData(); +#ifdef PSXHW_LOG + PSXHW_LOG("GPU DATA 32bit read %lx\n", hard); +#endif + return hard; + case 0x1f801814: + hard = GPU_readStatus(); +#ifdef PSXHW_LOG + PSXHW_LOG("GPU STATUS 32bit read %lx\n", hard); +#endif + return hard; + + case 0x1f801820: hard = mdecRead0(); break; + case 0x1f801824: hard = mdecRead1(); break; + +#ifdef PSXHW_LOG + case 0x1f8010a0: + PSXHW_LOG("DMA2 MADR 32bit read %lx\n", psxHu32(0x10a0)); + return SWAPu32(HW_DMA2_MADR); + case 0x1f8010a4: + PSXHW_LOG("DMA2 BCR 32bit read %lx\n", psxHu32(0x10a4)); + return SWAPu32(HW_DMA2_BCR); + case 0x1f8010a8: + PSXHW_LOG("DMA2 CHCR 32bit read %lx\n", psxHu32(0x10a8)); + return SWAPu32(HW_DMA2_CHCR); +#endif + +#ifdef PSXHW_LOG + case 0x1f8010b0: + PSXHW_LOG("DMA3 MADR 32bit read %lx\n", psxHu32(0x10b0)); + return SWAPu32(HW_DMA3_MADR); + case 0x1f8010b4: + PSXHW_LOG("DMA3 BCR 32bit read %lx\n", psxHu32(0x10b4)); + return SWAPu32(HW_DMA3_BCR); + case 0x1f8010b8: + PSXHW_LOG("DMA3 CHCR 32bit read %lx\n", psxHu32(0x10b8)); + return SWAPu32(HW_DMA3_CHCR); +#endif + +#ifdef PSXHW_LOG +/* case 0x1f8010f0: + PSXHW_LOG("DMA PCR 32bit read %x\n", psxHu32(0x10f0)); + return SWAPu32(HW_DMA_PCR); // dma rest channel + case 0x1f8010f4: + PSXHW_LOG("DMA ICR 32bit read %x\n", psxHu32(0x10f4)); + return SWAPu32(HW_DMA_ICR); // interrupt enabler?*/ +#endif + + // time for rootcounters :) + case 0x1f801100: + hard = psxRcntRcount(0); +#ifdef PSXHW_LOG + PSXHW_LOG("T0 count read32: %lx\n", hard); +#endif + return hard; + case 0x1f801104: + hard = psxCounters[0].mode; +#ifdef PSXHW_LOG + PSXHW_LOG("T0 mode read32: %lx\n", hard); +#endif + return hard; + case 0x1f801108: + hard = psxCounters[0].target; +#ifdef PSXHW_LOG + PSXHW_LOG("T0 target read32: %lx\n", hard); +#endif + return hard; + case 0x1f801110: + hard = psxRcntRcount(1); +#ifdef PSXHW_LOG + PSXHW_LOG("T1 count read32: %lx\n", hard); +#endif + return hard; + case 0x1f801114: + hard = psxCounters[1].mode; +#ifdef PSXHW_LOG + PSXHW_LOG("T1 mode read32: %lx\n", hard); +#endif + return hard; + case 0x1f801118: + hard = psxCounters[1].target; +#ifdef PSXHW_LOG + PSXHW_LOG("T1 target read32: %lx\n", hard); +#endif + return hard; + case 0x1f801120: + hard = psxRcntRcount(2); +#ifdef PSXHW_LOG + PSXHW_LOG("T2 count read32: %lx\n", hard); +#endif + return hard; + case 0x1f801124: + hard = psxCounters[2].mode; +#ifdef PSXHW_LOG + PSXHW_LOG("T2 mode read32: %lx\n", hard); +#endif + return hard; + case 0x1f801128: + hard = psxCounters[2].target; +#ifdef PSXHW_LOG + PSXHW_LOG("T2 target read32: %lx\n", hard); +#endif + return hard; + + default: + hard = psxHu32(add); +#ifdef PSXHW_LOG + PSXHW_LOG("*Unkwnown 32bit read at address %lx\n", add); +#endif + return hard; + } +#ifdef PSXHW_LOG + PSXHW_LOG("*Known 32bit read at address %lx\n", add); +#endif + return hard; +} + +void psxHwWrite8(u32 add, u8 value) { + switch (add) { + case 0x1f801040: sioWrite8(value); break; + // case 0x1f801050: serial_write8(value); break;//serial port + case 0x1f801800: cdrWrite0(value); break; + case 0x1f801801: cdrWrite1(value); break; + case 0x1f801802: cdrWrite2(value); break; + case 0x1f801803: cdrWrite3(value); break; + + default: + psxHu8(add) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("*Unknown 8bit write at address %lx value %x\n", add, value); +#endif + return; + } + psxHu8(add) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("*Known 8bit write at address %lx value %x\n", add, value); +#endif +} + +void psxHwWrite16(u32 add, u16 value) { + switch (add) { + case 0x1f801040: + sioWrite8((unsigned char)value); + sioWrite8((unsigned char)(value>>8)); +#ifdef PAD_LOG + PAD_LOG ("sio write16 %lx, %x\n", add&0xf, value); +#endif + return; + case 0x1f801044: +#ifdef PAD_LOG + PAD_LOG ("sio write16 %lx, %x\n", add&0xf, value); +#endif + return; + case 0x1f801048: + ModeReg = value; +#ifdef PAD_LOG + PAD_LOG ("sio write16 %lx, %x\n", add&0xf, value); +#endif + return; + case 0x1f80104a: // control register + sioWriteCtrl16(value); +#ifdef PAD_LOG + PAD_LOG ("sio write16 %lx, %x\n", add&0xf, value); +#endif + return; + case 0x1f80104e: // baudrate register + BaudReg = value; +#ifdef PAD_LOG + PAD_LOG ("sio write16 %lx, %x\n", add&0xf, value); +#endif + return; + + //serial port ;P + // case 0x1f801050: serial_write16(value); break; + // case 0x1f80105a: serial_control_write(value);break; + // case 0x1f80105e: serial_baud_write(value); break; + // case 0x1f801054: serial_status_write(value); break; + + case 0x1f801070: +#ifdef PSXHW_LOG + PSXHW_LOG("IREG 16bit write %x\n", value); +#endif + if (Config.Sio) psxHu16ref(0x1070) |= SWAPu16(0x80); + if (Config.SpuIrq) psxHu16ref(0x1070) |= SWAPu16(0x200); + psxHu16ref(0x1070) &= SWAPu16((psxHu16(0x1074) & value)); + return; + + case 0x1f801074: +#ifdef PSXHW_LOG + PSXHW_LOG("IMASK 16bit write %x\n", value); +#endif + psxHu16ref(0x1074) = SWAPu16(value); + psxRegs.interrupt |= 0x80000000; + return; + + case 0x1f801100: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 0 COUNT 16bit write %x\n", value); +#endif + psxRcntWcount(0, value); return; + case 0x1f801104: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 0 MODE 16bit write %x\n", value); +#endif + psxRcntWmode(0, value); return; + case 0x1f801108: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 0 TARGET 16bit write %x\n", value); +#endif + psxRcntWtarget(0, value); return; + + case 0x1f801110: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 1 COUNT 16bit write %x\n", value); +#endif + psxRcntWcount(1, value); return; + case 0x1f801114: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 1 MODE 16bit write %x\n", value); +#endif + psxRcntWmode(1, value); return; + case 0x1f801118: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 1 TARGET 16bit write %x\n", value); +#endif + psxRcntWtarget(1, value); return; + + case 0x1f801120: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 2 COUNT 16bit write %x\n", value); +#endif + psxRcntWcount(2, value); return; + case 0x1f801124: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 2 MODE 16bit write %x\n", value); +#endif + psxRcntWmode(2, value); return; + case 0x1f801128: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 2 TARGET 16bit write %x\n", value); +#endif + psxRcntWtarget(2, value); return; + + default: + if (add>=0x1f801c00 && add<0x1f801e00) { + SPU_writeRegister(add, value); + return; + } + + psxHu16ref(add) = SWAPu16(value); +#ifdef PSXHW_LOG + PSXHW_LOG("*Unknown 16bit write at address %lx value %x\n", add, value); +#endif + return; + } + psxHu16ref(add) = SWAPu16(value); +#ifdef PSXHW_LOG + PSXHW_LOG("*Known 16bit write at address %lx value %x\n", add, value); +#endif +} + +#define DmaExec(n) { \ + if (SWAPu32(HW_DMA##n##_CHCR) & 0x01000000) return; \ + HW_DMA##n##_CHCR = SWAPu32(value); \ + \ + if (SWAPu32(HW_DMA##n##_CHCR) & 0x01000000 && SWAPu32(HW_DMA_PCR) & (8 << (n * 4))) { \ + psxDma##n(SWAPu32(HW_DMA##n##_MADR), SWAPu32(HW_DMA##n##_BCR), SWAPu32(HW_DMA##n##_CHCR)); \ + } \ +} + +void psxHwWrite32(u32 add, u32 value) { + switch (add) { + case 0x1f801040: + sioWrite8((unsigned char)value); + sioWrite8((unsigned char)((value&0xff) >> 8)); + sioWrite8((unsigned char)((value&0xff) >> 16)); + sioWrite8((unsigned char)((value&0xff) >> 24)); +#ifdef PAD_LOG + PAD_LOG("sio write32 %lx\n", value); +#endif + return; + // case 0x1f801050: serial_write32(value); break;//serial port +#ifdef PSXHW_LOG + case 0x1f801060: + PSXHW_LOG("RAM size write %lx\n", value); + psxHu32ref(add) = SWAPu32(value); + return; // Ram size +#endif + + case 0x1f801070: +#ifdef PSXHW_LOG + PSXHW_LOG("IREG 32bit write %lx\n", value); +#endif + if (Config.Sio) psxHu32ref(0x1070) |= SWAPu32(0x80); + if (Config.SpuIrq) psxHu32ref(0x1070) |= SWAPu32(0x200); + psxHu32ref(0x1070) &= SWAPu32((psxHu32(0x1074) & value)); + return; + case 0x1f801074: +#ifdef PSXHW_LOG + PSXHW_LOG("IMASK 32bit write %lx\n", value); +#endif + psxHu32ref(0x1074) = SWAPu32(value); + psxRegs.interrupt|= 0x80000000; + return; + +#ifdef PSXHW_LOG + case 0x1f801080: + PSXHW_LOG("DMA0 MADR 32bit write %lx\n", value); + HW_DMA0_MADR = SWAPu32(value); return; // DMA0 madr + case 0x1f801084: + PSXHW_LOG("DMA0 BCR 32bit write %lx\n", value); + HW_DMA0_BCR = SWAPu32(value); return; // DMA0 bcr +#endif + case 0x1f801088: +#ifdef PSXHW_LOG + PSXHW_LOG("DMA0 CHCR 32bit write %lx\n", value); +#endif + DmaExec(0); // DMA0 chcr (MDEC in DMA) + return; + +#ifdef PSXHW_LOG + case 0x1f801090: + PSXHW_LOG("DMA1 MADR 32bit write %lx\n", value); + HW_DMA1_MADR = SWAPu32(value); return; // DMA1 madr + case 0x1f801094: + PSXHW_LOG("DMA1 BCR 32bit write %lx\n", value); + HW_DMA1_BCR = SWAPu32(value); return; // DMA1 bcr +#endif + case 0x1f801098: +#ifdef PSXHW_LOG + PSXHW_LOG("DMA1 CHCR 32bit write %lx\n", value); +#endif + DmaExec(1); // DMA1 chcr (MDEC out DMA) + return; + +#ifdef PSXHW_LOG + case 0x1f8010a0: + PSXHW_LOG("DMA2 MADR 32bit write %lx\n", value); + HW_DMA2_MADR = SWAPu32(value); return; // DMA2 madr + case 0x1f8010a4: + PSXHW_LOG("DMA2 BCR 32bit write %lx\n", value); + HW_DMA2_BCR = SWAPu32(value); return; // DMA2 bcr +#endif + case 0x1f8010a8: +#ifdef PSXHW_LOG + PSXHW_LOG("DMA2 CHCR 32bit write %lx\n", value); +#endif + DmaExec(2); // DMA2 chcr (GPU DMA) + return; + +#ifdef PSXHW_LOG + case 0x1f8010b0: + PSXHW_LOG("DMA3 MADR 32bit write %lx\n", value); + HW_DMA3_MADR = SWAPu32(value); return; // DMA3 madr + case 0x1f8010b4: + PSXHW_LOG("DMA3 BCR 32bit write %lx\n", value); + HW_DMA3_BCR = SWAPu32(value); return; // DMA3 bcr +#endif + case 0x1f8010b8: +#ifdef PSXHW_LOG + PSXHW_LOG("DMA3 CHCR 32bit write %lx\n", value); +#endif + DmaExec(3); // DMA3 chcr (CDROM DMA) + + return; + +#ifdef PSXHW_LOG + case 0x1f8010c0: + PSXHW_LOG("DMA4 MADR 32bit write %lx\n", value); + HW_DMA4_MADR = SWAPu32(value); return; // DMA4 madr + case 0x1f8010c4: + PSXHW_LOG("DMA4 BCR 32bit write %lx\n", value); + HW_DMA4_BCR = SWAPu32(value); return; // DMA4 bcr +#endif + case 0x1f8010c8: +#ifdef PSXHW_LOG + PSXHW_LOG("DMA4 CHCR 32bit write %lx\n", value); +#endif + DmaExec(4); // DMA4 chcr (SPU DMA) + return; + +#if 0 + case 0x1f8010d0: break; //DMA5write_madr(); + case 0x1f8010d4: break; //DMA5write_bcr(); + case 0x1f8010d8: break; //DMA5write_chcr(); // Not needed +#endif + +#ifdef PSXHW_LOG + case 0x1f8010e0: + PSXHW_LOG("DMA6 MADR 32bit write %lx\n", value); + HW_DMA6_MADR = SWAPu32(value); return; // DMA6 bcr + case 0x1f8010e4: + PSXHW_LOG("DMA6 BCR 32bit write %lx\n", value); + HW_DMA6_BCR = SWAPu32(value); return; // DMA6 bcr +#endif + case 0x1f8010e8: +#ifdef PSXHW_LOG + PSXHW_LOG("DMA6 CHCR 32bit write %lx\n", value); +#endif + DmaExec(6); // DMA6 chcr (OT clear) + return; + +#ifdef PSXHW_LOG + case 0x1f8010f0: + PSXHW_LOG("DMA PCR 32bit write %lx\n", value); + HW_DMA_PCR = SWAPu32(value); + return; +#endif + + case 0x1f8010f4: +#ifdef PSXHW_LOG + PSXHW_LOG("DMA ICR 32bit write %lx\n", value); +#endif + { + u32 tmp = (~value) & SWAPu32(HW_DMA_ICR); + HW_DMA_ICR = SWAPu32(((tmp ^ value) & 0xffffff) ^ tmp); + return; + } + + case 0x1f801810: +#ifdef PSXHW_LOG + PSXHW_LOG("GPU DATA 32bit write %lx\n", value); +#endif + GPU_writeData(value); return; + case 0x1f801814: +#ifdef PSXHW_LOG + PSXHW_LOG("GPU STATUS 32bit write %lx\n", value); +#endif + GPU_writeStatus(value); return; + + case 0x1f801820: + mdecWrite0(value); break; + case 0x1f801824: + mdecWrite1(value); break; + + case 0x1f801100: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 0 COUNT 32bit write %lx\n", value); +#endif + psxRcntWcount(0, value & 0xffff); return; + case 0x1f801104: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 0 MODE 32bit write %lx\n", value); +#endif + psxRcntWmode(0, value); return; + case 0x1f801108: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 0 TARGET 32bit write %lx\n", value); +#endif + psxRcntWtarget(0, value & 0xffff); return; // HW_DMA_ICR&= SWAP32((~value)&0xff000000); + + case 0x1f801110: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 1 COUNT 32bit write %lx\n", value); +#endif + psxRcntWcount(1, value & 0xffff); return; + case 0x1f801114: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 1 MODE 32bit write %lx\n", value); +#endif + psxRcntWmode(1, value); return; + case 0x1f801118: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 1 TARGET 32bit write %lx\n", value); +#endif + psxRcntWtarget(1, value & 0xffff); return; + + case 0x1f801120: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 2 COUNT 32bit write %lx\n", value); +#endif + psxRcntWcount(2, value & 0xffff); return; + case 0x1f801124: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 2 MODE 32bit write %lx\n", value); +#endif + psxRcntWmode(2, value); return; + case 0x1f801128: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 2 TARGET 32bit write %lx\n", value); +#endif + psxRcntWtarget(2, value & 0xffff); return; + + default: + psxHu32ref(add) = SWAPu32(value); +#ifdef PSXHW_LOG + PSXHW_LOG("*Unknown 32bit write at address %lx value %lx\n", add, value); +#endif + return; + } + psxHu32ref(add) = SWAPu32(value); +#ifdef PSXHW_LOG + PSXHW_LOG("*Known 32bit write at address %lx value %lx\n", add, value); +#endif +} + +int psxHwFreeze(gzFile f, int Mode) { + char Unused[4096]; + + gzfreezel(Unused); + + return 0; +} diff --git a/libpcsxcore/psxhw.h b/libpcsxcore/psxhw.h new file mode 100644 index 00000000..92c66f90 --- /dev/null +++ b/libpcsxcore/psxhw.h @@ -0,0 +1,74 @@ +/*************************************************************************** + * Copyright (C) 2007 Ryan Schultz, PCSX-df Team, PCSX team * + * schultz.ryan@gmail.com, http://rschultz.ath.cx/code.php * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You 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 Steet, Fifth Floor, Boston, MA 02111-1307 USA. * + ***************************************************************************/ + +#ifndef __PSXHW_H__ +#define __PSXHW_H__ + +#include "psxcommon.h" +#include "r3000a.h" +#include "psxmem.h" +#include "sio.h" +#include "psxcounters.h" + +#define HW_DMA0_MADR (psxHu32ref(0x1080)) // MDEC in DMA +#define HW_DMA0_BCR (psxHu32ref(0x1084)) +#define HW_DMA0_CHCR (psxHu32ref(0x1088)) + +#define HW_DMA1_MADR (psxHu32ref(0x1090)) // MDEC out DMA +#define HW_DMA1_BCR (psxHu32ref(0x1094)) +#define HW_DMA1_CHCR (psxHu32ref(0x1098)) + +#define HW_DMA2_MADR (psxHu32ref(0x10a0)) // GPU DMA +#define HW_DMA2_BCR (psxHu32ref(0x10a4)) +#define HW_DMA2_CHCR (psxHu32ref(0x10a8)) + +#define HW_DMA3_MADR (psxHu32ref(0x10b0)) // CDROM DMA +#define HW_DMA3_BCR (psxHu32ref(0x10b4)) +#define HW_DMA3_CHCR (psxHu32ref(0x10b8)) + +#define HW_DMA4_MADR (psxHu32ref(0x10c0)) // SPU DMA +#define HW_DMA4_BCR (psxHu32ref(0x10c4)) +#define HW_DMA4_CHCR (psxHu32ref(0x10c8)) + +#define HW_DMA6_MADR (psxHu32ref(0x10e0)) // GPU DMA (OT) +#define HW_DMA6_BCR (psxHu32ref(0x10e4)) +#define HW_DMA6_CHCR (psxHu32ref(0x10e8)) + +#define HW_DMA_PCR (psxHu32ref(0x10f0)) +#define HW_DMA_ICR (psxHu32ref(0x10f4)) + +#define DMA_INTERRUPT(n) \ + if (SWAPu32(HW_DMA_ICR) & (1 << (16 + n))) { \ + HW_DMA_ICR|= SWAP32(1 << (24 + n)); \ + psxHu32ref(0x1070) |= SWAP32(8); \ + psxRegs.interrupt|= 0x80000000; \ + } + + +void psxHwReset(); +u8 psxHwRead8 (u32 add); +u16 psxHwRead16(u32 add); +u32 psxHwRead32(u32 add); +void psxHwWrite8 (u32 add, u8 value); +void psxHwWrite16(u32 add, u16 value); +void psxHwWrite32(u32 add, u32 value); +int psxHwFreeze(gzFile f, int Mode); + +#endif /* __PSXHW_H__ */ diff --git a/libpcsxcore/psxinterpreter.c b/libpcsxcore/psxinterpreter.c new file mode 100644 index 00000000..2eabc16e --- /dev/null +++ b/libpcsxcore/psxinterpreter.c @@ -0,0 +1,857 @@ +/*************************************************************************** + * Copyright (C) 2007 Ryan Schultz, PCSX-df Team, PCSX team * + * schultz.ryan@gmail.com, http://rschultz.ath.cx/code.php * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You 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 Steet, Fifth Floor, Boston, MA 02111-1307 USA. * + ***************************************************************************/ + +/* + * PSX assembly interpreter. + */ + +#include "psxcommon.h" +#include "r3000a.h" +#include "gte.h" +#include "psxhle.h" +/*FIXME*/ +#include "../gui/hdebug.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 + +inline void execI(); +inline void execIDbg(); + +// 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; + + psxBranchTest(); + + psxRegs.GPR.r[reg] = rold; + execI(); // first branch opcode + psxRegs.GPR.r[reg] = rnew; + + branch = 0; +} + +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 0x02: + case 0x10: case 0x12: // BLTZ/BGEZ... + 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 + if (_tRs_ == reg || _tRt_ == reg) return 2; + break; + + case 0x06: case 0x07: // BLEZ/BGTZ + 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; + + code = (u32 *)PSXM(bpc); + 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(); +} + +__inline void doBranch(u32 tar) { + u32 *code; + u32 tmp; + + branch2 = branch = 1; + branchPC = tar; + + code = (u32 *)PSXM(psxRegs.pc); + psxRegs.code = ((code == NULL) ? 0 : SWAP32(*code)); + + debugI(); + + psxRegs.pc += 4; + psxRegs.cycle++; + + // 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_); + } +} + +void psxDIVU() { + if (_rRt_ != 0) { + _rLo_ = _rRs_ / _rRt_; + _rHi_ = _rRs_ % _rRt_; + } +} + +void psxMULT() { + u64 res = (s64)((s64)_i32(_rRs_) * (s64)_i32(_rRt_)); + + psxRegs.GPR.n.lo = (u32)(res & 0xffffffff); + psxRegs.GPR.n.hi = (u32)((res >> 32) & 0xffffffff); +} + +void psxMULTU() { + u64 res = (u64)((u64)_u32(_rRs_) * (u64)_u32(_rRt_)); + + psxRegs.GPR.n.lo = (u32)(res & 0xffffffff); + psxRegs.GPR.n.hi = (u32)((res >> 32) & 0xffffffff); +} + +/********************************************************* +* Register branch logic * +* Format: OP rs, offset * +*********************************************************/ +#define RepZBranchi32(op) if(_i32(_rRs_) op 0) doBranch(_BranchTarget_); +#define RepZBranchLinki32(op) if(_i32(_rRs_) op 0) { _SetLink(31); doBranch(_BranchTarget_); } + +void psxBGEZ() { RepZBranchi32(>=) } // Branch if Rs >= 0 +void psxBGEZAL() { RepZBranchLinki32(>=) } // Branch if Rs >= 0 and link +void psxBGTZ() { RepZBranchi32(>) } // Branch if Rs > 0 +void psxBLEZ() { RepZBranchi32(<=) } // Branch if Rs <= 0 +void psxBLTZ() { RepZBranchi32(<) } // Branch if Rs < 0 +void psxBLTZAL() { RepZBranchLinki32(<) } // Branch if Rs < 0 and link + +/********************************************************* +* Shift arithmetic with constant shift * +* Format: OP rd, rt, sa * +*********************************************************/ +void psxSLL() { if (!_Rd_) return; _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() { + if (_Rt_) { + _i32(_rRt_) = (signed char)psxMemRead8(_oB_); + } else { + psxMemRead8(_oB_); + } +} + +void psxLBU() { + if (_Rt_) { + _u32(_rRt_) = psxMemRead8(_oB_); + } else { + psxMemRead8(_oB_); + } +} + +void psxLH() { + if (_Rt_) { + _i32(_rRt_) = (short)psxMemRead16(_oB_); + } else { + psxMemRead16(_oB_); + } +} + +void psxLHU() { + if (_Rt_) { + _u32(_rRt_) = psxMemRead16(_oB_); + } else { + psxMemRead16(_oB_); + } +} + +void psxLW() { + 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); + + 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); + + 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() { if (!_Rt_) return; _i32(_rRt_) = (int)_rFs_; } +void psxCFC0() { 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); + } +} + +__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(); + psxRegs.interrupt|= 0x80000000; + 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_)); } + +/********************************************************* +* 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() { + 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])() = { + gteMFC2, psxNULL, gteCFC2, 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() { +} + +static void intExecute() { + for (;;) + execI(); +} + +static void intExecuteDbg() { + for (;;) + execIDbg(); +} + +static void intExecuteBlock() { + branch2 = 0; + while (!branch2) execI(); +} + +static void intExecuteBlockDbg() { + branch2 = 0; + while (!branch2) execIDbg(); +} + +static void intClear(u32 Addr, u32 Size) { +} + +static void intShutdown() { +} + +// interpreter execution +inline void execI() { + u32 *code = (u32 *)PSXM(psxRegs.pc); + psxRegs.code = ((code == NULL) ? 0 : SWAP32(*code)); + + debugI(); + + psxRegs.pc += 4; + psxRegs.cycle++; + + psxBSC[psxRegs.code >> 26](); +} + +/* debugger version */ +inline void execIDbg() { + u32 *code = (u32 *)PSXM(psxRegs.pc); + psxRegs.code = ((code == NULL) ? 0 : SWAP32(*code)); + + // dump opcode when LOG_CPU is enabled + debugI(); + + // normal execution + if (!hdb_pause) { + psxRegs.pc += 4; + psxRegs.cycle++; + psxBSC[psxRegs.code >> 26](); + } + + // trace one instruction + if(hdb_pause == 2) { + psxRegs.pc += 4; + psxRegs.cycle++; + psxBSC[psxRegs.code >> 26](); + hdb_pause = 1; + } + + // wait for breakpoint + if(hdb_pause == 3) { + psxRegs.pc+= 4; psxRegs.cycle++; + psxBSC[psxRegs.code >> 26](); + if(psxRegs.pc == hdb_break) hdb_pause = 1; + } +} + +R3000Acpu psxInt = { + intInit, + intReset, + intExecute, + intExecuteBlock, + intClear, + intShutdown +}; + +R3000Acpu psxIntDbg = { + intInit, + intReset, + intExecuteDbg, + intExecuteBlockDbg, + intClear, + intShutdown +}; diff --git a/libpcsxcore/psxmem.c b/libpcsxcore/psxmem.c new file mode 100644 index 00000000..8dfc00e6 --- /dev/null +++ b/libpcsxcore/psxmem.c @@ -0,0 +1,324 @@ +/*************************************************************************** + * Copyright (C) 2007 Ryan Schultz, PCSX-df Team, PCSX team * + * schultz.ryan@gmail.com, http://rschultz.ath.cx/code.php * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You 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 Steet, Fifth Floor, Boston, MA 02111-1307 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 + +/* 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) + +0x8000_0000-0x801f_ffff Kernel and User Memory Mirror (2 Meg) Cached + +0xa000_0000-0xa01f_ffff Kernel and User Memory Mirror (2 Meg) Uncached + +0xbfc0_0000-0xbfc7_ffff BIOS (512K) +*/ + +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 = (char*)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*)); + + for (i=0; i<0x01; i++) psxMemRLUT[i + 0x1f00] = (u8*)&psxP[i << 16]; + + for (i=0; i<0x01; i++) psxMemRLUT[i + 0x1f80] = (u8*)&psxH[i << 16]; + + for (i=0; i<0x08; i++) psxMemRLUT[i + 0xbfc0] = (u8*)&psxR[i << 16]; + +// 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*)); + + for (i=0; i<0x01; i++) psxMemWLUT[i + 0x1f00] = (u8*)&psxP[i << 16]; + + for (i=0; i<0x01; i++) psxMemWLUT[i + 0x1f80] = (u8*)&psxH[i << 16]; + + return 0; +} + +void psxMemReset() { + FILE *f = NULL; + char bios[1024]; + + memset(psxM, 0, 0x00200000); + memset(psxP, 0, 0x00010000); + + if (strcmp(Config.Bios, "HLE")) { + 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 = BIOS_HLE; + } + else { + fread(psxR, 1, 0x80000, f); + fclose(f); + Config.HLE = BIOS_USER_DEFINED; + } + } else Config.HLE = BIOS_HLE; +} + +void psxMemShutdown() { + munmap(psxM, 0x00220000); + + free(psxR); + free(psxMemRLUT); + free(psxMemWLUT); +} + +static int writeok = 1; + +u8 psxMemRead8(u32 mem) { + char *p; + u32 t; + + t = mem >> 16; + if (t == 0x1f80) { + if (mem < 0x1f801000) + return psxHu8(mem); + else + return psxHwRead8(mem); + } else { + p = (char *)(psxMemRLUT[t]); + if (p != NULL) { + 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; + + t = mem >> 16; + if (t == 0x1f80) { + if (mem < 0x1f801000) + return psxHu16(mem); + else + return psxHwRead16(mem); + } else { + p = (char *)(psxMemRLUT[t]); + if (p != NULL) { + 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; + + t = mem >> 16; + if (t == 0x1f80) { + if (mem < 0x1f801000) + return psxHu32(mem); + else + return psxHwRead32(mem); + } else { + p = (char *)(psxMemRLUT[t]); + if (p != NULL) { + 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; + + t = mem >> 16; + if (t == 0x1f80) { + if (mem < 0x1f801000) + psxHu8(mem) = value; + else + psxHwWrite8(mem, value); + } else { + p = (char *)(psxMemWLUT[t]); + if (p != NULL) { + *(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; + + 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) { + *(u16 *)(p + (mem & 0xffff)) = SWAPu16(value); +#ifdef PSXREC + psxCpu->Clear((mem & (~1)), 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; + +// 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) { + *(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; + + 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*)); + break; + 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 new file mode 100644 index 00000000..cc4616c6 --- /dev/null +++ b/libpcsxcore/psxmem.h @@ -0,0 +1,140 @@ +/*************************************************************************** + * Copyright (C) 2007 Ryan Schultz, PCSX-df Team, PCSX team * + * schultz.ryan@gmail.com, http://rschultz.ath.cx/code.php * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You 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 Steet, Fifth Floor, Boston, MA 02111-1307 USA. * + ***************************************************************************/ + +#ifndef __PSXMEMORY_H__ +#define __PSXMEMORY_H__ + +#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 + +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]) + +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]) + +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]) + +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]) + +u8** psxMemWLUT; +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(__sh__) || 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); + +#endif /* __PSXMEMORY_H__ */ + diff --git a/libpcsxcore/r3000a.c b/libpcsxcore/r3000a.c new file mode 100644 index 00000000..b46ec124 --- /dev/null +++ b/libpcsxcore/r3000a.c @@ -0,0 +1,209 @@ +/*************************************************************************** + * Copyright (C) 2007 Ryan Schultz, PCSX-df Team, PCSX team * + * schultz.ryan@gmail.com, http://rschultz.ath.cx/code.php * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You 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 Steet, Fifth Floor, Boston, MA 02111-1307 USA. * + ***************************************************************************/ + +/* +* R3000A CPU functions. +*/ + +#include "r3000a.h" +#include "cdrom.h" +#include "mdec.h" +#include "gte.h" +#include "cheat.h" + +psxRegisters psxRegs; + +int psxInit() { + SysPrintf(_("Running PCSX Version %s (%s).\n"), PACKAGE_VERSION, __DATE__); + +#ifdef PSXREC + if (Config.Cpu) { + if (Config.Dbg) psxCpu = &psxIntDbg; + else psxCpu = &psxInt; + } else psxCpu = &psxRec; +#else + if (Config.Dbg) psxCpu = &psxIntDbg; + 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(); + + ClearAllCheats(); +} + +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 && (((PSXMu32(psxRegs.CP0.n.EPC) >> 24) & 0xfe) == 0x4a)) { + // "hokuto no ken" / "Crash Bandicot 2" ... fix + PSXMu32ref(psxRegs.CP0.n.EPC)&= SWAPu32(~0x02000000); + } + + if (Config.HLE) psxBiosException(); +} + +void psxBranchTest() { + if ((psxRegs.cycle - psxNextsCounter) >= psxNextCounter) + psxRcntUpdate(); + + if (psxRegs.interrupt) { + if ((psxRegs.interrupt & 0x80) && (!Config.Sio)) { // sio + if ((psxRegs.cycle - psxRegs.intCycle[7]) >= psxRegs.intCycle[7+1]) { + psxRegs.interrupt&=~0x80; + sioInterrupt(); + } + } + if (psxRegs.interrupt & 0x04) { // cdr + if ((psxRegs.cycle - psxRegs.intCycle[2]) >= psxRegs.intCycle[2+1]) { + psxRegs.interrupt&=~0x04; + cdrInterrupt(); + } + } + if (psxRegs.interrupt & 0x040000) { // cdr read + if ((psxRegs.cycle - psxRegs.intCycle[2+16]) >= psxRegs.intCycle[2+16+1]) { + psxRegs.interrupt&=~0x040000; + cdrReadInterrupt(); + } + } + if (psxRegs.interrupt & 0x01000000) { // gpu dma + if ((psxRegs.cycle - psxRegs.intCycle[3+24]) >= psxRegs.intCycle[3+24+1]) { + psxRegs.interrupt&=~0x01000000; + gpuInterrupt(); + } + } + if (psxRegs.interrupt & 0x02000000) { // mdec out dma + if ((psxRegs.cycle - psxRegs.intCycle[5+24]) >= psxRegs.intCycle[5+24+1]) { + psxRegs.interrupt&=~0x02000000; + mdec1Interrupt(); + } + } + + if (psxRegs.interrupt & 0x80000000) { + psxRegs.interrupt&=~0x80000000; + psxTestHWInts(); + } + } +// if (psxRegs.cycle > 0xd29c6500) Log=1; +} + +void psxTestHWInts() { + if (psxHu32(0x1070) & psxHu32(0x1074)) { + if ((psxRegs.CP0.n.Status & 0x401) == 0x401) { +#ifdef PSXCPU_LOG + PSXCPU_LOG("Interrupt: %x %x\n", psxHu32(0x1070), psxHu32(0x1074)); +#endif +// SysPrintf("Interrupt (%x): %x %x\n", psxRegs.cycle, psxHu32(0x1070), psxHu32(0x1074)); + psxException(0x400, 0); + } + } +} + +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 new file mode 100644 index 00000000..56c965fc --- /dev/null +++ b/libpcsxcore/r3000a.h @@ -0,0 +1,224 @@ +/*************************************************************************** + * Copyright (C) 2007 Ryan Schultz, PCSX-df Team, PCSX team * + * schultz.ryan@gmail.com, http://rschultz.ath.cx/code.php * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You 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 Steet, Fifth Floor, Boston, MA 02111-1307 USA. * + ***************************************************************************/ + +#ifndef __R3000A_H__ +#define __R3000A_H__ + +#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; + +R3000Acpu *psxCpu; +extern R3000Acpu psxInt; +extern R3000Acpu psxIntDbg; +#if (defined(__x86_64__) || defined(__i386__) || defined(__sh__) || defined(__ppc__)) && !defined(NOPSXREC) +extern R3000Acpu psxRec; +#define PSXREC +#endif + +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[33] and r[34] */ +} psxGPRRegs; + +typedef union { + struct { + u32 Index, Random, EntryLo0, EntryLo1, + Context, PageMask, Wired, Reserved0, + BadVAddr, Count, EntryHi, Compare, + Status, Cause, EPC, PRid, + Config, LLAddr, WatchLO, WatchHI, + XContext, Reserved1, Reserved2, Reserved3, + Reserved4, Reserved5, ECC, CacheErr, + TagLo, TagHi, ErrorEPC, Reserved6; + } n; + u32 r[32]; +} 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]; +} 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]; +} psxCP2Ctrl; + +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; + u32 intCycle[32]; +} psxRegisters; + +extern psxRegisters psxRegs; + +#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 psxTestHWInts(); +void psxJumpTest(); + +#endif /* __R3000A_H__ */ diff --git a/libpcsxcore/sio.c b/libpcsxcore/sio.c new file mode 100644 index 00000000..6e98d1fb --- /dev/null +++ b/libpcsxcore/sio.c @@ -0,0 +1,673 @@ +/*************************************************************************** + * Copyright (C) 2007 Ryan Schultz, PCSX-df Team, PCSX team * + * schultz.ryan@gmail.com, http://rschultz.ath.cx/code.php * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You 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 Steet, Fifth Floor, Boston, MA 02111-1307 USA. * + ***************************************************************************/ + +/* +* SIO functions. +*/ + +#include "sio.h" +#include <sys/stat.h> + +// *** FOR WORKS ON PADS AND MEMORY CARDS ***** + +static unsigned char buf[256]; +unsigned char cardh[4] = { 0x00, 0x00, 0x5a, 0x5d }; + +//static unsigned short StatReg = 0x002b; +// Transfer Ready and the Buffer is Empty +unsigned short StatReg = TX_RDY | TX_EMPTY; +unsigned short ModeReg; +unsigned short CtrlReg; +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; + +PadDataS pad; + +char Mcd1Data[MCD_SIZE], Mcd2Data[MCD_SIZE]; + +// clk cycle byte +// 4us * 8bits = ((PSXCLK / 1000000) * 32) / BIAS; (linuzappz) +#define SIO_INT() { \ + if (!Config.Sio) { \ + psxRegs.interrupt|= 0x80; \ + psxRegs.intCycle[7+1] = 200; /*270;*/ \ + psxRegs.intCycle[7] = psxRegs.cycle; \ + } \ +} + +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; +} + +void netError() { + ClosePlugins(); + SysMessage(_("Connection closed!\n")); + SysRunGui(); +} + +void sioWrite8(unsigned char value) { +#ifdef PAD_LOG + PAD_LOG("sio write8 %x\n", value); +#endif + switch (padst) { + case 1: SIO_INT(); + 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; + } + if (buf[parp] == 0x41) { + switch (value) { + case 0x43: + buf[1] = 0x43; + break; + case 0x45: + buf[1] = 0xf3; + break; + } + } + } + else padst = 0; + return; + case 2: + parp++; +/* if (buf[1] == 0x45) { + buf[parp] = 0; + SIO_INT(); + 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(); + return; + } + + switch (mcdst) { + case 1: + SIO_INT(); + 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(); + adrH = value; + *buf = 0; + parp = 0; + bufcount = 1; + mcdst = 3; + return; + case 3: // address L + SIO_INT(); + adrL = value; + *buf = adrH; + parp = 0; + bufcount = 1; + mcdst = 4; + return; + case 4: + SIO_INT(); + 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(); + 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(); + return; + case 0x81: // start memcard + StatReg |= RX_RDY; + memcpy(buf, cardh, 4); + parp = 0; + bufcount = 3; + mcdst = 1; + rdwr = 0; + SIO_INT(); + return; + } +} + +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&=~0x80; + } +} + +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); + psxRegs.interrupt|= 0x80000000; +} + +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--; + for (j = 0; j < 126; j++) { + fputc(0x00, f); + s--; + } + fputc(0xa0, 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; + unsigned short clut[16]; + unsigned short c; + int i, x; + + memset(Info, 0, sizeof(McdBlock)); + + str = Info->Title; + + if (mcd == 1) data = Mcd1Data; + if (mcd == 2) data = Mcd2Data; + + ptr = data + block * 8192 + 2; + + Info->IconCount = *ptr & 0x3; + + ptr+= 2; + + i=0; + memcpy(Info->sTitle, ptr, 48*2); + + for (i=0; i < 48; i++) { + c = *(ptr) << 8; + c|= *(ptr+1); + if (!c) break; + + if (c >= 0x8281 && c <= 0x8298) + c = (c - 0x8281) + 'a'; + else if (c >= 0x824F && c <= 0x827A) + c = (c - 0x824F) + '0'; + else if (c == 0x8144) c = '.'; + else if (c == 0x8146) 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 { + c = ' '; + } + + str[i] = c; + ptr+=2; + } + str[i] = 0; + + ptr = data + block * 8192 + 0x60; // icon palete 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); + Info->ID[12] = 0; + ptr += 12; + strncpy(Info->Name, ptr, 16); +} + +int sioFreeze(gzFile f, int Mode) { + char Unused[4096]; + + gzfreezel(buf); + gzfreezel(&StatReg); + gzfreezel(&ModeReg); + gzfreezel(&CtrlReg); + gzfreezel(&BaudReg); + gzfreezel(&bufcount); + gzfreezel(&parp); + gzfreezel(&mcdst); + gzfreezel(&rdwr); + gzfreezel(&adrH); + gzfreezel(&adrL); + gzfreezel(&padst); + gzfreezel(Unused); + + return 0; +} diff --git a/libpcsxcore/sio.h b/libpcsxcore/sio.h new file mode 100644 index 00000000..082c5447 --- /dev/null +++ b/libpcsxcore/sio.h @@ -0,0 +1,85 @@ +/*************************************************************************** + * Copyright (C) 2007 Ryan Schultz, PCSX-df Team, PCSX team * + * schultz.ryan@gmail.com, http://rschultz.ath.cx/code.php * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You 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 Steet, Fifth Floor, Boston, MA 02111-1307 USA. * + ***************************************************************************/ + + +#ifndef _SIO_H_ +#define _SIO_H_ + +#include "psxcommon.h" +#include "r3000a.h" +#include "psxmem.h" +#include "plugins.h" +#include "psemu_plugin_defs.h" + +#define MCD_SIZE (1024 * 8 * 16) + +// Status Flags +#define TX_RDY 0x0001 +#define RX_RDY 0x0002 +#define TX_EMPTY 0x0004 +#define PARITY_ERR 0x0008 +#define RX_OVERRUN 0x0010 +#define FRAMING_ERR 0x0020 +#define SYNC_DETECT 0x0040 +#define DSR 0x0080 +#define CTS 0x0100 +#define IRQ 0x0200 + +// Control Flags +#define TX_PERM 0x0001 +#define DTR 0x0002 +#define RX_PERM 0x0004 +#define BREAK 0x0008 +#define RESET_ERR 0x0010 +#define RTS 0x0020 +#define SIO_RESET 0x0040 + +extern unsigned short StatReg; +extern unsigned short ModeReg; +extern unsigned short CtrlReg; +extern unsigned short BaudReg; + +extern char Mcd1Data[MCD_SIZE], Mcd2Data[MCD_SIZE]; + +unsigned char sioRead8(); +void sioWrite8(unsigned char value); +void sioWriteCtrl16(unsigned short value); +void sioInterrupt(); +int sioFreeze(gzFile f, int Mode); + +void LoadMcd(int mcd, char *str); +void LoadMcds(char *mcd1, char *mcd2); +void SaveMcd(char *mcd, char *data, uint32_t adr, int size); +void CreateMcd(char *mcd); +void ConvertMcd(char *mcd, char *data); + +typedef struct { + char Title[48]; + short sTitle[48]; + char ID[14]; + char Name[16]; + int IconCount; + short Icon[16*16*3]; + unsigned char Flags; +} McdBlock; + +void GetMcdBlockInfo(int mcd, int block, McdBlock *info); + +#endif diff --git a/libpcsxcore/spu.c b/libpcsxcore/spu.c new file mode 100644 index 00000000..c3ad8b67 --- /dev/null +++ b/libpcsxcore/spu.c @@ -0,0 +1,30 @@ +/*************************************************************************** + * Copyright (C) 2007 Ryan Schultz, PCSX-df Team, PCSX team * + * schultz.ryan@gmail.com, http://rschultz.ath.cx/code.php * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You 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 Steet, Fifth Floor, Boston, MA 02111-1307 USA. * + ***************************************************************************/ + +/* +* Sound (SPU) functions. +*/ + +#include "spu.h" + +void CALLBACK SPUirq(void) { + psxHu32ref(0x1070)|= SWAPu32(0x200); + psxRegs.interrupt|= 0x80000000; +} diff --git a/libpcsxcore/spu.h b/libpcsxcore/spu.h new file mode 100644 index 00000000..12a8e475 --- /dev/null +++ b/libpcsxcore/spu.h @@ -0,0 +1,45 @@ +/*************************************************************************** + * Copyright (C) 2007 Ryan Schultz, PCSX-df Team, PCSX team * + * schultz.ryan@gmail.com, http://rschultz.ath.cx/code.php * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You 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 Steet, Fifth Floor, Boston, MA 02111-1307 USA. * + ***************************************************************************/ + +#ifndef __SPU_H__ +#define __SPU_H__ + +#include "psxcommon.h" +#include "plugins.h" +#include "r3000a.h" +#include "psxmem.h" + +#ifndef _WIN32 +#define CALLBACK +#endif + +#define H_SPUirqAddr 0x0da4 +#define H_SPUaddr 0x0da6 +#define H_SPUdata 0x0da8 +#define H_SPUctrl 0x0daa +#define H_SPUstat 0x0dae +#define H_SPUon1 0x0d88 +#define H_SPUon2 0x0d8a +#define H_SPUoff1 0x0d8c +#define H_SPUoff2 0x0d8e + +void CALLBACK SPUirq(void); + +#endif /* __SPU_H__ */ diff --git a/libpcsxcore/system.h b/libpcsxcore/system.h new file mode 100644 index 00000000..124a1cd6 --- /dev/null +++ b/libpcsxcore/system.h @@ -0,0 +1,36 @@ +/*************************************************************************** + * Copyright (C) 2007 Ryan Schultz, PCSX-df Team, PCSX team * + * schultz.ryan@gmail.com, http://rschultz.ath.cx/code.php * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You 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 Steet, Fifth Floor, Boston, MA 02111-1307 USA. * + ***************************************************************************/ + +#ifndef __SYSTEM_H__ +#define __SYSTEM_H__ + +int SysInit(); // Init mem and plugins +void SysReset(); // Resets mem +void SysPrintf(char *fmt, ...); // Printf used by bios syscalls +void SysMessage(char *fmt, ...); // Message used to print msg to users +void *SysLoadLibrary(char *lib); // Loads Library +void *SysLoadSym(void *lib, char *sym); // Loads Symbol from Library +const char *SysLibError(); // Gets previous error loading sysbols +void SysCloseLibrary(void *lib); // Closes Library +void SysUpdate(); // Called on VBlank (to update i.e. pads) +void SysRunGui(); // Returns to the Gui +void SysClose(); // Close mem and plugins + +#endif /* __SYSTEM_H__ */ |
