# HG changeset patch # User William Pitcock # Date 1224186341 18000 # Node ID 70b0973e7b708a022554da80deb96a3b8e183f5b # Parent fe2ba1a712cd73da0c5172ea26a234cdadb597e2 Merge xsf plugin. diff -r fe2ba1a712cd -r 70b0973e7b70 configure.ac --- a/configure.ac Wed Oct 15 15:30:25 2008 -0500 +++ b/configure.ac Thu Oct 16 14:45:41 2008 -0500 @@ -123,7 +123,7 @@ dnl These plugins are always built. -INPUT_PLUGINS="tonegen console sexypsf psf2 cue alac metronom vtx" +INPUT_PLUGINS="tonegen console sexypsf psf2 xsf cue alac metronom vtx" OUTPUT_PLUGINS="null" EFFECT_PLUGINS="audiocompress crystalizer ladspa voice_removal sndstretch stereo_plugin echo_plugin" GENERAL_PLUGINS="song_change alarm skins" @@ -1725,6 +1725,7 @@ echo " Game music (spc, nsf & gbs): yes" echo " PlayStation audio (sexypsf): yes" echo " PlayStation2 audio (psf2): yes" +echo " Nintendo DS audio (xsf): yes [experimental]" echo " AdLib synthesizer (adplug): $have_adplug" echo " Apple Lossless Audio Codec (alac): yes" echo " WavPack 4.31+ (wavpack): $have_wavpack" diff -r fe2ba1a712cd -r 70b0973e7b70 src/xsf/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/xsf/Makefile Thu Oct 16 14:45:41 2008 -0500 @@ -0,0 +1,16 @@ +PLUGIN = xsf${PLUGIN_SUFFIX} + +SRCS = corlett.c \ + plugin.c \ + vio2sf.c \ + desmume/armcpu.c desmume/bios.c desmume/FIFO.c desmume/matrix.c desmume/MMU.c desmume/SPU.c \ + desmume/arm_instructions.c desmume/cp15.c desmume/GPU.c desmume/mc.c desmume/NDSSystem.c desmume/thumb_instructions.c \ + +include ../../buildsys.mk +include ../../extra.mk + +plugindir := ${plugindir}/${INPUT_PLUGIN_DIR} + +CFLAGS += ${PLUGIN_CFLAGS} -O0 +CPPFLAGS += ${PLUGIN_CPPFLAGS} ${MOWGLI_CFLAGS} ${GTK_CFLAGS} ${GLIB_CFLAGS} -I../.. -Ispu/ -I. +LIBS += ${GTK_LIBS} ${GLIB_LIBS} ${MOWGLI_LIBS} -lz diff -r fe2ba1a712cd -r 70b0973e7b70 src/xsf/ao.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/xsf/ao.h Thu Oct 16 14:45:41 2008 -0500 @@ -0,0 +1,175 @@ +// +// Audio Overload SDK +// +// Fake ao.h to set up the general Audio Overload style environment +// + +#include "../../config.h" + +#ifndef __AO_H +#define __AO_H + +#define AO_SUCCESS 1 +#define AO_FAIL 0 +#define AO_FAIL_DECOMPRESSION -1 + +#define MAX_DISP_INFO_LENGTH 256 +#define AUDIO_RATE (44100) + +enum +{ + COMMAND_NONE = 0, + COMMAND_PREV, + COMMAND_NEXT, + COMMAND_RESTART, + COMMAND_HAS_PREV, + COMMAND_HAS_NEXT, + COMMAND_GET_MIN, + COMMAND_GET_MAX, + COMMAND_JUMP +}; + +/* Compiler defines for Xcode */ +#ifndef WORDS_BIGENDIAN + #define LSB_FIRST 1 +#endif + +typedef unsigned char ao_bool; + +#ifdef __GNUC__ +#include // get NULL +#include + +#ifndef nil +#define nil NULL +#endif + +#ifndef TRUE +#define TRUE (1) +#endif +#ifndef FALSE +#define FALSE (0) +#endif + +#define xmalloc(a) malloc(a) + +#endif + +#ifdef _MSC_VER +#include // get NULL +#include // for off_t + +#ifndef nil +#define nil NULL +#endif + +#ifndef TRUE +#define TRUE (1) +#endif +#ifndef FALSE +#define FALSE (0) +#endif + +#define true (1) +#define false (0) + +#define xmalloc(a) malloc(a) + +#define strcasecmp _strcmpi + +#endif + +#ifndef PATH_MAX +#define PATH_MAX 2048 +#endif + +typedef unsigned char uint8; +typedef unsigned char UINT8; +typedef signed char int8; +typedef signed char INT8; +typedef unsigned short uint16; +typedef unsigned short UINT16; +typedef signed short int16; +typedef signed short INT16; +typedef signed int int32; +typedef unsigned int uint32; +#ifdef LONG_IS_64BIT +typedef signed long int64; +typedef unsigned long uint64; +#else +typedef signed long long int64; +typedef unsigned long long uint64; +#endif + +#ifdef WIN32 +#ifndef _BASETSD_H +typedef signed int INT32; +typedef unsigned int UINT32; +typedef signed long long INT64; +typedef unsigned long long UINT64; +#endif +#else +typedef signed int INT32; +typedef unsigned int UINT32; +#ifdef LONG_IS_64BIT +typedef signed long INT64; +typedef unsigned long UINT64; +#else +typedef signed long long INT64; +typedef unsigned long long UINT64; +#endif +#endif + +#ifndef INLINE +#if defined(_MSC_VER) +#define INLINE __forceinline +#elif defined(__GNUC__) +#define INLINE __inline__ +#elif defined(_MWERKS_) +#define INLINE inline +#elif defined(__powerc) +#define INLINE inline +#else +#define INLINE +#endif +#endif + +#if LSB_FIRST +#define LE16(x) (x) +#define LE32(x) (x) + +#ifndef __ENDIAN__ /* Mac OS X Endian header has this function in it */ +static unsigned long INLINE Endian32_Swap(unsigned long addr) +{ + unsigned long res = (((addr&0xff000000)>>24) | + ((addr&0x00ff0000)>>8) | + ((addr&0x0000ff00)<<8) | + ((addr&0x000000ff)<<24)); + + return res; +} +#endif + +#else + +static unsigned short INLINE LE16(unsigned short x) +{ + unsigned short res = (((x & 0xFF00) >> 8) | ((x & 0xFF) << 8)); + return res; +} + +static unsigned long INLINE LE32(unsigned long addr) +{ + unsigned long res = (((addr&0xff000000)>>24) | + ((addr&0x00ff0000)>>8) | + ((addr&0x0000ff00)<<8) | + ((addr&0x000000ff)<<24)); + + return res; +} + +#endif + +int ao_get_lib(char *filename, uint8 **buffer, uint64 *length); + +#endif // AO_H diff -r fe2ba1a712cd -r 70b0973e7b70 src/xsf/corlett.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/xsf/corlett.c Thu Oct 16 14:45:41 2008 -0500 @@ -0,0 +1,381 @@ +/* + + Audio Overload SDK + + Copyright (c) 2007-2008, R. Belmont and Richard Bannister. + + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + * Neither the names of R. Belmont and Richard Bannister nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +// corlett.c + +// Decodes file format designed by Neill Corlett (PSF, QSF, ...) + +/* + - First 3 bytes: ASCII signature: "PSF" (case sensitive) + +- Next 1 byte: Version byte + The version byte is used to determine the type of PSF file. It does NOT + affect the basic structure of the file in any way. + + Currently accepted version bytes are: + 0x01: Playstation (PSF1) + 0x02: Playstation 2 (PSF2) + 0x11: Saturn (SSF) [TENTATIVE] + 0x12: Dreamcast (DSF) [TENTATIVE] + 0x21: Nintendo 64 (USF) [RESERVED] + 0x41: Capcom QSound (QSF) + +- Next 4 bytes: Size of reserved area (R), little-endian unsigned long + +- Next 4 bytes: Compressed program length (N), little-endian unsigned long + This is the length of the program data _after_ compression. + +- Next 4 bytes: Compressed program CRC-32, little-endian unsigned long + This is the CRC-32 of the program data _after_ compression. Filling in + this value is mandatory, as a PSF file may be regarded as corrupt if it + does not match. + +- Next R bytes: Reserved area. + May be empty if R is 0 bytes. + +- Next N bytes: Compressed program, in zlib compress() format. + May be empty if N is 0 bytes. + +The following data is optional and may be omitted: + +- Next 5 bytes: ASCII signature: "[TAG]" (case sensitive) + If these 5 bytes do not match, then the remainder of the file may be + regarded as invalid and discarded. + +- Remainder of file: Uncompressed ASCII tag data. +*/ + +#include +#include +#include + +#include "ao.h" +#include "corlett.h" + +#include +#include + +#define DECOMP_MAX_SIZE ((32 * 1024 * 1024) + 12) + +int corlett_decode(uint8 *input, uint32 input_len, uint8 **output, uint64 *size, corlett_t **c) +{ + uint32 *buf; + uint32 res_area, comp_crc, actual_crc; + uint8 *decomp_dat, *tag_dec; + uLongf decomp_length, comp_length; + + // 32-bit pointer to data + buf = (uint32 *)input; + + // Check we have a PSF format file. + if ((input[0] != 'P') || (input[1] != 'S') || (input[2] != 'F')) + { + return AO_FAIL; + } + + // Get our values + res_area = LE32(buf[1]); + comp_length = LE32(buf[2]); + comp_crc = LE32(buf[3]); + + if (comp_length > 0) + { + // Check length + if (input_len < comp_length + 16) + return AO_FAIL; + + // Check CRC is correct + actual_crc = crc32(0, (unsigned char *)&buf[4+(res_area/4)], comp_length); + if (actual_crc != comp_crc) + return AO_FAIL; + + // Decompress data if any + decomp_dat = malloc(DECOMP_MAX_SIZE); + decomp_length = DECOMP_MAX_SIZE; + if (uncompress(decomp_dat, &decomp_length, (unsigned char *)&buf[4+(res_area/4)], comp_length) != Z_OK) + { + free(decomp_dat); + return AO_FAIL; + } + + // Resize memory buffer to what we actually need + decomp_dat = realloc(decomp_dat, (size_t)decomp_length + 1); + } + else + { + decomp_dat = NULL; + decomp_length = 0; + } + + // Make structure + *c = malloc(sizeof(corlett_t)); + if (!(*c)) + { + free(decomp_dat); + return AO_FAIL; + } + memset(*c, 0, sizeof(corlett_t)); + strcpy((*c)->inf_title, "n/a"); + strcpy((*c)->inf_copy, "n/a"); + strcpy((*c)->inf_artist, "n/a"); + strcpy((*c)->inf_game, "n/a"); + strcpy((*c)->inf_year, "n/a"); + strcpy((*c)->inf_length, "n/a"); + strcpy((*c)->inf_fade, "n/a"); + + // set reserved section pointer + (*c)->res_section = &buf[4]; + (*c)->res_size = res_area; + + // Return it + if (output != NULL && size != NULL) + { + *output = decomp_dat; + *size = decomp_length; + } + else + free(decomp_dat); + + // Next check for tags + input_len -= (comp_length + 16 + res_area); + if (input_len < 5) + return AO_SUCCESS; + + printf("\n\nNew corlett: input len %d comp length %d res area %d\n", input_len, comp_length, res_area); + + tag_dec = input + (comp_length + res_area + 16); + if ((tag_dec[0] == '[') && (tag_dec[1] == 'T') && (tag_dec[2] == 'A') && (tag_dec[3] == 'G') && (tag_dec[4] == ']')) + { + int tag, l, num_tags, data; + + // Tags found! + tag_dec += 5; + input_len -= 5; + + tag = 0; + data = false; + num_tags = 0; + l = 0; + while (input_len && (num_tags < MAX_UNKNOWN_TAGS)) + { + if (data) + { + if ((*tag_dec == 0xA) || (*tag_dec == 0x00)) + { + (*c)->tag_data[num_tags][l] = 0; + data = false; + num_tags++; + l = 0; + } + else + { + (*c)->tag_data[num_tags][l++] = *tag_dec; + } + } + else + { + if (*tag_dec == '=') + { + (*c)->tag_name[num_tags][l] = 0; + l = 0; + data = true; + } + else + { + (*c)->tag_name[num_tags][l++] = *tag_dec; + } + } + + tag_dec++; + input_len--; + } + + + // Now, process that tag array into what we expect + for (num_tags = 0; num_tags < MAX_UNKNOWN_TAGS; num_tags++) + { + // See if tag belongs in one of the special fields we have + if (!strcasecmp((*c)->tag_name[num_tags], "_lib")) + { + strcpy((*c)->lib, (*c)->tag_data[num_tags]); + (*c)->tag_data[num_tags][0] = 0; + (*c)->tag_name[num_tags][0] = 0; + } + else if (!strncmp((*c)->tag_name[num_tags], "_lib2", 5)) + { + strcpy((*c)->libaux[0], (*c)->tag_data[num_tags]); + (*c)->tag_data[num_tags][0] = 0; + (*c)->tag_name[num_tags][0] = 0; + } + else if (!strncmp((*c)->tag_name[num_tags], "_lib3", 5)) + { + strcpy((*c)->libaux[1], (*c)->tag_data[num_tags]); + (*c)->tag_data[num_tags][0] = 0; + (*c)->tag_name[num_tags][0] = 0; + } + else if (!strncmp((*c)->tag_name[num_tags], "_lib4", 5)) + { + strcpy((*c)->libaux[2], (*c)->tag_data[num_tags]); + (*c)->tag_data[num_tags][0] = 0; + (*c)->tag_name[num_tags][0] = 0; + } + else if (!strncmp((*c)->tag_name[num_tags], "_lib5", 5)) + { + strcpy((*c)->libaux[3], (*c)->tag_data[num_tags]); + (*c)->tag_data[num_tags][0] = 0; + (*c)->tag_name[num_tags][0] = 0; + } + else if (!strncmp((*c)->tag_name[num_tags], "_lib6", 5)) + { + strcpy((*c)->libaux[4], (*c)->tag_data[num_tags]); + (*c)->tag_data[num_tags][0] = 0; + (*c)->tag_name[num_tags][0] = 0; + } + else if (!strncmp((*c)->tag_name[num_tags], "_lib7", 5)) + { + strcpy((*c)->libaux[5], (*c)->tag_data[num_tags]); + (*c)->tag_data[num_tags][0] = 0; + (*c)->tag_name[num_tags][0] = 0; + } + else if (!strncmp((*c)->tag_name[num_tags], "_lib8", 5)) + { + strcpy((*c)->libaux[6], (*c)->tag_data[num_tags]); + (*c)->tag_data[num_tags][0] = 0; + (*c)->tag_name[num_tags][0] = 0; + } + else if (!strncmp((*c)->tag_name[num_tags], "_lib9", 5)) + { + strcpy((*c)->libaux[7], (*c)->tag_data[num_tags]); + (*c)->tag_data[num_tags][0] = 0; + (*c)->tag_name[num_tags][0] = 0; + } + else if (!strncmp((*c)->tag_name[num_tags], "_refresh", 8)) + { + strcpy((*c)->inf_refresh, (*c)->tag_data[num_tags]); + (*c)->tag_data[num_tags][0] = 0; + (*c)->tag_name[num_tags][0] = 0; + } + else if (!strncmp((*c)->tag_name[num_tags], "title", 5)) + { + strcpy((*c)->inf_title, (*c)->tag_data[num_tags]); + (*c)->tag_data[num_tags][0] = 0; + (*c)->tag_name[num_tags][0] = 0; + } + else if (!strncmp((*c)->tag_name[num_tags], "copyright", 9)) + { + strcpy((*c)->inf_copy, (*c)->tag_data[num_tags]); + (*c)->tag_data[num_tags][0] = 0; + (*c)->tag_name[num_tags][0] = 0; + } + else if (!strncmp((*c)->tag_name[num_tags], "artist", 6)) + { + strcpy((*c)->inf_artist, (*c)->tag_data[num_tags]); + (*c)->tag_data[num_tags][0] = 0; + (*c)->tag_name[num_tags][0] = 0; + } + else if (!strncmp((*c)->tag_name[num_tags], "game", 4)) + { + strcpy((*c)->inf_game, (*c)->tag_data[num_tags]); + (*c)->tag_data[num_tags][0] = 0; + (*c)->tag_name[num_tags][0] = 0; + } + else if (!strncmp((*c)->tag_name[num_tags], "year", 4)) + { + strcpy((*c)->inf_year, (*c)->tag_data[num_tags]); + (*c)->tag_data[num_tags][0] = 0; + (*c)->tag_name[num_tags][0] = 0; + } + else if (!strncmp((*c)->tag_name[num_tags], "length", 6)) + { + strcpy((*c)->inf_length, (*c)->tag_data[num_tags]); + (*c)->tag_data[num_tags][0] = 0; + (*c)->tag_name[num_tags][0] = 0; + } + else if (!strncmp((*c)->tag_name[num_tags], "fade", 4)) + { + strcpy((*c)->inf_fade, (*c)->tag_data[num_tags]); + (*c)->tag_data[num_tags][0] = 0; + (*c)->tag_name[num_tags][0] = 0; + } + } + } + + // Bingo + return AO_SUCCESS; +} + +uint32 psfTimeToMS(char *str) +{ + int x, c=0; + uint32 acc=0; + char s[100]; + + strncpy(s,str,100); + s[99]=0; + + for (x=strlen(s); x>=0; x--) + { + if (s[x]=='.' || s[x]==',') + { + acc=atoi(s+x+1); + s[x]=0; + } + else if (s[x]==':') + { + if(c==0) + { + acc+=atoi(s+x+1)*10; + } + else if(c==1) + { + acc+=atoi(s+x+(x?1:0))*10*60; + } + + c++; + s[x]=0; + } + else if (x==0) + { + if(c==0) + { + acc+=atoi(s+x)*10; + } + else if(c==1) + { + acc+=atoi(s+x)*10*60; + } + else if(c==2) + { + acc+=atoi(s+x)*10*60*60; + } + } + } + + acc*=100; + return(acc); +} + diff -r fe2ba1a712cd -r 70b0973e7b70 src/xsf/corlett.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/xsf/corlett.h Thu Oct 16 14:45:41 2008 -0500 @@ -0,0 +1,35 @@ +// +// Audio Overload +// Emulated music player +// +// (C) 2000-2008 Richard F. Bannister +// + +// corlett.h + +#define MAX_UNKNOWN_TAGS 32 + +typedef struct { + char lib[256]; + char libaux[8][256]; + + char inf_title[256]; + char inf_copy[256]; + char inf_artist[256]; + char inf_game[256]; + char inf_year[256]; + char inf_length[256]; + char inf_fade[256]; + + char inf_refresh[256]; + + char tag_name[MAX_UNKNOWN_TAGS][256]; + char tag_data[MAX_UNKNOWN_TAGS][256]; + + uint32 *res_section; + uint32 res_size; +} corlett_t; + +int corlett_decode(uint8 *input, uint32 input_len, uint8 **output, uint64 *size, corlett_t **c); +uint32 psfTimeToMS(char *str); + diff -r fe2ba1a712cd -r 70b0973e7b70 src/xsf/desmume/ARM9.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/xsf/desmume/ARM9.h Thu Oct 16 14:45:41 2008 -0500 @@ -0,0 +1,33 @@ +#ifndef ARM9_H +#define ARM9_H + +#include "types.h" + +typedef struct { + //ARM9 mem + u8 ARM9_ITCM[0x8000]; + u8 ARM9_DTCM[0x4000]; + u8 ARM9_WRAM[0x1000000]; + u8 MAIN_MEM[0x400000]; + u8 ARM9_REG[0x1000000]; + u8 ARM9_BIOS[0x8000]; + u8 ARM9_VMEM[0x800]; + u8 ARM9_ABG[0x80000]; + u8 ARM9_BBG[0x20000]; + u8 ARM9_AOBJ[0x40000]; + u8 ARM9_BOBJ[0x20000]; + u8 ARM9_LCD[0xA4000]; + u8 ARM9_OAM[0x800]; + + u8 * ExtPal[2][4]; + u8 * ObjExtPal[2][2]; + u8 * texPalSlot[4]; + + const u8 *textureSlotAddr[4]; + + u8 *blank_memory[0x20000]; +} ARM9_struct; + +extern ARM9_struct ARM9Mem; + +#endif diff -r fe2ba1a712cd -r 70b0973e7b70 src/xsf/desmume/COPYING --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/xsf/desmume/COPYING Thu Oct 16 14:45:41 2008 -0500 @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff -r fe2ba1a712cd -r 70b0973e7b70 src/xsf/desmume/FIFO.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/xsf/desmume/FIFO.c Thu Oct 16 14:45:41 2008 -0500 @@ -0,0 +1,65 @@ +/* Copyright (C) 2006 yopyop + yopyop156@ifrance.com + yopyop156.ifrance.com + + Copyright (C) 2007 shash + + This file is part of DeSmuME + + DeSmuME is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DeSmuME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DeSmuME; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "FIFO.h" + +void FIFOInit(FIFO * fifo) +{ + u32 i; + + fifo->begin = 0; + fifo->end = 0; + for(i = 0; i<0x8000; ++i) + fifo->data[i] = 0; + fifo->full = FALSE; + fifo->empty = TRUE; + fifo->error = FALSE; +} + +void FIFOAdd(FIFO * fifo, u32 v) +{ + if(fifo->full) + { + fifo->error = TRUE; + return; + } + fifo->data[fifo->end] = v; + fifo->end = (fifo->end + 1)& 0x7FFF; + fifo->full = (fifo->end == fifo->begin); + fifo->empty = FALSE; +} + +u32 FIFOValue(FIFO * fifo) +{ + u32 v; + + if(fifo->empty) + { + fifo->error = TRUE; + return 0; + } + v = fifo->data[fifo->begin]; + fifo->begin = (fifo->begin + 1)& 0x7FFF; + fifo->empty = (fifo->begin == fifo->end); + return v; +} diff -r fe2ba1a712cd -r 70b0973e7b70 src/xsf/desmume/FIFO.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/xsf/desmume/FIFO.h Thu Oct 16 14:45:41 2008 -0500 @@ -0,0 +1,51 @@ +/* Copyright (C) 2006 yopyop + yopyop156@ifrance.com + yopyop156.ifrance.com + + Copyright (C) 2007 shash + + This file is part of DeSmuME + + DeSmuME is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DeSmuME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DeSmuME; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef FIFO_H +#define FIFO_H + +#include "types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct +{ + u32 data[0x8000]; + u32 begin; + u32 end; + BOOL full; + BOOL empty; + BOOL error; +} FIFO; + +void FIFOInit(FIFO * fifo); +void FIFOAdd(FIFO * fifo, u32 v); +u32 FIFOValue(FIFO * fifo); + +#ifdef __cplusplus +} +#endif + +#endif diff -r fe2ba1a712cd -r 70b0973e7b70 src/xsf/desmume/GPU.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/xsf/desmume/GPU.c Thu Oct 16 14:45:41 2008 -0500 @@ -0,0 +1,98 @@ +/* Copyright (C) 2006 yopyop + yopyop156@ifrance.com + yopyop156.ifrance.com + + Copyright (C) 2006-2007 Theo Berkau + Copyright (C) 2007 shash + + This file is part of DeSmuME + + DeSmuME is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DeSmuME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DeSmuME; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +// CONTENTS +// INITIALIZATION +// ENABLING / DISABLING LAYERS +// PARAMETERS OF BACKGROUNDS +// PARAMETERS OF ROTOSCALE +// PARAMETERS OF EFFECTS +// PARAMETERS OF WINDOWS +// ROUTINES FOR INSIDE / OUTSIDE WINDOW CHECKS +// PIXEL RENDERING +// BACKGROUND RENDERING -TEXT- +// BACKGROUND RENDERING -ROTOSCALE- +// BACKGROUND RENDERING -HELPER FUNCTIONS- +// SPRITE RENDERING -HELPER FUNCTIONS- +// SPRITE RENDERING +// SCREEN FUNCTIONS +// GRAPHICS CORE +// GPU_ligne + +#include +#include +#include +#include "MMU.h" +#include "GPU.h" + +ARM9_struct ARM9Mem; + +NDS_Screen MainScreen; +NDS_Screen SubScreen; + +//#define DEBUG_TRI + +/*****************************************************************************/ +// INITIALIZATION +/*****************************************************************************/ + +GPU * GPU_Init(u8 l) +{ + GPU * g; + + if ((g = (GPU *) malloc(sizeof(GPU))) == NULL) + return NULL; + + GPU_Reset(g, l); + return g; +} + +void GPU_Reset(GPU *g, u8 l) +{ + memset(g, 0, sizeof(GPU)); +} + +void GPU_DeInit(GPU * gpu) +{ + if (gpu) free(gpu); +} + + +int Screen_Init(int coreid) { + MainScreen.gpu = GPU_Init(0); + SubScreen.gpu = GPU_Init(1); + + return 0; +} + +void Screen_Reset(void) { + GPU_Reset(MainScreen.gpu, 0); + GPU_Reset(SubScreen.gpu, 1); +} + +void Screen_DeInit(void) { + GPU_DeInit(MainScreen.gpu); + GPU_DeInit(SubScreen.gpu); + +} diff -r fe2ba1a712cd -r 70b0973e7b70 src/xsf/desmume/GPU.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/xsf/desmume/GPU.h Thu Oct 16 14:45:41 2008 -0500 @@ -0,0 +1,813 @@ +/* Copyright (C) 2006 yopyop + yopyop156@ifrance.com + yopyop156.ifrance.com + + Copyright (C) 2006-2007 Theo Berkau + Copyright (C) 2007 shash + + This file is part of DeSmuME + + DeSmuME is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DeSmuME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DeSmuME; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef GPU_H +#define GPU_H + +#include "ARM9.h" +#include +#include "mem.h" +#include "registers.h" +#include "FIFO.h" +#include "MMU.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/******************************************************************************* + this structure is for display control, + it holds flags for general display +*******************************************************************************/ + +#ifdef WORDS_BIGENDIAN +struct _DISPCNT +{ +/* 7*/ u8 ForceBlank:1; // A+B: +/* 6*/ u8 OBJ_BMP_mapping:1; // A+B: 0=2D (128KB), 1=1D (128..256KB) +/* 5*/ u8 OBJ_BMP_2D_dim:1; // A+B: 0=128x512, 1=256x256 pixels +/* 4*/ u8 OBJ_Tile_1D:1; // A+B: 0=2D (32KB), 1=1D (32..256KB) +/* 3*/ u8 BG0_3D:1; // A : 0=2D, 1=3D +/* 0*/ u8 BG_Mode:3; // A+B: +/*15*/ u8 WinOBJ_Enable:1; // A+B: 0=disable, 1=Enable +/*14*/ u8 Win1_Enable:1; // A+B: 0=disable, 1=Enable +/*13*/ u8 Win0_Enable:1; // A+B: 0=disable, 1=Enable +/*12*/ u8 OBJ_Enable:1; // A+B: 0=disable, 1=Enable +/*11*/ u8 BG3_Enable:1; // A+B: 0=disable, 1=Enable +/*10*/ u8 BG2_Enable:1; // A+B: 0=disable, 1=Enable +/* 9*/ u8 BG1_Enable:1; // A+B: 0=disable, 1=Enable +/* 8*/ u8 BG0_Enable:1; // A+B: 0=disable, 1=Enable +/*23*/ u8 OBJ_HBlank_process:1; // A+B: OBJ processed during HBlank (GBA bit5) +/*22*/ u8 OBJ_BMP_1D_Bound:1; // A : +/*20*/ u8 OBJ_Tile_1D_Bound:2; // A+B: +/*18*/ u8 VRAM_Block:2; // A : VRAM block (0..3=A..D) + +/*16*/ u8 DisplayMode:2; // A+B: coreA(0..3) coreB(0..1) GBA(Green Swap) + // 0=off (white screen) + // 1=on (normal BG & OBJ layers) + // 2=VRAM display (coreA only) + // 3=RAM display (coreA only, DMA transfers) + +/*31*/ u8 ExOBJPalette_Enable:1; // A+B: 0=disable, 1=Enable OBJ extended Palette +/*30*/ u8 ExBGxPalette_Enable:1; // A+B: 0=disable, 1=Enable BG extended Palette +/*27*/ u8 ScreenBase_Block:3; // A : Screen Base (64K step) +/*24*/ u8 CharacBase_Block:3; // A : Character Base (64K step) +}; +#else +struct _DISPCNT +{ +/* 0*/ u8 BG_Mode:3; // A+B: +/* 3*/ u8 BG0_3D:1; // A : 0=2D, 1=3D +/* 4*/ u8 OBJ_Tile_1D:1; // A+B: 0=2D (32KB), 1=1D (32..256KB) +/* 5*/ u8 OBJ_BMP_2D_dim:1; // A+B: 0=128x512, 1=256x256 pixels +/* 6*/ u8 OBJ_BMP_mapping:1; // A+B: 0=2D (128KB), 1=1D (128..256KB) + + // 7-15 same as GBA +/* 7*/ u8 ForceBlank:1; // A+B: +/* 8*/ u8 BG0_Enable:1; // A+B: 0=disable, 1=Enable +/* 9*/ u8 BG1_Enable:1; // A+B: 0=disable, 1=Enable +/*10*/ u8 BG2_Enable:1; // A+B: 0=disable, 1=Enable +/*11*/ u8 BG3_Enable:1; // A+B: 0=disable, 1=Enable +/*12*/ u8 OBJ_Enable:1; // A+B: 0=disable, 1=Enable +/*13*/ u8 Win0_Enable:1; // A+B: 0=disable, 1=Enable +/*14*/ u8 Win1_Enable:1; // A+B: 0=disable, 1=Enable +/*15*/ u8 WinOBJ_Enable:1; // A+B: 0=disable, 1=Enable + +/*16*/ u8 DisplayMode:2; // A+B: coreA(0..3) coreB(0..1) GBA(Green Swap) + // 0=off (white screen) + // 1=on (normal BG & OBJ layers) + // 2=VRAM display (coreA only) + // 3=RAM display (coreA only, DMA transfers) + +/*18*/ u8 VRAM_Block:2; // A : VRAM block (0..3=A..D) +/*20*/ u8 OBJ_Tile_1D_Bound:2; // A+B: +/*22*/ u8 OBJ_BMP_1D_Bound:1; // A : +/*23*/ u8 OBJ_HBlank_process:1; // A+B: OBJ processed during HBlank (GBA bit5) +/*24*/ u8 CharacBase_Block:3; // A : Character Base (64K step) +/*27*/ u8 ScreenBase_Block:3; // A : Screen Base (64K step) +/*30*/ u8 ExBGxPalette_Enable:1; // A+B: 0=disable, 1=Enable BG extended Palette +/*31*/ u8 ExOBJPalette_Enable:1; // A+B: 0=disable, 1=Enable OBJ extended Palette +}; +#endif + +typedef union +{ + struct _DISPCNT bits; + u32 val; +} DISPCNT; +#define BGxENABLED(cnt,num) ((num<8)? ((cnt.val>>8) & num):0) + + + + +/******************************************************************************* + this structure is for display control of a specific layer, + there are 4 background layers + their priority indicate which one to draw on top of the other + some flags indicate special drawing mode, size, FX +*******************************************************************************/ + +#ifdef WORDS_BIGENDIAN +struct _BGxCNT +{ +/* 7*/ u8 Palette_256:1; // 0=16x16, 1=1*256 palette +/* 6*/ u8 Mosaic_Enable:1; // 0=disable, 1=Enable mosaic +/* 2*/ u8 CharacBase_Block:4; // individual character base offset (n*16KB) +/* 0*/ u8 Priority:2; // 0..3=high..low +/*14*/ u8 ScreenSize:2; // text : 256x256 512x256 256x512 512x512 + // x/rot/s : 128x128 256x256 512x512 1024x1024 + // bmp : 128x128 256x256 512x256 512x512 + // large : 512x1024 1024x512 - - +/*13*/ u8 PaletteSet_Wrap:1; // BG0 extended palette set 0=set0, 1=set2 + // BG1 extended palette set 0=set1, 1=set3 + // BG2 overflow area wraparound 0=off, 1=wrap + // BG3 overflow area wraparound 0=off, 1=wrap +/* 8*/ u8 ScreenBase_Block:5; // individual screen base offset (text n*2KB, BMP n*16KB) +}; +#else +struct _BGxCNT +{ +/* 0*/ u8 Priority:2; // 0..3=high..low +/* 2*/ u8 CharacBase_Block:4; // individual character base offset (n*16KB) +/* 6*/ u8 Mosaic_Enable:1; // 0=disable, 1=Enable mosaic +/* 7*/ u8 Palette_256:1; // 0=16x16, 1=1*256 palette +/* 8*/ u8 ScreenBase_Block:5; // individual screen base offset (text n*2KB, BMP n*16KB) +/*13*/ u8 PaletteSet_Wrap:1; // BG0 extended palette set 0=set0, 1=set2 + // BG1 extended palette set 0=set1, 1=set3 + // BG2 overflow area wraparound 0=off, 1=wrap + // BG3 overflow area wraparound 0=off, 1=wrap +/*14*/ u8 ScreenSize:2; // text : 256x256 512x256 256x512 512x512 + // x/rot/s : 128x128 256x256 512x512 1024x1024 + // bmp : 128x128 256x256 512x256 512x512 + // large : 512x1024 1024x512 - - +}; +#endif + + +typedef union +{ + struct _BGxCNT bits; + u16 val; +} BGxCNT; + +/******************************************************************************* + this structure is for background offset +*******************************************************************************/ + +typedef struct { + u16 BGxHOFS; + u16 BGxVOFS; +} BGxOFS; + +/******************************************************************************* + this structure is for rotoscale parameters +*******************************************************************************/ + +typedef struct { + s16 BGxPA; + s16 BGxPB; + s16 BGxPC; + s16 BGxPD; + s32 BGxX; + s32 BGxY; +} BGxPARMS; + + +/******************************************************************************* + these structures are for window description, + windows are square regions and can "subclass" + background layers or object layers (i.e window controls the layers) + + screen + | + +-- Window0/Window1/OBJwindow/OutOfWindows + | + +-- BG0/BG1/BG2/BG3/OBJ +*******************************************************************************/ + +typedef union { + struct { + u8 end:8; + u8 start:8; + } bits ; + u16 val; +} WINxDIM; + +#ifdef WORDS_BIGENDIAN +typedef struct { +/* 6*/ u8 :2; +/* 5*/ u8 WINx_Effect_Enable:1; +/* 4*/ u8 WINx_OBJ_Enable:1; +/* 3*/ u8 WINx_BG3_Enable:1; +/* 2*/ u8 WINx_BG2_Enable:1; +/* 1*/ u8 WINx_BG1_Enable:1; +/* 0*/ u8 WINx_BG0_Enable:1; +} WINxBIT; +#else +typedef struct { +/* 0*/ u8 WINx_BG0_Enable:1; +/* 1*/ u8 WINx_BG1_Enable:1; +/* 2*/ u8 WINx_BG2_Enable:1; +/* 3*/ u8 WINx_BG3_Enable:1; +/* 4*/ u8 WINx_OBJ_Enable:1; +/* 5*/ u8 WINx_Effect_Enable:1; +/* 6*/ u8 :2; +} WINxBIT; +#endif + +#ifdef WORDS_BIGENDIAN +typedef union { + struct { + WINxBIT win0; + WINxBIT win1; + } bits; + struct { + u8 :3; + u8 win0_en:5; + u8 :3; + u8 win1_en:5; + } packed_bits; + struct { + u8 low; + u8 high; + } bytes; + u16 val ; +} WINxCNT ; +#else +typedef union { + struct { + WINxBIT win0; + WINxBIT win1; + } bits; + struct { + u8 win0_en:5; + u8 :3; + u8 win1_en:5; + u8 :3; + } packed_bits; + struct { + u8 low; + u8 high; + } bytes; + u16 val ; +} WINxCNT ; +#endif + +/* +typedef struct { + WINxDIM WIN0H; + WINxDIM WIN1H; + WINxDIM WIN0V; + WINxDIM WIN1V; + WINxCNT WININ; + WINxCNT WINOUT; +} WINCNT; +*/ + +/******************************************************************************* + this structure is for miscellanous settings + //TODO: needs further description +*******************************************************************************/ + +typedef struct { + u16 MOSAIC; + u16 unused1; + u16 unused2;//BLDCNT; + u16 unused3;//BLDALPHA; + u16 unused4;//BLDY; + u16 unused5; + /* + u16 unused6; + u16 unused7; + u16 unused8; + u16 unused9; + */ +} MISCCNT; + + +/******************************************************************************* + this structure is for 3D settings +*******************************************************************************/ + +struct _DISP3DCNT +{ +/* 0*/ u8 EnableTexMapping:1; // +/* 1*/ u8 PolygonShading:1; // 0=Toon Shading, 1=Highlight Shading +/* 2*/ u8 EnableAlphaTest:1; // see ALPHA_TEST_REF +/* 3*/ u8 EnableAlphaBlending:1; // see various Alpha values +/* 4*/ u8 EnableAntiAliasing:1; // +/* 5*/ u8 EnableEdgeMarking:1; // see EDGE_COLOR +/* 6*/ u8 FogOnlyAlpha:1; // 0=Alpha and Color, 1=Only Alpha (see FOG_COLOR) +/* 7*/ u8 EnableFog:1; // Fog Master Enable +/* 8*/ u8 FogShiftSHR:4; // 0..10 SHR-Divider (see FOG_OFFSET) +/*12*/ u8 AckColorBufferUnderflow:1; // Color Buffer RDLINES Underflow (0=None, 1=Underflow/Acknowledge) +/*13*/ u8 AckVertexRAMOverflow:1; // Polygon/Vertex RAM Overflow (0=None, 1=Overflow/Acknowledge) +/*14*/ u8 RearPlaneMode:1; // 0=Blank, 1=Bitmap +/*15*/ u8 :1; +/*16*/ u16 :16; +}; + +typedef union +{ + struct _DISP3DCNT bits; + u32 val; +} DISP3DCNT; + +/******************************************************************************* + this structure is for capture control (core A only) + + source: + http://nocash.emubase.de/gbatek.htm#dsvideocaptureandmainmemorydisplaymode +*******************************************************************************/ + +struct _DISPCAPCNT +{ +/* 0*/ u8 BlendFactor_A:5; // 0..16 = Blending Factor for Source A +/* 5*/ u8 :3; // +/* 8*/ u8 BlendFactor_B:5; // 0..16 = Blending Factor for Source B +/*13*/ u8 :3; // +/*16*/ u8 VRAM_Write_Block:2; // 0..3 = VRAM A..D +/*18*/ u8 VRAM_Write_Offset:2; // n x 0x08000 +/*20*/ u8 Capture_Size:2; // 0=128x128, 1=256x64, 2=256x128, 3=256x192 dots +/*22*/ u8 :2; // +/*24*/ u8 Source_A:1; // 0=Graphics Screen BG+3D+OBJ, 1=3D Screen +/*25*/ u8 Source_B:1; // 0=VRAM, 1=Main Memory Display FIFO +/*26*/ u8 VRAM_Read_Offset:2; // n x 0x08000 +/*28*/ u8 :1; // +/*29*/ u8 Capture_Source:2; // 0=Source A, 1=Source B, 2/3=Sources A+B blended +/*31*/ u8 Capture_Enable:1; // 0=Disable/Ready, 1=Enable/Busy +}; + +typedef union +{ + struct _DISPCAPCNT bits; + u32 val; +} DISPCAPCNT; + + +/******************************************************************************* + this structure holds everything and should be mapped to + * core A : 0x04000000 + * core B : 0x04001000 +*******************************************************************************/ + +typedef struct _reg_dispx { + DISPCNT dispx_DISPCNT; // 0x0400x000 + u16 dispA_DISPSTAT; // 0x04000004 + u16 dispx_VCOUNT; // 0x0400x006 + BGxCNT dispx_BGxCNT[4]; // 0x0400x008 + BGxOFS dispx_BGxOFS[4]; // 0x0400x010 + BGxPARMS dispx_BG2PARMS; // 0x0400x020 + BGxPARMS dispx_BG3PARMS; // 0x0400x030 + u8 filler[12]; // 0x0400x040 + MISCCNT dispx_MISC; // 0x0400x04C + DISP3DCNT dispA_DISP3DCNT; // 0x04000060 + DISPCAPCNT dispA_DISPCAPCNT; // 0x04000064 + u32 dispA_DISPMMEMFIFO; // 0x04000068 +} REG_DISPx ; + + + + + + + + +#ifndef min +#define min(a,b) (((a)<(b))?(a):(b)) +#endif + +#ifndef max +#define max(a,b) (((a)>(b))?(a):(b)) +#endif + +typedef BOOL (*fun_gl_Begin) (int screen); +typedef void (*fun_gl_End) (int screen); +// the GUI should use this function prior to all gl calls +// if call to beg succeeds opengl draw +void register_gl_fun(fun_gl_Begin beg,fun_gl_End end); + +#define GPU_MAIN 0 +#define GPU_SUB 1 + +/* human readable bitmask names */ +#define ADDRESS_STEP_512B 0x00200 +#define ADDRESS_STEP_1KB 0x00400 +#define ADDRESS_STEP_2KB 0x00800 +#define ADDRESS_STEP_4KB 0x01000 +#define ADDRESS_STEP_8KB 0x02000 +#define ADDRESS_STEP_16KB 0x04000 +#define ADDRESS_STEP_32KB 0x08000 +#define ADDRESS_STEP_64kB 0x10000 + +#ifdef WORDS_BIGENDIAN +struct _TILEENTRY +{ +/*14*/ unsigned Palette:4; +/*13*/ unsigned VFlip:1; // VERTICAL FLIP (top<-->bottom) +/*12*/ unsigned HFlip:1; // HORIZONTAL FLIP (left<-->right) +/* 0*/ unsigned TileNum:10; +}; +#else +struct _TILEENTRY +{ +/* 0*/ unsigned TileNum:10; +/*12*/ unsigned HFlip:1; // HORIZONTAL FLIP (left<-->right) +/*13*/ unsigned VFlip:1; // VERTICAL FLIP (top<-->bottom) +/*14*/ unsigned Palette:4; +}; +#endif +typedef union +{ + struct _TILEENTRY bits; + u16 val; +} TILEENTRY; + +struct _ROTOCOORD +{ +/* 0*/ unsigned Fraction:8; +/* 8*/ signed Integer:24; +// /*28*/ unsigned :4; +}; +typedef union +{ + struct _ROTOCOORD bits; + s32 val; +} ROTOCOORD; + + +/* + this structure is for color representation, + it holds 5 meaningful bits per color channel (red,green,blue) + and 1 meaningful bit for alpha representation + this bit can be unused or used for special FX +*/ + +struct _COLOR { // abgr x555 +#ifdef WORDS_BIGENDIAN + unsigned alpha:1; // sometimes it is unused (pad) + unsigned blue:5; + unsigned green:5; + unsigned red:5; +#else + unsigned red:5; + unsigned green:5; + unsigned blue:5; + unsigned alpha:1; // sometimes it is unused (pad) +#endif +}; +struct _COLORx { // abgr x555 + unsigned bgr:15; + unsigned alpha:1; // sometimes it is unused (pad) +}; + +typedef union +{ + struct _COLOR bits; + struct _COLORx bitx; + u16 val; +} COLOR; + +struct _COLOR32 { // ARGB + unsigned :3; + unsigned blue:5; + unsigned :3; + unsigned green:5; + unsigned :3; + unsigned red:5; + unsigned :7; + unsigned alpha:1; // sometimes it is unused (pad) +}; + +typedef union +{ + struct _COLOR32 bits; + u32 val; +} COLOR32; + +#define COLOR_16_32(w,i) \ + /* doesnt matter who's 16bit who's 32bit */ \ + i.bits.red = w.bits.red; \ + i.bits.green = w.bits.green; \ + i.bits.blue = w.bits.blue; \ + i.bits.alpha = w.bits.alpha; + + + + + + +/* + this structure is for Sprite description, + it holds flags & transformations for 1 sprite + (max 128 OBJs / screen) +ref: http://www.bottledlight.com/ds/index.php/Video/Sprites +*/ + +typedef struct +{ +#ifdef WORDS_BIGENDIAN +// attr0 +/* 0*/ unsigned Y:8; +/*14*/ unsigned Shape:2; // (00: Square, 01: Wide, 10: Tall, 11: Illegal) +/*13*/ unsigned Depth:1; // (0: 16, 1: 256) +/*12*/ unsigned Mosaic:1; // (1: Enabled) +/*10*/ unsigned Mode:2; // (00: Normal, 01: Transparent, 10: Object window, 11: Bitmap) +/* 8*/ unsigned RotScale:2; // (00: Normal, 01: Rot/scale, 10: Disabled, 11: Double-size rot/scale) +// attr1 +/* 0*/ signed X:9; +/*14*/ unsigned Size:2; +/*13*/ unsigned VFlip:1; +/*12*/ unsigned HFlip:1; +/* 9*/ unsigned RotScalIndex:3; // Rot/scale matrix index +// attr2 +/* 0*/ unsigned TileIndex:10; +/*12*/ unsigned PaletteIndex:4; +/*10*/ unsigned Priority:2; +// attr3 +unsigned attr3:16; +#else +// attr0 +/* 0*/ unsigned Y:8; +/* 8*/ unsigned RotScale:2; // (00: Normal, 01: Rot/scale, 10: Disabled, 11: Double-size rot/scale) +/*10*/ unsigned Mode:2; // (00: Normal, 01: Transparent, 10: Object window, 11: Bitmap) +/*12*/ unsigned Mosaic:1; // (1: Enabled) +/*13*/ unsigned Depth:1; // (0: 16, 1: 256) +/*14*/ unsigned Shape:2; // (00: Square, 01: Wide, 10: Tall, 11: Illegal) +// attr1 +/* 0*/ signed X:9; +/* 9*/ unsigned RotScalIndex:3; // Rot/scale matrix index +/*12*/ unsigned HFlip:1; +/*13*/ unsigned VFlip:1; +/*14*/ unsigned Size:2; +// attr2 +/* 0*/ unsigned TileIndex:10; +/*10*/ unsigned Priority:2; +/*12*/ unsigned PaletteIndex:4; +// attr3 + unsigned attr3:16; +#endif +} _OAM_; + +typedef struct +{ + u16 attr0; + u16 attr1; + u16 attr2; + u16 attr3; +} OAM; + + + +typedef struct +{ + s16 x; + s16 y; +} size; + + + + +/* + this structure holds information + for rendering. +*/ + +#define NB_PRIORITIES 4 +#define NB_BG 4 +typedef struct +{ + u8 BGs[NB_BG], nbBGs; + u8 PixelsX[256]; + // doh ! yoda says : 256 pixels we can have... + u16 nbPixelsX; +} itemsForPriority_t; + + +typedef struct _GPU GPU; + +struct _GPU +{ + // some structs are becoming redundant + // some functions too (no need to recopy some vars as it is done by MMU) + REG_DISPx * dispx_st; + + DISPCAPCNT dispCapCnt; + BOOL LayersEnable[5]; + itemsForPriority_t itemsForPriority[NB_PRIORITIES]; + u8 sprWin[256][256]; + +#define BGBmpBB BG_bmp_ram +#define BGChBB BG_tile_ram + + u8 *(BG_bmp_ram[4]); + u8 *(BG_tile_ram[4]); + u8 *(BG_map_ram[4]); + + u8 BGExtPalSlot[4]; + u32 BGSize[4][2]; + + u8 lcd; + u8 core; + + u8 dispMode; + u8 vramBlock; + + BOOL dispBG[4]; + BOOL dispOBJ; + + OAM * oam; + u8 * sprMem; + u8 sprBoundary; + u8 sprBMPBoundary; + u8 sprBMPMode; + u32 sprEnable; + + u8 WIN0H0; + u8 WIN0H1; + u8 WIN0V0; + u8 WIN0V1; + + u8 WIN1H0; + u8 WIN1H1; + u8 WIN1V0; + u8 WIN1V1; + + u8 WININ0; + u8 WININ0_SPECIAL; + u8 WININ1; + u8 WININ1_SPECIAL; + + u8 WINOUT; + u8 WINOUT_SPECIAL; + u8 WINOBJ; + u8 WINOBJ_SPECIAL; + + u8 WIN0_ENABLED; + u8 WIN1_ENABLED; + u8 WINOBJ_ENABLED; + + u16 BLDCNT; + u8 BLDALPHA_EVA; + u8 BLDALPHA_EVB; + u8 BLDY_EVY; + + u8 MasterBrightMode; + u32 MasterBrightFactor; + + BOOL (*setFinalColorSpr)(const GPU *gpu, u32 passing, u8 bgnum, u8 *dst, u16 color, u16 x, u16 y); + BOOL (*setFinalColorBck)(const GPU *gpu, u32 passing, u8 bgnum, u8 *dst, u16 color, u16 x, u16 y); + void (*spriteRender) (GPU * gpu, u16 l, u8 * dst, u8 * prioTab); +}; +/* +// normally should have same addresses +static void REG_DISPx_pack_test(GPU * gpu) +{ + REG_DISPx * r = gpu->dispx_st; + printf ("%08x %02x\n", r, (long)(&r->dispx_DISPCNT) - (long)r); + printf ("\t%02x\n", (long)(&r->dispA_DISPSTAT) - (long)r); + printf ("\t%02x\n", (long)(&r->dispx_VCOUNT) - (long)r); + printf ("\t%02x\n", (long)(&r->dispx_BGxCNT[0]) - (long)r); + printf ("\t%02x\n", (long)(&r->dispx_BGxOFS[0]) - (long)r); + printf ("\t%02x\n", (long)(&r->dispx_BG2PARMS) - (long)r); + printf ("\t%02x\n", (long)(&r->dispx_BG3PARMS) - (long)r); + printf ("\t%02x\n", (long)(&r->dispx_WINCNT) - (long)r); + printf ("\t%02x\n", (long)(&r->dispx_MISC) - (long)r); + printf ("\t%02x\n", (long)(&r->dispA_DISP3DCNT) - (long)r); + printf ("\t%02x\n", (long)(&r->dispA_DISPCAPCNT) - (long)r); + printf ("\t%02x\n", (long)(&r->dispA_DISPMMEMFIFO) - (long)r); +} +*/ + +extern u8 GPU_screen[4*256*192]; + + +GPU * GPU_Init(u8 l); +void GPU_Reset(GPU *g, u8 l); +void GPU_DeInit(GPU *); + +void textBG(const GPU * gpu, u8 num, u8 * DST); //Draw text based background +void rotBG(GPU * gpu, u8 num, u8 * DST); +void extRotBG(GPU * gpu, u8 num, u8 * DST); +void sprite1D(GPU * gpu, u16 l, u8 * dst, u8 * prioTab); +void sprite2D(GPU * gpu, u16 l, u8 * dst, u8 * prioTab); + +extern short sizeTab[4][4][2]; +extern size sprSizeTab[4][4]; +extern s8 mode2type[8][4]; +extern void (*modeRender[8][4])(GPU * gpu, u8 num, u16 l, u8 * DST); + +typedef struct { + GPU * gpu; + u16 offset; +} NDS_Screen; + +extern NDS_Screen MainScreen; +extern NDS_Screen SubScreen; + +int Screen_Init(int coreid); +void Screen_Reset(void); +void Screen_DeInit(void); + +extern MMU_struct MMU; + + + +#define GFXCORE_DEFAULT -1 +#define GFXCORE_DUMMY 0 + +#define GFXCORE_FULLSCREEN (1 << 0) + +typedef struct +{ + int id; // ID number for core(see above defines) + const char *Name; // Name of core + int flags; // What features the core supports(full screen, etc.) + int (*Init)(); // Initializes stuff related to core + void (*DeInit)(); // Deinitializes stuff related to core + void (*Resize)(int width, int height, BOOL fullscreen); // Resizes window or fullscreen + void (*OnScreenText)(char *string, ...); // For handling save state messages, etc. +} GraphicsInterface_struct; + +extern GraphicsInterface_struct GFXDummy; + +void GPU_setVideoProp(GPU *, u32 p); +void GPU_setBGProp(GPU *, u16 num, u16 p); + +void GPU_setBLDCNT(GPU *gpu, u16 v) ; +void GPU_setBLDALPHA(GPU *gpu, u16 v) ; +void GPU_setBLDY(GPU *gpu, u16 v) ; +void GPU_setMOSAIC(GPU *gpu, u16 v) ; + + +void GPU_remove(GPU *, u8 num); +void GPU_addBack(GPU *, u8 num); + +int GPU_ChangeGraphicsCore(int coreid); + +void GPU_set_DISPCAPCNT(GPU * gpu, u32 val) ; +void GPU_ligne(NDS_Screen * screen, u16 l) ; +void GPU_setMasterBrightness (GPU *gpu, u16 val); + +void GPU_setWIN0_H (GPU *gpu, u16 val); +void GPU_setWIN0_H0 (GPU *gpu, u8 val); +void GPU_setWIN0_H1 (GPU *gpu, u8 val); + +void GPU_setWIN0_V (GPU *gpu, u16 val); +void GPU_setWIN0_V0 (GPU *gpu, u8 val); +void GPU_setWIN0_V1 (GPU *gpu, u8 val); + +void GPU_setWIN1_H (GPU *gpu, u16 val); +void GPU_setWIN1_H0 (GPU *gpu, u8 val); +void GPU_setWIN1_H1 (GPU *gpu, u8 val); + +void GPU_setWIN1_V (GPU *gpu, u16 val); +void GPU_setWIN1_V0 (GPU *gpu, u8 val); +void GPU_setWIN1_V1 (GPU *gpu, u8 val); + +void GPU_setWININ (GPU *gpu, u16 val); +void GPU_setWININ0 (GPU *gpu, u8 val); +void GPU_setWININ1 (GPU *gpu, u8 val); + +void GPU_setWINOUT16(GPU *gpu, u16 val); +void GPU_setWINOUT (GPU *gpu, u8 val); +void GPU_setWINOBJ (GPU *gpu, u8 val); + +void GPU_setBLDCNT_LOW (GPU *gpu, u8 val); +void GPU_setBLDCNT_HIGH (GPU *gpu, u8 val); +void GPU_setBLDCNT (GPU *gpu, u16 val); + +void GPU_setBLDALPHA (GPU *gpu, u16 val); +void GPU_setBLDALPHA_EVA(GPU *gpu, u8 val); +void GPU_setBLDALPHA_EVB(GPU *gpu, u8 val); + +void GPU_setBLDY_EVY (GPU *gpu, u8 val); + +#ifdef __cplusplus +} +#endif + +#endif + diff -r fe2ba1a712cd -r 70b0973e7b70 src/xsf/desmume/MMU.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/xsf/desmume/MMU.c Thu Oct 16 14:45:41 2008 -0500 @@ -0,0 +1,3565 @@ +/* Copyright (C) 2006 yopyop + yopyop156@ifrance.com + yopyop156.ifrance.com + + Copyright (C) 2007 shash + + This file is part of DeSmuME + + DeSmuME is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DeSmuME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DeSmuME; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +//#define RENDER3D + +#include +#include +#include + +//#include "gl_vertex.h" + +#include "debug.h" +#include "NDSSystem.h" +//#include "cflash.h" +#define cflash_read(a) 0 +#define cflash_write(a,d) +#include "cp15.h" +//#include "wifi.h" +#include "registers.h" + +#if VIO2SF_GPU_ENABLE +#include "render3D.h" +#else +#define GPU_setVideoProp(p1, p2) +#define GPU_setBGProp(p1, p2, p3) + +#define GPU_setBLDCNT(p1, p2) +#define GPU_setBLDALPHA(p1, p2) +#define GPU_setBLDY(p1, p2) +#define GPU_setMOSAIC(p1, p2) + + +#define GPU_remove(p1,p2) +#define GPU_addBack(p1,p2) + +#define GPU_ChangeGraphicsCore(p1) 0 + +#define GPU_set_DISPCAPCNT(p1, p2) +#define GPU_ligne(p1, p2) +#define GPU_setMasterBrightness(p1, p2) + +#define GPU_setWIN0_H(p1, p2) +#define GPU_setWIN0_H0(p1, p2) +#define GPU_setWIN0_H1(p1, p2) + +#define GPU_setWIN0_V(p1, p2) +#define GPU_setWIN0_V0(p1, p2) +#define GPU_setWIN0_V1(p1, p2) + +#define GPU_setWIN1_H(p1, p2) +#define GPU_setWIN1_H0(p1, p2) +#define GPU_setWIN1_H1(p1, p2) + +#define GPU_setWIN1_V(p1, p2) +#define GPU_setWIN1_V0(p1, p2) +#define GPU_setWIN1_V1(p1, p2) + +#define GPU_setWININ(p1, p2) +#define GPU_setWININ0(p1, p2) +#define GPU_setWININ1(p1, p2) + +#define GPU_setWINOUT16(p1, p2) +#define GPU_setWINOUT(p1, p2) +#define GPU_setWINOBJ(p1, p2) + +#define GPU_setBLDCNT_LOW(p1, p2) +#define GPU_setBLDCNT_HIGH(p1, p2) +#define GPU_setBLDCNT(p1, p2) + +#define GPU_setBLDALPHA(p1, p2) +#define GPU_setBLDALPHA_EVA(p1, p2) +#define GPU_setBLDALPHA_EVB(p1, p2) + +#define GPU_setBLDY_EVY(p1, p2) +#endif + +#define ROM_MASK 3 + +/* + * + */ +//#define PROFILE_MEMORY_ACCESS 1 +#define EARLY_MEMORY_ACCESS 1 + +#define INTERNAL_DTCM_READ 1 +#define INTERNAL_DTCM_WRITE 1 + +//#define LOG_CARD +//#define LOG_GPU +//#define LOG_DMA +//#define LOG_DMA2 +//#define LOG_DIV + +char szRomPath[512]; +char szRomBaseName[512]; + +#define DUP2(x) x, x +#define DUP4(x) x, x, x, x +#define DUP8(x) x, x, x, x, x, x, x, x +#define DUP16(x) x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x + +MMU_struct MMU; + +u8 * MMU_ARM9_MEM_MAP[256]={ +/* 0X*/ DUP16(ARM9Mem.ARM9_ITCM), +/* 1X*/ //DUP16(ARM9Mem.ARM9_ITCM) +/* 1X*/ DUP16(ARM9Mem.ARM9_WRAM), +/* 2X*/ DUP16(ARM9Mem.MAIN_MEM), +/* 3X*/ DUP16(MMU.SWIRAM), +/* 4X*/ DUP16(ARM9Mem.ARM9_REG), +/* 5X*/ DUP16(ARM9Mem.ARM9_VMEM), +/* 6X*/ DUP2(ARM9Mem.ARM9_ABG), + DUP2(ARM9Mem.ARM9_BBG), + DUP2(ARM9Mem.ARM9_AOBJ), + DUP2(ARM9Mem.ARM9_BOBJ), + DUP8(ARM9Mem.ARM9_LCD), +/* 7X*/ DUP16(ARM9Mem.ARM9_OAM), +/* 8X*/ DUP16(NULL), +/* 9X*/ DUP16(NULL), +/* AX*/ DUP16(MMU.CART_RAM), +/* BX*/ DUP16(MMU.UNUSED_RAM), +/* CX*/ DUP16(MMU.UNUSED_RAM), +/* DX*/ DUP16(MMU.UNUSED_RAM), +/* EX*/ DUP16(MMU.UNUSED_RAM), +/* FX*/ DUP16(ARM9Mem.ARM9_BIOS) +}; + +u32 MMU_ARM9_MEM_MASK[256]={ +/* 0X*/ DUP16(0x00007FFF), +/* 1X*/ //DUP16(0x00007FFF) +/* 1X*/ DUP16(0x00FFFFFF), +/* 2X*/ DUP16(0x003FFFFF), +/* 3X*/ DUP16(0x00007FFF), +/* 4X*/ DUP16(0x00FFFFFF), +/* 5X*/ DUP16(0x000007FF), +/* 6X*/ DUP2(0x0007FFFF), + DUP2(0x0001FFFF), + DUP2(0x0003FFFF), + DUP2(0x0001FFFF), + DUP8(0x000FFFFF), +/* 7X*/ DUP16(0x000007FF), +/* 8X*/ DUP16(ROM_MASK), +/* 9X*/ DUP16(ROM_MASK), +/* AX*/ DUP16(0x0000FFFF), +/* BX*/ DUP16(0x00000003), +/* CX*/ DUP16(0x00000003), +/* DX*/ DUP16(0x00000003), +/* EX*/ DUP16(0x00000003), +/* FX*/ DUP16(0x00007FFF) +}; + +u8 * MMU_ARM7_MEM_MAP[256]={ +/* 0X*/ DUP16(MMU.ARM7_BIOS), +/* 1X*/ DUP16(MMU.UNUSED_RAM), +/* 2X*/ DUP16(ARM9Mem.MAIN_MEM), +/* 3X*/ DUP8(MMU.SWIRAM), + DUP8(MMU.ARM7_ERAM), +/* 4X*/ DUP8(MMU.ARM7_REG), + DUP8(MMU.ARM7_WIRAM), +/* 5X*/ DUP16(MMU.UNUSED_RAM), +/* 6X*/ DUP16(ARM9Mem.ARM9_ABG), +/* 7X*/ DUP16(MMU.UNUSED_RAM), +/* 8X*/ DUP16(NULL), +/* 9X*/ DUP16(NULL), +/* AX*/ DUP16(MMU.CART_RAM), +/* BX*/ DUP16(MMU.UNUSED_RAM), +/* CX*/ DUP16(MMU.UNUSED_RAM), +/* DX*/ DUP16(MMU.UNUSED_RAM), +/* EX*/ DUP16(MMU.UNUSED_RAM), +/* FX*/ DUP16(MMU.UNUSED_RAM) +}; + +u32 MMU_ARM7_MEM_MASK[256]={ +/* 0X*/ DUP16(0x00003FFF), +/* 1X*/ DUP16(0x00000003), +/* 2X*/ DUP16(0x003FFFFF), +/* 3X*/ DUP8(0x00007FFF), + DUP8(0x0000FFFF), +/* 4X*/ DUP8(0x00FFFFFF), + DUP8(0x0000FFFF), +/* 5X*/ DUP16(0x00000003), +/* 6X*/ DUP16(0x0003FFFF), +/* 7X*/ DUP16(0x00000003), +/* 8X*/ DUP16(ROM_MASK), +/* 9X*/ DUP16(ROM_MASK), +/* AX*/ DUP16(0x0000FFFF), +/* BX*/ DUP16(0x00000003), +/* CX*/ DUP16(0x00000003), +/* DX*/ DUP16(0x00000003), +/* EX*/ DUP16(0x00000003), +/* FX*/ DUP16(0x00000003) +}; + +u32 MMU_ARM9_WAIT16[16]={ + 1, 1, 1, 1, 1, 1, 1, 1, 5, 5, 5, 1, 1, 1, 1, 1, +}; + +u32 MMU_ARM9_WAIT32[16]={ + 1, 1, 1, 1, 1, 2, 2, 1, 8, 8, 5, 1, 1, 1, 1, 1, +}; + +u32 MMU_ARM7_WAIT16[16]={ + 1, 1, 1, 1, 1, 1, 1, 1, 5, 5, 5, 1, 1, 1, 1, 1, +}; + +u32 MMU_ARM7_WAIT32[16]={ + 1, 1, 1, 1, 1, 1, 1, 1, 8, 8, 5, 1, 1, 1, 1, 1, +}; + +void MMU_Init(void) { + int i; + + LOG("MMU init\n"); + + memset(&MMU, 0, sizeof(MMU_struct)); + + MMU.CART_ROM = MMU.UNUSED_RAM; + + for(i = 0x80; i<0xA0; ++i) + { + MMU_ARM9_MEM_MAP[i] = MMU.CART_ROM; + MMU_ARM7_MEM_MAP[i] = MMU.CART_ROM; + } + + MMU.MMU_MEM[0] = MMU_ARM9_MEM_MAP; + MMU.MMU_MEM[1] = MMU_ARM7_MEM_MAP; + MMU.MMU_MASK[0]= MMU_ARM9_MEM_MASK; + MMU.MMU_MASK[1] = MMU_ARM7_MEM_MASK; + + MMU.ITCMRegion = 0x00800000; + + MMU.MMU_WAIT16[0] = MMU_ARM9_WAIT16; + MMU.MMU_WAIT16[1] = MMU_ARM7_WAIT16; + MMU.MMU_WAIT32[0] = MMU_ARM9_WAIT32; + MMU.MMU_WAIT32[1] = MMU_ARM7_WAIT32; + + for(i = 0;i < 16;i++) + FIFOInit(MMU.fifos + i); + + mc_init(&MMU.fw, MC_TYPE_FLASH); /* init fw device */ + mc_alloc(&MMU.fw, NDS_FW_SIZE_V1); + MMU.fw.fp = NULL; + + // Init Backup Memory device, this should really be done when the rom is loaded + mc_init(&MMU.bupmem, MC_TYPE_AUTODETECT); + mc_alloc(&MMU.bupmem, 1); + MMU.bupmem.fp = NULL; + +} + +void MMU_DeInit(void) { + LOG("MMU deinit\n"); +// if (MMU.fw.fp) +// fclose(MMU.fw.fp); + mc_free(&MMU.fw); +// if (MMU.bupmem.fp) +// fclose(MMU.bupmem.fp); + mc_free(&MMU.bupmem); +} + +//Card rom & ram + +u16 SPI_CNT = 0; +u16 SPI_CMD = 0; +u16 AUX_SPI_CNT = 0; +u16 AUX_SPI_CMD = 0; + +u32 rom_mask = 0; + +u32 DMASrc[2][4] = {{0, 0, 0, 0}, {0, 0, 0, 0}}; +u32 DMADst[2][4] = {{0, 0, 0, 0}, {0, 0, 0, 0}}; + +void MMU_clearMem() +{ + int i; + + memset(ARM9Mem.ARM9_ABG, 0, 0x080000); + memset(ARM9Mem.ARM9_AOBJ, 0, 0x040000); + memset(ARM9Mem.ARM9_BBG, 0, 0x020000); + memset(ARM9Mem.ARM9_BOBJ, 0, 0x020000); + memset(ARM9Mem.ARM9_DTCM, 0, 0x4000); + memset(ARM9Mem.ARM9_ITCM, 0, 0x8000); + memset(ARM9Mem.ARM9_LCD, 0, 0x0A4000); + memset(ARM9Mem.ARM9_OAM, 0, 0x0800); + memset(ARM9Mem.ARM9_REG, 0, 0x01000000); + memset(ARM9Mem.ARM9_VMEM, 0, 0x0800); + memset(ARM9Mem.ARM9_WRAM, 0, 0x01000000); + memset(ARM9Mem.MAIN_MEM, 0, 0x400000); + + memset(ARM9Mem.blank_memory, 0, 0x020000); + + memset(MMU.ARM7_ERAM, 0, 0x010000); + memset(MMU.ARM7_REG, 0, 0x010000); + + for(i = 0;i < 16;i++) + FIFOInit(MMU.fifos + i); + + MMU.DTCMRegion = 0; + MMU.ITCMRegion = 0x00800000; + + memset(MMU.timer, 0, sizeof(u16) * 2 * 4); + memset(MMU.timerMODE, 0, sizeof(s32) * 2 * 4); + memset(MMU.timerON, 0, sizeof(u32) * 2 * 4); + memset(MMU.timerRUN, 0, sizeof(u32) * 2 * 4); + memset(MMU.timerReload, 0, sizeof(u16) * 2 * 4); + + memset(MMU.reg_IME, 0, sizeof(u32) * 2); + memset(MMU.reg_IE, 0, sizeof(u32) * 2); + memset(MMU.reg_IF, 0, sizeof(u32) * 2); + + memset(MMU.DMAStartTime, 0, sizeof(u32) * 2 * 4); + memset(MMU.DMACycle, 0, sizeof(s32) * 2 * 4); + memset(MMU.DMACrt, 0, sizeof(u32) * 2 * 4); + memset(MMU.DMAing, 0, sizeof(BOOL) * 2 * 4); + + memset(MMU.dscard, 0, sizeof(nds_dscard) * 2); + + MainScreen.offset = 192; + SubScreen.offset = 0; + + /* setup the texture slot pointers */ +#if 0 + ARM9Mem.textureSlotAddr[0] = ARM9Mem.blank_memory; + ARM9Mem.textureSlotAddr[1] = ARM9Mem.blank_memory; + ARM9Mem.textureSlotAddr[2] = ARM9Mem.blank_memory; + ARM9Mem.textureSlotAddr[3] = ARM9Mem.blank_memory; +#else + ARM9Mem.textureSlotAddr[0] = &ARM9Mem.ARM9_LCD[0x20000 * 0]; + ARM9Mem.textureSlotAddr[1] = &ARM9Mem.ARM9_LCD[0x20000 * 1]; + ARM9Mem.textureSlotAddr[2] = &ARM9Mem.ARM9_LCD[0x20000 * 2]; + ARM9Mem.textureSlotAddr[3] = &ARM9Mem.ARM9_LCD[0x20000 * 3]; +#endif +} + +/* the VRAM blocks keep their content even when not blended in */ +/* to ensure that we write the content back to the LCD ram */ +/* FIXME: VRAM Bank E,F,G,H,I missing */ +void MMU_VRAMWriteBackToLCD(u8 block) +{ + u8 *destination; + u8 *source; + u32 size ; + u8 VRAMBankCnt; + #if 1 + return ; + #endif + destination = 0 ; + source = 0; + VRAMBankCnt = MMU_read8(ARMCPU_ARM9,REG_VRAMCNTA+block) ; + switch (block) + { + case 0: // Bank A + destination = ARM9Mem.ARM9_LCD ; + size = 0x20000 ; + break ; + case 1: // Bank B + destination = ARM9Mem.ARM9_LCD + 0x20000 ; + size = 0x20000 ; + break ; + case 2: // Bank C + destination = ARM9Mem.ARM9_LCD + 0x40000 ; + size = 0x20000 ; + break ; + case 3: // Bank D + destination = ARM9Mem.ARM9_LCD + 0x60000 ; + size = 0x20000 ; + break ; + case 4: // Bank E + destination = ARM9Mem.ARM9_LCD + 0x80000 ; + size = 0x10000 ; + break ; + case 5: // Bank F + destination = ARM9Mem.ARM9_LCD + 0x90000 ; + size = 0x4000 ; + break ; + case 6: // Bank G + destination = ARM9Mem.ARM9_LCD + 0x94000 ; + size = 0x4000 ; + break ; + case 8: // Bank H + destination = ARM9Mem.ARM9_LCD + 0x98000 ; + size = 0x8000 ; + break ; + case 9: // Bank I + destination = ARM9Mem.ARM9_LCD + 0xA0000 ; + size = 0x4000 ; + break ; + default: + return ; + } + switch (VRAMBankCnt & 7) { + case 0: + /* vram is allready stored at LCD, we dont need to write it back */ + MMU.vScreen = 1; + break ; + case 1: + switch(block){ + case 0: + case 1: + case 2: + case 3: + /* banks are in use for BG at ABG + ofs * 0x20000 */ + source = ARM9Mem.ARM9_ABG + ((VRAMBankCnt >> 3) & 3) * 0x20000 ; + break ; + case 4: + /* bank E is in use at ABG */ + source = ARM9Mem.ARM9_ABG ; + break; + case 5: + case 6: + /* banks are in use for BG at ABG + (0x4000*OFS.0)+(0x10000*OFS.1)*/ + source = ARM9Mem.ARM9_ABG + (((VRAMBankCnt >> 3) & 1) * 0x4000) + (((VRAMBankCnt >> 2) & 1) * 0x10000) ; + break; + case 8: + /* bank H is in use at BBG */ + source = ARM9Mem.ARM9_BBG ; + break ; + case 9: + /* bank I is in use at BBG */ + source = ARM9Mem.ARM9_BBG + 0x8000 ; + break; + default: return ; + } + break ; + case 2: + if (block < 2) + { + /* banks A,B are in use for OBJ at AOBJ + ofs * 0x20000 */ + source = ARM9Mem.ARM9_AOBJ + ((VRAMBankCnt >> 3) & 1) * 0x20000 ; + } else return ; + break ; + case 4: + switch(block){ + case 2: + /* bank C is in use at BBG */ + source = ARM9Mem.ARM9_BBG ; + break ; + case 3: + /* bank D is in use at BOBJ */ + source = ARM9Mem.ARM9_BOBJ ; + break ; + default: return ; + } + break ; + default: + return ; + } + if (!destination) return ; + if (!source) return ; + memcpy(destination,source,size) ; +} + +void MMU_VRAMReloadFromLCD(u8 block,u8 VRAMBankCnt) +{ + u8 *destination; + u8 *source; + u32 size; + #if 1 + return ; + #endif + destination = 0; + source = 0; + size = 0; + switch (block) + { + case 0: // Bank A + source = ARM9Mem.ARM9_LCD ; + size = 0x20000 ; + break ; + case 1: // Bank B + source = ARM9Mem.ARM9_LCD + 0x20000 ; + size = 0x20000 ; + break ; + case 2: // Bank C + source = ARM9Mem.ARM9_LCD + 0x40000 ; + size = 0x20000 ; + break ; + case 3: // Bank D + source = ARM9Mem.ARM9_LCD + 0x60000 ; + size = 0x20000 ; + break ; + case 4: // Bank E + source = ARM9Mem.ARM9_LCD + 0x80000 ; + size = 0x10000 ; + break ; + case 5: // Bank F + source = ARM9Mem.ARM9_LCD + 0x90000 ; + size = 0x4000 ; + break ; + case 6: // Bank G + source = ARM9Mem.ARM9_LCD + 0x94000 ; + size = 0x4000 ; + break ; + case 8: // Bank H + source = ARM9Mem.ARM9_LCD + 0x98000 ; + size = 0x8000 ; + break ; + case 9: // Bank I + source = ARM9Mem.ARM9_LCD + 0xA0000 ; + size = 0x4000 ; + break ; + default: + return ; + } + switch (VRAMBankCnt & 7) { + case 0: + /* vram is allready stored at LCD, we dont need to write it back */ + MMU.vScreen = 1; + break ; + case 1: + if (block < 4) + { + /* banks are in use for BG at ABG + ofs * 0x20000 */ + destination = ARM9Mem.ARM9_ABG + ((VRAMBankCnt >> 3) & 3) * 0x20000 ; + } else return ; + break ; + case 2: + switch(block){ + case 0: + case 1: + case 2: + case 3: + /* banks are in use for BG at ABG + ofs * 0x20000 */ + destination = ARM9Mem.ARM9_ABG + ((VRAMBankCnt >> 3) & 3) * 0x20000 ; + break ; + case 4: + /* bank E is in use at ABG */ + destination = ARM9Mem.ARM9_ABG ; + break; + case 5: + case 6: + /* banks are in use for BG at ABG + (0x4000*OFS.0)+(0x10000*OFS.1)*/ + destination = ARM9Mem.ARM9_ABG + (((VRAMBankCnt >> 3) & 1) * 0x4000) + (((VRAMBankCnt >> 2) & 1) * 0x10000) ; + break; + case 8: + /* bank H is in use at BBG */ + destination = ARM9Mem.ARM9_BBG ; + break ; + case 9: + /* bank I is in use at BBG */ + destination = ARM9Mem.ARM9_BBG + 0x8000 ; + break; + default: return ; + } + break ; + case 4: + switch(block){ + case 2: + /* bank C is in use at BBG */ + destination = ARM9Mem.ARM9_BBG ; + break ; + case 3: + /* bank D is in use at BOBJ */ + destination = ARM9Mem.ARM9_BOBJ ; + break ; + default: return ; + } + break ; + default: + return ; + } + if (!destination) return ; + if (!source) return ; + memcpy(destination,source,size) ; +} + +void MMU_setRom(u8 * rom, u32 mask) +{ + unsigned int i; + MMU.CART_ROM = rom; + + for(i = 0x80; i<0xA0; ++i) + { + MMU_ARM9_MEM_MAP[i] = rom; + MMU_ARM7_MEM_MAP[i] = rom; + MMU_ARM9_MEM_MASK[i] = mask; + MMU_ARM7_MEM_MASK[i] = mask; + } + rom_mask = mask; +} + +void MMU_unsetRom() +{ + unsigned int i; + MMU.CART_ROM=MMU.UNUSED_RAM; + + for(i = 0x80; i<0xA0; ++i) + { + MMU_ARM9_MEM_MAP[i] = MMU.UNUSED_RAM; + MMU_ARM7_MEM_MAP[i] = MMU.UNUSED_RAM; + MMU_ARM9_MEM_MASK[i] = ROM_MASK; + MMU_ARM7_MEM_MASK[i] = ROM_MASK; + } + rom_mask = ROM_MASK; +} +char txt[80]; + +u8 FASTCALL MMU_read8(u32 proc, u32 adr) +{ +#ifdef INTERNAL_DTCM_READ + if((proc==ARMCPU_ARM9)&((adr&(~0x3FFF))==MMU.DTCMRegion)) + { + return ARM9Mem.ARM9_DTCM[adr&0x3FFF]; + } +#endif + + // CFlash reading, Mic + if ((adr>=0x9000000)&&(adr<0x9900000)) + return (unsigned char)cflash_read(adr); + +#ifdef EXPERIMENTAL_WIFI + /* wifi mac access */ + if ((proc==ARMCPU_ARM7) && (adr>=0x04800000)&&(adr<0x05000000)) + { + if (adr & 1) + return (WIFI_read16(&wifiMac,adr) >> 8) & 0xFF; + else + return WIFI_read16(&wifiMac,adr) & 0xFF; + } +#endif + + return MMU.MMU_MEM[proc][(adr>>20)&0xFF][adr&MMU.MMU_MASK[proc][(adr>>20)&0xFF]]; +} + + + +u16 FASTCALL MMU_read16(u32 proc, u32 adr) +{ +#ifdef INTERNAL_DTCM_READ + if((proc == ARMCPU_ARM9) && ((adr & ~0x3FFF) == MMU.DTCMRegion)) + { + /* Returns data from DTCM (ARM9 only) */ + return T1ReadWord(ARM9Mem.ARM9_DTCM, adr & 0x3FFF); + } +#endif + + // CFlash reading, Mic + if ((adr>=0x08800000)&&(adr<0x09900000)) + return (unsigned short)cflash_read(adr); + +#ifdef EXPERIMENTAL_WIFI + /* wifi mac access */ + if ((proc==ARMCPU_ARM7) && (adr>=0x04800000)&&(adr<0x05000000)) + return WIFI_read16(&wifiMac,adr) ; +#endif + + adr &= 0x0FFFFFFF; + + if(adr&0x04000000) + { + /* Adress is an IO register */ + switch(adr) + { + +#if VIO2SF_GPU_ENABLE + case 0x04000604: + return (gpu3D->NDS_3D_GetNumPolys()&2047); + case 0x04000606: + return (gpu3D->NDS_3D_GetNumVertex()&8191); +#endif + + case REG_IPCFIFORECV : /* TODO (clear): ??? */ + execute = FALSE; + return 1; + + case REG_IME : + return (u16)MMU.reg_IME[proc]; + + case REG_IE : + return (u16)MMU.reg_IE[proc]; + case REG_IE + 2 : + return (u16)(MMU.reg_IE[proc]>>16); + + case REG_IF : + return (u16)MMU.reg_IF[proc]; + case REG_IF + 2 : + return (u16)(MMU.reg_IF[proc]>>16); + + case REG_TM0CNTL : + case REG_TM1CNTL : + case REG_TM2CNTL : + case REG_TM3CNTL : + return MMU.timer[proc][(adr&0xF)>>2]; + + case 0x04000630 : + LOG("vect res\r\n"); /* TODO (clear): ??? */ + //execute = FALSE; + return 0; + case REG_POSTFLG : + return 1; + default : + break; + } + } + + /* Returns data from memory */ + return T1ReadWord(MMU.MMU_MEM[proc][(adr >> 20) & 0xFF], adr & MMU.MMU_MASK[proc][(adr >> 20) & 0xFF]); +} + +u32 FASTCALL MMU_read32(u32 proc, u32 adr) +{ +#ifdef INTERNAL_DTCM_READ + if((proc == ARMCPU_ARM9) && ((adr & ~0x3FFF) == MMU.DTCMRegion)) + { + /* Returns data from DTCM (ARM9 only) */ + return T1ReadLong(ARM9Mem.ARM9_DTCM, adr & 0x3FFF); + } +#endif + + // CFlash reading, Mic + if ((adr>=0x9000000)&&(adr<0x9900000)) + return (unsigned long)cflash_read(adr); + + adr &= 0x0FFFFFFF; + + if((adr >> 24) == 4) + { + /* Adress is an IO register */ + switch(adr) + { + // This is hacked due to the only current 3D core + case 0x04000600: + { + u32 fifonum = IPCFIFO+proc; + + u32 gxstat = (MMU.fifos[fifonum].empty<<26) | + (1<<25) | + (MMU.fifos[fifonum].full<<24) | + /*((NDS_nbpush[0]&1)<<13) | ((NDS_nbpush[2]&0x1F)<<8) |*/ + 2; + + LOG ("GXSTAT: 0x%X", gxstat); + + return gxstat; + } + + case 0x04000640: + case 0x04000644: + case 0x04000648: + case 0x0400064C: + case 0x04000650: + case 0x04000654: + case 0x04000658: + case 0x0400065C: + case 0x04000660: + case 0x04000664: + case 0x04000668: + case 0x0400066C: + case 0x04000670: + case 0x04000674: + case 0x04000678: + case 0x0400067C: + { + //LOG("4000640h..67Fh - CLIPMTX_RESULT - Read Current Clip Coordinates Matrix (R)"); +#if VIO2SF_GPU_ENABLE + return gpu3D->NDS_3D_GetClipMatrix ((adr-0x04000640)/4); +#else + return 0; +#endif + } + case 0x04000680: + case 0x04000684: + case 0x04000688: + case 0x0400068C: + case 0x04000690: + case 0x04000694: + case 0x04000698: + case 0x0400069C: + case 0x040006A0: + { +#if VIO2SF_GPU_ENABLE + //LOG("4000680h..6A3h - VECMTX_RESULT - Read Current Directional Vector Matrix (R)"); + return gpu3D->NDS_3D_GetDirectionalMatrix ((adr-0x04000680)/4); +#else + return 0; +#endif + } + + case 0x4000604: + { +#if VIO2SF_GPU_ENABLE + return (gpu3D->NDS_3D_GetNumPolys()&2047) & ((gpu3D->NDS_3D_GetNumVertex()&8191) << 16); + //LOG ("read32 - RAM_COUNT -> 0x%X", ((u32 *)(MMU.MMU_MEM[proc][(adr>>20)&0xFF]))[(adr&MMU.MMU_MASK[proc][(adr>>20)&0xFF])>>2]); +#else + return 0; +#endif + } + + case REG_IME : + return MMU.reg_IME[proc]; + case REG_IE : + return MMU.reg_IE[proc]; + case REG_IF : + return MMU.reg_IF[proc]; + case REG_IPCFIFORECV : + { + u16 IPCFIFO_CNT = T1ReadWord(MMU.MMU_MEM[proc][0x40], 0x184); + if(IPCFIFO_CNT&0x8000) + { + //execute = FALSE; + u32 fifonum = IPCFIFO+proc; + u32 val = FIFOValue(MMU.fifos + fifonum); + u32 remote = (proc+1) & 1; + u16 IPCFIFO_CNT_remote = T1ReadWord(MMU.MMU_MEM[remote][0x40], 0x184); + IPCFIFO_CNT |= (MMU.fifos[fifonum].empty<<8) | (MMU.fifos[fifonum].full<<9) | (MMU.fifos[fifonum].error<<14); + IPCFIFO_CNT_remote |= (MMU.fifos[fifonum].empty) | (MMU.fifos[fifonum].full<<1); + T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x184, IPCFIFO_CNT); + T1WriteWord(MMU.MMU_MEM[remote][0x40], 0x184, IPCFIFO_CNT_remote); + if ((MMU.fifos[fifonum].empty) && (IPCFIFO_CNT & BIT(2))) + NDS_makeInt(remote,17) ; /* remote: SEND FIFO EMPTY */ + return val; + } + } + return 0; + case REG_TM0CNTL : + case REG_TM1CNTL : + case REG_TM2CNTL : + case REG_TM3CNTL : + { + u32 val = T1ReadWord(MMU.MMU_MEM[proc][0x40], (adr + 2) & 0xFFF); + return MMU.timer[proc][(adr&0xF)>>2] | (val<<16); + } + /* + case 0x04000640 : // TODO (clear): again, ??? + LOG("read proj\r\n"); + return 0; + case 0x04000680 : + LOG("read roat\r\n"); + return 0; + case 0x04000620 : + LOG("point res\r\n"); + return 0; + */ + case REG_GCDATAIN: + { + u32 val; + + if(!MMU.dscard[proc].adress) return 0; + + val = T1ReadLong(MMU.CART_ROM, MMU.dscard[proc].adress); + + MMU.dscard[proc].adress += 4; /* increment adress */ + + MMU.dscard[proc].transfer_count--; /* update transfer counter */ + if(MMU.dscard[proc].transfer_count) /* if transfer is not ended */ + { + return val; /* return data */ + } + else /* transfer is done */ + { + T1WriteLong(MMU.MMU_MEM[proc][(REG_GCROMCTRL >> 20) & 0xff], REG_GCROMCTRL & 0xfff, T1ReadLong(MMU.MMU_MEM[proc][(REG_GCROMCTRL >> 20) & 0xff], REG_GCROMCTRL & 0xfff) & ~(0x00800000 | 0x80000000)); + /* = 0x7f7fffff */ + + /* if needed, throw irq for the end of transfer */ + if(T1ReadWord(MMU.MMU_MEM[proc][(REG_AUXSPICNT >> 20) & 0xff], REG_AUXSPICNT & 0xfff) & 0x4000) + { + if(proc == ARMCPU_ARM7) NDS_makeARM7Int(19); + else NDS_makeARM9Int(19); + } + + return val; + } + } + + default : + break; + } + } + + /* Returns data from memory */ + return T1ReadLong(MMU.MMU_MEM[proc][(adr >> 20) & 0xFF], adr & MMU.MMU_MASK[proc][(adr >> 20) & 0xFF]); +} + +void FASTCALL MMU_write8(u32 proc, u32 adr, u8 val) +{ +#ifdef INTERNAL_DTCM_WRITE + if((proc == ARMCPU_ARM9) && ((adr & ~0x3FFF) == MMU.DTCMRegion)) + { + /* Writes data in DTCM (ARM9 only) */ + ARM9Mem.ARM9_DTCM[adr&0x3FFF] = val; + return ; + } +#endif + + // CFlash writing, Mic + if ((adr>=0x9000000)&&(adr<0x9900000)) { + cflash_write(adr,val); + return; + } + + adr &= 0x0FFFFFFF; + + // This is bad, remove it + if(proc == ARMCPU_ARM7) + { + if ((adr>=0x04000400)&&(adr<0x0400051D)) + { + SPU_WriteByte(adr, val); + return; + } + } + + if (adr & 0xFF800000 == 0x04800000) + { + /* is wifi hardware, dont intermix with regular hardware registers */ + /* FIXME handle 8 bit writes */ + return ; + } + + switch(adr) + { + case REG_DISPA_WIN0H: + if(proc == ARMCPU_ARM9) GPU_setWIN0_H1 (MainScreen.gpu, val); + break ; + case REG_DISPA_WIN0H+1: + if(proc == ARMCPU_ARM9) GPU_setWIN0_H0 (MainScreen.gpu, val); + break ; + case REG_DISPA_WIN1H: + if(proc == ARMCPU_ARM9) GPU_setWIN1_H1 (MainScreen.gpu,val); + break ; + case REG_DISPA_WIN1H+1: + if(proc == ARMCPU_ARM9) GPU_setWIN1_H0 (MainScreen.gpu,val); + break ; + + case REG_DISPB_WIN0H: + if(proc == ARMCPU_ARM9) GPU_setWIN0_H1(SubScreen.gpu,val); + break ; + case REG_DISPB_WIN0H+1: + if(proc == ARMCPU_ARM9) GPU_setWIN0_H0(SubScreen.gpu,val); + break ; + case REG_DISPB_WIN1H: + if(proc == ARMCPU_ARM9) GPU_setWIN1_H1(SubScreen.gpu,val); + break ; + case REG_DISPB_WIN1H+1: + if(proc == ARMCPU_ARM9) GPU_setWIN1_H0(SubScreen.gpu,val); + break ; + + case REG_DISPA_WIN0V: + if(proc == ARMCPU_ARM9) GPU_setWIN0_V1(MainScreen.gpu,val) ; + break ; + case REG_DISPA_WIN0V+1: + if(proc == ARMCPU_ARM9) GPU_setWIN0_V0(MainScreen.gpu,val) ; + break ; + case REG_DISPA_WIN1V: + if(proc == ARMCPU_ARM9) GPU_setWIN1_V1(MainScreen.gpu,val) ; + break ; + case REG_DISPA_WIN1V+1: + if(proc == ARMCPU_ARM9) GPU_setWIN1_V0(MainScreen.gpu,val) ; + break ; + + case REG_DISPB_WIN0V: + if(proc == ARMCPU_ARM9) GPU_setWIN0_V1(SubScreen.gpu,val) ; + break ; + case REG_DISPB_WIN0V+1: + if(proc == ARMCPU_ARM9) GPU_setWIN0_V0(SubScreen.gpu,val) ; + break ; + case REG_DISPB_WIN1V: + if(proc == ARMCPU_ARM9) GPU_setWIN1_V1(SubScreen.gpu,val) ; + break ; + case REG_DISPB_WIN1V+1: + if(proc == ARMCPU_ARM9) GPU_setWIN1_V0(SubScreen.gpu,val) ; + break ; + + case REG_DISPA_WININ: + if(proc == ARMCPU_ARM9) GPU_setWININ0(MainScreen.gpu,val) ; + break ; + case REG_DISPA_WININ+1: + if(proc == ARMCPU_ARM9) GPU_setWININ1(MainScreen.gpu,val) ; + break ; + case REG_DISPA_WINOUT: + if(proc == ARMCPU_ARM9) GPU_setWINOUT(MainScreen.gpu,val) ; + break ; + case REG_DISPA_WINOUT+1: + if(proc == ARMCPU_ARM9) GPU_setWINOBJ(MainScreen.gpu,val); + break ; + + case REG_DISPB_WININ: + if(proc == ARMCPU_ARM9) GPU_setWININ0(SubScreen.gpu,val) ; + break ; + case REG_DISPB_WININ+1: + if(proc == ARMCPU_ARM9) GPU_setWININ1(SubScreen.gpu,val) ; + break ; + case REG_DISPB_WINOUT: + if(proc == ARMCPU_ARM9) GPU_setWINOUT(SubScreen.gpu,val) ; + break ; + case REG_DISPB_WINOUT+1: + if(proc == ARMCPU_ARM9) GPU_setWINOBJ(SubScreen.gpu,val) ; + break ; + + + case REG_DISPA_BLDCNT: + if(proc == ARMCPU_ARM9) GPU_setBLDCNT_HIGH(MainScreen.gpu,val); + break; + case REG_DISPA_BLDCNT+1: + if(proc == ARMCPU_ARM9) GPU_setBLDCNT_LOW (MainScreen.gpu,val); + break; + + case REG_DISPB_BLDCNT: + if(proc == ARMCPU_ARM9) GPU_setBLDCNT_HIGH (SubScreen.gpu,val); + break; + case REG_DISPB_BLDCNT+1: + if(proc == ARMCPU_ARM9) GPU_setBLDCNT_LOW (SubScreen.gpu,val); + break; + + case REG_DISPA_BLDALPHA: + if(proc == ARMCPU_ARM9) GPU_setBLDALPHA_EVB(MainScreen.gpu,val) ; + break; + case REG_DISPA_BLDALPHA+1: + if(proc == ARMCPU_ARM9) GPU_setBLDALPHA_EVA(MainScreen.gpu,val) ; + break; + + case REG_DISPB_BLDALPHA: + if(proc == ARMCPU_ARM9) GPU_setBLDALPHA_EVB(SubScreen.gpu,val) ; + break; + case REG_DISPB_BLDALPHA+1: + if(proc == ARMCPU_ARM9) GPU_setBLDALPHA_EVA(SubScreen.gpu,val); + break; + + case REG_DISPA_BLDY: + if(proc == ARMCPU_ARM9) GPU_setBLDY_EVY(MainScreen.gpu,val) ; + break ; + case REG_DISPB_BLDY: + if(proc == ARMCPU_ARM9) GPU_setBLDY_EVY(SubScreen.gpu,val) ; + break; + + /* TODO: EEEK ! Controls for VRAMs A, B, C, D are missing ! */ + /* TODO: Not all mappings of VRAMs are handled... (especially BG and OBJ modes) */ + case REG_VRAMCNTA: + case REG_VRAMCNTB: + case REG_VRAMCNTC: + case REG_VRAMCNTD: + if(proc == ARMCPU_ARM9) + { + MMU_VRAMWriteBackToLCD(0) ; + MMU_VRAMWriteBackToLCD(1) ; + MMU_VRAMWriteBackToLCD(2) ; + MMU_VRAMWriteBackToLCD(3) ; + switch(val & 0x1F) + { + case 1 : + MMU.vram_mode[adr-REG_VRAMCNTA] = 0; // BG-VRAM + //MMU.vram_offset[0] = ARM9Mem.ARM9_ABG+(0x20000*0); // BG-VRAM + break; + case 1 | (1 << 3) : + MMU.vram_mode[adr-REG_VRAMCNTA] = 1; // BG-VRAM + //MMU.vram_offset[0] = ARM9Mem.ARM9_ABG+(0x20000*1); // BG-VRAM + break; + case 1 | (2 << 3) : + MMU.vram_mode[adr-REG_VRAMCNTA] = 2; // BG-VRAM + //MMU.vram_offset[0] = ARM9Mem.ARM9_ABG+(0x20000*2); // BG-VRAM + break; + case 1 | (3 << 3) : + MMU.vram_mode[adr-REG_VRAMCNTA] = 3; // BG-VRAM + //MMU.vram_offset[0] = ARM9Mem.ARM9_ABG+(0x20000*3); // BG-VRAM + break; + case 0: /* mapped to lcd */ + MMU.vram_mode[adr-REG_VRAMCNTA] = 4 | (adr-REG_VRAMCNTA) ; + break ; + } + /* + * FIXME: simply texture slot handling + * This is a first stab and is not correct. It does + * not handle a VRAM texture slot becoming + * unconfigured. + * Revisit all of VRAM control handling for future + * release? + */ + if ( val & 0x80) { + if ( (val & 0x7) == 3) { + int slot_index = (val >> 3) & 0x3; + + ARM9Mem.textureSlotAddr[slot_index] = + &ARM9Mem.ARM9_LCD[0x20000 * (adr - REG_VRAMCNTA)]; + } + } + MMU_VRAMReloadFromLCD(adr-REG_VRAMCNTA,val) ; + } + break; + case REG_VRAMCNTE : + if(proc == ARMCPU_ARM9) + { + MMU_VRAMWriteBackToLCD((u8)REG_VRAMCNTE) ; + if((val & 7) == 5) + { + ARM9Mem.ExtPal[0][0] = ARM9Mem.ARM9_LCD + 0x80000; + ARM9Mem.ExtPal[0][1] = ARM9Mem.ARM9_LCD + 0x82000; + ARM9Mem.ExtPal[0][2] = ARM9Mem.ARM9_LCD + 0x84000; + ARM9Mem.ExtPal[0][3] = ARM9Mem.ARM9_LCD + 0x86000; + } + else if((val & 7) == 3) + { + ARM9Mem.texPalSlot[0] = ARM9Mem.ARM9_LCD + 0x80000; + ARM9Mem.texPalSlot[1] = ARM9Mem.ARM9_LCD + 0x82000; + ARM9Mem.texPalSlot[2] = ARM9Mem.ARM9_LCD + 0x84000; + ARM9Mem.texPalSlot[3] = ARM9Mem.ARM9_LCD + 0x86000; + } + else if((val & 7) == 4) + { + ARM9Mem.ExtPal[0][0] = ARM9Mem.ARM9_LCD + 0x80000; + ARM9Mem.ExtPal[0][1] = ARM9Mem.ARM9_LCD + 0x82000; + ARM9Mem.ExtPal[0][2] = ARM9Mem.ARM9_LCD + 0x84000; + ARM9Mem.ExtPal[0][3] = ARM9Mem.ARM9_LCD + 0x86000; + } + + MMU_VRAMReloadFromLCD(adr-REG_VRAMCNTE,val) ; + } + break; + + case REG_VRAMCNTF : + if(proc == ARMCPU_ARM9) + { + switch(val & 0x1F) + { + case 4 : + ARM9Mem.ExtPal[0][0] = ARM9Mem.ARM9_LCD + 0x90000; + ARM9Mem.ExtPal[0][1] = ARM9Mem.ARM9_LCD + 0x92000; + break; + + case 4 | (1 << 3) : + ARM9Mem.ExtPal[0][2] = ARM9Mem.ARM9_LCD + 0x90000; + ARM9Mem.ExtPal[0][3] = ARM9Mem.ARM9_LCD + 0x92000; + break; + + case 3 : + ARM9Mem.texPalSlot[0] = ARM9Mem.ARM9_LCD + 0x90000; + break; + + case 3 | (1 << 3) : + ARM9Mem.texPalSlot[1] = ARM9Mem.ARM9_LCD + 0x90000; + break; + + case 3 | (2 << 3) : + ARM9Mem.texPalSlot[2] = ARM9Mem.ARM9_LCD + 0x90000; + break; + + case 3 | (3 << 3) : + ARM9Mem.texPalSlot[3] = ARM9Mem.ARM9_LCD + 0x90000; + break; + + case 5 : + case 5 | (1 << 3) : + case 5 | (2 << 3) : + case 5 | (3 << 3) : + ARM9Mem.ObjExtPal[0][0] = ARM9Mem.ARM9_LCD + 0x90000; + ARM9Mem.ObjExtPal[0][1] = ARM9Mem.ARM9_LCD + 0x92000; + break; + } + } + break; + case REG_VRAMCNTG : + if(proc == ARMCPU_ARM9) + { + switch(val & 0x1F) + { + case 4 : + ARM9Mem.ExtPal[0][0] = ARM9Mem.ARM9_LCD + 0x94000; + ARM9Mem.ExtPal[0][1] = ARM9Mem.ARM9_LCD + 0x96000; + break; + + case 4 | (1 << 3) : + ARM9Mem.ExtPal[0][2] = ARM9Mem.ARM9_LCD + 0x94000; + ARM9Mem.ExtPal[0][3] = ARM9Mem.ARM9_LCD + 0x96000; + break; + + case 3 : + ARM9Mem.texPalSlot[0] = ARM9Mem.ARM9_LCD + 0x94000; + break; + + case 3 | (1 << 3) : + ARM9Mem.texPalSlot[1] = ARM9Mem.ARM9_LCD + 0x94000; + break; + + case 3 | (2 << 3) : + ARM9Mem.texPalSlot[2] = ARM9Mem.ARM9_LCD + 0x94000; + break; + + case 3 | (3 << 3) : + ARM9Mem.texPalSlot[3] = ARM9Mem.ARM9_LCD + 0x94000; + break; + + case 5 : + case 5 | (1 << 3) : + case 5 | (2 << 3) : + case 5 | (3 << 3) : + ARM9Mem.ObjExtPal[0][0] = ARM9Mem.ARM9_LCD + 0x94000; + ARM9Mem.ObjExtPal[0][1] = ARM9Mem.ARM9_LCD + 0x96000; + break; + } + } + break; + + case REG_VRAMCNTH : + if(proc == ARMCPU_ARM9) + { + MMU_VRAMWriteBackToLCD((u8)REG_VRAMCNTH) ; + + if((val & 7) == 2) + { + ARM9Mem.ExtPal[1][0] = ARM9Mem.ARM9_LCD + 0x98000; + ARM9Mem.ExtPal[1][1] = ARM9Mem.ARM9_LCD + 0x9A000; + ARM9Mem.ExtPal[1][2] = ARM9Mem.ARM9_LCD + 0x9C000; + ARM9Mem.ExtPal[1][3] = ARM9Mem.ARM9_LCD + 0x9E000; + } + + MMU_VRAMReloadFromLCD(adr-REG_VRAMCNTH,val) ; + } + break; + + case REG_VRAMCNTI : + if(proc == ARMCPU_ARM9) + { + MMU_VRAMWriteBackToLCD((u8)REG_VRAMCNTI) ; + + if((val & 7) == 3) + { + ARM9Mem.ObjExtPal[1][0] = ARM9Mem.ARM9_LCD + 0xA0000; + ARM9Mem.ObjExtPal[1][1] = ARM9Mem.ARM9_LCD + 0xA2000; + } + + MMU_VRAMReloadFromLCD(adr-REG_VRAMCNTI,val) ; + } + break; + +#ifdef LOG_CARD + case 0x040001A0 : /* TODO (clear): ??? */ + case 0x040001A1 : + case 0x040001A2 : + case 0x040001A8 : + case 0x040001A9 : + case 0x040001AA : + case 0x040001AB : + case 0x040001AC : + case 0x040001AD : + case 0x040001AE : + case 0x040001AF : + LOG("%08X : %02X\r\n", adr, val); +#endif + + default : + break; + } + + MMU.MMU_MEM[proc][(adr>>20)&0xFF][adr&MMU.MMU_MASK[proc][(adr>>20)&0xFF]]=val; +} + +u16 partie = 1; + +void FASTCALL MMU_write16(u32 proc, u32 adr, u16 val) +{ +#ifdef INTERNAL_DTCM_WRITE + if((proc == ARMCPU_ARM9) && ((adr & ~0x3FFF) == MMU.DTCMRegion)) + { + /* Writes in DTCM (ARM9 only) */ + T1WriteWord(ARM9Mem.ARM9_DTCM, adr & 0x3FFF, val); + return; + } +#endif + + // CFlash writing, Mic + if ((adr>=0x08800000)&&(adr<0x09900000)) + { + cflash_write(adr,val); + return; + } + +#ifdef EXPERIMENTAL_WIFI + + /* wifi mac access */ + if ((proc==ARMCPU_ARM7) && (adr>=0x04800000)&&(adr<0x05000000)) + { + WIFI_write16(&wifiMac,adr,val) ; + return ; + } +#else + if ((proc==ARMCPU_ARM7) && (adr>=0x04800000)&&(adr<0x05000000)) + return ; +#endif + + adr &= 0x0FFFFFFF; + + // This is bad, remove it + if(proc == ARMCPU_ARM7) + { + if ((adr>=0x04000400)&&(adr<0x0400051D)) + { + SPU_WriteWord(adr, val); + return; + } + } + + if((adr >> 24) == 4) + { + /* Adress is an IO register */ + switch(adr) + { +#if VIO2SF_GPU_ENABLE + case 0x0400035C: + { + ((u16 *)(MMU.MMU_MEM[proc][0x40]))[0x35C>>1] = val; + if(proc == ARMCPU_ARM9) + { + gpu3D->NDS_3D_FogOffset (val); + } + return; + } + case 0x04000340: + { + ((u16 *)(MMU.MMU_MEM[proc][0x40]))[0x340>>1] = val; + if(proc == ARMCPU_ARM9) + { + gpu3D->NDS_3D_AlphaFunc(val); + } + return; + } + case 0x04000060: + { + ((u16 *)(MMU.MMU_MEM[proc][0x40]))[0x060>>1] = val; + if(proc == ARMCPU_ARM9) + { + gpu3D->NDS_3D_Control(val); + } + return; + } + case 0x04000354: + { + ((u16 *)(MMU.MMU_MEM[proc][0x40]))[0x354>>1] = val; + if(proc == ARMCPU_ARM9) + { + gpu3D->NDS_3D_ClearDepth(val); + } + return; + } +#endif + + case REG_DISPA_BLDCNT: + if(proc == ARMCPU_ARM9) GPU_setBLDCNT(MainScreen.gpu,val) ; + break ; + case REG_DISPB_BLDCNT: + if(proc == ARMCPU_ARM9) GPU_setBLDCNT(SubScreen.gpu,val) ; + break ; + case REG_DISPA_BLDALPHA: + if(proc == ARMCPU_ARM9) GPU_setBLDALPHA(MainScreen.gpu,val) ; + break ; + case REG_DISPB_BLDALPHA: + if(proc == ARMCPU_ARM9) GPU_setBLDALPHA(SubScreen.gpu,val) ; + break ; + case REG_DISPA_BLDY: + if(proc == ARMCPU_ARM9) GPU_setBLDY_EVY(MainScreen.gpu,val) ; + break ; + case REG_DISPB_BLDY: + if(proc == ARMCPU_ARM9) GPU_setBLDY_EVY(SubScreen.gpu,val) ; + break; + case REG_DISPA_MASTERBRIGHT: + GPU_setMasterBrightness (MainScreen.gpu, val); + break; + /* + case REG_DISPA_MOSAIC: + if(proc == ARMCPU_ARM9) GPU_setMOSAIC(MainScreen.gpu,val) ; + break ; + case REG_DISPB_MOSAIC: + if(proc == ARMCPU_ARM9) GPU_setMOSAIC(SubScreen.gpu,val) ; + break ; + */ + + case REG_DISPA_WIN0H: + if(proc == ARMCPU_ARM9) GPU_setWIN0_H (MainScreen.gpu,val) ; + break ; + case REG_DISPA_WIN1H: + if(proc == ARMCPU_ARM9) GPU_setWIN1_H(MainScreen.gpu,val) ; + break ; + case REG_DISPB_WIN0H: + if(proc == ARMCPU_ARM9) GPU_setWIN0_H(SubScreen.gpu,val) ; + break ; + case REG_DISPB_WIN1H: + if(proc == ARMCPU_ARM9) GPU_setWIN1_H(SubScreen.gpu,val) ; + break ; + case REG_DISPA_WIN0V: + if(proc == ARMCPU_ARM9) GPU_setWIN0_V(MainScreen.gpu,val) ; + break ; + case REG_DISPA_WIN1V: + if(proc == ARMCPU_ARM9) GPU_setWIN1_V(MainScreen.gpu,val) ; + break ; + case REG_DISPB_WIN0V: + if(proc == ARMCPU_ARM9) GPU_setWIN0_V(SubScreen.gpu,val) ; + break ; + case REG_DISPB_WIN1V: + if(proc == ARMCPU_ARM9) GPU_setWIN1_V(SubScreen.gpu,val) ; + break ; + case REG_DISPA_WININ: + if(proc == ARMCPU_ARM9) GPU_setWININ(MainScreen.gpu, val) ; + break ; + case REG_DISPA_WINOUT: + if(proc == ARMCPU_ARM9) GPU_setWINOUT16(MainScreen.gpu, val) ; + break ; + case REG_DISPB_WININ: + if(proc == ARMCPU_ARM9) GPU_setWININ(SubScreen.gpu, val) ; + break ; + case REG_DISPB_WINOUT: + if(proc == ARMCPU_ARM9) GPU_setWINOUT16(SubScreen.gpu, val) ; + break ; + + case REG_DISPB_MASTERBRIGHT: + GPU_setMasterBrightness (SubScreen.gpu, val); + break; + + case REG_POWCNT1 : + if(proc == ARMCPU_ARM9) + { + if(val & (1<<15)) + { + LOG("Main core on top\n"); + MainScreen.offset = 0; + SubScreen.offset = 192; + //nds.swapScreen(); + } + else + { + LOG("Main core on bottom (%04X)\n", val); + MainScreen.offset = 192; + SubScreen.offset = 0; + } + } + T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x304, val); + return; + + case REG_AUXSPICNT: + T1WriteWord(MMU.MMU_MEM[proc][(REG_AUXSPICNT >> 20) & 0xff], REG_AUXSPICNT & 0xfff, val); + AUX_SPI_CNT = val; + + if (val == 0) + mc_reset_com(&MMU.bupmem); /* reset backup memory device communication */ + return; + + case REG_AUXSPIDATA: + if(val!=0) + { + AUX_SPI_CMD = val & 0xFF; + } + + T1WriteWord(MMU.MMU_MEM[proc][(REG_AUXSPIDATA >> 20) & 0xff], REG_AUXSPIDATA & 0xfff, bm_transfer(&MMU.bupmem, val)); + return; + + case REG_SPICNT : + if(proc == ARMCPU_ARM7) + { + int reset_firmware = 1; + + if ( ((SPI_CNT >> 8) & 0x3) == 1) { + if ( ((val >> 8) & 0x3) == 1) { + if ( BIT11(SPI_CNT)) { + /* select held */ + reset_firmware = 0; + } + } + } + + //MMU.fw.com == 0; /* reset fw device communication */ + if ( reset_firmware) { + /* reset fw device communication */ + mc_reset_com(&MMU.fw); + } + SPI_CNT = val; + } + + T1WriteWord(MMU.MMU_MEM[proc][(REG_SPICNT >> 20) & 0xff], REG_SPICNT & 0xfff, val); + return; + + case REG_SPIDATA : + if(proc==ARMCPU_ARM7) + { + u16 spicnt; + + if(val!=0) + { + SPI_CMD = val; + } + + spicnt = T1ReadWord(MMU.MMU_MEM[proc][(REG_SPICNT >> 20) & 0xff], REG_SPICNT & 0xfff); + + switch((spicnt >> 8) & 0x3) + { + case 0 : + break; + + case 1 : /* firmware memory device */ + if(spicnt & 0x3 != 0) /* check SPI baudrate (must be 4mhz) */ + { + T1WriteWord(MMU.MMU_MEM[proc][(REG_SPIDATA >> 20) & 0xff], REG_SPIDATA & 0xfff, 0); + break; + } + T1WriteWord(MMU.MMU_MEM[proc][(REG_SPIDATA >> 20) & 0xff], REG_SPIDATA & 0xfff, fw_transfer(&MMU.fw, val)); + + return; + + case 2 : + switch(SPI_CMD & 0x70) + { + case 0x00 : + val = 0; + break; + case 0x10 : + //execute = FALSE; + if(SPI_CNT&(1<<11)) + { + if(partie) + { + val = ((nds.touchY<<3)&0x7FF); + partie = 0; + //execute = FALSE; + break; + } + val = (nds.touchY>>5); + partie = 1; + break; + } + val = ((nds.touchY<<3)&0x7FF); + partie = 1; + break; + case 0x20 : + val = 0; + break; + case 0x30 : + val = 0; + break; + case 0x40 : + val = 0; + break; + case 0x50 : + if(spicnt & 0x800) + { + if(partie) + { + val = ((nds.touchX<<3)&0x7FF); + partie = 0; + break; + } + val = (nds.touchX>>5); + partie = 1; + break; + } + val = ((nds.touchX<<3)&0x7FF); + partie = 1; + break; + case 0x60 : + val = 0; + break; + case 0x70 : + val = 0; + break; + } + break; + + case 3 : + /* NOTICE: Device 3 of SPI is reserved (unused and unusable) */ + break; + } + } + + T1WriteWord(MMU.MMU_MEM[proc][(REG_SPIDATA >> 20) & 0xff], REG_SPIDATA & 0xfff, val); + return; + + /* NOTICE: Perhaps we have to use gbatek-like reg names instead of libnds-like ones ...*/ + + case REG_DISPA_BG0CNT : + //GPULOG("MAIN BG0 SETPROP 16B %08X\r\n", val); + if(proc == ARMCPU_ARM9) GPU_setBGProp(MainScreen.gpu, 0, val); + T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x8, val); + return; + case REG_DISPA_BG1CNT : + //GPULOG("MAIN BG1 SETPROP 16B %08X\r\n", val); + if(proc == ARMCPU_ARM9) GPU_setBGProp(MainScreen.gpu, 1, val); + T1WriteWord(MMU.MMU_MEM[proc][0x40], 0xA, val); + return; + case REG_DISPA_BG2CNT : + //GPULOG("MAIN BG2 SETPROP 16B %08X\r\n", val); + if(proc == ARMCPU_ARM9) GPU_setBGProp(MainScreen.gpu, 2, val); + T1WriteWord(MMU.MMU_MEM[proc][0x40], 0xC, val); + return; + case REG_DISPA_BG3CNT : + //GPULOG("MAIN BG3 SETPROP 16B %08X\r\n", val); + if(proc == ARMCPU_ARM9) GPU_setBGProp(MainScreen.gpu, 3, val); + T1WriteWord(MMU.MMU_MEM[proc][0x40], 0xE, val); + return; + case REG_DISPB_BG0CNT : + //GPULOG("SUB BG0 SETPROP 16B %08X\r\n", val); + if(proc == ARMCPU_ARM9) GPU_setBGProp(SubScreen.gpu, 0, val); + T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x1008, val); + return; + case REG_DISPB_BG1CNT : + //GPULOG("SUB BG1 SETPROP 16B %08X\r\n", val); + if(proc == ARMCPU_ARM9) GPU_setBGProp(SubScreen.gpu, 1, val); + T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x100A, val); + return; + case REG_DISPB_BG2CNT : + //GPULOG("SUB BG2 SETPROP 16B %08X\r\n", val); + if(proc == ARMCPU_ARM9) GPU_setBGProp(SubScreen.gpu, 2, val); + T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x100C, val); + return; + case REG_DISPB_BG3CNT : + //GPULOG("SUB BG3 SETPROP 16B %08X\r\n", val); + if(proc == ARMCPU_ARM9) GPU_setBGProp(SubScreen.gpu, 3, val); + T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x100E, val); + return; + case REG_IME : { + u32 old_val = MMU.reg_IME[proc]; + u32 new_val = val & 1; + MMU.reg_IME[proc] = new_val; + T1WriteLong(MMU.MMU_MEM[proc][0x40], 0x208, val); + if ( new_val && old_val != new_val) { + /* raise an interrupt request to the CPU if needed */ + if ( MMU.reg_IE[proc] & MMU.reg_IF[proc]) { + NDS_ARM7.wIRQ = TRUE; + NDS_ARM7.waitIRQ = FALSE; + } + } + return; + } + case REG_VRAMCNTA: + MMU_write8(proc,adr,val & 0xFF) ; + MMU_write8(proc,adr+1,val >> 8) ; + return ; + case REG_VRAMCNTC: + MMU_write8(proc,adr,val & 0xFF) ; + MMU_write8(proc,adr+1,val >> 8) ; + return ; + case REG_VRAMCNTE: + MMU_write8(proc,adr,val & 0xFF) ; + MMU_write8(proc,adr+1,val >> 8) ; + return ; + case REG_VRAMCNTG: + MMU_write8(proc,adr,val & 0xFF) ; + MMU_write8(proc,adr+1,val >> 8) ; + return ; + case REG_VRAMCNTI: + MMU_write8(proc,adr,val & 0xFF) ; + return ; + + case REG_IE : + MMU.reg_IE[proc] = (MMU.reg_IE[proc]&0xFFFF0000) | val; + if ( MMU.reg_IME[proc]) { + /* raise an interrupt request to the CPU if needed */ + if ( MMU.reg_IE[proc] & MMU.reg_IF[proc]) { + NDS_ARM7.wIRQ = TRUE; + NDS_ARM7.waitIRQ = FALSE; + } + } + return; + case REG_IE + 2 : + execute = FALSE; + MMU.reg_IE[proc] = (MMU.reg_IE[proc]&0xFFFF) | (((u32)val)<<16); + return; + + case REG_IF : + execute = FALSE; + MMU.reg_IF[proc] &= (~((u32)val)); + return; + case REG_IF + 2 : + execute = FALSE; + MMU.reg_IF[proc] &= (~(((u32)val)<<16)); + return; + + case REG_IPCSYNC : + { + u32 remote = (proc+1)&1; + u16 IPCSYNC_remote = T1ReadWord(MMU.MMU_MEM[remote][0x40], 0x180); + T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x180, (val&0xFFF0)|((IPCSYNC_remote>>8)&0xF)); + T1WriteWord(MMU.MMU_MEM[remote][0x40], 0x180, (IPCSYNC_remote&0xFFF0)|((val>>8)&0xF)); + MMU.reg_IF[remote] |= ((IPCSYNC_remote & (1<<14))<<2) & ((val & (1<<13))<<3);// & (MMU.reg_IME[remote] << 16);// & (MMU.reg_IE[remote] & (1<<16));// + //execute = FALSE; + } + return; + case REG_IPCFIFOCNT : + { + u32 cnt_l = T1ReadWord(MMU.MMU_MEM[proc][0x40], 0x184) ; + u32 cnt_r = T1ReadWord(MMU.MMU_MEM[(proc+1) & 1][0x40], 0x184) ; + if ((val & 0x8000) && !(cnt_l & 0x8000)) + { + /* this is the first init, the other side didnt init yet */ + /* so do a complete init */ + FIFOInit(MMU.fifos + (IPCFIFO+proc)); + T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x184,0x8101) ; + /* and then handle it as usual */ + } + + if(val & 0x4008) + { + FIFOInit(MMU.fifos + (IPCFIFO+((proc+1)&1))); + T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x184, (cnt_l & 0x0301) | (val & 0x8404) | 1); + T1WriteWord(MMU.MMU_MEM[proc^1][0x40], 0x184, (cnt_r & 0xC507) | 0x100); + MMU.reg_IF[proc] |= ((val & 4)<<15);// & (MMU.reg_IME[proc]<<17);// & (MMU.reg_IE[proc]&0x20000);// + return; + } + T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x184, T1ReadWord(MMU.MMU_MEM[proc][0x40], 0x184) | (val & 0xBFF4)); + } + return; + case REG_TM0CNTL : + case REG_TM1CNTL : + case REG_TM2CNTL : + case REG_TM3CNTL : + MMU.timerReload[proc][(adr>>2)&3] = val; + return; + case REG_TM0CNTH : + case REG_TM1CNTH : + case REG_TM2CNTH : + case REG_TM3CNTH : + if(val&0x80) + { + MMU.timer[proc][((adr-2)>>2)&0x3] = MMU.timerReload[proc][((adr-2)>>2)&0x3]; + } + MMU.timerON[proc][((adr-2)>>2)&0x3] = val & 0x80; + switch(val&7) + { + case 0 : + MMU.timerMODE[proc][((adr-2)>>2)&0x3] = 0+1;//proc; + break; + case 1 : + MMU.timerMODE[proc][((adr-2)>>2)&0x3] = 6+1;//proc; + break; + case 2 : + MMU.timerMODE[proc][((adr-2)>>2)&0x3] = 8+1;//proc; + break; + case 3 : + MMU.timerMODE[proc][((adr-2)>>2)&0x3] = 10+1;//proc; + break; + default : + MMU.timerMODE[proc][((adr-2)>>2)&0x3] = 0xFFFF; + break; + } + if(!(val & 0x80)) + MMU.timerRUN[proc][((adr-2)>>2)&0x3] = FALSE; + T1WriteWord(MMU.MMU_MEM[proc][0x40], adr & 0xFFF, val); + return; + case REG_DISPA_DISPCNT+2 : + { + //execute = FALSE; + u32 v = (T1ReadLong(MMU.MMU_MEM[proc][0x40], 0) & 0xFFFF) | ((u32) val << 16); + GPU_setVideoProp(MainScreen.gpu, v); + T1WriteLong(MMU.MMU_MEM[proc][0x40], 0, v); + } + return; + case REG_DISPA_DISPCNT : + if(proc == ARMCPU_ARM9) + { + u32 v = (T1ReadLong(MMU.MMU_MEM[proc][0x40], 0) & 0xFFFF0000) | val; + GPU_setVideoProp(MainScreen.gpu, v); + T1WriteLong(MMU.MMU_MEM[proc][0x40], 0, v); + } + return; + case REG_DISPA_DISPCAPCNT : + if(proc == ARMCPU_ARM9) + { + GPU_set_DISPCAPCNT(MainScreen.gpu,val); + } + return; + case REG_DISPB_DISPCNT+2 : + if(proc == ARMCPU_ARM9) + { + //execute = FALSE; + u32 v = (T1ReadLong(MMU.MMU_MEM[proc][0x40], 0x1000) & 0xFFFF) | ((u32) val << 16); + GPU_setVideoProp(SubScreen.gpu, v); + T1WriteLong(MMU.MMU_MEM[proc][0x40], 0x1000, v); + } + return; + case REG_DISPB_DISPCNT : + { + u32 v = (T1ReadLong(MMU.MMU_MEM[proc][0x40], 0x1000) & 0xFFFF0000) | val; + GPU_setVideoProp(SubScreen.gpu, v); + T1WriteLong(MMU.MMU_MEM[proc][0x40], 0x1000, v); + } + return; + //case 0x020D8460 : + /*case 0x0235A904 : + LOG("ECRIRE %d %04X\r\n", proc, val); + execute = FALSE;*/ + case REG_DMA0CNTH : + { + u32 v; + + //if(val&0x8000) execute = FALSE; + //LOG("16 bit dma0 %04X\r\n", val); + T1WriteWord(MMU.MMU_MEM[proc][0x40], 0xBA, val); + DMASrc[proc][0] = T1ReadLong(MMU.MMU_MEM[proc][0x40], 0xB0); + DMADst[proc][0] = T1ReadLong(MMU.MMU_MEM[proc][0x40], 0xB4); + v = T1ReadLong(MMU.MMU_MEM[proc][0x40], 0xB8); + MMU.DMAStartTime[proc][0] = (proc ? (v>>28) & 0x3 : (v>>27) & 0x7); + MMU.DMACrt[proc][0] = v; + if(MMU.DMAStartTime[proc][0] == 0) + MMU_doDMA(proc, 0); + #ifdef LOG_DMA2 + //else + { + LOG("proc %d, dma %d src %08X dst %08X %s\r\n", proc, 0, DMASrc[proc][0], DMADst[proc][0], (val&(1<<25))?"ON":"OFF"); + } + #endif + } + return; + case REG_DMA1CNTH : + { + u32 v; + //if(val&0x8000) execute = FALSE; + //LOG("16 bit dma1 %04X\r\n", val); + T1WriteWord(MMU.MMU_MEM[proc][0x40], 0xC6, val); + DMASrc[proc][1] = T1ReadLong(MMU.MMU_MEM[proc][0x40], 0xBC); + DMASrc[proc][1] = T1ReadLong(MMU.MMU_MEM[proc][0x40], 0xC0); + v = T1ReadLong(MMU.MMU_MEM[proc][0x40], 0xC4); + MMU.DMAStartTime[proc][1] = (proc ? (v>>28) & 0x3 : (v>>27) & 0x7); + MMU.DMACrt[proc][1] = v; + if(MMU.DMAStartTime[proc][1] == 0) + MMU_doDMA(proc, 1); + #ifdef LOG_DMA2 + //else + { + LOG("proc %d, dma %d src %08X dst %08X %s\r\n", proc, 1, DMASrc[proc][1], DMADst[proc][1], (val&(1<<25))?"ON":"OFF"); + } + #endif + } + return; + case REG_DMA2CNTH : + { + u32 v; + //if(val&0x8000) execute = FALSE; + //LOG("16 bit dma2 %04X\r\n", val); + T1WriteWord(MMU.MMU_MEM[proc][0x40], 0xD2, val); + DMASrc[proc][2] = T1ReadLong(MMU.MMU_MEM[proc][0x40], 0xC8); + DMASrc[proc][2] = T1ReadLong(MMU.MMU_MEM[proc][0x40], 0xCC); + v = T1ReadLong(MMU.MMU_MEM[proc][0x40], 0xD0); + MMU.DMAStartTime[proc][2] = (proc ? (v>>28) & 0x3 : (v>>27) & 0x7); + MMU.DMACrt[proc][2] = v; + if(MMU.DMAStartTime[proc][2] == 0) + MMU_doDMA(proc, 2); + #ifdef LOG_DMA2 + //else + { + LOG("proc %d, dma %d src %08X dst %08X %s\r\n", proc, 2, DMASrc[proc][2], DMADst[proc][2], (val&(1<<25))?"ON":"OFF"); + } + #endif + } + return; + case REG_DMA3CNTH : + { + u32 v; + //if(val&0x8000) execute = FALSE; + //LOG("16 bit dma3 %04X\r\n", val); + T1WriteWord(MMU.MMU_MEM[proc][0x40], 0xDE, val); + DMASrc[proc][3] = T1ReadLong(MMU.MMU_MEM[proc][0x40], 0xD4); + DMASrc[proc][3] = T1ReadLong(MMU.MMU_MEM[proc][0x40], 0xD8); + v = T1ReadLong(MMU.MMU_MEM[proc][0x40], 0xDC); + MMU.DMAStartTime[proc][3] = (proc ? (v>>28) & 0x3 : (v>>27) & 0x7); + MMU.DMACrt[proc][3] = v; + + if(MMU.DMAStartTime[proc][3] == 0) + MMU_doDMA(proc, 3); + #ifdef LOG_DMA2 + //else + { + LOG("proc %d, dma %d src %08X dst %08X %s\r\n", proc, 3, DMASrc[proc][3], DMADst[proc][3], (val&(1<<25))?"ON":"OFF"); + } + #endif + } + return; + //case REG_AUXSPICNT : execute = FALSE; + default : + T1WriteWord(MMU.MMU_MEM[proc][0x40], adr&MMU.MMU_MASK[proc][(adr>>20)&0xFF], val); + return; + } + } + T1WriteWord(MMU.MMU_MEM[proc][(adr>>20)&0xFF], adr&MMU.MMU_MASK[proc][(adr>>20)&0xFF], val); +} + + +void FASTCALL MMU_write32(u32 proc, u32 adr, u32 val) +{ +#ifdef INTERNAL_DTCM_WRITE + if((proc==ARMCPU_ARM9)&((adr&(~0x3FFF))==MMU.DTCMRegion)) + { + T1WriteLong(ARM9Mem.ARM9_DTCM, adr & 0x3FFF, val); + return ; + } +#endif + + // CFlash writing, Mic + if ((adr>=0x9000000)&&(adr<0x9900000)) { + cflash_write(adr,val); + return; + } + + adr &= 0x0FFFFFFF; + + // This is bad, remove it + if(proc == ARMCPU_ARM7) + { + if ((adr>=0x04000400)&&(adr<0x0400051D)) + { + SPU_WriteLong(adr, val); + return; + } + } + + if (adr & 0xFF800000 == 0x04800000) { + /* access to non regular hw registers */ + /* return to not overwrite valid data */ + return ; + } ; + + + if((adr>>24)==4) + { + if (adr >= 0x04000400 && adr < 0x04000440) + { + // Geometry commands (aka Dislay Lists) - Parameters:X + ((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x400>>2] = val; +#if VIO2SF_GPU_ENABLE + if(proc==ARMCPU_ARM9) + { + gpu3D->NDS_3D_CallList(val); + } +#endif + } + else + switch(adr) + { +#if VIO2SF_GPU_ENABLE + // Alpha test reference value - Parameters:1 + case 0x04000340: + { + ((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x340>>2] = val; + if(proc == ARMCPU_ARM9) + { + gpu3D->NDS_3D_AlphaFunc(val); + } + return; + } + // Clear background color setup - Parameters:2 + case 0x04000350: + { + ((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x350>>2] = val; + if(proc == ARMCPU_ARM9) + { + gpu3D->NDS_3D_ClearColor(val); + } + return; + } + // Clear background depth setup - Parameters:2 + case 0x04000354: + { + ((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x354>>2] = val; + if(proc == ARMCPU_ARM9) + { + gpu3D->NDS_3D_ClearDepth(val); + } + return; + } + // Fog Color - Parameters:4b + case 0x04000358: + { + ((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x358>>2] = val; + if(proc == ARMCPU_ARM9) + { + gpu3D->NDS_3D_FogColor(val); + } + return; + } + case 0x0400035C: + { + ((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x35C>>2] = val; + if(proc == ARMCPU_ARM9) + { + gpu3D->NDS_3D_FogOffset(val); + } + return; + } + // Matrix mode - Parameters:1 + case 0x04000440: + { + ((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x440>>2] = val; + + if(proc == ARMCPU_ARM9) + { + gpu3D->NDS_3D_MatrixMode(val); + } + return; + } + // Push matrix - Parameters:0 + case 0x04000444: + { + ((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x444>>2] = val; + if(proc == ARMCPU_ARM9) + { + gpu3D->NDS_3D_PushMatrix(); + } + return; + } + // Pop matrix/es - Parameters:1 + case 0x04000448: + { + ((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x448>>2] = val; + if(proc == ARMCPU_ARM9) + { + gpu3D->NDS_3D_PopMatrix(val); + } + return; + } + // Store matrix in the stack - Parameters:1 + case 0x0400044C: + { + ((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x44C>>2] = val; + if(proc == ARMCPU_ARM9) + { + gpu3D->NDS_3D_StoreMatrix(val); + } + return; + } + // Restore matrix from the stack - Parameters:1 + case 0x04000450: + { + ((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x450>>2] = val; + if(proc == ARMCPU_ARM9) + { + gpu3D->NDS_3D_RestoreMatrix(val); + } + return; + } + // Load Identity matrix - Parameters:0 + case 0x04000454: + { + ((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x454>>2] = val; + if(proc == ARMCPU_ARM9) + { + gpu3D->NDS_3D_LoadIdentity(); + } + return; + } + // Load 4x4 matrix - Parameters:16 + case 0x04000458: + { + ((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x458>>2] = val; + if(proc == ARMCPU_ARM9) + { + gpu3D->NDS_3D_LoadMatrix4x4(val); + } + return; + } + // Load 4x3 matrix - Parameters:12 + case 0x0400045C: + { + ((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x45C>>2] = val; + if(proc == ARMCPU_ARM9) + { + gpu3D->NDS_3D_LoadMatrix4x3(val); + } + return; + } + // Multiply 4x4 matrix - Parameters:16 + case 0x04000460: + { + ((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x460>>2] = val; + if(proc == ARMCPU_ARM9) + { + gpu3D->NDS_3D_MultMatrix4x4(val); + } + return; + } + // Multiply 4x4 matrix - Parameters:12 + case 0x04000464: + { + ((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x464>>2] = val; + if(proc == ARMCPU_ARM9) + { + gpu3D->NDS_3D_MultMatrix4x3(val); + } + return; + } + // Multiply 3x3 matrix - Parameters:9 + case 0x04000468 : + { + ((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x468>>2] = val; + if(proc == ARMCPU_ARM9) + { + gpu3D->NDS_3D_MultMatrix3x3(val); + } + return; + } + // Multiply current matrix by scaling matrix - Parameters:3 + case 0x0400046C: + { + ((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x46C>>2] = val; + if(proc==ARMCPU_ARM9) + { + gpu3D->NDS_3D_Scale(val); + } + return; + } + // Multiply current matrix by translation matrix - Parameters:3 + case 0x04000470: + { + ((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x470>>2] = val; + if(proc == ARMCPU_ARM9) + { + gpu3D->NDS_3D_Translate(val); + } + return; + } + // Set vertex color - Parameters:1 + case 0x04000480: + { + ((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x480>>2] = val; + if(proc == ARMCPU_ARM9) + { + gpu3D->NDS_3D_Color3b(val); + } + return; + } + // Set vertex normal - Parameters:1 + case 0x04000484: + { + ((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x484>>2] = val; + if(proc == ARMCPU_ARM9) + { + gpu3D->NDS_3D_Normal(val); + } + return; + } + // Set vertex texture coordinate - Parameters:1 + case 0x04000488: + { + ((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x488>>2] = val; + if(proc==ARMCPU_ARM9) + { + gpu3D->NDS_3D_TexCoord(val); + } + return; + } + // Set vertex position 16b/coordinate - Parameters:2 + case 0x0400048C: + { + ((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x48C>>2] = val; + if(proc == ARMCPU_ARM9) + { + gpu3D->NDS_3D_Vertex16b(val); + } + return; + } + // Set vertex position 10b/coordinate - Parameters:1 + case 0x04000490: + { + ((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x490>>2] = val; + if(proc == ARMCPU_ARM9) + { + gpu3D->NDS_3D_Vertex10b(val); + } + return; + } + // Set vertex XY position - Parameters:1 + case 0x04000494: + { + ((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x494>>2] = val; + if(proc==ARMCPU_ARM9) + { + gpu3D->NDS_3D_Vertex3_cord(0,1,val); + } + return; + } + // Set vertex XZ position - Parameters:1 + case 0x04000498: + { + ((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x498>>2] = val; + if(proc==ARMCPU_ARM9) + { + gpu3D->NDS_3D_Vertex3_cord(0,2,val); + } + return; + } + // Set vertex YZ position - Parameters:1 + case 0x0400049C: + { + ((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x49C>>2] = val; + if(proc==ARMCPU_ARM9) + { + gpu3D->NDS_3D_Vertex3_cord(1,2,val); + } + return; + } + // Set vertex difference position (offset from the last vertex) - Parameters:1 + case 0x040004A0: + { + ((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x4A0>>2] = val; + if(proc==ARMCPU_ARM9) + { + gpu3D->NDS_3D_Vertex_rel (val); + } + return; + } + // Set polygon attributes - Parameters:1 + case 0x040004A4: + { + ((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x4A4>>2] = val; + if(proc == ARMCPU_ARM9) + { + gpu3D->NDS_3D_PolygonAttrib(val); + } + return; + } + // Set texture parameteres - Parameters:1 + case 0x040004A8: + { + ((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x4A8>>2] = val; + if(proc==ARMCPU_ARM9) + { + gpu3D->NDS_3D_TexImage(val); + } + return; + } + // Set palette base address - Parameters:1 + case 0x040004AC: + { + ((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x4AC>>2] = val&0x1FFF; + if(proc==ARMCPU_ARM9) + { + gpu3D->NDS_3D_TexPalette(val&0x1FFFF); + } + return; + } + // Set material diffuse/ambient parameters - Parameters:1 + case 0x040004C0: + { + ((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x4C0>>2] = val; + if(proc == ARMCPU_ARM9) + { + gpu3D->NDS_3D_Material0 (val); + } + return; + } + // Set material reflection/emission parameters - Parameters:1 + case 0x040004C4: + { + ((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x4C4>>2] = val; + if(proc == ARMCPU_ARM9) + { + gpu3D->NDS_3D_Material1 (val); + } + return; + } + // Light direction vector - Parameters:1 + case 0x040004C8: + { + ((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x4C8>>2] = val; + if(proc == ARMCPU_ARM9) + { + gpu3D->NDS_3D_LightDirection (val); + } + return; + } + // Light color - Parameters:1 + case 0x040004CC: + { + ((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x4CC>>2] = val; + if(proc == ARMCPU_ARM9) + { + gpu3D->NDS_3D_LightColor(val); + } + return; + } + // Material Shininess - Parameters:32 + case 0x040004D0: + { + ((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x4D0>>2] = val; + if(proc == ARMCPU_ARM9) + { + gpu3D->NDS_3D_Shininess(val); + } + return; + } + // Begin vertex list - Parameters:1 + case 0x04000500: + { + ((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x500>>2] = val; + if(proc == ARMCPU_ARM9) + { + gpu3D->NDS_3D_Begin(val); + } + return; + } + // End vertex list - Parameters:0 + case 0x04000504: + { + ((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x504>>2] = val; + if(proc == ARMCPU_ARM9) + { + gpu3D->NDS_3D_End(); + } + return; + } + // Swap rendering engine buffers - Parameters:1 + case 0x04000540: + { + ((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x540>>2] = val; + if(proc == ARMCPU_ARM9) + { + gpu3D->NDS_3D_Flush(val); + } + return; + } + // Set viewport coordinates - Parameters:1 + case 0x04000580: + { + ((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x580>>2] = val; + if(proc == ARMCPU_ARM9) + { + gpu3D->NDS_3D_ViewPort(val); + } + return; + } +#endif + + case REG_DISPA_WININ: + { + if(proc == ARMCPU_ARM9) + { + GPU_setWININ (MainScreen.gpu, val & 0xFFFF) ; + GPU_setWINOUT16 (MainScreen.gpu, (val >> 16) & 0xFFFF) ; + } + break; + } + case REG_DISPB_WININ: + { + if(proc == ARMCPU_ARM9) + { + GPU_setWININ (SubScreen.gpu, val & 0xFFFF) ; + GPU_setWINOUT16 (SubScreen.gpu, (val >> 16) & 0xFFFF) ; + } + break; + } + + case REG_DISPA_BLDCNT: + { + if (proc == ARMCPU_ARM9) + { + GPU_setBLDCNT (MainScreen.gpu,val&0xffff); + GPU_setBLDALPHA (MainScreen.gpu,val>>16); + } + break; + } + case REG_DISPB_BLDCNT: + { + if (proc == ARMCPU_ARM9) + { + GPU_setBLDCNT (SubScreen.gpu,val&0xffff); + GPU_setBLDALPHA (SubScreen.gpu,val>>16); + } + break; + } +/* + // Commented out, as this doesn't use the plug-in system, neither works + case cmd_3D_MTX_MODE // 0x04000440 : + if (proc == ARMCPU_ARM9) gl_MTX_MODE(val); + return; + case cmd_3D_MTX_PUSH // 0x04000444 : + case cmd_3D_MTX_POP // 0x04000448 : + case cmd_3D_MTX_STORE // 0x0400044C : + case cmd_3D_MTX_RESTORE // 0x04000450 : + if (proc == ARMCPU_ARM9) gl_print_cmd(adr); + return; + case cmd_3D_MTX_IDENTITY // 0x04000454 : + if (proc == ARMCPU_ARM9) gl_MTX_IDENTITY(); + return; + case cmd_3D_MTX_LOAD_4x4 // 0x04000458 : + if (proc == ARMCPU_ARM9) gl_MTX_LOAD_4x4(val); + return; + case cmd_3D_MTX_LOAD_4x3 // 0x0400045C : + if (proc == ARMCPU_ARM9) gl_MTX_LOAD_4x3(val); + return; + case cmd_3D_MTX_MULT_4x4 // 0x04000460 : + if (proc == ARMCPU_ARM9) gl_MTX_MULT_4x4(val); + return; + case cmd_3D_MTX_MULT_4x3 // 0x04000464 : + if (proc == ARMCPU_ARM9) gl_MTX_MULT_4x3(val); + return; + case cmd_3D_MTX_MULT_3x3 // 0x04000468 : + if (proc == ARMCPU_ARM9) gl_MTX_MULT_3x3(val); + return; + case cmd_3D_MTX_SCALE // 0x0400046C : + case cmd_3D_MTX_TRANS // 0x04000470 : + case cmd_3D_COLOR // 0x04000480 : + case cmd_3D_NORMA // 0x04000484 : + if (proc == ARMCPU_ARM9) gl_print_cmd(adr); + return; + case cmd_3D_TEXCOORD // 0x04000488 : + if (proc == ARMCPU_ARM9) gl_TEXCOORD(val); + return; + case cmd_3D_VTX_16 // 0x0400048C : + if (proc == ARMCPU_ARM9) gl_VTX_16(val); + return; + case cmd_3D_VTX_10 // 0x04000490 : + if (proc == ARMCPU_ARM9) gl_VTX_10(val); + return; + case cmd_3D_VTX_XY // 0x04000494 : + if (proc == ARMCPU_ARM9) gl_VTX_XY(val); + return; + case cmd_3D_VTX_XZ // 0x04000498 : + if (proc == ARMCPU_ARM9) gl_VTX_XZ(val); + return; + case cmd_3D_VTX_YZ // 0x0400049C : + if (proc == ARMCPU_ARM9) gl_VTX_YZ(val); + return; + case cmd_3D_VTX_DIFF // 0x040004A0 : + if (proc == ARMCPU_ARM9) gl_VTX_DIFF(val); + return; + case cmd_3D_POLYGON_ATTR // 0x040004A4 : + case cmd_3D_TEXIMAGE_PARAM // 0x040004A8 : + case cmd_3D_PLTT_BASE // 0x040004AC : + case cmd_3D_DIF_AMB // 0x040004C0 : + case cmd_3D_SPE_EMI // 0x040004C4 : + case cmd_3D_LIGHT_VECTOR // 0x040004C8 : + case cmd_3D_LIGHT_COLOR // 0x040004CC : + case cmd_3D_SHININESS // 0x040004D0 : + if (proc == ARMCPU_ARM9) gl_print_cmd(adr); + return; + case cmd_3D_BEGIN_VTXS // 0x04000500 : + if (proc == ARMCPU_ARM9) gl_VTX_begin(val); + return; + case cmd_3D_END_VTXS // 0x04000504 : + if (proc == ARMCPU_ARM9) gl_VTX_end(); + return; + case cmd_3D_SWAP_BUFFERS // 0x04000540 : + case cmd_3D_VIEWPORT // 0x04000580 : + case cmd_3D_BOX_TEST // 0x040005C0 : + case cmd_3D_POS_TEST // 0x040005C4 : + case cmd_3D_VEC_TEST // 0x040005C8 : + if (proc == ARMCPU_ARM9) gl_print_cmd(adr); + return; +*/ + case REG_DISPA_DISPCNT : + if(proc == ARMCPU_ARM9) GPU_setVideoProp(MainScreen.gpu, val); + + //GPULOG("MAIN INIT 32B %08X\r\n", val); + T1WriteLong(MMU.MMU_MEM[proc][0x40], 0, val); + return; + + case REG_DISPB_DISPCNT : + if (proc == ARMCPU_ARM9) GPU_setVideoProp(SubScreen.gpu, val); + //GPULOG("SUB INIT 32B %08X\r\n", val); + T1WriteLong(MMU.MMU_MEM[proc][0x40], 0x1000, val); + return; + case REG_VRAMCNTA: + case REG_VRAMCNTE: + MMU_write8(proc,adr,val & 0xFF) ; + MMU_write8(proc,adr+1,val >> 8) ; + MMU_write8(proc,adr+2,val >> 16) ; + MMU_write8(proc,adr+3,val >> 24) ; + return ; + case REG_VRAMCNTI: + MMU_write8(proc,adr,val & 0xFF) ; + return ; + + case REG_IME : { + u32 old_val = MMU.reg_IME[proc]; + u32 new_val = val & 1; + MMU.reg_IME[proc] = new_val; + T1WriteLong(MMU.MMU_MEM[proc][0x40], 0x208, val); + if ( new_val && old_val != new_val) { + /* raise an interrupt request to the CPU if needed */ + if ( MMU.reg_IE[proc] & MMU.reg_IF[proc]) { + NDS_ARM7.wIRQ = TRUE; + NDS_ARM7.waitIRQ = FALSE; + } + } + return; + } + + case REG_IE : + MMU.reg_IE[proc] = val; + if ( MMU.reg_IME[proc]) { + /* raise an interrupt request to the CPU if needed */ + if ( MMU.reg_IE[proc] & MMU.reg_IF[proc]) { + NDS_ARM7.wIRQ = TRUE; + NDS_ARM7.waitIRQ = FALSE; + } + } + return; + + case REG_IF : + MMU.reg_IF[proc] &= (~val); + return; + case REG_TM0CNTL : + case REG_TM1CNTL : + case REG_TM2CNTL : + case REG_TM3CNTL : + MMU.timerReload[proc][(adr>>2)&0x3] = (u16)val; + if(val&0x800000) + { + MMU.timer[proc][(adr>>2)&0x3] = MMU.timerReload[proc][(adr>>2)&0x3]; + } + MMU.timerON[proc][(adr>>2)&0x3] = val & 0x800000; + switch((val>>16)&7) + { + case 0 : + MMU.timerMODE[proc][(adr>>2)&0x3] = 0+1;//proc; + break; + case 1 : + MMU.timerMODE[proc][(adr>>2)&0x3] = 6+1;//proc; + break; + case 2 : + MMU.timerMODE[proc][(adr>>2)&0x3] = 8+1;//proc; + break; + case 3 : + MMU.timerMODE[proc][(adr>>2)&0x3] = 10+1;//proc; + break; + default : + MMU.timerMODE[proc][(adr>>2)&0x3] = 0xFFFF; + break; + } + if(!(val & 0x800000)) + { + MMU.timerRUN[proc][(adr>>2)&0x3] = FALSE; + } + T1WriteLong(MMU.MMU_MEM[proc][0x40], adr & 0xFFF, val); + return; + case REG_DIVDENOM : + { + u16 cnt; + s64 num = 0; + s64 den = 1; + s64 res; + s64 mod; + T1WriteLong(MMU.MMU_MEM[proc][0x40], 0x298, val); + cnt = T1ReadWord(MMU.MMU_MEM[proc][0x40], 0x280); + switch(cnt&3) + { + case 0: + { + num = (s64) (s32) T1ReadLong(MMU.MMU_MEM[proc][0x40], 0x290); + den = (s64) (s32) T1ReadLong(MMU.MMU_MEM[proc][0x40], 0x298); + } + break; + case 1: + { + num = (s64) T1ReadQuad(MMU.MMU_MEM[proc][0x40], 0x290); + den = (s64) (s32) T1ReadLong(MMU.MMU_MEM[proc][0x40], 0x298); + } + break; + case 2: + { + return; + } + break; + default: + break; + } + if(den==0) + { + res = 0; + mod = 0; + cnt |= 0x4000; + cnt &= 0x7FFF; + } + else + { + res = num / den; + mod = num % den; + cnt &= 0x3FFF; + } + DIVLOG("BOUT1 %08X%08X / %08X%08X = %08X%08X\r\n", (u32)(num>>32), (u32)num, + (u32)(den>>32), (u32)den, + (u32)(res>>32), (u32)res); + T1WriteLong(MMU.MMU_MEM[proc][0x40], 0x2A0, (u32) res); + T1WriteLong(MMU.MMU_MEM[proc][0x40], 0x2A4, (u32) (res >> 32)); + T1WriteLong(MMU.MMU_MEM[proc][0x40], 0x2A8, (u32) mod); + T1WriteLong(MMU.MMU_MEM[proc][0x40], 0x2AC, (u32) (mod >> 32)); + T1WriteLong(MMU.MMU_MEM[proc][0x40], 0x280, cnt); + } + return; + case REG_DIVDENOM+4 : + { + u16 cnt; + s64 num = 0; + s64 den = 1; + s64 res; + s64 mod; + T1WriteLong(MMU.MMU_MEM[proc][0x40], 0x29C, val); + cnt = T1ReadWord(MMU.MMU_MEM[proc][0x40], 0x280); + switch(cnt&3) + { + case 0: + { + return; + } + break; + case 1: + { + return; + } + break; + case 2: + { + num = (s64) T1ReadQuad(MMU.MMU_MEM[proc][0x40], 0x290); + den = (s64) T1ReadQuad(MMU.MMU_MEM[proc][0x40], 0x298); + } + break; + default: + break; + } + if(den==0) + { + res = 0; + mod = 0; + cnt |= 0x4000; + cnt &= 0x7FFF; + } + else + { + res = num / den; + mod = num % den; + cnt &= 0x3FFF; + } + DIVLOG("BOUT2 %08X%08X / %08X%08X = %08X%08X\r\n", (u32)(num>>32), (u32)num, + (u32)(den>>32), (u32)den, + (u32)(res>>32), (u32)res); + T1WriteLong(MMU.MMU_MEM[proc][0x40], 0x2A0, (u32) res); + T1WriteLong(MMU.MMU_MEM[proc][0x40], 0x2A4, (u32) (res >> 32)); + T1WriteLong(MMU.MMU_MEM[proc][0x40], 0x2A8, (u32) mod); + T1WriteLong(MMU.MMU_MEM[proc][0x40], 0x2AC, (u32) (mod >> 32)); + T1WriteLong(MMU.MMU_MEM[proc][0x40], 0x280, cnt); + } + return; + case REG_SQRTPARAM : + { + u16 cnt; + u64 v = 1; + //execute = FALSE; + T1WriteLong(MMU.MMU_MEM[proc][0x40], 0x2B8, val); + cnt = T1ReadWord(MMU.MMU_MEM[proc][0x40], 0x2B0); + switch(cnt&1) + { + case 0: + v = (u64) T1ReadLong(MMU.MMU_MEM[proc][0x40], 0x2B8); + break; + case 1: + return; + } + T1WriteLong(MMU.MMU_MEM[proc][0x40], 0x2B4, (u32) sqrt((s64)v)); + T1WriteLong(MMU.MMU_MEM[proc][0x40], 0x2B0, cnt & 0x7FFF); + SQRTLOG("BOUT1 sqrt(%08X%08X) = %08X\r\n", (u32)(v>>32), (u32)v, + T1ReadLong(MMU.MMU_MEM[proc][0x40], 0x2B4)); + } + return; + case REG_SQRTPARAM+4 : + { + u16 cnt; + u64 v = 1; + T1WriteLong(MMU.MMU_MEM[proc][0x40], 0x2BC, val); + cnt = T1ReadWord(MMU.MMU_MEM[proc][0x40], 0x2B0); + switch(cnt&1) + { + case 0: + return; + //break; + case 1: + v = T1ReadQuad(MMU.MMU_MEM[proc][0x40], 0x2B8); + break; + } + T1WriteLong(MMU.MMU_MEM[proc][0x40], 0x2B4, (u32) sqrt((s64)v)); + T1WriteLong(MMU.MMU_MEM[proc][0x40], 0x2B0, cnt & 0x7FFF); + SQRTLOG("BOUT2 sqrt(%08X%08X) = %08X\r\n", (u32)(v>>32), (u32)v, + T1ReadLong(MMU.MMU_MEM[proc][0x40], 0x2B4)); + } + return; + case REG_IPCSYNC : + { + //execute=FALSE; + u32 remote = (proc+1)&1; + u32 IPCSYNC_remote = T1ReadLong(MMU.MMU_MEM[remote][0x40], 0x180); + T1WriteLong(MMU.MMU_MEM[proc][0x40], 0x180, (val&0xFFF0)|((IPCSYNC_remote>>8)&0xF)); + T1WriteLong(MMU.MMU_MEM[remote][0x40], 0x180, (IPCSYNC_remote&0xFFF0)|((val>>8)&0xF)); + MMU.reg_IF[remote] |= ((IPCSYNC_remote & (1<<14))<<2) & ((val & (1<<13))<<3);// & (MMU.reg_IME[remote] << 16);// & (MMU.reg_IE[remote] & (1<<16));// + } + return; + case REG_IPCFIFOCNT : + { + u32 cnt_l = T1ReadWord(MMU.MMU_MEM[proc][0x40], 0x184) ; + u32 cnt_r = T1ReadWord(MMU.MMU_MEM[(proc+1) & 1][0x40], 0x184) ; + if ((val & 0x8000) && !(cnt_l & 0x8000)) + { + /* this is the first init, the other side didnt init yet */ + /* so do a complete init */ + FIFOInit(MMU.fifos + (IPCFIFO+proc)); + T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x184,0x8101) ; + /* and then handle it as usual */ + } + if(val & 0x4008) + { + FIFOInit(MMU.fifos + (IPCFIFO+((proc+1)&1))); + T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x184, (cnt_l & 0x0301) | (val & 0x8404) | 1); + T1WriteWord(MMU.MMU_MEM[proc^1][0x40], 0x184, (cnt_r & 0xC507) | 0x100); + MMU.reg_IF[proc] |= ((val & 4)<<15);// & (MMU.reg_IME[proc]<<17);// & (MMU.reg_IE[proc]&0x20000);// + return; + } + T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x184, val & 0xBFF4); + //execute = FALSE; + return; + } + case REG_IPCFIFOSEND : + { + u16 IPCFIFO_CNT = T1ReadWord(MMU.MMU_MEM[proc][0x40], 0x184); + if(IPCFIFO_CNT&0x8000) + { + //if(val==43) execute = FALSE; + u32 remote = (proc+1)&1; + u32 fifonum = IPCFIFO+remote; + u16 IPCFIFO_CNT_remote; + FIFOAdd(MMU.fifos + fifonum, val); + IPCFIFO_CNT = (IPCFIFO_CNT & 0xFFFC) | (MMU.fifos[fifonum].full<<1); + IPCFIFO_CNT_remote = T1ReadWord(MMU.MMU_MEM[remote][0x40], 0x184); + IPCFIFO_CNT_remote = (IPCFIFO_CNT_remote & 0xFCFF) | (MMU.fifos[fifonum].full<<10); + T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x184, IPCFIFO_CNT); + T1WriteWord(MMU.MMU_MEM[remote][0x40], 0x184, IPCFIFO_CNT_remote); + MMU.reg_IF[remote] |= ((IPCFIFO_CNT_remote & (1<<10))<<8);// & (MMU.reg_IME[remote] << 18);// & (MMU.reg_IE[remote] & 0x40000);// + //execute = FALSE; + } + } + return; + case REG_DMA0CNTL : + //LOG("32 bit dma0 %04X\r\n", val); + DMASrc[proc][0] = T1ReadLong(MMU.MMU_MEM[proc][0x40], 0xB0); + DMADst[proc][0] = T1ReadLong(MMU.MMU_MEM[proc][0x40], 0xB4); + MMU.DMAStartTime[proc][0] = (proc ? (val>>28) & 0x3 : (val>>27) & 0x7); + MMU.DMACrt[proc][0] = val; + T1WriteLong(MMU.MMU_MEM[proc][0x40], 0xB8, val); + if( MMU.DMAStartTime[proc][0] == 0 || + MMU.DMAStartTime[proc][0] == 7) // Start Immediately + MMU_doDMA(proc, 0); + #ifdef LOG_DMA2 + else + { + LOG("proc %d, dma %d src %08X dst %08X start taille %d %d\r\n", proc, 0, DMASrc[proc][0], DMADst[proc][0], 0, ((MMU.DMACrt[proc][0]>>27)&7)); + } + #endif + //execute = FALSE; + return; + case REG_DMA1CNTL: + //LOG("32 bit dma1 %04X\r\n", val); + DMASrc[proc][1] = T1ReadLong(MMU.MMU_MEM[proc][0x40], 0xBC); + DMADst[proc][1] = T1ReadLong(MMU.MMU_MEM[proc][0x40], 0xC0); + MMU.DMAStartTime[proc][1] = (proc ? (val>>28) & 0x3 : (val>>27) & 0x7); + MMU.DMACrt[proc][1] = val; + T1WriteLong(MMU.MMU_MEM[proc][0x40], 0xC4, val); + if(MMU.DMAStartTime[proc][1] == 0 || + MMU.DMAStartTime[proc][1] == 7) // Start Immediately + MMU_doDMA(proc, 1); + #ifdef LOG_DMA2 + else + { + LOG("proc %d, dma %d src %08X dst %08X start taille %d %d\r\n", proc, 1, DMASrc[proc][1], DMADst[proc][1], 0, ((MMU.DMACrt[proc][1]>>27)&7)); + } + #endif + return; + case REG_DMA2CNTL : + //LOG("32 bit dma2 %04X\r\n", val); + DMASrc[proc][2] = T1ReadLong(MMU.MMU_MEM[proc][0x40], 0xC8); + DMADst[proc][2] = T1ReadLong(MMU.MMU_MEM[proc][0x40], 0xCC); + MMU.DMAStartTime[proc][2] = (proc ? (val>>28) & 0x3 : (val>>27) & 0x7); + MMU.DMACrt[proc][2] = val; + T1WriteLong(MMU.MMU_MEM[proc][0x40], 0xD0, val); + if(MMU.DMAStartTime[proc][2] == 0 || + MMU.DMAStartTime[proc][2] == 7) // Start Immediately + MMU_doDMA(proc, 2); + #ifdef LOG_DMA2 + else + { + LOG("proc %d, dma %d src %08X dst %08X start taille %d %d\r\n", proc, 2, DMASrc[proc][2], DMADst[proc][2], 0, ((MMU.DMACrt[proc][2]>>27)&7)); + } + #endif + return; + case 0x040000DC : + //LOG("32 bit dma3 %04X\r\n", val); + DMASrc[proc][3] = T1ReadLong(MMU.MMU_MEM[proc][0x40], 0xD4); + DMADst[proc][3] = T1ReadLong(MMU.MMU_MEM[proc][0x40], 0xD8); + MMU.DMAStartTime[proc][3] = (proc ? (val>>28) & 0x3 : (val>>27) & 0x7); + MMU.DMACrt[proc][3] = val; + T1WriteLong(MMU.MMU_MEM[proc][0x40], 0xDC, val); + if( MMU.DMAStartTime[proc][3] == 0 || + MMU.DMAStartTime[proc][3] == 7) // Start Immediately + MMU_doDMA(proc, 3); + #ifdef LOG_DMA2 + else + { + LOG("proc %d, dma %d src %08X dst %08X start taille %d %d\r\n", proc, 3, DMASrc[proc][3], DMADst[proc][3], 0, ((MMU.DMACrt[proc][3]>>27)&7)); + } + #endif + return; + case REG_GCROMCTRL : + { + int i; + + if(MEM_8(MMU.MMU_MEM[proc], REG_GCCMDOUT) == 0xB7) + { + MMU.dscard[proc].adress = (MEM_8(MMU.MMU_MEM[proc], REG_GCCMDOUT+1) << 24) | (MEM_8(MMU.MMU_MEM[proc], REG_GCCMDOUT+2) << 16) | (MEM_8(MMU.MMU_MEM[proc], REG_GCCMDOUT+3) << 8) | (MEM_8(MMU.MMU_MEM[proc], REG_GCCMDOUT+4)); + MMU.dscard[proc].transfer_count = 0x80;// * ((val>>24)&7)); + } + else if (MEM_8(MMU.MMU_MEM[proc], REG_GCCMDOUT) == 0xB8) + { + // Get ROM chip ID + val |= 0x800000; // Data-Word Status + T1WriteLong(MMU.MMU_MEM[proc][(REG_GCROMCTRL >> 20) & 0xff], REG_GCROMCTRL & 0xfff, val); + MMU.dscard[proc].adress = 0; + } + else + { + LOG("CARD command: %02X\n", MEM_8(MMU.MMU_MEM[proc], REG_GCCMDOUT)); + } + + //CARDLOG("%08X : %08X %08X\r\n", adr, val, adresse[proc]); + val |= 0x00800000; + + if(MMU.dscard[proc].adress == 0) + { + val &= ~0x80000000; + T1WriteLong(MMU.MMU_MEM[proc][(REG_GCROMCTRL >> 20) & 0xff], REG_GCROMCTRL & 0xfff, val); + return; + } + T1WriteLong(MMU.MMU_MEM[proc][(REG_GCROMCTRL >> 20) & 0xff], REG_GCROMCTRL & 0xfff, val); + + /* launch DMA if start flag was set to "DS Cart" */ + if(proc == ARMCPU_ARM7) i = 2; + else i = 5; + + if(proc == ARMCPU_ARM9 && MMU.DMAStartTime[proc][0] == i) /* dma0/1 on arm7 can't start on ds cart event */ + { + MMU_doDMA(proc, 0); + return; + } + else if(proc == ARMCPU_ARM9 && MMU.DMAStartTime[proc][1] == i) + { + MMU_doDMA(proc, 1); + return; + } + else if(MMU.DMAStartTime[proc][2] == i) + { + MMU_doDMA(proc, 2); + return; + } + else if(MMU.DMAStartTime[proc][3] == i) + { + MMU_doDMA(proc, 3); + return; + } + return; + + } + return; + case REG_DISPA_DISPCAPCNT : + if(proc == ARMCPU_ARM9) + { + GPU_set_DISPCAPCNT(MainScreen.gpu,val); + T1WriteLong(ARM9Mem.ARM9_REG, 0x64, val); + } + return; + + case REG_DISPA_BG0CNT : + if (proc == ARMCPU_ARM9) + { + GPU_setBGProp(MainScreen.gpu, 0, (val&0xFFFF)); + GPU_setBGProp(MainScreen.gpu, 1, (val>>16)); + } + //if((val>>16)==0x400) execute = FALSE; + T1WriteLong(ARM9Mem.ARM9_REG, 8, val); + return; + case REG_DISPA_BG2CNT : + if (proc == ARMCPU_ARM9) + { + GPU_setBGProp(MainScreen.gpu, 2, (val&0xFFFF)); + GPU_setBGProp(MainScreen.gpu, 3, (val>>16)); + } + T1WriteLong(ARM9Mem.ARM9_REG, 0xC, val); + return; + case REG_DISPB_BG0CNT : + if (proc == ARMCPU_ARM9) + { + GPU_setBGProp(SubScreen.gpu, 0, (val&0xFFFF)); + GPU_setBGProp(SubScreen.gpu, 1, (val>>16)); + } + T1WriteLong(ARM9Mem.ARM9_REG, 0x1008, val); + return; + case REG_DISPB_BG2CNT : + if (proc == ARMCPU_ARM9) + { + GPU_setBGProp(SubScreen.gpu, 2, (val&0xFFFF)); + GPU_setBGProp(SubScreen.gpu, 3, (val>>16)); + } + T1WriteLong(ARM9Mem.ARM9_REG, 0x100C, val); + return; + case REG_DISPA_DISPMMEMFIFO: + { + // NOTE: right now, the capture unit is not taken into account, + // I don't know is it should be handled here or + + FIFOAdd(MMU.fifos + MAIN_MEMORY_DISP_FIFO, val); + break; + } + //case 0x21FDFF0 : if(val==0) execute = FALSE; + //case 0x21FDFB0 : if(val==0) execute = FALSE; + default : + T1WriteLong(MMU.MMU_MEM[proc][0x40], adr & MMU.MMU_MASK[proc][(adr>>20)&0xFF], val); + return; + } + } + T1WriteLong(MMU.MMU_MEM[proc][(adr>>20)&0xFF], adr&MMU.MMU_MASK[proc][(adr>>20)&0xFF], val); +} + + +void FASTCALL MMU_doDMA(u32 proc, u32 num) +{ + u32 src = DMASrc[proc][num]; + u32 dst = DMADst[proc][num]; + u32 taille; + + if(src==dst) + { + T1WriteLong(MMU.MMU_MEM[proc][0x40], 0xB8 + (0xC*num), T1ReadLong(MMU.MMU_MEM[proc][0x40], 0xB8 + (0xC*num)) & 0x7FFFFFFF); + return; + } + + if((!(MMU.DMACrt[proc][num]&(1<<31)))&&(!(MMU.DMACrt[proc][num]&(1<<25)))) + { /* not enabled and not to be repeated */ + MMU.DMAStartTime[proc][num] = 0; + MMU.DMACycle[proc][num] = 0; + //MMU.DMAing[proc][num] = FALSE; + return; + } + + + /* word count */ + taille = (MMU.DMACrt[proc][num]&0xFFFF); + + // If we are in "Main memory display" mode just copy an entire + // screen (256x192 pixels). + // Reference: http://nocash.emubase.de/gbatek.htm#dsvideocaptureandmainmemorydisplaymode + // (under DISP_MMEM_FIFO) + if ((MMU.DMAStartTime[proc][num]==4) && // Must be in main memory display mode + (taille==4) && // Word must be 4 + (((MMU.DMACrt[proc][num]>>26)&1) == 1)) // Transfer mode must be 32bit wide + taille = 256*192/2; + + if(MMU.DMAStartTime[proc][num] == 5) + taille *= 0x80; + + MMU.DMACycle[proc][num] = taille + nds.cycles; + MMU.DMAing[proc][num] = TRUE; + + DMALOG("proc %d, dma %d src %08X dst %08X start %d taille %d repeat %s %08X\r\n", + proc, num, src, dst, MMU.DMAStartTime[proc][num], taille, + (MMU.DMACrt[proc][num]&(1<<25))?"on":"off",MMU.DMACrt[proc][num]); + + if(!(MMU.DMACrt[proc][num]&(1<<25))) + MMU.DMAStartTime[proc][num] = 0; + + // transfer + { + u32 i=0; + // 32 bit or 16 bit transfer ? + int sz = ((MMU.DMACrt[proc][num]>>26)&1)? 4 : 2; + int dstinc,srcinc; + int u=(MMU.DMACrt[proc][num]>>21); + switch(u & 0x3) { + case 0 : dstinc = sz; break; + case 1 : dstinc = -sz; break; + case 2 : dstinc = 0; break; + case 3 : dstinc = sz; break; //reload + } + switch((u >> 2)&0x3) { + case 0 : srcinc = sz; break; + case 1 : srcinc = -sz; break; + case 2 : srcinc = 0; break; + case 3 : // reserved + return; + } + if ((MMU.DMACrt[proc][num]>>26)&1) + for(; i < taille; ++i) + { + MMU_write32(proc, dst, MMU_read32(proc, src)); + dst += dstinc; + src += srcinc; + } + else + for(; i < taille; ++i) + { + MMU_write16(proc, dst, MMU_read16(proc, src)); + dst += dstinc; + src += srcinc; + } + } +} + +#ifdef MMU_ENABLE_ACL + +INLINE void check_access(u32 adr, u32 access) { + /* every other mode: sys */ + access |= 1; + if ((NDS_ARM9.CPSR.val & 0x1F) == 0x10) { + /* is user mode access */ + access ^= 1 ; + } + if (armcp15_isAccessAllowed((armcp15_t *)NDS_ARM9.coproc[15],adr,access)==FALSE) { + execute = FALSE ; + } +} +INLINE void check_access_write(u32 adr) { + u32 access = CP15_ACCESS_WRITE; + check_access(adr, access) +} + +u8 FASTCALL MMU_read8_acl(u32 proc, u32 adr, u32 access) +{ + /* on arm9 we need to check the MPU regions */ + if (proc == ARMCPU_ARM9) + check_access(u32 adr, u32 access); + return MMU_read8(proc,adr); +} +u16 FASTCALL MMU_read16_acl(u32 proc, u32 adr, u32 access) +{ + /* on arm9 we need to check the MPU regions */ + if (proc == ARMCPU_ARM9) + check_access(u32 adr, u32 access); + return MMU_read16(proc,adr); +} +u32 FASTCALL MMU_read32_acl(u32 proc, u32 adr, u32 access) +{ + /* on arm9 we need to check the MPU regions */ + if (proc == ARMCPU_ARM9) + check_access(u32 adr, u32 access); + return MMU_read32(proc,adr); +} + +void FASTCALL MMU_write8_acl(u32 proc, u32 adr, u8 val) +{ + /* check MPU region on ARM9 */ + if (proc == ARMCPU_ARM9) + check_access_write(adr); + MMU_write8(proc,adr,val); +} +void FASTCALL MMU_write16_acl(u32 proc, u32 adr, u16 val) +{ + /* check MPU region on ARM9 */ + if (proc == ARMCPU_ARM9) + check_access_write(adr); + MMU_write16(proc,adr,val) ; +} +void FASTCALL MMU_write32_acl(u32 proc, u32 adr, u32 val) +{ + /* check MPU region on ARM9 */ + if (proc == ARMCPU_ARM9) + check_access_write(adr); + MMU_write32(proc,adr,val) ; +} +#endif + + + +#ifdef PROFILE_MEMORY_ACCESS + +#define PROFILE_PREFETCH 0 +#define PROFILE_READ 1 +#define PROFILE_WRITE 2 + +struct mem_access_profile { + u64 num_accesses; + u32 address_mask; + u32 masked_value; +}; + +#define PROFILE_NUM_MEM_ACCESS_PROFILES 4 + +static u64 profile_num_accesses[2][3]; +static u64 profile_unknown_addresses[2][3]; +static struct mem_access_profile +profile_memory_accesses[2][3][PROFILE_NUM_MEM_ACCESS_PROFILES]; + +static void +setup_profiling( void) { + int i; + + for ( i = 0; i < 2; i++) { + int access_type; + + for ( access_type = 0; access_type < 3; access_type++) { + profile_num_accesses[i][access_type] = 0; + profile_unknown_addresses[i][access_type] = 0; + + /* + * Setup the access testing structures + */ + profile_memory_accesses[i][access_type][0].address_mask = 0x0e000000; + profile_memory_accesses[i][access_type][0].masked_value = 0x00000000; + profile_memory_accesses[i][access_type][0].num_accesses = 0; + + /* main memory */ + profile_memory_accesses[i][access_type][1].address_mask = 0x0f000000; + profile_memory_accesses[i][access_type][1].masked_value = 0x02000000; + profile_memory_accesses[i][access_type][1].num_accesses = 0; + + /* shared memory */ + profile_memory_accesses[i][access_type][2].address_mask = 0x0f800000; + profile_memory_accesses[i][access_type][2].masked_value = 0x03000000; + profile_memory_accesses[i][access_type][2].num_accesses = 0; + + /* arm7 memory */ + profile_memory_accesses[i][access_type][3].address_mask = 0x0f800000; + profile_memory_accesses[i][access_type][3].masked_value = 0x03800000; + profile_memory_accesses[i][access_type][3].num_accesses = 0; + } + } +} + +static void +profile_memory_access( int arm9, u32 adr, int access_type) { + static int first = 1; + int mem_profile; + int address_found = 0; + + if ( first) { + setup_profiling(); + first = 0; + } + + profile_num_accesses[arm9][access_type] += 1; + + for ( mem_profile = 0; + mem_profile < PROFILE_NUM_MEM_ACCESS_PROFILES && + !address_found; + mem_profile++) { + if ( (adr & profile_memory_accesses[arm9][access_type][mem_profile].address_mask) == + profile_memory_accesses[arm9][access_type][mem_profile].masked_value) { + /*printf( "adr %08x mask %08x res %08x expected %08x\n", + adr, + profile_memory_accesses[arm9][access_type][mem_profile].address_mask, + adr & profile_memory_accesses[arm9][access_type][mem_profile].address_mask, + profile_memory_accesses[arm9][access_type][mem_profile].masked_value);*/ + address_found = 1; + profile_memory_accesses[arm9][access_type][mem_profile].num_accesses += 1; + } + } + + if ( !address_found) { + profile_unknown_addresses[arm9][access_type] += 1; + } +} + + +static const char *access_type_strings[] = { + "prefetch", + "read ", + "write " +}; + +void +print_memory_profiling( void) { + int arm; + + printf("------ Memory access profile ------\n"); + + for ( arm = 0; arm < 2; arm++) { + int access_type; + + for ( access_type = 0; access_type < 3; access_type++) { + int mem_profile; + printf("ARM%c: num of %s %lld\n", + arm ? '9' : '7', + access_type_strings[access_type], + profile_num_accesses[arm][access_type]); + + for ( mem_profile = 0; + mem_profile < PROFILE_NUM_MEM_ACCESS_PROFILES; + mem_profile++) { + printf( "address %08x: %lld\n", + profile_memory_accesses[arm][access_type][mem_profile].masked_value, + profile_memory_accesses[arm][access_type][mem_profile].num_accesses); + } + + printf( "unknown addresses %lld\n", + profile_unknown_addresses[arm][access_type]); + + printf( "\n"); + } + } + + printf("------ End of Memory access profile ------\n\n"); +} +#else +void +print_memory_profiling( void) { +} +#endif /* End of PROFILE_MEMORY_ACCESS area */ + +static u16 FASTCALL +arm9_prefetch16( void *data, u32 adr) { +#ifdef PROFILE_MEMORY_ACCESS + profile_memory_access( 1, adr, PROFILE_PREFETCH); +#endif + +#ifdef EARLY_MEMORY_ACCESS + if((adr & ~0x3FFF) == MMU.DTCMRegion) + { + /* Returns data from DTCM (ARM9 only) */ + return T1ReadWord(ARM9Mem.ARM9_DTCM, adr & 0x3FFF); + } + /* access to main memory */ + if ( (adr & 0x0f000000) == 0x02000000) { + return T1ReadWord( MMU.MMU_MEM[ARMCPU_ARM9][(adr >> 20) & 0xFF], + adr & MMU.MMU_MASK[ARMCPU_ARM9][(adr >> 20) & 0xFF]); + } +#endif + + return MMU_read16( ARMCPU_ARM9, adr); +} +static u32 FASTCALL +arm9_prefetch32( void *data, u32 adr) { +#ifdef PROFILE_MEMORY_ACCESS + profile_memory_access( 1, adr, PROFILE_PREFETCH); +#endif + +#ifdef EARLY_MEMORY_ACCESS + if((adr & ~0x3FFF) == MMU.DTCMRegion) + { + /* Returns data from DTCM (ARM9 only) */ + return T1ReadLong(ARM9Mem.ARM9_DTCM, adr & 0x3FFF); + } + /* access to main memory */ + if ( (adr & 0x0f000000) == 0x02000000) { + return T1ReadLong( MMU.MMU_MEM[ARMCPU_ARM9][(adr >> 20) & 0xFF], + adr & MMU.MMU_MASK[ARMCPU_ARM9][(adr >> 20) & 0xFF]); + } +#endif + + return MMU_read32( ARMCPU_ARM9, adr); +} + +static u8 FASTCALL +arm9_read8( void *data, u32 adr) { +#ifdef PROFILE_MEMORY_ACCESS + profile_memory_access( 1, adr, PROFILE_READ); +#endif + +#ifdef EARLY_MEMORY_ACCESS + if( (adr&(~0x3FFF)) == MMU.DTCMRegion) + { + return ARM9Mem.ARM9_DTCM[adr&0x3FFF]; + } + /* access to main memory */ + if ( (adr & 0x0f000000) == 0x02000000) { + return MMU.MMU_MEM[ARMCPU_ARM9][(adr >> 20) & 0xFF] + [adr & MMU.MMU_MASK[ARMCPU_ARM9][(adr >> 20) & 0xFF]]; + } +#endif + + return MMU_read8( ARMCPU_ARM9, adr); +} +static u16 FASTCALL +arm9_read16( void *data, u32 adr) { +#ifdef PROFILE_MEMORY_ACCESS + profile_memory_access( 1, adr, PROFILE_READ); +#endif + +#ifdef EARLY_MEMORY_ACCESS + if((adr & ~0x3FFF) == MMU.DTCMRegion) + { + /* Returns data from DTCM (ARM9 only) */ + return T1ReadWord(ARM9Mem.ARM9_DTCM, adr & 0x3FFF); + } + + /* access to main memory */ + if ( (adr & 0x0f000000) == 0x02000000) { + return T1ReadWord( MMU.MMU_MEM[ARMCPU_ARM9][(adr >> 20) & 0xFF], + adr & MMU.MMU_MASK[ARMCPU_ARM9][(adr >> 20) & 0xFF]); + } +#endif + + return MMU_read16( ARMCPU_ARM9, adr); +} +static u32 FASTCALL +arm9_read32( void *data, u32 adr) { +#ifdef PROFILE_MEMORY_ACCESS + profile_memory_access( 1, adr, PROFILE_READ); +#endif + +#ifdef EARLY_MEMORY_ACCESS + if((adr & ~0x3FFF) == MMU.DTCMRegion) + { + /* Returns data from DTCM (ARM9 only) */ + return T1ReadLong(ARM9Mem.ARM9_DTCM, adr & 0x3FFF); + } + /* access to main memory */ + if ( (adr & 0x0f000000) == 0x02000000) { + return T1ReadLong( MMU.MMU_MEM[ARMCPU_ARM9][(adr >> 20) & 0xFF], + adr & MMU.MMU_MASK[ARMCPU_ARM9][(adr >> 20) & 0xFF]); + } +#endif + + return MMU_read32( ARMCPU_ARM9, adr); +} + + +static void FASTCALL +arm9_write8(void *data, u32 adr, u8 val) { +#ifdef PROFILE_MEMORY_ACCESS + profile_memory_access( 1, adr, PROFILE_WRITE); +#endif + +#ifdef EARLY_MEMORY_ACCESS + if( (adr & ~0x3FFF) == MMU.DTCMRegion) + { + /* Writes data in DTCM (ARM9 only) */ + ARM9Mem.ARM9_DTCM[adr&0x3FFF] = val; + return ; + } + /* main memory */ + if ( (adr & 0x0f000000) == 0x02000000) { + MMU.MMU_MEM[ARMCPU_ARM9][(adr>>20)&0xFF] + [adr&MMU.MMU_MASK[ARMCPU_ARM9][(adr>>20)&0xFF]] = val; + return; + } +#endif + + MMU_write8( ARMCPU_ARM9, adr, val); +} +static void FASTCALL +arm9_write16(void *data, u32 adr, u16 val) { +#ifdef PROFILE_MEMORY_ACCESS + profile_memory_access( 1, adr, PROFILE_WRITE); +#endif + +#ifdef EARLY_MEMORY_ACCESS + if((adr & ~0x3FFF) == MMU.DTCMRegion) + { + /* Writes in DTCM (ARM9 only) */ + T1WriteWord(ARM9Mem.ARM9_DTCM, adr & 0x3FFF, val); + return; + } + /* main memory */ + if ( (adr & 0x0f000000) == 0x02000000) { + T1WriteWord( MMU.MMU_MEM[ARMCPU_ARM9][(adr>>20)&0xFF], + adr&MMU.MMU_MASK[ARMCPU_ARM9][(adr>>20)&0xFF], val); + return; + } +#endif + + MMU_write16( ARMCPU_ARM9, adr, val); +} +static void FASTCALL +arm9_write32(void *data, u32 adr, u32 val) { +#ifdef PROFILE_MEMORY_ACCESS + profile_memory_access( 1, adr, PROFILE_WRITE); +#endif + +#ifdef EARLY_MEMORY_ACCESS + if((adr & ~0x3FFF) == MMU.DTCMRegion) + { + /* Writes in DTCM (ARM9 only) */ + T1WriteLong(ARM9Mem.ARM9_DTCM, adr & 0x3FFF, val); + return; + } + /* main memory */ + if ( (adr & 0x0f000000) == 0x02000000) { + T1WriteLong( MMU.MMU_MEM[ARMCPU_ARM9][(adr>>20)&0xFF], + adr&MMU.MMU_MASK[ARMCPU_ARM9][(adr>>20)&0xFF], val); + return; + } +#endif + + MMU_write32( ARMCPU_ARM9, adr, val); +} + + + + +static u16 FASTCALL +arm7_prefetch16( void *data, u32 adr) { +#ifdef PROFILE_MEMORY_ACCESS + profile_memory_access( 0, adr, PROFILE_PREFETCH); +#endif + +#ifdef EARLY_MEMORY_ACCESS + /* ARM7 private memory */ + if ( (adr & 0x0f800000) == 0x03800000) { + T1ReadWord(MMU.MMU_MEM[ARMCPU_ARM7][(adr >> 20) & 0xFF], + adr & MMU.MMU_MASK[ARMCPU_ARM7][(adr >> 20) & 0xFF]); + } +#endif + + return MMU_read16( ARMCPU_ARM7, adr); +} +static u32 FASTCALL +arm7_prefetch32( void *data, u32 adr) { +#ifdef PROFILE_MEMORY_ACCESS + profile_memory_access( 0, adr, PROFILE_PREFETCH); +#endif + +#ifdef EARLY_MEMORY_ACCESS + /* ARM7 private memory */ + if ( (adr & 0x0f800000) == 0x03800000) { + T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM7][(adr >> 20) & 0xFF], + adr & MMU.MMU_MASK[ARMCPU_ARM7][(adr >> 20) & 0xFF]); + } +#endif + + return MMU_read32( ARMCPU_ARM7, adr); +} + +static u8 FASTCALL +arm7_read8( void *data, u32 adr) { +#ifdef PROFILE_MEMORY_ACCESS + profile_memory_access( 0, adr, PROFILE_READ); +#endif + + return MMU_read8( ARMCPU_ARM7, adr); +} +static u16 FASTCALL +arm7_read16( void *data, u32 adr) { +#ifdef PROFILE_MEMORY_ACCESS + profile_memory_access( 0, adr, PROFILE_READ); +#endif + + return MMU_read16( ARMCPU_ARM7, adr); +} +static u32 FASTCALL +arm7_read32( void *data, u32 adr) { +#ifdef PROFILE_MEMORY_ACCESS + profile_memory_access( 0, adr, PROFILE_READ); +#endif + + return MMU_read32( ARMCPU_ARM7, adr); +} + + +static void FASTCALL +arm7_write8(void *data, u32 adr, u8 val) { +#ifdef PROFILE_MEMORY_ACCESS + profile_memory_access( 0, adr, PROFILE_WRITE); +#endif + + MMU_write8( ARMCPU_ARM7, adr, val); +} +static void FASTCALL +arm7_write16(void *data, u32 adr, u16 val) { +#ifdef PROFILE_MEMORY_ACCESS + profile_memory_access( 0, adr, PROFILE_WRITE); +#endif + + MMU_write16( ARMCPU_ARM7, adr, val); +} +static void FASTCALL +arm7_write32(void *data, u32 adr, u32 val) { +#ifdef PROFILE_MEMORY_ACCESS + profile_memory_access( 0, adr, PROFILE_WRITE); +#endif + + MMU_write32( ARMCPU_ARM7, adr, val); +} + + + +/* + * the base memory interfaces + */ +struct armcpu_memory_iface arm9_base_memory_iface = { +#ifdef __GNUC__ + .prefetch32 = arm9_prefetch32, + .prefetch16 = arm9_prefetch16, + + .read8 = arm9_read8, + .read16 = arm9_read16, + .read32 = arm9_read32, + + .write8 = arm9_write8, + .write16 = arm9_write16, + .write32 = arm9_write32 +#else + arm9_prefetch32, + arm9_prefetch16, + + arm9_read8, + arm9_read16, + arm9_read32, + + arm9_write8, + arm9_write16, + arm9_write32 +#endif +}; + +struct armcpu_memory_iface arm7_base_memory_iface = { +#ifdef __GNUC__ + .prefetch32 = arm7_prefetch32, + .prefetch16 = arm7_prefetch16, + + .read8 = arm7_read8, + .read16 = arm7_read16, + .read32 = arm7_read32, + + .write8 = arm7_write8, + .write16 = arm7_write16, + .write32 = arm7_write32 +#else + arm7_prefetch32, + arm7_prefetch16, + + arm7_read8, + arm7_read16, + arm7_read32, + + arm7_write8, + arm7_write16, + arm7_write32 +#endif +}; + +/* + * The direct memory interface for the ARM9. + * This avoids the ARM9 protection unit when accessing + * memory. + */ +struct armcpu_memory_iface arm9_direct_memory_iface = { +#ifdef __GNUC__ + /* the prefetch is not used */ + .prefetch32 = NULL, + .prefetch16 = NULL, + + .read8 = arm9_read8, + .read16 = arm9_read16, + .read32 = arm9_read32, + + .write8 = arm9_write8, + .write16 = arm9_write16, + .write32 = arm9_write32 +#else + NULL, + NULL, + + arm9_read8, + arm9_read16, + arm9_read32, + + arm9_write8, + arm9_write16, + arm9_write32 +#endif +}; diff -r fe2ba1a712cd -r 70b0973e7b70 src/xsf/desmume/MMU.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/xsf/desmume/MMU.h Thu Oct 16 14:45:41 2008 -0500 @@ -0,0 +1,198 @@ +/* Copyright (C) 2006 yopyop + yopyop156@ifrance.com + yopyop156.ifrance.com + + Copyright (C) 2007 shash + + This file is part of DeSmuME + + DeSmuME is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DeSmuME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DeSmuME; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef MMU_H +#define MMU_H + +#include "FIFO.h" +#include "dscard.h" + +#include "ARM9.h" +#include "mc.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern char szRomPath[512]; +extern char szRomBaseName[512]; + +/* theses macros are designed for reading/writing in memory (m is a pointer to memory, like MMU.MMU_MEM[proc], and a is an adress, like 0x04000000 */ +#define MEM_8(m, a) (((u8*)(m[((a)>>20)&0xff]))[((a)&0xfff)]) + +/* theses ones for reading in rom data */ +#define ROM_8(m, a) (((u8*)(m))[(a)]) + +#define IPCFIFO 0 +#define MAIN_MEMORY_DISP_FIFO 2 + +typedef struct { + //ARM7 mem + u8 ARM7_BIOS[0x4000]; + u8 ARM7_ERAM[0x10000]; + u8 ARM7_REG[0x10000]; + u8 ARM7_WIRAM[0x10000]; + + u8 vram_mode[9]; + u8 vScreen; + + //Shared ram + u8 SWIRAM[0x8000]; + + //Card rom & ram + u8 * CART_ROM; + u8 CART_RAM[0x10000]; + + //Unused ram + u8 UNUSED_RAM[4]; + + u8 * * MMU_MEM[2]; + u32 * MMU_MASK[2]; + + u8 ARM9_RW_MODE; + + FIFO fifos[16]; + + u32 * MMU_WAIT16[2]; + u32 * MMU_WAIT32[2]; + + u32 DTCMRegion; + u32 ITCMRegion; + + u16 timer[2][4]; + s32 timerMODE[2][4]; + u32 timerON[2][4]; + u32 timerRUN[2][4]; + u16 timerReload[2][4]; + + u32 reg_IME[2]; + u32 reg_IE[2]; + u32 reg_IF[2]; + + u32 DMAStartTime[2][4]; + s32 DMACycle[2][4]; + u32 DMACrt[2][4]; + BOOL DMAing[2][4]; + + memory_chip_t fw; + memory_chip_t bupmem; + + nds_dscard dscard[2]; + +} MMU_struct; + +extern MMU_struct MMU; + + +struct armcpu_memory_iface { + /** the 32 bit instruction prefetch */ + u32 FASTCALL (*prefetch32)( void *data, u32 adr); + + /** the 16 bit instruction prefetch */ + u16 FASTCALL (*prefetch16)( void *data, u32 adr); + + /** read 8 bit data value */ + u8 FASTCALL (*read8)( void *data, u32 adr); + /** read 16 bit data value */ + u16 FASTCALL (*read16)( void *data, u32 adr); + /** read 32 bit data value */ + u32 FASTCALL (*read32)( void *data, u32 adr); + + /** write 8 bit data value */ + void FASTCALL (*write8)( void *data, u32 adr, u8 val); + /** write 16 bit data value */ + void FASTCALL (*write16)( void *data, u32 adr, u16 val); + /** write 32 bit data value */ + void FASTCALL (*write32)( void *data, u32 adr, u32 val); + + void *data; +}; + + + +static void mmu_select_savetype(int type, int *bmemtype, u32 *bmemsize) { + if (type<0 || type > 5) return; + *bmemtype=save_types[type][0]; + *bmemsize=save_types[type][1]; + mc_realloc(&MMU.bupmem, *bmemtype, *bmemsize); +} + +void MMU_Init(void); +void MMU_DeInit(void); + +void MMU_clearMem( void); + +void MMU_setRom(u8 * rom, u32 mask); +void MMU_unsetRom( void); + + +/** + * Memory reading + */ +u8 FASTCALL MMU_read8(u32 proc, u32 adr); +u16 FASTCALL MMU_read16(u32 proc, u32 adr); +u32 FASTCALL MMU_read32(u32 proc, u32 adr); + +#ifdef MMU_ENABLE_ACL + u8 FASTCALL MMU_read8_acl(u32 proc, u32 adr, u32 access); + u16 FASTCALL MMU_read16_acl(u32 proc, u32 adr, u32 access); + u32 FASTCALL MMU_read32_acl(u32 proc, u32 adr, u32 access); +#else + #define MMU_read8_acl(proc,adr,access) MMU_read8(proc,adr) + #define MMU_read16_acl(proc,adr,access) MMU_read16(proc,adr) + #define MMU_read32_acl(proc,adr,access) MMU_read32(proc,adr) +#endif + +/** + * Memory writing + */ +void FASTCALL MMU_write8(u32 proc, u32 adr, u8 val); +void FASTCALL MMU_write16(u32 proc, u32 adr, u16 val); +void FASTCALL MMU_write32(u32 proc, u32 adr, u32 val); + +#ifdef MMU_ENABLE_ACL + void FASTCALL MMU_write8_acl(u32 proc, u32 adr, u8 val); + void FASTCALL MMU_write16_acl(u32 proc, u32 adr, u16 val); + void FASTCALL MMU_write32_acl(u32 proc, u32 adr, u32 val); +#else + #define MMU_write8_acl MMU_write8 + #define MMU_write16_acl MMU_write16 + #define MMU_write32_acl MMU_write32 +#endif + +void FASTCALL MMU_doDMA(u32 proc, u32 num); + + +/* + * The base ARM memory interfaces + */ +extern struct armcpu_memory_iface arm9_base_memory_iface; +extern struct armcpu_memory_iface arm7_base_memory_iface; +extern struct armcpu_memory_iface arm9_direct_memory_iface; + + +#ifdef __cplusplus +} +#endif + +#endif diff -r fe2ba1a712cd -r 70b0973e7b70 src/xsf/desmume/NDSSystem.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/xsf/desmume/NDSSystem.c Thu Oct 16 14:45:41 2008 -0500 @@ -0,0 +1,748 @@ +/* Copyright (C) 2006 yopyop + yopyop156@ifrance.com + yopyop156.ifrance.com + + This file is part of DeSmuME + + DeSmuME is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DeSmuME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DeSmuME; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include +#include + +#include "NDSSystem.h" +#include "MMU.h" +//#include "cflash.h" + +//#include "ROMReader.h" + +/* the count of bytes copied from the firmware into memory */ +#define NDS_FW_USER_SETTINGS_MEM_BYTE_COUNT 0x70 + +NDSSystem nds; + +static u32 +calc_CRC16( u32 start, const u8 *data, int count) { + int i,j; + u32 crc = start & 0xffff; + static u16 val[] = { 0xC0C1,0xC181,0xC301,0xC601,0xCC01,0xD801,0xF001,0xA001 }; + for(i = 0; i < count; i++) + { + crc = crc ^ data[i]; + + for(j = 0; j < 8; j++) { + int do_bit = 0; + + if ( crc & 0x1) + do_bit = 1; + + crc = crc >> 1; + + if ( do_bit) { + crc = crc ^ (val[j] << (7-j)); + } + } + } + return crc; +} + +static int +copy_firmware_user_data( u8 *dest_buffer, const u8 *fw_data) { + /* + * Determine which of the two user settings in the firmware is the current + * and valid one and then copy this into the destination buffer. + * + * The current setting will have a greater count. + * Settings are only valid if its CRC16 is correct. + */ + int user1_valid = 0; + int user2_valid = 0; + u32 user_settings_offset; + u32 fw_crc; + u32 crc; + int copy_good = 0; + + user_settings_offset = fw_data[0x20]; + user_settings_offset |= fw_data[0x21] << 8; + user_settings_offset <<= 3; + + if ( user_settings_offset <= 0x3FE00) { + s32 copy_settings_offset = -1; + + crc = calc_CRC16( 0xffff, &fw_data[user_settings_offset], + NDS_FW_USER_SETTINGS_MEM_BYTE_COUNT); + fw_crc = fw_data[user_settings_offset + 0x72]; + fw_crc |= fw_data[user_settings_offset + 0x73] << 8; + if ( crc == fw_crc) { + user1_valid = 1; + } + + crc = calc_CRC16( 0xffff, &fw_data[user_settings_offset + 0x100], + NDS_FW_USER_SETTINGS_MEM_BYTE_COUNT); + fw_crc = fw_data[user_settings_offset + 0x100 + 0x72]; + fw_crc |= fw_data[user_settings_offset + 0x100 + 0x73] << 8; + if ( crc == fw_crc) { + user2_valid = 1; + } + + if ( user1_valid) { + if ( user2_valid) { + u16 count1, count2; + + count1 = fw_data[user_settings_offset + 0x70]; + count1 |= fw_data[user_settings_offset + 0x71] << 8; + + count2 = fw_data[user_settings_offset + 0x100 + 0x70]; + count2 |= fw_data[user_settings_offset + 0x100 + 0x71] << 8; + + if ( count2 > count1) { + copy_settings_offset = user_settings_offset + 0x100; + } + else { + copy_settings_offset = user_settings_offset; + } + } + else { + copy_settings_offset = user_settings_offset; + } + } + else if ( user2_valid) { + /* copy the second user settings */ + copy_settings_offset = user_settings_offset + 0x100; + } + + if ( copy_settings_offset > 0) { + memcpy( dest_buffer, &fw_data[copy_settings_offset], + NDS_FW_USER_SETTINGS_MEM_BYTE_COUNT); + copy_good = 1; + } + } + + return copy_good; +} + + +#ifdef GDB_STUB +int NDS_Init( struct armcpu_memory_iface *arm9_mem_if, + struct armcpu_ctrl_iface **arm9_ctrl_iface, + struct armcpu_memory_iface *arm7_mem_if, + struct armcpu_ctrl_iface **arm7_ctrl_iface) { +#else +int NDS_Init( void) { +#endif + nds.ARM9Cycle = 0; + nds.ARM7Cycle = 0; + nds.cycles = 0; + MMU_Init(); + nds.nextHBlank = 3168; + nds.VCount = 0; + nds.lignerendu = FALSE; + + if (Screen_Init(GFXCORE_DUMMY) != 0) + return -1; + + #ifdef GDB_STUB + armcpu_new(&NDS_ARM7,1, arm7_mem_if, arm7_ctrl_iface); + armcpu_new(&NDS_ARM9,0, arm9_mem_if, arm9_ctrl_iface); +#else + armcpu_new(&NDS_ARM7,1); + armcpu_new(&NDS_ARM9,0); +#endif + + if (SPU_Init(SNDCORE_DUMMY, 735) != 0) + return -1; + +#ifdef EXPERIMENTAL_WIFI + WIFI_Init(&wifiMac) ; +#endif + + return 0; +} + +static void armcpu_deinit(armcpu_t *armcpu) +{ + if(armcpu->coproc[15]) + { + free(armcpu->coproc[15]); + armcpu->coproc[15] = 0; + } +} + +void NDS_DeInit(void) { + if(MMU.CART_ROM != MMU.UNUSED_RAM) + NDS_FreeROM(); + + armcpu_deinit(&NDS_ARM7); + armcpu_deinit(&NDS_ARM9); + + nds.nextHBlank = 3168; + SPU_DeInit(); + Screen_DeInit(); + MMU_DeInit(); +} + +BOOL NDS_SetROM(u8 * rom, u32 mask) +{ + MMU_setRom(rom, mask); + + return TRUE; +} + +NDS_header * NDS_getROMHeader(void) +{ + NDS_header * header = malloc(sizeof(NDS_header)); + + memcpy(header->gameTile, MMU.CART_ROM, 12); + memcpy(header->gameCode, MMU.CART_ROM + 12, 4); + header->makerCode = T1ReadWord(MMU.CART_ROM, 16); + header->unitCode = MMU.CART_ROM[18]; + header->deviceCode = MMU.CART_ROM[19]; + header->cardSize = MMU.CART_ROM[20]; + memcpy(header->cardInfo, MMU.CART_ROM + 21, 8); + header->flags = MMU.CART_ROM[29]; + header->ARM9src = T1ReadLong(MMU.CART_ROM, 32); + header->ARM9exe = T1ReadLong(MMU.CART_ROM, 36); + header->ARM9cpy = T1ReadLong(MMU.CART_ROM, 40); + header->ARM9binSize = T1ReadLong(MMU.CART_ROM, 44); + header->ARM7src = T1ReadLong(MMU.CART_ROM, 48); + header->ARM7exe = T1ReadLong(MMU.CART_ROM, 52); + header->ARM7cpy = T1ReadLong(MMU.CART_ROM, 56); + header->ARM7binSize = T1ReadLong(MMU.CART_ROM, 60); + header->FNameTblOff = T1ReadLong(MMU.CART_ROM, 64); + header->FNameTblSize = T1ReadLong(MMU.CART_ROM, 68); + header->FATOff = T1ReadLong(MMU.CART_ROM, 72); + header->FATSize = T1ReadLong(MMU.CART_ROM, 76); + header->ARM9OverlayOff = T1ReadLong(MMU.CART_ROM, 80); + header->ARM9OverlaySize = T1ReadLong(MMU.CART_ROM, 84); + header->ARM7OverlayOff = T1ReadLong(MMU.CART_ROM, 88); + header->ARM7OverlaySize = T1ReadLong(MMU.CART_ROM, 92); + header->unknown2a = T1ReadLong(MMU.CART_ROM, 96); + header->unknown2b = T1ReadLong(MMU.CART_ROM, 100); + header->IconOff = T1ReadLong(MMU.CART_ROM, 104); + header->CRC16 = T1ReadWord(MMU.CART_ROM, 108); + header->ROMtimeout = T1ReadWord(MMU.CART_ROM, 110); + header->ARM9unk = T1ReadLong(MMU.CART_ROM, 112); + header->ARM7unk = T1ReadLong(MMU.CART_ROM, 116); + memcpy(header->unknown3c, MMU.CART_ROM + 120, 8); + header->ROMSize = T1ReadLong(MMU.CART_ROM, 128); + header->HeaderSize = T1ReadLong(MMU.CART_ROM, 132); + memcpy(header->unknown5, MMU.CART_ROM + 136, 56); + memcpy(header->logo, MMU.CART_ROM + 192, 156); + header->logoCRC16 = T1ReadWord(MMU.CART_ROM, 348); + header->headerCRC16 = T1ReadWord(MMU.CART_ROM, 350); + memcpy(header->reserved, MMU.CART_ROM + 352, 160); + + return header; + + //return (NDS_header *)MMU.CART_ROM; +} + + + +void NDS_FreeROM(void) +{ + if (MMU.CART_ROM != MMU.UNUSED_RAM) + free(MMU.CART_ROM); + MMU_unsetRom(); +// if (MMU.bupmem.fp) +// fclose(MMU.bupmem.fp); +// MMU.bupmem.fp = NULL; +} + + + +void NDS_Reset( void) +{ + BOOL oldexecute=execute; + int i; + u32 src; + u32 dst; + NDS_header * header = NDS_getROMHeader(); + + if (!header) return ; + + execute = FALSE; + + MMU_clearMem(); + + src = header->ARM9src; + dst = header->ARM9cpy; + + for(i = 0; i < (header->ARM9binSize>>2); ++i) + { + MMU_write32(0, dst, T1ReadLong(MMU.CART_ROM, src)); + dst += 4; + src += 4; + } + + src = header->ARM7src; + dst = header->ARM7cpy; + + for(i = 0; i < (header->ARM7binSize>>2); ++i) + { + MMU_write32(1, dst, T1ReadLong(MMU.CART_ROM, src)); + dst += 4; + src += 4; + } + + armcpu_init(&NDS_ARM7, header->ARM7exe); + armcpu_init(&NDS_ARM9, header->ARM9exe); + + nds.ARM9Cycle = 0; + nds.ARM7Cycle = 0; + nds.cycles = 0; + memset(nds.timerCycle, 0, sizeof(s32) * 2 * 4); + memset(nds.timerOver, 0, sizeof(BOOL) * 2 * 4); + nds.nextHBlank = 3168; + nds.VCount = 0; + nds.old = 0; + nds.diff = 0; + nds.lignerendu = FALSE; + nds.touchX = nds.touchY = 0; + + MMU_write16(0, 0x04000130, 0x3FF); + MMU_write16(1, 0x04000130, 0x3FF); + MMU_write8(1, 0x04000136, 0x43); + + /* + * Setup a copy of the firmware user settings in memory. + * (this is what the DS firmware would do). + */ + { + u8 temp_buffer[NDS_FW_USER_SETTINGS_MEM_BYTE_COUNT]; + int fw_index; + + if ( copy_firmware_user_data( temp_buffer, MMU.fw.data)) { + for ( fw_index = 0; fw_index < NDS_FW_USER_SETTINGS_MEM_BYTE_COUNT; fw_index++) { + MMU_write8( 0, 0x027FFC80 + fw_index, temp_buffer[fw_index]); + } + } + } + + // Copy the whole header to Main RAM 0x27FFE00 on startup. + // Reference: http://nocash.emubase.de/gbatek.htm#dscartridgeheader + for (i = 0; i < ((0x170+0x90)/4); i++) + { + MMU_write32 (0, 0x027FFE00+i*4, LE_TO_LOCAL_32(((u32*)MMU.CART_ROM)[i])); + } + + MainScreen.offset = 0; + SubScreen.offset = 192; + + //MMU_write32(0, 0x02007FFC, 0xE92D4030); + + //ARM7 BIOS IRQ HANDLER + MMU_write32(1, 0x00, 0xE25EF002); + MMU_write32(1, 0x04, 0xEAFFFFFE); + MMU_write32(1, 0x18, 0xEA000000); + MMU_write32(1, 0x20, 0xE92D500F); + MMU_write32(1, 0x24, 0xE3A00301); + MMU_write32(1, 0x28, 0xE28FE000); + MMU_write32(1, 0x2C, 0xE510F004); + MMU_write32(1, 0x30, 0xE8BD500F); + MMU_write32(1, 0x34, 0xE25EF004); + + //ARM9 BIOS IRQ HANDLER + MMU_write32(0, 0xFFFF0018, 0xEA000000); + MMU_write32(0, 0xFFFF0020, 0xE92D500F); + MMU_write32(0, 0xFFFF0024, 0xEE190F11); + MMU_write32(0, 0xFFFF0028, 0xE1A00620); + MMU_write32(0, 0xFFFF002C, 0xE1A00600); + MMU_write32(0, 0xFFFF0030, 0xE2800C40); + MMU_write32(0, 0xFFFF0034, 0xE28FE000); + MMU_write32(0, 0xFFFF0038, 0xE510F004); + MMU_write32(0, 0xFFFF003C, 0xE8BD500F); + MMU_write32(0, 0xFFFF0040, 0xE25EF004); + + MMU_write32(0, 0x0000004, 0xE3A0010E); + MMU_write32(0, 0x0000008, 0xE3A01020); +// MMU_write32(0, 0x000000C, 0xE1B02110); + MMU_write32(0, 0x000000C, 0xE1B02040); + MMU_write32(0, 0x0000010, 0xE3B02020); +// MMU_write32(0, 0x0000010, 0xE2100202); + + free(header); + + GPU_Reset(MainScreen.gpu, 0); + GPU_Reset(SubScreen.gpu, 1); + SPU_Reset(); + + execute = oldexecute; +} + +static void dma_check(void) +{ + if((MMU.DMAing[0][0])&&(MMU.DMACycle[0][0]<=nds.cycles)) + { + T1WriteLong(ARM9Mem.ARM9_REG, 0xB8 + (0xC*0), T1ReadLong(ARM9Mem.ARM9_REG, 0xB8 + (0xC*0)) & 0x7FFFFFFF); + if((MMU.DMACrt[0][0])&(1<<30)) NDS_makeARM9Int(8); + MMU.DMAing[0][0] = FALSE; + } + + if((MMU.DMAing[0][1])&&(MMU.DMACycle[0][1]<=nds.cycles)) + { + T1WriteLong(ARM9Mem.ARM9_REG, 0xB8 + (0xC*1), T1ReadLong(ARM9Mem.ARM9_REG, 0xB8 + (0xC*1)) & 0x7FFFFFFF); + if((MMU.DMACrt[0][1])&(1<<30)) NDS_makeARM9Int(9); + MMU.DMAing[0][1] = FALSE; + } + + if((MMU.DMAing[0][2])&&(MMU.DMACycle[0][2]<=nds.cycles)) + { + T1WriteLong(ARM9Mem.ARM9_REG, 0xB8 + (0xC*2), T1ReadLong(ARM9Mem.ARM9_REG, 0xB8 + (0xC*2)) & 0x7FFFFFFF); + if((MMU.DMACrt[0][2])&(1<<30)) NDS_makeARM9Int(10); + MMU.DMAing[0][2] = FALSE; + } + + if((MMU.DMAing[0][3])&&(MMU.DMACycle[0][3]<=nds.cycles)) + { + T1WriteLong(ARM9Mem.ARM9_REG, 0xB8 + (0xC*3), T1ReadLong(ARM9Mem.ARM9_REG, 0xB8 + (0xC*3)) & 0x7FFFFFFF); + if((MMU.DMACrt[0][3])&(1<<30)) NDS_makeARM9Int(11); + MMU.DMAing[0][3] = FALSE; + } + + if((MMU.DMAing[1][0])&&(MMU.DMACycle[1][0]<=nds.cycles)) + { + T1WriteLong(MMU.ARM7_REG, 0xB8 + (0xC*0), T1ReadLong(MMU.ARM7_REG, 0xB8 + (0xC*0)) & 0x7FFFFFFF); + if((MMU.DMACrt[1][0])&(1<<30)) NDS_makeARM7Int(8); + MMU.DMAing[1][0] = FALSE; + } + + if((MMU.DMAing[1][1])&&(MMU.DMACycle[1][1]<=nds.cycles)) + { + T1WriteLong(MMU.ARM7_REG, 0xB8 + (0xC*1), T1ReadLong(MMU.ARM7_REG, 0xB8 + (0xC*1)) & 0x7FFFFFFF); + if((MMU.DMACrt[1][1])&(1<<30)) NDS_makeARM7Int(9); + MMU.DMAing[1][1] = FALSE; + } + + if((MMU.DMAing[1][2])&&(MMU.DMACycle[1][2]<=nds.cycles)) + { + T1WriteLong(MMU.ARM7_REG, 0xB8 + (0xC*2), T1ReadLong(MMU.ARM7_REG, 0xB8 + (0xC*2)) & 0x7FFFFFFF); + if((MMU.DMACrt[1][2])&(1<<30)) NDS_makeARM7Int(10); + MMU.DMAing[1][2] = FALSE; + } + + if((MMU.DMAing[1][3])&&(MMU.DMACycle[1][3]<=nds.cycles)) + { + T1WriteLong(MMU.ARM7_REG, 0xB8 + (0xC*3), T1ReadLong(MMU.ARM7_REG, 0xB8 + (0xC*3)) & 0x7FFFFFFF); + if((MMU.DMACrt[1][3])&(1<<30)) NDS_makeARM7Int(11); + MMU.DMAing[1][3] = FALSE; + } + + if((MMU.reg_IF[0]&MMU.reg_IE[0]) && (MMU.reg_IME[0])) + { +#ifdef GDB_STUB + if ( armcpu_flagIrq( &NDS_ARM9)) +#else + if ( armcpu_irqExeption(&NDS_ARM9)) +#endif + { + nds.ARM9Cycle = nds.cycles; + } + } + + if((MMU.reg_IF[1]&MMU.reg_IE[1]) && (MMU.reg_IME[1])) + { +#ifdef GDB_STUB + if ( armcpu_flagIrq( &NDS_ARM7)) +#else + if ( armcpu_irqExeption(&NDS_ARM7)) +#endif + { + nds.ARM7Cycle = nds.cycles; + } + } + +} + +static void timer_check(void) +{ + int p, t; + for (p = 0; p < 2; p++) + { + for (t = 0; t < 4; t++) + { + nds.timerOver[p][t] = 0; + if(MMU.timerON[p][t]) + { + if(MMU.timerRUN[p][t]) + { + switch(MMU.timerMODE[p][t]) + { + case 0xFFFF : + if(t > 0 && nds.timerOver[p][t - 1]) + { + ++(MMU.timer[p][t]); + nds.timerOver[p][t] = !MMU.timer[p][t]; + if (nds.timerOver[p][t]) + { + if (p == 0) + { + if(T1ReadWord(ARM9Mem.ARM9_REG, 0x102 + (t << 2)) & 0x40) + NDS_makeARM9Int(3 + t); + } + else + { + if(T1ReadWord(MMU.ARM7_REG, 0x102 + (t << 2)) & 0x40) + NDS_makeARM7Int(3 + t); + } + MMU.timer[p][t] = MMU.timerReload[p][t]; + } + } + break; + default : + { + nds.diff = (nds.cycles >> MMU.timerMODE[p][t]) - (nds.timerCycle[p][t] >> MMU.timerMODE[p][t]); + nds.old = MMU.timer[p][t]; + MMU.timer[p][t] += nds.diff; + nds.timerCycle[p][t] += nds.diff << MMU.timerMODE[p][t]; + nds.timerOver[p][t] = nds.old >= MMU.timer[p][t]; + if(nds.timerOver[p][t]) + { + if (p == 0) + { + if(T1ReadWord(ARM9Mem.ARM9_REG, 0x102 + (t << 2)) & 0x40) + NDS_makeARM9Int(3 + t); + } + else + { + if(T1ReadWord(MMU.ARM7_REG, 0x102 + (t << 2)) & 0x40) + NDS_makeARM7Int(3 + t); + } + MMU.timer[p][t] = MMU.timerReload[p][t] + MMU.timer[p][t] - nds.old; + } + } + break; + } + } + else + { + MMU.timerRUN[p][t] = TRUE; + nds.timerCycle[p][t] = nds.cycles; + } + } + } + } +} + +void NDS_exec_hframe(int cpu_clockdown_level_arm9, int cpu_clockdown_level_arm7) +{ + int h; + for (h = 0; h < 2; h++) + { + s32 nb = nds.cycles + (h ? (99 * 12) : (256 * 12)); + + while (nb > nds.ARM9Cycle && !NDS_ARM9.waitIRQ) + nds.ARM9Cycle += armcpu_exec(&NDS_ARM9) << (cpu_clockdown_level_arm9); + if (NDS_ARM9.waitIRQ) nds.ARM9Cycle = nb; + while (nb > nds.ARM7Cycle && !NDS_ARM7.waitIRQ) + nds.ARM7Cycle += armcpu_exec(&NDS_ARM7) << (1 + (cpu_clockdown_level_arm7)); + if (NDS_ARM7.waitIRQ) nds.ARM7Cycle = nb; + nds.cycles = (nds.ARM9Cycle>8)|((vmatch<<1)&(1<<8)))) + { + T1WriteWord(ARM9Mem.ARM9_REG, 4, T1ReadWord(ARM9Mem.ARM9_REG, 4) | 4); + if(T1ReadWord(ARM9Mem.ARM9_REG, 4) & 32) + NDS_makeARM9Int(2); + } + else + T1WriteWord(ARM9Mem.ARM9_REG, 4, T1ReadWord(ARM9Mem.ARM9_REG, 4) & 0xFFFB); + + vmatch = T1ReadWord(MMU.ARM7_REG, 4); + if((nds.VCount==(vmatch>>8)|((vmatch<<1)&(1<<8)))) + { + T1WriteWord(MMU.ARM7_REG, 4, T1ReadWord(MMU.ARM7_REG, 4) | 4); + if(T1ReadWord(MMU.ARM7_REG, 4) & 32) + NDS_makeARM7Int(2); + } + else + T1WriteWord(MMU.ARM7_REG, 4, T1ReadWord(MMU.ARM7_REG, 4) & 0xFFFB); + + timer_check(); + dma_check(); + } + } +} + +void NDS_exec_frame(int cpu_clockdown_level_arm9, int cpu_clockdown_level_arm7) +{ + int v; + for (v = 0; v < 263; v++) + { + NDS_exec_hframe(cpu_clockdown_level_arm9, cpu_clockdown_level_arm7); + } +} + diff -r fe2ba1a712cd -r 70b0973e7b70 src/xsf/desmume/NDSSystem.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/xsf/desmume/NDSSystem.h Thu Oct 16 14:45:41 2008 -0500 @@ -0,0 +1,255 @@ +/* Copyright (C) 2006 yopyop + yopyop156@ifrance.com + yopyop156.ifrance.com + + This file is part of DeSmuME + + DeSmuME is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DeSmuME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DeSmuME; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef NDSSYSTEM_H +#define NDSSYSTEM_H + +#include "armcpu.h" +#include "MMU.h" + +#include "GPU.h" +#include "SPU.h" + +#include "mem.h" +//#include "wifi.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +extern volatile BOOL execute; +extern BOOL click; + +/* + * The firmware language values + */ +#define NDS_FW_LANG_JAP 0 +#define NDS_FW_LANG_ENG 1 +#define NDS_FW_LANG_FRE 2 +#define NDS_FW_LANG_GER 3 +#define NDS_FW_LANG_ITA 4 +#define NDS_FW_LANG_SPA 5 +#define NDS_FW_LANG_CHI 6 +#define NDS_FW_LANG_RES 7 + + +//#define LOG_ARM9 +//#define LOG_ARM7 + +typedef struct +{ + char gameTile[12]; + char gameCode[4]; + u16 makerCode; + u8 unitCode; + u8 deviceCode; + u8 cardSize; + u8 cardInfo[8]; + u8 flags; + + u32 ARM9src; + u32 ARM9exe; + u32 ARM9cpy; + u32 ARM9binSize; + + u32 ARM7src; + u32 ARM7exe; + u32 ARM7cpy; + u32 ARM7binSize; + + u32 FNameTblOff; + u32 FNameTblSize; + + u32 FATOff; + u32 FATSize; + + u32 ARM9OverlayOff; + u32 ARM9OverlaySize; + u32 ARM7OverlayOff; + u32 ARM7OverlaySize; + + u32 unknown2a; + u32 unknown2b; + + u32 IconOff; + u16 CRC16; + u16 ROMtimeout; + u32 ARM9unk; + u32 ARM7unk; + + u8 unknown3c[8]; + u32 ROMSize; + u32 HeaderSize; + u8 unknown5[56]; + u8 logo[156]; + u16 logoCRC16; + u16 headerCRC16; + u8 reserved[160]; +} NDS_header; + +extern void debug(); + +typedef struct +{ + s32 ARM9Cycle; + s32 ARM7Cycle; + s32 cycles; + s32 timerCycle[2][4]; + BOOL timerOver[2][4]; + s32 nextHBlank; + u32 VCount; + u32 old; + s32 diff; + BOOL lignerendu; + + u16 touchX; + u16 touchY; +} NDSSystem; + +/** /brief A touchscreen calibration point. + */ +struct NDS_fw_touchscreen_cal { + u16 adc_x; + u16 adc_y; + + u8 screen_x; + u8 screen_y; +}; + +/** /brief The type of DS + */ +enum nds_fw_ds_type { + NDS_FW_DS_TYPE_FAT, + NDS_FW_DS_TYPE_LITE +}; + +#define MAX_FW_NICKNAME_LENGTH 10 +#define MAX_FW_MESSAGE_LENGTH 26 + +struct NDS_fw_config_data { + enum nds_fw_ds_type ds_type; + + u8 fav_colour; + u8 birth_month; + u8 birth_day; + + u16 nickname[MAX_FW_NICKNAME_LENGTH]; + u8 nickname_len; + + u16 message[MAX_FW_MESSAGE_LENGTH]; + u8 message_len; + + u8 language; + + /* touchscreen calibration */ + struct NDS_fw_touchscreen_cal touch_cal[2]; +}; + +extern NDSSystem nds; + +#ifdef GDB_STUB +int NDS_Init( struct armcpu_memory_iface *arm9_mem_if, + struct armcpu_ctrl_iface **arm9_ctrl_iface, + struct armcpu_memory_iface *arm7_mem_if, + struct armcpu_ctrl_iface **arm7_ctrl_iface); +#else +int NDS_Init ( void); +#endif + +void NDS_DeInit(void); +void +NDS_FillDefaultFirmwareConfigData( struct NDS_fw_config_data *fw_config); + +BOOL NDS_SetROM(u8 * rom, u32 mask); +NDS_header * NDS_getROMHeader(void); + +void NDS_setTouchPos(u16 x, u16 y); +void NDS_releasTouch(void); + +int NDS_LoadROM(const char *filename, int bmtype, u32 bmsize, + const char *cflash_disk_image_file); +void NDS_FreeROM(void); +void NDS_Reset(void); +int NDS_ImportSave(const char *filename); + +int NDS_WriteBMP(const char *filename); +int NDS_LoadFirmware(const char *filename); +int NDS_CreateDummyFirmware( struct NDS_fw_config_data *user_settings); +u32 +NDS_exec(s32 nb, BOOL force); + + static INLINE void NDS_ARM9HBlankInt(void) + { + if(T1ReadWord(ARM9Mem.ARM9_REG, 4) & 0x10) + { + MMU.reg_IF[0] |= 2;// & (MMU.reg_IME[0] << 1);// (MMU.reg_IE[0] & (1<<1)); + NDS_ARM9.wIRQ = TRUE; + } + } + + static INLINE void NDS_ARM7HBlankInt(void) + { + if(T1ReadWord(MMU.ARM7_REG, 4) & 0x10) + { + MMU.reg_IF[1] |= 2;// & (MMU.reg_IME[1] << 1);// (MMU.reg_IE[1] & (1<<1)); + NDS_ARM7.wIRQ = TRUE; + } + } + + static INLINE void NDS_ARM9VBlankInt(void) + { + if(T1ReadWord(ARM9Mem.ARM9_REG, 4) & 0x8) + { + MMU.reg_IF[0] |= 1;// & (MMU.reg_IME[0]);// (MMU.reg_IE[0] & 1); + NDS_ARM9.wIRQ = TRUE; + //execute = FALSE; + /*logcount++;*/ + } + } + + static INLINE void NDS_ARM7VBlankInt(void) + { + if(T1ReadWord(MMU.ARM7_REG, 4) & 0x8) + MMU.reg_IF[1] |= 1;// & (MMU.reg_IME[1]);// (MMU.reg_IE[1] & 1); + NDS_ARM7.wIRQ = TRUE; + //execute = FALSE; + } + + static INLINE void NDS_swapScreen(void) + { + u16 tmp = MainScreen.offset; + MainScreen.offset = SubScreen.offset; + SubScreen.offset = tmp; + } + + + +void NDS_exec_frame(int cpu_clockdown_level_arm9, int cpu_clockdown_level_arm7); +void NDS_exec_hframe(int cpu_clockdown_level_arm9, int cpu_clockdown_level_arm7); + +#ifdef __cplusplus +} +#endif + +#endif + + diff -r fe2ba1a712cd -r 70b0973e7b70 src/xsf/desmume/SPU.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/xsf/desmume/SPU.c Thu Oct 16 14:45:41 2008 -0500 @@ -0,0 +1,961 @@ +/* Copyright (C) 2006 Theo Berkau + + Ideas borrowed from Stephane Dallongeville's SCSP core + + This file is part of DeSmuME + + DeSmuME is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DeSmuME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DeSmuME; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include +#include + +#include "ARM9.h" +#include "MMU.h" +#include "SPU.h" +#include "mem.h" + +#include "armcpu.h" + +enum +{ + FORMAT_PCM8 = 0, + FORMAT_PCM16 = 1, + FORMAT_ADPCM = 2, + FORMAT_PSG = 3 +}; + +#define VOL_SHIFT 10 + +typedef struct +{ + int id; + int status; + int format; + u8 *buf8; s16 *buf16; + double pos, inc; + int loopend, looppos; + int loop, length; + s32 adpcm; + int adpcm_pos, adpcm_index; + s32 adpcm_loop; + int adpcm_loop_pos, adpcm_loop_index; + int psg_duty; + int timer; + int volume; + int pan; + int shift; + int repeat, hold; + u32 addr; + s32 volumel; + s32 volumer; + s16 output; +} SChannel; + +typedef struct +{ + s32 *pmixbuf; + s16 *pclipingbuf; + u32 buflen; + SChannel ch[16]; +} SPU_struct; + +static SPU_struct spu = { 0, 0, 0 }; + +static SoundInterface_struct *SNDCore=NULL; +extern SoundInterface_struct *SNDCoreList[]; + +int SPU_ChangeSoundCore(int coreid, int buffersize) +{ + int i; + SPU_DeInit(); + + // Allocate memory for sound buffer + spu.buflen = buffersize * 2; /* stereo */ + spu.pmixbuf = malloc(spu.buflen * sizeof(s32)); + if (!spu.pmixbuf) + { + SPU_DeInit(); + return -1; + } + + spu.pclipingbuf = malloc(spu.buflen * sizeof(s16)); + if (!spu.pclipingbuf) + { + SPU_DeInit(); + return -1; + } + + // So which core do we want? + if (coreid == SNDCORE_DEFAULT) + coreid = 0; // Assume we want the first one + + // Go through core list and find the id + for (i = 0; SNDCoreList[i] != NULL; i++) + { + if (SNDCoreList[i]->id == coreid) + { + // Set to current core + SNDCore = SNDCoreList[i]; + break; + } + } + + if (SNDCore == NULL) + { + SPU_DeInit(); + return -1; + } + + if (SNDCore->Init(spu.buflen) == -1) + { + // Since it failed, instead of it being fatal, we'll just use the dummy + // core instead + SNDCore = &SNDDummy; + } + + return 0; +} +int SPU_Init(int coreid, int buffersize) +{ + SPU_DeInit(); + SPU_Reset(); + return SPU_ChangeSoundCore(coreid, buffersize); +} +void SPU_Pause(int pause) +{ + if(pause) + SNDCore->MuteAudio(); + else + SNDCore->UnMuteAudio(); +} +void SPU_SetVolume(int volume) +{ + if (SNDCore) + SNDCore->SetVolume(volume); +} +void SPU_DeInit(void) +{ + spu.buflen = 0; + if (spu.pmixbuf) + { + free(spu.pmixbuf); + spu.pmixbuf = 0; + } + if (spu.pclipingbuf) + { + free(spu.pclipingbuf); + spu.pclipingbuf = 0; + } + if (SNDCore) + { + SNDCore->DeInit(); + } + SNDCore = &SNDDummy; +} + +static const short g_adpcm_index[16] = { -1, -1, -1, -1, -1, -1, -1, -1, 2, 2, 4, 4, 6, 6, 8, 8 }; + +static const int g_adpcm_mult[89] = +{ + 0x0007, 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x0010, 0x0011, + 0x0013, 0x0015, 0x0017, 0x0019, 0x001C, 0x001F, 0x0022, 0x0025, 0x0029, 0x002D, + 0x0032, 0x0037, 0x003C, 0x0042, 0x0049, 0x0050, 0x0058, 0x0061, 0x006B, 0x0076, + 0x0082, 0x008F, 0x009D, 0x00AD, 0x00BE, 0x00D1, 0x00E6, 0x00FD, 0x0117, 0x0133, + 0x0151, 0x0173, 0x0198, 0x01C1, 0x01EE, 0x0220, 0x0256, 0x0292, 0x02D4, 0x031C, + 0x036C, 0x03C3, 0x0424, 0x048E, 0x0502, 0x0583, 0x0610, 0x06AB, 0x0756, 0x0812, + 0x08E0, 0x09C3, 0x0ABD, 0x0BD0, 0x0CFF, 0x0E4C, 0x0FBA, 0x114C, 0x1307, 0x14EE, + 0x1706, 0x1954, 0x1BDC, 0x1EA5, 0x21B6, 0x2515, 0x28CA, 0x2CDF, 0x315B, 0x364B, + 0x3BB9, 0x41B2, 0x4844, 0x4F7E, 0x5771, 0x602F, 0x69CE, 0x7462, 0x7FFF, +}; + +static const s16 g_psg_duty[8][8] = { + { -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, +0x7FFF }, + { -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, +0x7FFF, +0x7FFF }, + { -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, +0x7FFF, +0x7FFF, +0x7FFF }, + { -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, +0x7FFF, +0x7FFF, +0x7FFF, +0x7FFF }, + { -0x7FFF, -0x7FFF, -0x7FFF, +0x7FFF, +0x7FFF, +0x7FFF, +0x7FFF, +0x7FFF }, + { -0x7FFF, -0x7FFF, +0x7FFF, +0x7FFF, +0x7FFF, +0x7FFF, +0x7FFF, +0x7FFF }, + { -0x7FFF, +0x7FFF, +0x7FFF, +0x7FFF, +0x7FFF, +0x7FFF, +0x7FFF, +0x7FFF }, + { -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF }, +}; + + +static void reset_channel(SChannel *ch, int id) +{ + ch->status = 0; + ch->id = id; +} + +void SPU_Reset(void) +{ + int i; + for (i = 0;i < 16; i++) + reset_channel(&spu.ch[i], i); + + for (i = 0x400; i < 0x51D; i++) + T1WriteByte(MMU.ARM7_REG, i, 0); +} +void SPU_KeyOn(int channel) +{ +} + +static INLINE void adjust_channel_timer(SChannel *ch) +{ + ch->inc = (((double)33512000) / (44100 * 2)) / (double)(0x10000 - ch->timer); +} + +static int check_valid(u32 addr, u32 size) +{ + u32 t1, t2; + + if(size > MMU.MMU_MASK[1][(addr >> 20) & 0xff]) return 0; + + t1 = addr; + t2 = (addr + size); + t1 &= MMU.MMU_MASK[1][(addr >> 20) & 0xff]; + t2 &= MMU.MMU_MASK[1][(addr >> 20) & 0xff]; + + if(t2 < t1) return 0; + + return 1; +} + +static void start_channel(SChannel *ch) +{ + + switch(ch->format) + { + case FORMAT_PCM8: + { + u8 *p = MMU.MMU_MEM[1][(ch->addr >> 20) & 0xff]; + u32 ofs = MMU.MMU_MASK[1][(ch->addr >> 20) & 0xff] & ch->addr; + u32 size = ((ch->length + ch->loop) << 2); + if((p != NULL) && check_valid(ch->addr, size)) + { + ch->buf8 = p + ofs; + ch->looppos = ch->loop << 2; + ch->loopend = size; + ch->pos = 0; + ch->status = 1; + } + } + break; + case FORMAT_PCM16: + { + u8 *p = MMU.MMU_MEM[1][(ch->addr >> 20) & 0xff]; + u32 ofs = MMU.MMU_MASK[1][(ch->addr >> 20) & 0xff] & ch->addr; + u32 size = ((ch->length + ch->loop) << 1); + if((p != NULL) && check_valid(ch->addr, size << 1)) + { + ch->buf16 = (s16 *)(p + ofs - (ofs & 1)); + ch->looppos = ch->loop << 1; + ch->loopend = size; + ch->pos = 0; + ch->status = 1; + } + } + break; + case FORMAT_ADPCM: + { + u8 *p = MMU.MMU_MEM[1][(ch->addr >> 20) & 0xff]; + u32 ofs = MMU.MMU_MASK[1][(ch->addr >> 20) & 0xff] & ch->addr; + u32 size = ((ch->length + ch->loop) << 3); + if((p != NULL) && check_valid(ch->addr, size >> 1)) + { + ch->buf8 = p + ofs; +#ifdef WORDS_BIGENDIAN + ch->adpcm = ((s32)(s16)T1ReadWord((u8 *)ch->buf8, 0)) << 3; +#else + ch->adpcm = ((s32)*(s16 *)ch->buf8) << 3; +#endif + ch->adpcm_index = (ch->buf8[2] & 0x7F); + ch->adpcm_pos = 8; + ch->pos = 9; + ch->looppos = ch->loop << 3; + ch->loopend = size; + ch->adpcm_loop_index = -1; + ch->status = 1; + } + } + break; + case FORMAT_PSG: + ch->status = 1; + if(ch->id < 14) + { + ch->pos = 0; + } + else + { + ch->pos = 0x7FFF; + } + break; + } +} + +static void stop_channel(SChannel *ch) +{ + u32 addr = 0x400 + (ch->id << 4) + 3; + ch->status = 0; + T1WriteByte(MMU.ARM7_REG, addr, (u8)(T1ReadByte(MMU.ARM7_REG, addr) & ~0x80)); +} +static void set_channel_volume(SChannel *ch) +{ + s32 vol1 = (T1ReadByte(MMU.ARM7_REG, 0x500) & 0x7F) * ch->volume; + s32 vol2; + vol2 = vol1 * ch->pan; + vol1 = vol1 * (127-ch->pan); + ch->volumel = vol1 >> (21 - VOL_SHIFT + ch->shift); + ch->volumer = vol2 >> (21 - VOL_SHIFT + ch->shift); +} + +void SPU_WriteByte(u32 addr, u8 x) +{ + addr &= 0x00000FFF; + T1WriteByte(MMU.ARM7_REG, addr, x); + + if(addr < 0x500) + { + SChannel *ch; + switch(addr & 0x0F) + { + case 0x0: + ch = spu.ch + (addr >> 4 & 0xF); + ch->volume = (x & 0x7F); + set_channel_volume(ch); + break; + case 0x1: + ch = spu.ch + (addr >> 4 & 0xF); + ch->shift = (x & 0x03); + ch->hold = (x >> 7 & 0x01); + set_channel_volume(ch); + break; + case 0x2: + ch = spu.ch + (addr >> 4 & 0xF); + ch->pan = (x & 0x7F); + set_channel_volume(ch); + break; + case 0x3: + ch = spu.ch + (addr >> 4 & 0xF); + ch->psg_duty = (x & 0x07); + ch->repeat = (x >> 3 & 0x03); + ch->format = (x >> 5 & 0x03); + if(x & 0x80) start_channel(ch); else stop_channel(ch); + break; +#if !DISABLE_XSF_TESTS + case 0x04: + case 0x05: + case 0x06: + case 0x07: + ch = spu.ch + (addr >> 4 & 0xF); + ch->addr = (T1ReadLong(MMU.ARM7_REG, addr & ~3) & 0x07FFFFFF); + break; + case 0x08: + case 0x09: + ch = spu.ch + (addr >> 4 & 0xF); + ch->timer = T1ReadWord(MMU.ARM7_REG, addr & ~1); + adjust_channel_timer(ch); + break; + case 0x0a: + case 0x0b: + ch = spu.ch + (addr >> 4 & 0xF); + ch->loop = T1ReadWord(MMU.ARM7_REG, addr & ~1); + break; + case 0x0c: + case 0x0e: + case 0x0d: + case 0x0f: + ch = spu.ch + (addr >> 4 & 0xF); + ch->length = (T1ReadLong(MMU.ARM7_REG, addr & ~3) & 0x003FFFFF); + break; +#endif + } + } + +} + + +void SPU_WriteWord(u32 addr, u16 x) +{ + addr &= 0x00000FFF; + T1WriteWord(MMU.ARM7_REG, addr, x); + + if(addr < 0x500) + { + SChannel *ch; + switch(addr & 0x00F) + { + case 0x0: + ch = spu.ch + (addr >> 4 & 0xF); + ch->volume = (x & 0x007F); + ch->shift = (x >> 8 & 0x0003); + ch->hold = (x >> 15 & 0x0001); + set_channel_volume(ch); + break; + case 0x2: + ch = spu.ch + (addr >> 4 & 0xF); + ch->pan = (x & 0x007F); + ch->psg_duty = (x >> 8 & 0x0007); + ch->repeat = (x >> 11 & 0x0003); + ch->format = (x >> 13 & 0x0003); + set_channel_volume(ch); + if(x & 0x8000) start_channel(ch); else stop_channel(ch); + break; + case 0x08: + ch = spu.ch + (addr >> 4 & 0xF); + ch->timer = x; + adjust_channel_timer(ch); + break; + case 0x0a: + ch = spu.ch + (addr >> 4 & 0xF); + ch->loop = x; + break; +#if !DISABLE_XSF_TESTS + case 0x04: + case 0x06: + ch = spu.ch + (addr >> 4 & 0xF); + ch->addr = (T1ReadLong(MMU.ARM7_REG, addr & ~3) & 0x07FFFFFF); + break; + case 0x0c: + case 0x0e: + ch = spu.ch + (addr >> 4 & 0xF); + ch->length = (T1ReadLong(MMU.ARM7_REG, addr & ~3) & 0x003FFFFF); + break; +#endif + } + } +} + + +void SPU_WriteLong(u32 addr, u32 x) +{ + addr &= 0x00000FFF; + T1WriteLong(MMU.ARM7_REG, addr, x); + + if(addr < 0x500) + { + SChannel *ch; + switch(addr & 0x00F) + { + case 0x0: + ch = spu.ch + (addr >> 4 & 0xF); + ch->volume = (x & 0x7F); + ch->shift = (x >> 8 & 0x00000003); + ch->hold = (x >> 15 & 0x00000001); + ch->pan = (x >> 16 & 0x0000007F); + ch->psg_duty = (x >> 24 & 0x00000007); + ch->repeat = (x >> 27 & 0x00000003); + ch->format = (x >> 29 & 0x00000003); + set_channel_volume(ch); + if(x & 0x80000000) start_channel(ch); else stop_channel(ch); + break; + case 0x04: + ch = spu.ch + (addr >> 4 & 0xF); + ch->addr = (x & 0x07FFFFFF); + break; + case 0x08: + ch = spu.ch + (addr >> 4 & 0xF); + ch->timer = (x & 0x0000FFFF); + ch->loop = (x >> 16 & 0x0000FFFF); + adjust_channel_timer(ch); + break; + case 0x0C: + ch = spu.ch + (addr >> 4 & 0xF); + ch->length = (x & 0x003FFFFF); + break; + } + } +} + +////////////////////////////////////////////////////////////////////////////// + +u32 SPU_ReadLong(u32 addr) +{ + addr &= 0xFFF; + return T1ReadLong(MMU.ARM7_REG, addr); +} + +static INLINE s32 clipping(s32 x, s32 min, s32 max) { +#if 1 || defined(SIGNED_IS_NOT_2S_COMPLEMENT) + if (x < min) + { + return (min); + } + else if (x > max) + { + return (max); + } + return (x); +#else + return x ^ ((-(x < min)) & (x ^ min)) ^ ((-(x > max)) & (x ^ max)); +#endif +} + +extern unsigned long dwChannelMute; + +static void decode_pcm8(SChannel *ch, s32 *out, int length) +{ + int oi; + double pos, inc, len; + if (!ch->buf8) return; + + pos = ch->pos; inc = ch->inc; len = ch->loopend; + + for(oi = 0; oi < length; oi++) + { + ch->output = ((s16)(s8)ch->buf8[(int)pos]) << 8; +#if 0 + if (dwChannelMute & (1 << ch->id)) + { + out++; + out++; + } + else +#endif + { + *(out++) += (ch->output * ch->volumel) >> VOL_SHIFT; + *(out++) += (ch->output * ch->volumer) >> VOL_SHIFT; + } + pos += inc; + if(pos >= len) + { + switch(ch->repeat) + { +#if !DISABLE_XSF_TESTS + case 0: +#endif + case 1: + pos += ch->looppos - len; + break; + default: + stop_channel(ch); + oi = length; + break; + } + } + } + + ch->pos = pos; + return; +} + +static void decode_pcm16(SChannel *ch, s32 *out, int length) +{ + int oi; + double pos, inc, len; + + if (!ch->buf16) return; + + pos = ch->pos; inc = ch->inc; len = ch->loopend; + + for(oi = 0; oi < length; oi++) + { +#ifdef WORDS_BIGENDIAN + ch->output = (s16)T1ReadWord((u8 *)ch->buf16, pos << 1); +#else + ch->output = (s16)ch->buf16[(int)pos]; +#endif +#if 0 + if (dwChannelMute & (1 << ch->id)) + { + out++; + out++; + } + else +#endif + { + *(out++) += (ch->output * ch->volumel) >> VOL_SHIFT; + *(out++) += (ch->output * ch->volumer) >> VOL_SHIFT; + } + pos += inc; + if(pos >= len) + { + switch(ch->repeat) + { +#if !DISABLE_XSF_TESTS + case 0: +#endif + case 1: + pos += ch->looppos - len; + break; + default: + stop_channel(ch); + oi = length; + break; + } + } + } + + ch->pos = pos; +} + +static INLINE void decode_adpcmone_P4(SChannel *ch, int m) +{ + int i, ci0; + u8 *p; + s32 s; + int N; + + i = ch->adpcm_pos; + p = (ch->buf8 + (i >> 1)); + ci0 = ch->adpcm_index; + s = ch->adpcm; + + if (ch->adpcm_loop_index < 0 && m >= ch->looppos) + { + ch->adpcm_loop_index = ci0; + ch->adpcm_loop = s; + ch->adpcm_loop_pos = i; + } + + if(i++ & 1) + { + s32 x1, d1; + x1 = ((*(p++) >> 3) & 0x1F | 1); + d1 = ((x1 & 0xF) * g_adpcm_mult[ci0] & ~7); + ci0 = clipping((ci0 + g_adpcm_index[x1 & 0xE]), 0, 88); +#if 1 || defined(SIGNED_IS_NOT_2S_COMPLEMENT) + if(x1 & 0x10) d1 = -d1; +#else + d1 -= (d1 + d1) & (-(((x1 >> 4) & 1))); +#endif + + s = clipping((s + d1), (-32768 << 3), (32767 << 3)); + } + + N = (((m & ~1) - (i & ~1)) >> 1); + for(i = 0; i < N; i++) + { + s32 x0, d0; + s32 x1, d1; + int ci1; + x0 = ((*p << 1) & 0x1F | 1); + x1 = ((*p >> 3) & 0x1F | 1); + ci1 = clipping((ci0 + g_adpcm_index[x0 & 0xE]), 0, 88); + d0 = ((x0 & 0xF) * g_adpcm_mult[ci0] & ~7); + ci0 = clipping((ci1 + g_adpcm_index[x1 & 0xE]), 0, 88); + d1 = ((x1 & 0xF) * g_adpcm_mult[ci1] & ~7); +#if 1 || defined(SIGNED_IS_NOT_2S_COMPLEMENT) + if(x0 & 0x10) d0 = -d0; + if(x1 & 0x10) d1 = -d1; +#else + d0 -= (d0 + d0) & (-(((x0 >> 4) & 1))); + d1 -= (d1 + d1) & (-(((x1 >> 4) & 1))); +#endif + s = clipping((s + d0), (-32768 << 3), (32767 << 3)); + s = clipping((s + d1), (-32768 << 3), (32767 << 3)); + p++; + } + if(m & 1) + { + s32 x0, d0; + x0 = ((*p << 1) & 0x1F | 1); + d0 = ((x0 & 0xF) * g_adpcm_mult[ci0] & ~7); + ci0 = clipping((ci0 + g_adpcm_index[x0 & 0xE]), 0, 88); +#if 1 || defined(SIGNED_IS_NOT_2S_COMPLEMENT) + if(x0 & 0x10) d0 = -d0; +#else + d0 -= (d0 + d0) & (-(((x0 >> 4) & 1))); +#endif + s = clipping((s + d0), (-32768 << 3), (32767 << 3)); + } + + ch->output = (s16)(s >> 3); + + ch->adpcm = s; + ch->adpcm_index = ci0; + ch->adpcm_pos = m; +} + +static INLINE void decode_adpcmone_XX(SChannel *ch, int m) +{ + int i, ci0; + u8 *p; + s32 s; + + i = ch->adpcm_pos; + p = (ch->buf8 + (i >> 1)); + ci0 = ch->adpcm_index; + s = ch->adpcm; + + if (ch->adpcm_loop_index < 0 && m >= ch->looppos) + { + ch->adpcm_loop_index = ci0; + ch->adpcm_loop = s; + ch->adpcm_loop_pos = i; + } + + while (i < m) + { + s32 x1, d1; + x1 = ((s32)*p) >> ((i & 1) << 2) & 0xf; + x1 = x1 + x1 + 1; + d1 = ((x1 & 0xF) * g_adpcm_mult[ci0] & ~7); + ci0 = clipping((ci0 + g_adpcm_index[x1 & 0xE]), 0, 88); +#if 1 || defined(SIGNED_IS_NOT_2S_COMPLEMENT) + if(x1 & 0x10) d1 = -d1; +#else + d1 -= (d1 + d1) & (-(((x1 >> 4) & 1))); +#endif + + s = clipping((s + d1), (-32768 << 3), (32767 << 3)); + p += (i & 1); + i++; + } + + ch->output = (s16)(s >> 3); + + ch->adpcm = s; + ch->adpcm_index = ci0; + ch->adpcm_pos = m; +} + +#define decode_adpcmone decode_adpcmone_P4 + +static void decode_adpcm(SChannel *ch, s32 *out, int length) +{ + int oi; + double pos, inc, len; + if (!ch->buf8) return; + + pos = ch->pos; inc = ch->inc; len = ch->loopend; + + for(oi = 0; oi < length; oi++) + { + int m = (int)pos; + int i = ch->adpcm_pos; + if(i < m) + decode_adpcmone(ch, m); + +#if 0 + if (dwChannelMute & (1 << ch->id)) + { + out++; + out++; + } + else +#endif + { + *(out++) += (ch->output * ch->volumel) >> VOL_SHIFT; + *(out++) += (ch->output * ch->volumer) >> VOL_SHIFT; + } + pos += inc; + if(pos >= len) + { + switch(ch->repeat) + { + case 1: + if (ch->adpcm_loop_index >= 0) + { + pos += ch->looppos - len; + ch->adpcm_pos = ch->adpcm_loop_pos; + ch->adpcm_index = ch->adpcm_loop_index; + ch->adpcm = ch->adpcm_loop; + break; + } +#if !DISABLE_XSF_TESTS + case 0: + pos = 9 - len; +#ifdef WORDS_BIGENDIAN + ch->adpcm = ((s32)(s16)T1ReadWord((u8 *)ch->buf8, 0)) << 3; +#else + ch->adpcm = ((s32)*(s16 *)ch->buf8) << 3; +#endif + ch->adpcm_index = (ch->buf8[2] & 0x7F); + ch->adpcm_pos = 8; + break; +#endif + default: + stop_channel(ch); + oi = length; + break; + } + } + } + ch->pos = pos; +} + +static void decode_psg(SChannel *ch, s32 *out, int length) +{ + int oi; + + if(ch->id < 14) + { + // NOTE: square wave. + double pos, inc, len; + pos = ch->pos; inc = ch->inc; len = ch->length; + for(oi = 0; oi < length; oi++) + { + ch->output = (s16)g_psg_duty[ch->psg_duty][(int)pos & 0x00000007]; +#if 0 + if (dwChannelMute & (1 << ch->id)) + { + out++; + out++; + } + else +#endif + { + *(out++) += (ch->output * ch->volumel) >> VOL_SHIFT; + *(out++) += (ch->output * ch->volumer) >> VOL_SHIFT; + } + pos += inc; + } + ch->pos = pos; + } + else + { + // NOTE: noise. + u16 X; + X = (u16)ch->pos; + for(oi = 0; oi < length; oi++) + { + if(X & 1) + { + X >>= 1; + X ^= 0x6000; + ch->output = -0x8000; + } + else + { + X >>= 1; + ch->output = +0x7FFF; + } + } +#if 0 + if (dwChannelMute & (1 << ch->id)) + { + out++; + out++; + } + else +#endif + { + *(out++) += (ch->output * ch->volumel) >> VOL_SHIFT; + *(out++) += (ch->output * ch->volumer) >> VOL_SHIFT; + } + ch->pos = X; + } +} + + + +void SPU_EmulateSamples(u32 numsamples) +{ + u32 sizesmp = numsamples; + u32 sizebyte = sizesmp << 2; + if (sizebyte > spu.buflen * sizeof(s16)) sizebyte = spu.buflen * sizeof(s16); + sizesmp = sizebyte >> 2; + sizebyte = sizesmp << 2; + if (sizesmp > 0) + { + unsigned i; + SChannel *ch = spu.ch; + memset(spu.pmixbuf, 0, spu.buflen * sizeof(s32)); + for (i = 0; i < 16; i++) + { + if (ch->status) + { + switch (ch->format) + { + case 0: + decode_pcm8(ch, spu.pmixbuf, sizesmp); + break; + case 1: + decode_pcm16(ch, spu.pmixbuf, sizesmp); + break; + case 2: + decode_adpcm(ch, spu.pmixbuf, sizesmp); + break; + case 3: + decode_psg(ch, spu.pmixbuf, sizesmp); + break; + } + } + ch++; + } + for (i = 0; i < sizesmp * 2; i++) + spu.pclipingbuf[i] = (s16)clipping(spu.pmixbuf[i], -0x8000, 0x7fff); + SNDCore->UpdateAudio(spu.pclipingbuf, sizesmp); + } +} + +void SPU_Emulate(void) +{ + SPU_EmulateSamples(SNDCore->GetAudioSpace()); +} + + +////////////////////////////////////////////////////////////////////////////// +// Dummy Sound Interface +////////////////////////////////////////////////////////////////////////////// + +static int SNDDummyInit(int buffersize) +{ + return 0; +} + +////////////////////////////////////////////////////////////////////////////// + +static void SNDDummyDeInit() +{ +} + +////////////////////////////////////////////////////////////////////////////// + +static void SNDDummyUpdateAudio(s16 *buffer, u32 num_samples) +{ +} + +////////////////////////////////////////////////////////////////////////////// + +static u32 SNDDummyGetAudioSpace() +{ + return 735; +} + +////////////////////////////////////////////////////////////////////////////// + +static void SNDDummyMuteAudio() +{ +} + +////////////////////////////////////////////////////////////////////////////// + +static void SNDDummyUnMuteAudio() +{ +} + +////////////////////////////////////////////////////////////////////////////// + +static void SNDDummySetVolume(int volume) +{ +} + +////////////////////////////////////////////////////////////////////////////// + +SoundInterface_struct SNDDummy = +{ + SNDCORE_DUMMY, + "Dummy Sound Interface", + SNDDummyInit, + SNDDummyDeInit, + SNDDummyUpdateAudio, + SNDDummyGetAudioSpace, + SNDDummyMuteAudio, + SNDDummyUnMuteAudio, + SNDDummySetVolume +}; + diff -r fe2ba1a712cd -r 70b0973e7b70 src/xsf/desmume/SPU.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/xsf/desmume/SPU.h Thu Oct 16 14:45:41 2008 -0500 @@ -0,0 +1,57 @@ +/* Copyright (C) 2006 Theo Berkau + + This file is part of DeSmuME + + DeSmuME is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DeSmuME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DeSmuME; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef SPU_H +#define SPU_H + +#include "types.h" + +#define SNDCORE_DEFAULT -1 +#define SNDCORE_DUMMY 0 + +typedef struct +{ + int id; + const char *Name; + int (*Init)(int buffersize); + void (*DeInit)(); + void (*UpdateAudio)(s16 *buffer, u32 num_samples); + u32 (*GetAudioSpace)(); + void (*MuteAudio)(); + void (*UnMuteAudio)(); + void (*SetVolume)(int volume); +} SoundInterface_struct; +extern SoundInterface_struct SNDDummy; + + +int SPU_ChangeSoundCore(int coreid, int buffersize); +int SPU_Init(int coreid, int buffersize); +void SPU_Pause(int pause); +void SPU_SetVolume(int volume); +void SPU_Reset(void); +void SPU_DeInit(void); +void SPU_KeyOn(int channel); +void SPU_WriteByte(u32 addr, u8 val); +void SPU_WriteWord(u32 addr, u16 val); +void SPU_WriteLong(u32 addr, u32 val); +u32 SPU_ReadLong(u32 addr); +void SPU_Emulate(void); +void SPU_EmulateSamples(u32 numsamples); + +#endif diff -r fe2ba1a712cd -r 70b0973e7b70 src/xsf/desmume/arm_instructions.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/xsf/desmume/arm_instructions.c Thu Oct 16 14:45:41 2008 -0500 @@ -0,0 +1,7928 @@ +/* Copyright (C) 2006 yopyop + Copyright (C) 2006 shash + yopyop156@ifrance.com + yopyop156.ifrance.com + + Copyright (C) 2006-2007 shash + + This file is part of DeSmuME + + DeSmuME is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DeSmuME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DeSmuME; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "cp15.h" +#include "debug.h" +#include "MMU.h" + + +// Use this macros for reading/writing, so the GDB stub isn't broken +#ifdef GDB_STUB + #define READ32(a,b) cpu->mem_if->read32(a,b) + #define WRITE32(a,b,c) cpu->mem_if->write32(a,b,c) + #define READ16(a,b) cpu->mem_if->read16(a,b) + #define WRITE16(a,b,c) cpu->mem_if->write16(a,b,c) + #define READ8(a,b) cpu->mem_if->read8(a,b) + #define WRITE8(a,b,c) cpu->mem_if->write8(a,b,c) +#else + #define READ32(a,b) MMU_read32(cpu->proc_ID, b) + #define WRITE32(a,b,c) MMU_write32(cpu->proc_ID,b,c) + #define READ16(a,b) MMU_read16(cpu->proc_ID, b) + #define WRITE16(a,b,c) MMU_write16(cpu->proc_ID,b,c) + #define READ8(a,b) MMU_read8(cpu->proc_ID, b) + #define WRITE8(a,b,c) MMU_write8(cpu->proc_ID,b,c) +#endif + + + +#define LSL_IMM shift_op = cpu->R[REG_POS(i,0)]<<((i>>7)&0x1F); + +#define S_LSL_IMM u32 shift_op = ((i>>7)&0x1F);\ + u32 c = cpu->CPSR.bits.C;\ + if(shift_op==0)\ + shift_op=cpu->R[REG_POS(i,0)];\ + else\ + {\ + c = BIT_N(cpu->R[REG_POS(i,0)], 32-shift_op);\ + shift_op = cpu->R[REG_POS(i,0)]<<((i>>7)&0x1F);\ + } + +#define LSL_REG u32 shift_op = (cpu->R[REG_POS(i,8)])&0xFF;\ + if(shift_op>=32)\ + shift_op=0;\ + else\ + shift_op=cpu->R[REG_POS(i,0)]<R[REG_POS(i,8)])&0xFF;\ + u32 c = cpu->CPSR.bits.C;\ + if(shift_op==0)\ + shift_op=cpu->R[REG_POS(i,0)];\ + else\ + if(shift_op<32)\ + {\ + c = BIT_N(cpu->R[REG_POS(i,0)], 32-shift_op);\ + shift_op = cpu->R[REG_POS(i,0)]<R[REG_POS(i,0)]);\ + }\ + else\ + {\ + shift_op = 0;\ + c = 0;\ + } + +#define LSR_IMM shift_op = ((i>>7)&0x1F);\ + if(shift_op!=0)\ + shift_op = cpu->R[REG_POS(i,0)]>>shift_op; + +#define S_LSR_IMM u32 shift_op = ((i>>7)&0x1F);\ + u32 c = cpu->CPSR.bits.C;\ + if(shift_op==0)\ + {\ + c = BIT31(cpu->R[REG_POS(i,0)]);\ + }\ + else\ + {\ + c = BIT_N(cpu->R[REG_POS(i,0)], shift_op-1);\ + shift_op = cpu->R[REG_POS(i,0)]>>shift_op;\ + } + +#define LSR_REG u32 shift_op = (cpu->R[REG_POS(i,8)])&0xFF;\ + if(shift_op>=32)\ + shift_op = 0;\ + else\ + shift_op = cpu->R[REG_POS(i,0)]>>shift_op; + +#define S_LSR_REG u32 shift_op = (cpu->R[REG_POS(i,8)])&0xFF;\ + u32 c = cpu->CPSR.bits.C;\ + if(shift_op==0)\ + {\ + shift_op = cpu->R[REG_POS(i,0)];\ + }\ + else\ + if(shift_op<32)\ + {\ + c = BIT_N(cpu->R[REG_POS(i,0)], shift_op-1);\ + shift_op = cpu->R[REG_POS(i,0)]>>shift_op;\ + }\ + else\ + if(shift_op==32)\ + {\ + c = BIT31(cpu->R[REG_POS(i,0)]);\ + shift_op = 0;\ + }\ + else\ + {\ + c = 0;\ + shift_op = 0;\ + } + +#define ASR_IMM shift_op = ((i>>7)&0x1F);\ + if(shift_op==0)\ + shift_op=BIT31(cpu->R[REG_POS(i,0)])*0xFFFFFFFF;\ + else\ + shift_op = (u32)(((s32)(cpu->R[REG_POS(i,0)]))>>shift_op); + +#define S_ASR_IMM u32 shift_op = ((i>>7)&0x1F);\ + u32 c = cpu->CPSR.bits.C;\ + if(shift_op==0)\ + {\ + shift_op=BIT31(cpu->R[REG_POS(i,0)])*0xFFFFFFFF;\ + c = BIT31(cpu->R[REG_POS(i,0)]);\ + }\ + else\ + {\ + c = BIT_N(cpu->R[REG_POS(i,0)], shift_op-1);\ + shift_op = (u32)(((s32)(cpu->R[REG_POS(i,0)]))>>shift_op);\ + } + +#define ASR_REG u32 shift_op = (cpu->R[REG_POS(i,8)])&0xFF;\ + if(shift_op==0)\ + shift_op=cpu->R[REG_POS(i,0)];\ + else\ + if(shift_op<32)\ + shift_op = (u32)(((s32)(cpu->R[REG_POS(i,0)]))>>shift_op);\ + else\ + shift_op=BIT31(cpu->R[REG_POS(i,0)])*0xFFFFFFFF; + +#define S_ASR_REG u32 shift_op = (cpu->R[REG_POS(i,8)])&0xFF;\ + u32 c = cpu->CPSR.bits.C;\ + if(shift_op==0)\ + shift_op=cpu->R[REG_POS(i,0)];\ + else\ + if(shift_op<32)\ + {\ + c = BIT_N(cpu->R[REG_POS(i,0)], shift_op-1);\ + shift_op = (u32)(((s32)(cpu->R[REG_POS(i,0)]))>>shift_op);\ + }\ + else\ + {\ + c = BIT31(cpu->R[REG_POS(i,0)]);\ + shift_op=BIT31(cpu->R[REG_POS(i,0)])*0xFFFFFFFF;\ + } + +#define ROR_IMM shift_op = ((i>>7)&0x1F);\ + if(shift_op==0)\ + {\ + u32 tmp = cpu->CPSR.bits.C;\ + shift_op = (tmp<<31)|(cpu->R[REG_POS(i,0)]>>1);\ + }\ + else\ + shift_op = ROR(cpu->R[REG_POS(i,0)],shift_op); + +#define S_ROR_IMM u32 shift_op = ((i>>7)&0x1F);\ + u32 c = cpu->CPSR.bits.C;\ + if(shift_op==0)\ + {\ + u32 tmp = cpu->CPSR.bits.C;\ + shift_op = (tmp<<31)|(cpu->R[REG_POS(i,0)]>>1);\ + c = BIT0(cpu->R[REG_POS(i,0)]);\ + }\ + else\ + {\ + c = BIT_N(cpu->R[REG_POS(i,0)], shift_op-1);\ + shift_op = ROR(cpu->R[REG_POS(i,0)],shift_op);\ + } + +#define ROR_REG u32 shift_op = (cpu->R[REG_POS(i,8)])&0xFF;\ + if((shift_op==0)||((shift_op&0xF)==0))\ + shift_op=cpu->R[REG_POS(i,0)];\ + else\ + shift_op = ROR(cpu->R[REG_POS(i,0)],(shift_op&0xF)); + +#define S_ROR_REG u32 shift_op = (cpu->R[REG_POS(i,8)])&0xFF;\ + u32 c = cpu->CPSR.bits.C;\ + if(shift_op==0)\ + shift_op=cpu->R[REG_POS(i,0)];\ + else\ + {\ + shift_op&=0xF;\ + if(shift_op==0)\ + {\ + shift_op=cpu->R[REG_POS(i,0)];\ + c = BIT31(cpu->R[REG_POS(i,0)]);\ + }\ + else\ + {\ + c = BIT_N(cpu->R[REG_POS(i,0)], shift_op-1);\ + shift_op = ROR(cpu->R[REG_POS(i,0)],(shift_op&0xF));\ + }\ + } + +#define IMM_VALUE u32 shift_op = ROR((i&0xFF), (i>>7)&0x1E); + +#define S_IMM_VALUE u32 shift_op = ROR((i&0xFF), (i>>7)&0x1E);\ + u32 c = cpu->CPSR.bits.C;\ + if((i>>8)&0xF)\ + c = BIT31(shift_op); + +#define IMM_OFF (((i>>4)&0xF0)+(i&0xF)) + +#define IMM_OFF_12 ((i)&0xFFF) + +extern BOOL execute; + +static u32 FASTCALL OP_UND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + LOG("Undefined instruction: %08X\n", i); + execute = FALSE; + return 1; +} + +//-----------------------AND------------------------------------ + +#define OP_AND(a, b) cpu->R[REG_POS(i,12)] = cpu->R[REG_POS(i,16)] & shift_op;\ + if(REG_POS(i,12)==15)\ + {\ + cpu->next_instruction = cpu->R[15];\ + return b;\ + }\ + return a; + +#define OP_ANDS(a, b)\ + if(REG_POS(i,12)==15)\ + {\ + Status_Reg SPSR;\ + cpu->R[15] = cpu->R[REG_POS(i,16)] & shift_op;\ + SPSR = cpu->SPSR;\ + armcpu_switchMode(cpu, SPSR.bits.mode);\ + cpu->CPSR=SPSR;\ + cpu->R[15] &= (0XFFFFFFFC|(((u32)SPSR.bits.T)<<1));\ + cpu->next_instruction = cpu->R[15];\ + return b;\ + }\ + cpu->R[REG_POS(i,12)] = cpu->R[REG_POS(i,16)] & shift_op;\ + cpu->CPSR.bits.C = c;\ + cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,12)]);\ + cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,12)]==0);\ + return a; + +static u32 FASTCALL OP_AND_LSL_IMM(register armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + LSL_IMM; + OP_AND(1, 3); +} + +static u32 FASTCALL OP_AND_LSL_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + LSL_REG; + OP_AND(2, 4); +} + +static u32 FASTCALL OP_AND_LSR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + LSR_IMM; + OP_AND(1, 3); +} + +static u32 FASTCALL OP_AND_LSR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + LSR_REG; + OP_AND(2, 4); +} + +static u32 FASTCALL OP_AND_ASR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + ASR_IMM; + OP_AND(1, 3); +} + +static u32 FASTCALL OP_AND_ASR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + ASR_REG; + OP_AND(2, 4); +} + +static u32 FASTCALL OP_AND_ROR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + ROR_IMM; + OP_AND(1, 3); +} + +static u32 FASTCALL OP_AND_ROR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + ROR_REG; + OP_AND(2, 4); +} + +static u32 FASTCALL OP_AND_IMM_VAL(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + IMM_VALUE; + OP_AND(1, 3); +} + +static u32 FASTCALL OP_AND_S_LSL_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_LSL_IMM; + OP_ANDS(2, 4); +} + +static u32 FASTCALL OP_AND_S_LSL_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_LSL_REG; + OP_ANDS(3, 5); +} + +static u32 FASTCALL OP_AND_S_LSR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_LSR_IMM; + OP_ANDS(2, 4); +} + +static u32 FASTCALL OP_AND_S_LSR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_LSR_REG; + OP_ANDS(3, 5); +} + +static u32 FASTCALL OP_AND_S_ASR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_ASR_IMM; + OP_ANDS(2, 4); +} + +static u32 FASTCALL OP_AND_S_ASR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_ASR_REG; + OP_ANDS(3, 5); +} + +static u32 FASTCALL OP_AND_S_ROR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_ROR_IMM; + OP_ANDS(2, 4); +} + +static u32 FASTCALL OP_AND_S_ROR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_ROR_REG; + OP_ANDS(3, 5); +} + +static u32 FASTCALL OP_AND_S_IMM_VAL(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_IMM_VALUE; + OP_ANDS(2, 4); +} + +//--------------EOR------------------------------ + +#define OP_EOR(a, b) cpu->R[REG_POS(i,12)] = cpu->R[REG_POS(i,16)] ^ shift_op;\ + if(REG_POS(i,12)==15)\ + {\ + cpu->next_instruction = cpu->R[15];\ + return b;\ + }\ + return a; + +#define OP_EORS(a, b) cpu->R[REG_POS(i,12)] = cpu->R[REG_POS(i,16)] ^ shift_op;\ + if(REG_POS(i,12)==15)\ + {\ + Status_Reg SPSR = cpu->SPSR;\ + armcpu_switchMode(cpu, SPSR.bits.mode);\ + cpu->CPSR=SPSR;\ + cpu->R[15] &= (0XFFFFFFFC|(((u32)SPSR.bits.T)<<1));\ + cpu->next_instruction = cpu->R[15];\ + return b;\ + }\ + cpu->CPSR.bits.C = c;\ + cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,12)]);\ + cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,12)]==0);\ + return a; + +static u32 FASTCALL OP_EOR_LSL_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + LSL_IMM; + OP_EOR(1, 3); +} + +static u32 FASTCALL OP_EOR_LSL_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + LSL_REG; + OP_EOR(2, 4); +} + +static u32 FASTCALL OP_EOR_LSR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + LSR_IMM; + OP_EOR(1, 3); +} + +static u32 FASTCALL OP_EOR_LSR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + LSR_REG; + OP_EOR(2, 4); +} + +static u32 FASTCALL OP_EOR_ASR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + ASR_IMM; + OP_EOR(1, 3); +} + +static u32 FASTCALL OP_EOR_ASR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + ASR_REG; + OP_EOR(2, 4); +} + +static u32 FASTCALL OP_EOR_ROR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + ROR_IMM; + OP_EOR(1, 3); +} + +static u32 FASTCALL OP_EOR_ROR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + ROR_REG; + OP_EOR(2, 4); +} + +static u32 FASTCALL OP_EOR_IMM_VAL(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + IMM_VALUE; + OP_EOR(1, 3); +} + +static u32 FASTCALL OP_EOR_S_LSL_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_LSL_IMM; + OP_EORS(2, 4); +} + +static u32 FASTCALL OP_EOR_S_LSL_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_LSL_REG; + OP_EORS(3, 5); +} + +static u32 FASTCALL OP_EOR_S_LSR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_LSR_IMM; + OP_EORS(2, 4); +} + +static u32 FASTCALL OP_EOR_S_LSR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_LSR_REG; + OP_EORS(3, 5); +} + +static u32 FASTCALL OP_EOR_S_ASR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_ASR_IMM; + OP_EORS(2, 4); +} + +static u32 FASTCALL OP_EOR_S_ASR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_ASR_REG; + OP_EORS(3, 5); +} + +static u32 FASTCALL OP_EOR_S_ROR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_ROR_IMM; + OP_EORS(2, 4); +} + +static u32 FASTCALL OP_EOR_S_ROR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_ROR_REG; + OP_EORS(3, 5); +} + +static u32 FASTCALL OP_EOR_S_IMM_VAL(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_IMM_VALUE; + OP_EORS(2, 4); +} + +//-------------SUB------------------------------------- + +#define OP_SUB(a, b) cpu->R[REG_POS(i,12)] = cpu->R[REG_POS(i,16)] - shift_op;\ + if(REG_POS(i,12)==15)\ + {\ + cpu->next_instruction = cpu->R[15];\ + return b;\ + }\ + return a; + +#define OPSUBS(a, b) cpu->R[REG_POS(i,12)] = v - shift_op;\ + if(REG_POS(i,12)==15)\ + {\ + Status_Reg SPSR = cpu->SPSR;\ + armcpu_switchMode(cpu, SPSR.bits.mode);\ + cpu->CPSR=SPSR;\ + cpu->R[15] &= (0XFFFFFFFC|(((u32)SPSR.bits.T)<<1));\ + cpu->next_instruction = cpu->R[15];\ + return b;\ + }\ + cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,12)]);\ + cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,12)]==0);\ + cpu->CPSR.bits.C = !UNSIGNED_UNDERFLOW(v, shift_op, cpu->R[REG_POS(i,12)]);\ + cpu->CPSR.bits.V = SIGNED_UNDERFLOW(v, shift_op, cpu->R[REG_POS(i,12)]);\ + return a; + +static u32 FASTCALL OP_SUB_LSL_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + LSL_IMM; + OP_SUB(1, 3); +} + +static u32 FASTCALL OP_SUB_LSL_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + LSL_REG; + OP_SUB(2, 4); +} + +static u32 FASTCALL OP_SUB_LSR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + LSR_IMM; + OP_SUB(1, 3); +} + +static u32 FASTCALL OP_SUB_LSR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + LSR_REG; + OP_SUB(2, 4); +} + +static u32 FASTCALL OP_SUB_ASR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + ASR_IMM; + OP_SUB(1, 3); +} + +static u32 FASTCALL OP_SUB_ASR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + ASR_REG; + OP_SUB(2, 4); +} + +static u32 FASTCALL OP_SUB_ROR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + ROR_IMM; + OP_SUB(1, 3); +} + +static u32 FASTCALL OP_SUB_ROR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + ROR_REG; + OP_SUB(2, 4); +} + +static u32 FASTCALL OP_SUB_IMM_VAL(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + IMM_VALUE; + OP_SUB(1, 3); +} + +static u32 FASTCALL OP_SUB_S_LSL_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,16)]; + u32 shift_op; + LSL_IMM; + OPSUBS(2, 4); +} + +static u32 FASTCALL OP_SUB_S_LSL_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,16)]; + LSL_REG; + OPSUBS(3, 5); +} + +static u32 FASTCALL OP_SUB_S_LSR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,16)]; + u32 shift_op; + LSR_IMM; + OPSUBS(2, 4); +} + +static u32 FASTCALL OP_SUB_S_LSR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,16)]; + LSR_REG; + OPSUBS(3, 5); +} + +static u32 FASTCALL OP_SUB_S_ASR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,16)]; + u32 shift_op; + ASR_IMM; + OPSUBS(2, 4); +} + +static u32 FASTCALL OP_SUB_S_ASR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,16)]; + ASR_REG; + OPSUBS(3, 5); +} + +static u32 FASTCALL OP_SUB_S_ROR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,16)]; + u32 shift_op; + ROR_IMM; + OPSUBS(2, 4); +} + +static u32 FASTCALL OP_SUB_S_ROR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,16)]; + ROR_REG; + OPSUBS(3, 5); +} + +static u32 FASTCALL OP_SUB_S_IMM_VAL(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,16)]; + IMM_VALUE; + OPSUBS(2, 4); +} + +//------------------RSB------------------------ + +#define OP_RSB(a, b) cpu->R[REG_POS(i,12)] = shift_op - cpu->R[REG_POS(i,16)];\ + if(REG_POS(i,12)==15)\ + {\ + cpu->next_instruction = cpu->R[15];\ + return b;\ + }\ + return a; + +#define OP_RSBS(a, b) cpu->R[REG_POS(i,12)] = shift_op - v;\ + if(REG_POS(i,12)==15)\ + {\ + Status_Reg SPSR = cpu->SPSR;\ + armcpu_switchMode(cpu, SPSR.bits.mode);\ + cpu->CPSR=SPSR;\ + cpu->R[15] &= (0XFFFFFFFC|(((u32)SPSR.bits.T)<<1));\ + cpu->next_instruction = cpu->R[15];\ + return b;\ + }\ + cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,12)]);\ + cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,12)]==0);\ + cpu->CPSR.bits.C = !UNSIGNED_UNDERFLOW(shift_op, v, cpu->R[REG_POS(i,12)]);\ + cpu->CPSR.bits.V = SIGNED_UNDERFLOW(shift_op, v, cpu->R[REG_POS(i,12)]);\ + return a; + +static u32 FASTCALL OP_RSB_LSL_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + LSL_IMM; + OP_RSB(1, 3); +} + +static u32 FASTCALL OP_RSB_LSL_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + LSL_REG; + OP_RSB(2, 4); +} + +static u32 FASTCALL OP_RSB_LSR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + LSR_IMM; + OP_RSB(1, 3); +} + +static u32 FASTCALL OP_RSB_LSR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + LSR_REG; + OP_RSB(2, 4); +} + +static u32 FASTCALL OP_RSB_ASR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + ASR_IMM; + OP_RSB(1, 3); +} + +static u32 FASTCALL OP_RSB_ASR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + ASR_REG; + OP_RSB(2, 4); +} + +static u32 FASTCALL OP_RSB_ROR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + ROR_IMM; + OP_RSB(1, 3); +} + +static u32 FASTCALL OP_RSB_ROR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + ROR_REG; + OP_RSB(2, 4); +} + +static u32 FASTCALL OP_RSB_IMM_VAL(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + IMM_VALUE; + OP_RSB(1, 3); +} + +static u32 FASTCALL OP_RSB_S_LSL_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,16)]; + u32 shift_op; + LSL_IMM; + OP_RSBS(2, 4); +} + +static u32 FASTCALL OP_RSB_S_LSL_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,16)]; + LSL_REG; + OP_RSBS(3, 5); +} + +static u32 FASTCALL OP_RSB_S_LSR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,16)]; + u32 shift_op; + LSR_IMM; + OP_RSBS(2, 4); +} + +static u32 FASTCALL OP_RSB_S_LSR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,16)]; + LSR_REG; + OP_RSBS(3, 5); +} + +static u32 FASTCALL OP_RSB_S_ASR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,16)]; + u32 shift_op; + ASR_IMM; + OP_RSBS(2, 4); +} + +static u32 FASTCALL OP_RSB_S_ASR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,16)]; + ASR_REG; + OP_RSBS(3, 5); +} + +static u32 FASTCALL OP_RSB_S_ROR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,16)]; + u32 shift_op; + ROR_IMM; + OP_RSBS(2, 4); +} + +static u32 FASTCALL OP_RSB_S_ROR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,16)]; + ROR_REG; + OP_RSBS(3, 5); +} + +static u32 FASTCALL OP_RSB_S_IMM_VAL(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,16)]; + IMM_VALUE; + OP_RSBS(2, 4); +} + +//------------------ADD----------------------------------- + +#define OP_ADD(a, b) cpu->R[REG_POS(i,12)] = cpu->R[REG_POS(i,16)] + shift_op;\ + if(REG_POS(i,12)==15)\ + {\ + cpu->next_instruction = cpu->R[15];\ + return b;\ + }\ + return a; + +static u32 FASTCALL OP_ADD_LSL_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + LSL_IMM; + OP_ADD(1, 3); +} + +static u32 FASTCALL OP_ADD_LSL_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + LSL_REG; + OP_ADD(2, 4); +} + +static u32 FASTCALL OP_ADD_LSR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + LSR_IMM; + OP_ADD(1, 3); +} + +static u32 FASTCALL OP_ADD_LSR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + LSR_REG; + OP_ADD(2, 4); +} + +static u32 FASTCALL OP_ADD_ASR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + ASR_IMM; + OP_ADD(1, 3); +} + +static u32 FASTCALL OP_ADD_ASR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + ASR_REG; + OP_ADD(2, 4); +} + +static u32 FASTCALL OP_ADD_ROR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + ROR_IMM; + OP_ADD(1, 3); +} + +static u32 FASTCALL OP_ADD_ROR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + ROR_REG; + OP_ADD(2, 4); +} + +static u32 FASTCALL OP_ADD_IMM_VAL(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + IMM_VALUE; + OP_ADD(1, 3); +} + +#define OP_ADDS(a, b) cpu->R[REG_POS(i,12)] = v + shift_op;\ + if(REG_POS(i,12)==15)\ + {\ + Status_Reg SPSR = cpu->SPSR;\ + armcpu_switchMode(cpu, SPSR.bits.mode);\ + cpu->CPSR=SPSR;\ + cpu->R[15] &= (0XFFFFFFFC|(((u32)SPSR.bits.T)<<1));\ + cpu->next_instruction = cpu->R[15];\ + return b;\ + }\ + cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,12)]);\ + cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,12)]==0);\ + cpu->CPSR.bits.C = UNSIGNED_OVERFLOW(v, shift_op, cpu->R[REG_POS(i,12)]);\ + cpu->CPSR.bits.V = SIGNED_OVERFLOW(v, shift_op, cpu->R[REG_POS(i,12)]);\ + return a; + +static u32 FASTCALL OP_ADD_S_LSL_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,16)]; + u32 shift_op; + LSL_IMM; + OP_ADDS(2, 4); +} + +static u32 FASTCALL OP_ADD_S_LSL_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,16)]; + LSL_REG; + OP_ADDS(3, 5); +} + +static u32 FASTCALL OP_ADD_S_LSR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,16)]; + u32 shift_op; + LSR_IMM; + OP_ADDS(2, 4); +} + +static u32 FASTCALL OP_ADD_S_LSR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,16)]; + LSR_REG; + OP_ADDS(3, 5); +} + +static u32 FASTCALL OP_ADD_S_ASR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,16)]; + u32 shift_op; + ASR_IMM; + OP_ADDS(2, 4); +} + +static u32 FASTCALL OP_ADD_S_ASR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,16)]; + ASR_REG; + OP_ADDS(3, 5); +} + +static u32 FASTCALL OP_ADD_S_ROR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,16)]; + u32 shift_op; + ROR_IMM; + OP_ADDS(2, 4); +} + +static u32 FASTCALL OP_ADD_S_ROR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,16)]; + ROR_REG; + OP_ADDS(3, 5); +} + +static u32 FASTCALL OP_ADD_S_IMM_VAL(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,16)]; + IMM_VALUE; + OP_ADDS(2, 4); +} + +//------------------ADC----------------------------------- + +#define OP_ADC(a, b) cpu->R[REG_POS(i,12)] = cpu->R[REG_POS(i,16)] + shift_op + cpu->CPSR.bits.C;\ + if(REG_POS(i,12)==15)\ + {\ + cpu->next_instruction = cpu->R[15];\ + return b;\ + }\ + return a; + +static u32 FASTCALL OP_ADC_LSL_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + LSL_IMM; + OP_ADC(1, 3); +} + +static u32 FASTCALL OP_ADC_LSL_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + LSL_REG; + OP_ADC(2, 4); +} + +static u32 FASTCALL OP_ADC_LSR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + LSR_IMM; + OP_ADC(1, 3); +} + +static u32 FASTCALL OP_ADC_LSR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + LSR_REG; + OP_ADC(2, 4); +} + +static u32 FASTCALL OP_ADC_ASR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + ASR_IMM; + OP_ADC(1, 3); +} + +static u32 FASTCALL OP_ADC_ASR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + ASR_REG; + OP_ADC(2, 4); +} + +static u32 FASTCALL OP_ADC_ROR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + ROR_IMM; + OP_ADC(1, 3); +} + +static u32 FASTCALL OP_ADC_ROR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + ROR_REG; + OP_ADC(2, 4); +} + +static u32 FASTCALL OP_ADC_IMM_VAL(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + IMM_VALUE; + OP_ADC(1, 3); +} + +#define OP_ADCS(a, b) \ + { \ + u32 tmp = shift_op + cpu->CPSR.bits.C;\ + cpu->R[REG_POS(i,12)] = v + tmp;\ + if(REG_POS(i,12)==15)\ + {\ + Status_Reg SPSR = cpu->SPSR;\ + armcpu_switchMode(cpu, SPSR.bits.mode);\ + cpu->CPSR=SPSR;\ + cpu->R[15] &= (0XFFFFFFFC|(((u32)SPSR.bits.T)<<1));\ + cpu->next_instruction = cpu->R[15];\ + return b;\ + }\ + cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,12)]);\ + cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,12)]==0);\ + cpu->CPSR.bits.C = UNSIGNED_OVERFLOW(shift_op, cpu->CPSR.bits.C, tmp) | UNSIGNED_OVERFLOW(v, tmp, cpu->R[REG_POS(i,12)]);\ + cpu->CPSR.bits.V = SIGNED_OVERFLOW(shift_op, cpu->CPSR.bits.C, tmp) | SIGNED_OVERFLOW(v, tmp, cpu->R[REG_POS(i,12)]);\ + return a; \ + } + +static u32 FASTCALL OP_ADC_S_LSL_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,16)]; + u32 shift_op; + LSL_IMM; + OP_ADCS(2, 4); +} + +static u32 FASTCALL OP_ADC_S_LSL_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,16)]; + LSL_REG; + OP_ADCS(3, 5); +} + +static u32 FASTCALL OP_ADC_S_LSR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,16)]; + u32 shift_op; + LSR_IMM; + OP_ADCS(2, 4); +} + +static u32 FASTCALL OP_ADC_S_LSR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,16)]; + LSR_REG; + OP_ADCS(3, 5); +} + +static u32 FASTCALL OP_ADC_S_ASR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,16)]; + u32 shift_op; + ASR_IMM; + OP_ADCS(2, 4); +} + +static u32 FASTCALL OP_ADC_S_ASR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,16)]; + ASR_REG; + OP_ADCS(3, 5); +} + +static u32 FASTCALL OP_ADC_S_ROR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,16)]; + u32 shift_op; + ROR_IMM; + OP_ADCS(2, 4); +} + +static u32 FASTCALL OP_ADC_S_ROR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,16)]; + ROR_REG; + OP_ADCS(3, 5); +} + +static u32 FASTCALL OP_ADC_S_IMM_VAL(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,16)]; + IMM_VALUE; + OP_ADCS(2, 4); +} + +//-------------SBC------------------------------------- + +#define OP_SBC(a, b) cpu->R[REG_POS(i,12)] = cpu->R[REG_POS(i,16)] - shift_op - (!cpu->CPSR.bits.C);\ + if(REG_POS(i,12)==15)\ + {\ + cpu->next_instruction = cpu->R[15];\ + return b;\ + }\ + return a; + +static u32 FASTCALL OP_SBC_LSL_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + LSL_IMM; + OP_SBC(1, 3); +} + +static u32 FASTCALL OP_SBC_LSL_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + LSL_REG; + OP_SBC(2, 4); +} + +static u32 FASTCALL OP_SBC_LSR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + LSR_IMM; + OP_SBC(1, 3); +} + +static u32 FASTCALL OP_SBC_LSR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + LSR_REG; + OP_SBC(2, 4); +} + +static u32 FASTCALL OP_SBC_ASR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + ASR_IMM; + OP_SBC(1, 3); +} + +static u32 FASTCALL OP_SBC_ASR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + ASR_REG; + OP_SBC(2, 4); +} + +static u32 FASTCALL OP_SBC_ROR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + ROR_IMM; + OP_SBC(1, 3); +} + +static u32 FASTCALL OP_SBC_ROR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + ROR_REG; + OP_SBC(2, 4); +} + +static u32 FASTCALL OP_SBC_IMM_VAL(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + IMM_VALUE; + OP_SBC(1, 3); +} + +#define OP_SBCS(a, b) \ + { \ + u32 tmp = v - (!cpu->CPSR.bits.C);\ + cpu->R[REG_POS(i,12)] = tmp - shift_op;\ + if(REG_POS(i,12)==15)\ + {\ + Status_Reg SPSR = cpu->SPSR;\ + armcpu_switchMode(cpu, SPSR.bits.mode);\ + cpu->CPSR=SPSR;\ + cpu->R[15] &= (0XFFFFFFFC|(((u32)SPSR.bits.T)<<1));\ + cpu->next_instruction = cpu->R[15];\ + return b;\ + }\ + cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,12)]);\ + cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,12)]==0);\ + cpu->CPSR.bits.C = (!UNSIGNED_UNDERFLOW(v, (!cpu->CPSR.bits.C), tmp)) & (!UNSIGNED_UNDERFLOW(tmp, shift_op, cpu->R[REG_POS(i,12)]));\ + cpu->CPSR.bits.V = SIGNED_UNDERFLOW(v, (!cpu->CPSR.bits.C), tmp) | SIGNED_UNDERFLOW(tmp, shift_op, cpu->R[REG_POS(i,12)]);\ + return a; \ + } + +static u32 FASTCALL OP_SBC_S_LSL_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,16)]; + u32 shift_op; + LSL_IMM; + OP_SBCS(2, 4); +} + +static u32 FASTCALL OP_SBC_S_LSL_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,16)]; + LSL_REG; + OP_SBCS(3, 5); +} + +static u32 FASTCALL OP_SBC_S_LSR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,16)]; + u32 shift_op; + LSR_IMM; + OP_SBCS(2, 4); +} + +static u32 FASTCALL OP_SBC_S_LSR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,16)]; + LSR_REG; + OP_SBCS(3, 5); +} + +static u32 FASTCALL OP_SBC_S_ASR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,16)]; + u32 shift_op; + ASR_IMM; + OP_SBCS(2, 4); +} + +static u32 FASTCALL OP_SBC_S_ASR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,16)]; + ASR_REG; + OP_SBCS(3, 5); +} + +static u32 FASTCALL OP_SBC_S_ROR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,16)]; + u32 shift_op; + ROR_IMM; + OP_SBCS(2, 4); +} + +static u32 FASTCALL OP_SBC_S_ROR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,16)]; + ROR_REG; + OP_SBCS(3, 5); +} + +static u32 FASTCALL OP_SBC_S_IMM_VAL(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,16)]; + IMM_VALUE; + OP_SBCS(2, 4); +} + +//---------------RSC---------------------------------- + +#define OP_RSC(a, b) cpu->R[REG_POS(i,12)] = shift_op - cpu->R[REG_POS(i,16)] - (!cpu->CPSR.bits.C);\ + if(REG_POS(i,12)==15)\ + {\ + cpu->next_instruction = cpu->R[15];\ + return b;\ + }\ + return a; + +static u32 FASTCALL OP_RSC_LSL_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + LSL_IMM; + OP_RSC(1, 3); +} + +static u32 FASTCALL OP_RSC_LSL_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + LSL_REG; + OP_RSC(2, 4); +} + +static u32 FASTCALL OP_RSC_LSR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + LSR_IMM; + OP_RSC(1, 3); +} + +static u32 FASTCALL OP_RSC_LSR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + LSR_REG; + OP_RSC(2, 4); +} + +static u32 FASTCALL OP_RSC_ASR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + ASR_IMM; + OP_RSC(1, 3); +} + +static u32 FASTCALL OP_RSC_ASR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + ASR_REG; + OP_RSC(2, 4); +} + +static u32 FASTCALL OP_RSC_ROR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + ROR_IMM; + OP_RSC(1, 3); +} + +static u32 FASTCALL OP_RSC_ROR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + ROR_REG; + OP_RSC(2, 4); +} + +static u32 FASTCALL OP_RSC_IMM_VAL(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + IMM_VALUE; + OP_RSC(1, 3); +} + +#define OP_RSCS(a,b) \ + { \ + u32 tmp = shift_op - (!cpu->CPSR.bits.C);\ + cpu->R[REG_POS(i,12)] = tmp - v;\ + if(REG_POS(i,12)==15)\ + {\ + Status_Reg SPSR = cpu->SPSR;\ + armcpu_switchMode(cpu, SPSR.bits.mode);\ + cpu->CPSR=SPSR;\ + cpu->R[15] &= (0XFFFFFFFC|(((u32)SPSR.bits.T)<<1));\ + cpu->next_instruction = cpu->R[15];\ + return b;\ + }\ + cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,12)]);\ + cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,12)]==0);\ + cpu->CPSR.bits.C = (!UNSIGNED_UNDERFLOW(shift_op, (!cpu->CPSR.bits.C), tmp)) & (!UNSIGNED_UNDERFLOW(tmp, v, cpu->R[REG_POS(i,12)]));\ + cpu->CPSR.bits.V = SIGNED_UNDERFLOW(shift_op, (!cpu->CPSR.bits.C), tmp) | SIGNED_UNDERFLOW(tmp, v, cpu->R[REG_POS(i,12)]);\ + return a; \ + } + +static u32 FASTCALL OP_RSC_S_LSL_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,16)]; + u32 shift_op; + LSL_IMM; + OP_RSCS(2,4); +} + +static u32 FASTCALL OP_RSC_S_LSL_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,16)]; + LSL_REG; + OP_RSCS(3,5); +} + +static u32 FASTCALL OP_RSC_S_LSR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,16)]; + u32 shift_op; + LSR_IMM; + OP_RSCS(2,4); +} + +static u32 FASTCALL OP_RSC_S_LSR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,16)]; + LSR_REG; + OP_RSCS(3,5); +} + +static u32 FASTCALL OP_RSC_S_ASR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,16)]; + u32 shift_op; + ASR_IMM; + OP_RSCS(2,4); +} + +static u32 FASTCALL OP_RSC_S_ASR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,16)]; + ASR_REG; + OP_RSCS(3,5); +} + +static u32 FASTCALL OP_RSC_S_ROR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,16)]; + u32 shift_op; + ROR_IMM; + OP_RSCS(2,4); +} + +static u32 FASTCALL OP_RSC_S_ROR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,16)]; + ROR_REG; + OP_RSCS(3,5); +} + +static u32 FASTCALL OP_RSC_S_IMM_VAL(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,16)]; + IMM_VALUE; + OP_RSCS(2,4); +} + +//-------------------TST---------------------------- + +#define OP_TST(a) \ + { \ + unsigned tmp = cpu->R[REG_POS(i,16)] & shift_op;\ + cpu->CPSR.bits.C = c;\ + cpu->CPSR.bits.N = BIT31(tmp);\ + cpu->CPSR.bits.Z = (tmp==0);\ + return a; \ + } + +static u32 FASTCALL OP_TST_LSL_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_LSL_IMM; + OP_TST(1); +} + +static u32 FASTCALL OP_TST_LSL_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_LSL_REG; + OP_TST(2); +} + +static u32 FASTCALL OP_TST_LSR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_LSR_IMM; + OP_TST(1); +} + +static u32 FASTCALL OP_TST_LSR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_LSR_REG; + OP_TST(2); +} + +static u32 FASTCALL OP_TST_ASR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_ASR_IMM; + OP_TST(1); +} + +static u32 FASTCALL OP_TST_ASR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_ASR_REG; + OP_TST(2); +} + +static u32 FASTCALL OP_TST_ROR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_ROR_IMM; + OP_TST(1); +} + +static u32 FASTCALL OP_TST_ROR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_ROR_REG; + OP_TST(2); +} + +static u32 FASTCALL OP_TST_IMM_VAL(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_IMM_VALUE; + OP_TST(1); +} + +//-------------------TEQ---------------------------- + +#define OP_TEQ(a) \ + { \ + unsigned tmp = cpu->R[REG_POS(i,16)] ^ shift_op;\ + cpu->CPSR.bits.C = c;\ + cpu->CPSR.bits.N = BIT31(tmp);\ + cpu->CPSR.bits.Z = (tmp==0);\ + return a; \ + } + +static u32 FASTCALL OP_TEQ_LSL_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_LSL_IMM; + OP_TEQ(1); +} + +static u32 FASTCALL OP_TEQ_LSL_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_LSL_REG; + OP_TEQ(2); +} + +static u32 FASTCALL OP_TEQ_LSR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_LSR_IMM; + OP_TEQ(1); +} + +static u32 FASTCALL OP_TEQ_LSR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_LSR_REG; + OP_TEQ(2); +} + +static u32 FASTCALL OP_TEQ_ASR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_ASR_IMM; + OP_TEQ(1); +} + +static u32 FASTCALL OP_TEQ_ASR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_ASR_REG; + OP_TEQ(2); +} + +static u32 FASTCALL OP_TEQ_ROR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_ROR_IMM; + OP_TEQ(1); +} + +static u32 FASTCALL OP_TEQ_ROR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_ROR_REG; + OP_TEQ(2); +} + +static u32 FASTCALL OP_TEQ_IMM_VAL(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_IMM_VALUE; + OP_TEQ(1); +} + +//-------------CMP------------------------------------- + +#define OP_CMP(a) \ + { \ + u32 tmp = cpu->R[REG_POS(i,16)] - shift_op;\ + cpu->CPSR.bits.N = BIT31(tmp);\ + cpu->CPSR.bits.Z = (tmp==0);\ + cpu->CPSR.bits.C = !UNSIGNED_UNDERFLOW(cpu->R[REG_POS(i,16)], shift_op, tmp);\ + cpu->CPSR.bits.V = SIGNED_UNDERFLOW(cpu->R[REG_POS(i,16)], shift_op, tmp);\ + return a; \ + } + +static u32 FASTCALL OP_CMP_LSL_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + LSL_IMM; + OP_CMP(1); +} + +static u32 FASTCALL OP_CMP_LSL_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + LSL_REG; + OP_CMP(2); +} + +static u32 FASTCALL OP_CMP_LSR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + LSR_IMM; + OP_CMP(1); +} + +static u32 FASTCALL OP_CMP_LSR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + LSR_REG; + OP_CMP(2); +} + +static u32 FASTCALL OP_CMP_ASR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + ASR_IMM; + OP_CMP(1); +} + +static u32 FASTCALL OP_CMP_ASR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + ASR_REG; + OP_CMP(2); +} + +static u32 FASTCALL OP_CMP_ROR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + ROR_IMM; + OP_CMP(1); +} + +static u32 FASTCALL OP_CMP_ROR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + ROR_REG; + OP_CMP(2); +} + +static u32 FASTCALL OP_CMP_IMM_VAL(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + IMM_VALUE; + OP_CMP(1); +} + +//---------------CMN--------------------------- + +#define OP_CMN(a) \ + { \ + u32 tmp = cpu->R[REG_POS(i,16)] + shift_op;\ + cpu->CPSR.bits.N = BIT31(tmp);\ + cpu->CPSR.bits.Z = (tmp==0);\ + cpu->CPSR.bits.C = UNSIGNED_OVERFLOW(cpu->R[REG_POS(i,16)], shift_op, tmp);\ + cpu->CPSR.bits.V = SIGNED_OVERFLOW(cpu->R[REG_POS(i,16)], shift_op, tmp);\ + return a; \ + } + +static u32 FASTCALL OP_CMN_LSL_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + LSL_IMM; + OP_CMN(1); +} + +static u32 FASTCALL OP_CMN_LSL_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + LSL_REG; + OP_CMN(2); +} + +static u32 FASTCALL OP_CMN_LSR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + LSR_IMM; + OP_CMN(1); +} + +static u32 FASTCALL OP_CMN_LSR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + LSR_REG; + OP_CMN(2); +} + +static u32 FASTCALL OP_CMN_ASR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + ASR_IMM; + OP_CMN(1); +} + +static u32 FASTCALL OP_CMN_ASR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + ASR_REG; + OP_CMN(2); +} + +static u32 FASTCALL OP_CMN_ROR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + ROR_IMM; + OP_CMN(1); +} + +static u32 FASTCALL OP_CMN_ROR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + ROR_REG; + OP_CMN(2); +} + +static u32 FASTCALL OP_CMN_IMM_VAL(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + IMM_VALUE; + OP_CMN(1); +} + +//------------------ORR------------------- + +#define OP_ORR(a, b) cpu->R[REG_POS(i,12)] = cpu->R[REG_POS(i,16)] | shift_op;\ + if(REG_POS(i,12)==15)\ + {\ + cpu->next_instruction = cpu->R[15];\ + return b;\ + }\ + return a; + +static u32 FASTCALL OP_ORR_LSL_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + LSL_IMM; + OP_ORR(1, 3); +} + +static u32 FASTCALL OP_ORR_LSL_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + LSL_REG; + OP_ORR(2, 4); +} + +static u32 FASTCALL OP_ORR_LSR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + LSR_IMM; + OP_ORR(1, 3); +} + +static u32 FASTCALL OP_ORR_LSR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + LSR_REG; + OP_ORR(2, 4); +} + +static u32 FASTCALL OP_ORR_ASR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + ASR_IMM; + OP_ORR(1, 3); +} + +static u32 FASTCALL OP_ORR_ASR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + ASR_REG; + OP_ORR(2, 4); +} + +static u32 FASTCALL OP_ORR_ROR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + ROR_IMM; + OP_ORR(1, 3); +} + +static u32 FASTCALL OP_ORR_ROR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + ROR_REG; + OP_ORR(2, 4); +} + +static u32 FASTCALL OP_ORR_IMM_VAL(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + IMM_VALUE; + OP_ORR(1, 3); +} + +static u32 FASTCALL OP_ORR_S_LSL_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_LSL_IMM; + cpu->R[REG_POS(i,12)] = cpu->R[REG_POS(i,16)] | shift_op; + if(REG_POS(i,12)==15) + { + Status_Reg SPSR = cpu->SPSR; + armcpu_switchMode(cpu, SPSR.bits.mode); + cpu->CPSR=SPSR; + cpu->R[15] &= (0XFFFFFFFC|(((u32)SPSR.bits.T)<<1)); + cpu->next_instruction = cpu->R[15]; + return 4; + } + cpu->CPSR.bits.C = c; + cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,12)]); + cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,12)]==0); + return 2; +} + +static u32 FASTCALL OP_ORR_S_LSL_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_LSL_REG; + cpu->R[REG_POS(i,12)] = cpu->R[REG_POS(i,16)] | shift_op; + if(REG_POS(i,12)==15) + { + Status_Reg SPSR = cpu->SPSR; + armcpu_switchMode(cpu, SPSR.bits.mode); + cpu->CPSR=SPSR; + cpu->R[15] &= (0XFFFFFFFC|(((u32)SPSR.bits.T)<<1)); + cpu->next_instruction = cpu->R[15]; + return 5; + } + cpu->CPSR.bits.C = c; + cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,12)]); + cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,12)]==0); + return 3; +} + +static u32 FASTCALL OP_ORR_S_LSR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_LSR_IMM; + cpu->R[REG_POS(i,12)] = cpu->R[REG_POS(i,16)] | shift_op; + if(REG_POS(i,12)==15) + { + Status_Reg SPSR = cpu->SPSR; + armcpu_switchMode(cpu, SPSR.bits.mode); + cpu->CPSR=SPSR; + cpu->R[15] &= (0XFFFFFFFC|(((u32)SPSR.bits.T)<<1)); + cpu->next_instruction = cpu->R[15]; + return 4; + } + cpu->CPSR.bits.C = c; + cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,12)]); + cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,12)]==0); + return 2; +} + +static u32 FASTCALL OP_ORR_S_LSR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_LSR_REG; + cpu->R[REG_POS(i,12)] = cpu->R[REG_POS(i,16)] | shift_op; + if(REG_POS(i,12)==15) + { + Status_Reg SPSR = cpu->SPSR; + armcpu_switchMode(cpu, SPSR.bits.mode); + cpu->CPSR=SPSR; + cpu->R[15] &= (0XFFFFFFFC|(((u32)SPSR.bits.T)<<1)); + cpu->next_instruction = cpu->R[15]; + return 5; + } + cpu->CPSR.bits.C = c; + cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,12)]); + cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,12)]==0); + return 3; +} + +static u32 FASTCALL OP_ORR_S_ASR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_ASR_IMM; + cpu->R[REG_POS(i,12)] = cpu->R[REG_POS(i,16)] | shift_op; + if(REG_POS(i,12)==15) + { + Status_Reg SPSR = cpu->SPSR; + armcpu_switchMode(cpu, SPSR.bits.mode); + cpu->CPSR=SPSR; + cpu->R[15] &= (0XFFFFFFFC|(((u32)SPSR.bits.T)<<1)); + cpu->next_instruction = cpu->R[15]; + return 4; + } + cpu->CPSR.bits.C = c; + cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,12)]); + cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,12)]==0); + return 2; +} + +static u32 FASTCALL OP_ORR_S_ASR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_ASR_REG; + cpu->R[REG_POS(i,12)] = cpu->R[REG_POS(i,16)] | shift_op; + if(REG_POS(i,12)==15) + { + Status_Reg SPSR = cpu->SPSR; + armcpu_switchMode(cpu, SPSR.bits.mode); + cpu->CPSR=SPSR; + cpu->R[15] &= (0XFFFFFFFC|(((u32)SPSR.bits.T)<<1)); + cpu->next_instruction = cpu->R[15]; + return 5; + } + cpu->CPSR.bits.C = c; + cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,12)]); + cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,12)]==0); + return 3; +} + +static u32 FASTCALL OP_ORR_S_ROR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_ROR_IMM; + cpu->R[REG_POS(i,12)] = cpu->R[REG_POS(i,16)] | shift_op; + if(REG_POS(i,12)==15) + { + Status_Reg SPSR = cpu->SPSR; + armcpu_switchMode(cpu, SPSR.bits.mode); + cpu->CPSR=SPSR; + cpu->R[15] &= (0XFFFFFFFC|(((u32)SPSR.bits.T)<<1)); + cpu->next_instruction = cpu->R[15]; + return 4; + } + cpu->CPSR.bits.C = c; + cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,12)]); + cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,12)]==0); + return 2; +} + +static u32 FASTCALL OP_ORR_S_ROR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_ROR_REG; + cpu->R[REG_POS(i,12)] = cpu->R[REG_POS(i,16)] | shift_op; + if(REG_POS(i,12)==15) + { + Status_Reg SPSR = cpu->SPSR; + armcpu_switchMode(cpu, SPSR.bits.mode); + cpu->CPSR=SPSR; + cpu->R[15] &= (0XFFFFFFFC|(((u32)SPSR.bits.T)<<1)); + cpu->next_instruction = cpu->R[15]; + return 5; + } + cpu->CPSR.bits.C = c; + cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,12)]); + cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,12)]==0); + return 3; +} + +static u32 FASTCALL OP_ORR_S_IMM_VAL(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_IMM_VALUE; + cpu->R[REG_POS(i,12)] = cpu->R[REG_POS(i,16)] | shift_op; + if(REG_POS(i,12)==15) + { + Status_Reg SPSR = cpu->SPSR; + armcpu_switchMode(cpu, SPSR.bits.mode); + cpu->CPSR=SPSR; + cpu->R[15] &= (0XFFFFFFFC|(((u32)SPSR.bits.T)<<1)); + cpu->next_instruction = cpu->R[15]; + return 4; + } + cpu->CPSR.bits.C = c; + cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,12)]); + cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,12)]==0); + return 2; +} + +//------------------MOV------------------- + +#define OP_MOV(a, b) cpu->R[REG_POS(i,12)] = shift_op;\ + if(REG_POS(i,12)==15)\ + {\ + cpu->next_instruction = shift_op;\ + return b;\ + }\ + return a; + +#define OP_MOV_S(a, b) cpu->R[REG_POS(i,12)] = shift_op;\ + if(BIT20(i) && REG_POS(i,12)==15)\ + {\ + Status_Reg SPSR = cpu->SPSR;\ + armcpu_switchMode(cpu, SPSR.bits.mode);\ + cpu->CPSR=SPSR;\ + cpu->R[15] &= (0XFFFFFFFC|(((u32)SPSR.bits.T)<<1));\ + cpu->next_instruction = cpu->R[15];\ + return b;\ + }\ + cpu->CPSR.bits.C = c;\ + cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,12)]);\ + cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,12)]==0);\ + return a;\ + +static u32 FASTCALL OP_MOV_LSL_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + LSL_IMM; + OP_MOV(1,3); +} + +static u32 FASTCALL OP_MOV_LSL_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + LSL_REG; + if (REG_POS(i,0) == 15) shift_op += 4; + OP_MOV(2,4); +} + +static u32 FASTCALL OP_MOV_LSR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + LSR_IMM; + OP_MOV(1,3); +} + +static u32 FASTCALL OP_MOV_LSR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + LSR_REG; + if (REG_POS(i,0) == 15) shift_op += 4; + OP_MOV(2,4); +} + +static u32 FASTCALL OP_MOV_ASR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + ASR_IMM; + OP_MOV(1,3); +} + +static u32 FASTCALL OP_MOV_ASR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + ASR_REG; + OP_MOV(2,4); +} + +static u32 FASTCALL OP_MOV_ROR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + ROR_IMM; + OP_MOV(2,4); +} + +static u32 FASTCALL OP_MOV_ROR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + ROR_REG; + OP_MOV(2,4); +} + +static u32 FASTCALL OP_MOV_IMM_VAL(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + IMM_VALUE; + OP_MOV(1,3); +} + +static u32 FASTCALL OP_MOV_S_LSL_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_LSL_IMM; + OP_MOV_S(2,4); +} + +static u32 FASTCALL OP_MOV_S_LSL_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_LSL_REG; + if (REG_POS(i,0) == 15) shift_op += 4; + OP_MOV_S(3,5); +} + +static u32 FASTCALL OP_MOV_S_LSR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_LSR_IMM; + OP_MOV_S(2,4); +} + +static u32 FASTCALL OP_MOV_S_LSR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_LSR_REG; + if (REG_POS(i,0) == 15) shift_op += 4; + OP_MOV_S(3,5); +} + +static u32 FASTCALL OP_MOV_S_ASR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_ASR_IMM; + OP_MOV_S(2,4); +} + +static u32 FASTCALL OP_MOV_S_ASR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_ASR_REG; + OP_MOV_S(3,5); +} + +static u32 FASTCALL OP_MOV_S_ROR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_ROR_IMM; + OP_MOV_S(2,4); +} + +static u32 FASTCALL OP_MOV_S_ROR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_ROR_REG; + OP_MOV_S(3,5); +} + +static u32 FASTCALL OP_MOV_S_IMM_VAL(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_IMM_VALUE; + OP_MOV_S(2,4); +} + +//------------------BIC------------------- +#define OPP_BIC(a, b) cpu->R[REG_POS(i,12)] = cpu->R[REG_POS(i,16)] & (~shift_op);\ + if(REG_POS(i,12)==15)\ + {\ + cpu->next_instruction = cpu->R[15];\ + return b;\ + }\ + return a; + +#define OPP_BIC_S(a, b) cpu->R[REG_POS(i,12)] = cpu->R[REG_POS(i,16)] & (~shift_op);\ + if(REG_POS(i,12)==15)\ + {\ + Status_Reg SPSR = cpu->SPSR;\ + armcpu_switchMode(cpu, SPSR.bits.mode);\ + cpu->CPSR=SPSR;\ + cpu->R[15] &= (0XFFFFFFFC|(((u32)SPSR.bits.T)<<1));\ + cpu->next_instruction = cpu->R[15];\ + return b;\ + }\ + cpu->CPSR.bits.C = c;\ + cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,12)]);\ + cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,12)]==0);\ + return a; + +static u32 FASTCALL OP_BIC_LSL_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + LSL_IMM; + OPP_BIC(1,3); +} + +static u32 FASTCALL OP_BIC_LSL_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + LSL_REG; + OPP_BIC(2,4); +} + +static u32 FASTCALL OP_BIC_LSR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + LSR_IMM; + OPP_BIC(1,3); +} + +static u32 FASTCALL OP_BIC_LSR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + LSR_REG; + OPP_BIC(2,4); +} + +static u32 FASTCALL OP_BIC_ASR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + ASR_IMM; + OPP_BIC(1,3); +} + +static u32 FASTCALL OP_BIC_ASR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + ASR_REG; + OPP_BIC(2,4); +} + +static u32 FASTCALL OP_BIC_ROR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + ROR_IMM; + OPP_BIC(1,3); +} + +static u32 FASTCALL OP_BIC_ROR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + ROR_REG; + OPP_BIC(2,4); +} + +static u32 FASTCALL OP_BIC_IMM_VAL(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + IMM_VALUE; + OPP_BIC(1,3); +} + +static u32 FASTCALL OP_BIC_S_LSL_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_LSL_IMM; + OPP_BIC_S(2,4); +} + +static u32 FASTCALL OP_BIC_S_LSL_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_LSL_REG; + OPP_BIC_S(3,5); +} + +static u32 FASTCALL OP_BIC_S_LSR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_LSR_IMM; + OPP_BIC_S(2,4); +} + +static u32 FASTCALL OP_BIC_S_LSR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_LSR_REG; + OPP_BIC_S(3,5); +} + +static u32 FASTCALL OP_BIC_S_ASR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_ASR_IMM; + OPP_BIC_S(2,4); +} + +static u32 FASTCALL OP_BIC_S_ASR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_ASR_REG; + OPP_BIC_S(3,5); +} + +static u32 FASTCALL OP_BIC_S_ROR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_ROR_IMM; + OPP_BIC_S(2,4); +} + +static u32 FASTCALL OP_BIC_S_ROR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_ROR_REG; + OPP_BIC_S(3,5); +} + +static u32 FASTCALL OP_BIC_S_IMM_VAL(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_IMM_VALUE; + OPP_BIC_S(2,4); +} + +//------------------MVN------------------- +#define OPP_MVN(a, b) cpu->R[REG_POS(i,12)] = ~shift_op;\ + if(REG_POS(i,12)==15)\ + {\ + cpu->next_instruction = cpu->R[15];\ + return b;\ + }\ + return a; + +#define OPP_MVN_S(a, b) cpu->R[REG_POS(i,12)] = ~shift_op;\ + if(REG_POS(i,12)==15)\ + {\ + Status_Reg SPSR = cpu->SPSR;\ + armcpu_switchMode(cpu, SPSR.bits.mode);\ + cpu->CPSR=SPSR;\ + cpu->R[15] &= (0XFFFFFFFC|(((u32)SPSR.bits.T)<<1));\ + cpu->next_instruction = cpu->R[15];\ + return b;\ + }\ + cpu->CPSR.bits.C = c;\ + cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,12)]);\ + cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,12)]==0);\ + return a; + +static u32 FASTCALL OP_MVN_LSL_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + LSL_IMM; + OPP_MVN(1,3); +} + +static u32 FASTCALL OP_MVN_LSL_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + LSL_REG; + OPP_MVN(2,4); +} + +static u32 FASTCALL OP_MVN_LSR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + LSR_IMM; + OPP_MVN(1,3); +} + +static u32 FASTCALL OP_MVN_LSR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + LSR_REG; + OPP_MVN(2,4); +} + +static u32 FASTCALL OP_MVN_ASR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + ASR_IMM; + OPP_MVN(1,3); +} + +static u32 FASTCALL OP_MVN_ASR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + ASR_REG; + OPP_MVN(2,4); +} + +static u32 FASTCALL OP_MVN_ROR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + ROR_IMM; + OPP_MVN(1,3); +} + +static u32 FASTCALL OP_MVN_ROR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + ROR_REG; + OPP_MVN(2,4); +} + +static u32 FASTCALL OP_MVN_IMM_VAL(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + IMM_VALUE; + OPP_MVN(1,3); +} + +static u32 FASTCALL OP_MVN_S_LSL_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_LSL_IMM; + OPP_MVN_S(2,4); +} + +static u32 FASTCALL OP_MVN_S_LSL_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_LSL_REG; + OPP_MVN_S(3,5); +} + +static u32 FASTCALL OP_MVN_S_LSR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_LSR_IMM; + OPP_MVN_S(2,4); +} + +static u32 FASTCALL OP_MVN_S_LSR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_LSR_REG; + OPP_MVN_S(3,5); +} + +static u32 FASTCALL OP_MVN_S_ASR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_ASR_IMM; + OPP_MVN_S(2,4); +} + +static u32 FASTCALL OP_MVN_S_ASR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_ASR_REG; + OPP_MVN_S(3,5); +} + +static u32 FASTCALL OP_MVN_S_ROR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_ROR_IMM; + OPP_MVN_S(2,4); +} + +static u32 FASTCALL OP_MVN_S_ROR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_ROR_REG; + OPP_MVN_S(3,5); +} + +static u32 FASTCALL OP_MVN_S_IMM_VAL(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_IMM_VALUE; + OPP_MVN_S(2,4); +} + +//-------------MUL------------------------ +#define OPP_M(a,b) v >>= 8;\ + if((v==0)||(v==0xFFFFFF))\ + return b;\ + v >>= 8;\ + if((v==0)||(v==0xFFFF))\ + return b+1;\ + v >>= 8;\ + if((v==0)||(v==0xFF))\ + return b+2;\ + return a;\ + +static u32 FASTCALL OP_MUL(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,0)]; + cpu->R[REG_POS(i,16)] = cpu->R[REG_POS(i,8)] * v; + OPP_M(5,2); +} + +static u32 FASTCALL OP_MLA(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,0)]; + u32 a = cpu->R[REG_POS(i,8)]; + u32 b = cpu->R[REG_POS(i,12)]; + cpu->R[REG_POS(i,16)] = a * v + b; + + OPP_M(6,3); +} + +static u32 FASTCALL OP_MUL_S(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,0)]; + cpu->R[REG_POS(i,16)] = cpu->R[REG_POS(i,8)] * v; + + cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,16)]); + cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,16)]==0); + + OPP_M(6,3); +} + +static u32 FASTCALL OP_MLA_S(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,0)]; + cpu->R[REG_POS(i,16)] = cpu->R[REG_POS(i,8)] * v + cpu->R[REG_POS(i,12)]; + cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,16)]); + cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,16)]==0); + OPP_M(7,4); +} + +//----------UMUL-------------------------- + +static u32 FASTCALL OP_UMULL(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,0)]; + u64 res = (u64)v * (u64)cpu->R[REG_POS(i,8)]; + + cpu->R[REG_POS(i,12)] = (u32)res; + cpu->R[REG_POS(i,16)] = (u32)(res>>32); + + OPP_M(6,3); +} + +static u32 FASTCALL OP_UMLAL(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,0)]; + u64 res = (u64)v * (u64)cpu->R[REG_POS(i,8)] + (u64)cpu->R[REG_POS(i,12)]; + + cpu->R[REG_POS(i,12)] = (u32)res; + cpu->R[REG_POS(i,16)] += (u32)(res>>32); + + OPP_M(7,4); +} + +static u32 FASTCALL OP_UMULL_S(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,0)]; + u64 res = (u64)v * (u64)cpu->R[REG_POS(i,8)]; + + cpu->R[REG_POS(i,12)] = (u32)res; + cpu->R[REG_POS(i,16)] = (u32)(res>>32); + + cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,16)]); + cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,16)]==0) & (cpu->R[REG_POS(i,12)]==0); + + OPP_M(7,4); +} + +static u32 FASTCALL OP_UMLAL_S(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,0)]; + u64 res = (u64)v * (u64)cpu->R[REG_POS(i,8)] + (u64)cpu->R[REG_POS(i,12)]; + + cpu->R[REG_POS(i,12)] = (u32)res; + cpu->R[REG_POS(i,16)] += (u32)(res>>32); + + cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,16)]); + cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,16)]==0) & (cpu->R[REG_POS(i,12)]==0); + + OPP_M(8,5); +} + +//----------SMUL-------------------------- + +static u32 FASTCALL OP_SMULL(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + s64 v = (s32)cpu->R[REG_POS(i,0)]; + s64 b = (s32)cpu->R[REG_POS(i,8)]; + s64 res = v * b; + + cpu->R[REG_POS(i,12)] = (u32)(res&0xFFFFFFFF); + cpu->R[REG_POS(i,16)] = (u32)(res>>32); + + v &= 0xFFFFFFFF; + + OPP_M(6,3); +} + +static u32 FASTCALL OP_SMLAL(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + + s64 v = (s32)cpu->R[REG_POS(i,0)]; + s64 b = (s32)cpu->R[REG_POS(i,8)]; + s64 res = v * b + (u64)cpu->R[REG_POS(i,12)]; + + //LOG("%08X * %08X + %08X%08X\r\n", cpu->R[REG_POS(i,0)], cpu->R[REG_POS(i,8)], cpu->R[REG_POS(i,16)], cpu->R[REG_POS(i,12)]); + + cpu->R[REG_POS(i,12)] = (u32)res; + cpu->R[REG_POS(i,16)] += (u32)(res>>32); + + //LOG("= %08X%08X %08X%08X\r\n", cpu->R[REG_POS(i,16)], cpu->R[REG_POS(i,12)], res); + + v &= 0xFFFFFFFF; + + OPP_M(7,4); +} + +static u32 FASTCALL OP_SMULL_S(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + s64 v = (s32)cpu->R[REG_POS(i,0)]; + s64 b = (s32)cpu->R[REG_POS(i,8)]; + s64 res = v * b; + + cpu->R[REG_POS(i,12)] = (u32)res; + cpu->R[REG_POS(i,16)] = (u32)(res>>32); + + cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,16)]); + cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,16)]==0) & (cpu->R[REG_POS(i,12)]==0); + + v &= 0xFFFFFFFF; + + OPP_M(7,4); +} + +static u32 FASTCALL OP_SMLAL_S(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + s64 v = (s32)cpu->R[REG_POS(i,0)]; + s64 b = (s32)cpu->R[REG_POS(i,8)]; + s64 res = v * b + (u64)cpu->R[REG_POS(i,12)]; + + cpu->R[REG_POS(i,12)] = (u32)res; + cpu->R[REG_POS(i,16)] += (u32)(res>>32); + + cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,16)]); + cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,16)]==0) & (cpu->R[REG_POS(i,12)]==0); + + v &= 0xFFFFFFFF; + + OPP_M(8,5); +} + +//---------------SWP------------------------------ + +static u32 FASTCALL OP_SWP(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)]; + u32 tmp = ROR(READ32(cpu->mem_if->data, adr), ((cpu->R[REG_POS(i,16)]&3)<<3)); + + WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,0)]); + cpu->R[REG_POS(i,12)] = tmp; + + return 4 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]*2; +} + +static u32 FASTCALL OP_SWPB(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)]; + u8 tmp = READ8(cpu->mem_if->data, adr); + WRITE8(cpu->mem_if->data, adr, (u8)(cpu->R[REG_POS(i,0)]&0xFF)); + cpu->R[REG_POS(i,12)] = tmp; + + return 4 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]*2; +} + +//------------LDRH----------------------------- + +static u32 FASTCALL OP_LDRH_P_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)] + IMM_OFF; + cpu->R[REG_POS(i,12)] = (u32)READ16(cpu->mem_if->data, adr); + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRH_M_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)] - IMM_OFF; + cpu->R[REG_POS(i,12)] = (u32)READ16(cpu->mem_if->data, adr); + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRH_P_REG_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)] + cpu->R[REG_POS(i,0)]; + cpu->R[REG_POS(i,12)] = (u32)READ16(cpu->mem_if->data, adr); + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRH_M_REG_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)] - cpu->R[REG_POS(i,0)]; + cpu->R[REG_POS(i,12)] = (u32)READ16(cpu->mem_if->data, adr); + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRH_PRE_INDE_P_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)] + IMM_OFF; + cpu->R[REG_POS(i,16)] = adr; + cpu->R[REG_POS(i,12)] = (u32)READ16(cpu->mem_if->data, adr); + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRH_PRE_INDE_M_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)] - IMM_OFF; + cpu->R[REG_POS(i,16)] = adr; + cpu->R[REG_POS(i,12)] = (u32)READ16(cpu->mem_if->data, adr); + + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRH_PRE_INDE_P_REG_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)] + cpu->R[REG_POS(i,0)]; + cpu->R[REG_POS(i,16)] = adr; + cpu->R[REG_POS(i,12)] =(u32)READ16(cpu->mem_if->data, adr); + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRH_PRE_INDE_M_REG_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)] - cpu->R[REG_POS(i,0)]; + cpu->R[REG_POS(i,16)] = adr; + cpu->R[REG_POS(i,12)] = (u32)READ16(cpu->mem_if->data, adr); + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRH_POS_INDE_P_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)]; + cpu->R[REG_POS(i,12)] = (u32)READ16(cpu->mem_if->data, adr); + cpu->R[REG_POS(i,16)] += IMM_OFF; + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRH_POS_INDE_M_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)]; + cpu->R[REG_POS(i,12)] = (u32)READ16(cpu->mem_if->data, adr); + cpu->R[REG_POS(i,16)] -= IMM_OFF; + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRH_POS_INDE_P_REG_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)]; + cpu->R[REG_POS(i,12)] = (u32)READ16(cpu->mem_if->data, adr); + cpu->R[REG_POS(i,16)] += cpu->R[REG_POS(i,0)]; + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRH_POS_INDE_M_REG_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)]; + cpu->R[REG_POS(i,12)] = (u32)READ16(cpu->mem_if->data, adr); + cpu->R[REG_POS(i,16)] -= cpu->R[REG_POS(i,0)]; + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +//------------STRH----------------------------- + +static u32 FASTCALL OP_STRH_P_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)] + IMM_OFF; + WRITE16(cpu->mem_if->data, adr, (u16)cpu->R[REG_POS(i,12)]); + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRH_M_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)] - IMM_OFF; + WRITE16(cpu->mem_if->data, adr, (u16)cpu->R[REG_POS(i,12)]); + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRH_P_REG_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)] + cpu->R[REG_POS(i,0)]; + WRITE16(cpu->mem_if->data, adr, (u16)cpu->R[REG_POS(i,12)]); + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRH_M_REG_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)] - cpu->R[REG_POS(i,0)]; + WRITE16(cpu->mem_if->data, adr, (u16)cpu->R[REG_POS(i,12)]); + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRH_PRE_INDE_P_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)] + IMM_OFF; + cpu->R[REG_POS(i,16)] = adr; + WRITE16(cpu->mem_if->data, adr, (u16)cpu->R[REG_POS(i,12)]); + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRH_PRE_INDE_M_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)] - IMM_OFF; + WRITE16(cpu->mem_if->data, adr, (u16)cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr; + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRH_PRE_INDE_P_REG_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)] + cpu->R[REG_POS(i,0)]; + WRITE16(cpu->mem_if->data, adr, (u16)cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr; + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRH_PRE_INDE_M_REG_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)] - cpu->R[REG_POS(i,0)]; + WRITE16(cpu->mem_if->data, adr, (u16)cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr; + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRH_POS_INDE_P_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)]; + WRITE16(cpu->mem_if->data, adr, (u16)cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] += IMM_OFF; + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRH_POS_INDE_M_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)]; + WRITE16(cpu->mem_if->data, adr, (u16)cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] -= IMM_OFF; + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRH_POS_INDE_P_REG_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)]; + WRITE16(cpu->mem_if->data, adr, (u16)cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] += cpu->R[REG_POS(i,0)]; + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRH_POS_INDE_M_REG_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)]; + WRITE16(cpu->mem_if->data, adr, (u16)cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] -= cpu->R[REG_POS(i,0)]; + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +//----------------LDRSH-------------------------- + +static u32 FASTCALL OP_LDRSH_P_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)] + IMM_OFF; + cpu->R[REG_POS(i,12)] = (s32)((s16)READ16(cpu->mem_if->data, adr)); + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRSH_M_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)] - IMM_OFF; + cpu->R[REG_POS(i,12)] = (s32)((s16)READ16(cpu->mem_if->data, adr)); + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRSH_P_REG_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)] + cpu->R[REG_POS(i,0)]; + cpu->R[REG_POS(i,12)] = (s32)((s16)READ16(cpu->mem_if->data, adr)); + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRSH_M_REG_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)] - cpu->R[REG_POS(i,0)]; + cpu->R[REG_POS(i,12)] = (s32)((s16)READ16(cpu->mem_if->data, adr)); + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRSH_PRE_INDE_P_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)] + IMM_OFF; + cpu->R[REG_POS(i,12)] = (s32)((s16)READ16(cpu->mem_if->data, adr)); + cpu->R[REG_POS(i,16)] = adr; + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRSH_PRE_INDE_M_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)] - IMM_OFF; + cpu->R[REG_POS(i,12)] = (s32)((s16)READ16(cpu->mem_if->data, adr)); + cpu->R[REG_POS(i,16)] = adr; + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRSH_PRE_INDE_P_REG_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)] + cpu->R[REG_POS(i,0)]; + cpu->R[REG_POS(i,12)] = (s32)((s16)READ16(cpu->mem_if->data, adr)); + cpu->R[REG_POS(i,16)] = adr; + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRSH_PRE_INDE_M_REG_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)] - cpu->R[REG_POS(i,0)]; + cpu->R[REG_POS(i,12)] = (s32)((s16)READ16(cpu->mem_if->data, adr)); + cpu->R[REG_POS(i,16)] = adr; + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRSH_POS_INDE_P_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)]; + cpu->R[REG_POS(i,12)] = (s32)((s16)READ16(cpu->mem_if->data, adr)); + cpu->R[REG_POS(i,16)] += IMM_OFF; + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRSH_POS_INDE_M_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)]; + cpu->R[REG_POS(i,12)] = (s32)((s16)READ16(cpu->mem_if->data, adr)); + cpu->R[REG_POS(i,16)] -= IMM_OFF; + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRSH_POS_INDE_P_REG_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)]; + cpu->R[REG_POS(i,12)] = (s32)((s16)READ16(cpu->mem_if->data, adr)); + cpu->R[REG_POS(i,16)] += cpu->R[REG_POS(i,0)]; + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRSH_POS_INDE_M_REG_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)]; + cpu->R[REG_POS(i,12)] = (s32)((s16)READ16(cpu->mem_if->data, adr)); + cpu->R[REG_POS(i,16)] -= cpu->R[REG_POS(i,0)]; + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +//----------------------LDRSB---------------------- + +static u32 FASTCALL OP_LDRSB_P_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)] + IMM_OFF; + cpu->R[REG_POS(i,12)] = (s32)((s8)READ8(cpu->mem_if->data, adr)); + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRSB_M_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)] - IMM_OFF; + cpu->R[REG_POS(i,12)] = (s32)((s8)READ8(cpu->mem_if->data, adr)); + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRSB_P_REG_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)] + cpu->R[REG_POS(i,0)]; + cpu->R[REG_POS(i,12)] = (s32)((s8)READ8(cpu->mem_if->data, adr)); + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRSB_M_REG_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)] - cpu->R[REG_POS(i,0)]; + cpu->R[REG_POS(i,12)] = (s32)((s8)READ8(cpu->mem_if->data, adr)); + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRSB_PRE_INDE_P_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)] + IMM_OFF; + cpu->R[REG_POS(i,12)] = (s32)((s8)READ8(cpu->mem_if->data, adr)); + cpu->R[REG_POS(i,16)] = adr; + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRSB_PRE_INDE_M_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)] - IMM_OFF; + cpu->R[REG_POS(i,12)] = (s32)((s8)READ8(cpu->mem_if->data, adr)); + cpu->R[REG_POS(i,16)] = adr; + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRSB_PRE_INDE_P_REG_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)] + cpu->R[REG_POS(i,0)]; + cpu->R[REG_POS(i,12)] = (s32)((s8)READ8(cpu->mem_if->data, adr)); + cpu->R[REG_POS(i,16)] = adr; + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRSB_PRE_INDE_M_REG_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)] - cpu->R[REG_POS(i,0)]; + cpu->R[REG_POS(i,12)] = (s32)((s8)READ8(cpu->mem_if->data, adr)); + cpu->R[REG_POS(i,16)] = adr; + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRSB_POS_INDE_P_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)]; + cpu->R[REG_POS(i,12)] = (s32)((s8)READ8(cpu->mem_if->data, adr)); + cpu->R[REG_POS(i,16)] += IMM_OFF; + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRSB_POS_INDE_M_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)]; + cpu->R[REG_POS(i,12)] = (s32)((s8)READ8(cpu->mem_if->data, adr)); + cpu->R[REG_POS(i,16)] -= IMM_OFF; + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRSB_POS_INDE_P_REG_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)]; + cpu->R[REG_POS(i,12)] = (s32)((s8)READ8(cpu->mem_if->data, adr)); + cpu->R[REG_POS(i,16)] += cpu->R[REG_POS(i,0)]; + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRSB_POS_INDE_M_REG_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)]; + cpu->R[REG_POS(i,12)] = (s32)((s8)READ8(cpu->mem_if->data, adr)); + cpu->R[REG_POS(i,16)] -= cpu->R[REG_POS(i,0)]; + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +//--------------MRS-------------------------------- + +static u32 FASTCALL OP_MRS_CPSR(armcpu_t *cpu) +{ + cpu->R[REG_POS(cpu->instruction,12)] = cpu->CPSR.val; + + return 1; +} + +static u32 FASTCALL OP_MRS_SPSR(armcpu_t *cpu) +{ + cpu->R[REG_POS(cpu->instruction,12)] = cpu->SPSR.val; + + return 1; +} + +//--------------MSR-------------------------------- + +static u32 FASTCALL OP_MSR_CPSR(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 operand = cpu->R[REG_POS(i,0)]; + + if(cpu->CPSR.bits.mode!=USR) + { + if(BIT16(i)) + { + armcpu_switchMode(cpu, operand & 0x1F); + cpu->CPSR.val = (cpu->CPSR.val & 0xFFFFFF00) | (operand & 0xFF); + } + if(BIT17(i)) + cpu->CPSR.val = (cpu->CPSR.val & 0xFFFF00FF) | (operand & 0xFF00); + if(BIT18(i)) + cpu->CPSR.val = (cpu->CPSR.val & 0xFF00FFFF) | (operand & 0xFF0000); + } + if(BIT19(i)) + cpu->CPSR.val = (cpu->CPSR.val & 0x00FFFFFF) | (operand & 0xFF000000); + + return 1; +} + +static u32 FASTCALL OP_MSR_SPSR(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 operand = cpu->R[REG_POS(i,0)]; + + if(cpu->CPSR.bits.mode!=USR) + { + if(BIT16(i)) + { + cpu->SPSR.val = (cpu->SPSR.val & 0xFFFFFF00) | (operand & 0XFF); + } + if(BIT17(i)) + cpu->SPSR.val = (cpu->SPSR.val & 0xFFFF00FF) | (operand & 0XFF00); + if(BIT18(i)) + cpu->SPSR.val = (cpu->SPSR.val & 0xFF00FFFF) | (operand & 0XFF0000); + } + if(BIT19(i)) + cpu->SPSR.val = (cpu->SPSR.val & 0x00FFFFFF) | (operand & 0XFF000000); + + return 1; +} + +static u32 FASTCALL OP_MSR_CPSR_IMM_VAL(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + IMM_VALUE; + + if(cpu->CPSR.bits.mode!=USR) + { + if(BIT16(i)) + { + armcpu_switchMode(cpu, shift_op & 0x1F); + cpu->CPSR.val = (cpu->CPSR.val & 0xFFFFFF00) | (shift_op & 0XFF); + } + if(BIT17(i)) + cpu->CPSR.val = (cpu->CPSR.val & 0xFFFF00FF) | (shift_op & 0XFF00); + if(BIT18(i)) + cpu->CPSR.val = (cpu->CPSR.val & 0xFF00FFFF) | (shift_op & 0XFF0000); + } + if(BIT19(i)) + { + //cpu->CPSR.val = (cpu->CPSR.val & 0xFF000000) | (shift_op & 0XFF000000); + cpu->CPSR.val = (cpu->CPSR.val & 0x00FFFFFF) | (shift_op & 0xFF000000); + } + + return 1; +} + +static u32 FASTCALL OP_MSR_SPSR_IMM_VAL(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + IMM_VALUE; + + if(cpu->CPSR.bits.mode!=USR) + { + if(BIT16(i)) + { + cpu->SPSR.val = (cpu->SPSR.val & 0xFFFFFF00) | (shift_op & 0XFF); + } + if(BIT17(i)) + cpu->SPSR.val = (cpu->SPSR.val & 0xFFFF00FF) | (shift_op & 0XFF00); + if(BIT18(i)) + cpu->SPSR.val = (cpu->SPSR.val & 0xFF00FFFF) | (shift_op & 0XFF0000); + } + if(BIT19(i)) + cpu->SPSR.val = (cpu->SPSR.val & 0xFF000000) | (shift_op & 0XFF000000); + + return 1; +} + +//-----------------BRANCH-------------------------- + +static u32 FASTCALL OP_BX(armcpu_t *cpu) +{ + u32 tmp = cpu->R[REG_POS(cpu->instruction, 0)]; + + cpu->CPSR.bits.T = BIT0(tmp); + cpu->R[15] = tmp & 0xFFFFFFFE; + cpu->next_instruction = cpu->R[15]; + return 3; +} + +static u32 FASTCALL OP_BLX_REG(armcpu_t *cpu) +{ + u32 tmp = cpu->R[REG_POS(cpu->instruction, 0)]; + + cpu->R[14] = cpu->next_instruction; + cpu->CPSR.bits.T = BIT0(tmp); + cpu->R[15] = tmp & 0xFFFFFFFE; + cpu->next_instruction = cpu->R[15]; + return 3; +} + +#define SIGNEXTEND_24(i) (((s32)((i)<<8))>>8) + +static u32 FASTCALL OP_B(armcpu_t *cpu) +{ + u32 off = SIGNEXTEND_24(cpu->instruction); + if(CONDITION(cpu->instruction)==0xF) + { + cpu->R[14] = cpu->next_instruction; + cpu->CPSR.bits.T = 1; + } + cpu->R[15] += (off<<2); + cpu->next_instruction = cpu->R[15]; + + return 3; +} + +static u32 FASTCALL OP_BL(armcpu_t *cpu) +{ + u32 off = SIGNEXTEND_24(cpu->instruction); + if(CONDITION(cpu->instruction)==0xF) + { + cpu->CPSR.bits.T = 1; + cpu->R[15] += 2; + } + cpu->R[14] = cpu->next_instruction; + cpu->R[15] += (off<<2); + cpu->next_instruction = cpu->R[15]; + + return 3; +} + +//----------------CLZ------------------------------- + +u8 CLZ_TAB[16]= +{ + 0, // 0000 + 1, // 0001 + 2, 2, // 001X + 3, 3, 3, 3, // 01XX + 4, 4, 4, 4, 4, 4, 4, 4 // 1XXX +}; + +static u32 FASTCALL OP_CLZ(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 Rm = cpu->R[REG_POS(i,0)]; + u32 pos; + + if(Rm==0) + { + cpu->R[REG_POS(i,12)]=32; + return 2; + } + + Rm |= (Rm >>1); + Rm |= (Rm >>2); + Rm |= (Rm >>4); + Rm |= (Rm >>8); + Rm |= (Rm >>16); + + pos = + CLZ_TAB[Rm&0xF] + + CLZ_TAB[(Rm>>4)&0xF] + + CLZ_TAB[(Rm>>8)&0xF] + + CLZ_TAB[(Rm>>12)&0xF] + + CLZ_TAB[(Rm>>16)&0xF] + + CLZ_TAB[(Rm>>20)&0xF] + + CLZ_TAB[(Rm>>24)&0xF] + + CLZ_TAB[(Rm>>28)&0xF]; + + cpu->R[REG_POS(i,12)]=32 - pos; + + return 2; +} + +//--------------------QADD--QSUB------------------------------ + +static u32 FASTCALL OP_QADD(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 res = cpu->R[REG_POS(i,16)]+cpu->R[REG_POS(i,0)]; + + LOG("spe add\r\n"); + if(SIGNED_OVERFLOW(cpu->R[REG_POS(i,16)],cpu->R[REG_POS(i,0)], res)) + { + cpu->CPSR.bits.Q=1; + cpu->R[REG_POS(i,12)]=0x80000000-BIT31(res); + return 2; + } + cpu->R[REG_POS(i,12)]=res; + if(REG_POS(i,12)==15) + { + cpu->R[15] &= 0XFFFFFFFC; + cpu->next_instruction = cpu->R[15]; + return 3; + } + return 2; +} + +static u32 FASTCALL OP_QSUB(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 res = cpu->R[REG_POS(i,0)]-cpu->R[REG_POS(i,16)]; + + LOG("spe add\r\n"); + if(SIGNED_UNDERFLOW(cpu->R[REG_POS(i,0)], cpu->R[REG_POS(i,16)], res)) + { + cpu->CPSR.bits.Q=1; + cpu->R[REG_POS(i,12)]=0x80000000-BIT31(res); + return 2; + } + cpu->R[REG_POS(i,12)]=res; + if(REG_POS(i,12)==15) + { + cpu->R[15] &= 0XFFFFFFFC; + cpu->next_instruction = cpu->R[15]; + return 3; + } + return 2; +} + +static u32 FASTCALL OP_QDADD(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 mul = cpu->R[REG_POS(i,16)]<<1; + u32 res; + + + LOG("spe add\r\n"); + if(BIT31(cpu->R[REG_POS(i,16)])!=BIT31(mul)) + { + cpu->CPSR.bits.Q=1; + mul = 0x80000000-BIT31(mul); + } + + res = mul + cpu->R[REG_POS(i,0)]; + if(SIGNED_OVERFLOW(cpu->R[REG_POS(i,0)],mul, res)) + { + cpu->CPSR.bits.Q=1; + cpu->R[REG_POS(i,12)]=0x80000000-BIT31(res); + return 2; + } + cpu->R[REG_POS(i,12)]=res; + if(REG_POS(i,12)==15) + { + cpu->R[15] &= 0XFFFFFFFC; + cpu->next_instruction = cpu->R[15]; + return 3; + } + return 2; +} + +static u32 FASTCALL OP_QDSUB(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 mul = cpu->R[REG_POS(i,16)]<<1; + u32 res; + + + LOG("spe add\r\n"); + if(BIT31(cpu->R[REG_POS(i,16)])!=BIT31(mul)) + { + cpu->CPSR.bits.Q=1; + mul = 0x80000000-BIT31(mul); + } + + res = cpu->R[REG_POS(i,0)] - mul; + if(SIGNED_UNDERFLOW(cpu->R[REG_POS(i,0)], mul, res)) + { + cpu->CPSR.bits.Q=1; + cpu->R[REG_POS(i,12)]=0x80000000-BIT31(res); + return 2; + } + cpu->R[REG_POS(i,12)]=res; + if(REG_POS(i,12)==15) + { + cpu->R[15] &= 0XFFFFFFFC; + cpu->next_instruction = cpu->R[15]; + return 3; + } + return 2; +} + +//-----------------SMUL------------------------------- + +#define HWORD(i) ((s32)(((s32)(i))>>16)) +#define LWORD(i) (s32)(((s32)((i)<<16))>>16) + +static u32 FASTCALL OP_SMUL_B_B(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + + cpu->R[REG_POS(i,16)] = (u32)(LWORD(cpu->R[REG_POS(i,0)])* LWORD(cpu->R[REG_POS(i,8)])); + + return 2; +} + +static u32 FASTCALL OP_SMUL_B_T(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + + cpu->R[REG_POS(i,16)] = (u32)(LWORD(cpu->R[REG_POS(i,0)])* HWORD(cpu->R[REG_POS(i,8)])); + + return 2; +} + +static u32 FASTCALL OP_SMUL_T_B(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + + cpu->R[REG_POS(i,16)] = (u32)(HWORD(cpu->R[REG_POS(i,0)])* LWORD(cpu->R[REG_POS(i,8)])); + + return 2; +} + +static u32 FASTCALL OP_SMUL_T_T(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + + cpu->R[REG_POS(i,16)] = (u32)(HWORD(cpu->R[REG_POS(i,0)])* HWORD(cpu->R[REG_POS(i,8)])); + + return 2; +} + +//-----------SMLA---------------------------- + +static u32 FASTCALL OP_SMLA_B_B(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 tmp = (u32)(LWORD(cpu->R[REG_POS(i,0)])* LWORD(cpu->R[REG_POS(i,8)])); + u32 a = cpu->R[REG_POS(i,12)]; + + //LOG("SMLABB %08X * %08X + %08X = %08X\r\n", cpu->R[REG_POS(i,0)], cpu->R[REG_POS(i,8)], a, tmp + a); + cpu->R[REG_POS(i,16)] = tmp + a; + + if(SIGNED_OVERFLOW(tmp, a, cpu->R[REG_POS(i,16)])) + cpu->CPSR.bits.Q = 1; + + return 2; +} + +static u32 FASTCALL OP_SMLA_B_T(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 tmp = (u32)(LWORD(cpu->R[REG_POS(i,0)])* HWORD(cpu->R[REG_POS(i,8)])); + u32 a = cpu->R[REG_POS(i,12)]; + + //LOG("SMLABT %08X * %08X + %08X = %08X\r\n", cpu->R[REG_POS(i,0)], cpu->R[REG_POS(i,8)], a, tmp + a); + cpu->R[REG_POS(i,16)] = tmp + a; + + if(SIGNED_OVERFLOW(tmp, a, cpu->R[REG_POS(i,16)])) + cpu->CPSR.bits.Q = 1; + + return 2; +} + +static u32 FASTCALL OP_SMLA_T_B(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 tmp = (u32)(HWORD(cpu->R[REG_POS(i,0)])* LWORD(cpu->R[REG_POS(i,8)])); + u32 a = cpu->R[REG_POS(i,12)]; + + //LOG("SMLATB %08X * %08X + %08X = %08X\r\n", cpu->R[REG_POS(i,0)], cpu->R[REG_POS(i,8)], a, tmp + a); + cpu->R[REG_POS(i,16)] = tmp + a; + + if(SIGNED_OVERFLOW(tmp, a, cpu->R[REG_POS(i,16)])) + cpu->CPSR.bits.Q = 1; + + return 2; +} + +static u32 FASTCALL OP_SMLA_T_T(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 tmp = (u32)(HWORD(cpu->R[REG_POS(i,0)])* HWORD(cpu->R[REG_POS(i,8)])); + u32 a = cpu->R[REG_POS(i,12)]; + + //LOG("SMLATT %08X * %08X + %08X = %08X\r\n", cpu->R[REG_POS(i,0)], cpu->R[REG_POS(i,8)], a, tmp + a); + cpu->R[REG_POS(i,16)] = tmp + a; + + if(SIGNED_OVERFLOW(tmp, a, cpu->R[REG_POS(i,16)])) + cpu->CPSR.bits.Q = 1; + + return 2; +} + +//--------------SMLAL--------------------------------------- + +static u32 FASTCALL OP_SMLAL_B_B(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + s64 tmp = (s64)(LWORD(cpu->R[REG_POS(i,0)])* LWORD(cpu->R[REG_POS(i,8)])); + u64 res = (u64)tmp + cpu->R[REG_POS(i,12)]; + + LOG("SMLALBB %08X * %08X + %08X%08X = %08X%08X\r\n", (int)cpu->R[REG_POS(i,0)], (int)cpu->R[REG_POS(i,8)], (int)cpu->R[REG_POS(i,16)], (int)cpu->R[REG_POS(i,12)], (int)(cpu->R[REG_POS(i,16)] + (res + ((tmp<0)*0xFFFFFFFF))), (int)(u32) res); + + cpu->R[REG_POS(i,12)] = (u32) res; + cpu->R[REG_POS(i,16)] += (res + ((tmp<0)*0xFFFFFFFF)); + + return 2; +} + +static u32 FASTCALL OP_SMLAL_B_T(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + s64 tmp = (s64)(LWORD(cpu->R[REG_POS(i,0)])* HWORD(cpu->R[REG_POS(i,8)])); + u64 res = (u64)tmp + cpu->R[REG_POS(i,12)]; + + LOG("SMLALBT %08X * %08X + %08X%08X = %08X%08X\r\n", (int)cpu->R[REG_POS(i,0)], (int)cpu->R[REG_POS(i,8)], (int)cpu->R[REG_POS(i,16)], (int)cpu->R[REG_POS(i,12)], (int)(cpu->R[REG_POS(i,16)] + res + ((tmp<0)*0xFFFFFFFF)), (int)(u32) res); + + cpu->R[REG_POS(i,12)] = (u32) res; + cpu->R[REG_POS(i,16)] += res + ((tmp<0)*0xFFFFFFFF); + + return 2; +} + +static u32 FASTCALL OP_SMLAL_T_B(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + s64 tmp = (s64)(HWORD(cpu->R[REG_POS(i,0)])* (s64)LWORD(cpu->R[REG_POS(i,8)])); + u64 res = (u64)tmp + cpu->R[REG_POS(i,12)]; + + LOG("SMLALTB %08X * %08X + %08X%08X = %08X%08X\r\n", (int)cpu->R[REG_POS(i,0)], (int)cpu->R[REG_POS(i,8)], (int)cpu->R[REG_POS(i,16)], (int)cpu->R[REG_POS(i,12)], (int)(cpu->R[REG_POS(i,16)] + res + ((tmp<0)*0xFFFFFFFF)), (int)(u32) res); + + cpu->R[REG_POS(i,12)] = (u32) res; + cpu->R[REG_POS(i,16)] += res + ((tmp<0)*0xFFFFFFFF); + + return 2; +} + +static u32 FASTCALL OP_SMLAL_T_T(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + s64 tmp = (s64)(HWORD(cpu->R[REG_POS(i,0)])* HWORD(cpu->R[REG_POS(i,8)])); + u64 res = (u64)tmp + cpu->R[REG_POS(i,12)]; + + LOG("SMLALTT %08X * %08X + %08X%08X = %08X%08X\r\n", (int)cpu->R[REG_POS(i,0)], (int)cpu->R[REG_POS(i,8)], (int)cpu->R[REG_POS(i,16)], (int)cpu->R[REG_POS(i,12)], (int)(cpu->R[REG_POS(i,16)] + res + ((tmp<0)*0xFFFFFFFF)), (int)(u32) res); + + cpu->R[REG_POS(i,12)] = (u32) res; + cpu->R[REG_POS(i,16)] += res + ((tmp<0)*0xFFFFFFFF); + + return 2; +} + +//--------------SMULW-------------------- + +static u32 FASTCALL OP_SMULW_B(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + s64 tmp = (s64)LWORD(cpu->R[REG_POS(i,8)]) * (s64)((s32)cpu->R[REG_POS(i,0)]); + + //LOG("SMULWB %08X * %08X = %08X\r\n", cpu->R[REG_POS(i,0)], cpu->R[REG_POS(i,8)], ((tmp>>16)&0xFFFFFFFF); + + cpu->R[REG_POS(i,16)] = ((tmp>>16)&0xFFFFFFFF); + + return 2; +} + +static u32 FASTCALL OP_SMULW_T(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + s64 tmp = (s64)HWORD(cpu->R[REG_POS(i,8)]) * (s64)((s32)cpu->R[REG_POS(i,0)]); + + //LOG("SMULWT %08X * %08X = %08X\r\n", cpu->R[REG_POS(i,0)], cpu->R[REG_POS(i,8)], ((tmp>>16)&0xFFFFFFFF)); + + cpu->R[REG_POS(i,16)] = ((tmp>>16)&0xFFFFFFFF); + + return 2; +} + +//--------------SMLAW------------------- +static u32 FASTCALL OP_SMLAW_B(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + s64 tmp = (s64)LWORD(cpu->R[REG_POS(i,8)]) * (s64)((s32)cpu->R[REG_POS(i,0)]); + u32 a = cpu->R[REG_POS(i,12)]; + + //LOG("SMLAWB %08X * %08X + %08X = %08X\r\n", cpu->R[REG_POS(i,0)], cpu->R[REG_POS(i,8)], a, (tmp>>16) + a); + + tmp = (tmp>>16); + + cpu->R[REG_POS(i,16)] = tmp + a; + + if(SIGNED_OVERFLOW(tmp, a, cpu->R[REG_POS(i,16)])) + cpu->CPSR.bits.Q = 1; + + return 2; +} + +static u32 FASTCALL OP_SMLAW_T(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + s64 tmp = (s64)HWORD(cpu->R[REG_POS(i,8)]) * (s64)((s32)cpu->R[REG_POS(i,0)]); + u32 a = cpu->R[REG_POS(i,12)]; + + //LOG("SMLAWT %08X * %08X + %08X = %08X\r\n", cpu->R[REG_POS(i,0)], cpu->R[REG_POS(i,8)], a, ((tmp>>16)&0xFFFFFFFF) + a); + + tmp = ((tmp>>16)&0xFFFFFFFF); + cpu->R[REG_POS(i,16)] = tmp + a; + + if(SIGNED_OVERFLOW(tmp, a, cpu->R[REG_POS(i,16)])) + cpu->CPSR.bits.Q = 1; + + return 2; +} + +//------------LDR--------------------------- + +static u32 FASTCALL OP_LDR_P_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)] + IMM_OFF_12; + u32 val = READ32(cpu->mem_if->data, adr); + + if(adr&3) + val = ROR(val, 8*(adr&3)); + + if(REG_POS(i,12)==15) + { + cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1)); + cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit; + cpu->next_instruction = cpu->R[15]; + return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; + } + + cpu->R[REG_POS(i,12)] = val; + return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDR_M_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)] - IMM_OFF_12; + u32 val = READ32(cpu->mem_if->data, adr); + + if(adr&3) + val = ROR(val, 8*(adr&3)); + + if(REG_POS(i,12)==15) + { + cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1)); + cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit; + cpu->next_instruction = cpu->R[15]; + return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; + } + + cpu->R[REG_POS(i,12)] = val; + + return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDR_P_LSL_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 val; + u32 shift_op; + LSL_IMM; + adr = cpu->R[REG_POS(i,16)] + shift_op; + val = READ32(cpu->mem_if->data, adr); + + if(adr&3) + val = ROR(val, 8*(adr&3)); + + if(REG_POS(i,12)==15) + { + cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1)); + cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit; + cpu->next_instruction = cpu->R[15]; + return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; + } + + cpu->R[REG_POS(i,12)] = val; + + return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDR_M_LSL_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 val; + u32 shift_op; + LSL_IMM; + adr = cpu->R[REG_POS(i,16)] - shift_op; + val = READ32(cpu->mem_if->data, adr); + + if(adr&3) + val = ROR(val, 8*(adr&3)); + + if(REG_POS(i,12)==15) + { + cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1)); + cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit; + cpu->next_instruction = cpu->R[15]; + return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; + } + + cpu->R[REG_POS(i,12)] = val; + + return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDR_P_LSR_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 val; + u32 shift_op; + LSR_IMM; + adr = cpu->R[REG_POS(i,16)] + shift_op; + val = READ32(cpu->mem_if->data, adr); + + if(adr&3) + val = ROR(val, 8*(adr&3)); + + if(REG_POS(i,12)==15) + { + cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1)); + cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit; + cpu->next_instruction = cpu->R[15]; + return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; + } + + cpu->R[REG_POS(i,12)] = val; + + return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDR_M_LSR_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 val; + u32 shift_op; + LSR_IMM; + adr = cpu->R[REG_POS(i,16)] - shift_op; + val = READ32(cpu->mem_if->data, adr); + + if(adr&3) + val = ROR(val, 8*(adr&3)); + + if(REG_POS(i,12)==15) + { + cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1)); + cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit; + cpu->next_instruction = cpu->R[15]; + return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; + } + + cpu->R[REG_POS(i,12)] = val; + + return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDR_P_ASR_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 val; + u32 shift_op; + ASR_IMM; + adr = cpu->R[REG_POS(i,16)] + shift_op; + val = READ32(cpu->mem_if->data, adr); + + if(adr&3) + val = ROR(val, 8*(adr&3)); + + if(REG_POS(i,12)==15) + { + cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1)); + cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit; + cpu->next_instruction = cpu->R[15]; + return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; + } + + cpu->R[REG_POS(i,12)] = val; + + return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDR_M_ASR_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 val; + u32 shift_op; + ASR_IMM; + adr = cpu->R[REG_POS(i,16)] - shift_op; + val = READ32(cpu->mem_if->data, adr); + + if(adr&3) + val = ROR(val, 8*(adr&3)); + + if(REG_POS(i,12)==15) + { + cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1)); + cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit; + cpu->next_instruction = cpu->R[15]; + return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; + } + + cpu->R[REG_POS(i,12)] = val; + + return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDR_P_ROR_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 val; + u32 shift_op; + ROR_IMM; + adr = cpu->R[REG_POS(i,16)] + shift_op; + val = READ32(cpu->mem_if->data, adr); + + if(adr&3) + val = ROR(val, 8*(adr&3)); + + if(REG_POS(i,12)==15) + { + cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1)); + cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit; + cpu->next_instruction = cpu->R[15]; + return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; + } + + cpu->R[REG_POS(i,12)] = val; + + return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDR_M_ROR_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 val; + u32 shift_op; + ROR_IMM; + adr = cpu->R[REG_POS(i,16)] - shift_op; + val = READ32(cpu->mem_if->data, adr); + + if(adr&3) + val = ROR(val, 8*(adr&3)); + + if(REG_POS(i,12)==15) + { + cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1)); + cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit; + cpu->next_instruction = cpu->R[15]; + return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; + } + + cpu->R[REG_POS(i,12)] = val; + cpu->R[REG_POS(i,16)] = adr; + + return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDR_P_IMM_OFF_PREIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)] + IMM_OFF_12; + u32 val = READ32(cpu->mem_if->data, adr); + + if(adr&3) + val = ROR(val, 8*(adr&3)); + + if(REG_POS(i,12)==15) + { + cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1)); + cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit; + cpu->next_instruction = cpu->R[15]; + cpu->R[REG_POS(i,16)] = adr; + return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; + } + + cpu->R[REG_POS(i,16)] = adr; + cpu->R[REG_POS(i,12)] = val; + + return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDR_M_IMM_OFF_PREIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)] - IMM_OFF_12; + u32 val = READ32(cpu->mem_if->data, adr); + + if(adr&3) + val = ROR(val, 8*(adr&3)); + + if(REG_POS(i,12)==15) + { + cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1)); + cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit; + cpu->next_instruction = cpu->R[15]; + cpu->R[REG_POS(i,16)] = adr; + return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; + } + + cpu->R[REG_POS(i,16)] = adr; + cpu->R[REG_POS(i,12)] = val; + + + return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDR_P_LSL_IMM_OFF_PREIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 val; + u32 shift_op; + LSL_IMM; + adr = cpu->R[REG_POS(i,16)] + shift_op; + val = READ32(cpu->mem_if->data, adr); + + if(adr&3) + val = ROR(val, 8*(adr&3)); + + if(REG_POS(i,12)==15) + { + cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1)); + cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit; + cpu->next_instruction = cpu->R[15]; + cpu->R[REG_POS(i,16)] = adr; + return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; + } + + cpu->R[REG_POS(i,16)] = adr; + cpu->R[REG_POS(i,12)] = val; + + + return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDR_M_LSL_IMM_OFF_PREIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 val; + u32 shift_op; + LSL_IMM; + adr = cpu->R[REG_POS(i,16)] - shift_op; + val = READ32(cpu->mem_if->data, adr); + + if(adr&3) + val = ROR(val, 8*(adr&3)); + + if(REG_POS(i,12)==15) + { + cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1)); + cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit; + cpu->next_instruction = cpu->R[15]; + cpu->R[REG_POS(i,16)] = adr; + return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; + } + + cpu->R[REG_POS(i,16)] = adr; + cpu->R[REG_POS(i,12)] = val; + + + return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDR_P_LSR_IMM_OFF_PREIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 val; + u32 shift_op; + LSR_IMM; + adr = cpu->R[REG_POS(i,16)] + shift_op; + val = READ32(cpu->mem_if->data, adr); + + if(adr&3) + val = ROR(val, 8*(adr&3)); + + if(REG_POS(i,12)==15) + { + cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1)); + cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit; + cpu->next_instruction = cpu->R[15]; + cpu->R[REG_POS(i,16)] = adr; + return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; + } + + cpu->R[REG_POS(i,16)] = adr; + cpu->R[REG_POS(i,12)] = val; + + + return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDR_M_LSR_IMM_OFF_PREIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 val; + u32 shift_op; + LSR_IMM; + adr = cpu->R[REG_POS(i,16)] - shift_op; + val = READ32(cpu->mem_if->data, adr); + + if(adr&3) + val = ROR(val, 8*(adr&3)); + + if(REG_POS(i,12)==15) + { + cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1)); + cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit; + cpu->next_instruction = cpu->R[15]; + cpu->R[REG_POS(i,16)] = adr; + return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; + } + + cpu->R[REG_POS(i,16)] = adr; + cpu->R[REG_POS(i,12)] = val; + + + return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDR_P_ASR_IMM_OFF_PREIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 val; + u32 shift_op; + ASR_IMM; + adr = cpu->R[REG_POS(i,16)] + shift_op; + val = READ32(cpu->mem_if->data, adr); + + if(adr&3) + val = ROR(val, 8*(adr&3)); + + if(REG_POS(i,12)==15) + { + cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1)); + cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit; + cpu->next_instruction = cpu->R[15]; + cpu->R[REG_POS(i,16)] = adr; + return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; + } + + cpu->R[REG_POS(i,16)] = adr; + cpu->R[REG_POS(i,12)] = val; + + + return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDR_M_ASR_IMM_OFF_PREIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 val; + u32 shift_op; + ASR_IMM; + adr = cpu->R[REG_POS(i,16)] - shift_op; + val = READ32(cpu->mem_if->data, adr); + + if(adr&3) + val = ROR(val, 8*(adr&3)); + + if(REG_POS(i,12)==15) + { + cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1)); + cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit; + cpu->next_instruction = cpu->R[15]; + cpu->R[REG_POS(i,16)] = adr; + return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; + } + + cpu->R[REG_POS(i,16)] = adr; + cpu->R[REG_POS(i,12)] = val; + + + return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDR_P_ROR_IMM_OFF_PREIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 val; + u32 shift_op; + ROR_IMM; + adr = cpu->R[REG_POS(i,16)] + shift_op; + val = READ32(cpu->mem_if->data, adr); + + if(adr&3) + val = ROR(val, 8*(adr&3)); + + if(REG_POS(i,12)==15) + { + cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1)); + cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit; + cpu->next_instruction = cpu->R[15]; + cpu->R[REG_POS(i,16)] = adr; + return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; + } + + cpu->R[REG_POS(i,16)] = adr; + cpu->R[REG_POS(i,12)] = val; + + + return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDR_M_ROR_IMM_OFF_PREIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 val; + u32 shift_op; + ROR_IMM; + adr = cpu->R[REG_POS(i,16)] - shift_op; + val = READ32(cpu->mem_if->data, adr); + + if(adr&3) + val = ROR(val, 8*(adr&3)); + + if(REG_POS(i,12)==15) + { + cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1)); + cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit; + cpu->next_instruction = cpu->R[15]; + cpu->R[REG_POS(i,16)] = adr; + return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; + } + + cpu->R[REG_POS(i,16)] = adr; + cpu->R[REG_POS(i,12)] = val; + + return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDR_P_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)]; + u32 val = READ32(cpu->mem_if->data, adr); + + if(adr&3) + val = ROR(val, 8*(adr&3)); + + if(REG_POS(i,12)==15) + { + cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1)); + cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit; + cpu->next_instruction = cpu->R[15]; + cpu->R[REG_POS(i,16)] = adr + IMM_OFF_12; + return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; + } + + cpu->R[REG_POS(i,16)] = adr + IMM_OFF_12; + cpu->R[REG_POS(i,12)] = val; + + return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +//------------------------------------------------------------ +static u32 FASTCALL OP_LDR_P_IMM_OFF_POSTIND2(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + + u32 adr = cpu->R[REG_POS(i,16)]; + u32 val = READ32(cpu->mem_if->data, adr); + u32 old; + if(adr&3) + val = ROR(val, 8*(adr&3)); + + if(REG_POS(i,12)==15) + { + cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1)); + cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit; + cpu->next_instruction = cpu->R[15]; + cpu->R[REG_POS(i,16)] = adr + IMM_OFF_12; + return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; + } + + old = armcpu_switchMode(cpu, USR); + cpu->R[REG_POS(i,12)] = val; + armcpu_switchMode(cpu, old); + + cpu->R[REG_POS(i,16)] = adr + IMM_OFF_12; + + return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +//------------------------------------------------------------ + +static u32 FASTCALL OP_LDR_M_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)]; + u32 val = READ32(cpu->mem_if->data, adr); + + if(adr&3) + val = ROR(val, 8*(adr&3)); + + if(REG_POS(i,12)==15) + { + cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1)); + cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit; + cpu->next_instruction = cpu->R[15]; + cpu->R[REG_POS(i,16)] = adr - IMM_OFF_12; + return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; + } + + cpu->R[REG_POS(i,16)] = adr - IMM_OFF_12; + cpu->R[REG_POS(i,12)] = val; + + return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDR_P_LSL_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 val; + u32 shift_op; + LSL_IMM; + adr = cpu->R[REG_POS(i,16)]; + val = READ32(cpu->mem_if->data, adr); + + if(adr&3) + val = ROR(val, 8*(adr&3)); + + if(REG_POS(i,12)==15) + { + cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1)); + cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit; + cpu->next_instruction = cpu->R[15]; + cpu->R[REG_POS(i,16)] = adr + shift_op; + return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; + } + + cpu->R[REG_POS(i,16)] = adr + shift_op; + cpu->R[REG_POS(i,12)] = val; + + return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDR_M_LSL_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 val; + u32 shift_op; + LSL_IMM; + adr = cpu->R[REG_POS(i,16)]; + val = READ32(cpu->mem_if->data, adr); + + if(adr&3) + val = ROR(val, 8*(adr&3)); + + if(REG_POS(i,12)==15) + { + cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1)); + cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit; + cpu->next_instruction = cpu->R[15]; + cpu->R[REG_POS(i,16)] = adr - shift_op; + return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; + } + + cpu->R[REG_POS(i,16)] = adr - shift_op; + cpu->R[REG_POS(i,12)] = val; + + return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDR_P_LSR_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 val; + u32 shift_op; + LSR_IMM; + adr = cpu->R[REG_POS(i,16)]; + val = READ32(cpu->mem_if->data, adr); + + if(adr&3) + val = ROR(val, 8*(adr&3)); + + if(REG_POS(i,12)==15) + { + cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1)); + cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit; + cpu->next_instruction = cpu->R[15]; + cpu->R[REG_POS(i,16)] = adr + shift_op; + return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; + } + + cpu->R[REG_POS(i,16)] = adr + shift_op; + cpu->R[REG_POS(i,12)] = val; + + return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDR_M_LSR_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 val; + u32 shift_op; + LSR_IMM; + adr = cpu->R[REG_POS(i,16)]; + val = READ32(cpu->mem_if->data, adr); + + if(adr&3) + val = ROR(val, 8*(adr&3)); + + if(REG_POS(i,12)==15) + { + cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1)); + cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit; + cpu->next_instruction = cpu->R[15]; + cpu->R[REG_POS(i,16)] = adr - shift_op; + return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; + } + + cpu->R[REG_POS(i,16)] = adr - shift_op; + cpu->R[REG_POS(i,12)] = val; + + return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDR_P_ASR_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 val; + u32 shift_op; + ASR_IMM; + adr = cpu->R[REG_POS(i,16)]; + val = READ32(cpu->mem_if->data, adr); + + if(adr&3) + val = ROR(val, 8*(adr&3)); + + if(REG_POS(i,12)==15) + { + cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1)); + cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit; + cpu->next_instruction = cpu->R[15]; + cpu->R[REG_POS(i,16)] = adr + shift_op; + return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; + } + + cpu->R[REG_POS(i,16)] = adr + shift_op; + cpu->R[REG_POS(i,12)] = val; + + return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDR_M_ASR_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 val; + u32 shift_op; + ASR_IMM; + adr = cpu->R[REG_POS(i,16)]; + val = READ32(cpu->mem_if->data, adr); + + if(adr&3) + val = ROR(val, 8*(adr&3)); + + if(REG_POS(i,12)==15) + { + cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1)); + cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit; + cpu->next_instruction = cpu->R[15]; + cpu->R[REG_POS(i,16)] = adr - shift_op; + return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; + } + + cpu->R[REG_POS(i,16)] = adr - shift_op; + cpu->R[REG_POS(i,12)] = val; + + return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDR_P_ROR_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 val; + u32 shift_op; + ROR_IMM; + adr = cpu->R[REG_POS(i,16)]; + val = READ32(cpu->mem_if->data, adr); + + if(adr&3) + val = ROR(val, 8*(adr&3)); + + if(REG_POS(i,12)==15) + { + cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1)); + cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit; + cpu->next_instruction = cpu->R[15]; + cpu->R[REG_POS(i,16)] = adr + shift_op; + return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; + } + + cpu->R[REG_POS(i,16)] = adr + shift_op; + cpu->R[REG_POS(i,12)] = val; + + return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDR_M_ROR_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 val; + u32 shift_op; + ROR_IMM; + adr = cpu->R[REG_POS(i,16)]; + val = READ32(cpu->mem_if->data, adr); + + if(adr&3) + val = ROR(val, 8*(adr&3)); + + if(REG_POS(i,12)==15) + { + cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1)); + cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit; + cpu->next_instruction = cpu->R[15]; + cpu->R[REG_POS(i,16)] = adr - shift_op; + return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; + } + + cpu->R[REG_POS(i,16)] = adr - shift_op; + cpu->R[REG_POS(i,12)] = val; + + return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +//-----------------LDRB------------------------------------------- + +static u32 FASTCALL OP_LDRB_P_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)] + IMM_OFF_12; + u32 val = READ8(cpu->mem_if->data, adr); + cpu->R[REG_POS(i,12)] = val; + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRB_M_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)] - IMM_OFF_12; + u32 val = READ8(cpu->mem_if->data, adr); + cpu->R[REG_POS(i,12)] = val; + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRB_P_LSL_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 val; + u32 shift_op; + LSL_IMM; + adr = cpu->R[REG_POS(i,16)] + shift_op; + val = READ8(cpu->mem_if->data, adr); + cpu->R[REG_POS(i,12)] = val; + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRB_M_LSL_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 val; + u32 shift_op; + LSL_IMM; + adr = cpu->R[REG_POS(i,16)] - shift_op; + val = READ8(cpu->mem_if->data, adr); + cpu->R[REG_POS(i,12)] = val; + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRB_P_LSR_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 val; + u32 shift_op; + LSR_IMM; + adr = cpu->R[REG_POS(i,16)] + shift_op; + val = READ8(cpu->mem_if->data, adr); + cpu->R[REG_POS(i,12)] = val; + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRB_M_LSR_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 val; + u32 shift_op; + LSR_IMM; + adr = cpu->R[REG_POS(i,16)] - shift_op; + val = READ8(cpu->mem_if->data, adr); + cpu->R[REG_POS(i,12)] = val; + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRB_P_ASR_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 val; + u32 shift_op; + ASR_IMM; + adr = cpu->R[REG_POS(i,16)] + shift_op; + val = READ8(cpu->mem_if->data, adr); + cpu->R[REG_POS(i,12)] = val; + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRB_M_ASR_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 val; + u32 shift_op; + ASR_IMM; + adr = cpu->R[REG_POS(i,16)] - shift_op; + val = READ8(cpu->mem_if->data, adr); + cpu->R[REG_POS(i,12)] = val; + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRB_P_ROR_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 val; + u32 shift_op; + ROR_IMM; + adr = cpu->R[REG_POS(i,16)] + shift_op; + val = READ8(cpu->mem_if->data, adr); + cpu->R[REG_POS(i,12)] = val; + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRB_M_ROR_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 val; + u32 shift_op; + ROR_IMM; + adr = cpu->R[REG_POS(i,16)] - shift_op; + val = READ8(cpu->mem_if->data, adr); + cpu->R[REG_POS(i,12)] = val; + cpu->R[REG_POS(i,16)] = adr; + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRB_P_IMM_OFF_PREIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)] + IMM_OFF_12; + u32 val = READ8(cpu->mem_if->data, adr); + + cpu->R[REG_POS(i,16)] = adr; + cpu->R[REG_POS(i,12)] = val; + + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRB_M_IMM_OFF_PREIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)] - IMM_OFF_12; + u32 val = READ8(cpu->mem_if->data, adr); + + cpu->R[REG_POS(i,16)] = adr; + cpu->R[REG_POS(i,12)] = val; + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRB_P_LSL_IMM_OFF_PREIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 val; + u32 shift_op; + LSL_IMM; + adr = cpu->R[REG_POS(i,16)] + shift_op; + val = READ8(cpu->mem_if->data, adr); + + cpu->R[REG_POS(i,16)] = adr; + cpu->R[REG_POS(i,12)] = val; + + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRB_M_LSL_IMM_OFF_PREIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 val; + u32 shift_op; + LSL_IMM; + adr = cpu->R[REG_POS(i,16)] - shift_op; + val = READ8(cpu->mem_if->data, adr); + + cpu->R[REG_POS(i,16)] = adr; + cpu->R[REG_POS(i,12)] = val; + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRB_P_LSR_IMM_OFF_PREIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 val; + u32 shift_op; + LSR_IMM; + adr = cpu->R[REG_POS(i,16)] + shift_op; + val = READ8(cpu->mem_if->data, adr); + cpu->R[REG_POS(i,16)] = adr; + cpu->R[REG_POS(i,12)] = val; + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRB_M_LSR_IMM_OFF_PREIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 val; + u32 shift_op; + LSR_IMM; + adr = cpu->R[REG_POS(i,16)] - shift_op; + val = READ8(cpu->mem_if->data, adr); + cpu->R[REG_POS(i,16)] = adr; + cpu->R[REG_POS(i,12)] = val; + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRB_P_ASR_IMM_OFF_PREIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 val; + u32 shift_op; + ASR_IMM; + adr = cpu->R[REG_POS(i,16)] + shift_op; + val = READ8(cpu->mem_if->data, adr); + cpu->R[REG_POS(i,16)] = adr; + cpu->R[REG_POS(i,12)] = val; + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRB_M_ASR_IMM_OFF_PREIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 val; + u32 shift_op; + ASR_IMM; + adr = cpu->R[REG_POS(i,16)] - shift_op; + val = READ8(cpu->mem_if->data, adr); + cpu->R[REG_POS(i,16)] = adr; + cpu->R[REG_POS(i,12)] = val; + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRB_P_ROR_IMM_OFF_PREIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 val; + u32 shift_op; + ROR_IMM; + adr = cpu->R[REG_POS(i,16)] + shift_op; + val = READ8(cpu->mem_if->data, adr); + cpu->R[REG_POS(i,16)] = adr; + cpu->R[REG_POS(i,12)] = val; + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRB_M_ROR_IMM_OFF_PREIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 val; + u32 shift_op; + ROR_IMM; + adr = cpu->R[REG_POS(i,16)] - shift_op; + val = READ8(cpu->mem_if->data, adr); + cpu->R[REG_POS(i,16)] = adr; + cpu->R[REG_POS(i,12)] = val; + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRB_P_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)]; + u32 val = READ8(cpu->mem_if->data, adr); + cpu->R[REG_POS(i,16)] = adr + IMM_OFF_12; + cpu->R[REG_POS(i,12)] = val; + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRB_M_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)]; + u32 val = READ8(cpu->mem_if->data, adr); + cpu->R[REG_POS(i,16)] = adr - IMM_OFF_12; + cpu->R[REG_POS(i,12)] = val; + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRB_P_LSL_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 val; + u32 shift_op; + LSL_IMM; + adr = cpu->R[REG_POS(i,16)]; + val = READ8(cpu->mem_if->data, adr); + cpu->R[REG_POS(i,16)] = adr + shift_op; + cpu->R[REG_POS(i,12)] = val; + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRB_M_LSL_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 val; + u32 shift_op; + LSL_IMM; + adr = cpu->R[REG_POS(i,16)]; + val = READ8(cpu->mem_if->data, adr); + cpu->R[REG_POS(i,16)] = adr - shift_op; + cpu->R[REG_POS(i,12)] = val; + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRB_P_LSR_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 val; + u32 shift_op; + LSR_IMM; + adr = cpu->R[REG_POS(i,16)]; + val = READ8(cpu->mem_if->data, adr); + cpu->R[REG_POS(i,16)] = adr + shift_op; + cpu->R[REG_POS(i,12)] = val; + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRB_M_LSR_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 val; + u32 shift_op; + LSR_IMM; + adr = cpu->R[REG_POS(i,16)]; + val = READ8(cpu->mem_if->data, adr); + cpu->R[REG_POS(i,16)] = adr - shift_op; + cpu->R[REG_POS(i,12)] = val; + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRB_P_ASR_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 val; + u32 shift_op; + ASR_IMM; + adr = cpu->R[REG_POS(i,16)]; + val = READ8(cpu->mem_if->data, adr); + cpu->R[REG_POS(i,16)] = adr + shift_op; + cpu->R[REG_POS(i,12)] = val; + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRB_M_ASR_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 val; + u32 shift_op; + ASR_IMM; + adr = cpu->R[REG_POS(i,16)]; + val = READ8(cpu->mem_if->data, adr); + cpu->R[REG_POS(i,16)] = adr - shift_op; + cpu->R[REG_POS(i,12)] = val; + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRB_P_ROR_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 val; + u32 shift_op; + ROR_IMM; + adr = cpu->R[REG_POS(i,16)]; + val = READ8(cpu->mem_if->data, adr); + cpu->R[REG_POS(i,16)] = adr + shift_op; + cpu->R[REG_POS(i,12)] = val; + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRB_M_ROR_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 val; + u32 shift_op; + ROR_IMM; + adr = cpu->R[REG_POS(i,16)]; + val = READ8(cpu->mem_if->data, adr); + cpu->R[REG_POS(i,16)] = adr - shift_op; + cpu->R[REG_POS(i,12)] = val; + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +//----------------------STR-------------------------------- + +static u32 FASTCALL OP_STR_P_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)] + IMM_OFF_12; + WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); + +// execute = false; + + return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STR_M_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)] - IMM_OFF_12; + WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); + + return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STR_P_LSL_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 shift_op; + LSL_IMM; + adr = cpu->R[REG_POS(i,16)] + shift_op; + WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); + + return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STR_M_LSL_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 shift_op; + LSL_IMM; + adr = cpu->R[REG_POS(i,16)] - shift_op; + WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); + + return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STR_P_LSR_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 shift_op; + LSR_IMM; + adr = cpu->R[REG_POS(i,16)] + shift_op; + WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); + + return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STR_M_LSR_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 shift_op; + LSR_IMM; + adr = cpu->R[REG_POS(i,16)] - shift_op; + WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); + + return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STR_P_ASR_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 shift_op; + ASR_IMM; + adr = cpu->R[REG_POS(i,16)] + shift_op; + WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); + + return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STR_M_ASR_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 shift_op; + ASR_IMM; + adr = cpu->R[REG_POS(i,16)] - shift_op; + WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); + + return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STR_P_ROR_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 shift_op; + ROR_IMM; + adr = cpu->R[REG_POS(i,16)] + shift_op; + WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); + + return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STR_M_ROR_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 shift_op; + ROR_IMM; + adr = cpu->R[REG_POS(i,16)] - shift_op; + WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr; + + return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STR_P_IMM_OFF_PREIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)] + IMM_OFF_12; + WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr; + + return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STR_M_IMM_OFF_PREIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)] - IMM_OFF_12; + WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr; + + return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STR_P_LSL_IMM_OFF_PREIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 shift_op; + LSL_IMM; + adr = cpu->R[REG_POS(i,16)] + shift_op; + WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr; + + return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STR_M_LSL_IMM_OFF_PREIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 shift_op; + LSL_IMM; + adr = cpu->R[REG_POS(i,16)] - shift_op; + WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr; + + return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STR_P_LSR_IMM_OFF_PREIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 shift_op; + LSR_IMM; + adr = cpu->R[REG_POS(i,16)] + shift_op; + WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr; + + return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STR_M_LSR_IMM_OFF_PREIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 shift_op; + LSR_IMM; + adr = cpu->R[REG_POS(i,16)] - shift_op; + WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr; + + return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STR_P_ASR_IMM_OFF_PREIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 shift_op; + ASR_IMM; + adr = cpu->R[REG_POS(i,16)] + shift_op; + WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr; + + return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STR_M_ASR_IMM_OFF_PREIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 shift_op; + ASR_IMM; + adr = cpu->R[REG_POS(i,16)] - shift_op; + WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr; + + return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STR_P_ROR_IMM_OFF_PREIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 shift_op; + ROR_IMM; + adr = cpu->R[REG_POS(i,16)] + shift_op; + WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr; + + return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STR_M_ROR_IMM_OFF_PREIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 shift_op; + ROR_IMM; + adr = cpu->R[REG_POS(i,16)] - shift_op; + WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr; + + return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STR_P_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)]; + WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr + IMM_OFF_12; + + return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STR_M_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)]; + WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr - IMM_OFF_12; + + return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STR_P_LSL_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 shift_op; + LSL_IMM; + adr = cpu->R[REG_POS(i,16)]; + WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr + shift_op; + + return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STR_M_LSL_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 shift_op; + LSL_IMM; + adr = cpu->R[REG_POS(i,16)]; + WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr - shift_op; + + return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STR_P_LSR_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 shift_op; + LSR_IMM; + adr = cpu->R[REG_POS(i,16)]; + WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr + shift_op; + + return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STR_M_LSR_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 shift_op; + LSR_IMM; + adr = cpu->R[REG_POS(i,16)]; + WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr - shift_op; + + return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STR_P_ASR_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 shift_op; + ASR_IMM; + adr = cpu->R[REG_POS(i,16)]; + WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr + shift_op; + + return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STR_M_ASR_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 shift_op; + ASR_IMM; + adr = cpu->R[REG_POS(i,16)]; + WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr - shift_op; + + return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STR_P_ROR_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 shift_op; + ROR_IMM; + adr = cpu->R[REG_POS(i,16)]; + WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr + shift_op; + + return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STR_M_ROR_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 shift_op; + ROR_IMM; + adr = cpu->R[REG_POS(i,16)]; + WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr - shift_op; + + return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +//-----------------------STRB------------------------------------- + +static u32 FASTCALL OP_STRB_P_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)] + IMM_OFF_12; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRB_M_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)] - IMM_OFF_12; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRB_P_LSL_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 shift_op; + LSL_IMM; + adr = cpu->R[REG_POS(i,16)] + shift_op; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRB_M_LSL_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 shift_op; + LSL_IMM; + adr = cpu->R[REG_POS(i,16)] - shift_op; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRB_P_LSR_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 shift_op; + LSR_IMM; + adr = cpu->R[REG_POS(i,16)] + shift_op; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRB_M_LSR_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 shift_op; + LSR_IMM; + adr = cpu->R[REG_POS(i,16)] - shift_op; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRB_P_ASR_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 shift_op; + ASR_IMM; + adr = cpu->R[REG_POS(i,16)] + shift_op; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRB_M_ASR_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 shift_op; + ASR_IMM; + adr = cpu->R[REG_POS(i,16)] - shift_op; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRB_P_ROR_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 shift_op; + ROR_IMM; + adr = cpu->R[REG_POS(i,16)] + shift_op; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRB_M_ROR_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 shift_op; + ROR_IMM; + adr = cpu->R[REG_POS(i,16)] - shift_op; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRB_P_IMM_OFF_PREIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)] + IMM_OFF_12; + WRITE8(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr; + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRB_M_IMM_OFF_PREIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)] - IMM_OFF_12; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr; + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRB_P_LSL_IMM_OFF_PREIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 shift_op; + LSL_IMM; + adr = cpu->R[REG_POS(i,16)] + shift_op; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr; + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRB_M_LSL_IMM_OFF_PREIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 shift_op; + LSL_IMM; + adr = cpu->R[REG_POS(i,16)] - shift_op; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr; + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRB_P_LSR_IMM_OFF_PREIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 shift_op; + LSR_IMM; + adr = cpu->R[REG_POS(i,16)] + shift_op; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr; + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRB_M_LSR_IMM_OFF_PREIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 shift_op; + LSR_IMM; + adr = cpu->R[REG_POS(i,16)] - shift_op; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr; + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRB_P_ASR_IMM_OFF_PREIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 shift_op; + ASR_IMM; + adr = cpu->R[REG_POS(i,16)] + shift_op; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr; + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRB_M_ASR_IMM_OFF_PREIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 shift_op; + ASR_IMM; + adr = cpu->R[REG_POS(i,16)] - shift_op; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr; + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRB_P_ROR_IMM_OFF_PREIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 shift_op; + ROR_IMM; + adr = cpu->R[REG_POS(i,16)] + shift_op; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr; + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRB_M_ROR_IMM_OFF_PREIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 shift_op; + ROR_IMM; + adr = cpu->R[REG_POS(i,16)] - shift_op; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr; + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRB_P_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)]; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr + IMM_OFF_12; + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRB_M_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)]; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr - IMM_OFF_12; + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRB_P_LSL_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 shift_op; + LSL_IMM; + adr = cpu->R[REG_POS(i,16)]; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr + shift_op; + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRB_M_LSL_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 shift_op; + LSL_IMM; + adr = cpu->R[REG_POS(i,16)]; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr - shift_op; + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRB_P_LSR_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 shift_op; + LSR_IMM; + adr = cpu->R[REG_POS(i,16)]; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr + shift_op; + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRB_M_LSR_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 shift_op; + LSR_IMM; + adr = cpu->R[REG_POS(i,16)]; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr - shift_op; + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRB_P_ASR_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 shift_op; + ASR_IMM; + adr = cpu->R[REG_POS(i,16)]; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr + shift_op; + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRB_M_ASR_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 shift_op; + ASR_IMM; + adr = cpu->R[REG_POS(i,16)]; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr - shift_op; + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRB_P_ROR_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 shift_op; + ROR_IMM; + adr = cpu->R[REG_POS(i,16)]; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr + shift_op; + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRB_M_ROR_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 shift_op; + ROR_IMM; + adr = cpu->R[REG_POS(i,16)]; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr - shift_op; + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +//-----------------------LDRBT------------------------------------- + +static u32 FASTCALL OP_LDRBT_P_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 oldmode; + u32 i; + u32 adr; + u32 val; + + if(cpu->CPSR.bits.mode==USR) + return 2; + oldmode = armcpu_switchMode(cpu, SYS); + + i = cpu->instruction; + adr = cpu->R[REG_POS(i,16)]; + val = READ8(cpu->mem_if->data, adr); + cpu->R[REG_POS(i,12)] = val; + cpu->R[REG_POS(i,16)] = adr + IMM_OFF_12; + + armcpu_switchMode(cpu, oldmode); + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRBT_M_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 oldmode; + u32 i; + u32 adr; + u32 val; + + if(cpu->CPSR.bits.mode==USR) + return 2; + oldmode = armcpu_switchMode(cpu, SYS); + + //execute = FALSE; + LOG("Untested opcode: OP_LDRBT_M_IMM_OFF_POSTIND\n"); + + + i = cpu->instruction; + adr = cpu->R[REG_POS(i,16)]; + val = READ8(cpu->mem_if->data, adr); + cpu->R[REG_POS(i,12)] = val; + cpu->R[REG_POS(i,16)] = adr - IMM_OFF_12; + + armcpu_switchMode(cpu, oldmode); + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRBT_P_REG_OFF_POSTIND(armcpu_t *cpu) +{ + u32 oldmode; + u32 i; + u32 adr; + u32 val; + + if(cpu->CPSR.bits.mode==USR) + return 2; + + oldmode = armcpu_switchMode(cpu, SYS); + //execute = FALSE; + LOG("Untested opcode: OP_LDRBT_P_REG_OFF_POSTIND"); + + + i = cpu->instruction; + adr = cpu->R[REG_POS(i,16)]; + val = READ8(cpu->mem_if->data, adr); + cpu->R[REG_POS(i,12)] = val; + cpu->R[REG_POS(i,16)] = adr + cpu->R[REG_POS(i,0)]; + + armcpu_switchMode(cpu, oldmode); + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRBT_P_LSL_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 oldmode; + u32 i; + u32 adr; + u32 val; + u32 shift_op; + + if(cpu->CPSR.bits.mode==USR) + return 2; + oldmode = armcpu_switchMode(cpu, SYS); + //execute = FALSE; + LOG("Untested opcode: OP_LDRBT_P_LSL_IMM_OFF_POSTIND"); + + + i = cpu->instruction; + LSL_IMM; + adr = cpu->R[REG_POS(i,16)]; + val = READ8(cpu->mem_if->data, adr); + cpu->R[REG_POS(i,12)] = val; + cpu->R[REG_POS(i,16)] = adr + shift_op; + + armcpu_switchMode(cpu, oldmode); + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRBT_M_LSL_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 oldmode; + u32 i; + u32 adr; + u32 val; + u32 shift_op; + + if(cpu->CPSR.bits.mode==USR) + return 2; + + oldmode = armcpu_switchMode(cpu, SYS); + //execute = FALSE; + LOG("Untested opcode: OP_LDRBT_M_LSL_IMM_OFF_POSTIND"); + + + i = cpu->instruction; + LSL_IMM; + adr = cpu->R[REG_POS(i,16)]; + val = READ8(cpu->mem_if->data, adr); + cpu->R[REG_POS(i,12)] = val; + cpu->R[REG_POS(i,16)] = adr - shift_op; + + armcpu_switchMode(cpu, oldmode); + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRBT_P_LSR_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 oldmode; + u32 i; + u32 adr; + u32 val; + u32 shift_op; + + if(cpu->CPSR.bits.mode==USR) + return 2; + + oldmode = armcpu_switchMode(cpu, SYS); + //execute = FALSE; + LOG("Untested opcode: OP_LDRBT_P_LSR_IMM_OFF_POSTIND"); + + + i = cpu->instruction; + LSR_IMM; + adr = cpu->R[REG_POS(i,16)]; + val = READ8(cpu->mem_if->data, adr); + cpu->R[REG_POS(i,12)] = val; + cpu->R[REG_POS(i,16)] = adr + shift_op; + + armcpu_switchMode(cpu, oldmode); + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRBT_M_LSR_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 oldmode; + u32 i; + u32 adr; + u32 val; + u32 shift_op; + + if(cpu->CPSR.bits.mode==USR) + return 2; + + oldmode = armcpu_switchMode(cpu, SYS); + //execute = FALSE; + LOG("Untested opcode: OP_LDRBT_M_LSR_IMM_OFF_POSTIND"); + + + i = cpu->instruction; + LSR_IMM; + adr = cpu->R[REG_POS(i,16)]; + val = READ8(cpu->mem_if->data, adr); + cpu->R[REG_POS(i,12)] = val; + cpu->R[REG_POS(i,16)] = adr - shift_op; + + armcpu_switchMode(cpu, oldmode); + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRBT_P_ASR_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 oldmode; + u32 i; + u32 adr; + u32 val; + u32 shift_op; + + if(cpu->CPSR.bits.mode==USR) + return 2; + + oldmode = armcpu_switchMode(cpu, SYS); + //execute = FALSE; + LOG("Untested opcode: OP_LDRBT_P_ASR_IMM_OFF_POSTIND"); + + + i = cpu->instruction; + ASR_IMM; + adr = cpu->R[REG_POS(i,16)]; + val = READ8(cpu->mem_if->data, adr); + cpu->R[REG_POS(i,12)] = val; + cpu->R[REG_POS(i,16)] = adr + shift_op; + + armcpu_switchMode(cpu, oldmode); + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRBT_M_ASR_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 oldmode; + u32 i; + u32 adr; + u32 val; + u32 shift_op; + + if(cpu->CPSR.bits.mode==USR) + return 2; + + oldmode = armcpu_switchMode(cpu, SYS); + //execute = FALSE; + LOG("Untested opcode: OP_LDRBT_M_ASR_IMM_OFF_POSTIND"); + + + i = cpu->instruction; + ASR_IMM; + adr = cpu->R[REG_POS(i,16)]; + val = READ8(cpu->mem_if->data, adr); + cpu->R[REG_POS(i,12)] = val; + cpu->R[REG_POS(i,16)] = adr - shift_op; + + armcpu_switchMode(cpu, oldmode); + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRBT_P_ROR_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 oldmode; + u32 i; + u32 adr; + u32 val; + u32 shift_op; + + if(cpu->CPSR.bits.mode==USR) + return 2; + + oldmode = armcpu_switchMode(cpu, SYS); + //execute = FALSE; + LOG("Untested opcode: OP_LDRBT_P_ROR_IMM_OFF_POSTIND"); + + + i = cpu->instruction; + ROR_IMM; + adr = cpu->R[REG_POS(i,16)]; + val = READ8(cpu->mem_if->data, adr); + cpu->R[REG_POS(i,12)] = val; + cpu->R[REG_POS(i,16)] = adr + shift_op; + + armcpu_switchMode(cpu, oldmode); + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRBT_M_ROR_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 oldmode; + u32 i; + u32 adr; + u32 val; + u32 shift_op; + + if(cpu->CPSR.bits.mode==USR) + return 2; + + oldmode = armcpu_switchMode(cpu, SYS); + //execute = FALSE; + LOG("Untested opcode: OP_LDRBT_M_ROR_IMM_OFF_POSTIND"); + + + i = cpu->instruction; + ROR_IMM; + adr = cpu->R[REG_POS(i,16)]; + val = READ8(cpu->mem_if->data, adr); + cpu->R[REG_POS(i,12)] = val; + cpu->R[REG_POS(i,16)] = adr - shift_op; + + armcpu_switchMode(cpu, oldmode); + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +//----------------------STRBT---------------------------- + +static u32 FASTCALL OP_STRBT_P_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 oldmode; + u32 i; + u32 adr; + + if(cpu->CPSR.bits.mode==USR) + return 2; + + oldmode = armcpu_switchMode(cpu, SYS); + + + i = cpu->instruction; + adr = cpu->R[REG_POS(i,16)]; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr + IMM_OFF_12; + + armcpu_switchMode(cpu, oldmode); + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRBT_M_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 oldmode; + u32 i; + u32 adr; + + if(cpu->CPSR.bits.mode==USR) + return 2; + + oldmode = armcpu_switchMode(cpu, SYS); + + + i = cpu->instruction; + adr = cpu->R[REG_POS(i,16)]; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr - IMM_OFF_12; + + armcpu_switchMode(cpu, oldmode); + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRBT_P_REG_OFF_POSTIND(armcpu_t *cpu) +{ + u32 oldmode; + u32 i; + u32 adr; + + if(cpu->CPSR.bits.mode==USR) + return 2; + + oldmode = armcpu_switchMode(cpu, SYS); + + + i = cpu->instruction; + adr = cpu->R[REG_POS(i,16)]; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr + cpu->R[REG_POS(i,0)]; + + armcpu_switchMode(cpu, oldmode); + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRBT_M_REG_OFF_POSTIND(armcpu_t *cpu) +{ + u32 oldmode; + u32 i; + u32 adr; + + if(cpu->CPSR.bits.mode==USR) + return 2; + + oldmode = armcpu_switchMode(cpu, SYS); + + + i = cpu->instruction; + adr = cpu->R[REG_POS(i,16)]; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr - cpu->R[REG_POS(i,0)]; + + armcpu_switchMode(cpu, oldmode); + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRBT_P_LSL_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 oldmode; + u32 i; + u32 adr; + u32 shift_op; + + if(cpu->CPSR.bits.mode==USR) + return 2; + + oldmode = armcpu_switchMode(cpu, SYS); + + + i = cpu->instruction; + LSL_IMM; + adr = cpu->R[REG_POS(i,16)]; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr + shift_op; + + armcpu_switchMode(cpu, oldmode); + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRBT_M_LSL_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 oldmode; + u32 i; + u32 adr; + u32 shift_op; + + if(cpu->CPSR.bits.mode==USR) + return 2; + + oldmode = armcpu_switchMode(cpu, SYS); + + + i = cpu->instruction; + LSL_IMM; + adr = cpu->R[REG_POS(i,16)]; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr - shift_op; + + armcpu_switchMode(cpu, oldmode); + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRBT_P_LSR_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 oldmode; + u32 i; + u32 adr; + u32 shift_op; + + if(cpu->CPSR.bits.mode==USR) + return 2; + + oldmode = armcpu_switchMode(cpu, SYS); + + + i = cpu->instruction; + LSR_IMM; + adr = cpu->R[REG_POS(i,16)]; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr + shift_op; + + armcpu_switchMode(cpu, oldmode); + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRBT_M_LSR_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 oldmode; + u32 i; + u32 adr; + u32 shift_op; + + if(cpu->CPSR.bits.mode==USR) + return 2; + + oldmode = armcpu_switchMode(cpu, SYS); + + + i = cpu->instruction; + LSR_IMM; + adr = cpu->R[REG_POS(i,16)]; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr - shift_op; + + armcpu_switchMode(cpu, oldmode); + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRBT_P_ASR_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 oldmode; + u32 i; + u32 adr; + u32 shift_op; + + if(cpu->CPSR.bits.mode==USR) + return 2; + + oldmode = armcpu_switchMode(cpu, SYS); + + + i = cpu->instruction; + ASR_IMM; + adr = cpu->R[REG_POS(i,16)]; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr + shift_op; + + armcpu_switchMode(cpu, oldmode); + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRBT_M_ASR_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 oldmode; + u32 i; + u32 adr; + u32 shift_op; + + if(cpu->CPSR.bits.mode==USR) + return 2; + + oldmode = armcpu_switchMode(cpu, SYS); + + + i = cpu->instruction; + ASR_IMM; + adr = cpu->R[REG_POS(i,16)]; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr - shift_op; + + armcpu_switchMode(cpu, oldmode); + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRBT_P_ROR_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 oldmode; + u32 i; + u32 adr; + u32 shift_op; + + if(cpu->CPSR.bits.mode==USR) + return 2; + + oldmode = armcpu_switchMode(cpu, SYS); + + + i = cpu->instruction; + ROR_IMM; + adr = cpu->R[REG_POS(i,16)]; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr + shift_op; + + armcpu_switchMode(cpu, oldmode); + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRBT_M_ROR_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 oldmode; + u32 i; + u32 adr; + u32 shift_op; + + if(cpu->CPSR.bits.mode==USR) + return 2; + + oldmode = armcpu_switchMode(cpu, SYS); + + + i = cpu->instruction; + ROR_IMM; + adr = cpu->R[REG_POS(i,16)]; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr - shift_op; + + armcpu_switchMode(cpu, oldmode); + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +//---------------------LDM----------------------------- + +#define OP_L_IA(reg, adr) if(BIT##reg(i))\ + {\ + registres[reg] = READ32(cpu->mem_if->data, start);\ + c += waitState[(start>>24)&0xF];\ + adr += 4;\ + } + +#define OP_L_IB(reg, adr) if(BIT##reg(i))\ + {\ + adr += 4;\ + registres[reg] = READ32(cpu->mem_if->data, start);\ + c += waitState[(start>>24)&0xF];\ + } + +#define OP_L_DA(reg, adr) if(BIT##reg(i))\ + {\ + registres[reg] = READ32(cpu->mem_if->data, start);\ + c += waitState[(start>>24)&0xF];\ + adr -= 4;\ + } + +#define OP_L_DB(reg, adr) if(BIT##reg(i))\ + {\ + adr -= 4;\ + registres[reg] = READ32(cpu->mem_if->data, start);\ + c += waitState[(start>>24)&0xF];\ + } + +static u32 FASTCALL OP_LDMIA(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 c = 0; + u32 start = cpu->R[REG_POS(i,16)]; + + u32 * registres = cpu->R; + u32 * waitState = MMU.MMU_WAIT32[cpu->proc_ID]; + + OP_L_IA(0, start); + OP_L_IA(1, start); + OP_L_IA(2, start); + OP_L_IA(3, start); + OP_L_IA(4, start); + OP_L_IA(5, start); + OP_L_IA(6, start); + OP_L_IA(7, start); + OP_L_IA(8, start); + OP_L_IA(9, start); + OP_L_IA(10, start); + OP_L_IA(11, start); + OP_L_IA(12, start); + OP_L_IA(13, start); + OP_L_IA(14, start); + + if(BIT15(i)) + { + u32 tmp = READ32(cpu->mem_if->data, start); + registres[15] = tmp & (0XFFFFFFFC | (BIT0(tmp)<<1)); + cpu->CPSR.bits.T = BIT0(tmp); + //start += 4; + cpu->next_instruction = registres[15]; + c += waitState[(start>>24)&0xF]; + } + + return c + 2; +} + +static u32 FASTCALL OP_LDMIB(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 c = 0; + u32 start = cpu->R[REG_POS(i,16)]; + + u32 * registres = cpu->R; + u32 * waitState = MMU.MMU_WAIT32[cpu->proc_ID]; + + OP_L_IB(0, start); + OP_L_IB(1, start); + OP_L_IB(2, start); + OP_L_IB(3, start); + OP_L_IB(4, start); + OP_L_IB(5, start); + OP_L_IB(6, start); + OP_L_IB(7, start); + OP_L_IB(8, start); + OP_L_IB(9, start); + OP_L_IB(10, start); + OP_L_IB(11, start); + OP_L_IB(12, start); + OP_L_IB(13, start); + OP_L_IB(14, start); + + if(BIT15(i)) + { + u32 tmp; + start += 4; + c += waitState[(start>>24)&0xF]; + tmp = READ32(cpu->mem_if->data, start); + registres[15] = tmp & (0XFFFFFFFC | (BIT0(tmp)<<1)); + cpu->CPSR.bits.T = BIT0(tmp); + cpu->next_instruction = registres[15]; + c += 2 + (c==0); + } + + return c + 2; +} + +static u32 FASTCALL OP_LDMDA(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 c = 0; + u32 start = cpu->R[REG_POS(i,16)]; + + u32 * registres = cpu->R; + u32 * waitState = MMU.MMU_WAIT32[cpu->proc_ID]; + + if(BIT15(i)) + { + u32 tmp = READ32(cpu->mem_if->data, start); + registres[15] = tmp & (0XFFFFFFFC | (BIT0(tmp)<<1)); + cpu->CPSR.bits.T = BIT0(tmp); + c += waitState[(start>>24)&0xF]; + start -= 4; + cpu->next_instruction = registres[15]; + } + + OP_L_DA(14, start); + OP_L_DA(13, start); + OP_L_DA(12, start); + OP_L_DA(11, start); + OP_L_DA(10, start); + OP_L_DA(9, start); + OP_L_DA(8, start); + OP_L_DA(7, start); + OP_L_DA(6, start); + OP_L_DA(5, start); + OP_L_DA(4, start); + OP_L_DA(3, start); + OP_L_DA(2, start); + OP_L_DA(1, start); + OP_L_DA(0, start); + + return c + 2; +} + +static u32 FASTCALL OP_LDMDB(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 c = 0; + u32 start = cpu->R[REG_POS(i,16)]; + + u32 * registres = cpu->R; + u32 * waitState = MMU.MMU_WAIT32[cpu->proc_ID]; + + if(BIT15(i)) + { + u32 tmp; + start -= 4; + tmp = READ32(cpu->mem_if->data, start); + registres[15] = tmp & (0XFFFFFFFC | (BIT0(tmp)<<1)); + cpu->CPSR.bits.T = BIT0(tmp); + cpu->next_instruction = registres[15]; + c += waitState[(start>>24)&0xF]; + } + + OP_L_DB(14, start); + OP_L_DB(13, start); + OP_L_DB(12, start); + OP_L_DB(11, start); + OP_L_DB(10, start); + OP_L_DB(9, start); + OP_L_DB(8, start); + OP_L_DB(7, start); + OP_L_DB(6, start); + OP_L_DB(5, start); + OP_L_DB(4, start); + OP_L_DB(3, start); + OP_L_DB(2, start); + OP_L_DB(1, start); + OP_L_DB(0, start); + + return c + 2; +} + +static u32 FASTCALL OP_LDMIA_W(armcpu_t *cpu) +{ + u32 i = cpu->instruction, c = 0, count; + u32 start = cpu->R[REG_POS(i,16)]; + u32 bitList = (~((2 << REG_POS(i,16))-1)) & 0xFFFF; + + u32 * registres = cpu->R; + u32 * waitState = MMU.MMU_WAIT32[cpu->proc_ID]; + + OP_L_IA(0, start); + OP_L_IA(1, start); + OP_L_IA(2, start); + OP_L_IA(3, start); + OP_L_IA(4, start); + OP_L_IA(5, start); + OP_L_IA(6, start); + OP_L_IA(7, start); + OP_L_IA(8, start); + OP_L_IA(9, start); + OP_L_IA(10, start); + OP_L_IA(11, start); + OP_L_IA(12, start); + OP_L_IA(13, start); + OP_L_IA(14, start); + + if(BIT15(i)) + { + u32 tmp = READ32(cpu->mem_if->data, start); + registres[15] = tmp & (0XFFFFFFFC | (BIT0(tmp)<<1)); + cpu->CPSR.bits.T = BIT0(tmp); + c += waitState[(start>>24)&0xF]; + start += 4; + cpu->next_instruction = registres[15]; + } + + if(i & (1 << REG_POS(i,16))) { + if(i & bitList) + cpu->R[REG_POS(i,16)] = start; + } + else + cpu->R[REG_POS(i,16)] = start; + + return c + 2; +} + +static u32 FASTCALL OP_LDMIB_W(armcpu_t *cpu) +{ + u32 i = cpu->instruction, c = 0, count; + u32 start = cpu->R[REG_POS(i,16)]; + u32 bitList = (~((2 << REG_POS(i,16))-1)) & 0xFFFF; + + u32 * registres = cpu->R; + u32 * waitState = MMU.MMU_WAIT32[cpu->proc_ID]; + + OP_L_IB(0, start); + OP_L_IB(1, start); + OP_L_IB(2, start); + OP_L_IB(3, start); + OP_L_IB(4, start); + OP_L_IB(5, start); + OP_L_IB(6, start); + OP_L_IB(7, start); + OP_L_IB(8, start); + OP_L_IB(9, start); + OP_L_IB(10, start); + OP_L_IB(11, start); + OP_L_IB(12, start); + OP_L_IB(13, start); + OP_L_IB(14, start); + + if(BIT15(i)) + { + u32 tmp; + start += 4; + c += waitState[(start>>24)&0xF]; + tmp = READ32(cpu->mem_if->data, start); + registres[15] = tmp & (0XFFFFFFFC | (BIT0(tmp)<<1)); + cpu->CPSR.bits.T = BIT0(tmp); + cpu->next_instruction = registres[15]; + c += 2 + (c==0); + } + + if(i & (1 << REG_POS(i,16))) { + if(i & bitList) + cpu->R[REG_POS(i,16)] = start; + } + else + cpu->R[REG_POS(i,16)] = start; + + return c + 2; +} + +static u32 FASTCALL OP_LDMDA_W(armcpu_t *cpu) +{ + u32 i = cpu->instruction, c = 0, count; + u32 start = cpu->R[REG_POS(i,16)]; + u32 bitList = (~((2 << REG_POS(i,16))-1)) & 0xFFFF; + + u32 * registres = cpu->R; + u32 * waitState = MMU.MMU_WAIT32[cpu->proc_ID]; + + if(BIT15(i)) + { + u32 tmp = READ32(cpu->mem_if->data, start); + registres[15] = tmp & (0XFFFFFFFC | (BIT0(tmp)<<1)); + cpu->CPSR.bits.T = BIT0(tmp); + c += waitState[(start>>24)&0xF]; + start -= 4; + cpu->next_instruction = registres[15]; + } + + OP_L_DA(14, start); + OP_L_DA(13, start); + OP_L_DA(12, start); + OP_L_DA(11, start); + OP_L_DA(10, start); + OP_L_DA(9, start); + OP_L_DA(8, start); + OP_L_DA(7, start); + OP_L_DA(6, start); + OP_L_DA(5, start); + OP_L_DA(4, start); + OP_L_DA(3, start); + OP_L_DA(2, start); + OP_L_DA(1, start); + OP_L_DA(0, start); + + if(i & (1 << REG_POS(i,16))) { + if(i & bitList) + cpu->R[REG_POS(i,16)] = start; + } + else + cpu->R[REG_POS(i,16)] = start; + + return c + 2; +} + +static u32 FASTCALL OP_LDMDB_W(armcpu_t *cpu) +{ + u32 i = cpu->instruction, c = 0, count; + u32 start = cpu->R[REG_POS(i,16)]; + u32 bitList = (~((2 << REG_POS(i,16))-1)) & 0xFFFF; + u32 * registres = cpu->R; + u32 * waitState = MMU.MMU_WAIT32[cpu->proc_ID]; + + if(BIT15(i)) + { + u32 tmp; + start -= 4; + tmp = READ32(cpu->mem_if->data, start); + registres[15] = tmp & (0XFFFFFFFC | (BIT0(tmp)<<1)); + cpu->CPSR.bits.T = BIT0(tmp); + cpu->next_instruction = registres[15]; + c += waitState[(start>>24)&0xF]; + } + + OP_L_DB(14, start); + OP_L_DB(13, start); + OP_L_DB(12, start); + OP_L_DB(11, start); + OP_L_DB(10, start); + OP_L_DB(9, start); + OP_L_DB(8, start); + OP_L_DB(7, start); + OP_L_DB(6, start); + OP_L_DB(5, start); + OP_L_DB(4, start); + OP_L_DB(3, start); + OP_L_DB(2, start); + OP_L_DB(1, start); + OP_L_DB(0, start); + + if(i & (1 << REG_POS(i,16))) { + if(i & bitList) + cpu->R[REG_POS(i,16)] = start; + } + else + cpu->R[REG_POS(i,16)] = start; + + return c + 2; +} + +static u32 FASTCALL OP_LDMIA2(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 oldmode; + + u32 c = 0; + + u32 start = cpu->R[REG_POS(i,16)]; + u32 * registres; + u32 * waitState; + + if(BIT15(i)==0) + { + if(cpu->CPSR.bits.mode==USR) + return 1; + oldmode = armcpu_switchMode(cpu, SYS); + } + + registres = cpu->R; + waitState = MMU.MMU_WAIT32[cpu->proc_ID]; + + OP_L_IA(0, start); + OP_L_IA(1, start); + OP_L_IA(2, start); + OP_L_IA(3, start); + OP_L_IA(4, start); + OP_L_IA(5, start); + OP_L_IA(6, start); + OP_L_IA(7, start); + OP_L_IA(8, start); + OP_L_IA(9, start); + OP_L_IA(10, start); + OP_L_IA(11, start); + OP_L_IA(12, start); + OP_L_IA(13, start); + OP_L_IA(14, start); + + if(BIT15(i)) + { + u32 tmp = READ32(cpu->mem_if->data, start); + Status_Reg SPSR; + cpu->R[15] = tmp & (0XFFFFFFFC | (BIT0(tmp)<<1)); + SPSR = cpu->SPSR; + armcpu_switchMode(cpu, SPSR.bits.mode); + cpu->CPSR=SPSR; + //start += 4; + cpu->next_instruction = cpu->R[15]; + c += MMU.MMU_WAIT32[cpu->proc_ID][(start>>24)&0xF]; + } + else + { + armcpu_switchMode(cpu, oldmode); + } + return c + 2; +} + +static u32 FASTCALL OP_LDMIB2(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 oldmode; + u32 c = 0; + + u32 start = cpu->R[REG_POS(i,16)]; + u32 * registres; + u32 * waitState; + //execute = FALSE; + LOG("Untested opcode: OP_LDMIB2"); + + if(BIT15(i)==0) + { + if(cpu->CPSR.bits.mode==USR) + return 2; + oldmode = armcpu_switchMode(cpu, SYS); + } + + registres = cpu->R; + waitState = MMU.MMU_WAIT32[cpu->proc_ID]; + + OP_L_IB(0, start); + OP_L_IB(1, start); + OP_L_IB(2, start); + OP_L_IB(3, start); + OP_L_IB(4, start); + OP_L_IB(5, start); + OP_L_IB(6, start); + OP_L_IB(7, start); + OP_L_IB(8, start); + OP_L_IB(9, start); + OP_L_IB(10, start); + OP_L_IB(11, start); + OP_L_IB(12, start); + OP_L_IB(13, start); + OP_L_IB(14, start); + + if(BIT15(i)) + { + u32 tmp; + Status_Reg SPSR; + start += 4; + tmp = READ32(cpu->mem_if->data, start); + registres[15] = tmp & (0XFFFFFFFC | (BIT0(tmp)<<1)); + SPSR = cpu->SPSR; + armcpu_switchMode(cpu, SPSR.bits.mode); + cpu->CPSR=SPSR; + cpu->next_instruction = registres[15]; + c += waitState[(start>>24)&0xF]; + } + else + { + armcpu_switchMode(cpu, oldmode); + } + return c + 2; +} + +static u32 FASTCALL OP_LDMDA2(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + + u32 oldmode; + u32 c = 0; + u32 * registres; + u32 * waitState; + + u32 start = cpu->R[REG_POS(i,16)]; + //execute = FALSE; + LOG("Untested opcode: OP_LDMDA2"); + + if(BIT15(i)==0) + { + if(cpu->CPSR.bits.mode==USR) + return 2; + oldmode = armcpu_switchMode(cpu, SYS); + } + + registres = cpu->R; + waitState = MMU.MMU_WAIT32[cpu->proc_ID]; + + if(BIT15(i)) + { + u32 tmp = READ32(cpu->mem_if->data, start); + registres[15] = tmp & (0XFFFFFFFC | (BIT0(tmp)<<1)); + cpu->CPSR = cpu->SPSR; + c += waitState[(start>>24)&0xF]; + start -= 4; + cpu->next_instruction = registres[15]; + } + + OP_L_DA(14, start); + OP_L_DA(13, start); + OP_L_DA(12, start); + OP_L_DA(11, start); + OP_L_DA(10, start); + OP_L_DA(9, start); + OP_L_DA(8, start); + OP_L_DA(7, start); + OP_L_DA(6, start); + OP_L_DA(5, start); + OP_L_DA(4, start); + OP_L_DA(3, start); + OP_L_DA(2, start); + OP_L_DA(1, start); + OP_L_DA(0, start); + + if(BIT15(i)==0) + { + armcpu_switchMode(cpu, oldmode); + } + else + { + Status_Reg SPSR = cpu->SPSR; + armcpu_switchMode(cpu, SPSR.bits.mode); + cpu->CPSR=SPSR; + } + + return c + 2; +} + +static u32 FASTCALL OP_LDMDB2(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + + u32 oldmode; + u32 c = 0; + u32 * registres; + u32 * waitState; + + u32 start = cpu->R[REG_POS(i,16)]; + if(BIT15(i)==0) + { + if(cpu->CPSR.bits.mode==USR) + return 2; + oldmode = armcpu_switchMode(cpu, SYS); + } + + registres = cpu->R; + waitState = MMU.MMU_WAIT32[cpu->proc_ID]; + + if(BIT15(i)) + { + u32 tmp; + start -= 4; + tmp = READ32(cpu->mem_if->data, start); + registres[15] = tmp & (0XFFFFFFFC | (BIT0(tmp)<<1)); + cpu->CPSR = cpu->SPSR; + cpu->next_instruction = registres[15]; + c += waitState[(start>>24)&0xF]; + } + + OP_L_DB(14, start); + OP_L_DB(13, start); + OP_L_DB(12, start); + OP_L_DB(11, start); + OP_L_DB(10, start); + OP_L_DB(9, start); + OP_L_DB(8, start); + OP_L_DB(7, start); + OP_L_DB(6, start); + OP_L_DB(5, start); + OP_L_DB(4, start); + OP_L_DB(3, start); + OP_L_DB(2, start); + OP_L_DB(1, start); + OP_L_DB(0, start); + + if(BIT15(i)==0) + { + armcpu_switchMode(cpu, oldmode); + } + else + { + Status_Reg SPSR = cpu->SPSR; + armcpu_switchMode(cpu, SPSR.bits.mode); + cpu->CPSR=SPSR; + } + + return 2 + c; +} + +static u32 FASTCALL OP_LDMIA2_W(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 c = 0; + + u32 oldmode; + u32 start = cpu->R[REG_POS(i,16)]; + u32 * registres; + u32 * waitState; + u32 tmp; + Status_Reg SPSR; +// execute = FALSE; + if(BIT15(i)==0) + { + if(cpu->CPSR.bits.mode==USR) + return 2; + oldmode = armcpu_switchMode(cpu, SYS); + } + + registres = cpu->R; + waitState = MMU.MMU_WAIT32[cpu->proc_ID]; + + OP_L_IA(0, start); + OP_L_IA(1, start); + OP_L_IA(2, start); + OP_L_IA(3, start); + OP_L_IA(4, start); + OP_L_IA(5, start); + OP_L_IA(6, start); + OP_L_IA(7, start); + OP_L_IA(8, start); + OP_L_IA(9, start); + OP_L_IA(10, start); + OP_L_IA(11, start); + OP_L_IA(12, start); + OP_L_IA(13, start); + OP_L_IA(14, start); + + if(BIT15(i)==0) + { + registres[REG_POS(i,16)] = start; + armcpu_switchMode(cpu, oldmode); + return c + 2; + } + + registres[REG_POS(i,16)] = start + 4; + tmp = READ32(cpu->mem_if->data, start); + registres[15] = tmp & (0XFFFFFFFC | (BIT0(tmp)<<1)); + SPSR = cpu->SPSR; + armcpu_switchMode(cpu, SPSR.bits.mode); + cpu->CPSR=SPSR; + cpu->next_instruction = registres[15]; + c += waitState[(start>>24)&0xF]; + + return c + 2; +} + +static u32 FASTCALL OP_LDMIB2_W(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 c = 0; + + u32 oldmode; + u32 start = cpu->R[REG_POS(i,16)]; + u32 * registres; + u32 * waitState; + u32 tmp; + Status_Reg SPSR; + + if(BIT15(i)==0) + { + if(cpu->CPSR.bits.mode==USR) + return 2; + oldmode = armcpu_switchMode(cpu, SYS); + } + + registres = cpu->R; + waitState = MMU.MMU_WAIT32[cpu->proc_ID]; + + OP_L_IB(0, start); + OP_L_IB(1, start); + OP_L_IB(2, start); + OP_L_IB(3, start); + OP_L_IB(4, start); + OP_L_IB(5, start); + OP_L_IB(6, start); + OP_L_IB(7, start); + OP_L_IB(8, start); + OP_L_IB(9, start); + OP_L_IB(10, start); + OP_L_IB(11, start); + OP_L_IB(12, start); + OP_L_IB(13, start); + OP_L_IB(14, start); + + if(BIT15(i)==0) + { + armcpu_switchMode(cpu, oldmode); + registres[REG_POS(i,16)] = start; + + return c + 2; + } + + registres[REG_POS(i,16)] = start + 4; + tmp = READ32(cpu->mem_if->data, start + 4); + registres[15] = tmp & (0XFFFFFFFC | (BIT0(tmp)<<1)); + cpu->CPSR = cpu->SPSR; + cpu->next_instruction = registres[15]; + SPSR = cpu->SPSR; + armcpu_switchMode(cpu, SPSR.bits.mode); + cpu->CPSR=SPSR; + c += waitState[(start>>24)&0xF]; + + return c + 2; +} + +static u32 FASTCALL OP_LDMDA2_W(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 c = 0; + + u32 oldmode; + u32 start = cpu->R[REG_POS(i,16)]; + u32 * registres; + u32 * waitState; + Status_Reg SPSR; +// execute = FALSE; + if(BIT15(i)==0) + { + if(cpu->CPSR.bits.mode==USR) + return 2; + oldmode = armcpu_switchMode(cpu, SYS); + } + + registres = cpu->R; + waitState = MMU.MMU_WAIT32[cpu->proc_ID]; + + if(BIT15(i)) + { + u32 tmp = READ32(cpu->mem_if->data, start); + registres[15] = tmp & (0XFFFFFFFC | (BIT0(tmp)<<1)); + c += waitState[(start>>24)&0xF]; + start -= 4; + cpu->next_instruction = registres[15]; + } + + OP_L_DA(14, start); + OP_L_DA(13, start); + OP_L_DA(12, start); + OP_L_DA(11, start); + OP_L_DA(10, start); + OP_L_DA(9, start); + OP_L_DA(8, start); + OP_L_DA(7, start); + OP_L_DA(6, start); + OP_L_DA(5, start); + OP_L_DA(4, start); + OP_L_DA(3, start); + OP_L_DA(2, start); + OP_L_DA(1, start); + OP_L_DA(0, start); + + registres[REG_POS(i,16)] = start; + + if(BIT15(i)==0) + { + armcpu_switchMode(cpu, oldmode); + return c + 2; + } + + SPSR = cpu->SPSR; + armcpu_switchMode(cpu, SPSR.bits.mode); + cpu->CPSR=SPSR; + return c + 2; +} + +static u32 FASTCALL OP_LDMDB2_W(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 c = 0; + + u32 oldmode; + u32 start = cpu->R[REG_POS(i,16)]; + u32 * registres; + u32 * waitState; + Status_Reg SPSR; +// execute = FALSE; + if(BIT15(i)==0) + { + if(cpu->CPSR.bits.mode==USR) + return 2; + oldmode = armcpu_switchMode(cpu, SYS); + } + + registres = cpu->R; + waitState = MMU.MMU_WAIT32[cpu->proc_ID]; + + if(BIT15(i)) + { + u32 tmp; + start -= 4; + tmp = READ32(cpu->mem_if->data, start); + c += waitState[(start>>24)&0xF]; + registres[15] = tmp & (0XFFFFFFFC | (BIT0(tmp)<<1)); + cpu->CPSR = cpu->SPSR; + cpu->next_instruction = registres[15]; + } + + OP_L_DB(14, start); + OP_L_DB(13, start); + OP_L_DB(12, start); + OP_L_DB(11, start); + OP_L_DB(10, start); + OP_L_DB(9, start); + OP_L_DB(8, start); + OP_L_DB(7, start); + OP_L_DB(6, start); + OP_L_DB(5, start); + OP_L_DB(4, start); + OP_L_DB(3, start); + OP_L_DB(2, start); + OP_L_DB(1, start); + OP_L_DB(0, start); + + registres[REG_POS(i,16)] = start; + + if(BIT15(i)==0) + { + armcpu_switchMode(cpu, oldmode); + return c + 2; + } + + SPSR = cpu->SPSR; + armcpu_switchMode(cpu, SPSR.bits.mode); + cpu->CPSR=SPSR; + return c + 2; +} + +//------------------------------STM---------------------------------- + +static u32 FASTCALL OP_STMIA(armcpu_t *cpu) +{ + u32 i = cpu->instruction, c = 0, b; + u32 start = cpu->R[REG_POS(i,16)]; + + for(b=0; b<16; ++b) + { + if(BIT_N(i, b)) + { + WRITE32(cpu->mem_if->data, start, cpu->R[b]); + c += MMU.MMU_WAIT32[cpu->proc_ID][(start>>24)&0xF]; + start += 4; + } + } + return c + 1; +} + +static u32 FASTCALL OP_STMIB(armcpu_t *cpu) +{ + u32 i = cpu->instruction, c = 0, b; + u32 start = cpu->R[REG_POS(i,16)]; + + for(b=0; b<16; ++b) + { + if(BIT_N(i, b)) + { + start += 4; + WRITE32(cpu->mem_if->data, start, cpu->R[b]); + c += MMU.MMU_WAIT32[cpu->proc_ID][(start>>24)&0xF]; + } + } + return c + 1; +} + +static u32 FASTCALL OP_STMDA(armcpu_t *cpu) +{ + u32 i = cpu->instruction, c = 0, b; + u32 start = cpu->R[REG_POS(i,16)]; + + for(b=0; b<16; ++b) + { + if(BIT_N(i, 15-b)) + { + WRITE32(cpu->mem_if->data, start, cpu->R[15-b]); + c += MMU.MMU_WAIT32[cpu->proc_ID][(start>>24)&0xF]; + start -= 4; + } + } + return c + 1; +} + +static u32 FASTCALL OP_STMDB(armcpu_t *cpu) +{ + u32 i = cpu->instruction, c = 0, b; + u32 start = cpu->R[REG_POS(i,16)]; + + for(b=0; b<16; ++b) + { + if(BIT_N(i, 15-b)) + { + start -= 4; + WRITE32(cpu->mem_if->data, start, cpu->R[15-b]); + c += MMU.MMU_WAIT32[cpu->proc_ID][(start>>24)&0xF]; + } + } + return c + 1; +} + +static u32 FASTCALL OP_STMIA_W(armcpu_t *cpu) +{ + u32 i = cpu->instruction, c = 0, b; + u32 start = cpu->R[REG_POS(i,16)]; + + for(b=0; b<16; ++b) + { + if(BIT_N(i, b)) + { + WRITE32(cpu->mem_if->data, start, cpu->R[b]); + c += MMU.MMU_WAIT32[cpu->proc_ID][(start>>24)&0xF]; + start += 4; + } + } + + cpu->R[REG_POS(i,16)] = start; + return c + 1; +} + +static u32 FASTCALL OP_STMIB_W(armcpu_t *cpu) +{ + u32 i = cpu->instruction, c = 0, b; + u32 start = cpu->R[REG_POS(i,16)]; + + for(b=0; b<16; ++b) + { + if(BIT_N(i, b)) + { + start += 4; + WRITE32(cpu->mem_if->data, start, cpu->R[b]); + c += MMU.MMU_WAIT32[cpu->proc_ID][(start>>24)&0xF]; + } + } + cpu->R[REG_POS(i,16)] = start; + return c + 1; +} + +static u32 FASTCALL OP_STMDA_W(armcpu_t *cpu) +{ + u32 i = cpu->instruction, c = 0, b; + u32 start = cpu->R[REG_POS(i,16)]; + + for(b=0; b<16; ++b) + { + if(BIT_N(i, 15-b)) + { + WRITE32(cpu->mem_if->data, start, cpu->R[15-b]); + c += MMU.MMU_WAIT32[cpu->proc_ID][(start>>24)&0xF]; + start -= 4; + } + } + + cpu->R[REG_POS(i,16)] = start; + return c + 1; +} + +static u32 FASTCALL OP_STMDB_W(armcpu_t *cpu) +{ + u32 i = cpu->instruction, c = 0, b; + u32 start = cpu->R[REG_POS(i,16)]; + + for(b=0; b<16; ++b) + { + if(BIT_N(i, 15-b)) + { + start -= 4; + WRITE32(cpu->mem_if->data, start, cpu->R[15-b]); + c += MMU.MMU_WAIT32[cpu->proc_ID][(start>>24)&0xF]; + } + } + + cpu->R[REG_POS(i,16)] = start; + return c + 1; +} + +static u32 FASTCALL OP_STMIA2(armcpu_t *cpu) +{ + u32 i, c, b; + u32 start; + u32 oldmode; + + if(cpu->CPSR.bits.mode==USR) + return 2; + + i = cpu->instruction; + c = 0; + start = cpu->R[REG_POS(i,16)]; + oldmode = armcpu_switchMode(cpu, SYS); + + //execute = FALSE; + LOG("Untested opcode: OP_STMIA2"); + + for(b=0; b<16; ++b) + { + if(BIT_N(i, b)) + { + WRITE32(cpu->mem_if->data, start, cpu->R[b]); + c += MMU.MMU_WAIT32[cpu->proc_ID][(start>>24)&0xF]; + start += 4; + } + } + + armcpu_switchMode(cpu, oldmode); + return c + 1; +} + +static u32 FASTCALL OP_STMIB2(armcpu_t *cpu) +{ + u32 i, c, b; + u32 start; + u32 oldmode; + + if(cpu->CPSR.bits.mode==USR) + return 2; + + i = cpu->instruction; + c = 0; + start = cpu->R[REG_POS(i,16)]; + oldmode = armcpu_switchMode(cpu, SYS); + + //execute = FALSE; + LOG("Untested opcode: OP_STMIB2"); + + for(b=0; b<16; ++b) + { + if(BIT_N(i, b)) + { + start += 4; + WRITE32(cpu->mem_if->data, start, cpu->R[b]); + c += MMU.MMU_WAIT32[cpu->proc_ID][(start>>24)&0xF]; + } + } + + armcpu_switchMode(cpu, oldmode); + return c + 1; +} + +static u32 FASTCALL OP_STMDA2(armcpu_t *cpu) +{ + u32 i, c, b; + u32 start; + u32 oldmode; + + if(cpu->CPSR.bits.mode==USR) + return 2; + + i = cpu->instruction; + c = 0; + start = cpu->R[REG_POS(i,16)]; + oldmode = armcpu_switchMode(cpu, SYS); + + //execute = FALSE; + LOG("Untested opcode: OP_STMDA2"); + + for(b=0; b<16; ++b) + { + if(BIT_N(i, 15-b)) + { + WRITE32(cpu->mem_if->data, start, cpu->R[15-b]); + c += MMU.MMU_WAIT32[cpu->proc_ID][(start>>24)&0xF]; + start -= 4; + } + } + + armcpu_switchMode(cpu, oldmode); + return c + 1; +} + +static u32 FASTCALL OP_STMDB2(armcpu_t *cpu) +{ + u32 i, c, b; + u32 start; + u32 oldmode; + + if(cpu->CPSR.bits.mode==USR) + return 2; + i = cpu->instruction; + c=0; + start = cpu->R[REG_POS(i,16)]; + oldmode = armcpu_switchMode(cpu, SYS); + + for(b=0; b<16; ++b) + { + if(BIT_N(i, 15-b)) + { + start -= 4; + WRITE32(cpu->mem_if->data, start, cpu->R[15-b]); + c += MMU.MMU_WAIT32[cpu->proc_ID][(start>>24)&0xF]; + } + } + + armcpu_switchMode(cpu, oldmode); + return c + 1; +} + +static u32 FASTCALL OP_STMIA2_W(armcpu_t *cpu) +{ + u32 i, c, b; + u32 start; + u32 oldmode; + + if(cpu->CPSR.bits.mode==USR) + return 2; + + i = cpu->instruction; + c=0; + start = cpu->R[REG_POS(i,16)]; + oldmode = armcpu_switchMode(cpu, SYS); + + //execute = FALSE; + LOG("Untested opcode: OP_STMIA2_W"); + + for(b=0; b<16; ++b) + { + if(BIT_N(i, b)) + { + WRITE32(cpu->mem_if->data, start, cpu->R[b]); + c += MMU.MMU_WAIT32[cpu->proc_ID][(start>>24)&0xF]; + start += 4; + } + } + + cpu->R[REG_POS(i,16)] = start; + + armcpu_switchMode(cpu, oldmode); + return c + 1; +} + +static u32 FASTCALL OP_STMIB2_W(armcpu_t *cpu) +{ + u32 i, c, b; + u32 start; + u32 oldmode; + + if(cpu->CPSR.bits.mode==USR) + return 2; + i = cpu->instruction; + c=0; + start = cpu->R[REG_POS(i,16)]; + oldmode = armcpu_switchMode(cpu, SYS); + + for(b=0; b<16; ++b) + { + if(BIT_N(i, b)) + { + start += 4; + WRITE32(cpu->mem_if->data, start, cpu->R[b]); + c += MMU.MMU_WAIT32[cpu->proc_ID][(start>>24)&0xF]; + } + } + armcpu_switchMode(cpu, oldmode); + cpu->R[REG_POS(i,16)] = start; + + return c + 1; +} + +static u32 FASTCALL OP_STMDA2_W(armcpu_t *cpu) +{ + u32 i, c, b; + u32 start; + u32 oldmode; + + if(cpu->CPSR.bits.mode==USR) + return 2; + + i = cpu->instruction; + c = 0; + start = cpu->R[REG_POS(i,16)]; + oldmode = armcpu_switchMode(cpu, SYS); + //execute = FALSE; + LOG("Untested opcode: OP_STMDA2_W"); + + for(b=0; b<16; ++b) + { + if(BIT_N(i, 15-b)) + { + WRITE32(cpu->mem_if->data, start, cpu->R[15-b]); + c += MMU.MMU_WAIT32[cpu->proc_ID][(start>>24)&0xF]; + start -= 4; + } + } + + cpu->R[REG_POS(i,16)] = start; + + armcpu_switchMode(cpu, oldmode); + return c + 1; +} + +static u32 FASTCALL OP_STMDB2_W(armcpu_t *cpu) +{ + u32 i, c, b; + u32 start; + u32 oldmode; + + if(cpu->CPSR.bits.mode==USR) + return 2; + + i = cpu->instruction; + c = 0; + + start = cpu->R[REG_POS(i,16)]; + oldmode = armcpu_switchMode(cpu, SYS); + + //execute = FALSE; + LOG("Untested opcode: OP_STMDB2_W"); + + for(b=0; b<16; ++b) + { + if(BIT_N(i, 15-b)) + { + start -= 4; + WRITE32(cpu->mem_if->data, start, cpu->R[15-b]); + c += MMU.MMU_WAIT32[cpu->proc_ID][(start>>24)&0xF]; + } + } + + cpu->R[REG_POS(i,16)] = start; + + armcpu_switchMode(cpu, oldmode); + return c + 1; +} + +/* + * + * The Enhanced DSP Extension LDRD and STRD instructions. + * + */ +static u32 FASTCALL +OP_LDRD_STRD_POST_INDEX( armcpu_t *cpu) { + u32 i = cpu->instruction; + u32 Rd_num = REG_POS( i, 12); + u32 addr = cpu->R[REG_POS(i,16)]; + u32 index; + + /* I bit - immediate or register */ + if ( BIT22(i)) + index = IMM_OFF; + else + index = cpu->R[REG_POS(i,0)]; + + /* U bit - add or subtract */ + if ( BIT23(i)) + cpu->R[REG_POS(i,16)] += index; + else + cpu->R[REG_POS(i,16)] -= index; + + if ( !(Rd_num & 0x1)) { + /* Store/Load */ + if ( BIT5(i)) { + WRITE32(cpu->mem_if->data, addr, cpu->R[Rd_num]); + WRITE32(cpu->mem_if->data, addr + 4, cpu->R[Rd_num + 1]); + } + else { + cpu->R[Rd_num] = READ32(cpu->mem_if->data, addr); + cpu->R[Rd_num + 1] = READ32(cpu->mem_if->data, addr + 4); + } + } + + return 3 + (MMU.MMU_WAIT32[cpu->proc_ID][(addr>>24)&0xF] * 2); +} + +static u32 FASTCALL +OP_LDRD_STRD_OFFSET_PRE_INDEX( armcpu_t *cpu) { + u32 i = cpu->instruction; + u32 Rd_num = REG_POS( i, 12); + u32 addr = cpu->R[REG_POS(i,16)]; + u32 index; + + /* I bit - immediate or register */ + if ( BIT22(i)) + index = IMM_OFF; + else + index = cpu->R[REG_POS(i,0)]; + + /* U bit - add or subtract */ + if ( BIT23(i)) { + addr += index; + + /* W bit - writeback */ + if ( BIT21(i)) + cpu->R[REG_POS(i,16)] = addr; + } + else { + addr -= index; + + /* W bit - writeback */ + if ( BIT21(i)) + cpu->R[REG_POS(i,16)] = addr; + } + + if ( !(Rd_num & 0x1)) { + /* Store/Load */ + if ( BIT5(i)) { + WRITE32(cpu->mem_if->data, addr, cpu->R[Rd_num]); + WRITE32(cpu->mem_if->data, addr + 4, cpu->R[Rd_num + 1]); + } + else { + cpu->R[Rd_num] = READ32(cpu->mem_if->data, addr); + cpu->R[Rd_num + 1] = READ32(cpu->mem_if->data, addr + 4); + } + } + + return 3 + (MMU.MMU_WAIT32[cpu->proc_ID][(addr>>24)&0xF] * 2); +} + + + +//---------------------STC---------------------------------- + +static u32 FASTCALL OP_STC_P_IMM_OFF(armcpu_t *cpu) +{ + { + /* the NDS has no coproc that responses to a STC, no feedback is given to the arm */ + return 2; + } +} + +static u32 FASTCALL OP_STC_M_IMM_OFF(armcpu_t *cpu) +{ + { + /* the NDS has no coproc that responses to a STC, no feedback is given to the arm */ + return 2; + } +} + +static u32 FASTCALL OP_STC_P_PREIND(armcpu_t *cpu) +{ + { + /* the NDS has no coproc that responses to a STC, no feedback is given to the arm */ + return 2; + } +} + +static u32 FASTCALL OP_STC_M_PREIND(armcpu_t *cpu) +{ + { + /* the NDS has no coproc that responses to a STC, no feedback is given to the arm */ + return 2; + } +} + +static u32 FASTCALL OP_STC_P_POSTIND(armcpu_t *cpu) +{ + { + /* the NDS has no coproc that responses to a STC, no feedback is given to the arm */ + return 2; + } +} + +static u32 FASTCALL OP_STC_M_POSTIND(armcpu_t *cpu) +{ + { + /* the NDS has no coproc that responses to a STC, no feedback is given to the arm */ + return 2; + } +} + +static u32 FASTCALL OP_STC_OPTION(armcpu_t *cpu) +{ + { + /* the NDS has no coproc that responses to a STC, no feedback is given to the arm */ + return 2; + } +} + +//---------------------LDC---------------------------------- + +static u32 FASTCALL OP_LDC_P_IMM_OFF(armcpu_t *cpu) +{ + { + /* the NDS has no coproc that responses to a LDC, no feedback is given to the arm */ + return 2; + } +} + +static u32 FASTCALL OP_LDC_M_IMM_OFF(armcpu_t *cpu) +{ + { + /* the NDS has no coproc that responses to a LDC, no feedback is given to the arm */ + return 2; + } +} + +static u32 FASTCALL OP_LDC_P_PREIND(armcpu_t *cpu) +{ + { + /* the NDS has no coproc that responses to a LDC, no feedback is given to the arm */ + return 2; + } +} + +static u32 FASTCALL OP_LDC_M_PREIND(armcpu_t *cpu) +{ + { + /* the NDS has no coproc that responses to a LDC, no feedback is given to the arm */ + return 2; + } +} + +static u32 FASTCALL OP_LDC_P_POSTIND(armcpu_t *cpu) +{ + { + /* the NDS has no coproc that responses to a LDC, no feedback is given to the arm */ + return 2; + } +} + +static u32 FASTCALL OP_LDC_M_POSTIND(armcpu_t *cpu) +{ + { + /* the NDS has no coproc that responses to a LDC, no feedback is given to the arm */ + return 2; + } +} + +static u32 FASTCALL OP_LDC_OPTION(armcpu_t *cpu) +{ + { + /* the NDS has no coproc that responses to a LDC, no feedback is given to the arm */ + return 2; + } +} + +//----------------MCR----------------------- + +static u32 FASTCALL OP_MCR(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 cpnum = REG_POS(i, 8); + + if(!cpu->coproc[cpnum]) + { + execute = FALSE; + return 2; + } + + armcp15_moveARM2CP((armcp15_t*)cpu->coproc[cpnum], cpu->R[REG_POS(i, 12)], REG_POS(i, 16), REG_POS(i, 0), (i>>21)&7, (i>>5)&7); + //cpu->coproc[cpnum]->moveARM2CP(cpu->R[REG_POS(i, 12)], REG_POS(i, 16), REG_POS(i, 0), (i>>21)&7, (i>>5)&7); + return 2; +} + +//----------------MRC----------------------- + +static u32 FASTCALL OP_MRC(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 cpnum = REG_POS(i, 8); + + if(!cpu->coproc[cpnum]) + { + execute = FALSE; + return 2; + } + + armcp15_moveCP2ARM((armcp15_t*)cpu->coproc[cpnum], &cpu->R[REG_POS(i, 12)], REG_POS(i, 16), REG_POS(i, 0), (i>>21)&7, (i>>5)&7); + //cpu->coproc[cpnum]->moveCP2ARM(&cpu->R[REG_POS(i, 12)], REG_POS(i, 16), REG_POS(i, 0), (i>>21)&7, (i>>5)&7); + return 4; +} + +//--------------SWI------------------------------- +static u32 FASTCALL OP_SWI(armcpu_t *cpu) +{ + if (((cpu->intVector != 0) ^ (cpu->proc_ID == ARMCPU_ARM9))) + { + /* TODO (#1#): translocated SWI vectors */ + /* we use an irq thats not in the irq tab, as + it was replaced duie to a changed intVector */ + Status_Reg tmp = cpu->CPSR; + armcpu_switchMode(cpu, SVC); /* enter svc mode */ + cpu->R[14] = cpu->R[15] - 4; /* jump to swi Vector */ + cpu->SPSR = tmp; /* save old CPSR as new SPSR */ + cpu->CPSR.bits.T = 0; /* handle as ARM32 code */ + cpu->CPSR.bits.I = cpu->SPSR.bits.I; /* keep int disable flag */ + cpu->R[15] = cpu->intVector + 0x08; + cpu->next_instruction = cpu->R[15]; + return 4; + } + else + { + u32 swinum = (cpu->instruction>>16)&0x1F; + return cpu->swi_tab[swinum](cpu) + 3; + } +} + +//----------------BKPT------------------------- +static u32 FASTCALL OP_BKPT(armcpu_t *cpu) +{ + execute = FALSE; + return 4; +} + +//----------------CDP----------------------- + +static u32 FASTCALL OP_CDP(armcpu_t *cpu) +{ + execute = FALSE; + return 4; +} + +#define TYPE_RETOUR u32 +#define PARAMETRES armcpu_t *cpu +#define CALLTYPE FASTCALL +#define NOM_TAB arm_instructions_set + +#include "instruction_tabdef.inc" diff -r fe2ba1a712cd -r 70b0973e7b70 src/xsf/desmume/arm_instructions.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/xsf/desmume/arm_instructions.h Thu Oct 16 14:45:41 2008 -0500 @@ -0,0 +1,31 @@ +/* Copyright (C) 2006 yopyop + yopyop156@ifrance.com + yopyop156.ifrance.com + + This file is part of DeSmuME + + DeSmuME is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DeSmuME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DeSmuME; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef ARMINSTRUCTION_H +#define ARMINSTRUCTION_H + +#include "types.h" +#include "armcpu.h" + +extern u32 (FASTCALL* arm_instructions_set[4096])(armcpu_t * cpu); + +#endif + diff -r fe2ba1a712cd -r 70b0973e7b70 src/xsf/desmume/armcpu.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/xsf/desmume/armcpu.c Thu Oct 16 14:45:41 2008 -0500 @@ -0,0 +1,579 @@ +/* Copyright (C) 2006 yopyop + yopyop156@ifrance.com + yopyop156.ifrance.com + + This file is part of DeSmuME + + DeSmuME is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DeSmuME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DeSmuME; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "arm_instructions.h" +#include "thumb_instructions.h" +#include "cp15.h" +#include "bios.h" +#include +#include + +const unsigned char arm_cond_table[16*16] = { + /* N=0, Z=0, C=0, V=0 */ + 0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF, + 0x00,0xFF,0xFF,0x00,0xFF,0x00,0xFF,0x20, + /* N=0, Z=0, C=0, V=1 */ + 0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0x00, + 0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0x20, + /* N=0, Z=0, C=1, V=0 */ + 0x00,0xFF,0xFF,0x00,0x00,0xFF,0x00,0xFF, + 0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x20, + /* N=0, Z=0, C=1, V=1 */ + 0x00,0xFF,0xFF,0x00,0x00,0xFF,0xFF,0x00, + 0xFF,0x00,0x00,0xFF,0x00,0xFF,0xFF,0x20, + /* N=0, Z=1, C=0, V=0 */ + 0xFF,0x00,0x00,0xFF,0x00,0xFF,0x00,0xFF, + 0x00,0xFF,0xFF,0x00,0x00,0xFF,0xFF,0x20, + /* N=0, Z=1, C=0, V=1 */ + 0xFF,0x00,0x00,0xFF,0x00,0xFF,0xFF,0x00, + 0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0x20, + /* N=0, Z=1, C=1, V=0 */ + 0xFF,0x00,0xFF,0x00,0x00,0xFF,0x00,0xFF, + 0x00,0xFF,0xFF,0x00,0x00,0xFF,0xFF,0x20, + /* N=0, Z=1, C=1, V=1 */ + 0xFF,0x00,0xFF,0x00,0x00,0xFF,0xFF,0x00, + 0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0x20, + /* N=1, Z=0, C=0, V=0 */ + 0x00,0xFF,0x00,0xFF,0xFF,0x00,0x00,0xFF, + 0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0x20, + /* N=1, Z=0, C=0, V=1 */ + 0x00,0xFF,0x00,0xFF,0xFF,0x00,0xFF,0x00, + 0x00,0xFF,0xFF,0x00,0xFF,0x00,0xFF,0x20, + /* N=1, Z=0, C=1, V=0 */ + 0x00,0xFF,0xFF,0x00,0xFF,0x00,0x00,0xFF, + 0xFF,0x00,0x00,0xFF,0x00,0xFF,0xFF,0x20, + /* N=1, Z=0, C=1, V=1 */ + 0x00,0xFF,0xFF,0x00,0xFF,0x00,0xFF,0x00, + 0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x20, + /* N=1, Z=1, C=0, V=0 */ + 0xFF,0x00,0x00,0xFF,0xFF,0x00,0x00,0xFF, + 0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0x20, + /* N=1, Z=1, C=0, V=1 */ + 0xFF,0x00,0x00,0xFF,0xFF,0x00,0xFF,0x00, + 0x00,0xFF,0xFF,0x00,0x00,0xFF,0xFF,0x20, + /* N=1, Z=1, C=1, V=0 */ + 0xFF,0x00,0xFF,0x00,0xFF,0x00,0x00,0xFF, + 0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0x20, + /* N=1, Z=1, C=1, V=1 */ + 0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00, + 0x00,0xFF,0xFF,0x00,0x00,0xFF,0xFF,0x20, +}; + +armcpu_t NDS_ARM7; +armcpu_t NDS_ARM9; + +#define SWAP(a, b, c) do \ + { \ + c=a; \ + a=b; \ + b=c; \ + } \ + while(0) + +#ifdef GDB_STUB + +#define STALLED_CYCLE_COUNT 10 + +static void +stall_cpu( void *instance) { + armcpu_t *armcpu = (armcpu_t *)instance; + + armcpu->stalled = 1; +} + +static void +unstall_cpu( void *instance) { + armcpu_t *armcpu = (armcpu_t *)instance; + + armcpu->stalled = 0; +} + +static void +install_post_exec_fn( void *instance, + void (*ex_fn)( void *, u32 adr, int thumb), + void *fn_data) { + armcpu_t *armcpu = (armcpu_t *)instance; + + armcpu->post_ex_fn = ex_fn; + armcpu->post_ex_fn_data = fn_data; +} + +static void +remove_post_exec_fn( void *instance) { + armcpu_t *armcpu = (armcpu_t *)instance; + + armcpu->post_ex_fn = NULL; +} +#endif + +static u32 +read_cpu_reg( void *instance, u32 reg_num) { + armcpu_t *armcpu = (armcpu_t *)instance; + u32 reg_value = 0; + + if ( reg_num <= 14) { + reg_value = armcpu->R[reg_num]; + } + else if ( reg_num == 15) { + reg_value = armcpu->next_instruction; + } + else if ( reg_num == 16) { + /* CPSR */ + reg_value = armcpu->CPSR.val; + } + + return reg_value; +} + +static void +set_cpu_reg( void *instance, u32 reg_num, u32 value) { + armcpu_t *armcpu = (armcpu_t *)instance; + + if ( reg_num <= 14) { + armcpu->R[reg_num] = value; + } + else if ( reg_num == 15) { + armcpu->next_instruction = value; + } + else if ( reg_num == 16) { + /* FIXME: setting the CPSR */ + } +} + +#ifdef GDB_STUB +int armcpu_new( armcpu_t *armcpu, u32 id, + struct armcpu_memory_iface *mem_if, + struct armcpu_ctrl_iface **ctrl_iface_ret) +#else +int armcpu_new( armcpu_t *armcpu, u32 id) +#endif +{ + armcpu->proc_ID = id; + + if(id==0) + armcpu->swi_tab = ARM9_swi_tab; + else + armcpu->swi_tab = ARM7_swi_tab; + +#ifdef GDB_STUB + armcpu->mem_if = mem_if; + + /* populate the control interface */ + armcpu->ctrl_iface.stall = stall_cpu; + armcpu->ctrl_iface.unstall = unstall_cpu; + armcpu->ctrl_iface.read_reg = read_cpu_reg; + armcpu->ctrl_iface.set_reg = set_cpu_reg; + armcpu->ctrl_iface.install_post_ex_fn = install_post_exec_fn; + armcpu->ctrl_iface.remove_post_ex_fn = remove_post_exec_fn; + armcpu->ctrl_iface.data = armcpu; + + *ctrl_iface_ret = &armcpu->ctrl_iface; + + armcpu->stalled = 0; + armcpu->post_ex_fn = NULL; +#endif + + armcpu_init(armcpu, 0); + + return 0; +} + +void armcpu_init(armcpu_t *armcpu, u32 adr) +{ + u32 i; + + armcpu->LDTBit = (armcpu->proc_ID==0); //Si ARM9 utiliser le syte v5 pour le load + armcpu->intVector = 0xFFFF0000 * (armcpu->proc_ID==0); + armcpu->waitIRQ = FALSE; + armcpu->wirq = FALSE; + +#ifdef GDB_STUB + armcpu->irq_flag = 0; +#endif + + if(armcpu->coproc[15]) free(armcpu->coproc[15]); + + for(i = 0; i < 15; ++i) + { + armcpu->R[i] = 0; + armcpu->coproc[i] = NULL; + } + + armcpu->CPSR.val = armcpu->SPSR.val = SYS; + + armcpu->R13_usr = armcpu->R14_usr = 0; + armcpu->R13_svc = armcpu->R14_svc = 0; + armcpu->R13_abt = armcpu->R14_abt = 0; + armcpu->R13_und = armcpu->R14_und = 0; + armcpu->R13_irq = armcpu->R14_irq = 0; + armcpu->R8_fiq = armcpu->R9_fiq = armcpu->R10_fiq = armcpu->R11_fiq = armcpu->R12_fiq = armcpu->R13_fiq = armcpu->R14_fiq = 0; + + armcpu->SPSR_svc.val = armcpu->SPSR_abt.val = armcpu->SPSR_und.val = armcpu->SPSR_irq.val = armcpu->SPSR_fiq.val = 0; + +#ifdef GDB_STUB + armcpu->instruct_adr = adr; + armcpu->R[15] = adr + 8; +#else + armcpu->R[15] = adr; +#endif + + armcpu->next_instruction = adr; + + armcpu->coproc[15] = (armcp_t*)armcp15_new(armcpu); + +#ifndef GDB_STUB + armcpu_prefetch(armcpu); +#endif +} + +u32 armcpu_switchMode(armcpu_t *armcpu, u8 mode) +{ + u32 oldmode = armcpu->CPSR.bits.mode; + + switch(oldmode) + { + case USR : + case SYS : + armcpu->R13_usr = armcpu->R[13]; + armcpu->R14_usr = armcpu->R[14]; + break; + + case FIQ : + { + u32 tmp; + SWAP(armcpu->R[8], armcpu->R8_fiq, tmp); + SWAP(armcpu->R[9], armcpu->R9_fiq, tmp); + SWAP(armcpu->R[10], armcpu->R10_fiq, tmp); + SWAP(armcpu->R[11], armcpu->R11_fiq, tmp); + SWAP(armcpu->R[12], armcpu->R12_fiq, tmp); + armcpu->R13_fiq = armcpu->R[13]; + armcpu->R14_fiq = armcpu->R[14]; + armcpu->SPSR_fiq = armcpu->SPSR; + break; + } + case IRQ : + armcpu->R13_irq = armcpu->R[13]; + armcpu->R14_irq = armcpu->R[14]; + armcpu->SPSR_irq = armcpu->SPSR; + break; + + case SVC : + armcpu->R13_svc = armcpu->R[13]; + armcpu->R14_svc = armcpu->R[14]; + armcpu->SPSR_svc = armcpu->SPSR; + break; + + case ABT : + armcpu->R13_abt = armcpu->R[13]; + armcpu->R14_abt = armcpu->R[14]; + armcpu->SPSR_abt = armcpu->SPSR; + break; + + case UND : + armcpu->R13_und = armcpu->R[13]; + armcpu->R14_und = armcpu->R[14]; + armcpu->SPSR_und = armcpu->SPSR; + break; + default : + break; + } + + switch(mode) + { + case USR : + case SYS : + armcpu->R[13] = armcpu->R13_usr; + armcpu->R[14] = armcpu->R14_usr; + //SPSR = CPSR; + break; + + case FIQ : + { + u32 tmp; + SWAP(armcpu->R[8], armcpu->R8_fiq, tmp); + SWAP(armcpu->R[9], armcpu->R9_fiq, tmp); + SWAP(armcpu->R[10], armcpu->R10_fiq, tmp); + SWAP(armcpu->R[11], armcpu->R11_fiq, tmp); + SWAP(armcpu->R[12], armcpu->R12_fiq, tmp); + armcpu->R[13] = armcpu->R13_fiq; + armcpu->R[14] = armcpu->R14_fiq; + armcpu->SPSR = armcpu->SPSR_fiq; + break; + } + + case IRQ : + armcpu->R[13] = armcpu->R13_irq; + armcpu->R[14] = armcpu->R14_irq; + armcpu->SPSR = armcpu->SPSR_irq; + break; + + case SVC : + armcpu->R[13] = armcpu->R13_svc; + armcpu->R[14] = armcpu->R14_svc; + armcpu->SPSR = armcpu->SPSR_svc; + break; + + case ABT : + armcpu->R[13] = armcpu->R13_abt; + armcpu->R[14] = armcpu->R14_abt; + armcpu->SPSR = armcpu->SPSR_abt; + break; + + case UND : + armcpu->R[13] = armcpu->R13_und; + armcpu->R[14] = armcpu->R14_und; + armcpu->SPSR = armcpu->SPSR_und; + break; + + default : + break; + } + + armcpu->CPSR.bits.mode = mode & 0x1F; + return oldmode; +} + +static u32 +armcpu_prefetch(armcpu_t *armcpu) +{ + u32 temp_instruction; + + if(armcpu->CPSR.bits.T == 0) + { +#ifdef GDB_STUB + temp_instruction = + armcpu->mem_if->prefetch32( armcpu->mem_if->data, + armcpu->next_instruction); + + if ( !armcpu->stalled) { + armcpu->instruction = temp_instruction; + armcpu->instruct_adr = armcpu->next_instruction; + armcpu->next_instruction += 4; + armcpu->R[15] = armcpu->next_instruction + 4; + } +#else + armcpu->instruction = MMU_read32_acl(armcpu->proc_ID, armcpu->next_instruction,CP15_ACCESS_EXECUTE); + + armcpu->instruct_adr = armcpu->next_instruction; + armcpu->next_instruction += 4; + armcpu->R[15] = armcpu->next_instruction + 4; +#endif + + return MMU.MMU_WAIT32[armcpu->proc_ID][(armcpu->instruct_adr>>24)&0xF]; + } + +#ifdef GDB_STUB + temp_instruction = + armcpu->mem_if->prefetch16( armcpu->mem_if->data, + armcpu->next_instruction); + + if ( !armcpu->stalled) { + armcpu->instruction = temp_instruction; + armcpu->instruct_adr = armcpu->next_instruction; + armcpu->next_instruction = armcpu->next_instruction + 2; + armcpu->R[15] = armcpu->next_instruction + 2; + } +#else + armcpu->instruction = MMU_read16_acl(armcpu->proc_ID, armcpu->next_instruction,CP15_ACCESS_EXECUTE); + + armcpu->instruct_adr = armcpu->next_instruction; + armcpu->next_instruction += 2; + armcpu->R[15] = armcpu->next_instruction + 2; +#endif + + return MMU.MMU_WAIT16[armcpu->proc_ID][(armcpu->instruct_adr>>24)&0xF]; +} + + +static BOOL FASTCALL test_EQ(Status_Reg CPSR) { return ( CPSR.bits.Z); } +static BOOL FASTCALL test_NE(Status_Reg CPSR) { return (!CPSR.bits.Z); } +static BOOL FASTCALL test_CS(Status_Reg CPSR) { return ( CPSR.bits.C); } +static BOOL FASTCALL test_CC(Status_Reg CPSR) { return (!CPSR.bits.C); } +static BOOL FASTCALL test_MI(Status_Reg CPSR) { return ( CPSR.bits.N); } +static BOOL FASTCALL test_PL(Status_Reg CPSR) { return (!CPSR.bits.N); } +static BOOL FASTCALL test_VS(Status_Reg CPSR) { return ( CPSR.bits.V); } +static BOOL FASTCALL test_VC(Status_Reg CPSR) { return (!CPSR.bits.V); } +static BOOL FASTCALL test_HI(Status_Reg CPSR) { return (CPSR.bits.C) && (!CPSR.bits.Z); } +static BOOL FASTCALL test_LS(Status_Reg CPSR) { return (CPSR.bits.Z) || (!CPSR.bits.C); } +static BOOL FASTCALL test_GE(Status_Reg CPSR) { return (CPSR.bits.N==CPSR.bits.V); } +static BOOL FASTCALL test_LT(Status_Reg CPSR) { return (CPSR.bits.N!=CPSR.bits.V); } +static BOOL FASTCALL test_GT(Status_Reg CPSR) { return (!CPSR.bits.Z) && (CPSR.bits.N==CPSR.bits.V); } +static BOOL FASTCALL test_LE(Status_Reg CPSR) { return ( CPSR.bits.Z) || (CPSR.bits.N!=CPSR.bits.V); } +static BOOL FASTCALL test_AL(Status_Reg CPSR) { return 1; } + +static BOOL (FASTCALL* test_conditions[])(Status_Reg CPSR)= { + test_EQ , test_NE , + test_CS , test_CC , + test_MI , test_PL , + test_VS , test_VC , + test_HI , test_LS , + test_GE , test_LT , + test_GT , test_LE , + test_AL +}; +#define TEST_COND2(cond, CPSR) \ + (cond<15&&test_conditions[cond](CPSR)) + + +BOOL armcpu_irqExeption(armcpu_t *armcpu) +{ + Status_Reg tmp; + + if(armcpu->CPSR.bits.I) return FALSE; + +#ifdef GDB_STUB + armcpu->irq_flag = 0; +#endif + + tmp = armcpu->CPSR; + armcpu_switchMode(armcpu, IRQ); + +#ifdef GDB_STUB + armcpu->R[14] = armcpu->next_instruction + 4; +#else + armcpu->R[14] = armcpu->instruct_adr + 4; +#endif + armcpu->SPSR = tmp; + armcpu->CPSR.bits.T = 0; + armcpu->CPSR.bits.I = 1; + armcpu->next_instruction = armcpu->intVector + 0x18; + armcpu->waitIRQ = 0; + +#ifndef GDB_STUB + armcpu->R[15] = armcpu->next_instruction + 8; + armcpu_prefetch(armcpu); +#endif + + return TRUE; +} +/* +static BOOL armcpu_prefetchExeption(armcpu_t *armcpu) +{ + Status_Reg tmp; + if(armcpu->CPSR.bits.I) return FALSE; + tmp = armcpu->CPSR; + armcpu_switchMode(armcpu, ABT); + armcpu->R[14] = armcpu->next_instruction + 4; + armcpu->SPSR = tmp; + armcpu->CPSR.bits.T = 0; + armcpu->CPSR.bits.I = 1; + armcpu->next_instruction = armcpu->intVector + 0xC; + armcpu->R[15] = armcpu->next_instruction + 8; + armcpu->waitIRQ = 0; + return TRUE; +} +*/ + +static BOOL armcpu_prefetchExeption(armcpu_t *armcpu) +{ + Status_Reg tmp; + if(armcpu->CPSR.bits.I) return FALSE; + tmp = armcpu->CPSR; + armcpu_switchMode(armcpu, ABT); + +#ifdef GDB_STUB + armcpu->R[14] = armcpu->next_instruction + 4; +#else + armcpu->R[14] = armcpu->instruct_adr + 4; +#endif + + armcpu->SPSR = tmp; + armcpu->CPSR.bits.T = 0; + armcpu->CPSR.bits.I = 1; + armcpu->next_instruction = armcpu->intVector + 0xC; + armcpu->waitIRQ = 0; + +#ifdef GDB_STUB + armcpu->R[15] = armcpu->next_instruction + 8; +#else + armcpu->R[15] = armcpu->next_instruction; + armcpu_prefetch(armcpu); +#endif + + return TRUE; +} + +BOOL +armcpu_flagIrq( armcpu_t *armcpu) { + if(armcpu->CPSR.bits.I) return FALSE; + + armcpu->waitIRQ = 0; + +#ifdef GDB_STUB + armcpu->irq_flag = 1; +#endif + + return TRUE; +} + + +u32 armcpu_exec(armcpu_t *armcpu) +{ + u32 c = 1; + +#ifdef GDB_STUB + if ( armcpu->stalled) + return STALLED_CYCLE_COUNT; + + /* check for interrupts */ + if ( armcpu->irq_flag) { + armcpu_irqExeption( armcpu); + } + + c = armcpu_prefetch(armcpu); + + if ( armcpu->stalled) { + return c; + } +#endif + + if(armcpu->CPSR.bits.T == 0) + { +/* if((TEST_COND(CONDITION(armcpu->instruction), armcpu->CPSR)) || ((CONDITION(armcpu->instruction)==0xF)&&(CODE(armcpu->instruction)==0x5)))*/ + if((TEST_COND(CONDITION(armcpu->instruction), CODE(armcpu->instruction), armcpu->CPSR))) + { + c += arm_instructions_set[INSTRUCTION_INDEX(armcpu->instruction)](armcpu); + } +#ifdef GDB_STUB + if ( armcpu->post_ex_fn != NULL) { + /* call the external post execute function */ + armcpu->post_ex_fn( armcpu->post_ex_fn_data, + armcpu->instruct_adr, 0); + } +#else + c += armcpu_prefetch(armcpu); +#endif + return c; + } + + c += thumb_instructions_set[armcpu->instruction>>6](armcpu); + +#ifdef GDB_STUB + if ( armcpu->post_ex_fn != NULL) { + /* call the external post execute function */ + armcpu->post_ex_fn( armcpu->post_ex_fn_data, armcpu->instruct_adr, 1); + } +#else + c += armcpu_prefetch(armcpu); +#endif + return c; +} + diff -r fe2ba1a712cd -r 70b0973e7b70 src/xsf/desmume/armcpu.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/xsf/desmume/armcpu.h Thu Oct 16 14:45:41 2008 -0500 @@ -0,0 +1,288 @@ +/* Copyright (C) 2006 yopyop + yopyop156@ifrance.com + yopyop156.ifrance.com + + This file is part of DeSmuME + + DeSmuME is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DeSmuME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DeSmuME; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef ARM_CPU +#define ARM_CPU + +#include "types.h" +#include "bits.h" +#include "MMU.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ARMCPU_ARM7 1 +#define ARMCPU_ARM9 0 + +#define CODE(i) (((i)>>25)&0X7) +#define OPCODE(i) (((i)>>21)&0xF) +#define SIGNEBIT(i) BIT_N(i,20) + +#define INSTRUCTION_INDEX(i) ((((i)>>16)&0xFF0)|(((i)>>4)&0xF)) + +#define ROR(i, j) ((((u32)(i))>>(j)) | (((u32)(i))<<(32-(j)))) + +#define UNSIGNED_OVERFLOW(a,b,c) ((BIT31(a)&BIT31(b)) | \ + ((BIT31(a)|BIT31(b))&BIT31(~c))) + +#define UNSIGNED_UNDERFLOW(a,b,c) ((BIT31(~a)&BIT31(b)) | \ + ((BIT31(~a)|BIT31(b))&BIT31(c))) + +#define SIGNED_OVERFLOW(a,b,c) ((BIT31(a)&BIT31(b)&BIT31(~c))|\ + (BIT31(~a)&BIT31(~(b))&BIT31(c))) + +#define SIGNED_UNDERFLOW(a,b,c) ((BIT31(a)&BIT31(~(b))&BIT31(~c))|\ + (BIT31(~a)&BIT31(b)&BIT31(c))) + +#define EQ 0x0 +#define NE 0x1 +#define CS 0x2 +#define CC 0x3 +#define MI 0x4 +#define PL 0x5 +#define VS 0x6 +#define VC 0x7 +#define HI 0x8 +#define LS 0x9 +#define GE 0xA +#define LT 0xB +#define GT 0xC +#define LE 0xD +#define AL 0xE + +/* +#define TEST_COND(cond, CPSR) (((cond)==AL) ||\ + (((cond)==EQ) && ( CPSR.bits.Z))||\ + (((cond)==NE) && (!CPSR.bits.Z))||\ + (((cond)==CS) && ( CPSR.bits.C))||\ + (((cond)==CC) && (!CPSR.bits.C))||\ + (((cond)==MI) && ( CPSR.bits.N))||\ + (((cond)==PL) && (!CPSR.bits.N))||\ + (((cond)==VS) && ( CPSR.bits.V))||\ + (((cond)==VC) && (!CPSR.bits.V))||\ + (((cond)==HI) && (CPSR.bits.C) && (!CPSR.bits.Z))||\ + (((cond)==LS) && ((CPSR.bits.Z) || (!CPSR.bits.C)))||\ + (((cond)==GE) && (CPSR.bits.N==CPSR.bits.V))||\ + (((cond)==LT) && (CPSR.bits.N!=CPSR.bits.V))||\ + (((cond)==GT) && (CPSR.bits.Z==0) && (CPSR.bits.N==CPSR.bits.V))||\ + (((cond)==LE) && ((CPSR.bits.Z) || (CPSR.bits.N!=CPSR.bits.V)))) +*/ + +extern const unsigned char arm_cond_table[16*16]; + +#define TEST_COND(cond, inst, CPSR) ((arm_cond_table[((CPSR.val >> 24) & 0xf0)+(cond)] >> (inst)) & 1) + + +enum Mode +{ + USR = 0x10, + FIQ = 0x11, + IRQ = 0x12, + SVC = 0x13, + ABT = 0x17, + UND = 0x1B, + SYS = 0x1F +}; + +#ifdef WORDS_BIGENDIAN +typedef union +{ + struct + { + u32 N : 1, + Z : 1, + C : 1, + V : 1, + Q : 1, + RAZ : 19, + I : 1, + F : 1, + T : 1, + mode : 5; + } bits; + u32 val; +} Status_Reg; +#else +typedef union +{ + struct + { + u32 mode : 5, + T : 1, + F : 1, + I : 1, + RAZ : 19, + Q : 1, + V : 1, + C : 1, + Z : 1, + N : 1; + } bits; + u32 val; +} Status_Reg; +#endif + +/** + * The control interface to a CPU + */ +struct armcpu_ctrl_iface { + /** stall the processor */ + void (*stall)( void *instance); + + /** unstall the processor */ + void (*unstall)( void *instance); + + /** read a register value */ + u32 (*read_reg)( void *instance, u32 reg_num); + + /** set a register value */ + void (*set_reg)( void *instance, u32 reg_num, u32 value); + + /** install the post execute function */ + void (*install_post_ex_fn)( void *instance, + void (*fn)( void *, u32 adr, int thumb), + void *fn_data); + + /** remove the post execute function */ + void (*remove_post_ex_fn)( void *instance); + + /** the private data passed to all interface functions */ + void *data; +}; + + +typedef void* armcp_t; + +typedef struct armcpu_t +{ + u32 proc_ID; + u32 instruction; //4 + u32 instruct_adr; //8 + u32 next_instruction; //12 + + u32 R[16]; //16 + Status_Reg CPSR; //80 + Status_Reg SPSR; + + u32 R13_usr, R14_usr; + u32 R13_svc, R14_svc; + u32 R13_abt, R14_abt; + u32 R13_und, R14_und; + u32 R13_irq, R14_irq; + u32 R8_fiq, R9_fiq, R10_fiq, R11_fiq, R12_fiq, R13_fiq, R14_fiq; + Status_Reg SPSR_svc, SPSR_abt, SPSR_und, SPSR_irq, SPSR_fiq; + + armcp_t *coproc[16]; + + u32 intVector; + u8 LDTBit; //1 : ARMv5 style 0 : non ARMv5 + BOOL waitIRQ; + BOOL wIRQ; + BOOL wirq; + + u32 (* *swi_tab)(struct armcpu_t * cpu); + +#ifdef GDB_STUB + /** there is a pending irq for the cpu */ + int irq_flag; + + /** the post executed function (if installed) */ + void (*post_ex_fn)( void *, u32 adr, int thumb); + + /** data for the post executed function */ + void *post_ex_fn_data; + + + /** flag indicating if the processor is stalled */ + int stalled; + + /** the memory interface */ + struct armcpu_memory_iface *mem_if; + + /** the ctrl interface */ + struct armcpu_ctrl_iface ctrl_iface; +#endif +} armcpu_t; + +#ifdef GDB_STUB +int armcpu_new( armcpu_t *armcpu, u32 id, struct armcpu_memory_iface *mem_if, + struct armcpu_ctrl_iface **ctrl_iface_ret); +#else +int armcpu_new( armcpu_t *armcpu, u32 id); +#endif +void armcpu_init(armcpu_t *armcpu, u32 adr); +u32 armcpu_switchMode(armcpu_t *armcpu, u8 mode); +static u32 armcpu_prefetch(armcpu_t *armcpu); +u32 armcpu_exec(armcpu_t *armcpu); +BOOL armcpu_irqExeption(armcpu_t *armcpu); +//BOOL armcpu_prefetchExeption(armcpu_t *armcpu); +BOOL +armcpu_flagIrq( armcpu_t *armcpu); + +extern armcpu_t NDS_ARM7; +extern armcpu_t NDS_ARM9; + +static INLINE void NDS_makeARM9Int(u32 num) +{ + /* flag the interrupt request source */ + MMU.reg_IF[0] |= (1< +#include "MMU.h" +#include "SPU.h" +#include "debug.h" + +extern BOOL execute; + +static u16 getsinetbl[] = { +0x0000, 0x0324, 0x0648, 0x096A, 0x0C8C, 0x0FAB, 0x12C8, 0x15E2, +0x18F9, 0x1C0B, 0x1F1A, 0x2223, 0x2528, 0x2826, 0x2B1F, 0x2E11, +0x30FB, 0x33DF, 0x36BA, 0x398C, 0x3C56, 0x3F17, 0x41CE, 0x447A, +0x471C, 0x49B4, 0x4C3F, 0x4EBF, 0x5133, 0x539B, 0x55F5, 0x5842, +0x5A82, 0x5CB3, 0x5ED7, 0x60EB, 0x62F1, 0x64E8, 0x66CF, 0x68A6, +0x6A6D, 0x6C23, 0x6DC9, 0x6F5E, 0x70E2, 0x7254, 0x73B5, 0x7504, +0x7641, 0x776B, 0x7884, 0x7989, 0x7A7C, 0x7B5C, 0x7C29, 0x7CE3, +0x7D89, 0x7E1D, 0x7E9C, 0x7F09, 0x7F61, 0x7FA6, 0x7FD8, 0x7FF5 +}; + +static u16 getpitchtbl[] = { +0x0000, 0x003B, 0x0076, 0x00B2, 0x00ED, 0x0128, 0x0164, 0x019F, +0x01DB, 0x0217, 0x0252, 0x028E, 0x02CA, 0x0305, 0x0341, 0x037D, +0x03B9, 0x03F5, 0x0431, 0x046E, 0x04AA, 0x04E6, 0x0522, 0x055F, +0x059B, 0x05D8, 0x0614, 0x0651, 0x068D, 0x06CA, 0x0707, 0x0743, +0x0780, 0x07BD, 0x07FA, 0x0837, 0x0874, 0x08B1, 0x08EF, 0x092C, +0x0969, 0x09A7, 0x09E4, 0x0A21, 0x0A5F, 0x0A9C, 0x0ADA, 0x0B18, +0x0B56, 0x0B93, 0x0BD1, 0x0C0F, 0x0C4D, 0x0C8B, 0x0CC9, 0x0D07, +0x0D45, 0x0D84, 0x0DC2, 0x0E00, 0x0E3F, 0x0E7D, 0x0EBC, 0x0EFA, +0x0F39, 0x0F78, 0x0FB6, 0x0FF5, 0x1034, 0x1073, 0x10B2, 0x10F1, +0x1130, 0x116F, 0x11AE, 0x11EE, 0x122D, 0x126C, 0x12AC, 0x12EB, +0x132B, 0x136B, 0x13AA, 0x13EA, 0x142A, 0x146A, 0x14A9, 0x14E9, +0x1529, 0x1569, 0x15AA, 0x15EA, 0x162A, 0x166A, 0x16AB, 0x16EB, +0x172C, 0x176C, 0x17AD, 0x17ED, 0x182E, 0x186F, 0x18B0, 0x18F0, +0x1931, 0x1972, 0x19B3, 0x19F5, 0x1A36, 0x1A77, 0x1AB8, 0x1AFA, +0x1B3B, 0x1B7D, 0x1BBE, 0x1C00, 0x1C41, 0x1C83, 0x1CC5, 0x1D07, +0x1D48, 0x1D8A, 0x1DCC, 0x1E0E, 0x1E51, 0x1E93, 0x1ED5, 0x1F17, +0x1F5A, 0x1F9C, 0x1FDF, 0x2021, 0x2064, 0x20A6, 0x20E9, 0x212C, +0x216F, 0x21B2, 0x21F5, 0x2238, 0x227B, 0x22BE, 0x2301, 0x2344, +0x2388, 0x23CB, 0x240E, 0x2452, 0x2496, 0x24D9, 0x251D, 0x2561, +0x25A4, 0x25E8, 0x262C, 0x2670, 0x26B4, 0x26F8, 0x273D, 0x2781, +0x27C5, 0x280A, 0x284E, 0x2892, 0x28D7, 0x291C, 0x2960, 0x29A5, +0x29EA, 0x2A2F, 0x2A74, 0x2AB9, 0x2AFE, 0x2B43, 0x2B88, 0x2BCD, +0x2C13, 0x2C58, 0x2C9D, 0x2CE3, 0x2D28, 0x2D6E, 0x2DB4, 0x2DF9, +0x2E3F, 0x2E85, 0x2ECB, 0x2F11, 0x2F57, 0x2F9D, 0x2FE3, 0x302A, +0x3070, 0x30B6, 0x30FD, 0x3143, 0x318A, 0x31D0, 0x3217, 0x325E, +0x32A5, 0x32EC, 0x3332, 0x3379, 0x33C1, 0x3408, 0x344F, 0x3496, +0x34DD, 0x3525, 0x356C, 0x35B4, 0x35FB, 0x3643, 0x368B, 0x36D3, +0x371A, 0x3762, 0x37AA, 0x37F2, 0x383A, 0x3883, 0x38CB, 0x3913, +0x395C, 0x39A4, 0x39ED, 0x3A35, 0x3A7E, 0x3AC6, 0x3B0F, 0x3B58, +0x3BA1, 0x3BEA, 0x3C33, 0x3C7C, 0x3CC5, 0x3D0E, 0x3D58, 0x3DA1, +0x3DEA, 0x3E34, 0x3E7D, 0x3EC7, 0x3F11, 0x3F5A, 0x3FA4, 0x3FEE, +0x4038, 0x4082, 0x40CC, 0x4116, 0x4161, 0x41AB, 0x41F5, 0x4240, +0x428A, 0x42D5, 0x431F, 0x436A, 0x43B5, 0x4400, 0x444B, 0x4495, +0x44E1, 0x452C, 0x4577, 0x45C2, 0x460D, 0x4659, 0x46A4, 0x46F0, +0x473B, 0x4787, 0x47D3, 0x481E, 0x486A, 0x48B6, 0x4902, 0x494E, +0x499A, 0x49E6, 0x4A33, 0x4A7F, 0x4ACB, 0x4B18, 0x4B64, 0x4BB1, +0x4BFE, 0x4C4A, 0x4C97, 0x4CE4, 0x4D31, 0x4D7E, 0x4DCB, 0x4E18, +0x4E66, 0x4EB3, 0x4F00, 0x4F4E, 0x4F9B, 0x4FE9, 0x5036, 0x5084, +0x50D2, 0x5120, 0x516E, 0x51BC, 0x520A, 0x5258, 0x52A6, 0x52F4, +0x5343, 0x5391, 0x53E0, 0x542E, 0x547D, 0x54CC, 0x551A, 0x5569, +0x55B8, 0x5607, 0x5656, 0x56A5, 0x56F4, 0x5744, 0x5793, 0x57E2, +0x5832, 0x5882, 0x58D1, 0x5921, 0x5971, 0x59C1, 0x5A10, 0x5A60, +0x5AB0, 0x5B01, 0x5B51, 0x5BA1, 0x5BF1, 0x5C42, 0x5C92, 0x5CE3, +0x5D34, 0x5D84, 0x5DD5, 0x5E26, 0x5E77, 0x5EC8, 0x5F19, 0x5F6A, +0x5FBB, 0x600D, 0x605E, 0x60B0, 0x6101, 0x6153, 0x61A4, 0x61F6, +0x6248, 0x629A, 0x62EC, 0x633E, 0x6390, 0x63E2, 0x6434, 0x6487, +0x64D9, 0x652C, 0x657E, 0x65D1, 0x6624, 0x6676, 0x66C9, 0x671C, +0x676F, 0x67C2, 0x6815, 0x6869, 0x68BC, 0x690F, 0x6963, 0x69B6, +0x6A0A, 0x6A5E, 0x6AB1, 0x6B05, 0x6B59, 0x6BAD, 0x6C01, 0x6C55, +0x6CAA, 0x6CFE, 0x6D52, 0x6DA7, 0x6DFB, 0x6E50, 0x6EA4, 0x6EF9, +0x6F4E, 0x6FA3, 0x6FF8, 0x704D, 0x70A2, 0x70F7, 0x714D, 0x71A2, +0x71F7, 0x724D, 0x72A2, 0x72F8, 0x734E, 0x73A4, 0x73FA, 0x7450, +0x74A6, 0x74FC, 0x7552, 0x75A8, 0x75FF, 0x7655, 0x76AC, 0x7702, +0x7759, 0x77B0, 0x7807, 0x785E, 0x78B4, 0x790C, 0x7963, 0x79BA, +0x7A11, 0x7A69, 0x7AC0, 0x7B18, 0x7B6F, 0x7BC7, 0x7C1F, 0x7C77, +0x7CCF, 0x7D27, 0x7D7F, 0x7DD7, 0x7E2F, 0x7E88, 0x7EE0, 0x7F38, +0x7F91, 0x7FEA, 0x8042, 0x809B, 0x80F4, 0x814D, 0x81A6, 0x81FF, +0x8259, 0x82B2, 0x830B, 0x8365, 0x83BE, 0x8418, 0x8472, 0x84CB, +0x8525, 0x857F, 0x85D9, 0x8633, 0x868E, 0x86E8, 0x8742, 0x879D, +0x87F7, 0x8852, 0x88AC, 0x8907, 0x8962, 0x89BD, 0x8A18, 0x8A73, +0x8ACE, 0x8B2A, 0x8B85, 0x8BE0, 0x8C3C, 0x8C97, 0x8CF3, 0x8D4F, +0x8DAB, 0x8E07, 0x8E63, 0x8EBF, 0x8F1B, 0x8F77, 0x8FD4, 0x9030, +0x908C, 0x90E9, 0x9146, 0x91A2, 0x91FF, 0x925C, 0x92B9, 0x9316, +0x9373, 0x93D1, 0x942E, 0x948C, 0x94E9, 0x9547, 0x95A4, 0x9602, +0x9660, 0x96BE, 0x971C, 0x977A, 0x97D8, 0x9836, 0x9895, 0x98F3, +0x9952, 0x99B0, 0x9A0F, 0x9A6E, 0x9ACD, 0x9B2C, 0x9B8B, 0x9BEA, +0x9C49, 0x9CA8, 0x9D08, 0x9D67, 0x9DC7, 0x9E26, 0x9E86, 0x9EE6, +0x9F46, 0x9FA6, 0xA006, 0xA066, 0xA0C6, 0xA127, 0xA187, 0xA1E8, +0xA248, 0xA2A9, 0xA30A, 0xA36B, 0xA3CC, 0xA42D, 0xA48E, 0xA4EF, +0xA550, 0xA5B2, 0xA613, 0xA675, 0xA6D6, 0xA738, 0xA79A, 0xA7FC, +0xA85E, 0xA8C0, 0xA922, 0xA984, 0xA9E7, 0xAA49, 0xAAAC, 0xAB0E, +0xAB71, 0xABD4, 0xAC37, 0xAC9A, 0xACFD, 0xAD60, 0xADC3, 0xAE27, +0xAE8A, 0xAEED, 0xAF51, 0xAFB5, 0xB019, 0xB07C, 0xB0E0, 0xB145, +0xB1A9, 0xB20D, 0xB271, 0xB2D6, 0xB33A, 0xB39F, 0xB403, 0xB468, +0xB4CD, 0xB532, 0xB597, 0xB5FC, 0xB662, 0xB6C7, 0xB72C, 0xB792, +0xB7F7, 0xB85D, 0xB8C3, 0xB929, 0xB98F, 0xB9F5, 0xBA5B, 0xBAC1, +0xBB28, 0xBB8E, 0xBBF5, 0xBC5B, 0xBCC2, 0xBD29, 0xBD90, 0xBDF7, +0xBE5E, 0xBEC5, 0xBF2C, 0xBF94, 0xBFFB, 0xC063, 0xC0CA, 0xC132, +0xC19A, 0xC202, 0xC26A, 0xC2D2, 0xC33A, 0xC3A2, 0xC40B, 0xC473, +0xC4DC, 0xC544, 0xC5AD, 0xC616, 0xC67F, 0xC6E8, 0xC751, 0xC7BB, +0xC824, 0xC88D, 0xC8F7, 0xC960, 0xC9CA, 0xCA34, 0xCA9E, 0xCB08, +0xCB72, 0xCBDC, 0xCC47, 0xCCB1, 0xCD1B, 0xCD86, 0xCDF1, 0xCE5B, +0xCEC6, 0xCF31, 0xCF9C, 0xD008, 0xD073, 0xD0DE, 0xD14A, 0xD1B5, +0xD221, 0xD28D, 0xD2F8, 0xD364, 0xD3D0, 0xD43D, 0xD4A9, 0xD515, +0xD582, 0xD5EE, 0xD65B, 0xD6C7, 0xD734, 0xD7A1, 0xD80E, 0xD87B, +0xD8E9, 0xD956, 0xD9C3, 0xDA31, 0xDA9E, 0xDB0C, 0xDB7A, 0xDBE8, +0xDC56, 0xDCC4, 0xDD32, 0xDDA0, 0xDE0F, 0xDE7D, 0xDEEC, 0xDF5B, +0xDFC9, 0xE038, 0xE0A7, 0xE116, 0xE186, 0xE1F5, 0xE264, 0xE2D4, +0xE343, 0xE3B3, 0xE423, 0xE493, 0xE503, 0xE573, 0xE5E3, 0xE654, +0xE6C4, 0xE735, 0xE7A5, 0xE816, 0xE887, 0xE8F8, 0xE969, 0xE9DA, +0xEA4B, 0xEABC, 0xEB2E, 0xEB9F, 0xEC11, 0xEC83, 0xECF5, 0xED66, +0xEDD9, 0xEE4B, 0xEEBD, 0xEF2F, 0xEFA2, 0xF014, 0xF087, 0xF0FA, +0xF16D, 0xF1E0, 0xF253, 0xF2C6, 0xF339, 0xF3AD, 0xF420, 0xF494, +0xF507, 0xF57B, 0xF5EF, 0xF663, 0xF6D7, 0xF74C, 0xF7C0, 0xF834, +0xF8A9, 0xF91E, 0xF992, 0xFA07, 0xFA7C, 0xFAF1, 0xFB66, 0xFBDC, +0xFC51, 0xFCC7, 0xFD3C, 0xFDB2, 0xFE28, 0xFE9E, 0xFF14, 0xFF8A +}; + +static u8 getvoltbl[] = { +0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, +0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, +0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, +0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, +0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, +0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, +0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, +0x05, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, +0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x08, 0x08, 0x08, 0x08, +0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, +0x09, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, +0x0B, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0E, +0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x10, 0x10, 0x10, 0x10, 0x10, +0x10, 0x11, 0x11, 0x11, 0x11, 0x11, 0x12, 0x12, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x13, 0x14, +0x14, 0x14, 0x14, 0x14, 0x15, 0x15, 0x15, 0x15, 0x16, 0x16, 0x16, 0x16, 0x17, 0x17, 0x17, 0x18, +0x18, 0x18, 0x18, 0x19, 0x19, 0x19, 0x19, 0x1A, 0x1A, 0x1A, 0x1B, 0x1B, 0x1B, 0x1C, 0x1C, 0x1C, +0x1D, 0x1D, 0x1D, 0x1E, 0x1E, 0x1E, 0x1F, 0x1F, 0x1F, 0x20, 0x20, 0x20, 0x21, 0x21, 0x22, 0x22, +0x22, 0x23, 0x23, 0x24, 0x24, 0x24, 0x25, 0x25, 0x26, 0x26, 0x27, 0x27, 0x27, 0x28, 0x28, 0x29, +0x29, 0x2A, 0x2A, 0x2B, 0x2B, 0x2C, 0x2C, 0x2D, 0x2D, 0x2E, 0x2E, 0x2F, 0x2F, 0x30, 0x31, 0x31, +0x32, 0x32, 0x33, 0x33, 0x34, 0x35, 0x35, 0x36, 0x36, 0x37, 0x38, 0x38, 0x39, 0x3A, 0x3A, 0x3B, +0x3C, 0x3C, 0x3D, 0x3E, 0x3F, 0x3F, 0x40, 0x41, 0x42, 0x42, 0x43, 0x44, 0x45, 0x45, 0x46, 0x47, +0x48, 0x49, 0x4A, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x52, 0x53, 0x54, 0x55, +0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5D, 0x5E, 0x5F, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x67, +0x68, 0x69, 0x6A, 0x6B, 0x6D, 0x6E, 0x6F, 0x71, 0x72, 0x73, 0x75, 0x76, 0x77, 0x79, 0x7A, 0x7B, +0x7D, 0x7E, 0x7F, 0x20, 0x21, 0x21, 0x21, 0x22, 0x22, 0x23, 0x23, 0x23, 0x24, 0x24, 0x25, 0x25, +0x26, 0x26, 0x26, 0x27, 0x27, 0x28, 0x28, 0x29, 0x29, 0x2A, 0x2A, 0x2B, 0x2B, 0x2C, 0x2C, 0x2D, +0x2D, 0x2E, 0x2E, 0x2F, 0x2F, 0x30, 0x30, 0x31, 0x31, 0x32, 0x33, 0x33, 0x34, 0x34, 0x35, 0x36, +0x36, 0x37, 0x37, 0x38, 0x39, 0x39, 0x3A, 0x3B, 0x3B, 0x3C, 0x3D, 0x3E, 0x3E, 0x3F, 0x40, 0x40, +0x41, 0x42, 0x43, 0x43, 0x44, 0x45, 0x46, 0x47, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4D, +0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, +0x5E, 0x5F, 0x60, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6F, 0x70, +0x71, 0x73, 0x74, 0x75, 0x77, 0x78, 0x79, 0x7B, 0x7C, 0x7E, 0x7E, 0x40, 0x41, 0x42, 0x43, 0x43, +0x44, 0x45, 0x46, 0x47, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, +0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x61, +0x62, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6B, 0x6C, 0x6D, 0x6E, 0x70, 0x71, 0x72, 0x74, 0x75, +0x76, 0x78, 0x79, 0x7B, 0x7C, 0x7D, 0x7E, 0x40, 0x41, 0x42, 0x42, 0x43, 0x44, 0x45, 0x46, 0x46, +0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, +0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x61, 0x62, 0x63, 0x65, 0x66, +0x67, 0x68, 0x69, 0x6A, 0x6C, 0x6D, 0x6E, 0x6F, 0x71, 0x72, 0x73, 0x75, 0x76, 0x77, 0x79, 0x7A, +0x7C, 0x7D, 0x7E, 0x7F +}; + +u32 bios_nop(armcpu_t * cpu) +{ + if (cpu->proc_ID == ARMCPU_ARM9) + { + LOG("Unimplemented bios function %02X(ARM9) was used. R0:%08X\n", (cpu->instruction)&0x1F, cpu->R[0]); + } + else + { + LOG("Unimplemented bios function %02X(ARM7) was used. R0:%08X\n", (cpu->instruction)&0x1F, cpu->R[0]); + } + return 3; +} + +u32 delayLoop(armcpu_t * cpu) +{ + return cpu->R[0] * 4; +} + +//u32 oldmode[2]; + +u32 intrWaitARM(armcpu_t * cpu) +{ + u32 intrFlagAdr;// = (((armcp15_t *)(cpu->coproc[15]))->DTCMRegion&0xFFFFF000)+0x3FF8; + u32 intr; + u32 intrFlag = 0; + + //execute = FALSE; + if(cpu->proc_ID) + { + intrFlagAdr = 0x380FFF8; + } else { + intrFlagAdr = (((armcp15_t *)(cpu->coproc[15]))->DTCMRegion&0xFFFFF000)+0x3FF8; + } + intr = MMU_read32(cpu->proc_ID, intrFlagAdr); + intrFlag = cpu->R[1] & intr; + + if(intrFlag) + { + // si une(ou plusieurs) des interruptions que l'on attend s'est(se sont) produite(s) + // on efface son(les) occurence(s). + intr ^= intrFlag; + MMU_write32(cpu->proc_ID, intrFlagAdr, intr); + //cpu->switchMode(oldmode[cpu->proc_ID]); + return 1; + } + + cpu->R[15] = cpu->instruct_adr; + cpu->next_instruction = cpu->R[15]; + cpu->waitIRQ = 1; + //oldmode[cpu->proc_ID] = cpu->switchMode(SVC); + + return 1; +} + +u32 waitVBlankARM(armcpu_t * cpu) +{ + u32 intrFlagAdr;// = (((armcp15_t *)(cpu->coproc[15]))->DTCMRegion&0xFFFFF000)+0x3FF8; + u32 intr; + u32 intrFlag = 0; + + //execute = FALSE; + if(cpu->proc_ID) + { + intrFlagAdr = 0x380FFF8; + } else { + intrFlagAdr = (((armcp15_t *)(cpu->coproc[15]))->DTCMRegion&0xFFFFF000)+0x3FF8; + } + intr = MMU_read32(cpu->proc_ID, intrFlagAdr); + intrFlag = 1 & intr; + + if(intrFlag) + { + // si une(ou plusieurs) des interruptions que l'on attend s'est(se sont) produite(s) + // on efface son(les) occurence(s). + intr ^= intrFlag; + MMU_write32(cpu->proc_ID, intrFlagAdr, intr); + //cpu->switchMode(oldmode[cpu->proc_ID]); + return 1; + } + + cpu->R[15] = cpu->instruct_adr; + cpu->next_instruction = cpu->R[15]; + cpu->waitIRQ = 1; + //oldmode[cpu->proc_ID] = cpu->switchMode(SVC); + + return 1; +} + +u32 wait4IRQ(armcpu_t* cpu) +{ + //execute= FALSE; + if(cpu->wirq) + { + if(!cpu->waitIRQ) + { + cpu->waitIRQ = 0; + cpu->wirq = 0; + //cpu->switchMode(oldmode[cpu->proc_ID]); + return 1; + } + cpu->R[15] = cpu->instruct_adr; + cpu->next_instruction = cpu->R[15]; + return 1; + } + cpu->waitIRQ = 1; + cpu->wirq = 1; + cpu->R[15] = cpu->instruct_adr; + cpu->next_instruction = cpu->R[15]; + //oldmode[cpu->proc_ID] = cpu->switchMode(SVC); + return 1; +} + +u32 devide(armcpu_t* cpu) +{ + s32 num = (s32)cpu->R[0]; + s32 dnum = (s32)cpu->R[1]; + + if(dnum==0) return 0; + + cpu->R[0] = (u32)(num / dnum); + cpu->R[1] = (u32)(num % dnum); + cpu->R[3] = (u32) (((s32)cpu->R[0])<0 ? -cpu->R[0] : cpu->R[0]); + + return 6; +} + +u32 copy(armcpu_t* cpu) +{ + u32 src = cpu->R[0]; + u32 dst = cpu->R[1]; + u32 cnt = cpu->R[2]; + + switch(BIT26(cnt)) + { + case 0: + src &= 0xFFFFFFFE; + dst &= 0xFFFFFFFE; + switch(BIT24(cnt)) + { + case 0: + cnt &= 0x1FFFFF; + while(cnt) + { + MMU_write16(cpu->proc_ID, dst, MMU_read16(cpu->proc_ID, src)); + cnt--; + dst+=2; + src+=2; + } + break; + case 1: + { + u32 val = MMU_read16(cpu->proc_ID, src); + cnt &= 0x1FFFFF; + while(cnt) + { + MMU_write16(cpu->proc_ID, dst, val); + cnt--; + dst+=2; + } + } + break; + } + break; + case 1: + src &= 0xFFFFFFFC; + dst &= 0xFFFFFFFC; + switch(BIT24(cnt)) + { + case 0: + cnt &= 0x1FFFFF; + while(cnt) + { + MMU_write32(cpu->proc_ID, dst, MMU_read32(cpu->proc_ID, src)); + cnt--; + dst+=4; + src+=4; + } + break; + case 1: + { + u32 val = MMU_read32(cpu->proc_ID, src); + cnt &= 0x1FFFFF; + while(cnt) + { + MMU_write32(cpu->proc_ID, dst, val); + cnt--; + dst+=4; + } + } + break; + } + break; + } + return 1; +} + +u32 fastCopy(armcpu_t* cpu) +{ + u32 src = cpu->R[0] & 0xFFFFFFFC; + u32 dst = cpu->R[1] & 0xFFFFFFFC; + u32 cnt = cpu->R[2]; + + switch(BIT24(cnt)) + { + case 0: + cnt &= 0x1FFFFF; + while(cnt) + { + MMU_write32(cpu->proc_ID, dst, MMU_read32(cpu->proc_ID, src)); + cnt--; + dst+=4; + src+=4; + } + break; + case 1: + { + u32 val = MMU_read32(cpu->proc_ID, src); + cnt &= 0x1FFFFF; + while(cnt) + { + MMU_write32(cpu->proc_ID, dst, val); + cnt--; + dst+=4; + } + } + break; + } + return 1; +} + +u32 LZ77UnCompVram(armcpu_t* cpu) +{ + int i1, i2; + int byteCount; + int byteShift; + u32 writeValue; + int len; + u32 source = cpu->R[0]; + u32 dest = cpu->R[1]; + u32 header = MMU_read32(cpu->proc_ID, source); + source += 4; + + if(((source & 0xe000000) == 0) || + ((source + ((header >> 8) & 0x1fffff)) & 0xe000000) == 0) + return 0; + + byteCount = 0; + byteShift = 0; + writeValue = 0; + + len = header >> 8; + + while(len > 0) { + u8 d = MMU_read8(cpu->proc_ID, source++); + + if(d) { + for(i1 = 0; i1 < 8; i1++) { + if(d & 0x80) { + int length; + int offset; + u32 windowOffset; + u16 data = MMU_read8(cpu->proc_ID, source++) << 8; + data |= MMU_read8(cpu->proc_ID, source++); + length = (data >> 12) + 3; + offset = (data & 0x0FFF); + windowOffset = dest + byteCount - offset - 1; + for(i2 = 0; i2 < length; i2++) { + writeValue |= (MMU_read8(cpu->proc_ID, windowOffset++) << byteShift); + byteShift += 8; + byteCount++; + + if(byteCount == 2) { + MMU_write16(cpu->proc_ID, dest, writeValue); + dest += 2; + byteCount = 0; + byteShift = 0; + writeValue = 0; + } + len--; + if(len == 0) + return 0; + } + } else { + writeValue |= (MMU_read8(cpu->proc_ID, source++) << byteShift); + byteShift += 8; + byteCount++; + if(byteCount == 2) { + MMU_write16(cpu->proc_ID, dest, writeValue); + dest += 2; + byteCount = 0; + byteShift = 0; + writeValue = 0; + } + len--; + if(len == 0) + return 0; + } + d <<= 1; + } + } else { + for(i1 = 0; i1 < 8; i1++) { + writeValue |= (MMU_read8(cpu->proc_ID, source++) << byteShift); + byteShift += 8; + byteCount++; + if(byteCount == 2) { + MMU_write16(cpu->proc_ID, dest, writeValue); + dest += 2; + byteShift = 0; + byteCount = 0; + writeValue = 0; + } + len--; + if(len == 0) + return 0; + } + } + } + return 1; +} + +u32 LZ77UnCompWram(armcpu_t* cpu) +{ + int i1, i2; + int len; + u32 source = cpu->R[0]; + u32 dest = cpu->R[1]; + + u32 header = MMU_read32(cpu->proc_ID, source); + source += 4; + + if(((source & 0xe000000) == 0) || + ((source + ((header >> 8) & 0x1fffff)) & 0xe000000) == 0) + return 0; + + len = header >> 8; + + while(len > 0) { + u8 d = MMU_read8(cpu->proc_ID, source++); + + if(d) { + for(i1 = 0; i1 < 8; i1++) { + if(d & 0x80) { + int length; + int offset; + u32 windowOffset; + u16 data = MMU_read8(cpu->proc_ID, source++) << 8; + data |= MMU_read8(cpu->proc_ID, source++); + length = (data >> 12) + 3; + offset = (data & 0x0FFF); + windowOffset = dest - offset - 1; + for(i2 = 0; i2 < length; i2++) { + MMU_write8(cpu->proc_ID, dest++, MMU_read8(cpu->proc_ID, windowOffset++)); + len--; + if(len == 0) + return 0; + } + } else { + MMU_write8(cpu->proc_ID, dest++, MMU_read8(cpu->proc_ID, source++)); + len--; + if(len == 0) + return 0; + } + d <<= 1; + } + } else { + for(i1 = 0; i1 < 8; i1++) { + MMU_write8(cpu->proc_ID, dest++, MMU_read8(cpu->proc_ID, source++)); + len--; + if(len == 0) + return 0; + } + } + } + return 1; +} + +u32 RLUnCompVram(armcpu_t* cpu) +{ + int i; + int len; + int byteCount; + int byteShift; + u32 writeValue; + u32 source = cpu->R[0]; + u32 dest = cpu->R[1]; + + u32 header = MMU_read32(cpu->proc_ID, source); + source += 4; + + if(((source & 0xe000000) == 0) || + ((source + ((header >> 8) & 0x1fffff)) & 0xe000000) == 0) + return 0; + + len = header >> 8; + byteCount = 0; + byteShift = 0; + writeValue = 0; + + while(len > 0) { + u8 d = MMU_read8(cpu->proc_ID, source++); + int l = d & 0x7F; + if(d & 0x80) { + u8 data = MMU_read8(cpu->proc_ID, source++); + l += 3; + for(i = 0;i < l; i++) { + writeValue |= (data << byteShift); + byteShift += 8; + byteCount++; + + if(byteCount == 2) { + MMU_write16(cpu->proc_ID, dest, writeValue); + dest += 2; + byteCount = 0; + byteShift = 0; + writeValue = 0; + } + len--; + if(len == 0) + return 0; + } + } else { + l++; + for(i = 0; i < l; i++) { + writeValue |= (MMU_read8(cpu->proc_ID, source++) << byteShift); + byteShift += 8; + byteCount++; + if(byteCount == 2) { + MMU_write16(cpu->proc_ID, dest, writeValue); + dest += 2; + byteCount = 0; + byteShift = 0; + writeValue = 0; + } + len--; + if(len == 0) + return 0; + } + } + } + return 1; +} + +u32 RLUnCompWram(armcpu_t* cpu) +{ + int i; + int len; + u32 source = cpu->R[0]; + u32 dest = cpu->R[1]; + + u32 header = MMU_read32(cpu->proc_ID, source); + source += 4; + + if(((source & 0xe000000) == 0) || + ((source + ((header >> 8) & 0x1fffff)) & 0xe000000) == 0) + return 0; + + len = header >> 8; + + while(len > 0) { + u8 d = MMU_read8(cpu->proc_ID, source++); + int l = d & 0x7F; + if(d & 0x80) { + u8 data = MMU_read8(cpu->proc_ID, source++); + l += 3; + for(i = 0;i < l; i++) { + MMU_write8(cpu->proc_ID, dest++, data); + len--; + if(len == 0) + return 0; + } + } else { + l++; + for(i = 0; i < l; i++) { + MMU_write8(cpu->proc_ID, dest++, MMU_read8(cpu->proc_ID, source++)); + len--; + if(len == 0) + return 0; + } + } + } + return 1; +} + +u32 UnCompHuffman(armcpu_t* cpu) +{ + u32 source, dest, writeValue, header, treeStart, mask; + u32 data; + u8 treeSize, currentNode, rootNode; + int byteCount, byteShift, len, pos; + int writeData; + + source = cpu->R[0]; + dest = cpu->R[1]; + + header = MMU_read8(cpu->proc_ID, source); + source += 4; + + if(((source & 0xe000000) == 0) || + ((source + ((header >> 8) & 0x1fffff)) & 0xe000000) == 0) + return 0; + + treeSize = MMU_read8(cpu->proc_ID, source++); + + treeStart = source; + + source += ((treeSize+1)<<1)-1; // minus because we already skipped one byte + + len = header >> 8; + + mask = 0x80000000; + data = MMU_read8(cpu->proc_ID, source); + source += 4; + + pos = 0; + rootNode = MMU_read8(cpu->proc_ID, treeStart); + currentNode = rootNode; + writeData = 0; + byteShift = 0; + byteCount = 0; + writeValue = 0; + + if((header & 0x0F) == 8) { + while(len > 0) { + // take left + if(pos == 0) + pos++; + else + pos += (((currentNode & 0x3F)+1)<<1); + + if(data & mask) { + // right + if(currentNode & 0x40) + writeData = 1; + currentNode = MMU_read8(cpu->proc_ID, treeStart+pos+1); + } else { + // left + if(currentNode & 0x80) + writeData = 1; + currentNode = MMU_read8(cpu->proc_ID, treeStart+pos); + } + + if(writeData) { + writeValue |= (currentNode << byteShift); + byteCount++; + byteShift += 8; + + pos = 0; + currentNode = rootNode; + writeData = 0; + + if(byteCount == 4) { + byteCount = 0; + byteShift = 0; + MMU_write8(cpu->proc_ID, dest, writeValue); + writeValue = 0; + dest += 4; + len -= 4; + } + } + mask >>= 1; + if(mask == 0) { + mask = 0x80000000; + data = MMU_read8(cpu->proc_ID, source); + source += 4; + } + } + } else { + int halfLen = 0; + int value = 0; + while(len > 0) { + // take left + if(pos == 0) + pos++; + else + pos += (((currentNode & 0x3F)+1)<<1); + + if((data & mask)) { + // right + if(currentNode & 0x40) + writeData = 1; + currentNode = MMU_read8(cpu->proc_ID, treeStart+pos+1); + } else { + // left + if(currentNode & 0x80) + writeData = 1; + currentNode = MMU_read8(cpu->proc_ID, treeStart+pos); + } + + if(writeData) { + if(halfLen == 0) + value |= currentNode; + else + value |= (currentNode<<4); + + halfLen += 4; + if(halfLen == 8) { + writeValue |= (value << byteShift); + byteCount++; + byteShift += 8; + + halfLen = 0; + value = 0; + + if(byteCount == 4) { + byteCount = 0; + byteShift = 0; + MMU_write8(cpu->proc_ID, dest, writeValue); + dest += 4; + writeValue = 0; + len -= 4; + } + } + pos = 0; + currentNode = rootNode; + writeData = 0; + } + mask >>= 1; + if(mask == 0) { + mask = 0x80000000; + data = MMU_read8(cpu->proc_ID, source); + source += 4; + } + } + } + return 1; +} + +u32 BitUnPack(armcpu_t* cpu) +{ + u32 source,dest,header,base,d,temp; + int len,bits,revbits,dataSize,data,bitwritecount,mask,bitcount,addBase; + u8 b; + + source = cpu->R[0]; + dest = cpu->R[1]; + header = cpu->R[2]; + + len = MMU_read16(cpu->proc_ID, header); + // check address + bits = MMU_read8(cpu->proc_ID, header+2); + revbits = 8 - bits; + // u32 value = 0; + base = MMU_read8(cpu->proc_ID, header+4); + addBase = (base & 0x80000000) ? 1 : 0; + base &= 0x7fffffff; + dataSize = MMU_read8(cpu->proc_ID, header+3); + + data = 0; + bitwritecount = 0; + while(1) { + len -= 1; + if(len < 0) + break; + mask = 0xff >> revbits; + b = MMU_read8(cpu->proc_ID, source); + source++; + bitcount = 0; + while(1) { + if(bitcount >= 8) + break; + d = b & mask; + temp = d >> bitcount; + if(!temp && addBase) { + temp += base; + } + data |= temp << bitwritecount; + bitwritecount += dataSize; + if(bitwritecount >= 32) { + MMU_write8(cpu->proc_ID, dest, data); + dest += 4; + data = 0; + bitwritecount = 0; + } + mask <<= bits; + bitcount += bits; + } + } + return 1; +} + +u32 Diff8bitUnFilterWram(armcpu_t* cpu) +{ + u32 source,dest,header; + u8 data,diff; + int len; + + source = cpu->R[0]; + dest = cpu->R[1]; + + header = MMU_read8(cpu->proc_ID, source); + source += 4; + + if(((source & 0xe000000) == 0) || + (( (source + ((header >> 8) & 0x1fffff)) & 0xe000000) == 0)) + return 0; + + len = header >> 8; + + data = MMU_read8(cpu->proc_ID, source++); + MMU_write8(cpu->proc_ID, dest++, data); + len--; + + while(len > 0) { + diff = MMU_read8(cpu->proc_ID, source++); + data += diff; + MMU_write8(cpu->proc_ID, dest++, data); + len--; + } + return 1; +} + +u32 Diff16bitUnFilter(armcpu_t* cpu) +{ + u32 source,dest,header; + u16 data; + int len; + + source = cpu->R[0]; + dest = cpu->R[1]; + + header = MMU_read8(cpu->proc_ID, source); + source += 4; + + if(((source & 0xe000000) == 0) || + ((source + ((header >> 8) & 0x1fffff)) & 0xe000000) == 0) + return 0; + + len = header >> 8; + + data = MMU_read16(cpu->proc_ID, source); + source += 2; + MMU_write16(cpu->proc_ID, dest, data); + dest += 2; + len -= 2; + + while(len >= 2) { + u16 diff = MMU_read16(cpu->proc_ID, source); + source += 2; + data += diff; + MMU_write16(cpu->proc_ID, dest, data); + dest += 2; + len -= 2; + } + return 1; +} + +u32 bios_sqrt(armcpu_t* cpu) +{ + cpu->R[0] = (u32)sqrt((double)(cpu->R[0])); + return 1; +} + +u32 setHaltCR(armcpu_t* cpu) +{ + MMU_write8(cpu->proc_ID, 0x4000300+cpu->proc_ID, cpu->R[0]); + return 1; +} + +u32 getSineTab(armcpu_t* cpu) +{ + cpu->R[0] = getsinetbl[cpu->R[0]]; + return 1; +} + +u32 getPitchTab(armcpu_t* cpu) +{ + cpu->R[0] = getpitchtbl[cpu->R[0]]; + return 1; +} + +u32 getVolumeTab(armcpu_t* cpu) +{ + cpu->R[0] = getvoltbl[cpu->R[0]]; + return 1; +} + +u32 getCRC16(armcpu_t* cpu) +{ + unsigned int i,j; + + u32 crc = cpu->R[0]; + u32 datap = cpu->R[1]; + u32 size = cpu->R[2]; + + static u16 val[] = { 0xC0C1,0xC181,0xC301,0xC601,0xCC01,0xD801,0xF001,0xA001 }; + for(i = 0; i < size; i++) + { + crc = crc ^ MMU_read8( cpu->proc_ID, datap + i); + + for(j = 0; j < 8; j++) { + int do_bit = 0; + + if ( crc & 0x1) + do_bit = 1; + + crc = crc >> 1; + + if ( do_bit) { + crc = crc ^ (val[j] << (7-j)); + } + } + } + cpu->R[0] = crc; + return 1; +} + +u32 SoundBias(armcpu_t* cpu) +{ + u32 current = SPU_ReadLong(0x4000504); + if (cpu->R[0] > current) + SPU_WriteLong(0x4000504, current + 0x1); + else + SPU_WriteLong(0x4000504, current - 0x1); + return cpu->R[1]; +} + +u32 (* ARM9_swi_tab[32])(armcpu_t* cpu)={ + bios_nop, // 0x00 + bios_nop, // 0x01 + bios_nop, // 0x02 + delayLoop, // 0x03 + intrWaitARM, // 0x04 + waitVBlankARM, // 0x05 + wait4IRQ, // 0x06 + bios_nop, // 0x07 + bios_nop, // 0x08 + devide, // 0x09 + bios_nop, // 0x0A + copy, // 0x0B + fastCopy, // 0x0C + bios_sqrt, // 0x0D + getCRC16, // 0x0E + bios_nop, // 0x0F + BitUnPack, // 0x10 + LZ77UnCompWram, // 0x11 + LZ77UnCompVram, // 0x12 + UnCompHuffman, // 0x13 + RLUnCompWram, // 0x14 + RLUnCompVram, // 0x15 + Diff8bitUnFilterWram, // 0x16 + bios_nop, // 0x17 + Diff16bitUnFilter, // 0x18 + bios_nop, // 0x19 + bios_nop, // 0x1A + bios_nop, // 0x1B + bios_nop, // 0x1C + bios_nop, // 0x1D + bios_nop, // 0x1E + setHaltCR, // 0x1F +}; + +u32 (* ARM7_swi_tab[32])(armcpu_t* cpu)={ + bios_nop, // 0x00 + bios_nop, // 0x01 + bios_nop, // 0x02 + delayLoop, // 0x03 + intrWaitARM, // 0x04 + waitVBlankARM, // 0x05 + wait4IRQ, // 0x06 + wait4IRQ, // 0x07 + SoundBias, // 0x08 + devide, // 0x09 + bios_nop, // 0x0A + copy, // 0x0B + fastCopy, // 0x0C + bios_sqrt, // 0x0D + getCRC16, // 0x0E + bios_nop, // 0x0F + BitUnPack, // 0x10 + LZ77UnCompWram, // 0x11 + LZ77UnCompVram, // 0x12 + UnCompHuffman, // 0x13 + RLUnCompWram, // 0x14 + RLUnCompVram, // 0x15 + Diff8bitUnFilterWram, // 0x16 + bios_nop, // 0x17 + bios_nop, // 0x18 + bios_nop, // 0x19 + getSineTab, // 0x1A + getPitchTab, // 0x1B + getVolumeTab, // 0x1C + bios_nop, // 0x1D + bios_nop, // 0x1E + setHaltCR, // 0x1F +}; diff -r fe2ba1a712cd -r 70b0973e7b70 src/xsf/desmume/bios.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/xsf/desmume/bios.h Thu Oct 16 14:45:41 2008 -0500 @@ -0,0 +1,32 @@ +/* Copyright (C) 2006 yopyop + yopyop156@ifrance.com + yopyop156.ifrance.com + + This file is part of DeSmuME + + DeSmuME is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DeSmuME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DeSmuME; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef BIOS_H +#define BIOS_H + +#include "armcpu.h" + +extern u32 (* ARM9_swi_tab[32])(armcpu_t * cpu); +extern u32 (* ARM7_swi_tab[32])(armcpu_t * cpu); +extern u32 wait4IRQ(armcpu_t * cpu); + +#endif + diff -r fe2ba1a712cd -r 70b0973e7b70 src/xsf/desmume/bits.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/xsf/desmume/bits.h Thu Oct 16 14:45:41 2008 -0500 @@ -0,0 +1,44 @@ +#ifndef BITS_H +#define BITS_H + +#define BIT(n) (1<<(n)) + +#define BIT_N(i,n) (((i)>>(n))&1) +#define BIT0(i) ((i)&1) +#define BIT1(i) BIT_N(i,1) +#define BIT2(i) BIT_N(i,2) +#define BIT3(i) BIT_N(i,3) +#define BIT4(i) BIT_N(i,4) +#define BIT5(i) BIT_N(i,5) +#define BIT6(i) BIT_N(i,6) +#define BIT7(i) BIT_N(i,7) +#define BIT8(i) BIT_N(i,8) +#define BIT9(i) BIT_N(i,9) +#define BIT10(i) BIT_N(i,10) +#define BIT11(i) BIT_N(i,11) +#define BIT12(i) BIT_N(i,12) +#define BIT13(i) BIT_N(i,13) +#define BIT14(i) BIT_N(i,14) +#define BIT15(i) BIT_N(i,15) +#define BIT16(i) BIT_N(i,16) +#define BIT17(i) BIT_N(i,17) +#define BIT18(i) BIT_N(i,18) +#define BIT19(i) BIT_N(i,19) +#define BIT20(i) BIT_N(i,20) +#define BIT21(i) BIT_N(i,21) +#define BIT22(i) BIT_N(i,22) +#define BIT23(i) BIT_N(i,23) +#define BIT24(i) BIT_N(i,24) +#define BIT25(i) BIT_N(i,25) +#define BIT26(i) BIT_N(i,26) +#define BIT27(i) BIT_N(i,27) +#define BIT28(i) BIT_N(i,28) +#define BIT29(i) BIT_N(i,29) +#define BIT30(i) BIT_N(i,30) +#define BIT31(i) ((i)>>31) + +#define CONDITION(i) (i)>>28 + +#define REG_POS(i,n) (((i)>>n)&0xF) + +#endif diff -r fe2ba1a712cd -r 70b0973e7b70 src/xsf/desmume/config.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/xsf/desmume/config.h Thu Oct 16 14:45:41 2008 -0500 @@ -0,0 +1,28 @@ +/* Copyright (C) 2006 thoduv + + This file is part of DeSmuME + + DeSmuME is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DeSmuME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DeSmuME; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef __CONFIG_H__ +#define __CONFIG_H__ + +#include + +#include "debug.h" + +#endif /*__CONFIG_H__*/ + diff -r fe2ba1a712cd -r 70b0973e7b70 src/xsf/desmume/cp15.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/xsf/desmume/cp15.c Thu Oct 16 14:45:41 2008 -0500 @@ -0,0 +1,590 @@ +/* Copyright (C) 2006 yopyop + yopyop156@ifrance.com + yopyop156.ifrance.com + + This file is part of DeSmuME + + DeSmuME is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DeSmuME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DeSmuME; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include + +#include "cp15.h" +#include "debug.h" +#include "MMU.h" + +armcp15_t *armcp15_new(armcpu_t * c) +{ + int i; + armcp15_t *armcp15 = (armcp15_t*)malloc(sizeof(armcp15_t)); + if(!armcp15) return NULL; + + armcp15->cpu = c; + armcp15->IDCode = 0x41049460; + armcp15->cacheType = 0x0F0D2112; + armcp15->TCMSize = 0x00140140; + armcp15->ctrl = 0x00000000; + armcp15->DCConfig = 0x0; + armcp15->ICConfig = 0x0; + armcp15->writeBuffCtrl = 0x0; + armcp15->und = 0x0; + armcp15->DaccessPerm = 0x22222222; + armcp15->IaccessPerm = 0x22222222; + armcp15->protectBaseSize0 = 0x0; + armcp15->protectBaseSize1 = 0x0; + armcp15->protectBaseSize2 = 0x0; + armcp15->protectBaseSize3 = 0x0; + armcp15->protectBaseSize4 = 0x0; + armcp15->protectBaseSize5 = 0x0; + armcp15->protectBaseSize6 = 0x0; + armcp15->protectBaseSize7 = 0x0; + armcp15->cacheOp = 0x0; + armcp15->DcacheLock = 0x0; + armcp15->IcacheLock = 0x0; + armcp15->ITCMRegion = 0x0C; + armcp15->DTCMRegion = 0x0080000A; + armcp15->processID = 0; + + /* preset calculated regionmasks */ + for (i=0;i<8;i++) { + armcp15->regionWriteMask_USR[i] = 0 ; + armcp15->regionWriteMask_SYS[i] = 0 ; + armcp15->regionReadMask_USR[i] = 0 ; + armcp15->regionReadMask_SYS[i] = 0 ; + armcp15->regionExecuteMask_USR[i] = 0 ; + armcp15->regionExecuteMask_SYS[i] = 0 ; + armcp15->regionWriteSet_USR[i] = 0 ; + armcp15->regionWriteSet_SYS[i] = 0 ; + armcp15->regionReadSet_USR[i] = 0 ; + armcp15->regionReadSet_SYS[i] = 0 ; + armcp15->regionExecuteSet_USR[i] = 0 ; + armcp15->regionExecuteSet_SYS[i] = 0 ; + } ; + + return armcp15; +} + +#define ACCESSTYPE(val,n) (((val) >> (4*n)) & 0x0F) +#define SIZEIDENTIFIER(val) ((((val) >> 1) & 0x1F)) +#define SIZEBINARY(val) (1 << (SIZEIDENTIFIER(val)+1)) +#define MASKFROMREG(val) (~((SIZEBINARY(val)-1) | 0x3F)) +#define SETFROMREG(val) ((val) & MASKFROMREG(val)) +/* sets the precalculated regions to mask,set for the affected accesstypes */ +void armcp15_setSingleRegionAccess(armcp15_t *armcp15,unsigned long dAccess,unsigned long iAccess,unsigned char num, unsigned long mask,unsigned long set) { + + switch (ACCESSTYPE(dAccess,num)) { + case 4: /* UNP */ + case 7: /* UNP */ + case 8: /* UNP */ + case 9: /* UNP */ + case 10: /* UNP */ + case 11: /* UNP */ + case 12: /* UNP */ + case 13: /* UNP */ + case 14: /* UNP */ + case 15: /* UNP */ + case 0: /* no access at all */ + armcp15->regionWriteMask_USR[num] = 0 ; + armcp15->regionWriteSet_USR[num] = 0xFFFFFFFF ; + armcp15->regionReadMask_USR[num] = 0 ; + armcp15->regionReadSet_USR[num] = 0xFFFFFFFF ; + armcp15->regionWriteMask_SYS[num] = 0 ; + armcp15->regionWriteSet_SYS[num] = 0xFFFFFFFF ; + armcp15->regionReadMask_SYS[num] = 0 ; + armcp15->regionReadSet_SYS[num] = 0xFFFFFFFF ; + break ; + case 1: /* no access at USR, all to sys */ + armcp15->regionWriteMask_USR[num] = 0 ; + armcp15->regionWriteSet_USR[num] = 0xFFFFFFFF ; + armcp15->regionReadMask_USR[num] = 0 ; + armcp15->regionReadSet_USR[num] = 0xFFFFFFFF ; + armcp15->regionWriteMask_SYS[num] = mask ; + armcp15->regionWriteSet_SYS[num] = set ; + armcp15->regionReadMask_SYS[num] = mask ; + armcp15->regionReadSet_SYS[num] = set ; + break ; + case 2: /* read at USR, all to sys */ + armcp15->regionWriteMask_USR[num] = 0 ; + armcp15->regionWriteSet_USR[num] = 0xFFFFFFFF ; + armcp15->regionReadMask_USR[num] = mask ; + armcp15->regionReadSet_USR[num] = set ; + armcp15->regionWriteMask_SYS[num] = mask ; + armcp15->regionWriteSet_SYS[num] = set ; + armcp15->regionReadMask_SYS[num] = mask ; + armcp15->regionReadSet_SYS[num] = set ; + break ; + case 3: /* all to USR, all to sys */ + armcp15->regionWriteMask_USR[num] = mask ; + armcp15->regionWriteSet_USR[num] = set ; + armcp15->regionReadMask_USR[num] = mask ; + armcp15->regionReadSet_USR[num] = set ; + armcp15->regionWriteMask_SYS[num] = mask ; + armcp15->regionWriteSet_SYS[num] = set ; + armcp15->regionReadMask_SYS[num] = mask ; + armcp15->regionReadSet_SYS[num] = set ; + break ; + case 5: /* no access at USR, read to sys */ + armcp15->regionWriteMask_USR[num] = 0 ; + armcp15->regionWriteSet_USR[num] = 0xFFFFFFFF ; + armcp15->regionReadMask_USR[num] = 0 ; + armcp15->regionReadSet_USR[num] = 0xFFFFFFFF ; + armcp15->regionWriteMask_SYS[num] = 0 ; + armcp15->regionWriteSet_SYS[num] = 0xFFFFFFFF ; + armcp15->regionReadMask_SYS[num] = mask ; + armcp15->regionReadSet_SYS[num] = set ; + break ; + case 6: /* read at USR, read to sys */ + armcp15->regionWriteMask_USR[num] = 0 ; + armcp15->regionWriteSet_USR[num] = 0xFFFFFFFF ; + armcp15->regionReadMask_USR[num] = mask ; + armcp15->regionReadSet_USR[num] = set ; + armcp15->regionWriteMask_SYS[num] = 0 ; + armcp15->regionWriteSet_SYS[num] = 0xFFFFFFFF ; + armcp15->regionReadMask_SYS[num] = mask ; + armcp15->regionReadSet_SYS[num] = set ; + break ; + } + switch (ACCESSTYPE(iAccess,num)) { + case 4: /* UNP */ + case 7: /* UNP */ + case 8: /* UNP */ + case 9: /* UNP */ + case 10: /* UNP */ + case 11: /* UNP */ + case 12: /* UNP */ + case 13: /* UNP */ + case 14: /* UNP */ + case 15: /* UNP */ + case 0: /* no access at all */ + armcp15->regionExecuteMask_USR[num] = 0 ; + armcp15->regionExecuteSet_USR[num] = 0xFFFFFFFF ; + armcp15->regionExecuteMask_SYS[num] = 0 ; + armcp15->regionExecuteSet_SYS[num] = 0xFFFFFFFF ; + break ; + case 1: + armcp15->regionExecuteMask_USR[num] = 0 ; + armcp15->regionExecuteSet_USR[num] = 0xFFFFFFFF ; + armcp15->regionExecuteMask_SYS[num] = mask ; + armcp15->regionExecuteSet_SYS[num] = set ; + break ; + case 2: + case 3: + case 6: + armcp15->regionExecuteMask_USR[num] = mask ; + armcp15->regionExecuteSet_USR[num] = set ; + armcp15->regionExecuteMask_SYS[num] = mask ; + armcp15->regionExecuteSet_SYS[num] = set ; + break ; + } +} ; + +/* precalculate region masks/sets from cp15 register */ +void armcp15_maskPrecalc(armcp15_t *armcp15) +{ + #define precalc(num) { \ + u32 mask = 0, set = 0xFFFFFFFF ; /* (x & 0) == 0xFF..FF is allways false (disabled) */ \ + if (BIT_N(armcp15->protectBaseSize##num,0)) /* if region is enabled */ \ + { /* reason for this define: naming includes var */ \ + mask = MASKFROMREG(armcp15->protectBaseSize##num) ; \ + set = SETFROMREG(armcp15->protectBaseSize##num) ; \ + if (SIZEIDENTIFIER(armcp15->protectBaseSize##num)==0x1F) \ + { /* for the 4GB region, u32 suffers wraparound */ \ + mask = 0 ; set = 0 ; /* (x & 0) == 0 is allways true (enabled) */ \ + } \ + } \ + armcp15_setSingleRegionAccess(armcp15,armcp15->DaccessPerm,armcp15->IaccessPerm,num,mask,set) ; \ + } + precalc(0) ; + precalc(1) ; + precalc(2) ; + precalc(3) ; + precalc(4) ; + precalc(5) ; + precalc(6) ; + precalc(7) ; +} + +INLINE BOOL armcp15_isAccessAllowed(armcp15_t *armcp15,u32 address,u32 access) +{ + int i ; + if (!(armcp15->ctrl & 1)) return TRUE ; /* protection checking is not enabled */ + for (i=0;i<8;i++) { + switch (access) { + case CP15_ACCESS_WRITEUSR: + if ((address & armcp15->regionWriteMask_USR[i]) == armcp15->regionWriteSet_USR[i]) return TRUE ; + break ; + case CP15_ACCESS_WRITESYS: + if ((address & armcp15->regionWriteMask_SYS[i]) == armcp15->regionWriteSet_SYS[i]) return TRUE ; + break ; + case CP15_ACCESS_READUSR: + if ((address & armcp15->regionReadMask_USR[i]) == armcp15->regionReadSet_USR[i]) return TRUE ; + break ; + case CP15_ACCESS_READSYS: + if ((address & armcp15->regionReadMask_SYS[i]) == armcp15->regionReadSet_SYS[i]) return TRUE ; + break ; + case CP15_ACCESS_EXECUSR: + if ((address & armcp15->regionExecuteMask_USR[i]) == armcp15->regionExecuteSet_USR[i]) return TRUE ; + break ; + case CP15_ACCESS_EXECSYS: + if ((address & armcp15->regionExecuteMask_SYS[i]) == armcp15->regionExecuteSet_SYS[i]) return TRUE ; + break ; + } + } + /* when protections are enabled, but no region allows access, deny access */ + return FALSE ; +} + +BOOL armcp15_dataProcess(armcp15_t *armcp15, u8 CRd, u8 CRn, u8 CRm, u8 opcode1, u8 opcode2) +{ + return FALSE; +} + +BOOL armcp15_load(armcp15_t *armcp15, u8 CRd, u8 adr) +{ + return FALSE; +} + +BOOL armcp15_store(armcp15_t *armcp15, u8 CRd, u8 adr) +{ + return FALSE; +} + +BOOL armcp15_moveCP2ARM(armcp15_t *armcp15, u32 * R, u8 CRn, u8 CRm, u8 opcode1, u8 opcode2) +{ + if(armcp15->cpu->CPSR.bits.mode == USR) return FALSE; + + switch(CRn) + { + case 0 : + if((opcode1 == 0)&&(CRm==0)) + { + switch(opcode2) + { + case 1 : + *R = armcp15->cacheType; + return TRUE; + case 2 : + *R = armcp15->TCMSize; + return TRUE; + default : + *R = armcp15->IDCode; + return TRUE; + } + } + return FALSE; + case 1 : + if((opcode1==0) && (opcode2==0) && (CRm==0)) + { + *R = armcp15->ctrl; + return TRUE; + } + return FALSE; + + case 2 : + if((opcode1==0) && (CRm==0)) + { + switch(opcode2) + { + case 0 : + *R = armcp15->DCConfig; + return TRUE; + case 1 : + *R = armcp15->ICConfig; + return TRUE; + default : + return FALSE; + } + } + return FALSE; + case 3 : + if((opcode1==0) && (opcode2==0) && (CRm==0)) + { + *R = armcp15->writeBuffCtrl; + return TRUE; + } + return FALSE; + case 5 : + if((opcode1==0) && (CRm==0)) + { + switch(opcode2) + { + case 2 : + *R = armcp15->DaccessPerm; + return TRUE; + case 3 : + *R = armcp15->IaccessPerm; + return TRUE; + default : + return FALSE; + } + } + return FALSE; + case 6 : + if((opcode1==0) && (opcode2==0)) + { + switch(CRm) + { + case 0 : + *R = armcp15->protectBaseSize0; + return TRUE; + case 1 : + *R = armcp15->protectBaseSize1; + return TRUE; + case 2 : + *R = armcp15->protectBaseSize2; + return TRUE; + case 3 : + *R = armcp15->protectBaseSize3; + return TRUE; + case 4 : + *R = armcp15->protectBaseSize4; + return TRUE; + case 5 : + *R = armcp15->protectBaseSize5; + return TRUE; + case 6 : + *R = armcp15->protectBaseSize6; + return TRUE; + case 7 : + *R = armcp15->protectBaseSize7; + return TRUE; + default : + return FALSE; + } + } + return FALSE; + case 9 : + if((opcode1==0)) + { + switch(CRm) + { + case 0 : + switch(opcode2) + { + case 0 : + *R = armcp15->DcacheLock; + return TRUE; + case 1 : + *R = armcp15->IcacheLock; + return TRUE; + default : + return FALSE; + } + case 1 : + switch(opcode2) + { + case 0 : + *R = armcp15->DTCMRegion; + return TRUE; + case 1 : + *R = armcp15->ITCMRegion; + return TRUE; + default : + return FALSE; + } + } + } + return FALSE; + default : + return FALSE; + } +} + + +u32 CP15wait4IRQ(armcpu_t *cpu) +{ + /* on the first call, wirq is not set */ + if(cpu->wirq) + { + /* check wether an irq was issued */ + if(!cpu->waitIRQ) + { + cpu->waitIRQ = 0; + cpu->wirq = 0; + return 1; /* return execution */ + } + /* otherwise, repeat this instruction */ + cpu->R[15] = cpu->instruct_adr; + cpu->next_instruction = cpu->R[15]; + return 1; + } + /* first run, set us into waiting state */ + cpu->waitIRQ = 1; + cpu->wirq = 1; + /* and set next instruction to repeat this */ + cpu->R[15] = cpu->instruct_adr; + cpu->next_instruction = cpu->R[15]; + /* CHECKME: IME shouldn't be modified (?) */ + MMU.reg_IME[0] = 1; + return 1; +} + +BOOL armcp15_moveARM2CP(armcp15_t *armcp15, u32 val, u8 CRn, u8 CRm, u8 opcode1, u8 opcode2) +{ + if(armcp15->cpu->CPSR.bits.mode == USR) return FALSE; + + switch(CRn) + { + case 1 : + if((opcode1==0) && (opcode2==0) && (CRm==0)) + { + armcp15->ctrl = val; + MMU.ARM9_RW_MODE = BIT7(val); + armcp15->cpu->intVector = 0x0FFF0000 * (BIT13(val)); + armcp15->cpu->LDTBit = !BIT15(val); //TBit + /*if(BIT17(val)) + { + log::ajouter("outch !!!!!!!"); + } + if(BIT19(val)) + { + log::ajouter("outch !!!!!!!"); + }*/ + return TRUE; + } + return FALSE; + case 2 : + if((opcode1==0) && (CRm==0)) + { + switch(opcode2) + { + case 0 : + armcp15->DCConfig = val; + return TRUE; + case 1 : + armcp15->ICConfig = val; + return TRUE; + default : + return FALSE; + } + } + return FALSE; + case 3 : + if((opcode1==0) && (opcode2==0) && (CRm==0)) + { + armcp15->writeBuffCtrl = val; + return TRUE; + } + return FALSE; + if((opcode1==0) && (CRm==0)) + { + switch(opcode2) + { + case 2 : + armcp15->DaccessPerm = val; + armcp15_maskPrecalc(armcp15); + return TRUE; + case 3 : + armcp15->IaccessPerm = val; + armcp15_maskPrecalc(armcp15); + return TRUE; + default : + return FALSE; + } + } + return FALSE; + case 6 : + if((opcode1==0) && (opcode2==0)) + { + switch(CRm) + { + case 0 : + armcp15->protectBaseSize0 = val; + armcp15_maskPrecalc(armcp15) ; + return TRUE; + case 1 : + armcp15->protectBaseSize1 = val; + armcp15_maskPrecalc(armcp15) ; + return TRUE; + case 2 : + armcp15->protectBaseSize2 = val; + armcp15_maskPrecalc(armcp15) ; + return TRUE; + case 3 : + armcp15->protectBaseSize3 = val; + armcp15_maskPrecalc(armcp15) ; + return TRUE; + case 4 : + armcp15->protectBaseSize4 = val; + armcp15_maskPrecalc(armcp15) ; + return TRUE; + case 5 : + armcp15->protectBaseSize5 = val; + armcp15_maskPrecalc(armcp15) ; + return TRUE; + case 6 : + armcp15->protectBaseSize6 = val; + armcp15_maskPrecalc(armcp15) ; + return TRUE; + case 7 : + armcp15->protectBaseSize7 = val; + armcp15_maskPrecalc(armcp15) ; + return TRUE; + default : + return FALSE; + } + } + return FALSE; + case 7 : + if((CRm==0)&&(opcode1==0)&&((opcode2==4))) + { + CP15wait4IRQ(armcp15->cpu); + return TRUE; + } + return FALSE; + case 9 : + if((opcode1==0)) + { + switch(CRm) + { + case 0 : + switch(opcode2) + { + case 0 : + armcp15->DcacheLock = val; + return TRUE; + case 1 : + armcp15->IcacheLock = val; + return TRUE; + default : + return FALSE; + } + case 1 : + switch(opcode2) + { + case 0 : + armcp15->DTCMRegion = val; + MMU.DTCMRegion = val & 0x0FFFFFFC0; + /*sprintf(logbuf, "%08X", val); + log::ajouter(logbuf);*/ + return TRUE; + case 1 : + armcp15->ITCMRegion = val; + /* ITCM base is not writeable! */ + MMU.ITCMRegion = 0; + return TRUE; + default : + return FALSE; + } + } + } + return FALSE; + default : + return FALSE; + } +} + + + diff -r fe2ba1a712cd -r 70b0973e7b70 src/xsf/desmume/cp15.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/xsf/desmume/cp15.h Thu Oct 16 14:45:41 2008 -0500 @@ -0,0 +1,94 @@ +/* Copyright (C) 2006 yopyop + yopyop156@ifrance.com + yopyop156.ifrance.com + + This file is part of DeSmuME + + DeSmuME is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DeSmuME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DeSmuME; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef __CP15_H__ +#define __CP15_H__ + +#include "armcpu.h" + +typedef struct +{ + u32 IDCode; + u32 cacheType; + u32 TCMSize; + u32 ctrl; + u32 DCConfig; + u32 ICConfig; + u32 writeBuffCtrl; + u32 und; + u32 DaccessPerm; + u32 IaccessPerm; + u32 protectBaseSize0; + u32 protectBaseSize1; + u32 protectBaseSize2; + u32 protectBaseSize3; + u32 protectBaseSize4; + u32 protectBaseSize5; + u32 protectBaseSize6; + u32 protectBaseSize7; + u32 cacheOp; + u32 DcacheLock; + u32 IcacheLock; + u32 ITCMRegion; + u32 DTCMRegion; + u32 processID; + u32 RAM_TAG; + u32 testState; + u32 cacheDbg; + /* calculated bitmasks for the regions to decide rights uppon */ + /* calculation is done in the MCR instead of on mem access for performance */ + u32 regionWriteMask_USR[8] ; + u32 regionWriteMask_SYS[8] ; + u32 regionReadMask_USR[8] ; + u32 regionReadMask_SYS[8] ; + u32 regionExecuteMask_USR[8] ; + u32 regionExecuteMask_SYS[8] ; + u32 regionWriteSet_USR[8] ; + u32 regionWriteSet_SYS[8] ; + u32 regionReadSet_USR[8] ; + u32 regionReadSet_SYS[8] ; + u32 regionExecuteSet_USR[8] ; + u32 regionExecuteSet_SYS[8] ; + + armcpu_t * cpu; + +} armcp15_t; + +armcp15_t *armcp15_new(armcpu_t *c); +BOOL armcp15_dataProcess(armcp15_t *armcp15, u8 CRd, u8 CRn, u8 CRm, u8 opcode1, u8 opcode2); +BOOL armcp15_load(armcp15_t *armcp15, u8 CRd, u8 adr); +BOOL armcp15_store(armcp15_t *armcp15, u8 CRd, u8 adr); +BOOL armcp15_moveCP2ARM(armcp15_t *armcp15, u32 * R, u8 CRn, u8 CRm, u8 opcode1, u8 opcode2); +BOOL armcp15_moveARM2CP(armcp15_t *armcp15, u32 val, u8 CRn, u8 CRm, u8 opcode1, u8 opcode2); +INLINE BOOL armcp15_isAccessAllowed(armcp15_t *armcp15,u32 address,u32 access) ; + + +#define CP15_ACCESS_WRITE 0 +#define CP15_ACCESS_READ 2 +#define CP15_ACCESS_EXECUTE 4 +#define CP15_ACCESS_WRITEUSR CP15_ACCESS_WRITE +#define CP15_ACCESS_WRITESYS 1 +#define CP15_ACCESS_READUSR CP15_ACCESS_READ +#define CP15_ACCESS_READSYS 3 +#define CP15_ACCESS_EXECUSR CP15_ACCESS_EXECUTE +#define CP15_ACCESS_EXECSYS 5 + +#endif /* __CP15_H__*/ diff -r fe2ba1a712cd -r 70b0973e7b70 src/xsf/desmume/debug.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/xsf/desmume/debug.h Thu Oct 16 14:45:41 2008 -0500 @@ -0,0 +1,11 @@ +#ifndef DEBUG_H +#define DEBUG_H + +#define LOG(...) +#define GPULOG(...) +#define DIVLOG(...) +#define SQRTLOG(...) +#define CARDLOG(...) +#define DMALOG(...) + +#endif diff -r fe2ba1a712cd -r 70b0973e7b70 src/xsf/desmume/dscard.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/xsf/desmume/dscard.h Thu Oct 16 14:45:41 2008 -0500 @@ -0,0 +1,34 @@ +/* Copyright (C) 2006 thoduv + + This file is part of DeSmuME + + DeSmuME is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DeSmuME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DeSmuME; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef __DSCARD_H__ +#define __DSCARD_H__ + +typedef struct +{ + + u32 adress; + u32 transfer_count; + +} nds_dscard; + +#endif /*__DSCARD_H__*/ + + + diff -r fe2ba1a712cd -r 70b0973e7b70 src/xsf/desmume/instruction_tabdef.inc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/xsf/desmume/instruction_tabdef.inc Thu Oct 16 14:45:41 2008 -0500 @@ -0,0 +1,4400 @@ +/* Copyright (C) 2006 yopyop + yopyop156@ifrance.com + yopyop156.ifrance.com + + This file is part of DeSmuME + + DeSmuME is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DeSmuME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DeSmuME; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +TYPE_RETOUR (*CALLTYPE NOM_TAB[4096])(PARAMETRES)={ + OP_AND_LSL_IMM, // 000 0000 0 0000 + OP_AND_LSL_REG, // 000 0000 0 0001 + OP_AND_LSR_IMM, // 000 0000 0 0010 + OP_AND_LSR_REG, // 000 0000 0 0011 + OP_AND_ASR_IMM, // 000 0000 0 0100 + OP_AND_ASR_REG, // 000 0000 0 0101 + OP_AND_ROR_IMM, // 000 0000 0 0110 + OP_AND_ROR_REG, // 000 0000 0 0111 + + OP_AND_LSL_IMM, // 000 0000 0 1000 + OP_MUL, // 000 0000 0 1001 + OP_AND_LSR_IMM, // OOO OOOO O 1010 + OP_STRH_POS_INDE_M_REG_OFF, // 000 0000 0 1011 + OP_AND_ASR_IMM, // 000 0000 0 1100 + OP_LDRD_STRD_POST_INDEX, + // 000 0000 0 1101 + OP_AND_ROR_IMM, // 000 0000 0 1110 + OP_LDRD_STRD_POST_INDEX, + // 000 0000 0 1111 + + OP_AND_S_LSL_IMM, // 000 0000 1 0000 + OP_AND_S_LSL_REG, // 000 0000 1 0001 + OP_AND_S_LSR_IMM, // 000 0000 1 0010 + OP_AND_S_LSR_REG, // 000 0000 1 0011 + OP_AND_S_ASR_IMM, // 000 0000 1 0100 + OP_AND_S_ASR_REG, // 000 0000 1 0101 + OP_AND_S_ROR_IMM, // 000 0000 1 0110 + OP_AND_S_ROR_REG, // 000 0000 1 0111 + + OP_AND_S_LSL_IMM, // 000 0000 1 1000 + OP_MUL_S, // 000 0000 1 1001 + OP_AND_S_LSR_IMM, // 000 0000 1 1010 + OP_LDRH_POS_INDE_M_REG_OFF, // 000 0000 1 1011 + OP_AND_S_ASR_IMM, // 000 0000 1 1100 + OP_LDRSB_POS_INDE_M_REG_OFF,// 000 0000 1 1101 + OP_AND_S_ROR_IMM, // 000 0000 1 1110 + OP_LDRSH_POS_INDE_M_REG_OFF,// 000 0000 1 1111 + + OP_EOR_LSL_IMM, // 000 0001 0 0000 + OP_EOR_LSL_REG, // 000 0001 0 0001 + OP_EOR_LSR_IMM, // 000 0001 0 0010 + OP_EOR_LSR_REG, // 000 0001 0 0011 + OP_EOR_ASR_IMM, // 000 0001 0 0100 + OP_EOR_ASR_REG, // 000 0001 0 0101 + OP_EOR_ROR_IMM, // 000 0001 0 0110 + OP_EOR_ROR_REG, // 000 0001 0 0111 + + OP_EOR_LSL_IMM, // 000 0001 0 1000 + OP_MLA, // 000 0001 0 1001 + OP_EOR_LSR_IMM, // OOO OOO1 O 1010 + OP_UND, // 000 0001 0 1011 + OP_EOR_ASR_IMM, // 000 0001 0 1100 + OP_UND, // 000 0001 0 1101 + OP_EOR_ROR_IMM, // 000 0001 0 1110 + OP_UND, // 000 0001 0 1111 + + OP_EOR_S_LSL_IMM, // 000 0001 1 0000 + OP_EOR_S_LSL_REG, // 000 0001 1 0001 + OP_EOR_S_LSR_IMM, // 000 0001 1 0010 + OP_EOR_S_LSR_REG, // 000 0001 1 0011 + OP_EOR_S_ASR_IMM, // 000 0001 1 0100 + OP_EOR_S_ASR_REG, // 000 0001 1 0101 + OP_EOR_S_ROR_IMM, // 000 0001 1 0110 + OP_EOR_S_ROR_REG, // 000 0001 1 0111 + + OP_EOR_S_LSL_IMM, // 000 0001 1 1000 + OP_MLA_S, // 000 0001 1 1001 + OP_EOR_S_LSR_IMM, // 000 0001 1 1010 + OP_UND, // 000 0001 1 1011 + OP_EOR_S_ASR_IMM, // 000 0001 1 1100 + OP_UND, // 000 0001 1 1101 + OP_EOR_S_ROR_IMM, // 000 0001 1 1110 + OP_UND, // 000 0001 1 1111 + + OP_SUB_LSL_IMM, // 000 0010 0 0000 + OP_SUB_LSL_REG, // 000 0010 0 0001 + OP_SUB_LSR_IMM, // 000 0010 0 0010 + OP_SUB_LSR_REG, // 000 0010 0 0011 + OP_SUB_ASR_IMM, // 000 0010 0 0100 + OP_SUB_ASR_REG, // 000 0010 0 0101 + OP_SUB_ROR_IMM, // 000 0010 0 0110 + OP_SUB_ROR_REG, // 000 0010 0 0111 + + OP_SUB_LSL_IMM, // 000 0010 0 1000 + OP_UND, // 000 0010 0 1001 + OP_SUB_LSR_IMM, // OOO OO1O O 1010 + OP_STRH_POS_INDE_M_IMM_OFF, // 000 0010 0 1011 + OP_SUB_ASR_IMM, // 000 0010 0 1100 + OP_LDRD_STRD_POST_INDEX, + // 000 0010 0 1101 + OP_SUB_ROR_IMM, // 000 0010 0 1110 + OP_LDRD_STRD_POST_INDEX, + // 000 0010 0 1111 + + OP_SUB_S_LSL_IMM, // 000 0010 1 0000 + OP_SUB_S_LSL_REG, // 000 0010 1 0001 + OP_SUB_S_LSR_IMM, // 000 0010 1 0010 + OP_SUB_S_LSR_REG, // 000 0010 1 0011 + OP_SUB_S_ASR_IMM, // 000 0010 1 0100 + OP_SUB_S_ASR_REG, // 000 0010 1 0101 + OP_SUB_S_ROR_IMM, // 000 0010 1 0110 + OP_SUB_S_ROR_REG, // 000 0010 1 0111 + + OP_SUB_S_LSL_IMM, // 000 0010 1 1000 + OP_UND, // 000 0010 1 1001 + OP_SUB_S_LSR_IMM, // 000 0010 1 1010 + OP_LDRH_POS_INDE_M_IMM_OFF, // 000 0010 1 1011 + OP_SUB_S_ASR_IMM, // 000 0010 1 1100 + OP_LDRSB_POS_INDE_M_IMM_OFF,// 000 0010 1 1101 + OP_SUB_S_ROR_IMM, // 000 0010 1 1110 + OP_LDRSH_POS_INDE_M_IMM_OFF,// 000 0010 1 1111 +//-------------------- + OP_RSB_LSL_IMM, // 000 0011 0 0000 + OP_RSB_LSL_REG, // 000 0011 0 0001 + OP_RSB_LSR_IMM, // 000 0011 0 0010 + OP_RSB_LSR_REG, // 000 0011 0 0011 + OP_RSB_ASR_IMM, // 000 0011 0 0100 + OP_RSB_ASR_REG, // 000 0011 0 0101 + OP_RSB_ROR_IMM, // 000 0011 0 0110 + OP_RSB_ROR_REG, // 000 0011 0 0111 + + OP_RSB_LSL_IMM, // 000 0011 0 1000 + OP_UND, // 000 0011 0 1001 + OP_RSB_LSR_IMM, // OOO OO11 O 1010 + OP_UND, // 000 0011 0 1011 + OP_RSB_ASR_IMM, // 000 0011 0 1100 + OP_UND, // 000 0011 0 1101 + OP_RSB_ROR_IMM, // 000 0011 0 1110 + OP_UND, // 000 0011 0 1111 + + OP_RSB_S_LSL_IMM, // 000 0011 1 0000 + OP_RSB_S_LSL_REG, // 000 0011 1 0001 + OP_RSB_S_LSR_IMM, // 000 0011 1 0010 + OP_RSB_S_LSR_REG, // 000 0011 1 0011 + OP_RSB_S_ASR_IMM, // 000 0011 1 0100 + OP_RSB_S_ASR_REG, // 000 0011 1 0101 + OP_RSB_S_ROR_IMM, // 000 0011 1 0110 + OP_RSB_S_ROR_REG, // 000 0011 1 0111 + + OP_RSB_S_LSL_IMM, // 000 0011 1 1000 + OP_UND, // 000 0011 1 1001 + OP_RSB_S_LSR_IMM, // 000 0011 1 1010 + OP_UND, // 000 0011 1 1011 + OP_RSB_S_ASR_IMM, // 000 0011 1 1100 + OP_UND, // 000 0011 1 1101 + OP_RSB_S_ROR_IMM, // 000 0011 1 1110 + OP_UND, // 000 0011 1 1111 +//-------------------------- + OP_ADD_LSL_IMM, // 000 0100 0 0000 + OP_ADD_LSL_REG, // 000 0100 0 0001 + OP_ADD_LSR_IMM, // 000 0100 0 0010 + OP_ADD_LSR_REG, // 000 0100 0 0011 + OP_ADD_ASR_IMM, // 000 0100 0 0100 + OP_ADD_ASR_REG, // 000 0100 0 0101 + OP_ADD_ROR_IMM, // 000 0100 0 0110 + OP_ADD_ROR_REG, // 000 0100 0 0111 + + OP_ADD_LSL_IMM, // 000 0100 0 1000 + OP_UMULL, // 000 0100 0 1001 + OP_ADD_LSR_IMM, // OOO O10O O 1010 + OP_STRH_POS_INDE_P_REG_OFF, // 000 0100 0 1011 + OP_ADD_ASR_IMM, // 000 0100 0 1100 + OP_LDRD_STRD_POST_INDEX, + // 000 0100 0 1101 + OP_ADD_ROR_IMM, // 000 0100 0 1110 + OP_LDRD_STRD_POST_INDEX, + // 000 0100 0 1111 + + OP_ADD_S_LSL_IMM, // 000 0100 1 0000 + OP_ADD_S_LSL_REG, // 000 0100 1 0001 + OP_ADD_S_LSR_IMM, // 000 0100 1 0010 + OP_ADD_S_LSR_REG, // 000 0100 1 0011 + OP_ADD_S_ASR_IMM, // 000 0100 1 0100 + OP_ADD_S_ASR_REG, // 000 0100 1 0101 + OP_ADD_S_ROR_IMM, // 000 0100 1 0110 + OP_ADD_S_ROR_REG, // 000 0100 1 0111 + + OP_ADD_S_LSL_IMM, // 000 0100 1 1000 + OP_UMULL_S, // 000 0100 1 1001 + OP_ADD_S_LSR_IMM, // 000 0100 1 1010 + OP_LDRH_POS_INDE_P_REG_OFF, // 000 0100 1 1011 + OP_ADD_S_ASR_IMM, // 000 0100 1 1100 + OP_LDRSB_POS_INDE_P_REG_OFF,// 000 0100 1 1101 + OP_ADD_S_ROR_IMM, // 000 0100 1 1110 + OP_LDRSH_POS_INDE_P_REG_OFF,// 000 0100 1 1111 +//----------------------------------------- + OP_ADC_LSL_IMM, // 000 0101 0 0000 + OP_ADC_LSL_REG, // 000 0101 0 0001 + OP_ADC_LSR_IMM, // 000 0101 0 0010 + OP_ADC_LSR_REG, // 000 0101 0 0011 + OP_ADC_ASR_IMM, // 000 0101 0 0100 + OP_ADC_ASR_REG, // 000 0101 0 0101 + OP_ADC_ROR_IMM, // 000 0101 0 0110 + OP_ADC_ROR_REG, // 000 0101 0 0111 + + OP_ADC_LSL_IMM, // 000 0101 0 1000 + OP_UMLAL, // 000 0101 0 1001 + OP_ADC_LSR_IMM, // OOO O101 O 1010 + OP_UND, // 000 0101 0 1011 + OP_ADC_ASR_IMM, // 000 0101 0 1100 + OP_UND, // 000 0101 0 1101 + OP_ADC_ROR_IMM, // 000 0101 0 1110 + OP_UND, // 000 0101 0 1111 + + OP_ADC_S_LSL_IMM, // 000 0101 1 0000 + OP_ADC_S_LSL_REG, // 000 0101 1 0001 + OP_ADC_S_LSR_IMM, // 000 0101 1 0010 + OP_ADC_S_LSR_REG, // 000 0101 1 0011 + OP_ADC_S_ASR_IMM, // 000 0101 1 0100 + OP_ADC_S_ASR_REG, // 000 0101 1 0101 + OP_ADC_S_ROR_IMM, // 000 0101 1 0110 + OP_ADC_S_ROR_REG, // 000 0101 1 0111 + + OP_ADC_S_LSL_IMM, // 000 0101 1 1000 + OP_UMLAL_S, // 000 0101 1 1001 + OP_ADC_S_LSR_IMM, // 000 0101 1 1010 + OP_UND, // 000 0101 1 1011 + OP_ADC_S_ASR_IMM, // 000 0101 1 1100 + OP_UND, // 000 0101 1 1101 + OP_ADC_S_ROR_IMM, // 000 0101 1 1110 + OP_UND, // 000 0101 1 1111 +//------------------------------------------ + OP_SBC_LSL_IMM, // 000 0110 0 0000 + OP_SBC_LSL_REG, // 000 0110 0 0001 + OP_SBC_LSR_IMM, // 000 0110 0 0010 + OP_SBC_LSR_REG, // 000 0110 0 0011 + OP_SBC_ASR_IMM, // 000 0110 0 0100 + OP_SBC_ASR_REG, // 000 0110 0 0101 + OP_SBC_ROR_IMM, // 000 0110 0 0110 + OP_SBC_ROR_REG, // 000 0110 0 0111 + + OP_SBC_LSL_IMM, // 000 0110 0 1000 + OP_SMULL, // 000 0110 0 1001 + OP_SBC_LSR_IMM, // OOO O11O O 1010 + OP_STRH_POS_INDE_P_IMM_OFF, // 000 0110 0 1011 + OP_SBC_ASR_IMM, // 000 0110 0 1100 + OP_LDRD_STRD_POST_INDEX, + // 000 0110 0 1101 + OP_SBC_ROR_IMM, // 000 0110 0 1110 + OP_LDRD_STRD_POST_INDEX, + // 000 0110 0 1111 + + OP_SBC_S_LSL_IMM, // 000 0110 1 0000 + OP_SBC_S_LSL_REG, // 000 0110 1 0001 + OP_SBC_S_LSR_IMM, // 000 0110 1 0010 + OP_SBC_S_LSR_REG, // 000 0110 1 0011 + OP_SBC_S_ASR_IMM, // 000 0110 1 0100 + OP_SBC_S_ASR_REG, // 000 0110 1 0101 + OP_SBC_S_ROR_IMM, // 000 0110 1 0110 + OP_SBC_S_ROR_REG, // 000 0110 1 0111 + + OP_SBC_S_LSL_IMM, // 000 0110 1 1000 + OP_SMULL_S, // 000 0110 1 1001 + OP_SBC_S_LSR_IMM, // 000 0110 1 1010 + OP_LDRH_POS_INDE_P_IMM_OFF, // 000 0110 1 1011 + OP_SBC_S_ASR_IMM, // 000 0110 1 1100 + OP_LDRSB_POS_INDE_P_IMM_OFF,// 000 0110 1 1101 + OP_SBC_S_ROR_IMM, // 000 0110 1 1110 + OP_LDRSH_POS_INDE_P_IMM_OFF,// 000 0110 1 1111 +//------------------------------------------ + OP_RSC_LSL_IMM, // 000 0111 0 0000 + OP_RSC_LSL_REG, // 000 0111 0 0001 + OP_RSC_LSR_IMM, // 000 0111 0 0010 + OP_RSC_LSR_REG, // 000 0111 0 0011 + OP_RSC_ASR_IMM, // 000 0111 0 0100 + OP_RSC_ASR_REG, // 000 0111 0 0101 + OP_RSC_ROR_IMM, // 000 0111 0 0110 + OP_RSC_ROR_REG, // 000 0111 0 0111 + + OP_RSC_LSL_IMM, // 000 0111 0 1000 + OP_SMLAL, // 000 0111 0 1001 + OP_RSC_LSR_IMM, // OOO O111 O 1010 + OP_UND, // 000 0111 0 1011 + OP_RSC_ASR_IMM, // 000 0111 0 1100 + OP_UND, // 000 0111 0 1101 + OP_RSC_ROR_IMM, // 000 0111 0 1110 + OP_UND, // 000 0111 0 1111 + + OP_RSC_S_LSL_IMM, // 000 0111 1 0000 + OP_RSC_S_LSL_REG, // 000 0111 1 0001 + OP_RSC_S_LSR_IMM, // 000 0111 1 0010 + OP_RSC_S_LSR_REG, // 000 0111 1 0011 + OP_RSC_S_ASR_IMM, // 000 0111 1 0100 + OP_RSC_S_ASR_REG, // 000 0111 1 0101 + OP_RSC_S_ROR_IMM, // 000 0111 1 0110 + OP_RSC_S_ROR_REG, // 000 0111 1 0111 + + OP_RSC_S_LSL_IMM, // 000 0111 1 1000 + OP_SMLAL_S, // 000 0111 1 1001 + OP_RSC_S_LSR_IMM, // 000 0111 1 1010 + OP_UND, // 000 0111 1 1011 + OP_RSC_S_ASR_IMM, // 000 0111 1 1100 + OP_UND, // 000 0111 1 1101 + OP_RSC_S_ROR_IMM, // 000 0111 1 1110 + OP_UND, // 000 0111 1 1111 +//------------------------------------------ + OP_MRS_CPSR, // 000 1000 0 0000 + OP_UND, // 000 1000 0 0001 + OP_UND, // 000 1000 0 0010 + OP_UND, // 000 1000 0 0011 + OP_UND, // 000 1000 0 0100 + OP_QADD, // 000 1000 0 0101 + OP_UND, // 000 1000 0 0110 + OP_UND, // 000 1000 0 0111 + + OP_SMLA_B_B, // 000 1000 0 1000 + OP_SWP, // 000 1000 0 1001 + OP_SMLA_T_B, // 000 1000 0 1010 + OP_STRH_M_REG_OFF, // 000 1000 0 1011 + OP_SMLA_B_T, // 000 1000 0 1100 + OP_LDRD_STRD_OFFSET_PRE_INDEX, + // 000 1000 0 1101 + OP_SMLA_T_T, // 000 1000 0 1110 + OP_LDRD_STRD_OFFSET_PRE_INDEX, + // 000 1000 0 1111 + + OP_TST_LSL_IMM, // 000 1000 1 0000 + OP_TST_LSL_REG, // 000 1000 1 0001 + OP_TST_LSR_IMM, // 000 1000 1 0010 + OP_TST_LSR_REG, // 000 1000 1 0011 + OP_TST_ASR_IMM, // 000 1000 1 0100 + OP_TST_ASR_REG, // 000 1000 1 0101 + OP_TST_ROR_IMM, // 000 1000 1 0110 + OP_TST_ROR_REG, // 000 1000 1 0111 + + OP_TST_LSL_IMM, // 000 1000 1 1000 + OP_UND, // 000 1000 1 1001 + OP_TST_LSR_IMM, // OOO 100O 1 1010 + OP_LDRH_M_REG_OFF, // 000 1000 1 1011 + OP_TST_ASR_IMM, // 000 1000 1 1100 + OP_LDRSB_M_REG_OFF,// 000 1000 1 1101 + OP_TST_ROR_IMM, // 000 1000 1 1110 + OP_LDRSH_M_REG_OFF,// 000 1000 1 1111 +//------------------------------------------ + OP_MSR_CPSR, // 000 1001 0 0000 + OP_BX, // 000 1001 0 0001 + OP_UND, // 000 1001 0 0010 + OP_BLX_REG, // 000 1001 0 0011 + OP_UND, // 000 1001 0 0100 + OP_QSUB, // 000 1001 0 0101 + OP_UND, // 000 1001 0 0110 + OP_BKPT, // 000 1001 0 0111 + + OP_SMLAW_B, // 000 1001 0 1000 + OP_UND, // 000 1001 0 1001 + OP_SMULW_B, // 000 1001 0 1010 + OP_STRH_PRE_INDE_M_REG_OFF, // 000 1001 0 1011 + OP_SMLAW_T, // 000 1001 0 1100 + OP_LDRD_STRD_OFFSET_PRE_INDEX, + // 000 1001 0 1101 + OP_SMULW_T, // 000 1001 0 1110 + OP_LDRD_STRD_OFFSET_PRE_INDEX, + // 000 1001 0 1111 + + OP_TEQ_LSL_IMM, // 000 1001 1 0000 + OP_TEQ_LSL_REG, // 000 1001 1 0001 + OP_TEQ_LSR_IMM, // 000 1001 1 0010 + OP_TEQ_LSR_REG, // 000 1001 1 0011 + OP_TEQ_ASR_IMM, // 000 1001 1 0100 + OP_TEQ_ASR_REG, // 000 1001 1 0101 + OP_TEQ_ROR_IMM, // 000 1001 1 0110 + OP_TEQ_ROR_REG, // 000 1001 1 0111 + + OP_TEQ_LSL_IMM, // 000 1001 1 1000 + OP_UND, // 000 1001 1 1001 + OP_TEQ_LSR_IMM, // OOO 1001 1 1010 + OP_LDRH_PRE_INDE_M_REG_OFF, // 000 1001 1 1011 + OP_TEQ_ASR_IMM, // 000 1001 1 1100 + OP_LDRSB_PRE_INDE_M_REG_OFF, // 000 1001 1 1101 + OP_TEQ_ROR_IMM, // 000 1001 1 1110 + OP_LDRSH_PRE_INDE_M_REG_OFF, // 000 1001 1 1111 +//------------------------------------------ + OP_MRS_SPSR, // 000 1010 0 0000 + OP_UND, // 000 1010 0 0001 + OP_UND, // 000 1010 0 0010 + OP_UND, // 000 1010 0 0011 + OP_UND, // 000 1010 0 0100 + OP_QDADD, // 000 1010 0 0101 + OP_UND, // 000 1010 0 0110 + OP_UND, // 000 1010 0 0111 + + OP_SMLAL_B_B, // 000 1010 0 1000 + OP_SWPB, // 000 1010 0 1001 + OP_SMLAL_T_B, // 000 1010 0 1010 + OP_STRH_M_IMM_OFF, // 000 1010 0 1011 + OP_SMLAL_B_T, // 000 1010 0 1100 + OP_LDRD_STRD_OFFSET_PRE_INDEX, + // 000 1010 0 1101 + OP_SMLAL_T_T, // 000 1010 0 1110 + OP_LDRD_STRD_OFFSET_PRE_INDEX, + // 000 1010 0 1111 + + OP_CMP_LSL_IMM, // 000 1010 1 0000 + OP_CMP_LSL_REG, // 000 1010 1 0001 + OP_CMP_LSR_IMM, // 000 1010 1 0010 + OP_CMP_LSR_REG, // 000 1010 1 0011 + OP_CMP_ASR_IMM, // 000 1010 1 0100 + OP_CMP_ASR_REG, // 000 1010 1 0101 + OP_CMP_ROR_IMM, // 000 1010 1 0110 + OP_CMP_ROR_REG, // 000 1010 1 0111 + + OP_CMP_LSL_IMM, // 000 1010 1 1000 + OP_UND, // 000 1010 1 1001 + OP_CMP_LSR_IMM, // OOO 1O1O 1 1010 + OP_LDRH_M_IMM_OFF, // 000 1010 1 1011 + OP_CMP_ASR_IMM, // 000 1010 1 1100 + OP_LDRSB_M_IMM_OFF,// 000 1010 1 1101 + OP_CMP_ROR_IMM, // 000 1010 1 1110 + OP_LDRSH_M_IMM_OFF,// 000 1010 1 1111 +//------------------------------------------ + OP_MSR_SPSR, // 000 1011 0 0000 + OP_CLZ, // 000 1011 0 0001 + OP_UND, // 000 1011 0 0010 + OP_UND, // 000 1011 0 0011 + OP_UND, // 000 1011 0 0100 + OP_QDSUB, // 000 1011 0 0101 + OP_UND, // 000 1011 0 0110 + OP_UND, // 000 1011 0 0111 + + OP_SMUL_B_B, // 000 1011 0 1000 + OP_UND, // 000 1011 0 1001 + OP_SMUL_T_B, // 000 1011 0 1010 + OP_STRH_PRE_INDE_M_IMM_OFF, // 000 1011 0 1011 + OP_SMUL_B_T, // 000 1011 0 1100 + OP_LDRD_STRD_OFFSET_PRE_INDEX, + // 000 1011 0 1101 + OP_SMUL_T_T, // 000 1011 0 1110 + OP_LDRD_STRD_OFFSET_PRE_INDEX, + // 000 1011 0 1111 + + OP_CMN_LSL_IMM, // 000 1011 1 0000 + OP_CMN_LSL_REG, // 000 1011 1 0001 + OP_CMN_LSR_IMM, // 000 1011 1 0010 + OP_CMN_LSR_REG, // 000 1011 1 0011 + OP_CMN_ASR_IMM, // 000 1011 1 0100 + OP_CMN_ASR_REG, // 000 1011 1 0101 + OP_CMN_ROR_IMM, // 000 1011 1 0110 + OP_CMN_ROR_REG, // 000 1011 1 0111 + + OP_CMN_LSL_IMM, // 000 1011 1 1000 + OP_UND, // 000 1011 1 1001 + OP_CMN_LSR_IMM, // OOO 1O11 1 1010 + OP_LDRH_PRE_INDE_M_IMM_OFF, // 000 1011 1 1011 + OP_CMN_ASR_IMM, // 000 1011 1 1100 + OP_LDRSB_PRE_INDE_M_IMM_OFF, // 000 1011 1 1101 + OP_CMN_ROR_IMM, // 000 1011 1 1110 + OP_LDRSH_PRE_INDE_M_IMM_OFF, // 000 1011 1 1111 +//------------------------------------------ + OP_ORR_LSL_IMM, // 000 1100 0 0000 + OP_ORR_LSL_REG, // 000 1100 0 0001 + OP_ORR_LSR_IMM, // 000 1100 0 0010 + OP_ORR_LSR_REG, // 000 1100 0 0011 + OP_ORR_ASR_IMM, // 000 1100 0 0100 + OP_ORR_ASR_REG, // 000 1100 0 0101 + OP_ORR_ROR_IMM, // 000 1100 0 0110 + OP_ORR_ROR_REG, // 000 1100 0 0111 + + OP_ORR_LSL_IMM, // 000 1100 0 1000 + OP_UND, // 000 1100 0 1001 + OP_ORR_LSR_IMM, // OOO 110O O 1010 + OP_STRH_P_REG_OFF, // 000 1100 0 1011 + OP_ORR_ASR_IMM, // 000 1100 0 1100 + OP_LDRD_STRD_OFFSET_PRE_INDEX, + // 000 1100 0 1101 + OP_ORR_ROR_IMM, // 000 1100 0 1110 + OP_LDRD_STRD_OFFSET_PRE_INDEX, + // 000 1100 0 1111 + + OP_ORR_S_LSL_IMM, // 000 1100 1 0000 + OP_ORR_S_LSL_REG, // 000 1100 1 0001 + OP_ORR_S_LSR_IMM, // 000 1100 1 0010 + OP_ORR_S_LSR_REG, // 000 1100 1 0011 + OP_ORR_S_ASR_IMM, // 000 1100 1 0100 + OP_ORR_S_ASR_REG, // 000 1100 1 0101 + OP_ORR_S_ROR_IMM, // 000 1100 1 0110 + OP_ORR_S_ROR_REG, // 000 1100 1 0111 + + OP_ORR_S_LSL_IMM, // 000 1100 1 1000 + OP_UND, // 000 1100 1 1001 + OP_ORR_S_LSR_IMM, // 000 1100 1 1010 + OP_LDRH_P_REG_OFF, // 000 1100 1 1011 + OP_ORR_S_ASR_IMM, // 000 1100 1 1100 + OP_LDRSB_P_REG_OFF,// 000 1100 1 1101 + OP_ORR_S_ROR_IMM, // 000 1100 1 1110 + OP_LDRSH_P_REG_OFF,// 000 1100 1 1111 +//------------------------------------------ + OP_MOV_LSL_IMM, // 000 1101 0 0000 + OP_MOV_LSL_REG, // 000 1101 0 0001 + OP_MOV_LSR_IMM, // 000 1101 0 0010 + OP_MOV_LSR_REG, // 000 1101 0 0011 + OP_MOV_ASR_IMM, // 000 1101 0 0100 + OP_MOV_ASR_REG, // 000 1101 0 0101 + OP_MOV_ROR_IMM, // 000 1101 0 0110 + OP_MOV_ROR_REG, // 000 1101 0 0111 + + OP_MOV_LSL_IMM, // 000 1101 0 1000 + OP_UND, // 000 1101 0 1001 + OP_MOV_LSR_IMM, // OOO 1101 O 1010 + OP_STRH_PRE_INDE_P_REG_OFF, // 000 1101 0 1011 + OP_MOV_ASR_IMM, // 000 1101 0 1100 + OP_LDRD_STRD_OFFSET_PRE_INDEX, + // 000 1101 0 1101 + OP_MOV_ROR_IMM, // 000 1101 0 1110 + OP_LDRD_STRD_OFFSET_PRE_INDEX, + // 000 1101 0 1111 + + OP_MOV_S_LSL_IMM, // 000 1101 1 0000 + OP_MOV_S_LSL_REG, // 000 1101 1 0001 + OP_MOV_S_LSR_IMM, // 000 1101 1 0010 + OP_MOV_S_LSR_REG, // 000 1101 1 0011 + OP_MOV_S_ASR_IMM, // 000 1101 1 0100 + OP_MOV_S_ASR_REG, // 000 1101 1 0101 + OP_MOV_S_ROR_IMM, // 000 1101 1 0110 + OP_MOV_S_ROR_REG, // 000 1101 1 0111 + + OP_MOV_S_LSL_IMM, // 000 1101 1 1000 + OP_UND, // 000 1101 1 1001 + OP_MOV_S_LSR_IMM, // 000 1101 1 1010 + OP_LDRH_PRE_INDE_P_REG_OFF, // 000 1101 1 1011 + OP_MOV_S_ASR_IMM, // 000 1101 1 1100 + OP_LDRSB_PRE_INDE_P_REG_OFF,// 000 1101 1 1101 + OP_MOV_S_ROR_IMM, // 000 1101 1 1110 + OP_LDRSH_PRE_INDE_P_REG_OFF,// 000 1101 1 1111 +//------------------------------------------ + OP_BIC_LSL_IMM, // 000 1110 0 0000 + OP_BIC_LSL_REG, // 000 1110 0 0001 + OP_BIC_LSR_IMM, // 000 1110 0 0010 + OP_BIC_LSR_REG, // 000 1110 0 0011 + OP_BIC_ASR_IMM, // 000 1110 0 0100 + OP_BIC_ASR_REG, // 000 1110 0 0101 + OP_BIC_ROR_IMM, // 000 1110 0 0110 + OP_BIC_ROR_REG, // 000 1110 0 0111 + + OP_BIC_LSL_IMM, // 000 1110 0 1000 + OP_UND, // 000 1110 0 1001 + OP_BIC_LSR_IMM, // OOO 111O O 1010 + OP_STRH_P_IMM_OFF, // 000 1110 0 1011 + OP_BIC_ASR_IMM, // 000 1110 0 1100 + OP_LDRD_STRD_OFFSET_PRE_INDEX, + // 000 1110 0 1101 + OP_BIC_ROR_IMM, // 000 1110 0 1110 + OP_LDRD_STRD_OFFSET_PRE_INDEX, + // 000 1110 0 1111 + + OP_BIC_S_LSL_IMM, // 000 1110 1 0000 + OP_BIC_S_LSL_REG, // 000 1110 1 0001 + OP_BIC_S_LSR_IMM, // 000 1110 1 0010 + OP_BIC_S_LSR_REG, // 000 1110 1 0011 + OP_BIC_S_ASR_IMM, // 000 1110 1 0100 + OP_BIC_S_ASR_REG, // 000 1110 1 0101 + OP_BIC_S_ROR_IMM, // 000 1110 1 0110 + OP_BIC_S_ROR_REG, // 000 1110 1 0111 + + OP_BIC_S_LSL_IMM, // 000 1110 1 1000 + OP_UND, // 000 1110 1 1001 + OP_BIC_S_LSR_IMM, // 000 1110 1 1010 + OP_LDRH_P_IMM_OFF, // 000 1110 1 1011 + OP_BIC_S_ASR_IMM, // 000 1110 1 1100 + OP_LDRSB_P_IMM_OFF,// 000 1110 1 1101 + OP_BIC_S_ROR_IMM, // 000 1110 1 1110 + OP_LDRSH_P_IMM_OFF,// 000 1110 1 1111 +//------------------------------------------- + OP_MVN_LSL_IMM, // 000 1111 0 0000 + OP_MVN_LSL_REG, // 000 1111 0 0001 + OP_MVN_LSR_IMM, // 000 1111 0 0010 + OP_MVN_LSR_REG, // 000 1111 0 0011 + OP_MVN_ASR_IMM, // 000 1111 0 0100 + OP_MVN_ASR_REG, // 000 1111 0 0101 + OP_MVN_ROR_IMM, // 000 1111 0 0110 + OP_MVN_ROR_REG, // 000 1111 0 0111 + + OP_MVN_LSL_IMM, // 000 1111 0 1000 + OP_UND, // 000 1111 0 1001 + OP_MVN_LSR_IMM, // OOO 1111 O 1010 + OP_STRH_PRE_INDE_P_IMM_OFF, // 000 1111 0 1011 + OP_MVN_ASR_IMM, // 000 1111 0 1100 + OP_LDRD_STRD_OFFSET_PRE_INDEX, + // 000 1111 0 1101 + OP_MVN_ROR_IMM, // 000 1111 0 1110 + OP_LDRD_STRD_OFFSET_PRE_INDEX, + // 000 1111 0 1111 + + OP_MVN_S_LSL_IMM, // 000 1111 1 0000 + OP_MVN_S_LSL_REG, // 000 1111 1 0001 + OP_MVN_S_LSR_IMM, // 000 1111 1 0010 + OP_MVN_S_LSR_REG, // 000 1111 1 0011 + OP_MVN_S_ASR_IMM, // 000 1111 1 0100 + OP_MVN_S_ASR_REG, // 000 1111 1 0101 + OP_MVN_S_ROR_IMM, // 000 1111 1 0110 + OP_MVN_S_ROR_REG, // 000 1111 1 0111 + + OP_MVN_S_LSL_IMM, // 000 1111 1 1000 + OP_UND, // 000 1111 1 1001 + OP_MVN_S_LSR_IMM, // 000 1111 1 1010 + OP_LDRH_PRE_INDE_P_IMM_OFF, // 000 1111 1 1011 + OP_MVN_S_ASR_IMM, // 000 1111 1 1100 + OP_LDRSB_PRE_INDE_P_IMM_OFF,// 000 1111 1 1101 + OP_MVN_S_ROR_IMM, // 000 1111 1 1110 + OP_LDRSH_PRE_INDE_P_IMM_OFF,// 000 1111 1 1111 +//------------------------------------------- + OP_AND_IMM_VAL, // 001 0000 0 0000 + OP_AND_IMM_VAL, // 001 0000 0 0001 + OP_AND_IMM_VAL, // 001 0000 0 0010 + OP_AND_IMM_VAL, // 001 0000 0 0011 + OP_AND_IMM_VAL, // 001 0000 0 0100 + OP_AND_IMM_VAL, // 001 0000 0 0101 + OP_AND_IMM_VAL, // 001 0000 0 0110 + OP_AND_IMM_VAL, // 001 0000 0 0111 + OP_AND_IMM_VAL, // 001 0000 0 1000 + OP_AND_IMM_VAL, // 001 0000 0 1001 + OP_AND_IMM_VAL, // 001 0000 0 1010 + OP_AND_IMM_VAL, // 001 0000 0 1011 + OP_AND_IMM_VAL, // 001 0000 0 1100 + OP_AND_IMM_VAL, // 001 0000 0 1101 + OP_AND_IMM_VAL, // 001 0000 0 1110 + OP_AND_IMM_VAL, // 001 0000 0 1111 + + OP_AND_S_IMM_VAL, // 001 0000 1 0000 + OP_AND_S_IMM_VAL, // 001 0000 1 0001 + OP_AND_S_IMM_VAL, // 001 0000 1 0010 + OP_AND_S_IMM_VAL, // 001 0000 1 0011 + OP_AND_S_IMM_VAL, // 001 0000 1 0100 + OP_AND_S_IMM_VAL, // 001 0000 1 0101 + OP_AND_S_IMM_VAL, // 001 0000 1 0110 + OP_AND_S_IMM_VAL, // 001 0000 1 0111 + OP_AND_S_IMM_VAL, // 001 0000 1 1000 + OP_AND_S_IMM_VAL, // 001 0000 1 1001 + OP_AND_S_IMM_VAL, // 001 0000 1 1010 + OP_AND_S_IMM_VAL, // 001 0000 1 1011 + OP_AND_S_IMM_VAL, // 001 0000 1 1100 + OP_AND_S_IMM_VAL, // 001 0000 1 1101 + OP_AND_S_IMM_VAL, // 001 0000 1 1110 + OP_AND_S_IMM_VAL, // 001 0000 1 1111 +//------------------------------------------ + OP_EOR_IMM_VAL, // 001 0001 0 0000 + OP_EOR_IMM_VAL, // 001 0001 0 0001 + OP_EOR_IMM_VAL, // 001 0001 0 0010 + OP_EOR_IMM_VAL, // 001 0001 0 0011 + OP_EOR_IMM_VAL, // 001 0001 0 0100 + OP_EOR_IMM_VAL, // 001 0001 0 0101 + OP_EOR_IMM_VAL, // 001 0001 0 0110 + OP_EOR_IMM_VAL, // 001 0001 0 0111 + OP_EOR_IMM_VAL, // 001 0001 0 1000 + OP_EOR_IMM_VAL, // 001 0001 0 1001 + OP_EOR_IMM_VAL, // 001 0001 0 1010 + OP_EOR_IMM_VAL, // 001 0001 0 1011 + OP_EOR_IMM_VAL, // 001 0001 0 1100 + OP_EOR_IMM_VAL, // 001 0001 0 1101 + OP_EOR_IMM_VAL, // 001 0001 0 1110 + OP_EOR_IMM_VAL, // 001 0001 0 1111 + + OP_EOR_S_IMM_VAL, // 001 0001 1 0000 + OP_EOR_S_IMM_VAL, // 001 0001 1 0001 + OP_EOR_S_IMM_VAL, // 001 0001 1 0010 + OP_EOR_S_IMM_VAL, // 001 0001 1 0011 + OP_EOR_S_IMM_VAL, // 001 0001 1 0100 + OP_EOR_S_IMM_VAL, // 001 0001 1 0101 + OP_EOR_S_IMM_VAL, // 001 0001 1 0110 + OP_EOR_S_IMM_VAL, // 001 0001 1 0111 + OP_EOR_S_IMM_VAL, // 001 0001 1 1000 + OP_EOR_S_IMM_VAL, // 001 0001 1 1001 + OP_EOR_S_IMM_VAL, // 001 0001 1 1010 + OP_EOR_S_IMM_VAL, // 001 0001 1 1011 + OP_EOR_S_IMM_VAL, // 001 0001 1 1100 + OP_EOR_S_IMM_VAL, // 001 0001 1 1101 + OP_EOR_S_IMM_VAL, // 001 0001 1 1110 + OP_EOR_S_IMM_VAL, // 001 0001 1 1111 +//------------------------------------------ + OP_SUB_IMM_VAL, // 001 0010 0 0000 + OP_SUB_IMM_VAL, // 001 0010 0 0001 + OP_SUB_IMM_VAL, // 001 0010 0 0010 + OP_SUB_IMM_VAL, // 001 0010 0 0011 + OP_SUB_IMM_VAL, // 001 0010 0 0100 + OP_SUB_IMM_VAL, // 001 0010 0 0101 + OP_SUB_IMM_VAL, // 001 0010 0 0110 + OP_SUB_IMM_VAL, // 001 0010 0 0111 + OP_SUB_IMM_VAL, // 001 0010 0 1000 + OP_SUB_IMM_VAL, // 001 0010 0 1001 + OP_SUB_IMM_VAL, // 001 0010 0 1010 + OP_SUB_IMM_VAL, // 001 0010 0 1011 + OP_SUB_IMM_VAL, // 001 0010 0 1100 + OP_SUB_IMM_VAL, // 001 0010 0 1101 + OP_SUB_IMM_VAL, // 001 0010 0 1110 + OP_SUB_IMM_VAL, // 001 0010 0 1111 + + OP_SUB_S_IMM_VAL, // 001 0010 1 0000 + OP_SUB_S_IMM_VAL, // 001 0010 1 0001 + OP_SUB_S_IMM_VAL, // 001 0010 1 0010 + OP_SUB_S_IMM_VAL, // 001 0010 1 0011 + OP_SUB_S_IMM_VAL, // 001 0010 1 0100 + OP_SUB_S_IMM_VAL, // 001 0010 1 0101 + OP_SUB_S_IMM_VAL, // 001 0010 1 0110 + OP_SUB_S_IMM_VAL, // 001 0010 1 0111 + OP_SUB_S_IMM_VAL, // 001 0010 1 1000 + OP_SUB_S_IMM_VAL, // 001 0010 1 1001 + OP_SUB_S_IMM_VAL, // 001 0010 1 1010 + OP_SUB_S_IMM_VAL, // 001 0010 1 1011 + OP_SUB_S_IMM_VAL, // 001 0010 1 1100 + OP_SUB_S_IMM_VAL, // 001 0010 1 1101 + OP_SUB_S_IMM_VAL, // 001 0010 1 1110 + OP_SUB_S_IMM_VAL, // 001 0010 1 1111 +//------------------------------------------ + OP_RSB_IMM_VAL, // 001 0011 0 0000 + OP_RSB_IMM_VAL, // 001 0011 0 0001 + OP_RSB_IMM_VAL, // 001 0011 0 0010 + OP_RSB_IMM_VAL, // 001 0011 0 0011 + OP_RSB_IMM_VAL, // 001 0011 0 0100 + OP_RSB_IMM_VAL, // 001 0011 0 0101 + OP_RSB_IMM_VAL, // 001 0011 0 0110 + OP_RSB_IMM_VAL, // 001 0011 0 0111 + OP_RSB_IMM_VAL, // 001 0011 0 1000 + OP_RSB_IMM_VAL, // 001 0011 0 1001 + OP_RSB_IMM_VAL, // 001 0011 0 1010 + OP_RSB_IMM_VAL, // 001 0011 0 1011 + OP_RSB_IMM_VAL, // 001 0011 0 1100 + OP_RSB_IMM_VAL, // 001 0011 0 1101 + OP_RSB_IMM_VAL, // 001 0011 0 1110 + OP_RSB_IMM_VAL, // 001 0011 0 1111 + + OP_RSB_S_IMM_VAL, // 001 0011 1 0000 + OP_RSB_S_IMM_VAL, // 001 0011 1 0001 + OP_RSB_S_IMM_VAL, // 001 0011 1 0010 + OP_RSB_S_IMM_VAL, // 001 0011 1 0011 + OP_RSB_S_IMM_VAL, // 001 0011 1 0100 + OP_RSB_S_IMM_VAL, // 001 0011 1 0101 + OP_RSB_S_IMM_VAL, // 001 0011 1 0110 + OP_RSB_S_IMM_VAL, // 001 0011 1 0111 + OP_RSB_S_IMM_VAL, // 001 0011 1 1000 + OP_RSB_S_IMM_VAL, // 001 0011 1 1001 + OP_RSB_S_IMM_VAL, // 001 0011 1 1010 + OP_RSB_S_IMM_VAL, // 001 0011 1 1011 + OP_RSB_S_IMM_VAL, // 001 0011 1 1100 + OP_RSB_S_IMM_VAL, // 001 0011 1 1101 + OP_RSB_S_IMM_VAL, // 001 0011 1 1110 + OP_RSB_S_IMM_VAL, // 001 0011 1 1111 +//------------------------------------------ + OP_ADD_IMM_VAL, // 001 0100 0 0000 + OP_ADD_IMM_VAL, // 001 0100 0 0001 + OP_ADD_IMM_VAL, // 001 0100 0 0010 + OP_ADD_IMM_VAL, // 001 0100 0 0011 + OP_ADD_IMM_VAL, // 001 0100 0 0100 + OP_ADD_IMM_VAL, // 001 0100 0 0101 + OP_ADD_IMM_VAL, // 001 0100 0 0110 + OP_ADD_IMM_VAL, // 001 0100 0 0111 + OP_ADD_IMM_VAL, // 001 0100 0 1000 + OP_ADD_IMM_VAL, // 001 0100 0 1001 + OP_ADD_IMM_VAL, // 001 0100 0 1010 + OP_ADD_IMM_VAL, // 001 0100 0 1011 + OP_ADD_IMM_VAL, // 001 0100 0 1100 + OP_ADD_IMM_VAL, // 001 0100 0 1101 + OP_ADD_IMM_VAL, // 001 0100 0 1110 + OP_ADD_IMM_VAL, // 001 0100 0 1111 + + OP_ADD_S_IMM_VAL, // 001 0100 1 0000 + OP_ADD_S_IMM_VAL, // 001 0100 1 0001 + OP_ADD_S_IMM_VAL, // 001 0100 1 0010 + OP_ADD_S_IMM_VAL, // 001 0100 1 0011 + OP_ADD_S_IMM_VAL, // 001 0100 1 0100 + OP_ADD_S_IMM_VAL, // 001 0100 1 0101 + OP_ADD_S_IMM_VAL, // 001 0100 1 0110 + OP_ADD_S_IMM_VAL, // 001 0100 1 0111 + OP_ADD_S_IMM_VAL, // 001 0100 1 1000 + OP_ADD_S_IMM_VAL, // 001 0100 1 1001 + OP_ADD_S_IMM_VAL, // 001 0100 1 1010 + OP_ADD_S_IMM_VAL, // 001 0100 1 1011 + OP_ADD_S_IMM_VAL, // 001 0100 1 1100 + OP_ADD_S_IMM_VAL, // 001 0100 1 1101 + OP_ADD_S_IMM_VAL, // 001 0100 1 1110 + OP_ADD_S_IMM_VAL, // 001 0100 1 1111 +//------------------------------------------ + OP_ADC_IMM_VAL, // 001 0101 0 0000 + OP_ADC_IMM_VAL, // 001 0101 0 0001 + OP_ADC_IMM_VAL, // 001 0101 0 0010 + OP_ADC_IMM_VAL, // 001 0101 0 0011 + OP_ADC_IMM_VAL, // 001 0101 0 0100 + OP_ADC_IMM_VAL, // 001 0101 0 0101 + OP_ADC_IMM_VAL, // 001 0101 0 0110 + OP_ADC_IMM_VAL, // 001 0101 0 0111 + OP_ADC_IMM_VAL, // 001 0101 0 1000 + OP_ADC_IMM_VAL, // 001 0101 0 1001 + OP_ADC_IMM_VAL, // 001 0101 0 1010 + OP_ADC_IMM_VAL, // 001 0101 0 1011 + OP_ADC_IMM_VAL, // 001 0101 0 1100 + OP_ADC_IMM_VAL, // 001 0101 0 1101 + OP_ADC_IMM_VAL, // 001 0101 0 1110 + OP_ADC_IMM_VAL, // 001 0101 0 1111 + + OP_ADC_S_IMM_VAL, // 001 0101 1 0000 + OP_ADC_S_IMM_VAL, // 001 0101 1 0001 + OP_ADC_S_IMM_VAL, // 001 0101 1 0010 + OP_ADC_S_IMM_VAL, // 001 0101 1 0011 + OP_ADC_S_IMM_VAL, // 001 0101 1 0100 + OP_ADC_S_IMM_VAL, // 001 0101 1 0101 + OP_ADC_S_IMM_VAL, // 001 0101 1 0110 + OP_ADC_S_IMM_VAL, // 001 0101 1 0111 + OP_ADC_S_IMM_VAL, // 001 0101 1 1000 + OP_ADC_S_IMM_VAL, // 001 0101 1 1001 + OP_ADC_S_IMM_VAL, // 001 0101 1 1010 + OP_ADC_S_IMM_VAL, // 001 0101 1 1011 + OP_ADC_S_IMM_VAL, // 001 0101 1 1100 + OP_ADC_S_IMM_VAL, // 001 0101 1 1101 + OP_ADC_S_IMM_VAL, // 001 0101 1 1110 + OP_ADC_S_IMM_VAL, // 001 0101 1 1111 +//------------------------------------------ + OP_SBC_IMM_VAL, // 001 0110 0 0000 + OP_SBC_IMM_VAL, // 001 0110 0 0001 + OP_SBC_IMM_VAL, // 001 0110 0 0010 + OP_SBC_IMM_VAL, // 001 0110 0 0011 + OP_SBC_IMM_VAL, // 001 0110 0 0100 + OP_SBC_IMM_VAL, // 001 0110 0 0101 + OP_SBC_IMM_VAL, // 001 0110 0 0110 + OP_SBC_IMM_VAL, // 001 0110 0 0111 + OP_SBC_IMM_VAL, // 001 0110 0 1000 + OP_SBC_IMM_VAL, // 001 0110 0 1001 + OP_SBC_IMM_VAL, // 001 0110 0 1010 + OP_SBC_IMM_VAL, // 001 0110 0 1011 + OP_SBC_IMM_VAL, // 001 0110 0 1100 + OP_SBC_IMM_VAL, // 001 0110 0 1101 + OP_SBC_IMM_VAL, // 001 0110 0 1110 + OP_SBC_IMM_VAL, // 001 0110 0 1111 + + OP_SBC_S_IMM_VAL, // 001 0110 1 0000 + OP_SBC_S_IMM_VAL, // 001 0110 1 0001 + OP_SBC_S_IMM_VAL, // 001 0110 1 0010 + OP_SBC_S_IMM_VAL, // 001 0110 1 0011 + OP_SBC_S_IMM_VAL, // 001 0110 1 0100 + OP_SBC_S_IMM_VAL, // 001 0110 1 0101 + OP_SBC_S_IMM_VAL, // 001 0110 1 0110 + OP_SBC_S_IMM_VAL, // 001 0110 1 0111 + OP_SBC_S_IMM_VAL, // 001 0110 1 1000 + OP_SBC_S_IMM_VAL, // 001 0110 1 1001 + OP_SBC_S_IMM_VAL, // 001 0110 1 1010 + OP_SBC_S_IMM_VAL, // 001 0110 1 1011 + OP_SBC_S_IMM_VAL, // 001 0110 1 1100 + OP_SBC_S_IMM_VAL, // 001 0110 1 1101 + OP_SBC_S_IMM_VAL, // 001 0110 1 1110 + OP_SBC_S_IMM_VAL, // 001 0110 1 1111 +//------------------------------------------ + OP_RSC_IMM_VAL, // 001 0111 0 0000 + OP_RSC_IMM_VAL, // 001 0111 0 0001 + OP_RSC_IMM_VAL, // 001 0111 0 0010 + OP_RSC_IMM_VAL, // 001 0111 0 0011 + OP_RSC_IMM_VAL, // 001 0111 0 0100 + OP_RSC_IMM_VAL, // 001 0111 0 0101 + OP_RSC_IMM_VAL, // 001 0111 0 0110 + OP_RSC_IMM_VAL, // 001 0111 0 0111 + OP_RSC_IMM_VAL, // 001 0111 0 1000 + OP_RSC_IMM_VAL, // 001 0111 0 1001 + OP_RSC_IMM_VAL, // 001 0111 0 1010 + OP_RSC_IMM_VAL, // 001 0111 0 1011 + OP_RSC_IMM_VAL, // 001 0111 0 1100 + OP_RSC_IMM_VAL, // 001 0111 0 1101 + OP_RSC_IMM_VAL, // 001 0111 0 1110 + OP_RSC_IMM_VAL, // 001 0111 0 1111 + + OP_RSC_S_IMM_VAL, // 001 0111 1 0000 + OP_RSC_S_IMM_VAL, // 001 0111 1 0001 + OP_RSC_S_IMM_VAL, // 001 0111 1 0010 + OP_RSC_S_IMM_VAL, // 001 0111 1 0011 + OP_RSC_S_IMM_VAL, // 001 0111 1 0100 + OP_RSC_S_IMM_VAL, // 001 0111 1 0101 + OP_RSC_S_IMM_VAL, // 001 0111 1 0110 + OP_RSC_S_IMM_VAL, // 001 0111 1 0111 + OP_RSC_S_IMM_VAL, // 001 0111 1 1000 + OP_RSC_S_IMM_VAL, // 001 0111 1 1001 + OP_RSC_S_IMM_VAL, // 001 0111 1 1010 + OP_RSC_S_IMM_VAL, // 001 0111 1 1011 + OP_RSC_S_IMM_VAL, // 001 0111 1 1100 + OP_RSC_S_IMM_VAL, // 001 0111 1 1101 + OP_RSC_S_IMM_VAL, // 001 0111 1 1110 + OP_RSC_S_IMM_VAL, // 001 0111 1 1111 +//------------------------------------------ + OP_UND, // 001 1000 0 0000 + OP_UND, // 001 1000 0 0001 + OP_UND, // 001 1000 0 0010 + OP_UND, // 001 1000 0 0011 + OP_UND, // 001 1000 0 0100 + OP_UND, // 001 1000 0 0101 + OP_UND, // 001 1000 0 0110 + OP_UND, // 001 1000 0 0111 + OP_UND, // 001 1000 0 1000 + OP_UND, // 001 1000 0 1001 + OP_UND, // 001 1000 0 1010 + OP_UND, // 001 1000 0 1011 + OP_UND, // 001 1000 0 1100 + OP_UND, // 001 1000 0 1101 + OP_UND, // 001 1000 0 1110 + OP_UND, // 001 1000 0 1111 + + OP_TST_IMM_VAL, // 001 1000 1 0000 + OP_TST_IMM_VAL, // 001 1000 1 0001 + OP_TST_IMM_VAL, // 001 1000 1 0010 + OP_TST_IMM_VAL, // 001 1000 1 0011 + OP_TST_IMM_VAL, // 001 1000 1 0100 + OP_TST_IMM_VAL, // 001 1000 1 0101 + OP_TST_IMM_VAL, // 001 1000 1 0110 + OP_TST_IMM_VAL, // 001 1000 1 0111 + OP_TST_IMM_VAL, // 001 1000 1 1000 + OP_TST_IMM_VAL, // 001 1000 1 1001 + OP_TST_IMM_VAL, // 001 1000 1 1010 + OP_TST_IMM_VAL, // 001 1000 1 1011 + OP_TST_IMM_VAL, // 001 1000 1 1100 + OP_TST_IMM_VAL, // 001 1000 1 1101 + OP_TST_IMM_VAL, // 001 1000 1 1110 + OP_TST_IMM_VAL, // 001 1000 1 1111 +//------------------------------------------ + OP_MSR_CPSR_IMM_VAL, // 001 1001 0 0000 + OP_MSR_CPSR_IMM_VAL, // 001 1001 0 0001 + OP_MSR_CPSR_IMM_VAL, // 001 1001 0 0010 + OP_MSR_CPSR_IMM_VAL, // 001 1001 0 0011 + OP_MSR_CPSR_IMM_VAL, // 001 1001 0 0100 + OP_MSR_CPSR_IMM_VAL, // 001 1001 0 0101 + OP_MSR_CPSR_IMM_VAL, // 001 1001 0 0110 + OP_MSR_CPSR_IMM_VAL, // 001 1001 0 0111 + OP_MSR_CPSR_IMM_VAL, // 001 1001 0 1000 + OP_MSR_CPSR_IMM_VAL, // 001 1001 0 1001 + OP_MSR_CPSR_IMM_VAL, // 001 1001 0 1010 + OP_MSR_CPSR_IMM_VAL, // 001 1001 0 1011 + OP_MSR_CPSR_IMM_VAL, // 001 1001 0 1100 + OP_MSR_CPSR_IMM_VAL, // 001 1001 0 1101 + OP_MSR_CPSR_IMM_VAL, // 001 1001 0 1110 + OP_MSR_CPSR_IMM_VAL, // 001 1001 0 1111 + + OP_TEQ_IMM_VAL, // 001 1001 1 0000 + OP_TEQ_IMM_VAL, // 001 1001 1 0001 + OP_TEQ_IMM_VAL, // 001 1001 1 0010 + OP_TEQ_IMM_VAL, // 001 1001 1 0011 + OP_TEQ_IMM_VAL, // 001 1001 1 0100 + OP_TEQ_IMM_VAL, // 001 1001 1 0101 + OP_TEQ_IMM_VAL, // 001 1001 1 0110 + OP_TEQ_IMM_VAL, // 001 1001 1 0111 + OP_TEQ_IMM_VAL, // 001 1001 1 1000 + OP_TEQ_IMM_VAL, // 001 1001 1 1001 + OP_TEQ_IMM_VAL, // 001 1001 1 1010 + OP_TEQ_IMM_VAL, // 001 1001 1 1011 + OP_TEQ_IMM_VAL, // 001 1001 1 1100 + OP_TEQ_IMM_VAL, // 001 1001 1 1101 + OP_TEQ_IMM_VAL, // 001 1001 1 1110 + OP_TEQ_IMM_VAL, // 001 1001 1 1111 +//------------------------------------------ + OP_UND, // 001 1010 0 0000 + OP_UND, // 001 1010 0 0001 + OP_UND, // 001 1010 0 0010 + OP_UND, // 001 1010 0 0011 + OP_UND, // 001 1010 0 0100 + OP_UND, // 001 1010 0 0101 + OP_UND, // 001 1010 0 0110 + OP_UND, // 001 1010 0 0111 + OP_UND, // 001 1010 0 1000 + OP_UND, // 001 1010 0 1001 + OP_UND, // 001 1010 0 1010 + OP_UND, // 001 1010 0 1011 + OP_UND, // 001 1010 0 1100 + OP_UND, // 001 1010 0 1101 + OP_UND, // 001 1010 0 1110 + OP_UND, // 001 1010 0 1111 + + OP_CMP_IMM_VAL, // 001 1010 1 0000 + OP_CMP_IMM_VAL, // 001 1010 1 0001 + OP_CMP_IMM_VAL, // 001 1010 1 0010 + OP_CMP_IMM_VAL, // 001 1010 1 0011 + OP_CMP_IMM_VAL, // 001 1010 1 0100 + OP_CMP_IMM_VAL, // 001 1010 1 0101 + OP_CMP_IMM_VAL, // 001 1010 1 0110 + OP_CMP_IMM_VAL, // 001 1010 1 0111 + OP_CMP_IMM_VAL, // 001 1010 1 1000 + OP_CMP_IMM_VAL, // 001 1010 1 1001 + OP_CMP_IMM_VAL, // 001 1010 1 1010 + OP_CMP_IMM_VAL, // 001 1010 1 1011 + OP_CMP_IMM_VAL, // 001 1010 1 1100 + OP_CMP_IMM_VAL, // 001 1010 1 1101 + OP_CMP_IMM_VAL, // 001 1010 1 1110 + OP_CMP_IMM_VAL, // 001 1010 1 1111 +//------------------------------------------ + OP_MSR_SPSR_IMM_VAL, // 001 1011 0 0000 + OP_MSR_SPSR_IMM_VAL, // 001 1011 0 0001 + OP_MSR_SPSR_IMM_VAL, // 001 1011 0 0010 + OP_MSR_SPSR_IMM_VAL, // 001 1011 0 0011 + OP_MSR_SPSR_IMM_VAL, // 001 1011 0 0100 + OP_MSR_SPSR_IMM_VAL, // 001 1011 0 0101 + OP_MSR_SPSR_IMM_VAL, // 001 1011 0 0110 + OP_MSR_SPSR_IMM_VAL, // 001 1011 0 0111 + OP_MSR_SPSR_IMM_VAL, // 001 1011 0 1000 + OP_MSR_SPSR_IMM_VAL, // 001 1011 0 1001 + OP_MSR_SPSR_IMM_VAL, // 001 1011 0 1010 + OP_MSR_SPSR_IMM_VAL, // 001 1011 0 1011 + OP_MSR_SPSR_IMM_VAL, // 001 1011 0 1100 + OP_MSR_SPSR_IMM_VAL, // 001 1011 0 1101 + OP_MSR_SPSR_IMM_VAL, // 001 1011 0 1110 + OP_MSR_SPSR_IMM_VAL, // 001 1011 0 1111 + + OP_CMN_IMM_VAL, // 001 1011 1 0000 + OP_CMN_IMM_VAL, // 001 1011 1 0001 + OP_CMN_IMM_VAL, // 001 1011 1 0010 + OP_CMN_IMM_VAL, // 001 1011 1 0011 + OP_CMN_IMM_VAL, // 001 1011 1 0100 + OP_CMN_IMM_VAL, // 001 1011 1 0101 + OP_CMN_IMM_VAL, // 001 1011 1 0110 + OP_CMN_IMM_VAL, // 001 1011 1 0111 + OP_CMN_IMM_VAL, // 001 1011 1 1000 + OP_CMN_IMM_VAL, // 001 1011 1 1001 + OP_CMN_IMM_VAL, // 001 1011 1 1010 + OP_CMN_IMM_VAL, // 001 1011 1 1011 + OP_CMN_IMM_VAL, // 001 1011 1 1100 + OP_CMN_IMM_VAL, // 001 1011 1 1101 + OP_CMN_IMM_VAL, // 001 1011 1 1110 + OP_CMN_IMM_VAL, // 001 1011 1 1111 +//------------------------------------------ + OP_ORR_IMM_VAL, // 001 1100 0 0000 + OP_ORR_IMM_VAL, // 001 1100 0 0001 + OP_ORR_IMM_VAL, // 001 1100 0 0010 + OP_ORR_IMM_VAL, // 001 1100 0 0011 + OP_ORR_IMM_VAL, // 001 1100 0 0100 + OP_ORR_IMM_VAL, // 001 1100 0 0101 + OP_ORR_IMM_VAL, // 001 1100 0 0110 + OP_ORR_IMM_VAL, // 001 1100 0 0111 + OP_ORR_IMM_VAL, // 001 1100 0 1000 + OP_ORR_IMM_VAL, // 001 1100 0 1001 + OP_ORR_IMM_VAL, // 001 1100 0 1010 + OP_ORR_IMM_VAL, // 001 1100 0 1011 + OP_ORR_IMM_VAL, // 001 1100 0 1100 + OP_ORR_IMM_VAL, // 001 1100 0 1101 + OP_ORR_IMM_VAL, // 001 1100 0 1110 + OP_ORR_IMM_VAL, // 001 1100 0 1111 + + OP_ORR_S_IMM_VAL, // 001 1100 1 0000 + OP_ORR_S_IMM_VAL, // 001 1100 1 0001 + OP_ORR_S_IMM_VAL, // 001 1100 1 0010 + OP_ORR_S_IMM_VAL, // 001 1100 1 0011 + OP_ORR_S_IMM_VAL, // 001 1100 1 0100 + OP_ORR_S_IMM_VAL, // 001 1100 1 0101 + OP_ORR_S_IMM_VAL, // 001 1100 1 0110 + OP_ORR_S_IMM_VAL, // 001 1100 1 0111 + OP_ORR_S_IMM_VAL, // 001 1100 1 1000 + OP_ORR_S_IMM_VAL, // 001 1100 1 1001 + OP_ORR_S_IMM_VAL, // 001 1100 1 1010 + OP_ORR_S_IMM_VAL, // 001 1100 1 1011 + OP_ORR_S_IMM_VAL, // 001 1100 1 1100 + OP_ORR_S_IMM_VAL, // 001 1100 1 1101 + OP_ORR_S_IMM_VAL, // 001 1100 1 1110 + OP_ORR_S_IMM_VAL, // 001 1100 1 1111 +//------------------------------------------ + OP_MOV_IMM_VAL, // 001 1101 0 0000 + OP_MOV_IMM_VAL, // 001 1101 0 0001 + OP_MOV_IMM_VAL, // 001 1101 0 0010 + OP_MOV_IMM_VAL, // 001 1101 0 0011 + OP_MOV_IMM_VAL, // 001 1101 0 0100 + OP_MOV_IMM_VAL, // 001 1101 0 0101 + OP_MOV_IMM_VAL, // 001 1101 0 0110 + OP_MOV_IMM_VAL, // 001 1101 0 0111 + OP_MOV_IMM_VAL, // 001 1101 0 1000 + OP_MOV_IMM_VAL, // 001 1101 0 1001 + OP_MOV_IMM_VAL, // 001 1101 0 1010 + OP_MOV_IMM_VAL, // 001 1101 0 1011 + OP_MOV_IMM_VAL, // 001 1101 0 1100 + OP_MOV_IMM_VAL, // 001 1101 0 1101 + OP_MOV_IMM_VAL, // 001 1101 0 1110 + OP_MOV_IMM_VAL, // 001 1101 0 1111 + + OP_MOV_S_IMM_VAL, // 001 1101 1 0000 + OP_MOV_S_IMM_VAL, // 001 1101 1 0001 + OP_MOV_S_IMM_VAL, // 001 1101 1 0010 + OP_MOV_S_IMM_VAL, // 001 1101 1 0011 + OP_MOV_S_IMM_VAL, // 001 1101 1 0100 + OP_MOV_S_IMM_VAL, // 001 1101 1 0101 + OP_MOV_S_IMM_VAL, // 001 1101 1 0110 + OP_MOV_S_IMM_VAL, // 001 1101 1 0111 + OP_MOV_S_IMM_VAL, // 001 1101 1 1000 + OP_MOV_S_IMM_VAL, // 001 1101 1 1001 + OP_MOV_S_IMM_VAL, // 001 1101 1 1010 + OP_MOV_S_IMM_VAL, // 001 1101 1 1011 + OP_MOV_S_IMM_VAL, // 001 1101 1 1100 + OP_MOV_S_IMM_VAL, // 001 1101 1 1101 + OP_MOV_S_IMM_VAL, // 001 1101 1 1110 + OP_MOV_S_IMM_VAL, // 001 1101 1 1111 +//------------------------------------------ + OP_BIC_IMM_VAL, // 001 1110 0 0000 + OP_BIC_IMM_VAL, // 001 1110 0 0001 + OP_BIC_IMM_VAL, // 001 1110 0 0010 + OP_BIC_IMM_VAL, // 001 1110 0 0011 + OP_BIC_IMM_VAL, // 001 1110 0 0100 + OP_BIC_IMM_VAL, // 001 1110 0 0101 + OP_BIC_IMM_VAL, // 001 1110 0 0110 + OP_BIC_IMM_VAL, // 001 1110 0 0111 + OP_BIC_IMM_VAL, // 001 1110 0 1000 + OP_BIC_IMM_VAL, // 001 1110 0 1001 + OP_BIC_IMM_VAL, // 001 1110 0 1010 + OP_BIC_IMM_VAL, // 001 1110 0 1011 + OP_BIC_IMM_VAL, // 001 1110 0 1100 + OP_BIC_IMM_VAL, // 001 1110 0 1101 + OP_BIC_IMM_VAL, // 001 1110 0 1110 + OP_BIC_IMM_VAL, // 001 1110 0 1111 + + OP_BIC_S_IMM_VAL, // 001 1110 1 0000 + OP_BIC_S_IMM_VAL, // 001 1110 1 0001 + OP_BIC_S_IMM_VAL, // 001 1110 1 0010 + OP_BIC_S_IMM_VAL, // 001 1110 1 0011 + OP_BIC_S_IMM_VAL, // 001 1110 1 0100 + OP_BIC_S_IMM_VAL, // 001 1110 1 0101 + OP_BIC_S_IMM_VAL, // 001 1110 1 0110 + OP_BIC_S_IMM_VAL, // 001 1110 1 0111 + OP_BIC_S_IMM_VAL, // 001 1110 1 1000 + OP_BIC_S_IMM_VAL, // 001 1110 1 1001 + OP_BIC_S_IMM_VAL, // 001 1110 1 1010 + OP_BIC_S_IMM_VAL, // 001 1110 1 1011 + OP_BIC_S_IMM_VAL, // 001 1110 1 1100 + OP_BIC_S_IMM_VAL, // 001 1110 1 1101 + OP_BIC_S_IMM_VAL, // 001 1110 1 1110 + OP_BIC_S_IMM_VAL, // 001 1110 1 1111 +//------------------------------------------ + OP_MVN_IMM_VAL, // 001 1111 0 0000 + OP_MVN_IMM_VAL, // 001 1111 0 0001 + OP_MVN_IMM_VAL, // 001 1111 0 0010 + OP_MVN_IMM_VAL, // 001 1111 0 0011 + OP_MVN_IMM_VAL, // 001 1111 0 0100 + OP_MVN_IMM_VAL, // 001 1111 0 0101 + OP_MVN_IMM_VAL, // 001 1111 0 0110 + OP_MVN_IMM_VAL, // 001 1111 0 0111 + OP_MVN_IMM_VAL, // 001 1111 0 1000 + OP_MVN_IMM_VAL, // 001 1111 0 1001 + OP_MVN_IMM_VAL, // 001 1111 0 1010 + OP_MVN_IMM_VAL, // 001 1111 0 1011 + OP_MVN_IMM_VAL, // 001 1111 0 1100 + OP_MVN_IMM_VAL, // 001 1111 0 1101 + OP_MVN_IMM_VAL, // 001 1111 0 1110 + OP_MVN_IMM_VAL, // 001 1111 0 1111 + + OP_MVN_S_IMM_VAL, // 001 1111 1 0000 + OP_MVN_S_IMM_VAL, // 001 1111 1 0001 + OP_MVN_S_IMM_VAL, // 001 1111 1 0010 + OP_MVN_S_IMM_VAL, // 001 1111 1 0011 + OP_MVN_S_IMM_VAL, // 001 1111 1 0100 + OP_MVN_S_IMM_VAL, // 001 1111 1 0101 + OP_MVN_S_IMM_VAL, // 001 1111 1 0110 + OP_MVN_S_IMM_VAL, // 001 1111 1 0111 + OP_MVN_S_IMM_VAL, // 001 1111 1 1000 + OP_MVN_S_IMM_VAL, // 001 1111 1 1001 + OP_MVN_S_IMM_VAL, // 001 1111 1 1010 + OP_MVN_S_IMM_VAL, // 001 1111 1 1011 + OP_MVN_S_IMM_VAL, // 001 1111 1 1100 + OP_MVN_S_IMM_VAL, // 001 1111 1 1101 + OP_MVN_S_IMM_VAL, // 001 1111 1 1110 + OP_MVN_S_IMM_VAL, // 001 1111 1 1111 +//------------------------------------------ + OP_STR_M_IMM_OFF_POSTIND, //010 0000 0 0000 + OP_STR_M_IMM_OFF_POSTIND, //010 0000 0 0001 + OP_STR_M_IMM_OFF_POSTIND, //010 0000 0 0010 + OP_STR_M_IMM_OFF_POSTIND, //010 0000 0 0011 + OP_STR_M_IMM_OFF_POSTIND, //010 0000 0 0100 + OP_STR_M_IMM_OFF_POSTIND, //010 0000 0 0101 + OP_STR_M_IMM_OFF_POSTIND, //010 0000 0 0110 + OP_STR_M_IMM_OFF_POSTIND, //010 0000 0 0111 + OP_STR_M_IMM_OFF_POSTIND, //010 0000 0 1000 + OP_STR_M_IMM_OFF_POSTIND, //010 0000 0 1001 + OP_STR_M_IMM_OFF_POSTIND, //010 0000 0 1010 + OP_STR_M_IMM_OFF_POSTIND, //010 0000 0 1011 + OP_STR_M_IMM_OFF_POSTIND, //010 0000 0 1100 + OP_STR_M_IMM_OFF_POSTIND, //010 0000 0 1101 + OP_STR_M_IMM_OFF_POSTIND, //010 0000 0 1110 + OP_STR_M_IMM_OFF_POSTIND, //010 0000 0 1111 + + OP_LDR_M_IMM_OFF_POSTIND, //010 0000 1 0000 + OP_LDR_M_IMM_OFF_POSTIND, //010 0000 1 0001 + OP_LDR_M_IMM_OFF_POSTIND, //010 0000 1 0010 + OP_LDR_M_IMM_OFF_POSTIND, //010 0000 1 0011 + OP_LDR_M_IMM_OFF_POSTIND, //010 0000 1 0100 + OP_LDR_M_IMM_OFF_POSTIND, //010 0000 1 0101 + OP_LDR_M_IMM_OFF_POSTIND, //010 0000 1 0110 + OP_LDR_M_IMM_OFF_POSTIND, //010 0000 1 0111 + OP_LDR_M_IMM_OFF_POSTIND, //010 0000 1 1000 + OP_LDR_M_IMM_OFF_POSTIND, //010 0000 1 1001 + OP_LDR_M_IMM_OFF_POSTIND, //010 0000 1 1010 + OP_LDR_M_IMM_OFF_POSTIND, //010 0000 1 1011 + OP_LDR_M_IMM_OFF_POSTIND, //010 0000 1 1100 + OP_LDR_M_IMM_OFF_POSTIND, //010 0000 1 1101 + OP_LDR_M_IMM_OFF_POSTIND, //010 0000 1 1110 + OP_LDR_M_IMM_OFF_POSTIND, //010 0000 1 1111 +//------------------------------------------ + OP_UND, //010 0001 0 0000 + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, +//------------------------------------------ + OP_STRB_M_IMM_OFF_POSTIND, //010 0010 0 0000 + OP_STRB_M_IMM_OFF_POSTIND, //010 0010 0 0001 + OP_STRB_M_IMM_OFF_POSTIND, //010 0010 0 0010 + OP_STRB_M_IMM_OFF_POSTIND, //010 0010 0 0011 + OP_STRB_M_IMM_OFF_POSTIND, //010 0010 0 0100 + OP_STRB_M_IMM_OFF_POSTIND, //010 0010 0 0101 + OP_STRB_M_IMM_OFF_POSTIND, //010 0010 0 0110 + OP_STRB_M_IMM_OFF_POSTIND, //010 0010 0 0111 + OP_STRB_M_IMM_OFF_POSTIND, //010 0010 0 1000 + OP_STRB_M_IMM_OFF_POSTIND, //010 0010 0 1001 + OP_STRB_M_IMM_OFF_POSTIND, //010 0010 0 1010 + OP_STRB_M_IMM_OFF_POSTIND, //010 0010 0 1011 + OP_STRB_M_IMM_OFF_POSTIND, //010 0010 0 1100 + OP_STRB_M_IMM_OFF_POSTIND, //010 0010 0 1101 + OP_STRB_M_IMM_OFF_POSTIND, //010 0010 0 1110 + OP_STRB_M_IMM_OFF_POSTIND, //010 0010 0 1111 + + OP_LDRB_M_IMM_OFF_POSTIND, //010 0010 1 0000 + OP_LDRB_M_IMM_OFF_POSTIND, //010 0010 1 0001 + OP_LDRB_M_IMM_OFF_POSTIND, //010 0010 1 0010 + OP_LDRB_M_IMM_OFF_POSTIND, //010 0010 1 0011 + OP_LDRB_M_IMM_OFF_POSTIND, //010 0010 1 0100 + OP_LDRB_M_IMM_OFF_POSTIND, //010 0010 1 0101 + OP_LDRB_M_IMM_OFF_POSTIND, //010 0010 1 0110 + OP_LDRB_M_IMM_OFF_POSTIND, //010 0010 1 0111 + OP_LDRB_M_IMM_OFF_POSTIND, //010 0010 1 1000 + OP_LDRB_M_IMM_OFF_POSTIND, //010 0010 1 1001 + OP_LDRB_M_IMM_OFF_POSTIND, //010 0010 1 1010 + OP_LDRB_M_IMM_OFF_POSTIND, //010 0010 1 1011 + OP_LDRB_M_IMM_OFF_POSTIND, //010 0010 1 1100 + OP_LDRB_M_IMM_OFF_POSTIND, //010 0010 1 1101 + OP_LDRB_M_IMM_OFF_POSTIND, //010 0010 1 1110 + OP_LDRB_M_IMM_OFF_POSTIND, //010 0010 1 1111 +//------------------------------------------ + OP_STRBT_M_IMM_OFF_POSTIND, //010 0011 0 0000 + OP_STRBT_M_IMM_OFF_POSTIND, //010 0011 0 0000 + OP_STRBT_M_IMM_OFF_POSTIND, //010 0011 0 0000 + OP_STRBT_M_IMM_OFF_POSTIND, //010 0011 0 0000 + OP_STRBT_M_IMM_OFF_POSTIND, //010 0011 0 0000 + OP_STRBT_M_IMM_OFF_POSTIND, //010 0011 0 0000 + OP_STRBT_M_IMM_OFF_POSTIND, //010 0011 0 0000 + OP_STRBT_M_IMM_OFF_POSTIND, //010 0011 0 0000 + OP_STRBT_M_IMM_OFF_POSTIND, //010 0011 0 0000 + OP_STRBT_M_IMM_OFF_POSTIND, //010 0011 0 0000 + OP_STRBT_M_IMM_OFF_POSTIND, //010 0011 0 0000 + OP_STRBT_M_IMM_OFF_POSTIND, //010 0011 0 0000 + OP_STRBT_M_IMM_OFF_POSTIND, //010 0011 0 0000 + OP_STRBT_M_IMM_OFF_POSTIND, //010 0011 0 0000 + OP_STRBT_M_IMM_OFF_POSTIND, //010 0011 0 0000 + OP_STRBT_M_IMM_OFF_POSTIND, //010 0011 0 0000 + + OP_LDRBT_M_IMM_OFF_POSTIND, //010 0011 0 0000 + OP_LDRBT_M_IMM_OFF_POSTIND, //010 0011 0 0000 + OP_LDRBT_M_IMM_OFF_POSTIND, //010 0011 0 0000 + OP_LDRBT_M_IMM_OFF_POSTIND, //010 0011 0 0000 + OP_LDRBT_M_IMM_OFF_POSTIND, //010 0011 0 0000 + OP_LDRBT_M_IMM_OFF_POSTIND, //010 0011 0 0000 + OP_LDRBT_M_IMM_OFF_POSTIND, //010 0011 0 0000 + OP_LDRBT_M_IMM_OFF_POSTIND, //010 0011 0 0000 + OP_LDRBT_M_IMM_OFF_POSTIND, //010 0011 0 0000 + OP_LDRBT_M_IMM_OFF_POSTIND, //010 0011 0 0000 + OP_LDRBT_M_IMM_OFF_POSTIND, //010 0011 0 0000 + OP_LDRBT_M_IMM_OFF_POSTIND, //010 0011 0 0000 + OP_LDRBT_M_IMM_OFF_POSTIND, //010 0011 0 0000 + OP_LDRBT_M_IMM_OFF_POSTIND, //010 0011 0 0000 + OP_LDRBT_M_IMM_OFF_POSTIND, //010 0011 0 0000 + OP_LDRBT_M_IMM_OFF_POSTIND, //010 0011 0 0000 +//------------------------------------------ + OP_STR_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STR_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STR_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STR_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STR_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STR_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STR_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STR_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STR_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STR_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STR_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STR_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STR_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STR_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STR_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STR_P_IMM_OFF_POSTIND, //010 0100 0 0000 + + OP_LDR_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_LDR_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_LDR_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_LDR_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_LDR_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_LDR_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_LDR_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_LDR_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_LDR_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_LDR_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_LDR_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_LDR_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_LDR_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_LDR_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_LDR_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_LDR_P_IMM_OFF_POSTIND, //010 0100 0 0000 +//------------------------------------------ + OP_STR_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STR_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STR_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STR_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STR_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STR_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STR_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STR_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STR_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STR_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STR_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STR_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STR_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STR_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STR_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STR_P_IMM_OFF_POSTIND, //010 0100 0 0000 + + OP_LDR_P_IMM_OFF_POSTIND2, //010 0100 0 0000 + OP_LDR_P_IMM_OFF_POSTIND2, //010 0100 0 0000 + OP_LDR_P_IMM_OFF_POSTIND2, //010 0100 0 0000 + OP_LDR_P_IMM_OFF_POSTIND2, //010 0100 0 0000 + OP_LDR_P_IMM_OFF_POSTIND2, //010 0100 0 0000 + OP_LDR_P_IMM_OFF_POSTIND2, //010 0100 0 0000 + OP_LDR_P_IMM_OFF_POSTIND2, //010 0100 0 0000 + OP_LDR_P_IMM_OFF_POSTIND2, //010 0100 0 0000 + OP_LDR_P_IMM_OFF_POSTIND2, //010 0100 0 0000 + OP_LDR_P_IMM_OFF_POSTIND2, //010 0100 0 0000 + OP_LDR_P_IMM_OFF_POSTIND2, //010 0100 0 0000 + OP_LDR_P_IMM_OFF_POSTIND2, //010 0100 0 0000 + OP_LDR_P_IMM_OFF_POSTIND2, //010 0100 0 0000 + OP_LDR_P_IMM_OFF_POSTIND2, //010 0100 0 0000 + OP_LDR_P_IMM_OFF_POSTIND2, //010 0100 0 0000 + OP_LDR_P_IMM_OFF_POSTIND2, //010 0100 0 0000 +//------------------------------------------ + OP_STRB_P_IMM_OFF_POSTIND, //010 0110 0 0000 + OP_STRB_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STRB_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STRB_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STRB_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STRB_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STRB_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STRB_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STRB_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STRB_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STRB_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STRB_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STRB_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STRB_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STRB_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STRB_P_IMM_OFF_POSTIND, //010 0100 0 0000 + + OP_LDRB_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_LDRB_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_LDRB_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_LDRB_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_LDRB_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_LDRB_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_LDRB_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_LDRB_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_LDRB_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_LDRB_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_LDRB_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_LDRB_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_LDRB_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_LDRB_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_LDRB_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_LDRB_P_IMM_OFF_POSTIND, //010 0110 1 1111 +//------------------------------------------ + OP_STRBT_P_IMM_OFF_POSTIND, //010 0111 0 0000 + OP_STRBT_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STRBT_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STRBT_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STRBT_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STRBT_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STRBT_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STRBT_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STRBT_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STRBT_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STRBT_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STRBT_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STRBT_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STRBT_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STRBT_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STRBT_P_IMM_OFF_POSTIND, //010 0100 0 0000 + + OP_LDRBT_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_LDRBT_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_LDRBT_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_LDRBT_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_LDRBT_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_LDRBT_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_LDRBT_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_LDRBT_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_LDRBT_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_LDRBT_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_LDRBT_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_LDRBT_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_LDRBT_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_LDRBT_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_LDRBT_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_LDRBT_P_IMM_OFF_POSTIND, //010 0111 1 1111 +//------------------------------------------ + OP_STR_M_IMM_OFF, //010 1000 0 0000 + OP_STR_M_IMM_OFF, + OP_STR_M_IMM_OFF, + OP_STR_M_IMM_OFF, + OP_STR_M_IMM_OFF, + OP_STR_M_IMM_OFF, + OP_STR_M_IMM_OFF, + OP_STR_M_IMM_OFF, + OP_STR_M_IMM_OFF, + OP_STR_M_IMM_OFF, + OP_STR_M_IMM_OFF, + OP_STR_M_IMM_OFF, + OP_STR_M_IMM_OFF, + OP_STR_M_IMM_OFF, + OP_STR_M_IMM_OFF, + OP_STR_M_IMM_OFF, + + OP_LDR_M_IMM_OFF, + OP_LDR_M_IMM_OFF, + OP_LDR_M_IMM_OFF, + OP_LDR_M_IMM_OFF, + OP_LDR_M_IMM_OFF, + OP_LDR_M_IMM_OFF, + OP_LDR_M_IMM_OFF, + OP_LDR_M_IMM_OFF, + OP_LDR_M_IMM_OFF, + OP_LDR_M_IMM_OFF, + OP_LDR_M_IMM_OFF, + OP_LDR_M_IMM_OFF, + OP_LDR_M_IMM_OFF, + OP_LDR_M_IMM_OFF, + OP_LDR_M_IMM_OFF, + OP_LDR_M_IMM_OFF, //010 1000 1 1111 +//------------------------------------------ + OP_STR_M_IMM_OFF_PREIND, //010 1001 0 0000 + OP_STR_M_IMM_OFF_PREIND, + OP_STR_M_IMM_OFF_PREIND, + OP_STR_M_IMM_OFF_PREIND, + OP_STR_M_IMM_OFF_PREIND, + OP_STR_M_IMM_OFF_PREIND, + OP_STR_M_IMM_OFF_PREIND, + OP_STR_M_IMM_OFF_PREIND, + OP_STR_M_IMM_OFF_PREIND, + OP_STR_M_IMM_OFF_PREIND, + OP_STR_M_IMM_OFF_PREIND, + OP_STR_M_IMM_OFF_PREIND, + OP_STR_M_IMM_OFF_PREIND, + OP_STR_M_IMM_OFF_PREIND, + OP_STR_M_IMM_OFF_PREIND, + OP_STR_M_IMM_OFF_PREIND, + + OP_LDR_M_IMM_OFF_PREIND, + OP_LDR_M_IMM_OFF_PREIND, + OP_LDR_M_IMM_OFF_PREIND, + OP_LDR_M_IMM_OFF_PREIND, + OP_LDR_M_IMM_OFF_PREIND, + OP_LDR_M_IMM_OFF_PREIND, + OP_LDR_M_IMM_OFF_PREIND, + OP_LDR_M_IMM_OFF_PREIND, + OP_LDR_M_IMM_OFF_PREIND, + OP_LDR_M_IMM_OFF_PREIND, + OP_LDR_M_IMM_OFF_PREIND, + OP_LDR_M_IMM_OFF_PREIND, + OP_LDR_M_IMM_OFF_PREIND, + OP_LDR_M_IMM_OFF_PREIND, + OP_LDR_M_IMM_OFF_PREIND, + OP_LDR_M_IMM_OFF_PREIND, //010 1001 1 1111 +//------------------------------------------ + OP_STRB_M_IMM_OFF, //010 1010 0 0000 + OP_STRB_M_IMM_OFF, + OP_STRB_M_IMM_OFF, + OP_STRB_M_IMM_OFF, + OP_STRB_M_IMM_OFF, + OP_STRB_M_IMM_OFF, + OP_STRB_M_IMM_OFF, + OP_STRB_M_IMM_OFF, + OP_STRB_M_IMM_OFF, + OP_STRB_M_IMM_OFF, + OP_STRB_M_IMM_OFF, + OP_STRB_M_IMM_OFF, + OP_STRB_M_IMM_OFF, + OP_STRB_M_IMM_OFF, + OP_STRB_M_IMM_OFF, + OP_STRB_M_IMM_OFF, + + OP_LDRB_M_IMM_OFF, + OP_LDRB_M_IMM_OFF, + OP_LDRB_M_IMM_OFF, + OP_LDRB_M_IMM_OFF, + OP_LDRB_M_IMM_OFF, + OP_LDRB_M_IMM_OFF, + OP_LDRB_M_IMM_OFF, + OP_LDRB_M_IMM_OFF, + OP_LDRB_M_IMM_OFF, + OP_LDRB_M_IMM_OFF, + OP_LDRB_M_IMM_OFF, + OP_LDRB_M_IMM_OFF, + OP_LDRB_M_IMM_OFF, + OP_LDRB_M_IMM_OFF, + OP_LDRB_M_IMM_OFF, + OP_LDRB_M_IMM_OFF, //010 1010 1 1111 +//------------------------------------------ + OP_STRB_M_IMM_OFF_PREIND, //010 1011 0 0000 + OP_STRB_M_IMM_OFF_PREIND, + OP_STRB_M_IMM_OFF_PREIND, + OP_STRB_M_IMM_OFF_PREIND, + OP_STRB_M_IMM_OFF_PREIND, + OP_STRB_M_IMM_OFF_PREIND, + OP_STRB_M_IMM_OFF_PREIND, + OP_STRB_M_IMM_OFF_PREIND, + OP_STRB_M_IMM_OFF_PREIND, + OP_STRB_M_IMM_OFF_PREIND, + OP_STRB_M_IMM_OFF_PREIND, + OP_STRB_M_IMM_OFF_PREIND, + OP_STRB_M_IMM_OFF_PREIND, + OP_STRB_M_IMM_OFF_PREIND, + OP_STRB_M_IMM_OFF_PREIND, + OP_STRB_M_IMM_OFF_PREIND, + + OP_LDRB_M_IMM_OFF_PREIND, + OP_LDRB_M_IMM_OFF_PREIND, + OP_LDRB_M_IMM_OFF_PREIND, + OP_LDRB_M_IMM_OFF_PREIND, + OP_LDRB_M_IMM_OFF_PREIND, + OP_LDRB_M_IMM_OFF_PREIND, + OP_LDRB_M_IMM_OFF_PREIND, + OP_LDRB_M_IMM_OFF_PREIND, + OP_LDRB_M_IMM_OFF_PREIND, + OP_LDRB_M_IMM_OFF_PREIND, + OP_LDRB_M_IMM_OFF_PREIND, + OP_LDRB_M_IMM_OFF_PREIND, + OP_LDRB_M_IMM_OFF_PREIND, + OP_LDRB_M_IMM_OFF_PREIND, + OP_LDRB_M_IMM_OFF_PREIND, + OP_LDRB_M_IMM_OFF_PREIND, //010 1011 1 1111 +//------------------------------------------ + OP_STR_P_IMM_OFF, //010 1100 0 0000 + OP_STR_P_IMM_OFF, + OP_STR_P_IMM_OFF, + OP_STR_P_IMM_OFF, + OP_STR_P_IMM_OFF, + OP_STR_P_IMM_OFF, + OP_STR_P_IMM_OFF, + OP_STR_P_IMM_OFF, + OP_STR_P_IMM_OFF, + OP_STR_P_IMM_OFF, + OP_STR_P_IMM_OFF, + OP_STR_P_IMM_OFF, + OP_STR_P_IMM_OFF, + OP_STR_P_IMM_OFF, + OP_STR_P_IMM_OFF, + OP_STR_P_IMM_OFF, + + OP_LDR_P_IMM_OFF, + OP_LDR_P_IMM_OFF, + OP_LDR_P_IMM_OFF, + OP_LDR_P_IMM_OFF, + OP_LDR_P_IMM_OFF, + OP_LDR_P_IMM_OFF, + OP_LDR_P_IMM_OFF, + OP_LDR_P_IMM_OFF, + OP_LDR_P_IMM_OFF, + OP_LDR_P_IMM_OFF, + OP_LDR_P_IMM_OFF, + OP_LDR_P_IMM_OFF, + OP_LDR_P_IMM_OFF, + OP_LDR_P_IMM_OFF, + OP_LDR_P_IMM_OFF, + OP_LDR_P_IMM_OFF, //010 1100 1 1111 +//------------------------------------------ + OP_STR_P_IMM_OFF_PREIND, //010 1101 0 0000 + OP_STR_P_IMM_OFF_PREIND, + OP_STR_P_IMM_OFF_PREIND, + OP_STR_P_IMM_OFF_PREIND, + OP_STR_P_IMM_OFF_PREIND, + OP_STR_P_IMM_OFF_PREIND, + OP_STR_P_IMM_OFF_PREIND, + OP_STR_P_IMM_OFF_PREIND, + OP_STR_P_IMM_OFF_PREIND, + OP_STR_P_IMM_OFF_PREIND, + OP_STR_P_IMM_OFF_PREIND, + OP_STR_P_IMM_OFF_PREIND, + OP_STR_P_IMM_OFF_PREIND, + OP_STR_P_IMM_OFF_PREIND, + OP_STR_P_IMM_OFF_PREIND, + OP_STR_P_IMM_OFF_PREIND, + + OP_LDR_P_IMM_OFF_PREIND, + OP_LDR_P_IMM_OFF_PREIND, + OP_LDR_P_IMM_OFF_PREIND, + OP_LDR_P_IMM_OFF_PREIND, + OP_LDR_P_IMM_OFF_PREIND, + OP_LDR_P_IMM_OFF_PREIND, + OP_LDR_P_IMM_OFF_PREIND, + OP_LDR_P_IMM_OFF_PREIND, + OP_LDR_P_IMM_OFF_PREIND, + OP_LDR_P_IMM_OFF_PREIND, + OP_LDR_P_IMM_OFF_PREIND, + OP_LDR_P_IMM_OFF_PREIND, + OP_LDR_P_IMM_OFF_PREIND, + OP_LDR_P_IMM_OFF_PREIND, + OP_LDR_P_IMM_OFF_PREIND, + OP_LDR_P_IMM_OFF_PREIND, //010 1101 1 1111 +//------------------------------------------ + OP_STRB_P_IMM_OFF, //010 1110 0 0000 + OP_STRB_P_IMM_OFF, + OP_STRB_P_IMM_OFF, + OP_STRB_P_IMM_OFF, + OP_STRB_P_IMM_OFF, + OP_STRB_P_IMM_OFF, + OP_STRB_P_IMM_OFF, + OP_STRB_P_IMM_OFF, + OP_STRB_P_IMM_OFF, + OP_STRB_P_IMM_OFF, + OP_STRB_P_IMM_OFF, + OP_STRB_P_IMM_OFF, + OP_STRB_P_IMM_OFF, + OP_STRB_P_IMM_OFF, + OP_STRB_P_IMM_OFF, + OP_STRB_P_IMM_OFF, + + OP_LDRB_P_IMM_OFF, + OP_LDRB_P_IMM_OFF, + OP_LDRB_P_IMM_OFF, + OP_LDRB_P_IMM_OFF, + OP_LDRB_P_IMM_OFF, + OP_LDRB_P_IMM_OFF, + OP_LDRB_P_IMM_OFF, + OP_LDRB_P_IMM_OFF, + OP_LDRB_P_IMM_OFF, + OP_LDRB_P_IMM_OFF, + OP_LDRB_P_IMM_OFF, + OP_LDRB_P_IMM_OFF, + OP_LDRB_P_IMM_OFF, + OP_LDRB_P_IMM_OFF, + OP_LDRB_P_IMM_OFF, + OP_LDRB_P_IMM_OFF, //010 1110 1 1111 +//------------------------------------------ + OP_STRB_P_IMM_OFF_PREIND, //010 1111 0 0000 + OP_STRB_P_IMM_OFF_PREIND, + OP_STRB_P_IMM_OFF_PREIND, + OP_STRB_P_IMM_OFF_PREIND, + OP_STRB_P_IMM_OFF_PREIND, + OP_STRB_P_IMM_OFF_PREIND, + OP_STRB_P_IMM_OFF_PREIND, + OP_STRB_P_IMM_OFF_PREIND, + OP_STRB_P_IMM_OFF_PREIND, + OP_STRB_P_IMM_OFF_PREIND, + OP_STRB_P_IMM_OFF_PREIND, + OP_STRB_P_IMM_OFF_PREIND, + OP_STRB_P_IMM_OFF_PREIND, + OP_STRB_P_IMM_OFF_PREIND, + OP_STRB_P_IMM_OFF_PREIND, + OP_STRB_P_IMM_OFF_PREIND, + + OP_LDRB_P_IMM_OFF_PREIND, + OP_LDRB_P_IMM_OFF_PREIND, + OP_LDRB_P_IMM_OFF_PREIND, + OP_LDRB_P_IMM_OFF_PREIND, + OP_LDRB_P_IMM_OFF_PREIND, + OP_LDRB_P_IMM_OFF_PREIND, + OP_LDRB_P_IMM_OFF_PREIND, + OP_LDRB_P_IMM_OFF_PREIND, + OP_LDRB_P_IMM_OFF_PREIND, + OP_LDRB_P_IMM_OFF_PREIND, + OP_LDRB_P_IMM_OFF_PREIND, + OP_LDRB_P_IMM_OFF_PREIND, + OP_LDRB_P_IMM_OFF_PREIND, + OP_LDRB_P_IMM_OFF_PREIND, + OP_LDRB_P_IMM_OFF_PREIND, + OP_LDRB_P_IMM_OFF_PREIND, //010 1111 1 1111 +//------------------------------------------ + OP_STR_M_LSL_IMM_OFF_POSTIND, //011 0000 0 0000 + OP_UND, + OP_STR_M_LSR_IMM_OFF_POSTIND, + OP_UND, + OP_STR_M_ASR_IMM_OFF_POSTIND, + OP_UND, + OP_STR_M_ROR_IMM_OFF_POSTIND, + OP_UND, + OP_STR_M_LSL_IMM_OFF_POSTIND, + OP_UND, + OP_STR_M_LSR_IMM_OFF_POSTIND, + OP_UND, + OP_STR_M_ASR_IMM_OFF_POSTIND, + OP_UND, + OP_STR_M_ROR_IMM_OFF_POSTIND, + OP_UND, + + OP_LDR_M_LSL_IMM_OFF_POSTIND, + OP_UND, + OP_LDR_M_LSR_IMM_OFF_POSTIND, + OP_UND, + OP_LDR_M_ASR_IMM_OFF_POSTIND, + OP_UND, + OP_LDR_M_ROR_IMM_OFF_POSTIND, + OP_UND, + OP_LDR_M_LSL_IMM_OFF_POSTIND, + OP_UND, + OP_LDR_M_LSR_IMM_OFF_POSTIND, + OP_UND, + OP_LDR_M_ASR_IMM_OFF_POSTIND, + OP_UND, + OP_LDR_M_ROR_IMM_OFF_POSTIND, + OP_UND, //011 0000 1 1111 +//------------------------------------------ + OP_UND, //011 0001 0 0000 + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, //011 0001 1 1111 +//------------------------------------------ + OP_STRB_M_LSL_IMM_OFF_POSTIND, //011 0010 0 0000 + OP_UND, + OP_STRB_M_LSR_IMM_OFF_POSTIND, + OP_UND, + OP_STRB_M_ASR_IMM_OFF_POSTIND, + OP_UND, + OP_STRB_M_ROR_IMM_OFF_POSTIND, + OP_UND, + OP_STRB_M_LSL_IMM_OFF_POSTIND, + OP_UND, + OP_STRB_M_LSR_IMM_OFF_POSTIND, + OP_UND, + OP_STRB_M_ASR_IMM_OFF_POSTIND, + OP_UND, + OP_STRB_M_ROR_IMM_OFF_POSTIND, + OP_UND, + + OP_LDRB_M_LSL_IMM_OFF_POSTIND, + OP_UND, + OP_LDRB_M_LSR_IMM_OFF_POSTIND, + OP_UND, + OP_LDRB_M_ASR_IMM_OFF_POSTIND, + OP_UND, + OP_LDRB_M_ROR_IMM_OFF_POSTIND, + OP_UND, + OP_LDRB_M_LSL_IMM_OFF_POSTIND, + OP_UND, + OP_LDRB_M_LSR_IMM_OFF_POSTIND, + OP_UND, + OP_LDRB_M_ASR_IMM_OFF_POSTIND, + OP_UND, + OP_LDRB_M_ROR_IMM_OFF_POSTIND, + OP_UND, //011 0010 1 1111 +//------------------------------------------ + OP_STRBT_M_LSL_IMM_OFF_POSTIND, //011 0011 0 0000 + OP_UND, + OP_STRBT_M_LSR_IMM_OFF_POSTIND, + OP_UND, + OP_STRBT_M_ASR_IMM_OFF_POSTIND, + OP_UND, + OP_STRBT_M_ROR_IMM_OFF_POSTIND, + OP_UND, + OP_STRBT_M_LSL_IMM_OFF_POSTIND, + OP_UND, + OP_STRBT_M_LSR_IMM_OFF_POSTIND, + OP_UND, + OP_STRBT_M_ASR_IMM_OFF_POSTIND, + OP_UND, + OP_STRBT_M_ROR_IMM_OFF_POSTIND, + OP_UND, + + OP_LDRBT_M_LSL_IMM_OFF_POSTIND, + OP_UND, + OP_LDRBT_M_LSR_IMM_OFF_POSTIND, + OP_UND, + OP_LDRBT_M_ASR_IMM_OFF_POSTIND, + OP_UND, + OP_LDRBT_M_ROR_IMM_OFF_POSTIND, + OP_UND, + OP_LDRBT_M_LSL_IMM_OFF_POSTIND, + OP_UND, + OP_LDRBT_M_LSR_IMM_OFF_POSTIND, + OP_UND, + OP_LDRBT_M_ASR_IMM_OFF_POSTIND, + OP_UND, + OP_LDRBT_M_ROR_IMM_OFF_POSTIND, + OP_UND, //011 0011 1 1111 +//------------------------------------------ + OP_STR_P_LSL_IMM_OFF_POSTIND, //011 0100 0 0000 + OP_UND, + OP_STR_P_LSR_IMM_OFF_POSTIND, + OP_UND, + OP_STR_P_ASR_IMM_OFF_POSTIND, + OP_UND, + OP_STR_P_ROR_IMM_OFF_POSTIND, + OP_UND, + OP_STR_P_LSL_IMM_OFF_POSTIND, + OP_UND, + OP_STR_P_LSR_IMM_OFF_POSTIND, + OP_UND, + OP_STR_P_ASR_IMM_OFF_POSTIND, + OP_UND, + OP_STR_P_ROR_IMM_OFF_POSTIND, + OP_UND, + + OP_LDR_P_LSL_IMM_OFF_POSTIND, + OP_UND, + OP_LDR_P_LSR_IMM_OFF_POSTIND, + OP_UND, + OP_LDR_P_ASR_IMM_OFF_POSTIND, + OP_UND, + OP_LDR_P_ROR_IMM_OFF_POSTIND, + OP_UND, + OP_LDR_P_LSL_IMM_OFF_POSTIND, + OP_UND, + OP_LDR_P_LSR_IMM_OFF_POSTIND, + OP_UND, + OP_LDR_P_ASR_IMM_OFF_POSTIND, + OP_UND, + OP_LDR_P_ROR_IMM_OFF_POSTIND, + OP_UND, //011 0100 1 1111 +//------------------------------------------ + OP_UND, //011 0101 0 0000 + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, //011 0101 1 1111 +//------------------------------------------ + OP_STRB_P_LSL_IMM_OFF_POSTIND, //011 0110 0 0000 + OP_UND, + OP_STRB_P_LSR_IMM_OFF_POSTIND, + OP_UND, + OP_STRB_P_ASR_IMM_OFF_POSTIND, + OP_UND, + OP_STRB_P_ROR_IMM_OFF_POSTIND, + OP_UND, + OP_STRB_P_LSL_IMM_OFF_POSTIND, + OP_UND, + OP_STRB_P_LSR_IMM_OFF_POSTIND, + OP_UND, + OP_STRB_P_ASR_IMM_OFF_POSTIND, + OP_UND, + OP_STRB_P_ROR_IMM_OFF_POSTIND, + OP_UND, + + OP_LDRB_P_LSL_IMM_OFF_POSTIND, + OP_UND, + OP_LDRB_P_LSR_IMM_OFF_POSTIND, + OP_UND, + OP_LDRB_P_ASR_IMM_OFF_POSTIND, + OP_UND, + OP_LDRB_P_ROR_IMM_OFF_POSTIND, + OP_UND, + OP_LDRB_P_LSL_IMM_OFF_POSTIND, + OP_UND, + OP_LDRB_P_LSR_IMM_OFF_POSTIND, + OP_UND, + OP_LDRB_P_ASR_IMM_OFF_POSTIND, + OP_UND, + OP_LDRB_P_ROR_IMM_OFF_POSTIND, + OP_UND, +//------------------------------------------ + OP_STRBT_P_LSL_IMM_OFF_POSTIND, //011 0111 0 0000 + OP_UND, + OP_STRBT_P_LSR_IMM_OFF_POSTIND, + OP_UND, + OP_STRBT_P_ASR_IMM_OFF_POSTIND, + OP_UND, + OP_STRBT_P_ROR_IMM_OFF_POSTIND, + OP_UND, + OP_STRBT_P_LSL_IMM_OFF_POSTIND, + OP_UND, + OP_STRBT_P_LSR_IMM_OFF_POSTIND, + OP_UND, + OP_STRBT_P_ASR_IMM_OFF_POSTIND, + OP_UND, + OP_STRBT_P_ROR_IMM_OFF_POSTIND, + OP_UND, + + OP_LDRBT_P_LSL_IMM_OFF_POSTIND, + OP_UND, + OP_LDRBT_P_LSR_IMM_OFF_POSTIND, + OP_UND, + OP_LDRBT_P_ASR_IMM_OFF_POSTIND, + OP_UND, + OP_LDRBT_P_ROR_IMM_OFF_POSTIND, + OP_UND, + OP_LDRBT_P_LSL_IMM_OFF_POSTIND, + OP_UND, + OP_LDRBT_P_LSR_IMM_OFF_POSTIND, + OP_UND, + OP_LDRBT_P_ASR_IMM_OFF_POSTIND, + OP_UND, + OP_LDRBT_P_ROR_IMM_OFF_POSTIND, + OP_UND, +//------------------------------------------ + OP_STR_M_LSL_IMM_OFF, //011 1000 0 0000 + OP_UND, + OP_STR_M_LSR_IMM_OFF, + OP_UND, + OP_STR_M_ASR_IMM_OFF, + OP_UND, + OP_STR_M_ROR_IMM_OFF, + OP_UND, + OP_STR_M_LSL_IMM_OFF, + OP_UND, + OP_STR_M_LSR_IMM_OFF, + OP_UND, + OP_STR_M_ASR_IMM_OFF, + OP_UND, + OP_STR_M_ROR_IMM_OFF, + OP_UND, + + OP_LDR_M_LSL_IMM_OFF, + OP_UND, + OP_LDR_M_LSR_IMM_OFF, + OP_UND, + OP_LDR_M_ASR_IMM_OFF, + OP_UND, + OP_LDR_M_ROR_IMM_OFF, + OP_UND, + OP_LDR_M_LSL_IMM_OFF, + OP_UND, + OP_LDR_M_LSR_IMM_OFF, + OP_UND, + OP_LDR_M_ASR_IMM_OFF, + OP_UND, + OP_LDR_M_ROR_IMM_OFF, + OP_UND, +//------------------------------------------ + OP_STR_M_LSL_IMM_OFF_PREIND, //011 1001 0 0000 + OP_UND, + OP_STR_M_LSR_IMM_OFF_PREIND, + OP_UND, + OP_STR_M_ASR_IMM_OFF_PREIND, + OP_UND, + OP_STR_M_ROR_IMM_OFF_PREIND, + OP_UND, + OP_STR_M_LSL_IMM_OFF_PREIND, + OP_UND, + OP_STR_M_LSR_IMM_OFF_PREIND, + OP_UND, + OP_STR_M_ASR_IMM_OFF_PREIND, + OP_UND, + OP_STR_M_ROR_IMM_OFF_PREIND, + OP_UND, + + OP_LDR_M_LSL_IMM_OFF_PREIND, + OP_UND, + OP_LDR_M_LSR_IMM_OFF_PREIND, + OP_UND, + OP_LDR_M_ASR_IMM_OFF_PREIND, + OP_UND, + OP_LDR_M_ROR_IMM_OFF_PREIND, + OP_UND, + OP_LDR_M_LSL_IMM_OFF_PREIND, + OP_UND, + OP_LDR_M_LSR_IMM_OFF_PREIND, + OP_UND, + OP_LDR_M_ASR_IMM_OFF_PREIND, + OP_UND, + OP_LDR_M_ROR_IMM_OFF_PREIND, + OP_UND, +//------------------------------------------ + OP_STRB_M_LSL_IMM_OFF, //011 1010 0 0000 + OP_UND, + OP_STRB_M_LSR_IMM_OFF, + OP_UND, + OP_STRB_M_ASR_IMM_OFF, + OP_UND, + OP_STRB_M_ROR_IMM_OFF, + OP_UND, + OP_STRB_M_LSL_IMM_OFF, + OP_UND, + OP_STRB_M_LSR_IMM_OFF, + OP_UND, + OP_STRB_M_ASR_IMM_OFF, + OP_UND, + OP_STRB_M_ROR_IMM_OFF, + OP_UND, + + OP_LDRB_M_LSL_IMM_OFF, + OP_UND, + OP_LDRB_M_LSR_IMM_OFF, + OP_UND, + OP_LDRB_M_ASR_IMM_OFF, + OP_UND, + OP_LDRB_M_ROR_IMM_OFF, + OP_UND, + OP_LDRB_M_LSL_IMM_OFF, + OP_UND, + OP_LDRB_M_LSR_IMM_OFF, + OP_UND, + OP_LDRB_M_ASR_IMM_OFF, + OP_UND, + OP_LDRB_M_ROR_IMM_OFF, + OP_UND, +//------------------------------------------ + OP_STRB_M_LSL_IMM_OFF_PREIND, //011 1011 0 0000 + OP_UND, + OP_STRB_M_LSR_IMM_OFF_PREIND, + OP_UND, + OP_STRB_M_ASR_IMM_OFF_PREIND, + OP_UND, + OP_STRB_M_ROR_IMM_OFF_PREIND, + OP_UND, + OP_STRB_M_LSL_IMM_OFF_PREIND, + OP_UND, + OP_STRB_M_LSR_IMM_OFF_PREIND, + OP_UND, + OP_STRB_M_ASR_IMM_OFF_PREIND, + OP_UND, + OP_STRB_M_ROR_IMM_OFF_PREIND, + OP_UND, + + OP_LDRB_M_LSL_IMM_OFF_PREIND, + OP_UND, + OP_LDRB_M_LSR_IMM_OFF_PREIND, + OP_UND, + OP_LDRB_M_ASR_IMM_OFF_PREIND, + OP_UND, + OP_LDRB_M_ROR_IMM_OFF_PREIND, + OP_UND, + OP_LDRB_M_LSL_IMM_OFF_PREIND, + OP_UND, + OP_LDRB_M_LSR_IMM_OFF_PREIND, + OP_UND, + OP_LDRB_M_ASR_IMM_OFF_PREIND, + OP_UND, + OP_LDRB_M_ROR_IMM_OFF_PREIND, + OP_UND, +//------------------------------------------ + OP_STR_P_LSL_IMM_OFF, //011 1100 0 0000 + OP_UND, + OP_STR_P_LSR_IMM_OFF, + OP_UND, + OP_STR_P_ASR_IMM_OFF, + OP_UND, + OP_STR_P_ROR_IMM_OFF, + OP_UND, + OP_STR_P_LSL_IMM_OFF, + OP_UND, + OP_STR_P_LSR_IMM_OFF, + OP_UND, + OP_STR_P_ASR_IMM_OFF, + OP_UND, + OP_STR_P_ROR_IMM_OFF, + OP_UND, + + OP_LDR_P_LSL_IMM_OFF, + OP_UND, + OP_LDR_P_LSR_IMM_OFF, + OP_UND, + OP_LDR_P_ASR_IMM_OFF, + OP_UND, + OP_LDR_P_ROR_IMM_OFF, + OP_UND, + OP_LDR_P_LSL_IMM_OFF, + OP_UND, + OP_LDR_P_LSR_IMM_OFF, + OP_UND, + OP_LDR_P_ASR_IMM_OFF, + OP_UND, + OP_LDR_P_ROR_IMM_OFF, + OP_UND, +//------------------------------------------ + OP_STR_P_LSL_IMM_OFF_PREIND, //011 1101 0 0000 + OP_UND, + OP_STR_P_LSR_IMM_OFF_PREIND, + OP_UND, + OP_STR_P_ASR_IMM_OFF_PREIND, + OP_UND, + OP_STR_P_ROR_IMM_OFF_PREIND, + OP_UND, + OP_STR_P_LSL_IMM_OFF_PREIND, + OP_UND, + OP_STR_P_LSR_IMM_OFF_PREIND, + OP_UND, + OP_STR_P_ASR_IMM_OFF_PREIND, + OP_UND, + OP_STR_P_ROR_IMM_OFF_PREIND, + OP_UND, + + OP_LDR_P_LSL_IMM_OFF_PREIND, + OP_UND, + OP_LDR_P_LSR_IMM_OFF_PREIND, + OP_UND, + OP_LDR_P_ASR_IMM_OFF_PREIND, + OP_UND, + OP_LDR_P_ROR_IMM_OFF_PREIND, + OP_UND, + OP_LDR_P_LSL_IMM_OFF_PREIND, + OP_UND, + OP_LDR_P_LSR_IMM_OFF_PREIND, + OP_UND, + OP_LDR_P_ASR_IMM_OFF_PREIND, + OP_UND, + OP_LDR_P_ROR_IMM_OFF_PREIND, + OP_UND, +//------------------------------------------ + OP_STRB_P_LSL_IMM_OFF, //011 1110 0 0000 + OP_UND, + OP_STRB_P_LSR_IMM_OFF, + OP_UND, + OP_STRB_P_ASR_IMM_OFF, + OP_UND, + OP_STRB_P_ROR_IMM_OFF, + OP_UND, + OP_STRB_P_LSL_IMM_OFF, + OP_UND, + OP_STRB_P_LSR_IMM_OFF, + OP_UND, + OP_STRB_P_ASR_IMM_OFF, + OP_UND, + OP_STRB_P_ROR_IMM_OFF, + OP_UND, + + OP_LDRB_P_LSL_IMM_OFF, + OP_UND, + OP_LDRB_P_LSR_IMM_OFF, + OP_UND, + OP_LDRB_P_ASR_IMM_OFF, + OP_UND, + OP_LDRB_P_ROR_IMM_OFF, + OP_UND, + OP_LDRB_P_LSL_IMM_OFF, + OP_UND, + OP_LDRB_P_LSR_IMM_OFF, + OP_UND, + OP_LDRB_P_ASR_IMM_OFF, + OP_UND, + OP_LDRB_P_ROR_IMM_OFF, + OP_UND, +//------------------------------------------ + OP_STRB_P_LSL_IMM_OFF_PREIND, //011 1111 0 0000 + OP_UND, + OP_STRB_P_LSR_IMM_OFF_PREIND, + OP_UND, + OP_STRB_P_ASR_IMM_OFF_PREIND, + OP_UND, + OP_STRB_P_ROR_IMM_OFF_PREIND, + OP_UND, + OP_STRB_P_LSL_IMM_OFF_PREIND, + OP_UND, + OP_STRB_P_LSR_IMM_OFF_PREIND, + OP_UND, + OP_STRB_P_ASR_IMM_OFF_PREIND, + OP_UND, + OP_STRB_P_ROR_IMM_OFF_PREIND, + OP_UND, + + OP_LDRB_P_LSL_IMM_OFF_PREIND, + OP_UND, + OP_LDRB_P_LSR_IMM_OFF_PREIND, + OP_UND, + OP_LDRB_P_ASR_IMM_OFF_PREIND, + OP_UND, + OP_LDRB_P_ROR_IMM_OFF_PREIND, + OP_UND, + OP_LDRB_P_LSL_IMM_OFF_PREIND, + OP_UND, + OP_LDRB_P_LSR_IMM_OFF_PREIND, + OP_UND, + OP_LDRB_P_ASR_IMM_OFF_PREIND, + OP_UND, + OP_LDRB_P_ROR_IMM_OFF_PREIND, + OP_UND, //011 1111 1 1111 +//------------------------------------------ + OP_STMDA, //100 0000 0 0000 + OP_STMDA, + OP_STMDA, + OP_STMDA, + OP_STMDA, + OP_STMDA, + OP_STMDA, + OP_STMDA, + OP_STMDA, + OP_STMDA, + OP_STMDA, + OP_STMDA, + OP_STMDA, + OP_STMDA, + OP_STMDA, + OP_STMDA, + + OP_LDMDA, + OP_LDMDA, + OP_LDMDA, + OP_LDMDA, + OP_LDMDA, + OP_LDMDA, + OP_LDMDA, + OP_LDMDA, + OP_LDMDA, + OP_LDMDA, + OP_LDMDA, + OP_LDMDA, + OP_LDMDA, + OP_LDMDA, + OP_LDMDA, + OP_LDMDA, +//------------------------------------------ + OP_STMDA_W, //100 0001 0 0000 + OP_STMDA_W, + OP_STMDA_W, + OP_STMDA_W, + OP_STMDA_W, + OP_STMDA_W, + OP_STMDA_W, + OP_STMDA_W, + OP_STMDA_W, + OP_STMDA_W, + OP_STMDA_W, + OP_STMDA_W, + OP_STMDA_W, + OP_STMDA_W, + OP_STMDA_W, + OP_STMDA_W, + + OP_LDMDA_W, + OP_LDMDA_W, + OP_LDMDA_W, + OP_LDMDA_W, + OP_LDMDA_W, + OP_LDMDA_W, + OP_LDMDA_W, + OP_LDMDA_W, + OP_LDMDA_W, + OP_LDMDA_W, + OP_LDMDA_W, + OP_LDMDA_W, + OP_LDMDA_W, + OP_LDMDA_W, + OP_LDMDA_W, + OP_LDMDA_W, +//------------------------------------------ + OP_STMDA2, //100 0010 0 0000 + OP_STMDA2, + OP_STMDA2, + OP_STMDA2, + OP_STMDA2, + OP_STMDA2, + OP_STMDA2, + OP_STMDA2, + OP_STMDA2, + OP_STMDA2, + OP_STMDA2, + OP_STMDA2, + OP_STMDA2, + OP_STMDA2, + OP_STMDA2, + OP_STMDA2, + + OP_LDMDA2, + OP_LDMDA2, + OP_LDMDA2, + OP_LDMDA2, + OP_LDMDA2, + OP_LDMDA2, + OP_LDMDA2, + OP_LDMDA2, + OP_LDMDA2, + OP_LDMDA2, + OP_LDMDA2, + OP_LDMDA2, + OP_LDMDA2, + OP_LDMDA2, + OP_LDMDA2, + OP_LDMDA2, +//------------------------------------------ + OP_STMDA2_W, //100 0011 0 0000 + OP_STMDA2_W, + OP_STMDA2_W, + OP_STMDA2_W, + OP_STMDA2_W, + OP_STMDA2_W, + OP_STMDA2_W, + OP_STMDA2_W, + OP_STMDA2_W, + OP_STMDA2_W, + OP_STMDA2_W, + OP_STMDA2_W, + OP_STMDA2_W, + OP_STMDA2_W, + OP_STMDA2_W, + OP_STMDA2_W, + + OP_LDMDA2_W, + OP_LDMDA2_W, + OP_LDMDA2_W, + OP_LDMDA2_W, + OP_LDMDA2_W, + OP_LDMDA2_W, + OP_LDMDA2_W, + OP_LDMDA2_W, + OP_LDMDA2_W, + OP_LDMDA2_W, + OP_LDMDA2_W, + OP_LDMDA2_W, + OP_LDMDA2_W, + OP_LDMDA2_W, + OP_LDMDA2_W, + OP_LDMDA2_W, +//------------------------------------------ + OP_STMIA, //100 0100 0 0000 + OP_STMIA, + OP_STMIA, + OP_STMIA, + OP_STMIA, + OP_STMIA, + OP_STMIA, + OP_STMIA, + OP_STMIA, + OP_STMIA, + OP_STMIA, + OP_STMIA, + OP_STMIA, + OP_STMIA, + OP_STMIA, + OP_STMIA, + + OP_LDMIA, + OP_LDMIA, + OP_LDMIA, + OP_LDMIA, + OP_LDMIA, + OP_LDMIA, + OP_LDMIA, + OP_LDMIA, + OP_LDMIA, + OP_LDMIA, + OP_LDMIA, + OP_LDMIA, + OP_LDMIA, + OP_LDMIA, + OP_LDMIA, + OP_LDMIA, +//------------------------------------------ + OP_STMIA_W, //100 0101 0 0000 + OP_STMIA_W, + OP_STMIA_W, + OP_STMIA_W, + OP_STMIA_W, + OP_STMIA_W, + OP_STMIA_W, + OP_STMIA_W, + OP_STMIA_W, + OP_STMIA_W, + OP_STMIA_W, + OP_STMIA_W, + OP_STMIA_W, + OP_STMIA_W, + OP_STMIA_W, + OP_STMIA_W, + + OP_LDMIA_W, + OP_LDMIA_W, + OP_LDMIA_W, + OP_LDMIA_W, + OP_LDMIA_W, + OP_LDMIA_W, + OP_LDMIA_W, + OP_LDMIA_W, + OP_LDMIA_W, + OP_LDMIA_W, + OP_LDMIA_W, + OP_LDMIA_W, + OP_LDMIA_W, + OP_LDMIA_W, + OP_LDMIA_W, + OP_LDMIA_W, +//------------------------------------------ + OP_STMIA2, //100 0110 0 0000 + OP_STMIA2, + OP_STMIA2, + OP_STMIA2, + OP_STMIA2, + OP_STMIA2, + OP_STMIA2, + OP_STMIA2, + OP_STMIA2, + OP_STMIA2, + OP_STMIA2, + OP_STMIA2, + OP_STMIA2, + OP_STMIA2, + OP_STMIA2, + OP_STMIA2, + + OP_LDMIA2, + OP_LDMIA2, + OP_LDMIA2, + OP_LDMIA2, + OP_LDMIA2, + OP_LDMIA2, + OP_LDMIA2, + OP_LDMIA2, + OP_LDMIA2, + OP_LDMIA2, + OP_LDMIA2, + OP_LDMIA2, + OP_LDMIA2, + OP_LDMIA2, + OP_LDMIA2, + OP_LDMIA2, +//------------------------------------------ + OP_STMIA2_W, //100 0111 0 0000 + OP_STMIA2_W, + OP_STMIA2_W, + OP_STMIA2_W, + OP_STMIA2_W, + OP_STMIA2_W, + OP_STMIA2_W, + OP_STMIA2_W, + OP_STMIA2_W, + OP_STMIA2_W, + OP_STMIA2_W, + OP_STMIA2_W, + OP_STMIA2_W, + OP_STMIA2_W, + OP_STMIA2_W, + OP_STMIA2_W, + + OP_LDMIA2_W, + OP_LDMIA2_W, + OP_LDMIA2_W, + OP_LDMIA2_W, + OP_LDMIA2_W, + OP_LDMIA2_W, + OP_LDMIA2_W, + OP_LDMIA2_W, + OP_LDMIA2_W, + OP_LDMIA2_W, + OP_LDMIA2_W, + OP_LDMIA2_W, + OP_LDMIA2_W, + OP_LDMIA2_W, + OP_LDMIA2_W, + OP_LDMIA2_W, +//------------------------------------------ + OP_STMDB, //100 1000 0 0000 + OP_STMDB, + OP_STMDB, + OP_STMDB, + OP_STMDB, + OP_STMDB, + OP_STMDB, + OP_STMDB, + OP_STMDB, + OP_STMDB, + OP_STMDB, + OP_STMDB, + OP_STMDB, + OP_STMDB, + OP_STMDB, + OP_STMDB, + + OP_LDMDB, + OP_LDMDB, + OP_LDMDB, + OP_LDMDB, + OP_LDMDB, + OP_LDMDB, + OP_LDMDB, + OP_LDMDB, + OP_LDMDB, + OP_LDMDB, + OP_LDMDB, + OP_LDMDB, + OP_LDMDB, + OP_LDMDB, + OP_LDMDB, + OP_LDMDB, +//------------------------------------------ + OP_STMDB_W, //100 1001 0 0000 + OP_STMDB_W, + OP_STMDB_W, + OP_STMDB_W, + OP_STMDB_W, + OP_STMDB_W, + OP_STMDB_W, + OP_STMDB_W, + OP_STMDB_W, + OP_STMDB_W, + OP_STMDB_W, + OP_STMDB_W, + OP_STMDB_W, + OP_STMDB_W, + OP_STMDB_W, + OP_STMDB_W, + + OP_LDMDB_W, + OP_LDMDB_W, + OP_LDMDB_W, + OP_LDMDB_W, + OP_LDMDB_W, + OP_LDMDB_W, + OP_LDMDB_W, + OP_LDMDB_W, + OP_LDMDB_W, + OP_LDMDB_W, + OP_LDMDB_W, + OP_LDMDB_W, + OP_LDMDB_W, + OP_LDMDB_W, + OP_LDMDB_W, + OP_LDMDB_W, +//------------------------------------------ + OP_STMDB2, //100 1010 0 0000 + OP_STMDB2, + OP_STMDB2, + OP_STMDB2, + OP_STMDB2, + OP_STMDB2, + OP_STMDB2, + OP_STMDB2, + OP_STMDB2, + OP_STMDB2, + OP_STMDB2, + OP_STMDB2, + OP_STMDB2, + OP_STMDB2, + OP_STMDB2, + OP_STMDB2, + + OP_LDMDB2, + OP_LDMDB2, + OP_LDMDB2, + OP_LDMDB2, + OP_LDMDB2, + OP_LDMDB2, + OP_LDMDB2, + OP_LDMDB2, + OP_LDMDB2, + OP_LDMDB2, + OP_LDMDB2, + OP_LDMDB2, + OP_LDMDB2, + OP_LDMDB2, + OP_LDMDB2, + OP_LDMDB2, +//------------------------------------------ + OP_STMDB2_W, //100 1011 0 0000 + OP_STMDB2_W, + OP_STMDB2_W, + OP_STMDB2_W, + OP_STMDB2_W, + OP_STMDB2_W, + OP_STMDB2_W, + OP_STMDB2_W, + OP_STMDB2_W, + OP_STMDB2_W, + OP_STMDB2_W, + OP_STMDB2_W, + OP_STMDB2_W, + OP_STMDB2_W, + OP_STMDB2_W, + OP_STMDB2_W, + + OP_LDMDB2_W, + OP_LDMDB2_W, + OP_LDMDB2_W, + OP_LDMDB2_W, + OP_LDMDB2_W, + OP_LDMDB2_W, + OP_LDMDB2_W, + OP_LDMDB2_W, + OP_LDMDB2_W, + OP_LDMDB2_W, + OP_LDMDB2_W, + OP_LDMDB2_W, + OP_LDMDB2_W, + OP_LDMDB2_W, + OP_LDMDB2_W, + OP_LDMDB2_W, +//------------------------------------------ + + + OP_STMIB, //100 1100 0 0000 + OP_STMIB, + OP_STMIB, + OP_STMIB, + OP_STMIB, + OP_STMIB, + OP_STMIB, + OP_STMIB, + OP_STMIB, + OP_STMIB, + OP_STMIB, + OP_STMIB, + OP_STMIB, + OP_STMIB, + OP_STMIB, + OP_STMIB, + + OP_LDMIB, + OP_LDMIB, + OP_LDMIB, + OP_LDMIB, + OP_LDMIB, + OP_LDMIB, + OP_LDMIB, + OP_LDMIB, + OP_LDMIB, + OP_LDMIB, + OP_LDMIB, + OP_LDMIB, + OP_LDMIB, + OP_LDMIB, + OP_LDMIB, + OP_LDMIB, +//------------------------------------------ + OP_STMIB_W, //100 1101 0 0000 + OP_STMIB_W, + OP_STMIB_W, + OP_STMIB_W, + OP_STMIB_W, + OP_STMIB_W, + OP_STMIB_W, + OP_STMIB_W, + OP_STMIB_W, + OP_STMIB_W, + OP_STMIB_W, + OP_STMIB_W, + OP_STMIB_W, + OP_STMIB_W, + OP_STMIB_W, + OP_STMIB_W, + + OP_LDMIB_W, + OP_LDMIB_W, + OP_LDMIB_W, + OP_LDMIB_W, + OP_LDMIB_W, + OP_LDMIB_W, + OP_LDMIB_W, + OP_LDMIB_W, + OP_LDMIB_W, + OP_LDMIB_W, + OP_LDMIB_W, + OP_LDMIB_W, + OP_LDMIB_W, + OP_LDMIB_W, + OP_LDMIB_W, + OP_LDMIB_W, +//------------------------------------------ + OP_STMIB2, //100 1110 0 0000 + OP_STMIB2, + OP_STMIB2, + OP_STMIB2, + OP_STMIB2, + OP_STMIB2, + OP_STMIB2, + OP_STMIB2, + OP_STMIB2, + OP_STMIB2, + OP_STMIB2, + OP_STMIB2, + OP_STMIB2, + OP_STMIB2, + OP_STMIB2, + OP_STMIB2, + + OP_LDMIB2, + OP_LDMIB2, + OP_LDMIB2, + OP_LDMIB2, + OP_LDMIB2, + OP_LDMIB2, + OP_LDMIB2, + OP_LDMIB2, + OP_LDMIB2, + OP_LDMIB2, + OP_LDMIB2, + OP_LDMIB2, + OP_LDMIB2, + OP_LDMIB2, + OP_LDMIB2, + OP_LDMIB2, +//------------------------------------------ + OP_STMIB2_W, //100 1111 0 0000 + OP_STMIB2_W, + OP_STMIB2_W, + OP_STMIB2_W, + OP_STMIB2_W, + OP_STMIB2_W, + OP_STMIB2_W, + OP_STMIB2_W, + OP_STMIB2_W, + OP_STMIB2_W, + OP_STMIB2_W, + OP_STMIB2_W, + OP_STMIB2_W, + OP_STMIB2_W, + OP_STMIB2_W, + OP_STMIB2_W, + + OP_LDMIB2_W, + OP_LDMIB2_W, + OP_LDMIB2_W, + OP_LDMIB2_W, + OP_LDMIB2_W, + OP_LDMIB2_W, + OP_LDMIB2_W, + OP_LDMIB2_W, + OP_LDMIB2_W, + OP_LDMIB2_W, + OP_LDMIB2_W, + OP_LDMIB2_W, + OP_LDMIB2_W, + OP_LDMIB2_W, + OP_LDMIB2_W, + OP_LDMIB2_W, +//------------------------------------------ + OP_B, //101 0000 0 0000 + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, +//------------------------------------------ + OP_B, //101 0001 0 0000 + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, +//------------------------------------------ + OP_B, //101 0010 0 0000 + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, +//------------------------------------------ + OP_B, //101 0011 0 0000 + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, +//------------------------------------------ + OP_B, //101 0100 0 0000 + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, +//------------------------------------------ + OP_B, //101 0101 0 0000 + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, +//------------------------------------------ + OP_B, //101 0110 0 0000 + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, +//------------------------------------------ + OP_B, //101 0111 0 0000 + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, +//------------------------------------------ + OP_BL, //101 1000 0 0000 + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, +//------------------------------------------ + OP_BL, //101 1001 0 0000 + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, +//------------------------------------------ + OP_BL, //101 1010 0 0000 + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, +//------------------------------------------ + OP_BL, //101 1011 0 0000 + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, +//------------------------------------------ + OP_BL, //101 1100 0 0000 + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, +//------------------------------------------ + OP_BL, //101 1101 0 0000 + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, +//------------------------------------------ + OP_BL, //101 1110 0 0000 + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, +//------------------------------------------ + OP_BL, //101 1111 0 0000 + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, +//------------------------------------------ + OP_STC_OPTION, //110 0000 0 0000 + OP_STC_OPTION, + OP_STC_OPTION, + OP_STC_OPTION, + OP_STC_OPTION, + OP_STC_OPTION, + OP_STC_OPTION, + OP_STC_OPTION, + OP_STC_OPTION, + OP_STC_OPTION, + OP_STC_OPTION, + OP_STC_OPTION, + OP_STC_OPTION, + OP_STC_OPTION, + OP_STC_OPTION, + OP_STC_OPTION, + + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, +//------------------------------------------ + OP_STC_M_POSTIND, //110 0001 0 0000 + OP_STC_M_POSTIND, + OP_STC_M_POSTIND, + OP_STC_M_POSTIND, + OP_STC_M_POSTIND, + OP_STC_M_POSTIND, + OP_STC_M_POSTIND, + OP_STC_M_POSTIND, + OP_STC_M_POSTIND, + OP_STC_M_POSTIND, + OP_STC_M_POSTIND, + OP_STC_M_POSTIND, + OP_STC_M_POSTIND, + OP_STC_M_POSTIND, + OP_STC_M_POSTIND, + OP_STC_M_POSTIND, + + OP_LDC_M_POSTIND, + OP_LDC_M_POSTIND, + OP_LDC_M_POSTIND, + OP_LDC_M_POSTIND, + OP_LDC_M_POSTIND, + OP_LDC_M_POSTIND, + OP_LDC_M_POSTIND, + OP_LDC_M_POSTIND, + OP_LDC_M_POSTIND, + OP_LDC_M_POSTIND, + OP_LDC_M_POSTIND, + OP_LDC_M_POSTIND, + OP_LDC_M_POSTIND, + OP_LDC_M_POSTIND, + OP_LDC_M_POSTIND, + OP_LDC_M_POSTIND, +//------------------------------------------ + OP_STC_OPTION, //110 0010 0 0000 + OP_STC_OPTION, + OP_STC_OPTION, + OP_STC_OPTION, + OP_STC_OPTION, + OP_STC_OPTION, + OP_STC_OPTION, + OP_STC_OPTION, + OP_STC_OPTION, + OP_STC_OPTION, + OP_STC_OPTION, + OP_STC_OPTION, + OP_STC_OPTION, + OP_STC_OPTION, + OP_STC_OPTION, + OP_STC_OPTION, + + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, +//------------------------------------------ + OP_STC_M_POSTIND, //110 0011 0 0000 + OP_STC_M_POSTIND, + OP_STC_M_POSTIND, + OP_STC_M_POSTIND, + OP_STC_M_POSTIND, + OP_STC_M_POSTIND, + OP_STC_M_POSTIND, + OP_STC_M_POSTIND, + OP_STC_M_POSTIND, + OP_STC_M_POSTIND, + OP_STC_M_POSTIND, + OP_STC_M_POSTIND, + OP_STC_M_POSTIND, + OP_STC_M_POSTIND, + OP_STC_M_POSTIND, + OP_STC_M_POSTIND, + + OP_LDC_M_POSTIND, + OP_LDC_M_POSTIND, + OP_LDC_M_POSTIND, + OP_LDC_M_POSTIND, + OP_LDC_M_POSTIND, + OP_LDC_M_POSTIND, + OP_LDC_M_POSTIND, + OP_LDC_M_POSTIND, + OP_LDC_M_POSTIND, + OP_LDC_M_POSTIND, + OP_LDC_M_POSTIND, + OP_LDC_M_POSTIND, + OP_LDC_M_POSTIND, + OP_LDC_M_POSTIND, + OP_LDC_M_POSTIND, + OP_LDC_M_POSTIND, +//------------------------------------------ + OP_STC_OPTION, //110 0100 0 0000 + OP_STC_OPTION, + OP_STC_OPTION, + OP_STC_OPTION, + OP_STC_OPTION, + OP_STC_OPTION, + OP_STC_OPTION, + OP_STC_OPTION, + OP_STC_OPTION, + OP_STC_OPTION, + OP_STC_OPTION, + OP_STC_OPTION, + OP_STC_OPTION, + OP_STC_OPTION, + OP_STC_OPTION, + OP_STC_OPTION, + + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, +//------------------------------------------ + OP_STC_P_POSTIND, //110 0101 0 0000 + OP_STC_P_POSTIND, + OP_STC_P_POSTIND, + OP_STC_P_POSTIND, + OP_STC_P_POSTIND, + OP_STC_P_POSTIND, + OP_STC_P_POSTIND, + OP_STC_P_POSTIND, + OP_STC_P_POSTIND, + OP_STC_P_POSTIND, + OP_STC_P_POSTIND, + OP_STC_P_POSTIND, + OP_STC_P_POSTIND, + OP_STC_P_POSTIND, + OP_STC_P_POSTIND, + OP_STC_P_POSTIND, + + OP_LDC_P_POSTIND, + OP_LDC_P_POSTIND, + OP_LDC_P_POSTIND, + OP_LDC_P_POSTIND, + OP_LDC_P_POSTIND, + OP_LDC_P_POSTIND, + OP_LDC_P_POSTIND, + OP_LDC_P_POSTIND, + OP_LDC_P_POSTIND, + OP_LDC_P_POSTIND, + OP_LDC_P_POSTIND, + OP_LDC_P_POSTIND, + OP_LDC_P_POSTIND, + OP_LDC_P_POSTIND, + OP_LDC_P_POSTIND, + OP_LDC_P_POSTIND, +//------------------------------------------ + OP_STC_OPTION, //110 0110 0 0000 + OP_STC_OPTION, + OP_STC_OPTION, + OP_STC_OPTION, + OP_STC_OPTION, + OP_STC_OPTION, + OP_STC_OPTION, + OP_STC_OPTION, + OP_STC_OPTION, + OP_STC_OPTION, + OP_STC_OPTION, + OP_STC_OPTION, + OP_STC_OPTION, + OP_STC_OPTION, + OP_STC_OPTION, + OP_STC_OPTION, + + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, +//------------------------------------------ + OP_STC_P_POSTIND, //110 0111 0 0000 + OP_STC_P_POSTIND, + OP_STC_P_POSTIND, + OP_STC_P_POSTIND, + OP_STC_P_POSTIND, + OP_STC_P_POSTIND, + OP_STC_P_POSTIND, + OP_STC_P_POSTIND, + OP_STC_P_POSTIND, + OP_STC_P_POSTIND, + OP_STC_P_POSTIND, + OP_STC_P_POSTIND, + OP_STC_P_POSTIND, + OP_STC_P_POSTIND, + OP_STC_P_POSTIND, + OP_STC_P_POSTIND, + + OP_LDC_P_POSTIND, + OP_LDC_P_POSTIND, + OP_LDC_P_POSTIND, + OP_LDC_P_POSTIND, + OP_LDC_P_POSTIND, + OP_LDC_P_POSTIND, + OP_LDC_P_POSTIND, + OP_LDC_P_POSTIND, + OP_LDC_P_POSTIND, + OP_LDC_P_POSTIND, + OP_LDC_P_POSTIND, + OP_LDC_P_POSTIND, + OP_LDC_P_POSTIND, + OP_LDC_P_POSTIND, + OP_LDC_P_POSTIND, + OP_LDC_P_POSTIND, +//------------------------------------------ + OP_STC_M_IMM_OFF, //110 1000 0 0000 + OP_STC_M_IMM_OFF, + OP_STC_M_IMM_OFF, + OP_STC_M_IMM_OFF, + OP_STC_M_IMM_OFF, + OP_STC_M_IMM_OFF, + OP_STC_M_IMM_OFF, + OP_STC_M_IMM_OFF, + OP_STC_M_IMM_OFF, + OP_STC_M_IMM_OFF, + OP_STC_M_IMM_OFF, + OP_STC_M_IMM_OFF, + OP_STC_M_IMM_OFF, + OP_STC_M_IMM_OFF, + OP_STC_M_IMM_OFF, + OP_STC_M_IMM_OFF, + + OP_LDC_M_IMM_OFF, + OP_LDC_M_IMM_OFF, + OP_LDC_M_IMM_OFF, + OP_LDC_M_IMM_OFF, + OP_LDC_M_IMM_OFF, + OP_LDC_M_IMM_OFF, + OP_LDC_M_IMM_OFF, + OP_LDC_M_IMM_OFF, + OP_LDC_M_IMM_OFF, + OP_LDC_M_IMM_OFF, + OP_LDC_M_IMM_OFF, + OP_LDC_M_IMM_OFF, + OP_LDC_M_IMM_OFF, + OP_LDC_M_IMM_OFF, + OP_LDC_M_IMM_OFF, + OP_LDC_M_IMM_OFF, +//------------------------------------------ + OP_STC_M_PREIND, //110 1001 0 0000 + OP_STC_M_PREIND, + OP_STC_M_PREIND, + OP_STC_M_PREIND, + OP_STC_M_PREIND, + OP_STC_M_PREIND, + OP_STC_M_PREIND, + OP_STC_M_PREIND, + OP_STC_M_PREIND, + OP_STC_M_PREIND, + OP_STC_M_PREIND, + OP_STC_M_PREIND, + OP_STC_M_PREIND, + OP_STC_M_PREIND, + OP_STC_M_PREIND, + OP_STC_M_PREIND, + + OP_LDC_M_PREIND, + OP_LDC_M_PREIND, + OP_LDC_M_PREIND, + OP_LDC_M_PREIND, + OP_LDC_M_PREIND, + OP_LDC_M_PREIND, + OP_LDC_M_PREIND, + OP_LDC_M_PREIND, + OP_LDC_M_PREIND, + OP_LDC_M_PREIND, + OP_LDC_M_PREIND, + OP_LDC_M_PREIND, + OP_LDC_M_PREIND, + OP_LDC_M_PREIND, + OP_LDC_M_PREIND, + OP_LDC_M_PREIND, +//------------------------------------------ + OP_STC_M_IMM_OFF, //110 1010 0 0000 + OP_STC_M_IMM_OFF, + OP_STC_M_IMM_OFF, + OP_STC_M_IMM_OFF, + OP_STC_M_IMM_OFF, + OP_STC_M_IMM_OFF, + OP_STC_M_IMM_OFF, + OP_STC_M_IMM_OFF, + OP_STC_M_IMM_OFF, + OP_STC_M_IMM_OFF, + OP_STC_M_IMM_OFF, + OP_STC_M_IMM_OFF, + OP_STC_M_IMM_OFF, + OP_STC_M_IMM_OFF, + OP_STC_M_IMM_OFF, + OP_STC_M_IMM_OFF, + + OP_LDC_M_IMM_OFF, + OP_LDC_M_IMM_OFF, + OP_LDC_M_IMM_OFF, + OP_LDC_M_IMM_OFF, + OP_LDC_M_IMM_OFF, + OP_LDC_M_IMM_OFF, + OP_LDC_M_IMM_OFF, + OP_LDC_M_IMM_OFF, + OP_LDC_M_IMM_OFF, + OP_LDC_M_IMM_OFF, + OP_LDC_M_IMM_OFF, + OP_LDC_M_IMM_OFF, + OP_LDC_M_IMM_OFF, + OP_LDC_M_IMM_OFF, + OP_LDC_M_IMM_OFF, + OP_LDC_M_IMM_OFF, +//------------------------------------------ + OP_STC_M_PREIND, //110 1011 0 0000 + OP_STC_M_PREIND, + OP_STC_M_PREIND, + OP_STC_M_PREIND, + OP_STC_M_PREIND, + OP_STC_M_PREIND, + OP_STC_M_PREIND, + OP_STC_M_PREIND, + OP_STC_M_PREIND, + OP_STC_M_PREIND, + OP_STC_M_PREIND, + OP_STC_M_PREIND, + OP_STC_M_PREIND, + OP_STC_M_PREIND, + OP_STC_M_PREIND, + OP_STC_M_PREIND, + + OP_LDC_M_PREIND, + OP_LDC_M_PREIND, + OP_LDC_M_PREIND, + OP_LDC_M_PREIND, + OP_LDC_M_PREIND, + OP_LDC_M_PREIND, + OP_LDC_M_PREIND, + OP_LDC_M_PREIND, + OP_LDC_M_PREIND, + OP_LDC_M_PREIND, + OP_LDC_M_PREIND, + OP_LDC_M_PREIND, + OP_LDC_M_PREIND, + OP_LDC_M_PREIND, + OP_LDC_M_PREIND, + OP_LDC_M_PREIND, +//------------------------------------------ + OP_STC_P_IMM_OFF, //110 1100 0 0000 + OP_STC_P_IMM_OFF, + OP_STC_P_IMM_OFF, + OP_STC_P_IMM_OFF, + OP_STC_P_IMM_OFF, + OP_STC_P_IMM_OFF, + OP_STC_P_IMM_OFF, + OP_STC_P_IMM_OFF, + OP_STC_P_IMM_OFF, + OP_STC_P_IMM_OFF, + OP_STC_P_IMM_OFF, + OP_STC_P_IMM_OFF, + OP_STC_P_IMM_OFF, + OP_STC_P_IMM_OFF, + OP_STC_P_IMM_OFF, + OP_STC_P_IMM_OFF, + + OP_LDC_P_IMM_OFF, + OP_LDC_P_IMM_OFF, + OP_LDC_P_IMM_OFF, + OP_LDC_P_IMM_OFF, + OP_LDC_P_IMM_OFF, + OP_LDC_P_IMM_OFF, + OP_LDC_P_IMM_OFF, + OP_LDC_P_IMM_OFF, + OP_LDC_P_IMM_OFF, + OP_LDC_P_IMM_OFF, + OP_LDC_P_IMM_OFF, + OP_LDC_P_IMM_OFF, + OP_LDC_P_IMM_OFF, + OP_LDC_P_IMM_OFF, + OP_LDC_P_IMM_OFF, + OP_LDC_P_IMM_OFF, +//------------------------------------------ + OP_STC_P_PREIND, //110 1101 0 0000 + OP_STC_P_PREIND, + OP_STC_P_PREIND, + OP_STC_P_PREIND, + OP_STC_P_PREIND, + OP_STC_P_PREIND, + OP_STC_P_PREIND, + OP_STC_P_PREIND, + OP_STC_P_PREIND, + OP_STC_P_PREIND, + OP_STC_P_PREIND, + OP_STC_P_PREIND, + OP_STC_P_PREIND, + OP_STC_P_PREIND, + OP_STC_P_PREIND, + OP_STC_P_PREIND, + + OP_LDC_P_PREIND, + OP_LDC_P_PREIND, + OP_LDC_P_PREIND, + OP_LDC_P_PREIND, + OP_LDC_P_PREIND, + OP_LDC_P_PREIND, + OP_LDC_P_PREIND, + OP_LDC_P_PREIND, + OP_LDC_P_PREIND, + OP_LDC_P_PREIND, + OP_LDC_P_PREIND, + OP_LDC_P_PREIND, + OP_LDC_P_PREIND, + OP_LDC_P_PREIND, + OP_LDC_P_PREIND, + OP_LDC_P_PREIND, +//------------------------------------------ + OP_STC_P_IMM_OFF, //110 1110 0 0000 + OP_STC_P_IMM_OFF, + OP_STC_P_IMM_OFF, + OP_STC_P_IMM_OFF, + OP_STC_P_IMM_OFF, + OP_STC_P_IMM_OFF, + OP_STC_P_IMM_OFF, + OP_STC_P_IMM_OFF, + OP_STC_P_IMM_OFF, + OP_STC_P_IMM_OFF, + OP_STC_P_IMM_OFF, + OP_STC_P_IMM_OFF, + OP_STC_P_IMM_OFF, + OP_STC_P_IMM_OFF, + OP_STC_P_IMM_OFF, + OP_STC_P_IMM_OFF, + + OP_LDC_P_IMM_OFF, + OP_LDC_P_IMM_OFF, + OP_LDC_P_IMM_OFF, + OP_LDC_P_IMM_OFF, + OP_LDC_P_IMM_OFF, + OP_LDC_P_IMM_OFF, + OP_LDC_P_IMM_OFF, + OP_LDC_P_IMM_OFF, + OP_LDC_P_IMM_OFF, + OP_LDC_P_IMM_OFF, + OP_LDC_P_IMM_OFF, + OP_LDC_P_IMM_OFF, + OP_LDC_P_IMM_OFF, + OP_LDC_P_IMM_OFF, + OP_LDC_P_IMM_OFF, + OP_LDC_P_IMM_OFF, +//------------------------------------------ + OP_STC_P_PREIND, //110 1111 0 0000 + OP_STC_P_PREIND, + OP_STC_P_PREIND, + OP_STC_P_PREIND, + OP_STC_P_PREIND, + OP_STC_P_PREIND, + OP_STC_P_PREIND, + OP_STC_P_PREIND, + OP_STC_P_PREIND, + OP_STC_P_PREIND, + OP_STC_P_PREIND, + OP_STC_P_PREIND, + OP_STC_P_PREIND, + OP_STC_P_PREIND, + OP_STC_P_PREIND, + OP_STC_P_PREIND, + + OP_LDC_P_PREIND, + OP_LDC_P_PREIND, + OP_LDC_P_PREIND, + OP_LDC_P_PREIND, + OP_LDC_P_PREIND, + OP_LDC_P_PREIND, + OP_LDC_P_PREIND, + OP_LDC_P_PREIND, + OP_LDC_P_PREIND, + OP_LDC_P_PREIND, + OP_LDC_P_PREIND, + OP_LDC_P_PREIND, + OP_LDC_P_PREIND, + OP_LDC_P_PREIND, + OP_LDC_P_PREIND, + OP_LDC_P_PREIND, +//------------------------------------------ + OP_CDP, //111 0000 0 0000 + OP_MCR, + OP_CDP, + OP_MCR, + OP_CDP, + OP_MCR, + OP_CDP, + OP_MCR, + OP_CDP, + OP_MCR, + OP_CDP, + OP_MCR, + OP_CDP, + OP_MCR, + OP_CDP, + OP_MCR, + + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, +//--------------------------------------------- + OP_CDP, //111 0001 0 0000 + OP_MCR, + OP_CDP, + OP_MCR, + OP_CDP, + OP_MCR, + OP_CDP, + OP_MCR, + OP_CDP, + OP_MCR, + OP_CDP, + OP_MCR, + OP_CDP, + OP_MCR, + OP_CDP, + OP_MCR, + + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, +//--------------------------------------------- + OP_CDP, //111 0010 0 0000 + OP_MCR, + OP_CDP, + OP_MCR, + OP_CDP, + OP_MCR, + OP_CDP, + OP_MCR, + OP_CDP, + OP_MCR, + OP_CDP, + OP_MCR, + OP_CDP, + OP_MCR, + OP_CDP, + OP_MCR, + + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, +//--------------------------------------------- + OP_CDP, //111 0011 0 0000 + OP_MCR, + OP_CDP, + OP_MCR, + OP_CDP, + OP_MCR, + OP_CDP, + OP_MCR, + OP_CDP, + OP_MCR, + OP_CDP, + OP_MCR, + OP_CDP, + OP_MCR, + OP_CDP, + OP_MCR, + + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, +//--------------------------------------------- + OP_CDP, //111 0100 0 0000 + OP_MCR, + OP_CDP, + OP_MCR, + OP_CDP, + OP_MCR, + OP_CDP, + OP_MCR, + OP_CDP, + OP_MCR, + OP_CDP, + OP_MCR, + OP_CDP, + OP_MCR, + OP_CDP, + OP_MCR, + + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, +//--------------------------------------------- + OP_CDP, //111 0101 0 0000 + OP_MCR, + OP_CDP, + OP_MCR, + OP_CDP, + OP_MCR, + OP_CDP, + OP_MCR, + OP_CDP, + OP_MCR, + OP_CDP, + OP_MCR, + OP_CDP, + OP_MCR, + OP_CDP, + OP_MCR, + + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, +//--------------------------------------------- + OP_CDP, //111 0110 0 0000 + OP_MCR, + OP_CDP, + OP_MCR, + OP_CDP, + OP_MCR, + OP_CDP, + OP_MCR, + OP_CDP, + OP_MCR, + OP_CDP, + OP_MCR, + OP_CDP, + OP_MCR, + OP_CDP, + OP_MCR, + + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, +//--------------------------------------------- + OP_CDP, //111 0111 0 0000 + OP_MCR, + OP_CDP, + OP_MCR, + OP_CDP, + OP_MCR, + OP_CDP, + OP_MCR, + OP_CDP, + OP_MCR, + OP_CDP, + OP_MCR, + OP_CDP, + OP_MCR, + OP_CDP, + OP_MCR, + + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, +//--------------------------------------------- + OP_SWI, //111 1000 0 0000 + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, +}; + diff -r fe2ba1a712cd -r 70b0973e7b70 src/xsf/desmume/matrix.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/xsf/desmume/matrix.c Thu Oct 16 14:45:41 2008 -0500 @@ -0,0 +1,257 @@ +/* + Copyright (C) 2006-2007 shash + + This file is part of DeSmuME + + DeSmuME is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DeSmuME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DeSmuME; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include +#include +#include +#include "matrix.h" + +void MatrixInit (float *matrix) +{ + memset (matrix, 0, sizeof(float)*16); + + matrix[0] = matrix[5] = matrix[10] = matrix[15] = 1.f; +} + +void MatrixMultVec4x4 (float *matrix, float *vecPtr) +{ + float x = vecPtr[0]; + float y = vecPtr[1]; + float z = vecPtr[2]; + + vecPtr[0] = x * matrix[0] + y * matrix[4] + z * matrix[ 8] + matrix[12]; + vecPtr[1] = x * matrix[1] + y * matrix[5] + z * matrix[ 9] + matrix[13]; + vecPtr[2] = x * matrix[2] + y * matrix[6] + z * matrix[10] + matrix[14]; +} + +void MatrixMultVec3x3 (float *matrix, float *vecPtr) +{ + float x = vecPtr[0]; + float y = vecPtr[1]; + float z = vecPtr[2]; + + vecPtr[0] = x * matrix[0] + y * matrix[4] + z * matrix[ 8]; + vecPtr[1] = x * matrix[1] + y * matrix[5] + z * matrix[ 9]; + vecPtr[2] = x * matrix[2] + y * matrix[6] + z * matrix[10]; +} + +void MatrixIdentity (float *matrix) +{ + memset (matrix, 0, sizeof(float)*16); + + matrix[0] = matrix[5] = matrix[10] = matrix[15] = 1.f; +} + +void MatrixMultiply (float *matrix, float *rightMatrix) +{ + float tmpMatrix[16]; + + tmpMatrix[0] = (matrix[0]*rightMatrix[0])+(matrix[4]*rightMatrix[1])+(matrix[8]*rightMatrix[2])+(matrix[12]*rightMatrix[3]); + tmpMatrix[1] = (matrix[1]*rightMatrix[0])+(matrix[5]*rightMatrix[1])+(matrix[9]*rightMatrix[2])+(matrix[13]*rightMatrix[3]); + tmpMatrix[2] = (matrix[2]*rightMatrix[0])+(matrix[6]*rightMatrix[1])+(matrix[10]*rightMatrix[2])+(matrix[14]*rightMatrix[3]); + tmpMatrix[3] = (matrix[3]*rightMatrix[0])+(matrix[7]*rightMatrix[1])+(matrix[11]*rightMatrix[2])+(matrix[15]*rightMatrix[3]); + + tmpMatrix[4] = (matrix[0]*rightMatrix[4])+(matrix[4]*rightMatrix[5])+(matrix[8]*rightMatrix[6])+(matrix[12]*rightMatrix[7]); + tmpMatrix[5] = (matrix[1]*rightMatrix[4])+(matrix[5]*rightMatrix[5])+(matrix[9]*rightMatrix[6])+(matrix[13]*rightMatrix[7]); + tmpMatrix[6] = (matrix[2]*rightMatrix[4])+(matrix[6]*rightMatrix[5])+(matrix[10]*rightMatrix[6])+(matrix[14]*rightMatrix[7]); + tmpMatrix[7] = (matrix[3]*rightMatrix[4])+(matrix[7]*rightMatrix[5])+(matrix[11]*rightMatrix[6])+(matrix[15]*rightMatrix[7]); + + tmpMatrix[8] = (matrix[0]*rightMatrix[8])+(matrix[4]*rightMatrix[9])+(matrix[8]*rightMatrix[10])+(matrix[12]*rightMatrix[11]); + tmpMatrix[9] = (matrix[1]*rightMatrix[8])+(matrix[5]*rightMatrix[9])+(matrix[9]*rightMatrix[10])+(matrix[13]*rightMatrix[11]); + tmpMatrix[10] = (matrix[2]*rightMatrix[8])+(matrix[6]*rightMatrix[9])+(matrix[10]*rightMatrix[10])+(matrix[14]*rightMatrix[11]); + tmpMatrix[11] = (matrix[3]*rightMatrix[8])+(matrix[7]*rightMatrix[9])+(matrix[11]*rightMatrix[10])+(matrix[15]*rightMatrix[11]); + + tmpMatrix[12] = (matrix[0]*rightMatrix[12])+(matrix[4]*rightMatrix[13])+(matrix[8]*rightMatrix[14])+(matrix[12]*rightMatrix[15]); + tmpMatrix[13] = (matrix[1]*rightMatrix[12])+(matrix[5]*rightMatrix[13])+(matrix[9]*rightMatrix[14])+(matrix[13]*rightMatrix[15]); + tmpMatrix[14] = (matrix[2]*rightMatrix[12])+(matrix[6]*rightMatrix[13])+(matrix[10]*rightMatrix[14])+(matrix[14]*rightMatrix[15]); + tmpMatrix[15] = (matrix[3]*rightMatrix[12])+(matrix[7]*rightMatrix[13])+(matrix[11]*rightMatrix[14])+(matrix[15]*rightMatrix[15]); + + memcpy (matrix, tmpMatrix, sizeof(float)*16); +} +/* +void MatrixMulti (float* right) +{ + float tmpMatrix[16]; + + tmpMatrix[0] = (matrix[0]*right[0])+(matrix[4]*right[1])+(matrix[8]*right[2])+(matrix[12]*right[3]); + tmpMatrix[1] = (matrix[1]*right[0])+(matrix[5]*right[1])+(matrix[9]*right[2])+(matrix[13]*right[3]); + tmpMatrix[2] = (matrix[2]*right[0])+(matrix[6]*right[1])+(matrix[10]*right[2])+(matrix[14]*right[3]); + tmpMatrix[3] = (matrix[3]*right[0])+(matrix[7]*right[1])+(matrix[11]*right[2])+(matrix[15]*right[3]); + + tmpMatrix[4] = (matrix[0]*right[4])+(matrix[4]*right[5])+(matrix[8]*right[6])+(matrix[12]*right[7]); + tmpMatrix[5] = (matrix[1]*right[4])+(matrix[5]*right[5])+(matrix[9]*right[6])+(matrix[13]*right[7]); + tmpMatrix[6] = (matrix[2]*right[4])+(matrix[6]*right[5])+(matrix[10]*right[6])+(matrix[14]*right[7]); + tmpMatrix[7] = (matrix[3]*right[4])+(matrix[7]*right[5])+(matrix[11]*right[6])+(matrix[15]*right[7]); + + tmpMatrix[8] = (matrix[0]*right[8])+(matrix[4]*right[9])+(matrix[8]*right[10])+(matrix[12]*right[11]); + tmpMatrix[9] = (matrix[1]*right[8])+(matrix[5]*right[9])+(matrix[9]*right[10])+(matrix[13]*right[11]); + tmpMatrix[10] = (matrix[2]*right[8])+(matrix[6]*right[9])+(matrix[10]*right[10])+(matrix[14]*right[11]); + tmpMatrix[11] = (matrix[3]*right[8])+(matrix[7]*right[9])+(matrix[11]*right[10])+(matrix[15]*right[11]); + + tmpMatrix[12] = (matrix[0]*right[12])+(matrix[4]*right[13])+(matrix[8]*right[14])+(matrix[12]*right[15]); + tmpMatrix[13] = (matrix[1]*right[12])+(matrix[5]*right[13])+(matrix[9]*right[14])+(matrix[13]*right[15]); + tmpMatrix[14] = (matrix[2]*right[12])+(matrix[6]*right[13])+(matrix[10]*right[14])+(matrix[14]*right[15]); + tmpMatrix[15] = (matrix[3]*right[12])+(matrix[7]*right[13])+(matrix[11]*right[14])+(matrix[15]*right[15]); + + memcpy (matrix, tmpMatrix, sizeof(float)*16); +} + + +float* Matrix::Get (void) +{ + return matrix; +} + +float MatrixGet (float *matrix, int index) +{ + return matrix[index]; +} +*/ + +float MatrixGetMultipliedIndex (int index, float *matrix, float *rightMatrix) +{ + int iMod = index%4, iDiv = (index>>2)<<2; + + return (matrix[iMod ]*rightMatrix[iDiv ])+(matrix[iMod+ 4]*rightMatrix[iDiv+1])+ + (matrix[iMod+8]*rightMatrix[iDiv+2])+(matrix[iMod+12]*rightMatrix[iDiv+3]); +} + +void MatrixSet (float *matrix, int x, int y, float value) +{ + matrix [x+(y<<2)] = value; +} +/* +void Matrix::Set (int pos, float value) +{ + matrix [pos] = value; +} +*/ +void MatrixCopy (float *matrixDST, float *matrixSRC) +{ + memcpy (matrixDST, matrixSRC, sizeof(float)*16); +} + +void MatrixTranslate (float *matrix, float *ptr) +{ + matrix[12] += (matrix[0]*ptr[0])+(matrix[4]*ptr[1])+(matrix[ 8]*ptr[2]); + matrix[13] += (matrix[1]*ptr[0])+(matrix[5]*ptr[1])+(matrix[ 9]*ptr[2]); + matrix[14] += (matrix[2]*ptr[0])+(matrix[6]*ptr[1])+(matrix[10]*ptr[2]); + matrix[15] += (matrix[3]*ptr[0])+(matrix[7]*ptr[1])+(matrix[11]*ptr[2]); +} + +void MatrixScale (float *matrix, float *ptr) +{ + matrix[0] *= ptr[0]; + matrix[1] *= ptr[0]; + matrix[2] *= ptr[0]; + matrix[3] *= ptr[0]; + + matrix[4] *= ptr[1]; + matrix[5] *= ptr[1]; + matrix[6] *= ptr[1]; + matrix[7] *= ptr[1]; + + matrix[8] *= ptr[2]; + matrix[9] *= ptr[2]; + matrix[10] *= ptr[2]; + matrix[11] *= ptr[2]; +} +/* +void Matrix::Set (float a11, float a21, float a31, float a41, + float a12, float a22, float a32, float a42, + float a13, float a23, float a33, float a43, + float a14, float a24, float a34, float a44) +{ +} +*/ + + +//----------------------------------------- + +void MatrixStackInit (MatrixStack *stack) +{ + stack->matrix = NULL; + stack->position = 0; + stack->size = 0; +} + +void MatrixStackSetMaxSize (MatrixStack *stack, int size) +{ + int i = 0; + + stack->size = size; + + if (stack->matrix == NULL) + { + stack->matrix = (float*) malloc (stack->size*16*sizeof(float)); + } + else + { + free (stack->matrix); + stack->matrix = (float*) malloc (stack->size*16*sizeof(float)); + } + + for (i = 0; i < stack->size; i++) + { + MatrixInit (&stack->matrix[i*16]); + } + + stack->size--; +} + + +void MatrixStackSetStackPosition (MatrixStack *stack, int pos) +{ + stack->position += pos; + + if (stack->position < 0) + stack->position = 0; + else if (stack->position > stack->size) + stack->position = stack->size; +} + +void MatrixStackPushMatrix (MatrixStack *stack, float *ptr) +{ + MatrixCopy (&stack->matrix[stack->position*16], ptr); + + MatrixStackSetStackPosition (stack, 1); +} + +float * MatrixStackPopMatrix (MatrixStack *stack, int size) +{ + MatrixStackSetStackPosition(stack, -size); + + return &stack->matrix[stack->position*16]; +} + +float * MatrixStackGetPos (MatrixStack *stack, int pos) +{ + return &stack->matrix[pos*16]; +} + +float * MatrixStackGet (MatrixStack *stack) +{ + return &stack->matrix[stack->position*16]; +} + +void MatrixStackLoadMatrix (MatrixStack *stack, int pos, float *ptr) +{ + MatrixCopy (&stack->matrix[pos*16], ptr); +} diff -r fe2ba1a712cd -r 70b0973e7b70 src/xsf/desmume/matrix.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/xsf/desmume/matrix.h Thu Oct 16 14:45:41 2008 -0500 @@ -0,0 +1,51 @@ +/* + Copyright (C) 2006-2007 shash + + This file is part of DeSmuME + + DeSmuME is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DeSmuME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DeSmuME; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef MATRIX_H +#define MATRIX_H + +typedef struct MatrixStack +{ + float *matrix; + int position; + int size; +} MatrixStack; + +void MatrixInit (float *matrix); +void MatrixMultVec3x3 (float *matrix, float *vecPtr); +void MatrixMultVec4x4 (float *matrix, float *vecPtr); +void MatrixIdentity (float *matrix); +void MatrixMultiply (float *matrix, float *rightMatrix); +float MatrixGetMultipliedIndex(int index, float *matrix, float *rightMatrix); +void MatrixSet (float *matrix, int x, int y, float value); +void MatrixCopy (float *matrixDST, float *matrixSRC); +void MatrixTranslate (float *matrix, float *ptr); +void MatrixScale (float *matrix, float *ptr); + +void MatrixStackInit (MatrixStack *stack); +void MatrixStackSetMaxSize (MatrixStack *stack, int size); +void MatrixStackSetStackPosition (MatrixStack *stack, int pos); +void MatrixStackPushMatrix (MatrixStack *stack, float *ptr); +float* MatrixStackPopMatrix (MatrixStack *stack, int size); +float* MatrixStackGetPos (MatrixStack *stack, int pos); +float* MatrixStackGet (MatrixStack *stack); +void MatrixStackLoadMatrix (MatrixStack *stack, int pos, float *ptr); + +#endif diff -r fe2ba1a712cd -r 70b0973e7b70 src/xsf/desmume/mc.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/xsf/desmume/mc.c Thu Oct 16 14:45:41 2008 -0500 @@ -0,0 +1,121 @@ +/* Copyright (C) 2006 thoduv + Copyright (C) 2006-2007 Theo Berkau + + This file is part of DeSmuME + + DeSmuME is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DeSmuME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DeSmuME; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include +#include "debug.h" +#include "types.h" +#include "mc.h" + +#define FW_CMD_READ 0x3 +#define FW_CMD_WRITEDISABLE 0x4 +#define FW_CMD_READSTATUS 0x5 +#define FW_CMD_WRITEENABLE 0x6 +#define FW_CMD_PAGEWRITE 0xA + +#define BM_CMD_AUTODETECT 0xFF +#define BM_CMD_WRITESTATUS 0x1 +#define BM_CMD_WRITELOW 0x2 +#define BM_CMD_READLOW 0x3 +#define BM_CMD_WRITEDISABLE 0x4 +#define BM_CMD_READSTATUS 0x5 +#define BM_CMD_WRITEENABLE 0x6 +#define BM_CMD_WRITEHIGH 0xA +#define BM_CMD_READHIGH 0xB + +/* FLASH*/ +#define COMM_PAGE_WRITE 0x0A +#define COMM_PAGE_ERASE 0xDB +#define COMM_SECTOR_ERASE 0xD8 +#define COMM_CHIP_ERASE 0xC7 +#define CARDFLASH_READ_BYTES_FAST 0x0B /* Not used*/ +#define CARDFLASH_DEEP_POWDOWN 0xB9 /* Not used*/ +#define CARDFLASH_WAKEUP 0xAB /* Not used*/ + +void mc_init(memory_chip_t *mc, int type) +{ + mc->com = 0; + mc->addr = 0; + mc->addr_shift = 0; + mc->data = NULL; + mc->size = 0; + mc->write_enable = FALSE; + mc->writeable_buffer = FALSE; + mc->type = type; + mc->autodetectsize = 0; + + switch(mc->type) + { + case MC_TYPE_EEPROM1: + mc->addr_size = 1; + break; + case MC_TYPE_EEPROM2: + case MC_TYPE_FRAM: + mc->addr_size = 2; + break; + case MC_TYPE_FLASH: + mc->addr_size = 3; + break; + default: break; + } +} + +u8 *mc_alloc(memory_chip_t *mc, u32 size) +{ + u8 *buffer; + buffer = malloc(size); + + mc->data = buffer; + if(!buffer) { return NULL; } + mc->size = size; + mc->writeable_buffer = TRUE; + + return buffer; +} + +void mc_free(memory_chip_t *mc) +{ + if(mc->data) + { + free(mc->data); + mc->data = 0; + } + mc_init(mc, 0); +} + +void mc_realloc(memory_chip_t *mc, int type, u32 size) +{ + mc_free(mc); + mc_init(mc, type); + mc_alloc(mc, size); +} + + +void mc_reset_com(memory_chip_t *mc) +{ +} +u8 fw_transfer(memory_chip_t *mc, u8 data) +{ + return 0; +} +u8 bm_transfer(memory_chip_t *mc, u8 data) +{ + return 0; +} + diff -r fe2ba1a712cd -r 70b0973e7b70 src/xsf/desmume/mc.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/xsf/desmume/mc.h Thu Oct 16 14:45:41 2008 -0500 @@ -0,0 +1,94 @@ +/* Copyright (C) 2006 thoduv + Copyright (C) 2006 Theo Berkau + + This file is part of DeSmuME + + DeSmuME is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DeSmuME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DeSmuME; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef __FW_H__ +#define __FW_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include "types.h" + +#define MC_TYPE_AUTODETECT 0x0 +#define MC_TYPE_EEPROM1 0x1 +#define MC_TYPE_EEPROM2 0x2 +#define MC_TYPE_FLASH 0x3 +#define MC_TYPE_FRAM 0x4 + +#define MC_SIZE_4KBITS 0x000200 +#define MC_SIZE_64KBITS 0x002000 +#define MC_SIZE_256KBITS 0x008000 +#define MC_SIZE_512KBITS 0x010000 +#define MC_SIZE_1MBITS 0x020000 +#define MC_SIZE_2MBITS 0x040000 +#define MC_SIZE_4MBITS 0x080000 +#define MC_SIZE_8MBITS 0x100000 +#define MC_SIZE_16MBITS 0x200000 +#define MC_SIZE_64MBITS 0x800000 + +static int save_types[6][2] = { + {MC_TYPE_AUTODETECT,1}, + {MC_TYPE_EEPROM1,MC_SIZE_4KBITS}, + {MC_TYPE_EEPROM2,MC_SIZE_64KBITS}, + {MC_TYPE_EEPROM2,MC_SIZE_512KBITS}, + {MC_TYPE_FLASH,MC_SIZE_256KBITS}, + {MC_TYPE_FRAM,MC_SIZE_2MBITS} +}; + +typedef struct +{ + u8 com; /* persistent command actually handled */ + u32 addr; /* current address for reading/writing */ + u8 addr_shift; /* shift for address (since addresses are transfered by 3 bytes units) */ + u8 addr_size; /* size of addr when writing/reading */ + + BOOL write_enable; /* is write enabled ? */ + + u8 *data; /* memory data */ + u32 size; /* memory size */ + BOOL writeable_buffer; /* is "data" writeable ? */ + int type; /* type of Memory */ + char *filename; + FILE *fp; + u8 autodetectbuf[32768]; + int autodetectsize; +} memory_chip_t; + +#define NDS_FW_SIZE_V1 (256 * 1024) /* size of fw memory on nds v1 */ +#define NDS_FW_SIZE_V2 (512 * 1024) /* size of fw memory on nds v2 */ + +void mc_init(memory_chip_t *mc, int type); /* reset and init values for memory struct */ +u8 *mc_alloc(memory_chip_t *mc, u32 size); /* alloc mc memory */ +void mc_realloc(memory_chip_t *mc, int type, u32 size); /* realloc mc memory */ +void mc_load_file(memory_chip_t *mc, const char* filename); /* load save file and setup fp */ +int mc_load_duc(memory_chip_t *mc, const char* filename); /* load Action Replay DS save file */ +void mc_free(memory_chip_t *mc); /* delete mc memory */ +void mc_reset_com(memory_chip_t *mc); /* reset communication with mc */ +u8 fw_transfer(memory_chip_t *mc, u8 data); /* transfer to, then receive data from firmware */ +u8 bm_transfer(memory_chip_t *mc, u8 data); /* transfer to, then receive data from backup memory */ + +#ifdef __cplusplus +} +#endif + +#endif /*__FW_H__*/ + diff -r fe2ba1a712cd -r 70b0973e7b70 src/xsf/desmume/mem.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/xsf/desmume/mem.h Thu Oct 16 14:45:41 2008 -0500 @@ -0,0 +1,141 @@ +/* Copyright 2005-2006 Guillaume Duhamel + Copyright 2005 Theo Berkau + + This file is part of Yabause. + + Yabause is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + Yabause is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Yabause; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef MEM_H +#define MEM_H + +#include +#include "types.h" + +/* Type 1 Memory, faster for byte (8 bits) accesses */ + +static INLINE u8 T1ReadByte(u8 * mem, u32 addr) +{ + return mem[addr]; +} + +static INLINE u16 T1ReadWord(u8 * mem, u32 addr) +{ +#ifdef WORDS_BIGENDIAN + return (mem[addr + 1] << 8) | mem[addr]; +#else + return *((u16 *) (mem + addr)); +#endif +} + +static INLINE u32 T1ReadLong(u8 * mem, u32 addr) +{ +#ifdef WORDS_BIGENDIAN + return (mem[addr + 3] << 24 | mem[addr + 2] << 16 | + mem[addr + 1] << 8 | mem[addr]); +#else + return *((u32 *)mem + (addr>>2)); +#endif +} + +static INLINE u64 T1ReadQuad(u8 * mem, u32 addr) +{ +#ifdef WORDS_BIGENDIAN + return (mem[addr + 7] << 56 | mem[addr + 6] << 48 | + mem[addr + 5] << 40 | mem[addr + 4] << 32 | + mem[addr + 3] << 24 | mem[addr + 2] << 16 | + mem[addr + 1] << 8 | mem[addr]); +#else + return *((u64 *) (mem + addr)); +#endif +} + +static INLINE void T1WriteByte(u8 * mem, u32 addr, u8 val) +{ + mem[addr] = val; +} + +static INLINE void T1WriteWord(u8 * mem, u32 addr, u16 val) +{ +#ifdef WORDS_BIGENDIAN + mem[addr + 1] = val >> 8; + mem[addr] = val & 0xFF; +#else + *((u16 *) (mem + addr)) = val; +#endif +} + +static INLINE void T1WriteLong(u8 * mem, u32 addr, u32 val) +{ +#ifdef WORDS_BIGENDIAN + mem[addr + 3] = val >> 24; + mem[addr + 2] = (val >> 16) & 0xFF; + mem[addr + 1] = (val >> 8) & 0xFF; + mem[addr] = val & 0xFF; +#else + *((u32 *) (mem + addr)) = val; +#endif +} + +/* Type 2 Memory, faster for word (16 bits) accesses */ + +static INLINE u8 T2ReadByte(u8 * mem, u32 addr) +{ +#ifdef WORDS_BIGENDIAN + return mem[addr ^ 1]; +#else + return mem[addr]; +#endif +} + +static INLINE u16 T2ReadWord(u8 * mem, u32 addr) +{ + return *((u16 *) (mem + addr)); +} + +static INLINE u32 T2ReadLong(u8 * mem, u32 addr) +{ +#ifdef WORDS_BIGENDIAN + return *((u16 *) (mem + addr + 2)) << 16 | *((u16 *) (mem + addr)); +#else + return *((u32 *) (mem + addr)); +#endif +} + +static INLINE void T2WriteByte(u8 * mem, u32 addr, u8 val) +{ +#ifdef WORDS_BIGENDIAN + mem[addr ^ 1] = val; +#else + mem[addr] = val; +#endif +} + +static INLINE void T2WriteWord(u8 * mem, u32 addr, u16 val) +{ + *((u16 *) (mem + addr)) = val; +} + +static INLINE void T2WriteLong(u8 * mem, u32 addr, u32 val) +{ +#ifdef WORDS_BIGENDIAN + *((u16 *) (mem + addr + 2)) = val >> 16; + *((u16 *) (mem + addr)) = val & 0xFFFF; +#else + *((u32 *) (mem + addr)) = val; +#endif +} + +#endif diff -r fe2ba1a712cd -r 70b0973e7b70 src/xsf/desmume/registers.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/xsf/desmume/registers.h Thu Oct 16 14:45:41 2008 -0500 @@ -0,0 +1,333 @@ +/* Copyright (C) 2006 Theo Berkau + + Ideas borrowed from Stephane Dallongeville's SCSP core + + This file is part of DeSmuME + + DeSmuME is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DeSmuME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DeSmuME; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef REGISTERS_H +#define REGISTERS_H + +#define REG_REGION_MASK 0x0FFFEF80 +#define REG_BASE_DISPx 0x04000000 +#define REG_BASE_DISPA 0x04000000 +#define REG_BASE_DISPB 0x04001000 +#define REG_BASE_DMA 0x04000080 +#define REG_BASE_SIORTCTIMERS 0x04000100 +#define REG_BASE_ROMIPC 0x04000180 +#define REG_BASE_MEMIRQ 0x04000200 +#define REG_BASE_MATH 0x04000280 +#define REG_BASE_OTHER 0x04000300 +#define REG_BASE_RCVPORTS 0x04100000 + +// Display Engine A +#define REG_DISPA_DISPCNT 0x04000000 +#define REG_DISPA_VCOUNT 0x04000006 +#define REG_DISPA_BG0CNT 0x04000008 +#define REG_DISPA_BG1CNT 0x0400000A +#define REG_DISPA_BG2CNT 0x0400000C +#define REG_DISPA_BG3CNT 0x0400000E +#define REG_DISPA_BG0HOFS 0x04000010 +#define REG_DISPA_BG0VOFS 0x04000012 +#define REG_DISPA_BG1HOFS 0x04000014 +#define REG_DISPA_BG1VOFS 0x04000016 +#define REG_DISPA_BG2HOFS 0x04000018 +#define REG_DISPA_BG2VOFS 0x0400001A +#define REG_DISPA_BG3HOFS 0x0400001C +#define REG_DISPA_BG3VOFS 0x0400001E +#define REG_DISPA_BG2PA 0x04000020 +#define REG_DISPA_BG2PB 0x04000022 +#define REG_DISPA_BG2PC 0x04000024 +#define REG_DISPA_BG2PD 0x04000026 +#define REG_DISPA_BG2XL 0x04000028 +#define REG_DISPA_BG2XH 0x0400002A +#define REG_DISPA_BG2YL 0x0400002C +#define REG_DISPA_BG2YH 0x0400002E +#define REG_DISPA_BG3PA 0x04000030 +#define REG_DISPA_BG3PB 0x04000032 +#define REG_DISPA_BG3PC 0x04000034 +#define REG_DISPA_BG3PD 0x04000036 +#define REG_DISPA_BG3XL 0x04000038 +#define REG_DISPA_BG3XH 0x0400003A +#define REG_DISPA_BG3YL 0x0400003C +#define REG_DISPA_BG3YH 0x0400003E +#define REG_DISPA_WIN0H 0x04000040 +#define REG_DISPA_WIN1H 0x04000042 +#define REG_DISPA_WIN0V 0x04000044 +#define REG_DISPA_WIN1V 0x04000046 +#define REG_DISPA_WININ 0x04000048 +#define REG_DISPA_WINOUT 0x0400004A +#define REG_DISPA_MOSAIC 0x0400004C +#define REG_DISPA_BLDCNT 0x04000050 +#define REG_DISPA_BLDALPHA 0x04000052 +#define REG_DISPA_BLDY 0x04000054 +#define REG_DISPA_MASTERBRIGHT 0x0400006C + +// DMA +#define REG_DMA0SAD 0x040000B0 +#define REG_DMA0DAD 0x040000B4 +#define REG_DMA0CNTL 0x040000B8 +#define REG_DMA0CNTH 0x040000BA +#define REG_DMA1SAD 0x040000BC +#define REG_DMA1DAD 0x040000C0 +#define REG_DMA1CNTL 0x040000C4 +#define REG_DMA1CNTH 0x040000C6 +#define REG_DMA2SAD 0x040000C8 +#define REG_DMA2DAD 0x040000CC +#define REG_DMA2CNTL 0x040000D0 +#define REG_DMA2CNTH 0x040000D2 +#define REG_DMA3SAD 0x040000D4 +#define REG_DMA3DAD 0x040000D8 +#define REG_DMA3CNTL 0x040000DC +#define REG_DMA3CNTH 0x040000DE +#define REG_DMA0FILL 0x040000E0 +#define REG_DMA1FILL 0x040000E4 +#define REG_DMA2FILL 0x040000E8 +#define REG_DMA3FILL 0x040000EC + +// Timers +#define REG_TM0CNTL 0x04000100 +#define REG_TM0CNTH 0x04000102 +#define REG_TM1CNTL 0x04000104 +#define REG_TM1CNTH 0x04000106 +#define REG_TM2CNTL 0x04000108 +#define REG_TM2CNTH 0x0400010A +#define REG_TM3CNTL 0x0400010C +#define REG_TM3CNTH 0x0400010E + +// SIO/Keypad Input/RTC +#define REG_SIODATA32 0x04000120 +#define REG_SIOCNT 0x04000128 +#define REG_KEYINPUT 0x04000130 +#define REG_KEYCNT 0x04000132 +#define REG_RCNT 0x04000134 +#define REG_EXTKEYIN 0x04000136 +#define REG_RTC 0x04000138 + +// IPC +#define REG_IPCSYNC 0x04000180 +#define REG_IPCFIFOCNT 0x04000184 +#define REG_IPCFIFOSEND 0x04000188 + +// ROM +#define REG_AUXSPICNT 0x040001A0 +#define REG_AUXSPIDATA 0x040001A2 +#define REG_GCROMCTRL 0x040001A4 +#define REG_GCCMDOUT 0x040001A8 +#define REG_ENCSEED0L 0x040001B0 +#define REG_ENCSEED1L 0x040001B4 +#define REG_ENCSEED0H 0x040001B8 +#define REG_ENCSEED1H 0x040001BC +#define REG_SPICNT 0x040001C0 +#define REG_SPIDATA 0x040001C2 + +// Memory/IRQ +#define REG_EXMEMCNT 0x04000204 +#define REG_WIFIWAITCNT 0x04000206 +#define REG_IME 0x04000208 +#define REG_IE 0x04000210 +#define REG_IF 0x04000214 +#define REG_VRAMCNTA 0x04000240 +#define REG_VRAMSTAT 0x04000240 +#define REG_VRAMCNTB 0x04000241 +#define REG_WRAMSTAT 0x04000241 +#define REG_VRAMCNTC 0x04000242 +#define REG_VRAMCNTD 0x04000243 +#define REG_VRAMCNTE 0x04000244 +#define REG_VRAMCNTF 0x04000245 +#define REG_VRAMCNTG 0x04000246 +#define REG_WRAMCNT 0x04000247 +#define REG_VRAMCNTH 0x04000248 +#define REG_VRAMCNTI 0x04000249 + +// Math +#define REG_DIVCNT 0x04000280 +#define REG_DIVNUMER 0x04000290 +#define REG_DIVDENOM 0x04000298 +#define REG_DIVRESULT 0x040002A0 +#define REG_DIVREMRESULT 0x040002A8 +#define REG_SQRTCNT 0x040002B0 +#define REG_SQRTRESULT 0x040002B4 +#define REG_SQRTPARAM 0x040002B8 + +// Other +#define REG_POSTFLG 0x04000300 +#define REG_HALTCNT 0x04000301 +#define REG_POWCNT1 0x04000304 +#define REG_POWCNT2 0x04000304 +#define REG_BIOSPROT 0x04000308 + +#define REG_DISPB_DISPCNT 0x04001000 +#define REG_DISPB_BG0CNT 0x04001008 +#define REG_DISPB_BG1CNT 0x0400100A +#define REG_DISPB_BG2CNT 0x0400100C +#define REG_DISPB_BG3CNT 0x0400100E +#define REG_DISPB_BG0HOFS 0x04001010 +#define REG_DISPB_BG0VOFS 0x04001012 +#define REG_DISPB_BG1HOFS 0x04001014 +#define REG_DISPB_BG1VOFS 0x04001016 +#define REG_DISPB_BG2HOFS 0x04001018 +#define REG_DISPB_BG2VOFS 0x0400101A +#define REG_DISPB_BG3HOFS 0x0400101C +#define REG_DISPB_BG3VOFS 0x0400101E +#define REG_DISPB_BG2PA 0x04001020 +#define REG_DISPB_BG2PB 0x04001022 +#define REG_DISPB_BG2PC 0x04001024 +#define REG_DISPB_BG2PD 0x04001026 +#define REG_DISPB_BG2XL 0x04001028 +#define REG_DISPB_BG2XH 0x0400102A +#define REG_DISPB_BG2YL 0x0400102C +#define REG_DISPB_BG2YH 0x0400102E +#define REG_DISPB_BG3PA 0x04001030 +#define REG_DISPB_BG3PB 0x04001032 +#define REG_DISPB_BG3PC 0x04001034 +#define REG_DISPB_BG3PD 0x04001036 +#define REG_DISPB_BG3XL 0x04001038 +#define REG_DISPB_BG3XH 0x0400103A +#define REG_DISPB_BG3YL 0x0400103C +#define REG_DISPB_BG3YH 0x0400103E +#define REG_DISPB_WIN0H 0x04001040 +#define REG_DISPB_WIN1H 0x04001042 +#define REG_DISPB_WIN0V 0x04001044 +#define REG_DISPB_WIN1V 0x04001046 +#define REG_DISPB_WININ 0x04001048 +#define REG_DISPB_WINOUT 0x0400104A +#define REG_DISPB_MOSAIC 0x0400104C +#define REG_DISPB_BLDCNT 0x04001050 +#define REG_DISPB_BLDALPHA 0x04001052 +#define REG_DISPB_BLDY 0x04001054 +#define REG_DISPB_MASTERBRIGHT 0x0400106C + +// Receive ports +#define REG_IPCFIFORECV 0x04100000 +#define REG_GCDATAIN 0x04100010 + + + + + +#define REG_DISPB 0x00001000 +// core A and B specific +#define REG_DISPx_DISPCNT 0x04000000 +#define REG_DISPx_VCOUNT 0x04000006 +#define REG_DISPx_BG0CNT 0x04000008 +#define REG_DISPx_BG1CNT 0x0400000A +#define REG_DISPx_BG2CNT 0x0400000C +#define REG_DISPx_BG3CNT 0x0400000E +#define REG_DISPx_BG0HOFS 0x04000010 +#define REG_DISPx_BG0VOFS 0x04000012 +#define REG_DISPx_BG1HOFS 0x04000014 +#define REG_DISPx_BG1VOFS 0x04000016 +#define REG_DISPx_BG2HOFS 0x04000018 +#define REG_DISPx_BG2VOFS 0x0400001A +#define REG_DISPx_BG3HOFS 0x0400001C +#define REG_DISPx_BG3VOFS 0x0400001E +#define REG_DISPx_BG2PA 0x04000020 +#define REG_DISPx_BG2PB 0x04000022 +#define REG_DISPx_BG2PC 0x04000024 +#define REG_DISPx_BG2PD 0x04000026 +#define REG_DISPx_BG2XL 0x04000028 +#define REG_DISPx_BG2XH 0x0400002A +#define REG_DISPx_BG2YL 0x0400002C +#define REG_DISPx_BG2YH 0x0400002E +#define REG_DISPx_BG3PA 0x04000030 +#define REG_DISPx_BG3PB 0x04000032 +#define REG_DISPx_BG3PC 0x04000034 +#define REG_DISPx_BG3PD 0x04000036 +#define REG_DISPx_BG3XL 0x04000038 +#define REG_DISPx_BG3XH 0x0400003A +#define REG_DISPx_BG3YL 0x0400003C +#define REG_DISPx_BG3YH 0x0400003E +#define REG_DISPx_WIN0H 0x04000040 +#define REG_DISPx_WIN1H 0x04000042 +#define REG_DISPx_WIN0V 0x04000044 +#define REG_DISPx_WIN1V 0x04000046 +#define REG_DISPx_WININ 0x04000048 +#define REG_DISPx_WINOUT 0x0400004A +#define REG_DISPx_MOSAIC 0x0400004C +#define REG_DISPx_BLDCNT 0x04000050 +#define REG_DISPx_BLDALPHA 0x04000052 +#define REG_DISPx_BLDY 0x04000054 +#define REG_DISPx_MASTERBRIGHT 0x0400006C +// core A specific +#define REG_DISPA_DISPSTAT 0x04000004 +#define REG_DISPA_DISP3DCNT 0x04000060 +#define REG_DISPA_DISPCAPCNT 0x04000064 +#define REG_DISPA_DISPMMEMFIFO 0x04000068 + + +#define eng_3D_RDLINES_COUNT 0x04000320 +#define eng_3D_EDGE_COLOR 0x04000330 +#define eng_3D_ALPHA_TEST_REF 0x04000340 +#define eng_3D_CLEAR_COLOR 0x04000350 +#define eng_3D_CLEAR_DEPTH 0x04000354 +#define eng_3D_CLRIMAGE_OFFSET 0x04000356 +#define eng_3D_FOG_COLOR 0x04000358 +#define eng_3D_FOG_OFFSET 0x0400035C +#define eng_3D_FOG_TABLE 0x04000360 +#define eng_3D_TOON_TABLE 0x04000380 +#define eng_3D_GXFIFO 0x04000400 + +// 3d commands +#define cmd_3D_MTX_MODE 0x04000440 +#define cmd_3D_MTX_PUSH 0x04000444 +#define cmd_3D_MTX_POP 0x04000448 +#define cmd_3D_MTX_STORE 0x0400044C +#define cmd_3D_MTX_RESTORE 0x04000450 +#define cmd_3D_MTX_IDENTITY 0x04000454 +#define cmd_3D_MTX_LOAD_4x4 0x04000458 +#define cmd_3D_MTX_LOAD_4x3 0x0400045C +#define cmd_3D_MTX_MULT_4x4 0x04000460 +#define cmd_3D_MTX_MULT_4x3 0x04000464 +#define cmd_3D_MTX_MULT_3x3 0x04000468 +#define cmd_3D_MTX_SCALE 0x0400046C +#define cmd_3D_MTX_TRANS 0x04000470 +#define cmd_3D_COLOR 0x04000480 +#define cmd_3D_NORMA 0x04000484 +#define cmd_3D_TEXCOORD 0x04000488 +#define cmd_3D_VTX_16 0x0400048C +#define cmd_3D_VTX_10 0x04000490 +#define cmd_3D_VTX_XY 0x04000494 +#define cmd_3D_VTX_XZ 0x04000498 +#define cmd_3D_VTX_YZ 0x0400049C +#define cmd_3D_VTX_DIFF 0x040004A0 +#define cmd_3D_POLYGON_ATTR 0x040004A4 +#define cmd_3D_TEXIMAGE_PARAM 0x040004A8 +#define cmd_3D_PLTT_BASE 0x040004AC +#define cmd_3D_DIF_AMB 0x040004C0 +#define cmd_3D_SPE_EMI 0x040004C4 +#define cmd_3D_LIGHT_VECTOR 0x040004C8 +#define cmd_3D_LIGHT_COLOR 0x040004CC +#define cmd_3D_SHININESS 0x040004D0 +#define cmd_3D_BEGIN_VTXS 0x04000500 +#define cmd_3D_END_VTXS 0x04000504 +#define cmd_3D_SWAP_BUFFERS 0x04000540 +#define cmd_3D_VIEWPORT 0x04000580 +#define cmd_3D_BOX_TEST 0x040005C0 +#define cmd_3D_POS_TEST 0x040005C4 +#define cmd_3D_VEC_TEST 0x040005C8 + +#define eng_3D_GXSTAT 0x04000600 +#define eng_3D_RAM_COUNT 0x04000604 +#define eng_3D_DISP_1DOT_DEPTH 0x04000610 +#define eng_3D_POS_RESULT 0x04000620 +#define eng_3D_VEC_RESULT 0x04000630 +#define eng_3D_CLIPMTX_RESULT 0x04000640 +#define eng_3D_VECMTX_RESULT 0x04000680 + + +#endif diff -r fe2ba1a712cd -r 70b0973e7b70 src/xsf/desmume/thumb_instructions.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/xsf/desmume/thumb_instructions.c Thu Oct 16 14:45:41 2008 -0500 @@ -0,0 +1,944 @@ +/* + Copyright (C) 2006 yopyop + yopyop156@ifrance.com + yopyop156.ifrance.com + + Code added on 18/08/2006 by shash + - Missing missaligned addresses correction + (reference in http://nocash.emubase.de/gbatek.htm#cpumemoryalignments) + + This file is part of DeSmuME + + DeSmuME is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DeSmuME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DeSmuME; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "bios.h" +#include "debug.h" +#include "MMU.h" + +#define REG_NUM(i, n) (((i)>>n)&0x7) + +extern BOOL execute; + +// Use this macros for reading/writing, so the GDB stub isn't broken +#ifdef GDB_STUB + #define READ32(a,b) cpu->mem_if->read32(a,b) + #define WRITE32(a,b,c) cpu->mem_if->write32(a,b,c) + #define READ16(a,b) cpu->mem_if->read16(a,b) + #define WRITE16(a,b,c) cpu->mem_if->write16(a,b,c) + #define READ8(a,b) cpu->mem_if->read8(a,b) + #define WRITE8(a,b,c) cpu->mem_if->write8(a,b,c) +#else + #define READ32(a,b) MMU_read32(cpu->proc_ID, b) + #define WRITE32(a,b,c) MMU_write32(cpu->proc_ID,b,c) + #define READ16(a,b) MMU_read16(cpu->proc_ID, b) + #define WRITE16(a,b,c) MMU_write16(cpu->proc_ID,b,c) + #define READ8(a,b) MMU_read8(cpu->proc_ID, b) + #define WRITE8(a,b,c) MMU_write8(cpu->proc_ID,b,c) +#endif + +static u32 FASTCALL OP_UND_THUMB(armcpu_t *cpu) +{ + execute = FALSE; + return 1; +} + +static u32 FASTCALL OP_LSL_0(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + cpu->R[REG_NUM(i, 0)] = cpu->R[REG_NUM(i, 3)]; + cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]); + cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0; + + return 2; +} + +static u32 FASTCALL OP_LSL(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = (i>>6) & 0x1F; + cpu->CPSR.bits.C = BIT_N(cpu->R[REG_NUM(i, 3)], 32-v); + cpu->R[REG_NUM(i, 0)] = (cpu->R[REG_NUM(i, 3)] << v); + cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]); + cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0; + + return 2; +} + +static u32 FASTCALL OP_LSR_0(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + // cpu->CPSR.bits.C = BIT31(cpu->R[REG_NUM(i, 0)]); + cpu->CPSR.bits.C = BIT31(cpu->R[REG_NUM(i, 3)]); + cpu->R[REG_NUM(i, 0)] = 0; + cpu->CPSR.bits.N = 0; + cpu->CPSR.bits.Z = 1; + + return 2; +} + +static u32 FASTCALL OP_LSR(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = (i>>6) & 0x1F; + cpu->CPSR.bits.C = BIT_N(cpu->R[REG_NUM(i, 0)], v-1); + cpu->R[REG_NUM(i, 0)] = (cpu->R[REG_NUM(i, 3)] >> v); + cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]); + cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0; + + return 2; +} + +static u32 FASTCALL OP_ASR_0(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + cpu->CPSR.bits.C = BIT31(cpu->R[REG_NUM(i, 3)]); + cpu->R[REG_NUM(i, 0)] = BIT31(cpu->R[REG_NUM(i, 3)])*0xFFFFFFFF; + cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]); + cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0; + + return 2; +} + +static u32 FASTCALL OP_ASR(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = (i>>6) & 0x1F; + cpu->CPSR.bits.C = BIT_N(cpu->R[REG_NUM(i, 3)], v-1); + cpu->R[REG_NUM(i, 0)] = (((s32)cpu->R[REG_NUM(i, 3)]) >> v); + cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]); + cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0; + + return 2; +} + +static u32 FASTCALL OP_ADD_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 a = cpu->R[REG_NUM(i, 3)]; + u32 b = cpu->R[REG_NUM(i, 6)]; + cpu->R[REG_NUM(i, 0)] = a + b; + cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]); + cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0; + cpu->CPSR.bits.C = UNSIGNED_OVERFLOW(a, b, cpu->R[REG_NUM(i, 0)]); + cpu->CPSR.bits.V = SIGNED_OVERFLOW(a, b, cpu->R[REG_NUM(i, 0)]); + + return 3; +} + +static u32 FASTCALL OP_SUB_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 a = cpu->R[REG_NUM(i, 3)]; + u32 b = cpu->R[REG_NUM(i, 6)]; + cpu->R[REG_NUM(i, 0)] = a - b; + cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]); + cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0; + cpu->CPSR.bits.C = !UNSIGNED_UNDERFLOW(a, b, cpu->R[REG_NUM(i, 0)]); + cpu->CPSR.bits.V = SIGNED_UNDERFLOW(a, b, cpu->R[REG_NUM(i, 0)]); + + return 3; +} + +static u32 FASTCALL OP_ADD_IMM3(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 a = cpu->R[REG_NUM(i, 3)]; + cpu->R[REG_NUM(i, 0)] = a + REG_NUM(i, 6); + cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]); + cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0; + cpu->CPSR.bits.C = UNSIGNED_OVERFLOW(a, REG_NUM(i, 6), cpu->R[REG_NUM(i, 0)]); + cpu->CPSR.bits.V = SIGNED_OVERFLOW(a, REG_NUM(i, 6), cpu->R[REG_NUM(i, 0)]); + + return 2; +} + +static u32 FASTCALL OP_SUB_IMM3(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 a = cpu->R[REG_NUM(i, 3)]; + cpu->R[REG_NUM(i, 0)] = a - REG_NUM(i, 6); + cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]); + cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0; + cpu->CPSR.bits.C = !UNSIGNED_UNDERFLOW(a, REG_NUM(i, 6), cpu->R[REG_NUM(i, 0)]); + cpu->CPSR.bits.V = SIGNED_UNDERFLOW(a, REG_NUM(i, 6), cpu->R[REG_NUM(i, 0)]); + + return 2; +} + +static u32 FASTCALL OP_MOV_IMM8(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + cpu->R[REG_NUM(i, 8)] = i & 0xFF; + cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 8)]); + cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 8)] == 0; + + return 2; +} + +static u32 FASTCALL OP_CMP_IMM8(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 tmp = cpu->R[REG_NUM(i, 8)] - (i & 0xFF); + cpu->CPSR.bits.N = BIT31(tmp); + cpu->CPSR.bits.Z = tmp == 0; + cpu->CPSR.bits.C = !UNSIGNED_UNDERFLOW(cpu->R[REG_NUM(i, 8)], (i & 0xFF), tmp); + cpu->CPSR.bits.V = SIGNED_UNDERFLOW(cpu->R[REG_NUM(i, 8)], (i & 0xFF), tmp); + + return 2; +} + +static u32 FASTCALL OP_ADD_IMM8(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 tmp = cpu->R[REG_NUM(i, 8)] + (i & 0xFF); + cpu->CPSR.bits.N = BIT31(tmp); + cpu->CPSR.bits.Z = tmp == 0; + cpu->CPSR.bits.C = UNSIGNED_OVERFLOW(cpu->R[REG_NUM(i, 8)], (i & 0xFF), tmp); + cpu->CPSR.bits.V = SIGNED_OVERFLOW(cpu->R[REG_NUM(i, 8)], (i & 0xFF), tmp); + cpu->R[REG_NUM(i, 8)] = tmp; + + return 2; +} + +static u32 FASTCALL OP_SUB_IMM8(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 tmp = cpu->R[REG_NUM(i, 8)] - (i & 0xFF); + cpu->CPSR.bits.N = BIT31(tmp); + cpu->CPSR.bits.Z = tmp == 0; + cpu->CPSR.bits.C = !UNSIGNED_UNDERFLOW(cpu->R[REG_NUM(i, 8)], (i & 0xFF), tmp); + cpu->CPSR.bits.V = SIGNED_UNDERFLOW(cpu->R[REG_NUM(i, 8)], (i & 0xFF), tmp); + cpu->R[REG_NUM(i, 8)] = tmp; + + return 2; +} + +static u32 FASTCALL OP_AND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + cpu->R[REG_NUM(i, 0)] &= cpu->R[REG_NUM(i, 3)]; + cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]); + cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0; + + return 3; +} + +static u32 FASTCALL OP_EOR(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + cpu->R[REG_NUM(i, 0)] ^= cpu->R[REG_NUM(i, 3)]; + cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]); + cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0; + + return 3; +} + +static u32 FASTCALL OP_LSL_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_NUM(i, 3)]&0xFF; + + if(!v) + { + cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]); + cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0; + return 3; + } + if(v<32) + { + cpu->CPSR.bits.C = BIT_N(cpu->R[REG_NUM(i, 0)], 32-v); + cpu->R[REG_NUM(i, 0)] <<= v; + cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]); + cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0; + return 3; + } + if(v==32) + cpu->CPSR.bits.C = BIT0(cpu->R[REG_NUM(i, 0)]); + else + cpu->CPSR.bits.C = 0; + cpu->R[REG_NUM(i, 0)] = 0; + cpu->CPSR.bits.N = 0; + cpu->CPSR.bits.Z = 1; + + return 3; +} + +static u32 FASTCALL OP_LSR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_NUM(i, 3)]&0xFF; + + if(!v) + { + cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]); + cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0; + return 3; + } + if(v<32) + { + cpu->CPSR.bits.C = BIT_N(cpu->R[REG_NUM(i, 0)], v-1); + cpu->R[REG_NUM(i, 0)] >>= v; + cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]); + cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0; + return 3; + } + if(v==32) + cpu->CPSR.bits.C = BIT31(cpu->R[REG_NUM(i, 0)]); + else + cpu->CPSR.bits.C = 0; + cpu->R[REG_NUM(i, 0)] = 0; + cpu->CPSR.bits.N = 0; + cpu->CPSR.bits.Z = 1; + + return 3; +} + +static u32 FASTCALL OP_ASR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_NUM(i, 3)]&0xFF; + + if(!v) + { + cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]); + cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0; + return 3; + } + if(v<32) + { + cpu->CPSR.bits.C = BIT_N(cpu->R[REG_NUM(i, 0)], v-1); + cpu->R[REG_NUM(i, 0)] = (u32)(((s32)cpu->R[REG_NUM(i, 0)]) >> v); + cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]); + cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0; + return 3; + } + + cpu->CPSR.bits.C = BIT31(cpu->R[REG_NUM(i, 0)]); + cpu->R[REG_NUM(i, 0)] = BIT31(cpu->R[REG_NUM(i, 0)])*0xFFFFFFFF; + cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]); + cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0; + + return 3; +} + +static u32 FASTCALL OP_ADC_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 a = cpu->R[REG_NUM(i, 0)]; + u32 b = cpu->R[REG_NUM(i, 3)]; + u32 tmp = b + cpu->CPSR.bits.C; + u32 res = a + tmp; + + cpu->R[REG_NUM(i, 0)] = res; + + cpu->CPSR.bits.N = BIT31(res); + cpu->CPSR.bits.Z = res == 0; + + cpu->CPSR.bits.C = UNSIGNED_OVERFLOW(b, cpu->CPSR.bits.C, tmp) | UNSIGNED_OVERFLOW(tmp, a, res); + cpu->CPSR.bits.V = SIGNED_OVERFLOW(b, cpu->CPSR.bits.C, tmp) | SIGNED_OVERFLOW(tmp, a, res); + + return 3; +} + +static u32 FASTCALL OP_SBC_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 a = cpu->R[REG_NUM(i, 0)]; + u32 b = cpu->R[REG_NUM(i, 3)]; + u32 tmp = a - (!cpu->CPSR.bits.C); + u32 res = tmp - b; + cpu->R[REG_NUM(i, 0)] = res; + + cpu->CPSR.bits.N = BIT31(res); + cpu->CPSR.bits.Z = res == 0; + + cpu->CPSR.bits.C = (!UNSIGNED_UNDERFLOW(a, !cpu->CPSR.bits.C, tmp)) & (!UNSIGNED_OVERFLOW(tmp, b, res)); + cpu->CPSR.bits.V = SIGNED_UNDERFLOW(a, !cpu->CPSR.bits.C, tmp) | SIGNED_OVERFLOW(tmp, b, res); + + return 3; +} + +static u32 FASTCALL OP_ROR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_NUM(i, 3)]&0xFF; + + if(v == 0) + { + cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]); + cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0; + return 3; + } + v &= 0xF; + if(v == 0) + { + cpu->CPSR.bits.C = BIT31(cpu->R[REG_NUM(i, 0)]); + cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]); + cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0; + return 3; + } + cpu->CPSR.bits.C = BIT_N(cpu->R[REG_NUM(i, 0)], v-1); + cpu->R[REG_NUM(i, 0)] = ROR(cpu->R[REG_NUM(i, 0)], v); + cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]); + cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0; + + return 3; +} + +static u32 FASTCALL OP_TST(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 tmp = cpu->R[REG_NUM(i, 0)] & cpu->R[REG_NUM(i, 3)]; + cpu->CPSR.bits.N = BIT31(tmp); + cpu->CPSR.bits.Z = tmp == 0; + + return 3; +} + +static u32 FASTCALL OP_NEG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 a = cpu->R[REG_NUM(i, 3)]; + cpu->R[REG_NUM(i, 0)] = -((signed int)a); + + cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]); + cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0; + cpu->CPSR.bits.C = !UNSIGNED_UNDERFLOW(0, a, cpu->R[REG_NUM(i, 0)]); + cpu->CPSR.bits.V = SIGNED_UNDERFLOW(0, a, cpu->R[REG_NUM(i, 0)]); + + return 3; +} + +static u32 FASTCALL OP_CMP(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 tmp = cpu->R[REG_NUM(i, 0)] -cpu->R[REG_NUM(i, 3)]; + + cpu->CPSR.bits.N = BIT31(tmp); + cpu->CPSR.bits.Z = tmp == 0; + cpu->CPSR.bits.C = !UNSIGNED_UNDERFLOW(cpu->R[REG_NUM(i, 0)], cpu->R[REG_NUM(i, 3)], tmp); + cpu->CPSR.bits.V = SIGNED_UNDERFLOW(cpu->R[REG_NUM(i, 0)], cpu->R[REG_NUM(i, 3)], tmp); + + return 3; +} + +static u32 FASTCALL OP_CMN(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 tmp = cpu->R[REG_NUM(i, 0)] + cpu->R[REG_NUM(i, 3)]; + + //execute = FALSE; + //log::ajouter("OP_CMN THUMB"); + cpu->CPSR.bits.N = BIT31(tmp); + cpu->CPSR.bits.Z = tmp == 0; + cpu->CPSR.bits.C = UNSIGNED_OVERFLOW(cpu->R[REG_NUM(i, 0)], cpu->R[REG_NUM(i, 3)], tmp); + cpu->CPSR.bits.V = SIGNED_OVERFLOW(cpu->R[REG_NUM(i, 0)], cpu->R[REG_NUM(i, 3)], tmp); + + return 3; +} + +static u32 FASTCALL OP_ORR(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + cpu->R[REG_NUM(i, 0)] |= cpu->R[REG_NUM(i, 3)]; + cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]); + cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0; + + return 3; +} + +static u32 FASTCALL OP_MUL_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + cpu->R[REG_NUM(i, 0)] *= cpu->R[REG_NUM(i, 3)]; + cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]); + cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0; + + return 3; +} + +static u32 FASTCALL OP_BIC(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + cpu->R[REG_NUM(i, 0)] &= (~cpu->R[REG_NUM(i, 3)]); + cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]); + cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0; + + return 3; +} + +static u32 FASTCALL OP_MVN(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + cpu->R[REG_NUM(i, 0)] = (~cpu->R[REG_NUM(i, 3)]); + cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]); + cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0; + + return 3; +} + +static u32 FASTCALL OP_ADD_SPE(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 Rd = (i&7) | ((i>>4)&8); + cpu->R[Rd] += cpu->R[REG_POS(i, 3)]; + + if(Rd==15) + cpu->next_instruction = cpu->R[15]; + + return 2; +} + +static u32 FASTCALL OP_CMP_SPE(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 Rn = (i&7) | ((i>>4)&8); + u32 tmp = cpu->R[Rn] -cpu->R[REG_POS(i, 3)]; + + cpu->CPSR.bits.N = BIT31(tmp); + cpu->CPSR.bits.Z = tmp == 0; + cpu->CPSR.bits.C = !UNSIGNED_UNDERFLOW(cpu->R[Rn], cpu->R[REG_POS(i, 3)], tmp); + cpu->CPSR.bits.V = SIGNED_UNDERFLOW(cpu->R[Rn], cpu->R[REG_POS(i, 3)], tmp); + + return 3; +} + +static u32 FASTCALL OP_MOV_SPE(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 Rd = (i&7) | ((i>>4)&8); + cpu->R[Rd] = cpu->R[REG_POS(i, 3)]; + + if(Rd==15) + cpu->next_instruction = cpu->R[15]; + + return 2; +} + +static u32 FASTCALL OP_BX_THUMB(armcpu_t *cpu) +{ + u32 Rm = cpu->R[REG_POS(cpu->instruction, 3)]; + + cpu->CPSR.bits.T = BIT0(Rm); + cpu->R[15] = (Rm & 0xFFFFFFFE); + cpu->next_instruction = cpu->R[15]; + + return 3; +} + +static u32 FASTCALL OP_BLX_THUMB(armcpu_t *cpu) +{ + u32 Rm = cpu->R[REG_POS(cpu->instruction, 3)]; + + cpu->CPSR.bits.T = BIT0(Rm); + cpu->R[14] = cpu->next_instruction | 1; + cpu->R[15] = (Rm & 0xFFFFFFFE); + cpu->next_instruction = cpu->R[15]; + + return 3; +} + +static u32 FASTCALL OP_LDR_PCREL(armcpu_t *cpu) +{ + u32 adr = (cpu->R[15]&0xFFFFFFFC) + ((cpu->instruction&0xFF)<<2); + + cpu->R[REG_NUM(cpu->instruction, 8)] = READ32(cpu->mem_if->data, adr); + + return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STR_REG_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_NUM(i, 6)] + cpu->R[REG_NUM(i, 3)]; + WRITE32(cpu->mem_if->data, adr, cpu->R[REG_NUM(i, 0)]); + + return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRH_REG_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_NUM(i, 3)] + cpu->R[REG_NUM(i, 6)]; + WRITE16(cpu->mem_if->data, adr, ((u16)cpu->R[REG_NUM(i, 0)])); + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRB_REG_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_NUM(i, 3)] + cpu->R[REG_NUM(i, 6)]; + WRITE8(cpu->mem_if->data, adr, ((u8)cpu->R[REG_NUM(i, 0)])); + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRSB_REG_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_NUM(i, 3)] + cpu->R[REG_NUM(i, 6)]; + cpu->R[REG_NUM(i, 0)] = (s32)((s8)READ8(cpu->mem_if->data, adr)); + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDR_REG_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = (cpu->R[REG_NUM(i, 3)] + cpu->R[REG_NUM(i, 6)]); + u32 tempValue = READ32(cpu->mem_if->data, adr&0xFFFFFFFC); + + adr = (adr&3)*8; + tempValue = (tempValue>>adr) | (tempValue<<(32-adr)); + cpu->R[REG_NUM(i, 0)] = tempValue; + + return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRH_REG_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_NUM(i, 3)] + cpu->R[REG_NUM(i, 6)]; + cpu->R[REG_NUM(i, 0)] = (u32)READ16(cpu->mem_if->data, adr); + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRB_REG_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_NUM(i, 3)] + cpu->R[REG_NUM(i, 6)]; + cpu->R[REG_NUM(i, 0)] = (u32)READ8(cpu->mem_if->data, adr); + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRSH_REG_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_NUM(i, 3)] + cpu->R[REG_NUM(i, 6)]; + cpu->R[REG_NUM(i, 0)] = (s32)((s16)READ16(cpu->mem_if->data, adr)); + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STR_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_NUM(i, 3)] + ((i>>4)&0x7C); + WRITE32(cpu->mem_if->data, adr, cpu->R[REG_NUM(i, 0)]); + + return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDR_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_NUM(i, 3)] + ((i>>4)&0x7C); + u32 tempValue = READ32(cpu->mem_if->data, adr&0xFFFFFFFC); + adr = (adr&3)*8; + tempValue = (tempValue>>adr) | (tempValue<<(32-adr)); + cpu->R[REG_NUM(i, 0)] = tempValue; + + return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRB_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_NUM(i, 3)] + ((i>>6)&0x1F); + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_NUM(i, 0)]); + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRB_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_NUM(i, 3)] + ((i>>6)&0x1F); + cpu->R[REG_NUM(i, 0)] = READ8(cpu->mem_if->data, adr); + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRH_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_NUM(i, 3)] + ((i>>5)&0x3E); + WRITE16(cpu->mem_if->data, adr, (u16)cpu->R[REG_NUM(i, 0)]); + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRH_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_NUM(i, 3)] + ((i>>5)&0x3E); + cpu->R[REG_NUM(i, 0)] = READ16(cpu->mem_if->data, adr); + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STR_SPREL(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[13] + ((i&0xFF)<<2); + WRITE32(cpu->mem_if->data, adr, cpu->R[REG_NUM(i, 8)]); + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDR_SPREL(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[13] + ((i&0xFF)<<2); + cpu->R[REG_NUM(i, 8)] = READ32(cpu->mem_if->data, adr); + + return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_ADD_2PC(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + cpu->R[REG_NUM(i, 8)] = (cpu->R[15]&0xFFFFFFFC) + ((i&0xFF)<<2); + + return 5; +} + +static u32 FASTCALL OP_ADD_2SP(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + cpu->R[REG_NUM(i, 8)] = cpu->R[13] + ((i&0xFF)<<2); + + return 2; +} + +static u32 FASTCALL OP_ADJUST_P_SP(armcpu_t *cpu) +{ + cpu->R[13] += ((cpu->instruction&0x7F)<<2); + + return 1; +} + +static u32 FASTCALL OP_ADJUST_M_SP(armcpu_t *cpu) +{ + cpu->R[13] -= ((cpu->instruction&0x7F)<<2); + + return 1; +} + +static u32 FASTCALL OP_PUSH(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[13] - 4; + u32 c = 0, j; + + for(j = 0; j<8; ++j) + if(BIT_N(i, 7-j)) + { + WRITE32(cpu->mem_if->data, adr, cpu->R[7-j]); + c += MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; + adr -= 4; + } + cpu->R[13] = adr + 4; + + return c + 3; +} + +static u32 FASTCALL OP_PUSH_LR(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[13] - 4; + u32 c = 0, j; + + WRITE32(cpu->mem_if->data, adr, cpu->R[14]); + c += MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; + adr -= 4; + + for(j = 0; j<8; ++j) + if(BIT_N(i, 7-j)) + { + WRITE32(cpu->mem_if->data, adr, cpu->R[7-j]); + c += MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; + adr -= 4; + } + cpu->R[13] = adr + 4; + + return c + 4; +} + +static u32 FASTCALL OP_POP(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[13]; + u32 c = 0, j; + + for(j = 0; j<8; ++j) + if(BIT_N(i, j)) + { + cpu->R[j] = READ32(cpu->mem_if->data, adr); + c += MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; + adr += 4; + } + cpu->R[13] = adr; + + return c + 2; +} + +static u32 FASTCALL OP_POP_PC(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[13]; + u32 c = 0, j; + u32 v; + + for(j = 0; j<8; ++j) + if(BIT_N(i, j)) + { + cpu->R[j] = READ32(cpu->mem_if->data, adr); + c += MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; + adr += 4; + } + + v = READ32(cpu->mem_if->data, adr); + c += MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; + cpu->R[15] = v & 0xFFFFFFFE; + cpu->next_instruction = v & 0xFFFFFFFE; + if(cpu->proc_ID==0) + cpu->CPSR.bits.T = BIT0(v); + adr += 4; + + cpu->R[13] = adr; + return c + 5; +} + +static u32 FASTCALL OP_BKPT_THUMB(armcpu_t *cpu) +{ + return 1; +} + +static u32 FASTCALL OP_STMIA_THUMB(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_NUM(i, 8)]; + u32 c = 0, j; + + for(j = 0; j<8; ++j) + if(BIT_N(i, j)) + { + WRITE32(cpu->mem_if->data, adr, cpu->R[j]); + c += MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; + adr += 4; + } + cpu->R[REG_NUM(i, 8)] = adr; + return c + 2; +} + +static u32 FASTCALL OP_LDMIA_THUMB(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_NUM(i, 8)]; + u32 c = 0, j; + + for(j = 0; j<8; ++j) + if(BIT_N(i, j)) + { + cpu->R[j] = READ32(cpu->mem_if->data, adr); + c += MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; + adr += 4; + } + cpu->R[REG_NUM(i, 8)] = adr; + return c + 3; +} + +static u32 FASTCALL OP_B_COND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + if(!TEST_COND((i>>8)&0xF, 0, cpu->CPSR)) + return 1; + + cpu->R[15] += ((s32)((s8)(i&0xFF)))<<1; + cpu->next_instruction = cpu->R[15]; + return 3; +} + +static u32 FASTCALL OP_SWI_THUMB(armcpu_t *cpu) +{ + if (((cpu->intVector != 0) ^ (cpu->proc_ID == ARMCPU_ARM9))) + { + /* we use an irq thats not in the irq tab, as + it was replaced duie to a changed intVector */ + Status_Reg tmp = cpu->CPSR; + armcpu_switchMode(cpu, SVC); /* enter svc mode */ + cpu->R[14] = cpu->R[15] - 4; /* jump to swi Vector */ + cpu->SPSR = tmp; /* save old CPSR as new SPSR */ + cpu->CPSR.bits.T = 0; /* handle as ARM32 code */ + cpu->CPSR.bits.I = cpu->SPSR.bits.I; /* keep int disable flag */ + cpu->R[15] = cpu->intVector + 0x08; + cpu->next_instruction = cpu->R[15]; + return 3; + } + else + { + u32 swinum = cpu->instruction & 0xFF; + return cpu->swi_tab[swinum](cpu) + 3; + } + //return 3; +} + +#define SIGNEEXT_IMM11(i) (((i)&0x7FF) | (BIT10(i) * 0xFFFFF800)) + +static u32 FASTCALL OP_B_UNCOND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + cpu->R[15] += (SIGNEEXT_IMM11(i)<<1); + cpu->next_instruction = cpu->R[15]; + return 3; +} + +static u32 FASTCALL OP_BLX(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + cpu->R[15] = (cpu->R[14] + ((i&0x7FF)<<1))&0xFFFFFFFC; + cpu->R[14] = cpu->next_instruction | 1; + cpu->next_instruction = cpu->R[15]; + cpu->CPSR.bits.T = 0; + return 3; +} + +static u32 FASTCALL OP_BL_10(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + cpu->R[14] = cpu->R[15] + (SIGNEEXT_IMM11(i)<<12); + return 1; +} + +static u32 FASTCALL OP_BL_THUMB(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + cpu->R[15] = (cpu->R[14] + ((i&0x7FF)<<1)); + cpu->R[14] = cpu->next_instruction | 1; + cpu->next_instruction = cpu->R[15]; + return 3; +} + +#define TYPE_RETOUR u32 +#define CALLTYPE FASTCALL +#define PARAMETRES armcpu_t *cpu +#define NOM_THUMB_TAB thumb_instructions_set + +#include "thumb_tabdef.inc" diff -r fe2ba1a712cd -r 70b0973e7b70 src/xsf/desmume/thumb_instructions.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/xsf/desmume/thumb_instructions.h Thu Oct 16 14:45:41 2008 -0500 @@ -0,0 +1,30 @@ +/* Copyright (C) 2006 yopyop + yopyop156@ifrance.com + yopyop156.ifrance.com + + This file is part of DeSmuME + + DeSmuME is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DeSmuME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DeSmuME; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef THUMB_INSTRUCTIONS_H +#define THUMB_INSTRUCTIONS_H + +#include "armcpu.h" + +extern u32 (FASTCALL* thumb_instructions_set[1024])(armcpu_t * cpu); + +#endif + diff -r fe2ba1a712cd -r 70b0973e7b70 src/xsf/desmume/thumb_tabdef.inc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/xsf/desmume/thumb_tabdef.inc Thu Oct 16 14:45:41 2008 -0500 @@ -0,0 +1,1111 @@ +/* Copyright (C) 2006 yopyop + yopyop156@ifrance.com + yopyop156.ifrance.com + + This file is part of DeSmuME + + DeSmuME is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DeSmuME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DeSmuME; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +TYPE_RETOUR (* CALLTYPE NOM_THUMB_TAB[1024])(PARAMETRES)={ + OP_LSL_0, //00 0000 0000 + OP_LSL, //00 0000 0001 + OP_LSL, //00 0000 0010 + OP_LSL, //00 0000 0011 + OP_LSL, //00 0000 0100 + OP_LSL, //00 0000 0101 + OP_LSL, //00 0000 0110 + OP_LSL, //00 0000 0111 + OP_LSL, //00 0000 1000 + OP_LSL, //00 0000 1001 + OP_LSL, //00 0000 1010 + OP_LSL, //00 0000 1011 + OP_LSL, //00 0000 1100 + OP_LSL, //00 0000 1101 + OP_LSL, //00 0000 1110 + OP_LSL, //00 0000 1111 + + OP_LSL, //00 0001 0000 + OP_LSL, //00 0001 0001 + OP_LSL, //00 0001 0010 + OP_LSL, //00 0001 0011 + OP_LSL, //00 0001 0100 + OP_LSL, //00 0001 0101 + OP_LSL, //00 0001 0110 + OP_LSL, //00 0001 0111 + OP_LSL, //00 0001 1000 + OP_LSL, //00 0001 1001 + OP_LSL, //00 0001 1010 + OP_LSL, //00 0001 1011 + OP_LSL, //00 0001 1100 + OP_LSL, //00 0001 1101 + OP_LSL, //00 0001 1110 + OP_LSL, //00 0001 1111 + + OP_LSR_0, //00 0010 0000 + OP_LSR, //00 0010 0001 + OP_LSR, //00 0010 0010 + OP_LSR, //00 0010 0011 + OP_LSR, //00 0010 0100 + OP_LSR, //00 0010 0101 + OP_LSR, //00 0010 0110 + OP_LSR, //00 0010 0111 + OP_LSR, //00 0010 1000 + OP_LSR, //00 0010 1001 + OP_LSR, //00 0010 1010 + OP_LSR, //00 0010 1011 + OP_LSR, //00 0010 1100 + OP_LSR, //00 0010 1101 + OP_LSR, //00 0010 1110 + OP_LSR, //00 0010 1111 + + OP_LSR, //00 0011 0000 + OP_LSR, //00 0011 0001 + OP_LSR, //00 0011 0010 + OP_LSR, //00 0011 0011 + OP_LSR, //00 0011 0100 + OP_LSR, //00 0011 0101 + OP_LSR, //00 0011 0110 + OP_LSR, //00 0011 0111 + OP_LSR, //00 0011 1000 + OP_LSR, //00 0011 1001 + OP_LSR, //00 0011 1010 + OP_LSR, //00 0011 1011 + OP_LSR, //00 0011 1100 + OP_LSR, //00 0011 1101 + OP_LSR, //00 0011 1110 + OP_LSR, //00 0011 1111 + + OP_ASR_0, //00 0100 0000 + OP_ASR, //00 0100 0001 + OP_ASR, //00 0100 0010 + OP_ASR, //00 0100 0011 + OP_ASR, //00 0100 0100 + OP_ASR, //00 0100 0101 + OP_ASR, //00 0100 0110 + OP_ASR, //00 0100 0111 + OP_ASR, //00 0100 1000 + OP_ASR, //00 0100 1001 + OP_ASR, //00 0100 1010 + OP_ASR, //00 0100 1011 + OP_ASR, //00 0100 1100 + OP_ASR, //00 0100 1101 + OP_ASR, //00 0100 1110 + OP_ASR, //00 0100 1111 + + OP_ASR, //00 0101 0000 + OP_ASR, //00 0101 0001 + OP_ASR, //00 0101 0010 + OP_ASR, //00 0101 0011 + OP_ASR, //00 0101 0100 + OP_ASR, //00 0101 0101 + OP_ASR, //00 0101 0110 + OP_ASR, //00 0101 0111 + OP_ASR, //00 0101 1000 + OP_ASR, //00 0101 1001 + OP_ASR, //00 0101 1010 + OP_ASR, //00 0101 1011 + OP_ASR, //00 0101 1100 + OP_ASR, //00 0101 1101 + OP_ASR, //00 0101 1110 + OP_ASR, //00 0101 1111 + + OP_ADD_REG, //00 0110 0000 + OP_ADD_REG, //00 0110 0001 + OP_ADD_REG, //00 0110 0010 + OP_ADD_REG, //00 0110 0011 + OP_ADD_REG, //00 0110 0100 + OP_ADD_REG, //00 0110 0101 + OP_ADD_REG, //00 0110 0110 + OP_ADD_REG, //00 0110 0111 + OP_SUB_REG, //00 0110 1000 + OP_SUB_REG, //00 0110 1001 + OP_SUB_REG, //00 0110 1010 + OP_SUB_REG, //00 0110 1011 + OP_SUB_REG, //00 0110 1100 + OP_SUB_REG, //00 0110 1101 + OP_SUB_REG, //00 0110 1110 + OP_SUB_REG, //00 0110 1111 + + OP_ADD_IMM3, //00 0111 0000 + OP_ADD_IMM3, //00 0111 0001 + OP_ADD_IMM3, //00 0111 0010 + OP_ADD_IMM3, //00 0111 0011 + OP_ADD_IMM3, //00 0111 0100 + OP_ADD_IMM3, //00 0111 0101 + OP_ADD_IMM3, //00 0111 0110 + OP_ADD_IMM3, //00 0111 0111 + OP_SUB_IMM3, //00 0111 1000 + OP_SUB_IMM3, //00 0111 1001 + OP_SUB_IMM3, //00 0111 1010 + OP_SUB_IMM3, //00 0111 1011 + OP_SUB_IMM3, //00 0111 1100 + OP_SUB_IMM3, //00 0111 1101 + OP_SUB_IMM3, //00 0111 1110 + OP_SUB_IMM3, //00 0111 1111 + + OP_MOV_IMM8, //00 1000 0000 + OP_MOV_IMM8, //00 1000 0001 + OP_MOV_IMM8, //00 1000 0010 + OP_MOV_IMM8, //00 1000 0011 + OP_MOV_IMM8, //00 1000 0100 + OP_MOV_IMM8, //00 1000 0101 + OP_MOV_IMM8, //00 1000 0110 + OP_MOV_IMM8, //00 1000 0111 + OP_MOV_IMM8, //00 1000 1000 + OP_MOV_IMM8, //00 1000 1001 + OP_MOV_IMM8, //00 1000 1010 + OP_MOV_IMM8, //00 1000 1011 + OP_MOV_IMM8, //00 1000 1100 + OP_MOV_IMM8, //00 1000 1101 + OP_MOV_IMM8, //00 1000 1110 + OP_MOV_IMM8, //00 1000 1111 + + OP_MOV_IMM8, //00 1001 0000 + OP_MOV_IMM8, //00 1001 0001 + OP_MOV_IMM8, //00 1001 0010 + OP_MOV_IMM8, //00 1001 0011 + OP_MOV_IMM8, //00 1001 0100 + OP_MOV_IMM8, //00 1001 0101 + OP_MOV_IMM8, //00 1001 0110 + OP_MOV_IMM8, //00 1001 0111 + OP_MOV_IMM8, //00 1001 1000 + OP_MOV_IMM8, //00 1001 1001 + OP_MOV_IMM8, //00 1001 1010 + OP_MOV_IMM8, //00 1001 1011 + OP_MOV_IMM8, //00 1001 1100 + OP_MOV_IMM8, //00 1001 1101 + OP_MOV_IMM8, //00 1001 1110 + OP_MOV_IMM8, //00 1001 1111 + + OP_CMP_IMM8, //00 1010 0000 + OP_CMP_IMM8, //00 1010 0001 + OP_CMP_IMM8, //00 1010 0010 + OP_CMP_IMM8, //00 1010 0011 + OP_CMP_IMM8, //00 1010 0100 + OP_CMP_IMM8, //00 1010 0101 + OP_CMP_IMM8, //00 1010 0110 + OP_CMP_IMM8, //00 1010 0111 + OP_CMP_IMM8, //00 1010 1000 + OP_CMP_IMM8, //00 1010 1001 + OP_CMP_IMM8, //00 1010 1010 + OP_CMP_IMM8, //00 1010 1011 + OP_CMP_IMM8, //00 1010 1100 + OP_CMP_IMM8, //00 1010 1101 + OP_CMP_IMM8, //00 1010 1110 + OP_CMP_IMM8, //00 1010 1111 + + OP_CMP_IMM8, //00 1011 0000 + OP_CMP_IMM8, //00 1011 0001 + OP_CMP_IMM8, //00 1011 0010 + OP_CMP_IMM8, //00 1011 0011 + OP_CMP_IMM8, //00 1011 0100 + OP_CMP_IMM8, //00 1011 0101 + OP_CMP_IMM8, //00 1011 0110 + OP_CMP_IMM8, //00 1011 0111 + OP_CMP_IMM8, //00 1011 1000 + OP_CMP_IMM8, //00 1011 1001 + OP_CMP_IMM8, //00 1011 1010 + OP_CMP_IMM8, //00 1011 1011 + OP_CMP_IMM8, //00 1011 1100 + OP_CMP_IMM8, //00 1011 1101 + OP_CMP_IMM8, //00 1011 1110 + OP_CMP_IMM8, //00 1011 1111 + + OP_ADD_IMM8, //00 1100 0000 + OP_ADD_IMM8, //00 1100 0001 + OP_ADD_IMM8, //00 1100 0010 + OP_ADD_IMM8, //00 1100 0011 + OP_ADD_IMM8, //00 1100 0100 + OP_ADD_IMM8, //00 1100 0101 + OP_ADD_IMM8, //00 1100 0110 + OP_ADD_IMM8, //00 1100 0111 + OP_ADD_IMM8, //00 1100 1000 + OP_ADD_IMM8, //00 1100 1001 + OP_ADD_IMM8, //00 1100 1010 + OP_ADD_IMM8, //00 1100 1011 + OP_ADD_IMM8, //00 1100 1100 + OP_ADD_IMM8, //00 1100 1101 + OP_ADD_IMM8, //00 1100 1110 + OP_ADD_IMM8, //00 1100 1111 + + OP_ADD_IMM8, //00 1101 0000 + OP_ADD_IMM8, //00 1101 0001 + OP_ADD_IMM8, //00 1101 0010 + OP_ADD_IMM8, //00 1101 0011 + OP_ADD_IMM8, //00 1101 0100 + OP_ADD_IMM8, //00 1101 0101 + OP_ADD_IMM8, //00 1101 0110 + OP_ADD_IMM8, //00 1101 0111 + OP_ADD_IMM8, //00 1101 1000 + OP_ADD_IMM8, //00 1101 1001 + OP_ADD_IMM8, //00 1101 1010 + OP_ADD_IMM8, //00 1101 1011 + OP_ADD_IMM8, //00 1101 1100 + OP_ADD_IMM8, //00 1101 1101 + OP_ADD_IMM8, //00 1101 1110 + OP_ADD_IMM8, //00 1101 1111 + + OP_SUB_IMM8, //00 1110 0000 + OP_SUB_IMM8, //00 1110 0001 + OP_SUB_IMM8, //00 1110 0010 + OP_SUB_IMM8, //00 1110 0011 + OP_SUB_IMM8, //00 1110 0100 + OP_SUB_IMM8, //00 1110 0101 + OP_SUB_IMM8, //00 1110 0110 + OP_SUB_IMM8, //00 1110 0111 + OP_SUB_IMM8, //00 1110 1000 + OP_SUB_IMM8, //00 1110 1001 + OP_SUB_IMM8, //00 1110 1010 + OP_SUB_IMM8, //00 1110 1011 + OP_SUB_IMM8, //00 1110 1100 + OP_SUB_IMM8, //00 1110 1101 + OP_SUB_IMM8, //00 1110 1110 + OP_SUB_IMM8, //00 1110 1111 + + OP_SUB_IMM8, //00 1111 0000 + OP_SUB_IMM8, //00 1111 0001 + OP_SUB_IMM8, //00 1111 0010 + OP_SUB_IMM8, //00 1111 0011 + OP_SUB_IMM8, //00 1111 0100 + OP_SUB_IMM8, //00 1111 0101 + OP_SUB_IMM8, //00 1111 0110 + OP_SUB_IMM8, //00 1111 0111 + OP_SUB_IMM8, //00 1111 1000 + OP_SUB_IMM8, //00 1111 1001 + OP_SUB_IMM8, //00 1111 1010 + OP_SUB_IMM8, //00 1111 1011 + OP_SUB_IMM8, //00 1111 1100 + OP_SUB_IMM8, //00 1111 1101 + OP_SUB_IMM8, //00 1111 1110 + OP_SUB_IMM8, //00 1111 1111 + + OP_AND, //01 0000 0000 + OP_EOR, //01 0000 0001 + OP_LSL_REG, //01 0000 0010 + OP_LSR_REG, //01 0000 0011 + OP_ASR_REG, //01 0000 0100 + OP_ADC_REG, //01 0000 0101 + OP_SBC_REG, //01 0000 0110 + OP_ROR_REG, //01 0000 0111 + OP_TST, //01 0000 1000 + OP_NEG, //01 0000 1001 + OP_CMP, //01 0000 1010 + OP_CMN, //01 0000 1011 + OP_ORR, //01 0000 1100 + OP_MUL_REG, //01 0000 1101 + OP_BIC, //01 0000 1110 + OP_MVN, //01 0000 1111 + + OP_ADD_SPE, //01 0001 0000 + OP_ADD_SPE, //01 0001 0001 + OP_ADD_SPE, //01 0001 0010 + OP_ADD_SPE, //01 0001 0011 + OP_CMP_SPE, //01 0001 0100 + OP_CMP_SPE, //01 0001 0101 + OP_CMP_SPE, //01 0001 0110 + OP_CMP_SPE, //01 0001 0111 + OP_MOV_SPE, //01 0001 1000 + OP_MOV_SPE, //01 0001 1001 + OP_MOV_SPE, //01 0001 1010 + OP_MOV_SPE, //01 0001 1011 + OP_BX_THUMB, //01 0001 1100 + OP_BX_THUMB, //01 0001 1101 + OP_BLX_THUMB, //01 0001 1110 + OP_BLX_THUMB, //01 0001 1111 + + OP_LDR_PCREL, //01 0010 0000 + OP_LDR_PCREL, //01 0010 0001 + OP_LDR_PCREL, //01 0010 0010 + OP_LDR_PCREL, //01 0010 0011 + OP_LDR_PCREL, //01 0010 0100 + OP_LDR_PCREL, //01 0010 0101 + OP_LDR_PCREL, //01 0010 0110 + OP_LDR_PCREL, //01 0010 0111 + OP_LDR_PCREL, //01 0010 1000 + OP_LDR_PCREL, //01 0010 1001 + OP_LDR_PCREL, //01 0010 1010 + OP_LDR_PCREL, //01 0010 1011 + OP_LDR_PCREL, //01 0010 1100 + OP_LDR_PCREL, //01 0010 1101 + OP_LDR_PCREL, //01 0010 1110 + OP_LDR_PCREL, //01 0010 1111 + + OP_LDR_PCREL, //01 0011 0000 + OP_LDR_PCREL, //01 0011 0001 + OP_LDR_PCREL, //01 0011 0010 + OP_LDR_PCREL, //01 0011 0011 + OP_LDR_PCREL, //01 0011 0100 + OP_LDR_PCREL, //01 0011 0101 + OP_LDR_PCREL, //01 0011 0110 + OP_LDR_PCREL, //01 0011 0111 + OP_LDR_PCREL, //01 0011 1000 + OP_LDR_PCREL, //01 0011 1001 + OP_LDR_PCREL, //01 0011 1010 + OP_LDR_PCREL, //01 0011 1011 + OP_LDR_PCREL, //01 0011 1100 + OP_LDR_PCREL, //01 0011 1101 + OP_LDR_PCREL, //01 0011 1110 + OP_LDR_PCREL, //01 0011 1111 + + OP_STR_REG_OFF, //01 0100 0000 + OP_STR_REG_OFF, //01 0100 0001 + OP_STR_REG_OFF, //01 0100 0010 + OP_STR_REG_OFF, //01 0100 0011 + OP_STR_REG_OFF, //01 0100 0100 + OP_STR_REG_OFF, //01 0100 0101 + OP_STR_REG_OFF, //01 0100 0110 + OP_STR_REG_OFF, //01 0100 0111 + OP_STRH_REG_OFF, //01 0100 1000 + OP_STRH_REG_OFF, //01 0100 1001 + OP_STRH_REG_OFF, //01 0100 1010 + OP_STRH_REG_OFF, //01 0100 1011 + OP_STRH_REG_OFF, //01 0100 1100 + OP_STRH_REG_OFF, //01 0100 1101 + OP_STRH_REG_OFF, //01 0100 1110 + OP_STRH_REG_OFF, //01 0100 1111 + + OP_STRB_REG_OFF, //01 0101 0000 + OP_STRB_REG_OFF, //01 0101 0001 + OP_STRB_REG_OFF, //01 0101 0010 + OP_STRB_REG_OFF, //01 0101 0011 + OP_STRB_REG_OFF, //01 0101 0100 + OP_STRB_REG_OFF, //01 0101 0101 + OP_STRB_REG_OFF, //01 0101 0110 + OP_STRB_REG_OFF, //01 0101 0111 + OP_LDRSB_REG_OFF, //01 0101 1000 + OP_LDRSB_REG_OFF, //01 0101 1001 + OP_LDRSB_REG_OFF, //01 0101 1010 + OP_LDRSB_REG_OFF, //01 0101 1011 + OP_LDRSB_REG_OFF, //01 0101 1100 + OP_LDRSB_REG_OFF, //01 0101 1101 + OP_LDRSB_REG_OFF, //01 0101 1110 + OP_LDRSB_REG_OFF, //01 0101 1111 + + OP_LDR_REG_OFF, //01 0110 0000 + OP_LDR_REG_OFF, //01 0110 0001 + OP_LDR_REG_OFF, //01 0110 0010 + OP_LDR_REG_OFF, //01 0110 0011 + OP_LDR_REG_OFF, //01 0110 0100 + OP_LDR_REG_OFF, //01 0110 0101 + OP_LDR_REG_OFF, //01 0110 0110 + OP_LDR_REG_OFF, //01 0110 0111 + OP_LDRH_REG_OFF, //01 0110 1000 + OP_LDRH_REG_OFF, //01 0110 1001 + OP_LDRH_REG_OFF, //01 0110 1010 + OP_LDRH_REG_OFF, //01 0110 1011 + OP_LDRH_REG_OFF, //01 0110 1100 + OP_LDRH_REG_OFF, //01 0110 1101 + OP_LDRH_REG_OFF, //01 0110 1110 + OP_LDRH_REG_OFF, //01 0110 1111 + + OP_LDRB_REG_OFF, //01 0111 0000 + OP_LDRB_REG_OFF, //01 0111 0001 + OP_LDRB_REG_OFF, //01 0111 0010 + OP_LDRB_REG_OFF, //01 0111 0011 + OP_LDRB_REG_OFF, //01 0111 0100 + OP_LDRB_REG_OFF, //01 0111 0101 + OP_LDRB_REG_OFF, //01 0111 0110 + OP_LDRB_REG_OFF, //01 0111 0111 + OP_LDRSH_REG_OFF, //01 0111 1000 + OP_LDRSH_REG_OFF, //01 0111 1001 + OP_LDRSH_REG_OFF, //01 0111 1010 + OP_LDRSH_REG_OFF, //01 0111 1011 + OP_LDRSH_REG_OFF, //01 0111 1100 + OP_LDRSH_REG_OFF, //01 0111 1101 + OP_LDRSH_REG_OFF, //01 0111 1110 + OP_LDRSH_REG_OFF, //01 0111 1111 + + OP_STR_IMM_OFF, //01 1000 0000 + OP_STR_IMM_OFF, //01 1000 0001 + OP_STR_IMM_OFF, //01 1000 0010 + OP_STR_IMM_OFF, //01 1000 0011 + OP_STR_IMM_OFF, //01 1000 0100 + OP_STR_IMM_OFF, //01 1000 0101 + OP_STR_IMM_OFF, //01 1000 0110 + OP_STR_IMM_OFF, //01 1000 0111 + OP_STR_IMM_OFF, //01 1000 1000 + OP_STR_IMM_OFF, //01 1000 1001 + OP_STR_IMM_OFF, //01 1000 1010 + OP_STR_IMM_OFF, //01 1000 1011 + OP_STR_IMM_OFF, //01 1000 1100 + OP_STR_IMM_OFF, //01 1000 1101 + OP_STR_IMM_OFF, //01 1000 1110 + OP_STR_IMM_OFF, //01 1000 1111 + + OP_STR_IMM_OFF, //01 1001 0000 + OP_STR_IMM_OFF, //01 1001 0001 + OP_STR_IMM_OFF, //01 1001 0010 + OP_STR_IMM_OFF, //01 1001 0011 + OP_STR_IMM_OFF, //01 1001 0100 + OP_STR_IMM_OFF, //01 1001 0101 + OP_STR_IMM_OFF, //01 1001 0110 + OP_STR_IMM_OFF, //01 1001 0111 + OP_STR_IMM_OFF, //01 1001 1000 + OP_STR_IMM_OFF, //01 1001 1001 + OP_STR_IMM_OFF, //01 1001 1010 + OP_STR_IMM_OFF, //01 1001 1011 + OP_STR_IMM_OFF, //01 1001 1100 + OP_STR_IMM_OFF, //01 1001 1101 + OP_STR_IMM_OFF, //01 1001 1110 + OP_STR_IMM_OFF, //01 1001 1111 + + OP_LDR_IMM_OFF, //01 1010 0000 + OP_LDR_IMM_OFF, //01 1010 0001 + OP_LDR_IMM_OFF, //01 1010 0010 + OP_LDR_IMM_OFF, //01 1010 0011 + OP_LDR_IMM_OFF, //01 1010 0100 + OP_LDR_IMM_OFF, //01 1010 0101 + OP_LDR_IMM_OFF, //01 1010 0110 + OP_LDR_IMM_OFF, //01 1010 0111 + OP_LDR_IMM_OFF, //01 1010 1000 + OP_LDR_IMM_OFF, //01 1010 1001 + OP_LDR_IMM_OFF, //01 1010 1010 + OP_LDR_IMM_OFF, //01 1010 1011 + OP_LDR_IMM_OFF, //01 1010 1100 + OP_LDR_IMM_OFF, //01 1010 1101 + OP_LDR_IMM_OFF, //01 1010 1110 + OP_LDR_IMM_OFF, //01 1010 1111 + + OP_LDR_IMM_OFF, //01 1011 0000 + OP_LDR_IMM_OFF, //01 1011 0001 + OP_LDR_IMM_OFF, //01 1011 0010 + OP_LDR_IMM_OFF, //01 1011 0011 + OP_LDR_IMM_OFF, //01 1011 0100 + OP_LDR_IMM_OFF, //01 1011 0101 + OP_LDR_IMM_OFF, //01 1011 0110 + OP_LDR_IMM_OFF, //01 1011 0111 + OP_LDR_IMM_OFF, //01 1011 1000 + OP_LDR_IMM_OFF, //01 1011 1001 + OP_LDR_IMM_OFF, //01 1011 1010 + OP_LDR_IMM_OFF, //01 1011 1011 + OP_LDR_IMM_OFF, //01 1011 1100 + OP_LDR_IMM_OFF, //01 1011 1101 + OP_LDR_IMM_OFF, //01 1011 1110 + OP_LDR_IMM_OFF, //01 1011 1111 + + OP_STRB_IMM_OFF, //01 1100 0000 + OP_STRB_IMM_OFF, //01 1100 0001 + OP_STRB_IMM_OFF, //01 1100 0010 + OP_STRB_IMM_OFF, //01 1100 0011 + OP_STRB_IMM_OFF, //01 1100 0100 + OP_STRB_IMM_OFF, //01 1100 0101 + OP_STRB_IMM_OFF, //01 1100 0110 + OP_STRB_IMM_OFF, //01 1100 0111 + OP_STRB_IMM_OFF, //01 1100 1000 + OP_STRB_IMM_OFF, //01 1100 1001 + OP_STRB_IMM_OFF, //01 1100 1010 + OP_STRB_IMM_OFF, //01 1100 1011 + OP_STRB_IMM_OFF, //01 1100 1100 + OP_STRB_IMM_OFF, //01 1100 1101 + OP_STRB_IMM_OFF, //01 1100 1110 + OP_STRB_IMM_OFF, //01 1100 1111 + + OP_STRB_IMM_OFF, //01 1101 0000 + OP_STRB_IMM_OFF, //01 1101 0001 + OP_STRB_IMM_OFF, //01 1101 0010 + OP_STRB_IMM_OFF, //01 1101 0011 + OP_STRB_IMM_OFF, //01 1101 0100 + OP_STRB_IMM_OFF, //01 1101 0101 + OP_STRB_IMM_OFF, //01 1101 0110 + OP_STRB_IMM_OFF, //01 1101 0111 + OP_STRB_IMM_OFF, //01 1101 1000 + OP_STRB_IMM_OFF, //01 1101 1001 + OP_STRB_IMM_OFF, //01 1101 1010 + OP_STRB_IMM_OFF, //01 1101 1011 + OP_STRB_IMM_OFF, //01 1101 1100 + OP_STRB_IMM_OFF, //01 1101 1101 + OP_STRB_IMM_OFF, //01 1101 1110 + OP_STRB_IMM_OFF, //01 1101 1111 + + OP_LDRB_IMM_OFF, //01 1110 0000 + OP_LDRB_IMM_OFF, //01 1110 0001 + OP_LDRB_IMM_OFF, //01 1110 0010 + OP_LDRB_IMM_OFF, //01 1110 0011 + OP_LDRB_IMM_OFF, //01 1110 0100 + OP_LDRB_IMM_OFF, //01 1110 0101 + OP_LDRB_IMM_OFF, //01 1110 0110 + OP_LDRB_IMM_OFF, //01 1110 0111 + OP_LDRB_IMM_OFF, //01 1110 1000 + OP_LDRB_IMM_OFF, //01 1110 1001 + OP_LDRB_IMM_OFF, //01 1110 1010 + OP_LDRB_IMM_OFF, //01 1110 1011 + OP_LDRB_IMM_OFF, //01 1110 1100 + OP_LDRB_IMM_OFF, //01 1110 1101 + OP_LDRB_IMM_OFF, //01 1110 1110 + OP_LDRB_IMM_OFF, //01 1110 1111 + + OP_LDRB_IMM_OFF, //01 1111 0000 + OP_LDRB_IMM_OFF, //01 1111 0001 + OP_LDRB_IMM_OFF, //01 1111 0010 + OP_LDRB_IMM_OFF, //01 1111 0011 + OP_LDRB_IMM_OFF, //01 1111 0100 + OP_LDRB_IMM_OFF, //01 1111 0101 + OP_LDRB_IMM_OFF, //01 1111 0110 + OP_LDRB_IMM_OFF, //01 1111 0111 + OP_LDRB_IMM_OFF, //01 1111 1000 + OP_LDRB_IMM_OFF, //01 1111 1001 + OP_LDRB_IMM_OFF, //01 1111 1010 + OP_LDRB_IMM_OFF, //01 1111 1011 + OP_LDRB_IMM_OFF, //01 1111 1100 + OP_LDRB_IMM_OFF, //01 1111 1101 + OP_LDRB_IMM_OFF, //01 1111 1110 + OP_LDRB_IMM_OFF, //01 1111 1111 + + OP_STRH_IMM_OFF, //10 0000 0000 + OP_STRH_IMM_OFF, //10 0000 0001 + OP_STRH_IMM_OFF, //10 0000 0010 + OP_STRH_IMM_OFF, //10 0000 0011 + OP_STRH_IMM_OFF, //10 0000 0100 + OP_STRH_IMM_OFF, //10 0000 0101 + OP_STRH_IMM_OFF, //10 0000 0110 + OP_STRH_IMM_OFF, //10 0000 0111 + OP_STRH_IMM_OFF, //10 0000 1000 + OP_STRH_IMM_OFF, //10 0000 1001 + OP_STRH_IMM_OFF, //10 0000 1010 + OP_STRH_IMM_OFF, //10 0000 1011 + OP_STRH_IMM_OFF, //10 0000 1100 + OP_STRH_IMM_OFF, //10 0000 1101 + OP_STRH_IMM_OFF, //10 0000 1110 + OP_STRH_IMM_OFF, //10 0000 1111 + + OP_STRH_IMM_OFF, //10 0001 0000 + OP_STRH_IMM_OFF, //10 0001 0001 + OP_STRH_IMM_OFF, //10 0001 0010 + OP_STRH_IMM_OFF, //10 0001 0011 + OP_STRH_IMM_OFF, //10 0001 0100 + OP_STRH_IMM_OFF, //10 0001 0101 + OP_STRH_IMM_OFF, //10 0001 0110 + OP_STRH_IMM_OFF, //10 0001 0111 + OP_STRH_IMM_OFF, //10 0001 1000 + OP_STRH_IMM_OFF, //10 0001 1001 + OP_STRH_IMM_OFF, //10 0001 1010 + OP_STRH_IMM_OFF, //10 0001 1011 + OP_STRH_IMM_OFF, //10 0001 1100 + OP_STRH_IMM_OFF, //10 0001 1101 + OP_STRH_IMM_OFF, //10 0001 1110 + OP_STRH_IMM_OFF, //10 0001 1111 + + OP_LDRH_IMM_OFF, //10 0010 0000 + OP_LDRH_IMM_OFF, //10 0010 0001 + OP_LDRH_IMM_OFF, //10 0010 0010 + OP_LDRH_IMM_OFF, //10 0010 0011 + OP_LDRH_IMM_OFF, //10 0010 0100 + OP_LDRH_IMM_OFF, //10 0010 0101 + OP_LDRH_IMM_OFF, //10 0010 0110 + OP_LDRH_IMM_OFF, //10 0010 0111 + OP_LDRH_IMM_OFF, //10 0010 1000 + OP_LDRH_IMM_OFF, //10 0010 1001 + OP_LDRH_IMM_OFF, //10 0010 1010 + OP_LDRH_IMM_OFF, //10 0010 1011 + OP_LDRH_IMM_OFF, //10 0010 1100 + OP_LDRH_IMM_OFF, //10 0010 1101 + OP_LDRH_IMM_OFF, //10 0010 1110 + OP_LDRH_IMM_OFF, //10 0010 1111 + + OP_LDRH_IMM_OFF, //10 0011 0000 + OP_LDRH_IMM_OFF, //10 0011 0001 + OP_LDRH_IMM_OFF, //10 0011 0010 + OP_LDRH_IMM_OFF, //10 0011 0011 + OP_LDRH_IMM_OFF, //10 0011 0100 + OP_LDRH_IMM_OFF, //10 0011 0101 + OP_LDRH_IMM_OFF, //10 0011 0110 + OP_LDRH_IMM_OFF, //10 0011 0111 + OP_LDRH_IMM_OFF, //10 0011 1000 + OP_LDRH_IMM_OFF, //10 0011 1001 + OP_LDRH_IMM_OFF, //10 0011 1010 + OP_LDRH_IMM_OFF, //10 0011 1011 + OP_LDRH_IMM_OFF, //10 0011 1100 + OP_LDRH_IMM_OFF, //10 0011 1101 + OP_LDRH_IMM_OFF, //10 0011 1110 + OP_LDRH_IMM_OFF, //10 0011 1111 + + OP_STR_SPREL, //10 0100 0000 + OP_STR_SPREL, //10 0100 0001 + OP_STR_SPREL, //10 0100 0010 + OP_STR_SPREL, //10 0100 0011 + OP_STR_SPREL, //10 0100 0100 + OP_STR_SPREL, //10 0100 0101 + OP_STR_SPREL, //10 0100 0110 + OP_STR_SPREL, //10 0100 0111 + OP_STR_SPREL, //10 0100 1000 + OP_STR_SPREL, //10 0100 1001 + OP_STR_SPREL, //10 0100 1010 + OP_STR_SPREL, //10 0100 1011 + OP_STR_SPREL, //10 0100 1100 + OP_STR_SPREL, //10 0100 1101 + OP_STR_SPREL, //10 0100 1110 + OP_STR_SPREL, //10 0100 1111 + + OP_STR_SPREL, //10 0101 0000 + OP_STR_SPREL, //10 0101 0001 + OP_STR_SPREL, //10 0101 0010 + OP_STR_SPREL, //10 0101 0011 + OP_STR_SPREL, //10 0101 0100 + OP_STR_SPREL, //10 0101 0101 + OP_STR_SPREL, //10 0101 0110 + OP_STR_SPREL, //10 0101 0111 + OP_STR_SPREL, //10 0101 1000 + OP_STR_SPREL, //10 0101 1001 + OP_STR_SPREL, //10 0101 1010 + OP_STR_SPREL, //10 0101 1011 + OP_STR_SPREL, //10 0101 1100 + OP_STR_SPREL, //10 0101 1101 + OP_STR_SPREL, //10 0101 1110 + OP_STR_SPREL, //10 0101 1111 + + OP_LDR_SPREL, //10 0110 0000 + OP_LDR_SPREL, //10 0110 0001 + OP_LDR_SPREL, //10 0110 0010 + OP_LDR_SPREL, //10 0110 0011 + OP_LDR_SPREL, //10 0110 0100 + OP_LDR_SPREL, //10 0110 0101 + OP_LDR_SPREL, //10 0110 0110 + OP_LDR_SPREL, //10 0110 0111 + OP_LDR_SPREL, //10 0110 1000 + OP_LDR_SPREL, //10 0110 1001 + OP_LDR_SPREL, //10 0110 1010 + OP_LDR_SPREL, //10 0110 1011 + OP_LDR_SPREL, //10 0110 1100 + OP_LDR_SPREL, //10 0110 1101 + OP_LDR_SPREL, //10 0110 1110 + OP_LDR_SPREL, //10 0110 1111 + + OP_LDR_SPREL, //10 0111 0000 + OP_LDR_SPREL, //10 0111 0001 + OP_LDR_SPREL, //10 0111 0010 + OP_LDR_SPREL, //10 0111 0011 + OP_LDR_SPREL, //10 0111 0100 + OP_LDR_SPREL, //10 0111 0101 + OP_LDR_SPREL, //10 0111 0110 + OP_LDR_SPREL, //10 0111 0111 + OP_LDR_SPREL, //10 0111 1000 + OP_LDR_SPREL, //10 0111 1001 + OP_LDR_SPREL, //10 0111 1010 + OP_LDR_SPREL, //10 0111 1011 + OP_LDR_SPREL, //10 0111 1100 + OP_LDR_SPREL, //10 0111 1101 + OP_LDR_SPREL, //10 0111 1110 + OP_LDR_SPREL, //10 0111 1111 + + OP_ADD_2PC, //10 1000 0000 + OP_ADD_2PC, //10 1000 0001 + OP_ADD_2PC, //10 1000 0010 + OP_ADD_2PC, //10 1000 0011 + OP_ADD_2PC, //10 1000 0100 + OP_ADD_2PC, //10 1000 0101 + OP_ADD_2PC, //10 1000 0110 + OP_ADD_2PC, //10 1000 0111 + OP_ADD_2PC, //10 1000 1000 + OP_ADD_2PC, //10 1000 1001 + OP_ADD_2PC, //10 1000 1010 + OP_ADD_2PC, //10 1000 1011 + OP_ADD_2PC, //10 1000 1100 + OP_ADD_2PC, //10 1000 1101 + OP_ADD_2PC, //10 1000 1110 + OP_ADD_2PC, //10 1000 1111 + + OP_ADD_2PC, //10 1001 0000 + OP_ADD_2PC, //10 1001 0001 + OP_ADD_2PC, //10 1001 0010 + OP_ADD_2PC, //10 1001 0011 + OP_ADD_2PC, //10 1001 0100 + OP_ADD_2PC, //10 1001 0101 + OP_ADD_2PC, //10 1001 0110 + OP_ADD_2PC, //10 1001 0111 + OP_ADD_2PC, //10 1001 1000 + OP_ADD_2PC, //10 1001 1001 + OP_ADD_2PC, //10 1001 1010 + OP_ADD_2PC, //10 1001 1011 + OP_ADD_2PC, //10 1001 1100 + OP_ADD_2PC, //10 1001 1101 + OP_ADD_2PC, //10 1001 1110 + OP_ADD_2PC, //10 1001 1111 + + OP_ADD_2SP, //10 1010 0000 + OP_ADD_2SP, //10 1010 0001 + OP_ADD_2SP, //10 1010 0010 + OP_ADD_2SP, //10 1010 0011 + OP_ADD_2SP, //10 1010 0100 + OP_ADD_2SP, //10 1010 0101 + OP_ADD_2SP, //10 1010 0110 + OP_ADD_2SP, //10 1010 0111 + OP_ADD_2SP, //10 1010 1000 + OP_ADD_2SP, //10 1010 1001 + OP_ADD_2SP, //10 1010 1010 + OP_ADD_2SP, //10 1010 1011 + OP_ADD_2SP, //10 1010 1100 + OP_ADD_2SP, //10 1010 1101 + OP_ADD_2SP, //10 1010 1110 + OP_ADD_2SP, //10 1010 1111 + + OP_ADD_2SP, //10 1011 0000 + OP_ADD_2SP, //10 1011 0001 + OP_ADD_2SP, //10 1011 0010 + OP_ADD_2SP, //10 1011 0011 + OP_ADD_2SP, //10 1011 0100 + OP_ADD_2SP, //10 1011 0101 + OP_ADD_2SP, //10 1011 0110 + OP_ADD_2SP, //10 1011 0111 + OP_ADD_2SP, //10 1011 1000 + OP_ADD_2SP, //10 1011 1001 + OP_ADD_2SP, //10 1011 1010 + OP_ADD_2SP, //10 1011 1011 + OP_ADD_2SP, //10 1011 1100 + OP_ADD_2SP, //10 1011 1101 + OP_ADD_2SP, //10 1011 1110 + OP_ADD_2SP, //10 1011 1111 + + OP_ADJUST_P_SP, //10 1100 0000 + OP_ADJUST_P_SP, //10 1100 0001 + OP_ADJUST_M_SP, //10 1100 0010 + OP_ADJUST_M_SP, //10 1100 0011 + OP_UND_THUMB, //10 1100 0100 + OP_UND_THUMB, //10 1100 0101 + OP_UND_THUMB, //10 1100 0110 + OP_UND_THUMB, //10 1100 0111 + OP_UND_THUMB, //10 1100 1000 + OP_UND_THUMB, //10 1100 1001 + OP_UND_THUMB, //10 1100 1010 + OP_UND_THUMB, //10 1100 1011 + OP_UND_THUMB, //10 1100 1100 + OP_UND_THUMB, //10 1100 1101 + OP_UND_THUMB, //10 1100 1110 + OP_UND_THUMB, //10 1100 1111 + + OP_PUSH, //10 1101 0000 + OP_PUSH, //10 1101 0001 + OP_PUSH, //10 1101 0010 + OP_PUSH, //10 1101 0011 + OP_PUSH_LR, //10 1101 0100 + OP_PUSH_LR, //10 1101 0101 + OP_PUSH_LR, //10 1101 0110 + OP_PUSH_LR, //10 1101 0111 + OP_UND_THUMB, //10 1101 1000 + OP_UND_THUMB, //10 1101 1001 + OP_UND_THUMB, //10 1101 1010 + OP_UND_THUMB, //10 1101 1011 + OP_UND_THUMB, //10 1101 1100 + OP_UND_THUMB, //10 1101 1101 + OP_UND_THUMB, //10 1101 1110 + OP_UND_THUMB, //10 1101 1111 + + OP_UND_THUMB, //10 1110 0000 + OP_UND_THUMB, //10 1110 0001 + OP_UND_THUMB, //10 1110 0010 + OP_UND_THUMB, //10 1110 0011 + OP_UND_THUMB, //10 1110 0100 + OP_UND_THUMB, //10 1110 0101 + OP_UND_THUMB, //10 1110 0110 + OP_UND_THUMB, //10 1110 0111 + OP_UND_THUMB, //10 1110 1000 + OP_UND_THUMB, //10 1110 1001 + OP_UND_THUMB, //10 1110 1010 + OP_UND_THUMB, //10 1110 1011 + OP_UND_THUMB, //10 1110 1100 + OP_UND_THUMB, //10 1110 1101 + OP_UND_THUMB, //10 1110 1110 + OP_UND_THUMB, //10 1110 1111 + + OP_POP, //10 1111 0000 + OP_POP, //10 1111 0001 + OP_POP, //10 1111 0010 + OP_POP, //10 1111 0011 + OP_POP_PC, //10 1111 0100 + OP_POP_PC, //10 1111 0101 + OP_POP_PC, //10 1111 0110 + OP_POP_PC, //10 1111 0111 + OP_BKPT_THUMB, //10 1111 1000 + OP_BKPT_THUMB, //10 1111 1001 + OP_BKPT_THUMB, //10 1111 1010 + OP_BKPT_THUMB, //10 1111 1011 + OP_UND_THUMB, //10 1111 1100 + OP_UND_THUMB, //10 1111 1101 + OP_UND_THUMB, //10 1111 1110 + OP_UND_THUMB, //10 1111 1111 + + OP_STMIA_THUMB, //11 0000 0000 + OP_STMIA_THUMB, //11 0000 0001 + OP_STMIA_THUMB, //11 0000 0010 + OP_STMIA_THUMB, //11 0000 0011 + OP_STMIA_THUMB, //11 0000 0100 + OP_STMIA_THUMB, //11 0000 0101 + OP_STMIA_THUMB, //11 0000 0110 + OP_STMIA_THUMB, //11 0000 0111 + OP_STMIA_THUMB, //11 0000 1000 + OP_STMIA_THUMB, //11 0000 1001 + OP_STMIA_THUMB, //11 0000 1010 + OP_STMIA_THUMB, //11 0000 1011 + OP_STMIA_THUMB, //11 0000 1100 + OP_STMIA_THUMB, //11 0000 1101 + OP_STMIA_THUMB, //11 0000 1110 + OP_STMIA_THUMB, //11 0000 1111 + + OP_STMIA_THUMB, //11 0001 0000 + OP_STMIA_THUMB, //11 0001 0001 + OP_STMIA_THUMB, //11 0001 0010 + OP_STMIA_THUMB, //11 0001 0011 + OP_STMIA_THUMB, //11 0001 0100 + OP_STMIA_THUMB, //11 0001 0101 + OP_STMIA_THUMB, //11 0001 0110 + OP_STMIA_THUMB, //11 0001 0111 + OP_STMIA_THUMB, //11 0001 1000 + OP_STMIA_THUMB, //11 0001 1001 + OP_STMIA_THUMB, //11 0001 1010 + OP_STMIA_THUMB, //11 0001 1011 + OP_STMIA_THUMB, //11 0001 1100 + OP_STMIA_THUMB, //11 0001 1101 + OP_STMIA_THUMB, //11 0001 1110 + OP_STMIA_THUMB, //11 0001 1111 + + OP_LDMIA_THUMB, //11 0010 0000 + OP_LDMIA_THUMB, //11 0010 0001 + OP_LDMIA_THUMB, //11 0010 0010 + OP_LDMIA_THUMB, //11 0010 0011 + OP_LDMIA_THUMB, //11 0010 0100 + OP_LDMIA_THUMB, //11 0010 0101 + OP_LDMIA_THUMB, //11 0010 0110 + OP_LDMIA_THUMB, //11 0010 0111 + OP_LDMIA_THUMB, //11 0010 1000 + OP_LDMIA_THUMB, //11 0010 1001 + OP_LDMIA_THUMB, //11 0010 1010 + OP_LDMIA_THUMB, //11 0010 1011 + OP_LDMIA_THUMB, //11 0010 1100 + OP_LDMIA_THUMB, //11 0010 1101 + OP_LDMIA_THUMB, //11 0010 1110 + OP_LDMIA_THUMB, //11 0010 1111 + + OP_LDMIA_THUMB, //11 0011 0000 + OP_LDMIA_THUMB, //11 0011 0001 + OP_LDMIA_THUMB, //11 0011 0010 + OP_LDMIA_THUMB, //11 0011 0011 + OP_LDMIA_THUMB, //11 0011 0100 + OP_LDMIA_THUMB, //11 0011 0101 + OP_LDMIA_THUMB, //11 0011 0110 + OP_LDMIA_THUMB, //11 0011 0111 + OP_LDMIA_THUMB, //11 0011 1000 + OP_LDMIA_THUMB, //11 0011 1001 + OP_LDMIA_THUMB, //11 0011 1010 + OP_LDMIA_THUMB, //11 0011 1011 + OP_LDMIA_THUMB, //11 0011 1100 + OP_LDMIA_THUMB, //11 0011 1101 + OP_LDMIA_THUMB, //11 0011 1110 + OP_LDMIA_THUMB, //11 0011 1111 + + OP_B_COND, //11 0100 0000 + OP_B_COND, //11 0100 0001 + OP_B_COND, //11 0100 0010 + OP_B_COND, //11 0100 0011 + OP_B_COND, //11 0100 0100 + OP_B_COND, //11 0100 0101 + OP_B_COND, //11 0100 0110 + OP_B_COND, //11 0100 0111 + OP_B_COND, //11 0100 1000 + OP_B_COND, //11 0100 1001 + OP_B_COND, //11 0100 1010 + OP_B_COND, //11 0100 1011 + OP_B_COND, //11 0100 1100 + OP_B_COND, //11 0100 1101 + OP_B_COND, //11 0100 1110 + OP_B_COND, //11 0100 1111 + + OP_B_COND, //11 0101 0000 + OP_B_COND, //11 0101 0001 + OP_B_COND, //11 0101 0010 + OP_B_COND, //11 0101 0011 + OP_B_COND, //11 0101 0100 + OP_B_COND, //11 0101 0101 + OP_B_COND, //11 0101 0110 + OP_B_COND, //11 0101 0111 + OP_B_COND, //11 0101 1000 + OP_B_COND, //11 0101 1001 + OP_B_COND, //11 0101 1010 + OP_B_COND, //11 0101 1011 + OP_B_COND, //11 0101 1100 + OP_B_COND, //11 0101 1101 + OP_B_COND, //11 0101 1110 + OP_B_COND, //11 0101 1111 + + OP_B_COND, //11 0110 0000 + OP_B_COND, //11 0110 0001 + OP_B_COND, //11 0110 0010 + OP_B_COND, //11 0110 0011 + OP_B_COND, //11 0110 0100 + OP_B_COND, //11 0110 0101 + OP_B_COND, //11 0110 0110 + OP_B_COND, //11 0110 0111 + OP_B_COND, //11 0110 1000 + OP_B_COND, //11 0110 1001 + OP_B_COND, //11 0110 1010 + OP_B_COND, //11 0110 1011 + OP_B_COND, //11 0110 1100 + OP_B_COND, //11 0110 1101 + OP_B_COND, //11 0110 1110 + OP_B_COND, //11 0110 1111 + + OP_B_COND, //11 0111 0000 + OP_B_COND, //11 0111 0001 + OP_B_COND, //11 0111 0010 + OP_B_COND, //11 0111 0011 + OP_B_COND, //11 0111 0100 + OP_B_COND, //11 0111 0101 + OP_B_COND, //11 0111 0110 + OP_B_COND, //11 0111 0111 + OP_B_COND, //11 0111 1000 + OP_B_COND, //11 0111 1001 + OP_B_COND, //11 0111 1010 + OP_B_COND, //11 0111 1011 + OP_SWI_THUMB, //11 0111 1100 + OP_SWI_THUMB, //11 0111 1101 + OP_SWI_THUMB, //11 0111 1110 + OP_SWI_THUMB, //11 0111 1111 + + OP_B_UNCOND, //11 1000 0000 + OP_B_UNCOND, //11 1000 0001 + OP_B_UNCOND, //11 1000 0010 + OP_B_UNCOND, //11 1000 0011 + OP_B_UNCOND, //11 1000 0100 + OP_B_UNCOND, //11 1000 0101 + OP_B_UNCOND, //11 1000 0110 + OP_B_UNCOND, //11 1000 0111 + OP_B_UNCOND, //11 1000 1000 + OP_B_UNCOND, //11 1000 1001 + OP_B_UNCOND, //11 1000 1010 + OP_B_UNCOND, //11 1000 1011 + OP_B_UNCOND, //11 1000 1100 + OP_B_UNCOND, //11 1000 1101 + OP_B_UNCOND, //11 1000 1110 + OP_B_UNCOND, //11 1000 1111 + + OP_B_UNCOND, //11 1001 0000 + OP_B_UNCOND, //11 1001 0001 + OP_B_UNCOND, //11 1001 0010 + OP_B_UNCOND, //11 1001 0011 + OP_B_UNCOND, //11 1001 0100 + OP_B_UNCOND, //11 1001 0101 + OP_B_UNCOND, //11 1001 0110 + OP_B_UNCOND, //11 1001 0111 + OP_B_UNCOND, //11 1001 1000 + OP_B_UNCOND, //11 1001 1001 + OP_B_UNCOND, //11 1001 1010 + OP_B_UNCOND, //11 1001 1011 + OP_B_UNCOND, //11 1001 1100 + OP_B_UNCOND, //11 1001 1101 + OP_B_UNCOND, //11 1001 1110 + OP_B_UNCOND, //11 1001 1111 + + OP_BLX, //11 1010 0000 + OP_BLX, //11 1010 0001 + OP_BLX, //11 1010 0010 + OP_BLX, //11 1010 0011 + OP_BLX, //11 1010 0100 + OP_BLX, //11 1010 0101 + OP_BLX, //11 1010 0110 + OP_BLX, //11 1010 0111 + OP_BLX, //11 1010 1000 + OP_BLX, //11 1010 1001 + OP_BLX, //11 1010 1010 + OP_BLX, //11 1010 1011 + OP_BLX, //11 1010 1100 + OP_BLX, //11 1010 1101 + OP_BLX, //11 1010 1110 + OP_BLX, //11 1010 1111 + + OP_BLX, //11 1011 0000 + OP_BLX, //11 1011 0001 + OP_BLX, //11 1011 0010 + OP_BLX, //11 1011 0011 + OP_BLX, //11 1011 0100 + OP_BLX, //11 1011 0101 + OP_BLX, //11 1011 0110 + OP_BLX, //11 1011 0111 + OP_BLX, //11 1011 1000 + OP_BLX, //11 1011 1001 + OP_BLX, //11 1011 1010 + OP_BLX, //11 1011 1011 + OP_BLX, //11 1011 1100 + OP_BLX, //11 1011 1101 + OP_BLX, //11 1011 1110 + OP_BLX, //11 1011 1111 + + OP_BL_10, //11 1100 0000 + OP_BL_10, //11 1100 0001 + OP_BL_10, //11 1100 0010 + OP_BL_10, //11 1100 0011 + OP_BL_10, //11 1100 0100 + OP_BL_10, //11 1100 0101 + OP_BL_10, //11 1100 0110 + OP_BL_10, //11 1100 0111 + OP_BL_10, //11 1100 1000 + OP_BL_10, //11 1100 1001 + OP_BL_10, //11 1100 1010 + OP_BL_10, //11 1100 1011 + OP_BL_10, //11 1100 1100 + OP_BL_10, //11 1100 1101 + OP_BL_10, //11 1100 1110 + OP_BL_10, //11 1100 1111 + + OP_BL_10, //11 1101 0000 + OP_BL_10, //11 1101 0001 + OP_BL_10, //11 1101 0010 + OP_BL_10, //11 1101 0011 + OP_BL_10, //11 1101 0100 + OP_BL_10, //11 1101 0101 + OP_BL_10, //11 1101 0110 + OP_BL_10, //11 1101 0111 + OP_BL_10, //11 1101 1000 + OP_BL_10, //11 1101 1001 + OP_BL_10, //11 1101 1010 + OP_BL_10, //11 1101 1011 + OP_BL_10, //11 1101 1100 + OP_BL_10, //11 1101 1101 + OP_BL_10, //11 1101 1110 + OP_BL_10, //11 1101 1111 + + OP_BL_THUMB, //11 1110 0000 + OP_BL_THUMB, //11 1110 0001 + OP_BL_THUMB, //11 1110 0010 + OP_BL_THUMB, //11 1110 0011 + OP_BL_THUMB, //11 1110 0100 + OP_BL_THUMB, //11 1110 0101 + OP_BL_THUMB, //11 1110 0110 + OP_BL_THUMB, //11 1110 0111 + OP_BL_THUMB, //11 1110 1000 + OP_BL_THUMB, //11 1110 1001 + OP_BL_THUMB, //11 1110 1010 + OP_BL_THUMB, //11 1110 1011 + OP_BL_THUMB, //11 1110 1100 + OP_BL_THUMB, //11 1110 1101 + OP_BL_THUMB, //11 1110 1110 + OP_BL_THUMB, //11 1110 1111 + + OP_BL_THUMB, //11 1111 0000 + OP_BL_THUMB, //11 1111 0001 + OP_BL_THUMB, //11 1111 0010 + OP_BL_THUMB, //11 1111 0011 + OP_BL_THUMB, //11 1111 0100 + OP_BL_THUMB, //11 1111 0101 + OP_BL_THUMB, //11 1111 0110 + OP_BL_THUMB, //11 1111 0111 + OP_BL_THUMB, //11 1111 1000 + OP_BL_THUMB, //11 1111 1001 + OP_BL_THUMB, //11 1111 1010 + OP_BL_THUMB, //11 1111 1011 + OP_BL_THUMB, //11 1111 1100 + OP_BL_THUMB, //11 1111 1101 + OP_BL_THUMB, //11 1111 1110 + OP_BL_THUMB, //11 1111 1111 +}; //1089 + diff -r fe2ba1a712cd -r 70b0973e7b70 src/xsf/desmume/types.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/xsf/desmume/types.h Thu Oct 16 14:45:41 2008 -0500 @@ -0,0 +1,171 @@ +/* Copyright (C) 2005 Guillaume Duhamel + + This file is part of DeSmuME + + DeSmuME is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DeSmuME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DeSmuME; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef TYPES_HPP +#define TYPES_HPP + +#ifndef FASTCALL +#ifdef __MINGW32__ +#define FASTCALL __attribute__((fastcall)) +#elif defined (__i386__) +#define FASTCALL __attribute__((regparm(3))) +#else +#define FASTCALL +#endif +#endif + +#ifndef INLINE +#ifdef _MSC_VER +#define INLINE _inline +#else +#define INLINE inline +#endif +#endif + +#ifdef DESMUME_COCOA +#ifdef __BIG_ENDIAN__ +#define WORDS_BIGENDIAN +#endif +#endif + +#if defined(__LP64__) +typedef unsigned char u8; +typedef unsigned short u16; +typedef unsigned int u32; +typedef unsigned long u64; +typedef unsigned long pointer; + +typedef signed char s8; +typedef signed short s16; +typedef signed int s32; +typedef signed long s64; +#else +typedef unsigned char u8; +typedef unsigned short u16; +typedef unsigned long u32; +#ifdef _MSC_VER +typedef unsigned __int64 u64; +#else +typedef unsigned long long u64; +#endif +typedef unsigned long pointer; + +typedef signed char s8; +typedef signed short s16; +typedef signed long s32; +#ifdef _MSC_VER +typedef __int64 s64; +#else +typedef signed long long s64; +#endif +#endif + +typedef u8 uint8; +typedef u16 uint16; + +#ifndef OBJ_C +typedef u32 uint32; +#else +#define uint32 u32 //uint32 is defined in Leopard somewhere, avoid conflicts +#endif + +/*---------- GPU3D fixed-points types -----------*/ + +typedef s32 f32; +#define inttof32(n) ((n) << 12) +#define f32toint(n) ((n) >> 12) +#define floattof32(n) ((int32)((n) * (1 << 12))) +#define f32tofloat(n) (((float)(n)) / (float)(1<<12)) + +typedef s16 t16; +#define f32tot16(n) ((t16)(n >> 8)) +#define inttot16(n) ((n) << 4) +#define t16toint(n) ((n) >> 4) +#define floattot16(n) ((t16)((n) * (1 << 4))) +#define t16ofloat(n) (((float)(n)) / (float)(1<<4)) + +typedef s16 v16; +#define inttov16(n) ((n) << 12) +#define f32tov16(n) (n) +#define floattov16(n) ((v16)((n) * (1 << 12))) +#define v16toint(n) ((n) >> 12) +#define v16tofloat(n) (((float)(n)) / (float)(1<<12)) + +typedef s16 v10; +#define inttov10(n) ((n) << 9) +#define f32tov10(n) ((v10)(n >> 3)) +#define v10toint(n) ((n) >> 9) +#define floattov10(n) ((v10)((n) * (1 << 9))) +#define v10tofloat(n) (((float)(n)) / (float)(1<<9)) + +/*----------------------*/ + +#ifndef OBJ_C +typedef int BOOL; +#else +//apple also defines BOOL +typedef int desmume_BOOL; +#define BOOL desmume_BOOL +#endif + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifdef __GNUC__ +#define PACKED __attribute__((packed)) +#endif + +#ifdef WORDS_BIGENDIAN +# define LOCAL_BE +#else +# define LOCAL_LE +#endif + +/* little endian (ds' endianess) to local endianess convert macros */ +#ifdef LOCAL_BE /* local arch is big endian */ +# define LE_TO_LOCAL_16(x) ((((x)&0xff)<<8)|(((x)>>8)&0xff)) +# define LE_TO_LOCAL_32(x) ((((x)&0xff)<<24)|(((x)&0xff00)<<8)|(((x)>>8)&0xff00)|(((x)>>24)&0xff)) +# define LOCAL_TO_LE_16(x) ((((x)&0xff)<<8)|(((x)>>8)&0xff)) +# define LOCAL_TO_LE_32(x) ((((x)&0xff)<<24)|(((x)&0xff00)<<8)|(((x)>>8)&0xff00)|(((x)>>24)&0xff)) +#else /* local arch is little endian */ +# define LE_TO_LOCAL_16(x) (x) +# define LE_TO_LOCAL_32(x) (x) +# define LOCAL_TO_LE_16(x) (x) +# define LOCAL_TO_LE_32(x) (x) +#endif + +/* kilobytes and megabytes macro */ +#define MB(x) ((x)*1024*1024) +#define KB(x) ((x)*1024) + +#define CPU_STR(c) ((c==ARM9)?"ARM9":"ARM7") +typedef enum +{ + ARM9 = 0, + ARM7 = 1 +} cpu_id_t; + +#define __PACKED __attribute__((__packed__)) + +#endif diff -r fe2ba1a712cd -r 70b0973e7b70 src/xsf/main.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/xsf/main.c Thu Oct 16 14:45:41 2008 -0500 @@ -0,0 +1,227 @@ +/* + Linux 2SF player - main program + +*/ + +#include +#include +#include +#include +#include +#include +#include + +#include "ao.h" +#include "corlett.h" +#include "vio2sf/vio2sf.h" + +static uint8 *buffer; // buffer containing 2sf file +static uint32 size; // size of buffer +static corlett_t *c = NULL; + +char *xsf_tagget(const char *tag, const char *pData, int dwSize); + +/* ao_get_lib: called to load secondary files */ +int xsf_get_lib(char *filename, void **buffer, unsigned int *length) +{ + uint8 *filebuf; + uint32 size; + FILE *auxfile; + + auxfile = fopen(filename, "rb"); + if (!auxfile) + { + printf("Unable to find auxiliary file %s\n", filename); + return AO_FAIL; + } + + fseek(auxfile, 0, SEEK_END); + size = ftell(auxfile); + fseek(auxfile, 0, SEEK_SET); + + filebuf = malloc(size); + + if (!filebuf) + { + fclose(auxfile); + printf("ERROR: could not allocate %d bytes of memory\n", size); + return AO_FAIL; + } + + fread(filebuf, size, 1, auxfile); + fclose(auxfile); + + *buffer = filebuf; + *length = (uint64)size; + + return AO_SUCCESS; +} + +static void do_frame(uint32 size, int16 *buffer) +{ + xsf_gen(buffer, size); +} + +// load and set up a 2sf file +int load_file(char *name) +{ + FILE *file; + uint32 filesig; + uint8 *filedata; + uint64 file_len; + + file = fopen(name, "rb"); + + if (!file) + { + printf("ERROR: could not open file %s\n", name); + return -1; + } + + // get the length of the file by seeking to the end then reading the current position + fseek(file, 0, SEEK_END); + size = ftell(file); + // reset the pointer + fseek(file, 0, SEEK_SET); + + buffer = malloc(size); + + if (!buffer) + { + fclose(file); + printf("ERROR: could not allocate %d bytes of memory\n", size); + return -1; + } + + // read the file + fread(buffer, size, 1, file); + fclose(file); + + // init our *SF engine so we can get tags + if (corlett_decode(buffer, size, &filedata, &file_len, &c) != AO_SUCCESS) + { + printf("Unable to process tags\n"); + return -1; + } + free(filedata); // we don't use this + + if (xsf_start(buffer, size) != XSF_TRUE) + { + printf("ERROR: vio2sf rejected the file!\n"); + return -1; + } + + m1sdr_Init(44100); + m1sdr_SetCallback(do_frame); + m1sdr_PlayStart(); + + if ((c != NULL) && (c->inf_title != NULL)) + { + printf("Playing \"%s\" by %s from %s. Copyright %s %s.\n", c->inf_title, c->inf_artist, c->inf_game, c->inf_copy, c->inf_year); + } + else + { + printf("Playing %s\n", name); + } + + return 0; +} + +int main(int argv, char *argc[]) +{ + struct termios tp; + struct timeval tv; + int fds; + fd_set watchset; + char ch = 0; + int song; + + printf("VIO2SF Linux player version 1.1\n\n"); + + // check if an argument was given + if (argv < 2) + { + printf("Error: must specify a filename or names!\n"); + return -1; + } + + printf("Press ESC or Q to stop. / = previous song, * = next song\n\n", argc[1]); + + if (load_file(argc[1]) < 0) + { + return -1; + } + + tcgetattr(STDIN_FILENO, &tp); + tp.c_lflag &= ~ICANON; + tp.c_lflag &= ~(ECHO | ECHOCTL | ECHONL); + tcsetattr(STDIN_FILENO, TCSANOW, &tp); + + ch = 0; + song = 1; + while ((ch != 27) && (ch != 'q') && (ch != 'Q')) + { + fds = STDIN_FILENO; + FD_ZERO(&watchset); + FD_SET(fds, &watchset); + tv.tv_sec = 0; + tv.tv_usec = 16666/2; // timeout every 1/120th of a second + if (select(fds+1, &watchset, NULL, NULL, &tv)) + { + ch = getchar(); // (blocks until something is pressed) + } + else + { + ch = 0; + } + + m1sdr_TimeCheck(); + + if ((ch == '*') && ((song+1) < argv)) + { + xsf_term(); + m1sdr_Exit(); + if (c) + { + free(c); + c = NULL; + } + free(buffer); + song++; + + if (load_file(argc[song]) < 0) + { + ch = 27; + } + } + + if ((ch == '/') && (song > 1)) + { + xsf_term(); + m1sdr_Exit(); + if (c) + { + free(c); + c = NULL; + } + free(buffer); + song--; + + if (load_file(argc[song]) < 0) + { + ch = 27; + } + } + } + + xsf_term(); + + tcgetattr(STDIN_FILENO, &tp); + tp.c_lflag |= ICANON; + tp.c_lflag |= (ECHO | ECHOCTL | ECHONL); + tcsetattr(STDIN_FILENO, TCSANOW, &tp); + + free(buffer); + + return 1; +} diff -r fe2ba1a712cd -r 70b0973e7b70 src/xsf/plugin.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/xsf/plugin.c Thu Oct 16 14:45:41 2008 -0500 @@ -0,0 +1,275 @@ +/* + Audio Overload SDK - main driver. for demonstration only, not user friendly! + + Copyright (c) 2007-2008 R. Belmont and Richard Bannister. + + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + * Neither the names of R. Belmont and Richard Bannister nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include +#include +#include + +#include + +#include "ao.h" +#include "corlett.h" +#include "vio2sf.h" + +/* xsf_get_lib: called to load secondary files */ +static gchar *path; +int xsf_get_lib(char *filename, void **buffer, unsigned int *length) +{ + guchar *filebuf; + gsize size; + char buf[PATH_MAX]; + + snprintf(buf, PATH_MAX, "%s/%s", dirname(path), filename); + + aud_vfs_file_get_contents(buf, (gchar **) &filebuf, &size); + + *buffer = filebuf; + *length = (uint64)size; + + return AO_SUCCESS; +} + +static gint seek = 0; +Tuple *xsf_tuple(gchar *filename) +{ + Tuple *t; + corlett_t *c; + guchar *buf; + gsize sz; + + aud_vfs_file_get_contents(filename, (gchar **) &buf, &sz); + + if (!buf) + return NULL; + + if (corlett_decode(buf, sz, NULL, NULL, &c) != AO_SUCCESS) + return NULL; + + t = aud_tuple_new_from_filename(filename); + + aud_tuple_associate_int(t, FIELD_LENGTH, NULL, c->inf_length ? psfTimeToMS(c->inf_length) + psfTimeToMS(c->inf_fade) : -1); + aud_tuple_associate_string(t, FIELD_ARTIST, NULL, c->inf_artist); + aud_tuple_associate_string(t, FIELD_ALBUM, NULL, c->inf_game); + aud_tuple_associate_string(t, -1, "game", c->inf_game); + aud_tuple_associate_string(t, FIELD_TITLE, NULL, c->inf_title); + aud_tuple_associate_string(t, FIELD_COPYRIGHT, NULL, c->inf_copy); + aud_tuple_associate_string(t, FIELD_QUALITY, NULL, "sequenced"); + aud_tuple_associate_string(t, FIELD_CODEC, NULL, "Nintendo DS Audio"); + aud_tuple_associate_string(t, -1, "console", "Nintendo DS"); + + free(c); + g_free(buf); + + return t; +} + +gchar *xsf_title(gchar *filename, gint *length) +{ + gchar *title = NULL; + Tuple *tuple = xsf_tuple(filename); + + if (tuple != NULL) + { + title = aud_tuple_formatter_make_title_string(tuple, aud_get_gentitle_format()); + *length = aud_tuple_get_int(tuple, FIELD_LENGTH, NULL); + aud_tuple_free(tuple); + } + else + { + title = g_path_get_basename(filename); + *length = -1; + } + + return title; +} + +void xsf_update(unsigned char *buffer, long count, InputPlayback *playback); + +void xsf_play(InputPlayback *data) +{ + guchar *buffer; + gsize size; + gint length; + gchar *title = xsf_title(data->filename, &length); + gint16 samples[44100*2]; + gint seglen = 44100 / 60; + + path = g_strdup(data->filename); + aud_vfs_file_get_contents(data->filename, (gchar **) &buffer, &size); + + if (xsf_start(buffer, size) != AO_SUCCESS) + { + free(buffer); + return; + } + + data->output->open_audio(FMT_S16_NE, 44100, 2); + + data->set_params(data, title, length, 44100*2*2*8, 44100, 2); + + data->playing = TRUE; + data->set_pb_ready(data); + + for (;;) + { + while (data->playing && !seek) + { + xsf_gen(samples, seglen); + xsf_update(samples, seglen * 4, data); + + if (data->output->written_time() > length) + data->eof = TRUE; + } + + if (seek) + { + data->eof = FALSE; + data->output->flush(seek); + + xsf_term(); + + if (xsf_start(buffer, size) == AO_SUCCESS) + { + //xsf_seek(seek); + seek = 0; + continue; + } + else + { + data->output->close_audio(); + break; + } + } + + xsf_term(); + + data->output->buffer_free(); + data->output->buffer_free(); + + while (data->eof && data->output->buffer_playing()) + g_usleep(10000); + + data->output->close_audio(); + + break; + } + + g_free(buffer); + g_free(path); + g_free(title); + + data->playing = FALSE; +} + +void xsf_update(unsigned char *buffer, long count, InputPlayback *playback) +{ + const int mask = ~((((16 / 8) * 2)) - 1); + + if (buffer == NULL) + { + playback->playing = FALSE; + playback->eof = TRUE; + + return; + } + + while (count > 0) + { + int t = playback->output->buffer_free() & mask; + if (t > count) + playback->pass_audio(playback, FMT_S16_NE, 2, count, buffer, NULL); + else + { + if (t) + playback->pass_audio(playback, FMT_S16_NE, 2, t, buffer, NULL); + + g_usleep((count-t)*1000*5/441/2); + } + count -= t; + buffer += t; + } + +#if 0 + if (seek) + { + if (xsf_seek(seek)) + { + playback->output->flush(seek); + seek = 0; + } + else + { + playback->eof = TRUE; + return; + } + } +#endif +} + +void xsf_Stop(InputPlayback *playback) +{ + playback->playing = FALSE; +} + +void xsf_pause(InputPlayback *playback, short p) +{ + playback->output->pause(p); +} + +int xsf_is_our_fd(gchar *filename, VFSFile *file) +{ + gchar magic[4]; + aud_vfs_fread(magic, 1, 4, file); + + if (!memcmp(magic, "PSF$", 4)) + return 1; + + return 0; +} + +void xsf_Seek(InputPlayback *playback, int time) +{ + seek = time * 1000; +} + +gchar *xsf_fmts[] = { "2sf", "mini2sf", NULL }; + +InputPlugin xsf_ip = +{ + .description = "2SF Audio Plugin", + .play_file = xsf_play, + .stop = xsf_Stop, + .pause = xsf_pause, + .seek = xsf_Seek, + .get_song_tuple = xsf_tuple, + .is_our_file_from_vfs = xsf_is_our_fd, + .vfs_extensions = xsf_fmts, +}; + +InputPlugin *xsf_iplist[] = { &xsf_ip, NULL }; + +DECLARE_PLUGIN(psf2, NULL, NULL, xsf_iplist, NULL, NULL, NULL, NULL, NULL); + diff -r fe2ba1a712cd -r 70b0973e7b70 src/xsf/tagget.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/xsf/tagget.h Thu Oct 16 14:45:41 2008 -0500 @@ -0,0 +1,205 @@ +static int getdwordle(unsigned char *pData) +{ + return pData[0] | ((pData[1]) << 8) | ((pData[2]) << 16) | ((pData[3]) << 24); +} + +static int xsf_tagsearchraw(const char *pData, int dwSize) +{ + int dwPos; + int dwReservedAreaSize; + int dwProgramLength; + int dwProgramCRC; + if (dwSize < 16 + 5 + 1) return 0; + if (pData[0] != 'P') return 0; + if (pData[1] != 'S') return 0; + if (pData[2] != 'F') return 0; + dwReservedAreaSize = getdwordle(pData + 4); + dwProgramLength = getdwordle(pData + 8); + dwProgramCRC = getdwordle(pData + 12); + dwPos = 16 + dwReservedAreaSize + dwProgramLength; + if (dwPos >= dwSize) return 0; + return dwPos; +} +static int xsf_tagsearch(int *pdwRet, const char *pData, int dwSize) +{ + int dwPos = xsf_tagsearchraw(pData, dwSize); + if (dwSize < dwPos + 5) return 0; + if (memcmp(pData + dwPos, "[TAG]", 5)) return 0; + *pdwRet = dwPos + 5; + return 1; +} + +enum xsf_tagenum_callback_returnvalue +{ + xsf_tagenum_callback_returnvaluecontinue = 0, + xsf_tagenum_callback_returnvaluebreak = 1 +}; +typedef int (*pfnxsf_tagenum_callback_t)(void *pWork, const char *pNameTop, const char *pNameEnd, const char *pValueTop, const char *pValueEnd); +static int xsf_tagenumraw(pfnxsf_tagenum_callback_t pCallBack, void *pWork, const char *pData, int dwSize) +{ + int dwPos = 0; + while (dwPos < dwSize) + { + int dwNameTop; + int dwNameEnd; + int dwValueTop; + int dwValueEnd; + if (dwPos < dwSize && pData[dwPos] == 0x0a) dwPos++; + while (dwPos < dwSize && pData[dwPos] != 0x0a && 0x01 <= pData[dwPos] && pData[dwPos] <= 0x20) + dwPos++; + if (dwPos >= dwSize || pData[dwPos] == 0x0a) continue; + dwNameTop = dwPos; + while (dwPos < dwSize && pData[dwPos] != 0x0a && pData[dwPos] != '=') + dwPos++; + if (dwPos >= dwSize || pData[dwPos] == 0x0a) continue; + dwNameEnd = dwPos; + while (dwNameTop < dwNameEnd && 0x01 <= pData[dwNameEnd - 1] && pData[dwNameEnd - 1] <= 0x20) + dwNameEnd--; + if (dwPos < dwSize && pData[dwPos] == '=') dwPos++; + while (dwPos < dwSize && pData[dwPos] != 0x0a && 0x01 <= pData[dwPos] && pData[dwPos] <= 0x20) + dwPos++; + dwValueTop = dwPos; + while (dwPos < dwSize && pData[dwPos] != 0x0a) + dwPos++; + dwValueEnd = dwPos; + while (dwValueTop < dwValueEnd && 0x01 <= pData[dwValueEnd - 1] && pData[dwValueEnd - 1] <= 0x20) + dwValueEnd--; + + if (pCallBack) + { + if (xsf_tagenum_callback_returnvaluecontinue != pCallBack(pWork, (const char *)pData + dwNameTop, (const char *)pData + dwNameEnd, (const char *)pData + dwValueTop, (const char *)pData + dwValueEnd)) + return -1; + } + } + return 1; +} + +static int xsf_tagenum(pfnxsf_tagenum_callback_t pCallBack, void *pWork, const char *pData, int dwSize) +{ + int dwPos = 0; + if (!xsf_tagsearch(&dwPos, pData, dwSize)) + return 0; + return xsf_tagenumraw(pCallBack, pWork, pData + dwPos, dwSize - dwPos); +} + +typedef struct +{ + int taglen; + const char *tag; + char *ret; +} xsf_tagget_work_t; + +static int xsf_tagenum_callback_tagget(void *pWork, const char *pNameTop, const char *pNameEnd, const char *pValueTop, const char *pValueEnd) +{ + xsf_tagget_work_t *pwork = (xsf_tagget_work_t *)pWork; + if (pwork->taglen == pNameEnd - pNameTop && !strncasecmp(pNameTop, pwork->tag, pwork->taglen)) + { + char *ret = (char *)malloc(pValueEnd - pValueTop + 1); + if (!ret) return xsf_tagenum_callback_returnvaluecontinue; + memcpy(ret, pValueTop, pValueEnd - pValueTop); + ret[pValueEnd - pValueTop] = 0; + pwork->ret = ret; + return xsf_tagenum_callback_returnvaluebreak; + } + return xsf_tagenum_callback_returnvaluecontinue; +} + +static char *xsf_taggetraw(const char *tag, const char *pData, int dwSize) +{ + xsf_tagget_work_t work; + work.ret = 0; + work.tag = tag; + work.taglen = (int)strlen(tag); + xsf_tagenumraw(xsf_tagenum_callback_tagget, &work, pData, dwSize); + return work.ret; +} + +static char *xsf_tagget(const char *tag, const char *pData, int dwSize) +{ + xsf_tagget_work_t work; + work.ret = 0; + work.tag = tag; + work.taglen = (int)strlen(tag); + xsf_tagenum(xsf_tagenum_callback_tagget, &work, pData, dwSize); + return work.ret; +} + +static int xsf_tagget_exist(const char *tag, const char *pData, int dwSize) +{ + int exists; + char *value = xsf_tagget(tag, pData, dwSize); + if (value) + { + exists = 1; + free(value); + } + else + { + exists = 0; + } + return exists; +} + +static int xsf_tagget_int(const char *tag, const char *pData, int dwSize, int value_default) +{ + int ret = value_default; + char *value = xsf_tagget(tag, pData, dwSize); + if (value) + { + if (*value) ret = atoi(value); + free(value); + } + return ret; +} + +static double xsf_tagget_float(const char *tag, const char *pData, int dwSize, double value_default) +{ + double ret = value_default; + char *value = xsf_tagget(tag, pData, dwSize); + if (value) + { + if (*value) ret = atof(value); + free(value); + } + return ret; +} + +static int tag2ms(const char *p) +{ + int f = 0; + int b = 0; + int r = 0; + for (;*p; p++) + { + if (*p >= '0' && *p <= '9') + { + if (f < 1000) + { + r = r * 10 + *p - '0'; + if (f) f *= 10; + continue; + } + break; + } + if (*p == '.') + { + f = 1; + continue; + } + if (*p == ':') + { + b = (b + r) * 60; + r = 0; + continue; + } + break; + } + if (f < 10) + r *= 1000; + else if (f == 10) + r *= 100; + else if (f == 100) + r *= 10; + r += b * 1000; + return r; +} diff -r fe2ba1a712cd -r 70b0973e7b70 src/xsf/vio2sf.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/xsf/vio2sf.c Thu Oct 16 14:45:41 2008 -0500 @@ -0,0 +1,833 @@ +#include +#include +#include + +#include "desmume/MMU.h" +#include "desmume/armcpu.h" +#include "desmume/NDSSystem.h" +#include "desmume/SPU.h" +#include "desmume/cp15.h" + +#include +#include "tagget.h" +#include "vio2sf.h" + +volatile BOOL execute = FALSE; + +static struct +{ + unsigned char *rom; + unsigned char *state; + unsigned romsize; + unsigned statesize; + unsigned stateptr; +} loaderwork = {0, 0, 0, 0, 0}; + +static void load_term(void) +{ + if (loaderwork.rom) + { + free(loaderwork.rom); + loaderwork.rom = 0; + } + loaderwork.romsize = 0; + if (loaderwork.state) + { + free(loaderwork.state); + loaderwork.state = 0; + } + loaderwork.statesize = 0; +} + +static int load_map(int issave, unsigned char *udata, unsigned usize) +{ + unsigned char *iptr; + unsigned isize; + unsigned char *xptr; + unsigned xsize = getdwordle(udata + 4); + unsigned xofs = getdwordle(udata + 0); + if (issave) + { + iptr = loaderwork.state; + isize = loaderwork.statesize; + loaderwork.state = 0; + loaderwork.statesize = 0; + } + else + { + iptr = loaderwork.rom; + isize = loaderwork.romsize; + loaderwork.rom = 0; + loaderwork.romsize = 0; + } + if (!iptr) + { + iptr = malloc(xofs + xsize + 10); + if (!iptr) + return XSF_FALSE; + memset(iptr, 0, xofs + xsize + 10); + isize = xofs + xsize; + } + else if (isize < xofs + xsize) + { + unsigned rsize = xofs + xsize; + if (!issave) + { + rsize -= 1; + rsize |= rsize >> 1; + rsize |= rsize >> 2; + rsize |= rsize >> 4; + rsize |= rsize >> 8; + rsize |= rsize >> 16; + rsize += 1; + } + xptr = realloc(iptr, xofs + rsize + 10); + if (!xptr) + { + free(iptr); + return XSF_FALSE; + } + iptr = xptr; + isize = rsize; + } + memcpy(iptr + xofs, udata + 8, xsize); + if (issave) + { + loaderwork.state = iptr; + loaderwork.statesize = isize; + } + else + { + loaderwork.rom = iptr; + loaderwork.romsize = isize; + } + return XSF_TRUE; +} + +static int load_mapz(int issave, unsigned char *zdata, unsigned zsize, unsigned zcrc) +{ + int ret; + int zerr; + uLongf usize = 8; + uLongf rsize = usize; + unsigned char *udata; + unsigned char *rdata; + + udata = malloc(usize); + if (!udata) + return XSF_FALSE; + + while (Z_OK != (zerr = uncompress(udata, &usize, zdata, zsize))) + { + if (Z_MEM_ERROR != zerr && Z_BUF_ERROR != zerr) + { + free(udata); + return XSF_FALSE; + } + if (usize >= 8) + { + usize = getdwordle(udata + 4) + 8; + if (usize < rsize) + { + rsize += rsize; + usize = rsize; + } + else + rsize = usize; + } + else + { + rsize += rsize; + usize = rsize; + } + free(udata); + udata = malloc(usize); + if (!udata) + return XSF_FALSE; + } + + rdata = realloc(udata, usize); + if (!rdata) + { + free(udata); + return XSF_FALSE; + } + + if (0) + { + unsigned ccrc = crc32(crc32(0L, Z_NULL, 0), rdata, usize); + if (ccrc != zcrc) + return XSF_FALSE; + } + + ret = load_map(issave, rdata, usize); + free(rdata); + return ret; +} + +static int load_psf_one(unsigned char *pfile, unsigned bytes) +{ + unsigned char *ptr = pfile; + unsigned code_size; + unsigned resv_size; + unsigned code_crc; + if (bytes < 16 || getdwordle(ptr) != 0x24465350) + return XSF_FALSE; + + resv_size = getdwordle(ptr + 4); + code_size = getdwordle(ptr + 8); + code_crc = getdwordle(ptr + 12); + + if (resv_size) + { + unsigned resv_pos = 0; + ptr = pfile + 16; + if (16+ resv_size > bytes) + return XSF_FALSE; + while (resv_pos + 12 < resv_size) + { + unsigned save_size = getdwordle(ptr + resv_pos + 4); + unsigned save_crc = getdwordle(ptr + resv_pos + 8); + if (getdwordle(ptr + resv_pos + 0) == 0x45564153) + { + if (resv_pos + 12 + save_size > resv_size) + return XSF_FALSE; + if (!load_mapz(1, ptr + resv_pos + 12, save_size, save_crc)) + return XSF_FALSE; + } + resv_pos += 12 + save_size; + } + } + + if (code_size) + { + ptr = pfile + 16 + resv_size; + if (16 + resv_size + code_size > bytes) + return XSF_FALSE; + if (!load_mapz(0, ptr, code_size, code_crc)) + return XSF_FALSE; + } + + return XSF_TRUE; +} + +typedef struct +{ + const char *tag; + int taglen; + int level; + int found; +} loadlibwork_t; + +static int load_libs(int level, void *pfile, unsigned bytes); + +static int load_psfcb(void *pWork, const char *pNameTop, const char *pNameEnd, const char *pValueTop, const char *pValueEnd) +{ + loadlibwork_t *pwork = (loadlibwork_t *)pWork; + int ret = xsf_tagenum_callback_returnvaluecontinue; + if (pNameEnd - pNameTop == pwork->taglen && !strncasecmp(pNameTop, pwork->tag , pwork->taglen)) + { + unsigned l = pValueEnd - pValueTop; + char *lib = malloc(l + 1); + if (!lib) + { + ret = xsf_tagenum_callback_returnvaluebreak; + } + else + { + void *libbuf; + unsigned libsize; + memcpy(lib, pValueTop, l); + lib[l] = '\0'; + if (!xsf_get_lib(lib, &libbuf, &libsize)) + { + ret = xsf_tagenum_callback_returnvaluebreak; + } + else + { + if (!load_libs(pwork->level + 1, libbuf, libsize) || !load_psf_one(libbuf, libsize)) + ret = xsf_tagenum_callback_returnvaluebreak; + else + pwork->found++; + free(libbuf); + } + free(lib); + } + } + return ret; +} + +static int load_libs(int level, void *pfile, unsigned bytes) +{ + char tbuf[16]; + loadlibwork_t work; + int n = 1; + + if (level > 10) + return XSF_TRUE; + + work.level = level; + work.tag = "_lib"; + + do + { + work.taglen = strlen(work.tag); + work.found = 0; + + if (xsf_tagenum(load_psfcb, &work, pfile, bytes) < 0) + return XSF_FALSE; + +#ifdef HAVE_SPRINTF_S + sprintf_s(tbuf, sizeof(tbuf), "_lib%10d", ++n); +#else + sprintf(tbuf, "_lib%10d", ++n); +#endif + work.tag = tbuf; + } + while (work.found); + + return XSF_TRUE; +} + +static int load_psf(void *pfile, unsigned bytes) +{ + load_term(); + + if (!load_libs(1, pfile, bytes) || !load_psf_one(pfile, bytes)) + return XSF_FALSE; + + return XSF_TRUE; +} + +static void load_getstateinit(unsigned ptr) +{ + loaderwork.stateptr = ptr; +} + +static u16 getwordle(const unsigned char *pData) +{ + return pData[0] | (((u16)pData[1]) << 8); +} + +static void load_getsta(Status_Reg *ptr, unsigned l) +{ + unsigned s = l << 2; + unsigned i; + if ((loaderwork.stateptr > loaderwork.statesize) || ((loaderwork.stateptr + s) > loaderwork.statesize)) + return; + for (i = 0; i < l; i++) + { + u32 st = getdwordle(loaderwork.state + loaderwork.stateptr + (i << 2)); + ptr[i].bits.N = (st >> 31) & 1; + ptr[i].bits.Z = (st >> 30) & 1; + ptr[i].bits.C = (st >> 29) & 1; + ptr[i].bits.V = (st >> 28) & 1; + ptr[i].bits.Q = (st >> 27) & 1; + ptr[i].bits.RAZ = (st >> 8) & ((1 << 19) - 1); + ptr[i].bits.I = (st >> 7) & 1; + ptr[i].bits.F = (st >> 6) & 1; + ptr[i].bits.T = (st >> 5) & 1; + ptr[i].bits.mode = (st >> 0) & 0x1f; + } + loaderwork.stateptr += s; +} + +static void load_getbool(BOOL *ptr, unsigned l) +{ + unsigned s = l << 2; + unsigned i; + if ((loaderwork.stateptr > loaderwork.statesize) || ((loaderwork.stateptr + s) > loaderwork.statesize)) + return; + for (i = 0; i < l; i++) + ptr[i] = (BOOL)getdwordle(loaderwork.state + loaderwork.stateptr + (i << 2)); + loaderwork.stateptr += s; +} + +#if defined(SIGNED_IS_NOT_2S_COMPLEMENT) +/* 2's complement */ +#define u32tos32(v) ((s32)((((s64)(v)) ^ 0x8000) - 0x8000)) +#else +/* 2's complement */ +#define u32tos32(v) ((s32)v) +#endif + +static void load_gets32(s32 *ptr, unsigned l) +{ + unsigned s = l << 2; + unsigned i; + if ((loaderwork.stateptr > loaderwork.statesize) || ((loaderwork.stateptr + s) > loaderwork.statesize)) + return; + for (i = 0; i < l; i++) + ptr[i] = u32tos32(getdwordle(loaderwork.state + loaderwork.stateptr + (i << 2))); + loaderwork.stateptr += s; +} + +static void load_getu32(u32 *ptr, unsigned l) +{ + unsigned s = l << 2; + unsigned i; + if ((loaderwork.stateptr > loaderwork.statesize) || ((loaderwork.stateptr + s) > loaderwork.statesize)) + return; + for (i = 0; i < l; i++) + ptr[i] = getdwordle(loaderwork.state + loaderwork.stateptr + (i << 2)); + loaderwork.stateptr += s; +} + +static void load_getu16(u16 *ptr, unsigned l) +{ + unsigned s = l << 1; + unsigned i; + if ((loaderwork.stateptr > loaderwork.statesize) || ((loaderwork.stateptr + s) > loaderwork.statesize)) + return; + for (i = 0; i < l; i++) + ptr[i] = getwordle(loaderwork.state + loaderwork.stateptr + (i << 1)); + loaderwork.stateptr += s; +} + +static void load_getu8(u8 *ptr, unsigned l) +{ + unsigned s = l; + unsigned i; + if ((loaderwork.stateptr > loaderwork.statesize) || ((loaderwork.stateptr + s) > loaderwork.statesize)) + return; + for (i = 0; i < l; i++) + ptr[i] = loaderwork.state[loaderwork.stateptr + i]; + loaderwork.stateptr += s; +} + +void gdb_stub_fix(armcpu_t *armcpu) +{ + /* armcpu->R[15] = armcpu->instruct_adr; */ + armcpu->next_instruction = armcpu->instruct_adr; + if(armcpu->CPSR.bits.T == 0) + { + armcpu->instruction = MMU_read32_acl(armcpu->proc_ID, armcpu->next_instruction,CP15_ACCESS_EXECUTE); + armcpu->instruct_adr = armcpu->next_instruction; + armcpu->next_instruction += 4; + armcpu->R[15] = armcpu->next_instruction + 4; + } + else + { + armcpu->instruction = MMU_read16_acl(armcpu->proc_ID, armcpu->next_instruction,CP15_ACCESS_EXECUTE); + armcpu->instruct_adr = armcpu->next_instruction; + armcpu->next_instruction += 2; + armcpu->R[15] = armcpu->next_instruction + 2; + } +} + +static void load_setstate(void) +{ + if (!loaderwork.statesize) + return; + + /* Skip over "Desmume Save File" crap */ + load_getstateinit(0x17); + + /* Read ARM7 cpu registers */ + load_getu32(&NDS_ARM7.proc_ID, 1); + load_getu32(&NDS_ARM7.instruction, 1); + load_getu32(&NDS_ARM7.instruct_adr, 1); + load_getu32(&NDS_ARM7.next_instruction, 1); + load_getu32(NDS_ARM7.R, 16); + load_getsta(&NDS_ARM7.CPSR, 1); + load_getsta(&NDS_ARM7.SPSR, 1); + load_getu32(&NDS_ARM7.R13_usr, 1); + load_getu32(&NDS_ARM7.R14_usr, 1); + load_getu32(&NDS_ARM7.R13_svc, 1); + load_getu32(&NDS_ARM7.R14_svc, 1); + load_getu32(&NDS_ARM7.R13_abt, 1); + load_getu32(&NDS_ARM7.R14_abt, 1); + load_getu32(&NDS_ARM7.R13_und, 1); + load_getu32(&NDS_ARM7.R14_und, 1); + load_getu32(&NDS_ARM7.R13_irq, 1); + load_getu32(&NDS_ARM7.R14_irq, 1); + load_getu32(&NDS_ARM7.R8_fiq, 1); + load_getu32(&NDS_ARM7.R9_fiq, 1); + load_getu32(&NDS_ARM7.R10_fiq, 1); + load_getu32(&NDS_ARM7.R11_fiq, 1); + load_getu32(&NDS_ARM7.R12_fiq, 1); + load_getu32(&NDS_ARM7.R13_fiq, 1); + load_getu32(&NDS_ARM7.R14_fiq, 1); + load_getsta(&NDS_ARM7.SPSR_svc, 1); + load_getsta(&NDS_ARM7.SPSR_abt, 1); + load_getsta(&NDS_ARM7.SPSR_und, 1); + load_getsta(&NDS_ARM7.SPSR_irq, 1); + load_getsta(&NDS_ARM7.SPSR_fiq, 1); + load_getu32(&NDS_ARM7.intVector, 1); + load_getu8(&NDS_ARM7.LDTBit, 1); + load_getbool(&NDS_ARM7.waitIRQ, 1); + load_getbool(&NDS_ARM7.wIRQ, 1); + load_getbool(&NDS_ARM7.wirq, 1); + + /* Read ARM9 cpu registers */ + load_getu32(&NDS_ARM9.proc_ID, 1); + load_getu32(&NDS_ARM9.instruction, 1); + load_getu32(&NDS_ARM9.instruct_adr, 1); + load_getu32(&NDS_ARM9.next_instruction, 1); + load_getu32(NDS_ARM9.R, 16); + load_getsta(&NDS_ARM9.CPSR, 1); + load_getsta(&NDS_ARM9.SPSR, 1); + load_getu32(&NDS_ARM9.R13_usr, 1); + load_getu32(&NDS_ARM9.R14_usr, 1); + load_getu32(&NDS_ARM9.R13_svc, 1); + load_getu32(&NDS_ARM9.R14_svc, 1); + load_getu32(&NDS_ARM9.R13_abt, 1); + load_getu32(&NDS_ARM9.R14_abt, 1); + load_getu32(&NDS_ARM9.R13_und, 1); + load_getu32(&NDS_ARM9.R14_und, 1); + load_getu32(&NDS_ARM9.R13_irq, 1); + load_getu32(&NDS_ARM9.R14_irq, 1); + load_getu32(&NDS_ARM9.R8_fiq, 1); + load_getu32(&NDS_ARM9.R9_fiq, 1); + load_getu32(&NDS_ARM9.R10_fiq, 1); + load_getu32(&NDS_ARM9.R11_fiq, 1); + load_getu32(&NDS_ARM9.R12_fiq, 1); + load_getu32(&NDS_ARM9.R13_fiq, 1); + load_getu32(&NDS_ARM9.R14_fiq, 1); + load_getsta(&NDS_ARM9.SPSR_svc, 1); + load_getsta(&NDS_ARM9.SPSR_abt, 1); + load_getsta(&NDS_ARM9.SPSR_und, 1); + load_getsta(&NDS_ARM9.SPSR_irq, 1); + load_getsta(&NDS_ARM9.SPSR_fiq, 1); + load_getu32(&NDS_ARM9.intVector, 1); + load_getu8(&NDS_ARM9.LDTBit, 1); + load_getbool(&NDS_ARM9.waitIRQ, 1); + load_getbool(&NDS_ARM9.wIRQ, 1); + load_getbool(&NDS_ARM9.wirq, 1); + + /* Read in other internal variables that are important */ + load_gets32(&nds.ARM9Cycle, 1); + load_gets32(&nds.ARM7Cycle, 1); + load_gets32(&nds.cycles, 1); + load_gets32(nds.timerCycle[0], 4); + load_gets32(nds.timerCycle[1], 4); + load_getbool(nds.timerOver[0], 4); + load_getbool(nds.timerOver[1], 4); + load_gets32(&nds.nextHBlank, 1); + load_getu32(&nds.VCount, 1); + load_getu32(&nds.old, 1); + load_gets32(&nds.diff, 1); + load_getbool(&nds.lignerendu, 1); + load_getu16(&nds.touchX, 1); + load_getu16(&nds.touchY, 1); + + /* Read in memory/registers specific to the ARM9 */ + load_getu8 (ARM9Mem.ARM9_ITCM, 0x8000); + load_getu8 (ARM9Mem.ARM9_DTCM, 0x4000); + load_getu8 (ARM9Mem.ARM9_WRAM, 0x1000000); + load_getu8 (ARM9Mem.MAIN_MEM, 0x400000); + load_getu8 (ARM9Mem.ARM9_REG, 0x10000); + load_getu8 (ARM9Mem.ARM9_VMEM, 0x800); + load_getu8 (ARM9Mem.ARM9_OAM, 0x800); + load_getu8 (ARM9Mem.ARM9_ABG, 0x80000); + load_getu8 (ARM9Mem.ARM9_BBG, 0x20000); + load_getu8 (ARM9Mem.ARM9_AOBJ, 0x40000); + load_getu8 (ARM9Mem.ARM9_BOBJ, 0x20000); + load_getu8 (ARM9Mem.ARM9_LCD, 0xA4000); + + /* Read in memory/registers specific to the ARM7 */ + load_getu8 (MMU.ARM7_ERAM, 0x10000); + load_getu8 (MMU.ARM7_REG, 0x10000); + load_getu8 (MMU.ARM7_WIRAM, 0x10000); + + /* Read in shared memory */ + load_getu8 (MMU.SWIRAM, 0x8000); + +#ifdef GDB_STUB +#else + gdb_stub_fix(&NDS_ARM9); + gdb_stub_fix(&NDS_ARM7); +#endif +} + +static struct +{ + unsigned char *pcmbufalloc; + unsigned char *pcmbuftop; + unsigned filled; + unsigned used; + u32 bufferbytes; + u32 cycles; + int xfs_load; + int sync_type; + int arm7_clockdown_level; + int arm9_clockdown_level; +} sndifwork = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + +static void SNDIFDeInit(void) +{ + if (sndifwork.pcmbufalloc) + { + free(sndifwork.pcmbufalloc); + sndifwork.pcmbufalloc = 0; + sndifwork.pcmbuftop = 0; + sndifwork.bufferbytes = 0; + } +} +static int SNDIFInit(int buffersize) +{ + u32 bufferbytes = buffersize * sizeof(s16); + SNDIFDeInit(); + sndifwork.pcmbufalloc = malloc(bufferbytes + 3); + if (!sndifwork.pcmbufalloc) + return -1; + sndifwork.pcmbuftop = sndifwork.pcmbufalloc + ((4 - (((int)sndifwork.pcmbufalloc) & 3)) & 3); + sndifwork.bufferbytes = bufferbytes; + sndifwork.filled = 0; + sndifwork.used = 0; + sndifwork.cycles = 0; + return 0; +} +static void SNDIFMuteAudio(void) +{ +} +static void SNDIFUnMuteAudio(void) +{ +} +static void SNDIFSetVolume(int volume) +{ +} +static int SNDIFGetAudioSpace(void) +{ + return sndifwork.bufferbytes >> 2; // bytes to samples +} +static void SNDIFUpdateAudio(s16 * buffer, u32 num_samples) +{ + u32 num_bytes = num_samples << 2; + if (num_bytes > sndifwork.bufferbytes) num_bytes = sndifwork.bufferbytes; + memcpy(sndifwork.pcmbuftop, buffer, num_bytes); + sndifwork.filled = num_bytes; + sndifwork.used = 0; +} +#define VIO2SFSNDIFID 2 +static SoundInterface_struct VIO2SFSNDIF = +{ + VIO2SFSNDIFID, + "vio2sf Sound Interface", + SNDIFInit, + SNDIFDeInit, + SNDIFUpdateAudio, + SNDIFGetAudioSpace, + SNDIFMuteAudio, + SNDIFUnMuteAudio, + SNDIFSetVolume +}; + +SoundInterface_struct *SNDCoreList[] = { + &VIO2SFSNDIF, + &SNDDummy, + NULL +}; + +static struct armcpu_ctrl_iface *arm9_ctrl_iface = 0; +static struct armcpu_ctrl_iface *arm7_ctrl_iface = 0; + +int xsf_start(void *pfile, unsigned bytes) +{ + int frames = xsf_tagget_int("_frames", pfile, bytes, -1); + int clockdown = xsf_tagget_int("_clockdown", pfile, bytes, 0); + sndifwork.sync_type = xsf_tagget_int("_vio2sf_sync_type", pfile, bytes, 0); + sndifwork.arm9_clockdown_level = xsf_tagget_int("_vio2sf_arm9_clockdown_level", pfile, bytes, clockdown); + sndifwork.arm7_clockdown_level = xsf_tagget_int("_vio2sf_arm7_clockdown_level", pfile, bytes, clockdown); + + sndifwork.xfs_load = 0; + if (!load_psf(pfile, bytes)) + return XSF_FALSE; + +#ifdef GDB_STUB + if (NDS_Init(&arm9_base_memory_iface, &arm9_ctrl_iface, &arm7_base_memory_iface, &arm7_ctrl_iface)) +#else + if (NDS_Init()) +#endif + return XSF_FALSE; + + SPU_ChangeSoundCore(VIO2SFSNDIFID, 737); + + execute = FALSE; + + MMU_unsetRom(); + if (loaderwork.rom) + { + NDS_SetROM(loaderwork.rom, loaderwork.romsize - 1); + } + + NDS_Reset(); + + execute = TRUE; + + if (loaderwork.state) + { + armcp15_t *c9 = (armcp15_t *)NDS_ARM9.coproc[15]; + int proc; + if (frames == -1) + { + + /* set initial ARM9 coprocessor state */ + + armcp15_moveARM2CP(c9, 0x00000000, 0x01, 0x00, 0, 0); + armcp15_moveARM2CP(c9, 0x00000000, 0x07, 0x05, 0, 0); + armcp15_moveARM2CP(c9, 0x00000000, 0x07, 0x06, 0, 0); + armcp15_moveARM2CP(c9, 0x00000000, 0x07, 0x0a, 0, 4); + armcp15_moveARM2CP(c9, 0x04000033, 0x06, 0x00, 0, 4); + armcp15_moveARM2CP(c9, 0x0200002d, 0x06, 0x01, 0, 0); + armcp15_moveARM2CP(c9, 0x027e0021, 0x06, 0x02, 0, 0); + armcp15_moveARM2CP(c9, 0x08000035, 0x06, 0x03, 0, 0); + armcp15_moveARM2CP(c9, 0x027e001b, 0x06, 0x04, 0, 0); + armcp15_moveARM2CP(c9, 0x0100002f, 0x06, 0x05, 0, 0); + armcp15_moveARM2CP(c9, 0xffff001d, 0x06, 0x06, 0, 0); + armcp15_moveARM2CP(c9, 0x027ff017, 0x06, 0x07, 0, 0); + armcp15_moveARM2CP(c9, 0x00000020, 0x09, 0x01, 0, 1); + + armcp15_moveARM2CP(c9, 0x027e000a, 0x09, 0x01, 0, 0); + + armcp15_moveARM2CP(c9, 0x00000042, 0x02, 0x00, 0, 1); + armcp15_moveARM2CP(c9, 0x00000042, 0x02, 0x00, 0, 0); + armcp15_moveARM2CP(c9, 0x00000002, 0x03, 0x00, 0, 0); + armcp15_moveARM2CP(c9, 0x05100011, 0x05, 0x00, 0, 3); + armcp15_moveARM2CP(c9, 0x15111011, 0x05, 0x00, 0, 2); + armcp15_moveARM2CP(c9, 0x07dd1e10, 0x01, 0x00, 0, 0); + armcp15_moveARM2CP(c9, 0x0005707d, 0x01, 0x00, 0, 0); + + armcp15_moveARM2CP(c9, 0x00000000, 0x07, 0x0a, 0, 4); + armcp15_moveARM2CP(c9, 0x02004000, 0x07, 0x05, 0, 1); + armcp15_moveARM2CP(c9, 0x02004000, 0x07, 0x0e, 0, 1); + + /* set initial timer state */ + + MMU_write16(0, REG_TM0CNTL, 0x0000); + MMU_write16(0, REG_TM0CNTH, 0x00C1); + MMU_write16(1, REG_TM0CNTL, 0x0000); + MMU_write16(1, REG_TM0CNTH, 0x00C1); + MMU_write16(1, REG_TM1CNTL, 0xf7e7); + MMU_write16(1, REG_TM1CNTH, 0x00C1); + + /* set initial interrupt state */ + + MMU.reg_IME[0] = 0x00000001; + MMU.reg_IE[0] = 0x00042001; + MMU.reg_IME[1] = 0x00000001; + MMU.reg_IE[1] = 0x0104009d; + } + else if (frames > 0) + { + /* execute boot code */ + int i; + for (i=0; i 0) + { + /* skip 1 sec */ + int i; + for (i=0; i 0) + { + if (remainbytes > bytes) + { + memcpy(ptr, sndifwork.pcmbuftop + sndifwork.used, bytes); + sndifwork.used += bytes; + ptr += bytes; + remainbytes -= bytes; /**/ + bytes = 0; /**/ + break; + } + else + { + memcpy(ptr, sndifwork.pcmbuftop + sndifwork.used, remainbytes); + sndifwork.used += remainbytes; + ptr += remainbytes; + bytes -= remainbytes; + remainbytes = 0; + } + } + if (remainbytes == 0) + { + +#define HBASE_CYCLES 33509300.322234 +#define VBASE_CYCLES (((double)HBASE_CYCLES) / 100) +#define HSAMPLES ((u32)((44100.0 * 6 * (99 + 256)) / HBASE_CYCLES)) +#define VSAMPLES ((u32)((44100.0 * 6 * (99 + 256) * 263) / HBASE_CYCLES)) + + int numsamples; + if (sndifwork.sync_type == 1) + { + /* vsync */ + sndifwork.cycles += (441 * 6 * (99 + 256) * 263); + if (sndifwork.cycles >= (u32)(VBASE_CYCLES * (VSAMPLES + 1))) + { + numsamples = (VSAMPLES + 1); + sndifwork.cycles -= (u32)(VBASE_CYCLES * (VSAMPLES + 1)); + } + else + { + numsamples = (VSAMPLES + 0); + sndifwork.cycles -= (u32)(VBASE_CYCLES * (VSAMPLES + 0)); + } + NDS_exec_frame(sndifwork.arm9_clockdown_level, sndifwork.arm7_clockdown_level); + } + else + { + /* hsync */ + sndifwork.cycles += (44100 * 6 * (99 + 256)); + if (sndifwork.cycles >= (u32)(HBASE_CYCLES * (HSAMPLES + 1))) + { + numsamples = (HSAMPLES + 1); + sndifwork.cycles -= (u32)(HBASE_CYCLES * (HSAMPLES + 1)); + } + else + { + numsamples = (HSAMPLES + 0); + sndifwork.cycles -= (u32)(HBASE_CYCLES * (HSAMPLES + 0)); + } + NDS_exec_hframe(sndifwork.arm9_clockdown_level, sndifwork.arm7_clockdown_level); + } + SPU_EmulateSamples(numsamples); + } + } + return ptr - (unsigned char *)pbuffer; +} + +void xsf_term(void) +{ + MMU_unsetRom(); + NDS_DeInit(); + load_term(); +} diff -r fe2ba1a712cd -r 70b0973e7b70 src/xsf/vio2sf.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/xsf/vio2sf.h Thu Oct 16 14:45:41 2008 -0500 @@ -0,0 +1,7 @@ +#define XSF_FALSE (0) +#define XSF_TRUE (!XSF_FALSE) + +int xsf_start(void *pfile, unsigned bytes); +int xsf_gen(void *pbuffer, unsigned samples); +int xsf_get_lib(char *pfilename, void **ppbuffer, unsigned int *plength); +void xsf_term(void); diff -r fe2ba1a712cd -r 70b0973e7b70 src/xsf/xsfdrv.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/xsf/xsfdrv.h Thu Oct 16 14:45:41 2008 -0500 @@ -0,0 +1,21 @@ +#ifdef __cplusplus +extern "C" { +#endif + +typedef int (PASCAL * LPFNGETLIB_XSFDRV)(void *lpWork, LPSTR lpszFilename, void **ppBuffer, DWORD *pdwSize); +typedef struct +{ + void * (PASCAL * LibAlloc)(DWORD dwSize); + void (PASCAL * LibFree)(void *lpPtr); + int (PASCAL * Start)(void *lpPtr, DWORD dwSize); + void (PASCAL * Gen)(void *lpPtr, DWORD dwSamples); + void (PASCAL * Term)(void); +} IXSFDRV; + +typedef IXSFDRV * (PASCAL * LPFNXSFDRVSETUP)(LPFNGETLIB_XSFDRV lpfn, void *lpWork); +/* IXSFDRV * PASCAL XSFDRVSetup(LPFNGETLIB_XSFDRV lpfn, void *lpWork); */ + +#ifdef __cplusplus +} +#endif +