desmume/src/utils/task_vita.cpp000664 001750 001750 00000007114 12755534123 017773 0ustar00sergiosergio000000 000000 /* Copyright (C) 2009-2015 DeSmuME team Copyright (C) 2015 Sergi Granell (xerpi) This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the this software. If not, see . */ #include #include #include "../utils/task.h" #include "debug.h" class Task::Impl { private: SceUID _thread; bool _isThreadRunning; public: Impl(); ~Impl(); void start(); void execute(const TWork &work, void *param); void* finish(); void shutdown(); //slock_t *mutex; SceUID condWork; TWork workFunc; void *workFuncParam; void *ret; bool exitThread; }; #define EVENT_WORK_START 1 #define EVENT_WORK_END 2 static int taskProc(SceSize args, void *argp) { Task::Impl *ctx = *(Task::Impl **)argp; do { while (!ctx->workFunc && !ctx->exitThread) sceKernelWaitEventFlag(ctx->condWork, EVENT_WORK_START, SCE_EVENT_WAITAND, NULL, NULL); sceKernelClearEventFlag(ctx->condWork, ~EVENT_WORK_START); if (ctx->workFunc) ctx->ret = ctx->workFunc(ctx->workFuncParam); else ctx->ret = NULL; ctx->workFunc = NULL; sceKernelSetEventFlag(ctx->condWork, EVENT_WORK_END); } while(!ctx->exitThread); return 0; } Task::Impl::Impl() { _isThreadRunning = false; workFunc = NULL; workFuncParam = NULL; ret = NULL; exitThread = false; condWork = sceKernelCreateEventFlag("desmume_cond_work", 0, 0, NULL); } Task::Impl::~Impl() { shutdown(); sceKernelDeleteEventFlag(condWork); } void Task::Impl::start() { if (this->_isThreadRunning) { return; } this->workFunc = NULL; this->workFuncParam = NULL; this->ret = NULL; this->exitThread = false; this->_thread = sceKernelCreateThread("desmume_task", taskProc, 0x10000100, 0x1000, 0, 0, NULL); sceKernelClearEventFlag(condWork, ~(EVENT_WORK_START | EVENT_WORK_END)); Task::Impl *_this = this; sceKernelStartThread(this->_thread, sizeof(_this), &_this); this->_isThreadRunning = true; } void Task::Impl::execute(const TWork &work, void *param) { if (!work || !this->_isThreadRunning) return; this->workFunc = work; this->workFuncParam = param; sceKernelSetEventFlag(condWork, EVENT_WORK_START); } void* Task::Impl::finish() { void *returnValue = NULL; if (!this->_isThreadRunning) goto end; while (this->workFunc != NULL) sceKernelWaitEventFlag(condWork, EVENT_WORK_END, SCE_EVENT_WAITAND, NULL, NULL); sceKernelClearEventFlag(condWork, ~EVENT_WORK_END); returnValue = this->ret; end: return returnValue; } void Task::Impl::shutdown() { if (!this->_isThreadRunning) return; this->workFunc = NULL; this->exitThread = true; sceKernelSetEventFlag(condWork, EVENT_WORK_START | EVENT_WORK_END); sceKernelWaitThreadEnd(_thread, NULL, NULL); sceKernelDeleteThread(_thread); this->_isThreadRunning = false; } void Task::start() { impl->start(); } void Task::shutdown() { impl->shutdown(); } Task::Task() : impl(new Task::Impl()) {} Task::~Task() { delete impl; } void Task::execute(const TWork &work, void* param) { impl->execute(work,param); } void* Task::finish() { return impl->finish(); } desmume/src/libretro-common/lists/000700 001750 001750 00000000000 12756420131 020363 5ustar00sergiosergio000000 000000 desmume/src/libretro-common/include/glsm/glsm.h000664 001750 001750 00000011446 12755534123 022755 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2016 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this libretro SDK code part (glsm.h). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef LIBRETRO_SDK_GLSM_H #define LIBRETRO_SDK_GLSM_H #include #include #include #include RETRO_BEGIN_DECLS #ifdef HAVE_OPENGLES2 typedef GLfloat GLdouble; typedef GLclampf GLclampd; #endif #if defined(HAVE_OPENGLES2) #define RARCH_GL_RENDERBUFFER GL_RENDERBUFFER #define RARCH_GL_DEPTH24_STENCIL8 GL_DEPTH24_STENCIL8_OES #define RARCH_GL_DEPTH_ATTACHMENT GL_DEPTH_ATTACHMENT #define RARCH_GL_STENCIL_ATTACHMENT GL_STENCIL_ATTACHMENT #elif defined(OSX_PPC) #define RARCH_GL_RENDERBUFFER GL_RENDERBUFFER_EXT #define RARCH_GL_DEPTH24_STENCIL8 GL_DEPTH24_STENCIL8_EXT #define RARCH_GL_DEPTH_ATTACHMENT GL_DEPTH_ATTACHMENT_EXT #define RARCH_GL_STENCIL_ATTACHMENT GL_STENCIL_ATTACHMENT_EXT #elif defined(HAVE_PSGL) #define RARCH_GL_RENDERBUFFER GL_RENDERBUFFER_OES #define RARCH_GL_DEPTH24_STENCIL8 GL_DEPTH24_STENCIL8_SCE #define RARCH_GL_DEPTH_ATTACHMENT GL_DEPTH_ATTACHMENT_OES #define RARCH_GL_STENCIL_ATTACHMENT GL_STENCIL_ATTACHMENT_OES #else #define RARCH_GL_RENDERBUFFER GL_RENDERBUFFER #define RARCH_GL_DEPTH24_STENCIL8 GL_DEPTH24_STENCIL8 #define RARCH_GL_DEPTH_ATTACHMENT GL_DEPTH_ATTACHMENT #define RARCH_GL_STENCIL_ATTACHMENT GL_STENCIL_ATTACHMENT #endif #if defined(HAVE_PSGL) #define RARCH_GL_FRAMEBUFFER GL_FRAMEBUFFER_OES #define RARCH_GL_FRAMEBUFFER_COMPLETE GL_FRAMEBUFFER_COMPLETE_OES #define RARCH_GL_COLOR_ATTACHMENT0 GL_COLOR_ATTACHMENT0_EXT #elif defined(OSX_PPC) #define RARCH_GL_FRAMEBUFFER GL_FRAMEBUFFER_EXT #define RARCH_GL_FRAMEBUFFER_COMPLETE GL_FRAMEBUFFER_COMPLETE_EXT #define RARCH_GL_COLOR_ATTACHMENT0 GL_COLOR_ATTACHMENT0_EXT #else #define RARCH_GL_FRAMEBUFFER GL_FRAMEBUFFER #define RARCH_GL_FRAMEBUFFER_COMPLETE GL_FRAMEBUFFER_COMPLETE #define RARCH_GL_COLOR_ATTACHMENT0 GL_COLOR_ATTACHMENT0 #endif #ifndef GL_FOG #define GL_FOG 0x0B60 #endif #ifndef GL_ALPHA_TEST #define GL_ALPHA_TEST 0x0BC0 #endif #ifndef GL_CLIP_DISTANCE0 #define GL_CLIP_DISTANCE0 0x3000 #endif #define MAX_ATTRIB 8 enum { SGL_DEPTH_TEST = 0, SGL_BLEND, SGL_POLYGON_OFFSET_FILL, SGL_FOG, SGL_CULL_FACE, SGL_ALPHA_TEST, SGL_SCISSOR_TEST, SGL_STENCIL_TEST, #if !defined(HAVE_OPENGLES) SGL_DEPTH_CLAMP, SGL_CLIP_DISTANCE0, #endif SGL_DITHER, SGL_SAMPLE_ALPHA_TO_COVERAGE, SGL_SAMPLE_COVERAGE, #ifndef HAVE_OPENGLES SGL_COLOR_LOGIC_OP, #endif SGL_CAP_MAX }; enum glsm_state_ctl { GLSM_CTL_NONE = 0, GLSM_CTL_STATE_SETUP, GLSM_CTL_STATE_BIND, GLSM_CTL_STATE_UNBIND, GLSM_CTL_STATE_CONTEXT_RESET, GLSM_CTL_STATE_CONTEXT_DESTROY, GLSM_CTL_STATE_CONTEXT_INIT, GLSM_CTL_IS_IMM_VBO, GLSM_CTL_SET_IMM_VBO, GLSM_CTL_UNSET_IMM_VBO, GLSM_CTL_IMM_VBO_DISABLE, GLSM_CTL_IMM_VBO_DRAW, GLSM_CTL_PROC_ADDRESS_GET }; typedef bool (*glsm_imm_vbo_draw)(void *); typedef bool (*glsm_imm_vbo_disable)(void *); typedef bool (*glsm_framebuffer_lock)(void *); typedef struct glsm_ctx_proc_address { retro_get_proc_address_t addr; } glsm_ctx_proc_address_t; typedef struct glsm_ctx_params { glsm_framebuffer_lock framebuffer_lock; glsm_imm_vbo_draw imm_vbo_draw; glsm_imm_vbo_disable imm_vbo_disable; retro_hw_context_reset_t context_reset; retro_hw_context_reset_t context_destroy; retro_environment_t environ_cb; bool stencil; unsigned major; unsigned minor; } glsm_ctx_params_t; GLuint glsm_get_current_framebuffer(void); bool glsm_ctl(enum glsm_state_ctl state, void *data); RETRO_END_DECLS #endif desmume/src/libretro-common/include/gfx/math/vector_2.h000664 001750 001750 00000003351 12755534123 024305 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2016 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (vector_2.h). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef __LIBRETRO_SDK_GFX_MATH_VECTOR_3_H__ #define __LIBRETRO_SDK_GFX_MATH_VECTOR_3_H__ #include typedef float vec2_t[2]; float vec2_dot(const float *a, const float *b); float vec2_cross(const float *a, const float *b) ; void vec2_add(float *dst, const float *src); void vec2_subtract(float *dst, const float *src); void vec2_copy(float *dst, const float *src); #endif desmume/src/NDSSystem.cpp000664 001750 001750 00000234647 12755534123 016514 0ustar00sergiosergio000000 000000 /* Copyright (C) 2006 yopyop Copyright (C) 2008-2015 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the this software. If not, see . */ #include "NDSSystem.h" #include #include #include #include #include extern unsigned long crc32(unsigned long, const unsigned char*,unsigned int); #include "utils/dlditool.h" #include "utils/decrypt/decrypt.h" #include "utils/decrypt/crc.h" #include "utils/advanscene.h" #include "utils/task.h" #include "utils/bits.h" #include "common.h" #include "armcpu.h" #include "render3D.h" #include "MMU.h" #include "gfx3d.h" #include "GPU.h" #include "cp15.h" #include "bios.h" #include "debug.h" #include "cheatSystem.h" #include "movie.h" #include "emufile.h" #ifdef DEBUG #include "Disassembler.h" #endif #include "FIFO.h" #include "readwrite.h" #include "registers.h" #ifdef DEBUG #include "debug.h" #endif #include "driver.h" #include "firmware.h" #include "version.h" #include "path.h" #include "slot1.h" #include "slot2.h" #include "SPU.h" #include "wifi.h" //int xxctr=0; //#define LOG_ARM9 //#define LOG_ARM7 //#define dolog (currFrameCounter>30) bool dolog = false; //#define LOG_TO_FILE //#define LOG_TO_FILE_REGS //=============================================================== FILE *fp_dis7 = NULL; FILE *fp_dis9 = NULL; PathInfo path; TCommonSettings CommonSettings; static BaseDriver _stub_driver; BaseDriver* driver = &_stub_driver; static BOOL LidClosed = FALSE; static u8 countLid = 0; GameInfo gameInfo; NDSSystem nds; CFIRMWARE *firmware = NULL; using std::min; using std::max; bool singleStep; bool nds_debug_continuing[2]; TSCalInfo TSCal; extern "C" int DLDI_tryPatch(void* data, size_t size, unsigned int device); void Desmume_InitOnce() { static bool initOnce = false; if(initOnce) return; initOnce = true; } int NDS_GetCPUCoreCount(void) { int amount = cpu_features_get_core_amount(); return amount; } void NDS_SetupDefaultFirmware() { NDS_FillDefaultFirmwareConfigData(&CommonSettings.fw_config); } void NDS_RunAdvansceneAutoImport() { if(CommonSettings.run_advanscene_import != "") { std::string fname = CommonSettings.run_advanscene_import; std::string fname_out = fname + ".ddb"; EMUFILE_FILE outf(fname_out,"wb"); u32 ret = advsc.convertDB(fname.c_str(),&outf); if(ret == 0) exit(0); else exit(1); } } int NDS_Init() { nds.idleFrameCounter = 0; memset(nds.runCycleCollector,0,sizeof(nds.runCycleCollector)); MMU_Init(); //got to print this somewhere.. printf("%s\n", EMU_DESMUME_NAME_AND_VERSION()); { char buf[PATH_MAX_LENGTH]; memset(buf, 0, sizeof(buf)); strcpy(buf, path.pathToModule); strcat(buf, "desmume.ddb"); // DeSmuME database :) advsc.setDatabase(buf); //why is this done here? shitty engineering. not intended. NDS_RunAdvansceneAutoImport(); } armcpu_new(&NDS_ARM9,0); NDS_ARM9.SetBaseMemoryInterface(&arm9_base_memory_iface); NDS_ARM9.SetBaseMemoryInterfaceData(NULL); NDS_ARM9.ResetMemoryInterfaceToBase(); armcpu_new(&NDS_ARM7,1); NDS_ARM7.SetBaseMemoryInterface(&arm7_base_memory_iface); NDS_ARM7.SetBaseMemoryInterfaceData(NULL); NDS_ARM7.ResetMemoryInterfaceToBase(); if (GPU != NULL) delete GPU; GPU = new GPUSubsystem; if (SPU_Init(SNDCORE_DUMMY, 740) != 0) return -1; WIFI_Init() ; cheats = new CHEATS(); return 0; } void NDS_DeInit(void) { gameInfo.closeROM(); SPU_DeInit(); delete GPU; GPU = NULL; MMU_DeInit(); WIFI_DeInit(); delete cheats; cheats = NULL; #ifdef HAVE_JIT arm_jit_close(); #endif #ifdef LOG_ARM7 if (fp_dis7 != NULL) { fclose(fp_dis7); fp_dis7 = NULL; } #endif #ifdef LOG_ARM9 if (fp_dis9 != NULL) { fclose(fp_dis9); fp_dis9 = NULL; } #endif } NDS_header* NDS_getROMHeader(void) { NDS_header *newHeader = new NDS_header; memcpy(newHeader, &gameInfo.header, sizeof(NDS_header)); return newHeader; } #ifdef DEBUG void debug() { //if(NDS_ARM9.R[15]==0x020520DC) emu_halt(); //DSLinux //if(NDS_ARM9.CPSR.bits.mode == 0) emu_halt(); //if((NDS_ARM9.R[15]&0xFFFFF000)==0) emu_halt(); //if((NDS_ARM9.R[15]==0x0201B4F4)/*&&(NDS_ARM9.R[1]==0x0)*/) emu_halt(); //AOE //if((NDS_ARM9.R[15]==0x01FFE194)&&(NDS_ARM9.R[0]==0)) emu_halt(); //if((NDS_ARM9.R[15]==0x01FFE134)&&(NDS_ARM9.R[0]==0)) emu_halt(); //BBMAN //if(NDS_ARM9.R[15]==0x02098B4C) emu_halt(); //if(NDS_ARM9.R[15]==0x02004924) emu_halt(); //if(NDS_ARM9.R[15]==0x02004890) emu_halt(); //if(NDS_ARM9.R[15]==0x0202B800) emu_halt(); //if(NDS_ARM9.R[15]==0x0202B3DC) emu_halt(); //if((NDS_ARM9.R[1]==0x9AC29AC1)&&(!fait)) {emu_halt();fait = TRUE;} //if(NDS_ARM9.R[1]==0x0400004A) {emu_halt();fait = TRUE;} /*if(NDS_ARM9.R[4]==0x2E33373C) emu_halt(); if(NDS_ARM9.R[15]==0x02036668) //emu_halt(); { nds.logcount++; sprintf(logbuf, "%d %08X", nds.logcount, NDS_ARM9.R[13]); log::ajouter(logbuf); if(nds.logcount==89) execute=FALSE; }*/ //if(NDS_ARM9.instruction==0) emu_halt(); //if((NDS_ARM9.R[15]>>28)) emu_halt(); } #endif RomBanner::RomBanner(bool defaultInit) { if(!defaultInit) return; version = 1; //Version (0001h) crc16 = 0; //CRC16 across entries 020h..83Fh memset(reserved,0,sizeof(reserved)); memset(bitmap,0,sizeof(bitmap)); memset(palette,0,sizeof(palette)); memset(titles,0,sizeof(titles)); memset(end0xFF,0,sizeof(end0xFF)); } bool GameInfo::hasRomBanner() { if(header.IconOff + sizeof(RomBanner) > romsize) return false; else return true; } const RomBanner& GameInfo::getRomBanner() { return banner; } void GameInfo::populate() { const char regions_index[] = "JPFSEODIRKHXVWUC"; const char *regions[] = { "???", "JPN", // J "EUR", // P "FRA", // F "ESP", // S "USA", // E "INT", // O "NOE", // D "ITA", // I "RUS", // R "KOR", // K "HOL", // H "EUU", // X "EUU", // V "EUU", // W "AUS", // U "CHN", // C }; memset(ROMserial, 0, sizeof(ROMserial)); memset(ROMname, 0, sizeof(ROMname)); if(isHomebrew()) { //we can't really make a serial for a homebrew game that hasnt set a game code strcpy(ROMserial, "Homebrew"); } else { if (isDSiEnhanced()) strcpy(ROMserial,"TWL- -"); else strcpy(ROMserial,"NTR- -"); memcpy(ROMserial+4, header.gameCode, 4); u32 regions_num = ARRAY_SIZE(regions); u32 region = (u32)(std::max(strchr(regions_index,header.gameCode[3]) - regions_index + 1, 0)); if (region < regions_num) strcat(ROMserial, regions[region]); else strcat(ROMserial, "???"); } //rom name is probably set even in homebrew, so do it regardless memset(ROMname, 0, sizeof(ROMname)); memcpy(ROMname, header.gameTile, 12); string_trim_whitespace(ROMname); /*if(header.IconOff < romsize) { u8 num = (T1ReadByte((u8*)romdata, header.IconOff) == 1)?6:7; for (int i = 0; i < num; i++) { wcstombs(ROMfullName[i], (wchar_t *)(romdata+header.IconOff+0x240+(i*0x100)), 0x100); trim(ROMfullName[i]); } }*/ } bool GameInfo::loadROM(std::string fname, u32 type) { //printf("ROM %s\n", CommonSettings.loadToMemory?"loaded to RAM":"stream from disk"); closeROM(); fROM = fopen(fname.c_str(), "rb"); if (!fROM) return false; headerOffset = (type == ROM_DSGBA)?DSGBA_LOADER_SIZE:0; fseek(fROM, 0, SEEK_END); romsize = ftell(fROM) - headerOffset; fseek(fROM, headerOffset, SEEK_SET); bool res = (fread(&header, 1, sizeof(header), fROM) == sizeof(header)); if (res) { #ifdef MSB_FIRST //endian swap necessary fields. It would be better if we made accessors for these. I wonder if you could make a macro for a field accessor that would take the bitsize and do the swap on the fly struct FieldSwap { const size_t offset; const size_t bytes; }; static const FieldSwap fieldSwaps[] = { { offsetof(NDS_header,makerCode), 2}, { offsetof(NDS_header,ARM9src), 4}, { offsetof(NDS_header,ARM9exe), 4}, { offsetof(NDS_header,ARM9cpy), 4}, { offsetof(NDS_header,ARM9binSize), 4}, { offsetof(NDS_header,ARM7src), 4}, { offsetof(NDS_header,ARM7exe), 4}, { offsetof(NDS_header,ARM7cpy), 4}, { offsetof(NDS_header,ARM7binSize), 4}, { offsetof(NDS_header,FNameTblOff), 4}, { offsetof(NDS_header,FNameTblSize), 4}, { offsetof(NDS_header,FATOff), 4}, { offsetof(NDS_header,FATSize), 4}, { offsetof(NDS_header,ARM9OverlayOff), 4}, { offsetof(NDS_header,ARM9OverlaySize), 4}, { offsetof(NDS_header,ARM7OverlayOff), 4}, { offsetof(NDS_header,ARM7OverlaySize), 4}, { offsetof(NDS_header,normalCmd), 4}, { offsetof(NDS_header,Key1Cmd), 4}, { offsetof(NDS_header,IconOff), 4}, { offsetof(NDS_header,CRC16), 2}, { offsetof(NDS_header,ROMtimeout), 2}, { offsetof(NDS_header,ARM9autoload), 4}, { offsetof(NDS_header,ARM7autoload), 4}, { offsetof(NDS_header,endROMoffset), 4}, { offsetof(NDS_header,HeaderSize), 4}, { offsetof(NDS_header, ARM9module), 4}, { offsetof(NDS_header, ARM7module), 4}, { offsetof(NDS_header,logoCRC16), 2}, { offsetof(NDS_header,headerCRC16), 2}, }; for(size_t i = 0; i < ARRAY_SIZE(fieldSwaps); i++) { const u8 *fieldAddr = (u8 *)&header + fieldSwaps[i].offset; switch(fieldSwaps[i].bytes) { case 2: *(u16 *)fieldAddr = LE_TO_LOCAL_16(*(u16 *)fieldAddr); break; case 4: *(u32 *)fieldAddr = LE_TO_LOCAL_32(*(u32 *)fieldAddr); break; } } #endif cardSize = (128 * 1024) << header.cardSize; if (cardSize < romsize) { msgbox->warn("The ROM header is invalid.\nThe device size has been increased to allow for the provided file size.\n"); for (u32 i = header.cardSize; i < 0xF; i++) { if (((128 * 1024) << i) >= romsize) { header.cardSize = i; cardSize = (128 * 1024) << i; break; } } } mask = (cardSize - 1); mask |= (mask >>1); mask |= (mask >>2); mask |= (mask >>4); mask |= (mask >>8); mask |= (mask >>16); if (type == ROM_NDS) { size_t elements_read; fseek(fROM, 0x4000 + headerOffset, SEEK_SET); elements_read = fread(&secureArea[0], 1, 0x4000, fROM); if (elements_read != 0x4000) printf("Unexpectedly short post-header bit.\n"); } if (CommonSettings.loadToMemory) { fseek(fROM, headerOffset, SEEK_SET); romdata = new u8[romsize + 4]; if (fread(romdata, 1, romsize, fROM) != romsize) { delete [] romdata; romdata = NULL; romsize = 0; return false; } if(hasRomBanner()) { memcpy(&banner, romdata + header.IconOff, sizeof(RomBanner)); banner.version = LE_TO_LOCAL_16(banner.version); banner.crc16 = LE_TO_LOCAL_16(banner.crc16); for(size_t i = 0; i < ARRAY_SIZE(banner.palette); i++) { banner.palette[i] = LE_TO_LOCAL_16(banner.palette[i]); } } _isDSiEnhanced = (LE_TO_LOCAL_32(*(u32*)(romdata + 0x180) == 0x8D898581U) && LE_TO_LOCAL_32(*(u32*)(romdata + 0x184) == 0x8C888480U)); fclose(fROM); fROM = NULL; return true; } _isDSiEnhanced = ((readROM(0x180) == 0x8D898581U) && (readROM(0x184) == 0x8C888480U)); if (hasRomBanner()) { size_t elements_read; const size_t elements_to_read = sizeof(RomBanner); fseek(fROM, header.IconOff + headerOffset, SEEK_SET); elements_read = fread(&banner, 1, elements_to_read, fROM); if (elements_read != elements_to_read) printf("Unexpectedly short post-header bit.\n"); banner.version = LE_TO_LOCAL_16(banner.version); banner.crc16 = LE_TO_LOCAL_16(banner.crc16); for(size_t i = 0; i < ARRAY_SIZE(banner.palette); i++) { banner.palette[i] = LE_TO_LOCAL_16(banner.palette[i]); } } fseek(fROM, headerOffset, SEEK_SET); lastReadPos = 0; return true; } romsize = 0; fclose(fROM); fROM = NULL; return false; } void GameInfo::closeROM() { if (fROM) fclose(fROM); if (romdata) delete [] romdata; fROM = NULL; romdata = NULL; romsize = 0; lastReadPos = 0xFFFFFFFF; } u32 GameInfo::readROM(u32 pos) { if (!romdata) { u32 data; if (lastReadPos != pos) fseek(fROM, pos + headerOffset, SEEK_SET); u32 num = fread(&data, 1, 4, fROM); lastReadPos = (pos + num); return LE_TO_LOCAL_32(data); } else { if(pos + 4 > romsize) { printf("Panic! GameInfo reading out of buffer!\n"); exit(-1); } return LE_TO_LOCAL_32(*(u32*)(romdata + pos)); } } bool GameInfo::isDSiEnhanced() { return _isDSiEnhanced; } bool GameInfo::isHomebrew() { return ((header.ARM9src < 0x4000) && (T1ReadLong(header.logo, 0) != 0x51AEFF24) && (T1ReadLong(header.logo, 4) != 0x699AA221)); } static int rom_init_path(const char *filename, const char *physicalName, const char *logicalFilename) { u32 type = ROM_NDS; path.init(logicalFilename? logicalFilename : filename); if ( path.isdsgba(path.path)) { type = ROM_DSGBA; gameInfo.loadROM(path.path, type); } else if ( !strcasecmp(path.extension().c_str(), "nds")) { type = ROM_NDS; gameInfo.loadROM(physicalName ? physicalName : path.path, type); //n.b. this does nothing if the file can't be found (i.e. if it was an extracted tempfile)... //...but since the data was extracted to gameInfo then it is ok } //ds.gba in archives, it's already been loaded into memory at this point else if (logicalFilename && path.isdsgba(std::string(logicalFilename))) { type = ROM_DSGBA; } else { //well, try to load it as an nds rom anyway type = ROM_NDS; gameInfo.loadROM(physicalName ? physicalName : path.path, type); } //check that size is at least the size of the header if (gameInfo.romsize < 352) { return -1; } gameInfo.romType = type; return 1; } int NDS_LoadROM(const char *filename, const char *physicalName, const char *logicalFilename) { int ret; char buf[PATH_MAX_LENGTH]; if (filename == NULL) return -1; ret = rom_init_path(filename, physicalName, logicalFilename); if (ret < 1) return ret; //check whether this rom is any kind of valid if(!CheckValidRom((u8*)&gameInfo.header, gameInfo.secureArea)) { printf("Specified file is not a valid rom\n"); return -1; } gameInfo.populate(); if (CommonSettings.loadToMemory) gameInfo.crc = crc32(0, (u8*)gameInfo.romdata, gameInfo.romsize); else gameInfo.crc = 0; gameInfo.chipID = 0xC2; // The Manufacturer ID is defined by JEDEC (C2h = Macronix) if (!gameInfo.isHomebrew()) { gameInfo.chipID |= ((((128 << gameInfo.header.cardSize) / 1024) - 1) << 8); // Chip size in megabytes minus 1 // (07h = 8MB, 0Fh = 16MB, 1Fh = 32MB, 3Fh = 64MB, 7Fh = 128MB) // flags // 0: Unknown // 1: Unknown // 2: Unknown // 3: Unknown // 4: Unknown // 5: DSi? (if set to 1 then DSi Enhanced games send command D6h to Slot1) // 6: Unknown // 7: ROM speed (Secure Area Block transfer mode (trasfer 8x200h or 1000h bytes) // TODO: //if (gameInfo.isDSiEnhanced()) // gameInfo.chipID |= (0x40 << 24); gameInfo.chipID |= (0x00 << 24); } #ifdef DEBUG INFO("\nROM game code: %c%c%c%c\n", gameInfo.header.gameCode[0], gameInfo.header.gameCode[1], gameInfo.header.gameCode[2], gameInfo.header.gameCode[3]); if (gameInfo.crc) INFO("ROM crc: %08X\n", gameInfo.crc); if (!gameInfo.isHomebrew()) { INFO("ROM serial: %s\n", gameInfo.ROMserial); INFO("ROM chipID: %08X\n", gameInfo.chipID); INFO("ROM internal name: %s\n", gameInfo.ROMname); if (gameInfo.isDSiEnhanced()) INFO("ROM DSi Enhanced\n"); } INFO("ROM developer: %s\n", ((gameInfo.header.makerCode == 0) && gameInfo.isHomebrew()) ? "Homebrew" : getDeveloperNameByID(gameInfo.header.makerCode)); #endif buf[0] = gameInfo.header.gameCode[0]; buf[1] = gameInfo.header.gameCode[1]; buf[2] = gameInfo.header.gameCode[2]; buf[3] = gameInfo.header.gameCode[3]; buf[4] = 0; if (advsc.checkDB(buf, gameInfo.crc)) { u8 sv = advsc.getSaveType(); printf("Found in game database by %s:\n", advsc.getIdMethod()); printf("\t* ROM serial:\t\t%s\n", advsc.getSerial()); printf("\t* ROM save type:\t"); if (sv == 0xFF) printf("Unknown"); else if (sv == 0xFE) printf("None"); else { printf("%s", save_types[sv + 1].descr); if (CommonSettings.autodetectBackupMethod == 1) backup_setManualBackupType(sv + 1); } printf("\n\t* ROM crc:\t\t%08X\n", advsc.getCRC32()); } printf("\n"); //for homebrew, try auto-patching DLDI. should be benign if there is no DLDI or if it fails if(gameInfo.isHomebrew()) { if(!CommonSettings.loadToMemory) msgbox->warn("Sorry.. right now, you can't use the default (stream rom from disk) with homebrew due to a bug with DLDI-autopatching"); if (slot1_GetCurrentType() == NDS_SLOT1_R4) DLDI_tryPatch((void*)gameInfo.romdata, gameInfo.romsize, 1); else if (slot2_GetCurrentType() == NDS_SLOT2_CFLASH) DLDI_tryPatch((void*)gameInfo.romdata, gameInfo.romsize, 0); } if (cheats != NULL) { memset(buf, 0, sizeof(buf)); path.getpathnoext(path.CHEATS, buf); strcat(buf, ".dct"); // DeSmuME cheat :) cheats->init(buf); } NDS_Reset(); return ret; } void NDS_FreeROM(void) { gameInfo.closeROM(); } void NDS_Sleep() { nds.sleeping = TRUE; } void NDS_TriggerCardEjectIRQ() { NDS_makeIrq(ARMCPU_ARM7, IRQ_BIT_GC_IREQ_MC); NDS_makeIrq(ARMCPU_ARM9, IRQ_BIT_GC_IREQ_MC); //zero added on 11-aug-2013 with no proof of accuracy } class FrameSkipper { public: void RequestSkip() { nextSkip = true; } void OmitSkip(bool force, bool forceEvenIfCapturing=false) { nextSkip = false; if((force && consecutiveNonCaptures > 30) || forceEvenIfCapturing) { SkipCur2DFrame = false; SkipCur3DFrame = false; SkipNext2DFrame = false; if(forceEvenIfCapturing) consecutiveNonCaptures = 0; } } void Advance() { const GPUEngineA *mainEngine = GPU->GetEngineMain(); bool capturing = (mainEngine->dispCapCnt.enabled || (mainEngine->dispCapCnt.val & 0x80000000)); if(capturing && consecutiveNonCaptures > 30) { // the worst-looking graphics corruption problems from frameskip // are the result of skipping the capture on first frame it turns on. // so we do this to handle the capture immediately, // despite the risk of 1 frame of 2d/3d mismatch or wrong screen display. SkipNext2DFrame = false; nextSkip = false; } else if((lastDisplayTarget != mainEngine->GetDisplayByID()) && lastSkip && !skipped) { // if we're switching from not skipping to skipping // and the screens are also switching around this frame, // go for 1 extra frame without skipping. // this avoids the scenario where we only draw one of the two screens // when a game is switching screens every frame. nextSkip = false; } if(capturing) consecutiveNonCaptures = 0; else if(!(consecutiveNonCaptures > 9000)) // arbitrary cap to avoid eventual wrap consecutiveNonCaptures++; lastDisplayTarget = mainEngine->GetDisplayByID(); lastSkip = skipped; skipped = nextSkip; nextSkip = false; SkipCur2DFrame = SkipNext2DFrame; SkipCur3DFrame = skipped; SkipNext2DFrame = skipped; } FORCEINLINE bool ShouldSkip2D() { return SkipCur2DFrame; } FORCEINLINE bool ShouldSkip3D() { return SkipCur3DFrame; } FrameSkipper() { nextSkip = false; skipped = false; lastSkip = false; lastDisplayTarget = NDSDisplayID_Main; SkipCur2DFrame = false; SkipCur3DFrame = false; SkipNext2DFrame = false; consecutiveNonCaptures = 0; } private: bool nextSkip; bool skipped; bool lastSkip; NDSDisplayID lastDisplayTarget; int consecutiveNonCaptures; bool SkipCur2DFrame; bool SkipCur3DFrame; bool SkipNext2DFrame; }; static FrameSkipper frameSkipper; void NDS_SkipNextFrame() { frameSkipper.RequestSkip(); } void NDS_OmitFrameSkip(int force) { frameSkipper.OmitSkip(force > 0, force > 1); } #define INDEX(i) ((((i)>>16)&0xFF0)|(((i)>>4)&0xF)) enum ESI_DISPCNT { ESI_DISPCNT_HStart, ESI_DISPCNT_HStartIRQ, ESI_DISPCNT_HDraw, ESI_DISPCNT_HBlank }; u64 nds_timer; u64 nds_arm9_timer, nds_arm7_timer; static const u64 kNever = 0xFFFFFFFFFFFFFFFFULL; struct TSequenceItem { u64 timestamp; u32 param; bool enabled; virtual void save(EMUFILE* os) { write64le(timestamp,os); write32le(param,os); writebool(enabled,os); } virtual bool load(EMUFILE* is) { if(read64le(×tamp,is) != 1) return false; if(read32le(¶m,is) != 1) return false; if(readbool(&enabled,is) != 1) return false; return true; } FORCEINLINE bool isTriggered() { return enabled && nds_timer >= timestamp; } FORCEINLINE u64 next() { return timestamp; } }; struct TSequenceItem_GXFIFO : public TSequenceItem { FORCEINLINE bool isTriggered() { return enabled && nds_timer >= MMU.gfx3dCycles; } FORCEINLINE void exec() { #ifndef NDEBUG IF_DEVELOPER(DEBUG_statistics.sequencerExecutionCounters[4]++); #endif while(isTriggered()) { enabled = false; gfx3d_execute3D(); } } FORCEINLINE u64 next() { if(enabled) return MMU.gfx3dCycles; else return kNever; } }; template struct TSequenceItem_Timer : public TSequenceItem { FORCEINLINE bool isTriggered() { return enabled && nds_timer >= nds.timerCycle[procnum][num]; } FORCEINLINE void schedule() { enabled = MMU.timerON[procnum][num] && MMU.timerMODE[procnum][num] != 0xFFFF; } FORCEINLINE u64 next() { return nds.timerCycle[procnum][num]; } FORCEINLINE void exec() { #ifndef NDEBUG IF_DEVELOPER(DEBUG_statistics.sequencerExecutionCounters[13+procnum*4+num]++); #endif u8* regs = procnum==0?MMU.ARM9_REG:MMU.ARM7_REG; bool first = true; //we'll need to check chained timers.. for(int i=num;i<4;i++) { bool over = false; //maybe too many checks if this is here, but we need it here for now if(!MMU.timerON[procnum][i]) return; if(MMU.timerMODE[procnum][i] == 0xFFFF) { ++(MMU.timer[procnum][i]); over = !MMU.timer[procnum][i]; } else { if(!first) break; //this timer isn't chained. break the chain first = false; over = true; int remain = 65536 - MMU.timerReload[procnum][i]; int ctr=0; while(nds.timerCycle[procnum][i] <= nds_timer) { nds.timerCycle[procnum][i] += (remain << MMU.timerMODE[procnum][i]); ctr++; } #ifndef NDEBUG if(ctr>1) { printf("yikes!!!!! please report!\n"); } #endif } if(over) { MMU.timer[procnum][i] = MMU.timerReload[procnum][i]; if(T1ReadWord(regs, 0x102 + i*4) & 0x40) { NDS_makeIrq(procnum, IRQ_BIT_TIMER_0 + i); } } else break; //no more chained timers to trigger. we're done here } } }; template struct TSequenceItem_DMA : public TSequenceItem { DmaController* controller; FORCEINLINE bool isTriggered() { return (controller->dmaCheck && nds_timer>= controller->nextEvent); } FORCEINLINE bool isEnabled() { return controller->dmaCheck?TRUE:FALSE; } FORCEINLINE u64 next() { return controller->nextEvent; } FORCEINLINE void exec() { #ifndef NDEBUG IF_DEVELOPER(DEBUG_statistics.sequencerExecutionCounters[5+procnum*4+chan]++); #endif //if (nds.freezeBus) return; //printf("exec from TSequenceItem_DMA: %d %d\n",procnum,chan); controller->exec(); // //give gxfifo dmas a chance to re-trigger // if(MMU.DMAStartTime[procnum][chan] == EDMAMode_GXFifo) { // MMU.DMAing[procnum][chan] = FALSE; // if (gxFIFO.size <= 127) // { // execHardware_doDma(procnum,chan,EDMAMode_GXFifo); // if (MMU.DMACompleted[procnum][chan]) // goto docomplete; // else return; // } // } // //docomplete: // if (MMU.DMACompleted[procnum][chan]) // { // u8* regs = procnum==0?MMU.ARM9_REG:MMU.ARM7_REG; // // //disable the channel // if(MMU.DMAStartTime[procnum][chan] != EDMAMode_GXFifo) { // T1WriteLong(regs, 0xB8 + (0xC*chan), T1ReadLong(regs, 0xB8 + (0xC*chan)) & 0x7FFFFFFF); // MMU.DMACrt[procnum][chan] &= 0x7FFFFFFF; //blehhh i hate this shit being mirrored in memory // } // // if((MMU.DMACrt[procnum][chan])&(1<<30)) { // if(procnum==0) NDS_makeARM9Int(8+chan); // else NDS_makeARM7Int(8+chan); // } // // MMU.DMAing[procnum][chan] = FALSE; // } } }; struct TSequenceItem_divider : public TSequenceItem { FORCEINLINE bool isTriggered() { return MMU.divRunning && nds_timer >= MMU.divCycles; } bool isEnabled() { return MMU.divRunning!=0; } FORCEINLINE u64 next() { return MMU.divCycles; } void exec() { #ifndef NDEBUG IF_DEVELOPER(DEBUG_statistics.sequencerExecutionCounters[2]++); #endif MMU_new.div.busy = 0; #ifdef HOST_64 T1WriteQuad(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x2A0, MMU.divResult); T1WriteQuad(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x2A8, MMU.divMod); #else T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x2A0, (u32)MMU.divResult); T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x2A4, (u32)(MMU.divResult >> 32)); T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x2A8, (u32)MMU.divMod); T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x2AC, (u32)(MMU.divMod >> 32)); #endif MMU.divRunning = FALSE; } }; struct TSequenceItem_sqrtunit : public TSequenceItem { FORCEINLINE bool isTriggered() { return MMU.sqrtRunning && nds_timer >= MMU.sqrtCycles; } bool isEnabled() { return MMU.sqrtRunning!=0; } FORCEINLINE u64 next() { return MMU.sqrtCycles; } FORCEINLINE void exec() { #ifndef NDEBUG IF_DEVELOPER(DEBUG_statistics.sequencerExecutionCounters[3]++); #endif MMU_new.sqrt.busy = 0; T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x2B4, MMU.sqrtResult); MMU.sqrtRunning = FALSE; } }; struct Sequencer { bool nds_vblankEnded; bool reschedule; TSequenceItem dispcnt; TSequenceItem wifi; TSequenceItem_divider divider; TSequenceItem_sqrtunit sqrtunit; TSequenceItem_GXFIFO gxfifo; TSequenceItem_DMA<0,0> dma_0_0; TSequenceItem_DMA<0,1> dma_0_1; TSequenceItem_DMA<0,2> dma_0_2; TSequenceItem_DMA<0,3> dma_0_3; TSequenceItem_DMA<1,0> dma_1_0; TSequenceItem_DMA<1,1> dma_1_1; TSequenceItem_DMA<1,2> dma_1_2; TSequenceItem_DMA<1,3> dma_1_3; TSequenceItem_Timer<0,0> timer_0_0; TSequenceItem_Timer<0,1> timer_0_1; TSequenceItem_Timer<0,2> timer_0_2; TSequenceItem_Timer<0,3> timer_0_3; TSequenceItem_Timer<1,0> timer_1_0; TSequenceItem_Timer<1,1> timer_1_1; TSequenceItem_Timer<1,2> timer_1_2; TSequenceItem_Timer<1,3> timer_1_3; void init(); void execHardware(); u64 findNext(); void save(EMUFILE* os) { write64le(nds_timer,os); write64le(nds_arm9_timer,os); write64le(nds_arm7_timer,os); dispcnt.save(os); divider.save(os); sqrtunit.save(os); gxfifo.save(os); wifi.save(os); #define SAVE(I,X,Y) I##_##X##_##Y .save(os); SAVE(timer,0,0); SAVE(timer,0,1); SAVE(timer,0,2); SAVE(timer,0,3); SAVE(timer,1,0); SAVE(timer,1,1); SAVE(timer,1,2); SAVE(timer,1,3); SAVE(dma,0,0); SAVE(dma,0,1); SAVE(dma,0,2); SAVE(dma,0,3); SAVE(dma,1,0); SAVE(dma,1,1); SAVE(dma,1,2); SAVE(dma,1,3); #undef SAVE } bool load(EMUFILE* is, int version) { if(read64le(&nds_timer,is) != 1) return false; if(read64le(&nds_arm9_timer,is) != 1) return false; if(read64le(&nds_arm7_timer,is) != 1) return false; if(!dispcnt.load(is)) return false; if(!divider.load(is)) return false; if(!sqrtunit.load(is)) return false; if(!gxfifo.load(is)) return false; if(version >= 1) if(!wifi.load(is)) return false; #define LOAD(I,X,Y) if(!I##_##X##_##Y .load(is)) return false; LOAD(timer,0,0); LOAD(timer,0,1); LOAD(timer,0,2); LOAD(timer,0,3); LOAD(timer,1,0); LOAD(timer,1,1); LOAD(timer,1,2); LOAD(timer,1,3); LOAD(dma,0,0); LOAD(dma,0,1); LOAD(dma,0,2); LOAD(dma,0,3); LOAD(dma,1,0); LOAD(dma,1,1); LOAD(dma,1,2); LOAD(dma,1,3); #undef LOAD return true; } } sequencer; void NDS_RescheduleGXFIFO(u32 cost) { if(!sequencer.gxfifo.enabled) { MMU.gfx3dCycles = nds_timer; sequencer.gxfifo.enabled = true; } MMU.gfx3dCycles += cost; NDS_Reschedule(); } void NDS_RescheduleTimers() { #define check(X,Y) sequencer.timer_##X##_##Y .schedule(); check(0,0); check(0,1); check(0,2); check(0,3); check(1,0); check(1,1); check(1,2); check(1,3); #undef check NDS_Reschedule(); } void NDS_RescheduleDMA() { //TBD NDS_Reschedule(); } static void initSchedule() { sequencer.init(); //begin at the very end of the last scanline //so that at t=0 we can increment to scanline=0 nds.VCount = 262; sequencer.nds_vblankEnded = false; } // 2196372 ~= (ARM7_CLOCK << 16) / 1000000 // This value makes more sense to me, because: // ARM7_CLOCK = 33.51 mhz // = 33513982 cycles per second // = 33.513982 cycles per microsecond const u64 kWifiCycles = 67;//34*2; //(this isn't very precise. I don't think it needs to be) void Sequencer::init() { NDS_RescheduleTimers(); NDS_RescheduleDMA(); reschedule = false; nds_timer = 0; nds_arm9_timer = 0; nds_arm7_timer = 0; dispcnt.enabled = true; dispcnt.param = ESI_DISPCNT_HStart; dispcnt.timestamp = 0; gxfifo.enabled = false; dma_0_0.controller = &MMU_new.dma[0][0]; dma_0_1.controller = &MMU_new.dma[0][1]; dma_0_2.controller = &MMU_new.dma[0][2]; dma_0_3.controller = &MMU_new.dma[0][3]; dma_1_0.controller = &MMU_new.dma[1][0]; dma_1_1.controller = &MMU_new.dma[1][1]; dma_1_2.controller = &MMU_new.dma[1][2]; dma_1_3.controller = &MMU_new.dma[1][3]; #ifdef EXPERIMENTAL_WIFI_COMM wifi.enabled = true; wifi.timestamp = kWifiCycles; #else wifi.enabled = false; #endif } static void execHardware_hblank() { //this logic keeps moving around. //now, we try and give the game as much time as possible to finish doing its work for the scanline, //by drawing scanline N at the end of drawing time (but before subsequent interrupt or hdma-driven events happen) //don't try to do this at the end of the scanline, because some games (sonic classics) may use hblank IRQ to set //scroll regs for the next scanline if(nds.VCount<192) { GPU->RenderLine(nds.VCount, frameSkipper.ShouldSkip2D()); //trigger hblank dmas //but notice, we do that just after we finished drawing the line //(values copied by this hdma should not be used until the next scanline) triggerDma(EDMAMode_HBlank); } #if 0 if(nds.VCount==262) { //we need to trigger one last hblank dma since //a. we're sort of lagged behind by one scanline //b. i think that 193 hblanks actually fire (one for the hblank in scanline 262) //this is demonstrated by NSMB splot-parallaxing clouds //for some reason the game will setup two hdma scroll register buffers //to be run consecutively, and unless we do this, the second buffer will be offset by one scanline //causing a glitch in the 0th scanline //triggerDma(EDMAMode_HBlank); //BUT! this was removed in order to make glitches in megaman zero collection (mmz 4 1st level) work. //and, it seems that it is no longer necessary in nsmb. perhaps something else fixed it } #endif //turn on hblank status bit T1WriteWord(MMU.ARM9_REG, 4, T1ReadWord(MMU.ARM9_REG, 4) | 2); T1WriteWord(MMU.ARM7_REG, 4, T1ReadWord(MMU.ARM7_REG, 4) | 2); //fire hblank interrupts if necessary if(T1ReadWord(MMU.ARM9_REG, 4) & 0x10) NDS_makeIrq(ARMCPU_ARM9,IRQ_BIT_LCD_HBLANK); if(T1ReadWord(MMU.ARM7_REG, 4) & 0x10) NDS_makeIrq(ARMCPU_ARM7,IRQ_BIT_LCD_HBLANK); //emulation housekeeping. for some reason we always do this at hblank, //even though it sounds more reasonable to do it at hstart SPU_Emulate_core(); } static void execHardware_hstart_vblankEnd() { sequencer.nds_vblankEnded = true; sequencer.reschedule = true; //turn off vblank status bit T1WriteWord(MMU.ARM9_REG, 4, T1ReadWord(MMU.ARM9_REG, 4) & ~1); T1WriteWord(MMU.ARM7_REG, 4, T1ReadWord(MMU.ARM7_REG, 4) & ~1); //some emulation housekeeping frameSkipper.Advance(); if (GPU->GetWillAutoBlitNativeToCustomBuffer()) { GPU->GetEngineMain()->BlitNativeToCustomFramebuffer(); GPU->GetEngineSub()->BlitNativeToCustomFramebuffer(); } } static void execHardware_hstart_vblankStart() { //printf("--------VBLANK!!!--------\n"); //fire vblank interrupts if necessary for(int i=0;i<2;i++) if(MMU.reg_IF_pending[i] & (1<>8)|((vmatch<<1)&(1<<8))); return vmatch; } static void execHardware_hstart_vcount_irq() { //trigger pending VMATCH irqs if(MMU.reg_IF_pending[ARMCPU_ARM9] & (1<>8)|((vmatch<<1)&(1<<8))); if(nds.VCount==vmatch) { //arm7 vmatch T1WriteWord(MMU.ARM7_REG, 4, T1ReadWord(MMU.ARM7_REG, 4) | 4); if(T1ReadWord(MMU.ARM7_REG, 4) & 32) MMU.reg_IF_pending[ARMCPU_ARM7] |= (1<> (32-1)) & (c^d)) ^ d); } FORCEINLINE u64 _fast_min(u64 a, u64 b) { //you might find that this is faster on a 64bit system; someone should try it //http://aggregate.org/MAGIC/#Integer%20Selection //u64 ret = (((((s64)(a-b)) >> (64-1)) & (a^b)) ^ b); //assert(ret==min(a,b)); //return ret; //but this ends up being the fastest on 32bits return a>= 63; //no 64bit shra in sse2, what a disappointment //temp = _mm_and_si128(temp,xorval); //temp = _mm_xor_si128(temp,__b); //return temp.m128i_u64[0]; } u64 Sequencer::findNext() { //this one is always enabled so dont bother to check it u64 next = dispcnt.next(); if(divider.isEnabled()) next = _fast_min(next,divider.next()); if(sqrtunit.isEnabled()) next = _fast_min(next,sqrtunit.next()); if(gxfifo.enabled) next = _fast_min(next,gxfifo.next()); #ifdef EXPERIMENTAL_WIFI_COMM next = _fast_min(next,wifi.next()); #endif #define test(X,Y) if(dma_##X##_##Y .isEnabled()) next = _fast_min(next,dma_##X##_##Y .next()); test(0,0); test(0,1); test(0,2); test(0,3); test(1,0); test(1,1); test(1,2); test(1,3); #undef test #define test(X,Y) if(timer_##X##_##Y .enabled) next = _fast_min(next,timer_##X##_##Y .next()); test(0,0); test(0,1); test(0,2); test(0,3); test(1,0); test(1,1); test(1,2); test(1,3); #undef test return next; } void Sequencer::execHardware() { if(dispcnt.isTriggered()) { #ifndef NDEBUG IF_DEVELOPER(DEBUG_statistics.sequencerExecutionCounters[1]++); #endif switch(dispcnt.param) { case ESI_DISPCNT_HStart: execHardware_hstart(); //(used to be 3168) //hstart is actually 8 dots before the visible drawing begins //we're going to run 1 here and then run 7 in the next case dispcnt.timestamp += 1*6*2; dispcnt.param = ESI_DISPCNT_HStartIRQ; break; case ESI_DISPCNT_HStartIRQ: execHardware_hstart_irq(); dispcnt.timestamp += 7*6*2; dispcnt.param = ESI_DISPCNT_HDraw; break; case ESI_DISPCNT_HDraw: //execHardware_hdraw(); //duration of non-blanking period is ~1606 clocks (gbatek agrees) [but says its different on arm7] //im gonna call this 267 dots = 267*6=1602 //so, this event lasts 267 dots minus the 8 dot preroll dispcnt.timestamp += (267-8)*6*2; dispcnt.param = ESI_DISPCNT_HBlank; break; case ESI_DISPCNT_HBlank: execHardware_hblank(); //(once this was 1092 or 1092/12=91 dots.) //there are surely 355 dots per scanline, less 267 for non-blanking period. the rest is hblank and then after that is hstart dispcnt.timestamp += (355-267)*6*2; dispcnt.param = ESI_DISPCNT_HStart; break; } } #ifdef EXPERIMENTAL_WIFI_COMM if(wifi.isTriggered()) { WIFI_usTrigger(); wifi.timestamp += kWifiCycles; } #endif if(divider.isTriggered()) divider.exec(); if(sqrtunit.isTriggered()) sqrtunit.exec(); if(gxfifo.isTriggered()) gxfifo.exec(); #define test(X,Y) if(dma_##X##_##Y .isTriggered()) dma_##X##_##Y .exec(); test(0,0); test(0,1); test(0,2); test(0,3); test(1,0); test(1,1); test(1,2); test(1,3); #undef test #define test(X,Y) if(timer_##X##_##Y .enabled) if(timer_##X##_##Y .isTriggered()) timer_##X##_##Y .exec(); test(0,0); test(0,1); test(0,2); test(0,3); test(1,0); test(1,1); test(1,2); test(1,3); #undef test } void execHardware_interrupts(); static void saveUserInput(EMUFILE* os); static bool loadUserInput(EMUFILE* is, int version); void nds_savestate(EMUFILE* os) { //version write32le(3,os); sequencer.save(os); saveUserInput(os); write32le(LidClosed,os); write8le(countLid,os); } bool nds_loadstate(EMUFILE* is, int size) { // this isn't part of the savestate loading logic, but // don't skip the next frame after loading a savestate frameSkipper.OmitSkip(true, true); //read version u32 version; if(read32le(&version,is) != 1) return false; if(version > 3) return false; bool temp = true; temp &= sequencer.load(is, version); if(version <= 1 || !temp) return temp; temp &= loadUserInput(is, version); if(version < 3) return temp; read32le(&LidClosed,is); read8le(&countLid,is); return temp; } #ifdef LOG_ARM9 FORCEINLINE void arm9log() { if(dolog) { char dasmbuf[4096]; if(NDS_ARM9.CPSR.bits.T) des_thumb_instructions_set[((NDS_ARM9.instruction)>>6)&1023](NDS_ARM9.instruct_adr, NDS_ARM9.instruction, dasmbuf); else des_arm_instructions_set[INDEX(NDS_ARM9.instruction)](NDS_ARM9.instruct_adr, NDS_ARM9.instruction, dasmbuf); #ifdef LOG_TO_FILE if (!fp_dis9) return; #ifdef LOG_TO_FILE_REGS fprintf(fp_dis9, "\t\t;%05d:%03d %12lld\n\t\t;R0:%08X R1:%08X R2:%08X R3:%08X R4:%08X R5:%08X R6:%08X R7:%08X R8:%08X R9:%08X\n\t\t;R10:%08X R11:%08X R12:%08X R13:%08X R14:%08X R15:%08X| next %08X, N:%i Z:%i C:%i V:%i\n", currFrameCounter, nds.VCount, nds_timer, NDS_ARM9.R[0], NDS_ARM9.R[1], NDS_ARM9.R[2], NDS_ARM9.R[3], NDS_ARM9.R[4], NDS_ARM9.R[5], NDS_ARM9.R[6], NDS_ARM9.R[7], NDS_ARM9.R[8], NDS_ARM9.R[9], NDS_ARM9.R[10], NDS_ARM9.R[11], NDS_ARM9.R[12], NDS_ARM9.R[13], NDS_ARM9.R[14], NDS_ARM9.R[15], NDS_ARM9.next_instruction, NDS_ARM9.CPSR.bits.N, NDS_ARM9.CPSR.bits.Z, NDS_ARM9.CPSR.bits.C, NDS_ARM9.CPSR.bits.V); #endif fprintf(fp_dis9, "%s %08X\t%08X \t%s\n", NDS_ARM9.CPSR.bits.T?"THUMB":"ARM", NDS_ARM9.instruct_adr, NDS_ARM9.instruction, dasmbuf); /*if (NDS_ARM9.instruction == 0) { dolog = false; INFO("Disassembler is stopped\n"); }*/ #else printf("%05d:%03d %12lld 9:%08X %08X %-30s R00:%08X R01:%08X R02:%08X R03:%08X R04:%08X R05:%08X R06:%08X R07:%08X R08:%08X R09:%08X R10:%08X R11:%08X R12:%08X R13:%08X R14:%08X R15:%08X\n", currFrameCounter, nds.VCount, nds_timer, NDS_ARM9.instruct_adr,NDS_ARM9.instruction, dasmbuf, NDS_ARM9.R[0], NDS_ARM9.R[1], NDS_ARM9.R[2], NDS_ARM9.R[3], NDS_ARM9.R[4], NDS_ARM9.R[5], NDS_ARM9.R[6], NDS_ARM9.R[7], NDS_ARM9.R[8], NDS_ARM9.R[9], NDS_ARM9.R[10], NDS_ARM9.R[11], NDS_ARM9.R[12], NDS_ARM9.R[13], NDS_ARM9.R[14], NDS_ARM9.R[15]); #endif } } #endif #ifdef LOG_ARM7 FORCEINLINE void arm7log() { if(dolog) { char dasmbuf[4096]; if(NDS_ARM7.CPSR.bits.T) des_thumb_instructions_set[((NDS_ARM7.instruction)>>6)&1023](NDS_ARM7.instruct_adr, NDS_ARM7.instruction, dasmbuf); else des_arm_instructions_set[INDEX(NDS_ARM7.instruction)](NDS_ARM7.instruct_adr, NDS_ARM7.instruction, dasmbuf); #ifdef LOG_TO_FILE if (!fp_dis7) return; #ifdef LOG_TO_FILE_REGS fprintf(fp_dis7, "\t\t;%05d:%03d %12lld\n\t\t;R0:%08X R1:%08X R2:%08X R3:%08X R4:%08X R5:%08X R6:%08X R7:%08X R8:%08X R9:%08X\n\t\t;R10:%08X R11:%08X R12:%08X R13:%08X R14:%08X R15:%08X| next %08X, N:%i Z:%i C:%i V:%i\n", currFrameCounter, nds.VCount, nds_timer, NDS_ARM7.R[0], NDS_ARM7.R[1], NDS_ARM7.R[2], NDS_ARM7.R[3], NDS_ARM7.R[4], NDS_ARM7.R[5], NDS_ARM7.R[6], NDS_ARM7.R[7], NDS_ARM7.R[8], NDS_ARM7.R[9], NDS_ARM7.R[10], NDS_ARM7.R[11], NDS_ARM7.R[12], NDS_ARM7.R[13], NDS_ARM7.R[14], NDS_ARM7.R[15], NDS_ARM7.next_instruction, NDS_ARM7.CPSR.bits.N, NDS_ARM7.CPSR.bits.Z, NDS_ARM7.CPSR.bits.C, NDS_ARM7.CPSR.bits.V); #endif fprintf(fp_dis7, "%s %08X\t%08X \t%s\n", NDS_ARM7.CPSR.bits.T?"THUMB":"ARM", NDS_ARM7.instruct_adr, NDS_ARM7.instruction, dasmbuf); /*if (NDS_ARM7.instruction == 0) { dolog = false; INFO("Disassembler is stopped\n"); }*/ #else printf("%05d:%03d %12lld 7:%08X %08X %-30s R00:%08X R01:%08X R02:%08X R03:%08X R04:%08X R05:%08X R06:%08X R07:%08X R08:%08X R09:%08X R10:%08X R11:%08X R12:%08X R13:%08X R14:%08X R15:%08X\n", currFrameCounter, nds.VCount, nds_timer, NDS_ARM7.instruct_adr,NDS_ARM7.instruction, dasmbuf, NDS_ARM7.R[0], NDS_ARM7.R[1], NDS_ARM7.R[2], NDS_ARM7.R[3], NDS_ARM7.R[4], NDS_ARM7.R[5], NDS_ARM7.R[6], NDS_ARM7.R[7], NDS_ARM7.R[8], NDS_ARM7.R[9], NDS_ARM7.R[10], NDS_ARM7.R[11], NDS_ARM7.R[12], NDS_ARM7.R[13], NDS_ARM7.R[14], NDS_ARM7.R[15]); #endif } } #endif //these have not been tuned very well yet. static const int kMaxWork = 4000; static const int kIrqWait = 4000; template static FORCEINLINE s32 minarmtime(s32 arm9, s32 arm7) { if(doarm9) { if(doarm7) return min(arm9,arm7); return arm9; } return arm7; } #ifdef HAVE_JIT template #else template #endif static /*donotinline*/ std::pair armInnerLoop( const u64 nds_timer_base, const s32 s32next, s32 arm9, s32 arm7) { s32 timer = minarmtime(arm9,arm7); while(timer < s32next && !sequencer.reschedule && execute) { if(doarm9 && (!doarm7 || arm9 <= timer)) { if(!NDS_ARM9.waitIRQ&&!nds.freezeBus) { #ifdef LOG_ARM9 arm9log(); #endif #ifdef DEBUG debug(); #endif #ifdef HAVE_JIT arm9 += armcpu_exec(); #else arm9 += armcpu_exec(); #endif #ifdef DEVELOPER nds_debug_continuing[0] = false; #endif } else { s32 temp = arm9; arm9 = min(s32next, arm9 + kIrqWait); nds.idleCycles[0] += arm9-temp; if (gxFIFO.size < 255) nds.freezeBus &= ~1; } } if(doarm7 && (!doarm9 || arm7 <= timer)) { if(!NDS_ARM7.waitIRQ&&!nds.freezeBus) { #ifdef LOG_ARM7 arm7log(); #endif #ifdef HAVE_JIT arm7 += (armcpu_exec()<<1); #else arm7 += (armcpu_exec()<<1); #endif #ifdef DEVELOPER nds_debug_continuing[1] = false; #endif } else { s32 temp = arm7; arm7 = min(s32next, arm7 + kIrqWait); nds.idleCycles[1] += arm7-temp; if(arm7 == s32next) { nds_timer = nds_timer_base + minarmtime(arm9,arm7); #ifdef HAVE_JIT return armInnerLoop(nds_timer_base, s32next, arm9, arm7); #else return armInnerLoop(nds_timer_base, s32next, arm9, arm7); #endif } } } timer = minarmtime(arm9,arm7); nds_timer = nds_timer_base + timer; } return std::make_pair(arm9, arm7); } void NDS_debug_break() { NDS_ARM9.stalled = NDS_ARM7.stalled = 1; //triggers an immediate exit from the cpu loop NDS_Reschedule(); } void NDS_debug_continue() { NDS_ARM9.stalled = NDS_ARM7.stalled = 0; } void NDS_debug_step() { NDS_debug_continue(); singleStep = true; } void NDS_exec(s32 nb) { sequencer.nds_vblankEnded = false; nds.cpuloopIterationCount = 0; #ifndef NDEBUG IF_DEVELOPER(for(int i=0;i<32;i++) DEBUG_statistics.sequencerExecutionCounters[i] = 0); #endif if(nds.sleeping) { //speculative code: if ANY irq happens, wake up the arm7. //I think the arm7 program analyzes the system and may decide not to wake up //if it is dissatisfied with the conditions if((MMU.reg_IE[1] & MMU.gen_IF<1>())) nds.sleeping = FALSE; } else { for(;;) { //trap the debug-stalled condition #ifdef DEVELOPER singleStep = false; //(gdb stub doesnt yet know how to trigger these immediately by calling reschedule) if ((NDS_ARM9.stalled || NDS_ARM7.stalled) && execute) { driver->EMU_DebugIdleEnter(); while((NDS_ARM9.stalled || NDS_ARM7.stalled) && execute) { driver->EMU_DebugIdleUpdate(); nds_debug_continuing[0] = nds_debug_continuing[1] = true; } driver->EMU_DebugIdleWakeUp(); } #endif nds.cpuloopIterationCount++; sequencer.execHardware(); //break out once per frame if(sequencer.nds_vblankEnded) break; //it should be benign to execute execHardware in the next frame, //since there won't be anything for it to do (everything should be scheduled in the future) //bail in case the system halted if(!execute) break; execHardware_interrupts(); //find next work unit: u64 next = sequencer.findNext(); next = min(next,nds_timer+kMaxWork); //lets set an upper limit for now //printf("%d\n",(next-nds_timer)); sequencer.reschedule = false; //cast these down to 32bits so that things run faster on 32bit procs u64 nds_timer_base = nds_timer; s32 arm9 = (s32)(nds_arm9_timer-nds_timer); s32 arm7 = (s32)(nds_arm7_timer-nds_timer); s32 s32next = (s32)(next-nds_timer); #ifdef DEVELOPER if(singleStep) { s32next = 1; } #endif #ifdef HAVE_JIT std::pair arm9arm7 = CommonSettings.use_jit ? armInnerLoop(nds_timer_base,s32next,arm9,arm7) : armInnerLoop(nds_timer_base,s32next,arm9,arm7); #else std::pair arm9arm7 = armInnerLoop(nds_timer_base,s32next,arm9,arm7); #endif #ifdef DEVELOPER if(singleStep) { NDS_ARM9.stalled = NDS_ARM7.stalled = 1; } #endif arm9 = arm9arm7.first; arm7 = arm9arm7.second; nds_arm7_timer = nds_timer_base+arm7; nds_arm9_timer = nds_timer_base+arm9; #ifndef NDEBUG //what we find here is dependent on the timing constants above //if(nds_timer>next && (nds_timer-next)>22) // printf("curious. please report: over by %d\n",(int)(nds_timer-next)); #endif //if we were waiting for an irq, don't wait too long: //let's re-analyze it after this hardware event (this rolls back a big burst of irq waiting which may have been interrupted by a resynch) if(NDS_ARM9.waitIRQ) { nds.idleCycles[0] -= (s32)(nds_arm9_timer-nds_timer); nds_arm9_timer = nds_timer; } if(NDS_ARM7.waitIRQ) { nds.idleCycles[1] -= (s32)(nds_arm7_timer-nds_timer); nds_arm7_timer = nds_timer; } } } currFrameCounter++; #ifndef NDEBUG DEBUG_Notify.NextFrame(); #endif if (cheats) cheats->process(); } template static void execHardware_interrupts_core() { u32 IF = MMU.gen_IF(); u32 IE = MMU.reg_IE[PROCNUM]; u32 masked = IF & IE; if(ARMPROC.halt_IE_and_IF && masked) { ARMPROC.halt_IE_and_IF = FALSE; ARMPROC.waitIRQ = FALSE; } if(masked && MMU.reg_IME[PROCNUM] && !ARMPROC.CPSR.bits.I) { //printf("Executing IRQ on procnum %d with IF = %08X and IE = %08X\n",PROCNUM,IF,IE); armcpu_irqException(&ARMPROC); } } void execHardware_interrupts() { execHardware_interrupts_core(); execHardware_interrupts_core(); } static void resetUserInput(); static void PrepareBiosARM7() { //begin with the bios unloaded NDS_ARM7.BIOS_loaded = false; memset(MMU.ARM7_BIOS, 0, sizeof(MMU.ARM7_BIOS)); if(CommonSettings.UseExtBIOS == true) { //read arm7 bios from inputfile and flag it if it succeeds FILE *arm7inf = fopen(CommonSettings.ARM7BIOS,"rb"); if (arm7inf) { if (fread(MMU.ARM7_BIOS,1,16384,arm7inf) == 16384) NDS_ARM7.BIOS_loaded = true; fclose(arm7inf); } } //choose to use SWI emulation or routines from bios if((CommonSettings.SWIFromBIOS) && (NDS_ARM7.BIOS_loaded)) { NDS_ARM7.swi_tab = 0; //if we used routines from bios, apply patches if (CommonSettings.PatchSWI3) { //[3801] SUB R0, #1 -> [4770] BX LR T1WriteWord(MMU.ARM7_BIOS,0x2F08, 0x4770); } } else NDS_ARM7.swi_tab = ARM_swi_tab[ARMCPU_ARM7]; if(NDS_ARM7.BIOS_loaded) { #ifdef DEBUG INFO("ARM7 BIOS load: %s.\n", NDS_ARM7.BIOS_loaded?"OK":"FAILED"); #endif } else { //fake bios content, critical to normal operations, since we dont have a real bios. T1WriteLong(MMU.ARM7_BIOS, 0x0000, 0xEAFFFFFE); //B 00000000 (reset: infinite loop) (originally: 0xE25EF002 - SUBS PC, LR, #2 T1WriteLong(MMU.ARM7_BIOS, 0x0004, 0xEAFFFFFE); //B 00000004 (undefined instruction: infinite loop) T1WriteLong(MMU.ARM7_BIOS, 0x0008, 0xEAFFFFFE); //B 00000280 (SWI: infinite loop [since we will be HLEing the SWI routines]) T1WriteLong(MMU.ARM7_BIOS, 0x000C, 0xEAFFFFFE); //B 0000000C (prefetch abort: infinite loop) T1WriteLong(MMU.ARM7_BIOS, 0x0010, 0xEAFFFFFE); //B 00000010 (data abort: infinite loop) T1WriteLong(MMU.ARM7_BIOS, 0x0018, 0xEA000000); //B 00000020 (IRQ: branch to handler) T1WriteLong(MMU.ARM7_BIOS, 0x001C, 0xEAFFFFFE); //B 0000001C (FIQ vector: infinite loop) //IRQ handler T1WriteLong(MMU.ARM7_BIOS, 0x0020, 0xE92D500F); //STMDB SP!, {R0-R3,R12,LR} T1WriteLong(MMU.ARM7_BIOS, 0x0024, 0xE3A00301); //MOV R0, #4000000 T1WriteLong(MMU.ARM7_BIOS, 0x0028, 0xE28FE000); //ADD LR, PC, #0 T1WriteLong(MMU.ARM7_BIOS, 0x002C, 0xE510F004); //LDR PC, [R0, -#4] T1WriteLong(MMU.ARM7_BIOS, 0x0030, 0xE8BD500F); //LDMIA SP!, {R0-R3,R12,LR} T1WriteLong(MMU.ARM7_BIOS, 0x0034, 0xE25EF004); //SUBS PC, LR, #4 } } static void PrepareBiosARM9() { //begin with the bios unloaded memset(MMU.ARM9_BIOS, 0, sizeof(MMU.ARM9_BIOS)); NDS_ARM9.BIOS_loaded = false; if(CommonSettings.UseExtBIOS == true) { //read arm9 bios from inputfile and flag it if it succeeds FILE* arm9inf = fopen(CommonSettings.ARM9BIOS,"rb"); if (arm9inf) { if (fread(MMU.ARM9_BIOS,1,4096,arm9inf) == 4096) NDS_ARM9.BIOS_loaded = true; fclose(arm9inf); } } //choose to use SWI emulation or routines from bios if((CommonSettings.SWIFromBIOS) && (NDS_ARM9.BIOS_loaded)) { NDS_ARM9.swi_tab = 0; //if we used routines from bios, apply patches //[3801] SUB R0, #1 -> [4770] BX LR if (CommonSettings.PatchSWI3) T1WriteWord(MMU.ARM9_BIOS, 0x07CC, 0x4770); } else NDS_ARM9.swi_tab = ARM_swi_tab[ARMCPU_ARM9]; if(NDS_ARM9.BIOS_loaded) { #ifdef DEBUG INFO("ARM9 BIOS load: %s.\n", NDS_ARM9.BIOS_loaded?"OK":"FAILED"); #endif } else { //fake bios content, critical to normal operations, since we dont have a real bios. //it'd be cool if we could write this in some kind of assembly language, inline or otherwise, without some bulky dependencies //perhaps we could build it with devkitarm? but thats bulky (offline) dependencies, to be sure.. //reminder: bios chains data abort to fast irq //exception vectors: T1WriteLong(MMU.ARM9_BIOS, 0x0000, 0xEAFFFFFE); // (infinite loop for) Reset !!! //T1WriteLong(MMU.ARM9_BIOS, 0x0004, 0xEAFFFFFE); // (infinite loop for) Undefined instruction T1WriteLong(MMU.ARM9_BIOS, 0x0004, 0xEA000004); // Undefined instruction -> Fast IRQ (just guessing) T1WriteLong(MMU.ARM9_BIOS, 0x0008, 0xEA00009C); // SWI -> ????? T1WriteLong(MMU.ARM9_BIOS, 0x000C, 0xEAFFFFFE); // (infinite loop for) Prefetch Abort T1WriteLong(MMU.ARM9_BIOS, 0x0010, 0xEA000001); // Data Abort -> Fast IRQ T1WriteLong(MMU.ARM9_BIOS, 0x0014, 0x00000000); // Reserved T1WriteLong(MMU.ARM9_BIOS, 0x0018, 0xEA000095); // Normal IRQ -> 0x0274 T1WriteLong(MMU.ARM9_BIOS, 0x001C, 0xEA00009D); // Fast IRQ -> 0x0298 //copy the logo content into the bios - Pokemon Platinum uses this in Pal Park trade //it compares the logo from the arm9 bios to the logo in the GBA header. //NOTE: in the unlikely event that the valid header is missing from the gameInfo, we'd be doing wrong here. // however, its nice not to have the logo embedded here. // TODO - take a CRC of the logo, check vs logoCRC16, and a hardcoded value, to make sure all is in order--report error if not memcpy(&MMU.ARM9_BIOS[0x20], &gameInfo.header.logo[0], 0x9C); T1WriteWord(MMU.ARM9_BIOS, 0x20 + 0x9C, gameInfo.header.logoCRC16); //... and with that we are at 0xBC: //(now what goes in this gap?? nothing we need, i guess) //IRQ handler: get dtcm address and jump to a vector in it T1WriteLong(MMU.ARM9_BIOS, 0x0274, 0xE92D500F); //STMDB SP!, {R0-R3,R12,LR} T1WriteLong(MMU.ARM9_BIOS, 0x0278, 0xEE190F11); //MRC CP15, 0, R0, CR9, CR1, 0 T1WriteLong(MMU.ARM9_BIOS, 0x027C, 0xE1A00620); //MOV R0, R0, LSR #C T1WriteLong(MMU.ARM9_BIOS, 0x0280, 0xE1A00600); //MOV R0, R0, LSL #C T1WriteLong(MMU.ARM9_BIOS, 0x0284, 0xE2800C40); //ADD R0, R0, #4000 T1WriteLong(MMU.ARM9_BIOS, 0x0288, 0xE28FE000); //ADD LR, PC, #0 T1WriteLong(MMU.ARM9_BIOS, 0x028C, 0xE510F004); //LDR PC, [R0, -#4] //???? T1WriteLong(MMU.ARM9_BIOS, 0x0290, 0xE8BD500F); //LDMIA SP!, {R0-R3,R12,LR} T1WriteLong(MMU.ARM9_BIOS, 0x0294, 0xE25EF004); //SUBS PC, LR, #4 //------- //FIQ and abort exception handler //TODO - this code is copied from the bios. refactor it //friendly reminder: to calculate an immediate offset: encoded = (desired_address-cur_address-8) T1WriteLong(MMU.ARM9_BIOS, 0x0298, 0xE10FD000); //MRS SP, CPSR T1WriteLong(MMU.ARM9_BIOS, 0x029C, 0xE38DD0C0); //ORR SP, SP, #C0 T1WriteLong(MMU.ARM9_BIOS, 0x02A0, 0xE12FF00D); //MSR CPSR_fsxc, SP T1WriteLong(MMU.ARM9_BIOS, 0x02A4, 0xE59FD000 | (0x2D4-0x2A4-8)); //LDR SP, [FFFF02D4] T1WriteLong(MMU.ARM9_BIOS, 0x02A8, 0xE28DD001); //ADD SP, SP, #1 T1WriteLong(MMU.ARM9_BIOS, 0x02AC, 0xE92D5000); //STMDB SP!, {R12,LR} T1WriteLong(MMU.ARM9_BIOS, 0x02B0, 0xE14FE000); //MRS LR, SPSR T1WriteLong(MMU.ARM9_BIOS, 0x02B4, 0xEE11CF10); //MRC CP15, 0, R12, CR1, CR0, 0 T1WriteLong(MMU.ARM9_BIOS, 0x02B8, 0xE92D5000); //STMDB SP!, {R12,LR} T1WriteLong(MMU.ARM9_BIOS, 0x02BC, 0xE3CCC001); //BIC R12, R12, #1 T1WriteLong(MMU.ARM9_BIOS, 0x02C0, 0xEE01CF10); //MCR CP15, 0, R12, CR1, CR0, 0 T1WriteLong(MMU.ARM9_BIOS, 0x02C4, 0xE3CDC001); //BIC R12, SP, #1 T1WriteLong(MMU.ARM9_BIOS, 0x02C8, 0xE59CC010); //LDR R12, [R12, #10] T1WriteLong(MMU.ARM9_BIOS, 0x02CC, 0xE35C0000); //CMP R12, #0 T1WriteLong(MMU.ARM9_BIOS, 0x02D0, 0x112FFF3C); //BLXNE R12 T1WriteLong(MMU.ARM9_BIOS, 0x02D4, 0x027FFD9C); //0x027FFD9C //--------- } } static void JumbleMemory() { } static void PrepareLogfiles() { #ifdef LOG_ARM7 if (fp_dis7 != NULL) { fclose(fp_dis7); fp_dis7 = NULL; } fp_dis7 = fopen("D:\\desmume_dis7.asm", "w"); #endif #ifdef LOG_ARM9 if (fp_dis9 != NULL) { fclose(fp_dis9); fp_dis9 = NULL; } fp_dis9 = fopen("D:\\desmume_dis9.asm", "w"); #endif } bool NDS_LegitBoot() { #ifdef HAVE_JIT //hack for firmware boot in JIT mode. //we know that it takes certain jit parameters to successfully boot the firmware. //CRAZYMAX: is it safe to accept anything smaller than 12? CommonSettings.jit_max_block_size = std::min(CommonSettings.jit_max_block_size,12U); #endif //partially clobber the loaded firmware with the user settings from DFC firmware->loadSettings(); //since firmware only boots encrypted roms, we have to make sure it's encrypted first //this has not been validated on big endian systems. it almost positively doesn't work. if (gameInfo.header.CRC16 != 0) EncryptSecureArea((u8*)&gameInfo.header, (u8*)gameInfo.secureArea); //boot processors from their bios entrypoints armcpu_init(&NDS_ARM7, 0x00000000); armcpu_init(&NDS_ARM9, 0xFFFF0000); return true; } //the fake firmware boot-up process bool NDS_FakeBoot() { NDS_header * header = NDS_getROMHeader(); #ifndef NDEBUG DEBUG_reset(); #endif if (!header) return false; nds.isFakeBooted = true; //since we're bypassing the code to decrypt the secure area, we need to make sure its decrypted first //this has not been validated on big endian systems. it almost positively doesn't work. if (gameInfo.header.CRC16 != 0) { bool okRom = DecryptSecureArea((u8*)&gameInfo.header, (u8*)gameInfo.secureArea); if(!okRom) { printf("Specified file is not a valid rom\n"); return false; } } //bios (or firmware) sets this default, which is generally not important for retail games but some homebrews are depending on _MMU_write08(REG_WRAMCNT,3); //EDIT - whats this firmware and how is it relating to the dummy firmware below //how do these even get used? what is the purpose of unpack and why is it not used by the firmware boot process? if (CommonSettings.UseExtFirmware && firmware->loaded()) { firmware->unpack(); firmware->loadSettings(); } // Create the dummy firmware //EDIT - whats dummy firmware and how is relating to the above? //it seems to be emplacing basic firmware data into MMU.fw.data NDS_CreateDummyFirmware(&CommonSettings.fw_config); //firmware loads the game card arm9 and arm7 programs as specified in rom header { bool hasSecureArea = ((gameInfo.romType == ROM_NDS) && (gameInfo.header.CRC16 != 0)); //copy the arm9 program to the address specified by rom header u32 src = header->ARM9src; u32 dst = header->ARM9cpy; for(u32 i = 0; i < header->ARM9binSize; i+=4) { u32 tmp = (hasSecureArea && ((src >= 0x4000) && (src < 0x8000)))?LE_TO_LOCAL_32(*(u32*)(gameInfo.secureArea + (src - 0x4000))):gameInfo.readROM(src); _MMU_write32(dst, tmp); dst += 4; src += 4; } //copy the arm7 program to the address specified by rom header src = header->ARM7src; dst = header->ARM7cpy; for(u32 i = 0; i < header->ARM7binSize; i+=4) { _MMU_write32(dst, gameInfo.readROM(src)); dst += 4; src += 4; } } //bios does this (thats weird, though. shouldnt it get changed when the card is swapped in the firmware menu? //right now our firmware menu isnt detecting any change to the card. //are some games depending on it being written here? please document. //_MMU_write16(0x027FF808, T1ReadWord(MMU.CART_ROM, 0x15E)); //firmware sets up a copy of the firmware user settings in memory. //TBD - this code is really clunky //it seems to be copying the MMU.fw.data data into RAM in the user memory stash locations u8 temp_buffer[NDS_FW_USER_SETTINGS_MEM_BYTE_COUNT]; if ( copy_firmware_user_data( temp_buffer, MMU.fw.data)) { for ( int fw_index = 0; fw_index < NDS_FW_USER_SETTINGS_MEM_BYTE_COUNT; fw_index++) _MMU_write08(0x027FFC80 + fw_index, temp_buffer[fw_index]); } //something copies the whole header to Main RAM 0x27FFE00 on startup. (http://nocash.emubase.de/gbatek.htm#dscartridgeheader) //once upon a time this copied 0x90 more. this was thought to be wrong, and changed. if(nds.Is_DSI()) { //dsi needs this copied later in memory. there are probably a number of things that get copied to a later location in memory.. thats where the NDS consoles tend to stash stuff. for (int i = 0; i < (0x170); i+=4) _MMU_write32(0x027FFE00 + i, gameInfo.readROM(i)); } else { for (int i = 0; i < (0x170); i+=4) _MMU_write32(0x027FFE00 + i, gameInfo.readROM(i)); } //the firmware will be booting to these entrypoint addresses via BX (well, the arm9 at least; is unverified for the arm7) armcpu_init(&NDS_ARM7, header->ARM7exe); armcpu_init(&NDS_ARM9, header->ARM9exe); //firmware sets REG_POSTFLG to the value indicating post-firmware status MMU.ARM9_REG[0x300] = 1; MMU.ARM7_REG[0x300] = 1; //firmware makes system think it's booted from card -- EXTREMELY IMPORTANT!!! This is actually checked by some things. (which things?) Thanks to cReDiAr _MMU_write08(0x02FFFC40,0x1); // removed redundant write to ARM9, this is going to shared main memory. But one has to wonder why r3478 was made which corrected a typo resulting in only ARMCPU_ARM7 getting used. //the chipId is read several times //for some reason, each of those reads get stored here. _MMU_write32(0x027FF800, gameInfo.chipID); //1st chipId _MMU_write32(0x027FF804, gameInfo.chipID); //2nd (secure) chipId _MMU_write32(0x027FFC00, gameInfo.chipID); //3rd (secure) chipId // Write the header checksum to memory _MMU_write16(0x027FF808, gameInfo.header.headerCRC16); //bitbox 4k demo is so stripped down it relies on default stack values //otherwise the arm7 will crash before making a sound //(these according to gbatek softreset bios docs) NDS_ARM7.R13_svc = 0x0380FFDC; NDS_ARM7.R13_irq = 0x0380FFB0; NDS_ARM7.R13_usr = 0x0380FF00; NDS_ARM7.R[13] = NDS_ARM7.R13_usr; //and let's set these for the arm9 while we're at it, though we have no proof NDS_ARM9.R13_svc = 0x00803FC0; NDS_ARM9.R13_irq = 0x00803FA0; NDS_ARM9.R13_usr = 0x00803EC0; NDS_ARM9.R13_abt = NDS_ARM9.R13_usr; //????? //I think it is wrong to take gbatek's "SYS" and put it in USR--maybe USR doesnt matter. //i think SYS is all the misc modes. please verify by setting nonsensical stack values for USR here NDS_ARM9.R[13] = NDS_ARM9.R13_usr; //n.b.: im not sure about all these, I dont know enough about arm9 svc/irq/etc modes //and how theyre named in desmume to match them up correctly. i just guessed. //-------------------------------- //setup the homebrew argv //this is useful for nitrofs apps which are emulating themselves via cflash //struct __argv { // int argvMagic; //!< argv magic number, set to 0x5f617267 ('_arg') if valid // char *commandLine; //!< base address of command line, set of null terminated strings // int length; //!< total length of command line // int argc; //!< internal use, number of arguments // char **argv; //!< internal use, argv pointer //}; std::string rompath = "fat:/" + path.RomName; const u32 kCommandline = 0x027E0000; //const u32 kCommandline = 0x027FFF84; //homebrew-related stuff. //its safe to put things in this position.. apparently nothing important is here. //however, some games could be checking them as an anti-desmume measure, so we might have to control it with slot-1 settings to suggest booting a homebrew app //perhaps we could automatically boot homebrew to an R4-like device. _MMU_write32(0x02FFFE70, 0x5f617267); _MMU_write32(0x02FFFE74, kCommandline); //(commandline starts here) _MMU_write32(0x02FFFE78, rompath.size()+1); //0x027FFF7C (argc) //0x027FFF80 (argv) for(size_t i=0;i(kCommandline+i, rompath[i]); _MMU_write08(kCommandline+rompath.size(), 0); //-------------------------------- //Call the card post_fakeboot hook to perform additional initialization slot1_device->post_fakeboot(ARMCPU_ARM9); slot1_device->post_fakeboot(ARMCPU_ARM7); delete header; return true; } void NDS_Reset() { PrepareLogfiles(); currFrameCounter = 0; resetUserInput(); singleStep = false; nds_debug_continuing[0] = nds_debug_continuing[1] = false; nds.sleeping = FALSE; nds.cardEjected = FALSE; nds.freezeBus = 0; nds.power1.lcd = nds.power1.gpuMain = nds.power1.gfx3d_render = nds.power1.gfx3d_geometry = nds.power1.gpuSub = nds.power1.dispswap = 1; nds.power2.speakers = 1; nds.power2.wifi = 0; nds.wifiCycle = 0; memset(nds.timerCycle, 0, sizeof(u64) * 2 * 4); nds.old = 0; nds.scr_touchX = nds.scr_touchY = nds.adc_touchX = nds.adc_touchY = 0; nds.isTouch = 0; nds.isFakeBooted = false; nds.paddle = 0; nds.ConsoleType = CommonSettings.ConsoleType; nds._DebugConsole = CommonSettings.DebugConsole; nds.ensataEmulation = CommonSettings.EnsataEmulation; nds.stylusJitter = CommonSettings.StylusJitter; nds.ensataHandshake = ENSATA_HANDSHAKE_none; nds.ensataIpcSyncCounter = 0; nds_timer = 0; nds_arm9_timer = 0; nds_arm7_timer = 0; LidClosed = FALSE; countLid = 0; MMU_Reset(); SetupMMU(nds.Is_DebugConsole(),nds.Is_DSI()); JumbleMemory(); #ifdef HAVE_JIT arm_jit_reset(CommonSettings.use_jit); #endif //initialize CP15 specially for this platform //TODO - how much of this is necessary for firmware boot? //(only ARM9 has CP15) reconstruct(&cp15); MMU.ARM9_RW_MODE = BIT7(cp15.ctrl); NDS_ARM9.intVector = 0xFFFF0000 * (BIT13(cp15.ctrl)); NDS_ARM9.LDTBit = !BIT15(cp15.ctrl); //TBit PrepareBiosARM7(); PrepareBiosARM9(); if (firmware) { delete firmware; firmware = NULL; } firmware = new CFIRMWARE(); firmware->load(); //we will allow a proper firmware boot, if: //1. we have the ARM7 and ARM9 bioses (its doubtful that our HLE bios implement the necessary functions) //2. firmware is available //3. user has requested booting from firmware bool canBootFromFirmware = (NDS_ARM7.BIOS_loaded && NDS_ARM9.BIOS_loaded && CommonSettings.BootFromFirmware && firmware->loaded()); bool bootResult = false; if(canBootFromFirmware) bootResult = NDS_LegitBoot(); else bootResult = NDS_FakeBoot(); // Init calibration info memcpy(&TSCal, firmware->getTouchCalibrate(), sizeof(TSCalInfo)); GPU->Reset(); WIFI_Reset(); memcpy(FW_Mac, (MMU.fw.data + 0x36), 6); SPU_DeInit(); SPU_ReInit(!canBootFromFirmware && bootResult); //this needs to happen last, pretty much, since it establishes the correct scheduling state based on all of the above initialization initSchedule(); } //convert a 12.4 screen coordinate to an ADC value. //the desmume host system will track the screen coordinate, but the hardware should be receiving the raw ADC values. //so we'll need to use this to simulate the ADC values corresponding to the desired screen coords, based on the current TSC calibrations u16 NDS_getADCTouchPosX(int scrX_lsl4) { scrX_lsl4 >>= 4; int rv = ((scrX_lsl4 - TSCal.scr.x1 + 1) * TSCal.adc.width) / TSCal.scr.width + TSCal.adc.x1; rv = min(0xFFF, max(0, rv)); return (u16)(rv); } u16 NDS_getADCTouchPosY(int scrY_lsl4) { scrY_lsl4 >>= 4; int rv = ((scrY_lsl4 - TSCal.scr.y1 + 1) * TSCal.adc.height) / TSCal.scr.height + TSCal.adc.y1; rv = min(0xFFF, max(0, rv)); return (u16)(rv); } static UserInput rawUserInput = {}; // requested input, generally what the user is physically pressing static UserInput finalUserInput = {}; // what gets sent to the game and possibly recorded const UserInput& NDS_getRawUserInput() { return rawUserInput; } UserInput& NDS_getProcessingUserInput() { return rawUserInput; } const UserInput& NDS_getFinalUserInput() { return finalUserInput; } static void saveUserInput(EMUFILE* os, UserInput& input) { os->fwrite((const char*)input.buttons.array, 14); writebool(input.touch.isTouch, os); write16le(input.touch.touchX, os); write16le(input.touch.touchY, os); write32le(input.mic.micButtonPressed, os); } static bool loadUserInput(EMUFILE* is, UserInput& input, int version) { is->fread((char*)input.buttons.array, 14); readbool(&input.touch.isTouch, is); read16le(&input.touch.touchX, is); read16le(&input.touch.touchY, is); read32le(&input.mic.micButtonPressed, is); return true; } static void resetUserInput(UserInput& input) { memset(&input, 0, sizeof(UserInput)); } // (userinput is kind of a misnomer, e.g. finalUserInput has to mirror nds.pad, nds.touchX, etc.) static void saveUserInput(EMUFILE* os) { saveUserInput(os, finalUserInput); saveUserInput(os, rawUserInput); // saved in case a savestate is made during input processing (which Lua could do if nothing else) bool validToProcessInput = true; writebool(validToProcessInput, os); for(int i = 0; i < 14; i++) write32le(0, os); // saved to make autofire more tolerable to use with re-recording } static bool loadUserInput(EMUFILE* is, int version) { bool rv = true; bool validToProcessInput = true; rv &= loadUserInput(is, finalUserInput, version); rv &= loadUserInput(is, rawUserInput, version); readbool(&validToProcessInput, is); u32 j = 0; for(int i = 0; i < 14; i++) read32le((u32*)&j, is); return rv; } static void resetUserInput() { resetUserInput(finalUserInput); } void NDS_setPad(bool R,bool L,bool D,bool U,bool T,bool S,bool B,bool A,bool Y,bool X,bool W,bool E,bool G, bool F) { UserButtons& rawButtons = rawUserInput.buttons; rawButtons.R = R; rawButtons.L = L; rawButtons.D = D; rawButtons.U = U; rawButtons.T = T; rawButtons.S = S; rawButtons.B = B; rawButtons.A = A; rawButtons.Y = Y; rawButtons.X = X; rawButtons.W = W; rawButtons.E = E; rawButtons.G = G; rawButtons.F = F; } void NDS_setTouchPos(u16 x, u16 y, u16 scale) { rawUserInput.touch.touchX = (x/scale)<<4; rawUserInput.touch.touchY = (y/scale)<<4; rawUserInput.touch.isTouch = true; nds.stylusJitter = CommonSettings.StylusJitter; } void NDS_releaseTouch(void) { rawUserInput.touch.touchX = 0; rawUserInput.touch.touchY = 0; rawUserInput.touch.isTouch = false; } void NDS_setMic(bool pressed) { rawUserInput.mic.micButtonPressed = (pressed ? TRUE : FALSE); } static void NDS_applyFinalInput() { const UserInput& input = NDS_getFinalUserInput(); u16 pad = (0 | ((input.buttons.A ? 0 : 0x80) >> 7) | ((input.buttons.B ? 0 : 0x80) >> 6) | ((input.buttons.T ? 0 : 0x80) >> 5) | ((input.buttons.S ? 0 : 0x80) >> 4) | ((input.buttons.R ? 0 : 0x80) >> 3) | ((input.buttons.L ? 0 : 0x80) >> 2) | ((input.buttons.U ? 0 : 0x80) >> 1) | ((input.buttons.D ? 0 : 0x80) ) | ((input.buttons.E ? 0 : 0x80) << 1) | ((input.buttons.W ? 0 : 0x80) << 2)) ; pad = LOCAL_TO_LE_16(pad); ((u16 *)MMU.ARM9_REG)[0x130>>1] = (u16)pad; ((u16 *)MMU.ARM7_REG)[0x130>>1] = (u16)pad; u16 k_cnt = ((u16 *)MMU.ARM9_REG)[0x132>>1]; if ( k_cnt & (1<<14)) { //INFO("ARM9: KeyPad IRQ (pad 0x%04X, cnt 0x%04X (condition %s))\n", pad, k_cnt, k_cnt&(1<<15)?"AND":"OR"); u16 k_cnt_selected = (k_cnt & 0x3F); if (k_cnt&(1<<15)) // AND { if ((~pad & k_cnt_selected) == k_cnt_selected) NDS_makeIrq(ARMCPU_ARM9,IRQ_BIT_KEYPAD); } else // OR { if (~pad & k_cnt_selected) NDS_makeIrq(ARMCPU_ARM9,IRQ_BIT_KEYPAD); } } k_cnt = ((u16 *)MMU.ARM7_REG)[0x132>>1]; if ( k_cnt & (1<<14)) { //INFO("ARM7: KeyPad IRQ (pad 0x%04X, cnt 0x%04X (condition %s))\n", pad, k_cnt, k_cnt&(1<<15)?"AND":"OR"); u16 k_cnt_selected = (k_cnt & 0x3F); if (k_cnt&(1<<15)) // AND { if ((~pad & k_cnt_selected) == k_cnt_selected) NDS_makeIrq(ARMCPU_ARM7,IRQ_BIT_KEYPAD); } else // OR { if (~pad & k_cnt_selected) NDS_makeIrq(ARMCPU_ARM7,IRQ_BIT_KEYPAD); } } if(input.touch.isTouch) { u16 adc_x = NDS_getADCTouchPosX(input.touch.touchX); u16 adc_y = NDS_getADCTouchPosY(input.touch.touchY); nds.adc_touchX = adc_x; nds.adc_touchY = adc_y; nds.adc_jitterctr = 0; nds.scr_touchX = input.touch.touchX; nds.scr_touchY = input.touch.touchY; nds.isTouch = 1; } else { nds.adc_touchX = 0; nds.adc_touchY = 0; nds.scr_touchX = 0; nds.scr_touchY = 0; nds.isTouch = 0; } if (input.buttons.F && !countLid) { LidClosed = (!LidClosed) & 0x01; if (!LidClosed) { NDS_makeIrq(ARMCPU_ARM7,IRQ_BIT_ARM7_FOLD); } countLid = 30; } else { if (countLid > 0) countLid--; } u16 padExt = ((input.buttons.X ? 0 : 0x80) >> 7) | ((input.buttons.Y ? 0 : 0x80) >> 6) | ((input.buttons.G ? 0 : 0x80) >> 4) | ((LidClosed) << 7) | 0x0034; padExt = LOCAL_TO_LE_16(padExt); padExt |= (((u16 *)MMU.ARM7_REG)[0x136>>1] & 0x0070); ((u16 *)MMU.ARM7_REG)[0x136>>1] = (u16)padExt; //put into the format we want for the movie system //fRLDUTSBAYXWEg //we don't really need nds.pad anymore, but removing it would be a pain nds.pad = ((input.buttons.R ? 1 : 0) << 12)| ((input.buttons.L ? 1 : 0) << 11)| ((input.buttons.D ? 1 : 0) << 10)| ((input.buttons.U ? 1 : 0) << 9)| ((input.buttons.T ? 1 : 0) << 8)| ((input.buttons.S ? 1 : 0) << 7)| ((input.buttons.B ? 1 : 0) << 6)| ((input.buttons.A ? 1 : 0) << 5)| ((input.buttons.Y ? 1 : 0) << 4)| ((input.buttons.X ? 1 : 0) << 3)| ((input.buttons.W ? 1 : 0) << 2)| ((input.buttons.E ? 1 : 0) << 1); } void NDS_beginProcessingInput() { } void NDS_endProcessingInput() { // transfer the processed input finalUserInput = rawUserInput; // use the final input for a few things right away NDS_applyFinalInput(); } void NDS_suspendProcessingInput(bool suspend) { static int suspendCount = 0; if(suspend) suspendCount++; else if(suspendCount) suspendCount--; } void NDS_swapScreen() { if (GPU->GetDisplayMain()->GetEngineID() == GPUEngineID_Main) { GPU->GetDisplayMain()->SetEngineByID(GPUEngineID_Sub); GPU->GetDisplayTouch()->SetEngineByID(GPUEngineID_Main); } else { GPU->GetDisplayMain()->SetEngineByID(GPUEngineID_Main); GPU->GetDisplayTouch()->SetEngineByID(GPUEngineID_Sub); } } #if defined(LOG_ARM9) || defined(LOG_ARM7) void emu_halt() { //printf("halting emu: ARM9 PC=%08X/%08X, ARM7 PC=%08X/%08X\n", NDS_ARM9.R[15], NDS_ARM9.instruct_adr, NDS_ARM7.R[15], NDS_ARM7.instruct_adr); execute = false; #ifdef LOG_ARM9 if (fp_dis9) { char buf[256] = { 0 }; sprintf(buf, "halting emu: ARM9 PC=%08X/%08X\n", NDS_ARM9.R[15], NDS_ARM9.instruct_adr); fwrite(buf, 1, strlen(buf), fp_dis9); INFO("ARM9 halted\n"); } #endif #ifdef LOG_ARM7 if (fp_dis7) { char buf[256] = { 0 }; sprintf(buf, "halting emu: ARM7 PC=%08X/%08X\n", NDS_ARM7.R[15], NDS_ARM7.instruct_adr); fwrite(buf, 1, strlen(buf), fp_dis7); INFO("ARM7 halted\n"); } #endif } #endif //returns true if exmemcnt specifies satisfactory parameters for the device, which calls this function bool ValidateSlot2Access(u32 procnum, u32 demandSRAMSpeed, u32 demand1stROMSpeed, u32 demand2ndROMSpeed, int clockbits) { static const u32 _sramSpeeds[] = {10,8,6,18}; static const u32 _rom1Speeds[] = {10,8,6,18}; static const u32 _rom2Speeds[] = {6,4}; u16 exmemcnt = T1ReadWord(MMU.MMU_MEM[procnum][0x40], 0x204); u16 exmemcnt9 = T1ReadWord(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x204); u32 arm7access = (exmemcnt9 & EXMEMCNT_MASK_SLOT2_ARM7); u32 sramSpeed = _sramSpeeds[(exmemcnt & EXMEMCNT_MASK_SLOT2_SRAM_TIME)]; u32 romSpeed1 = _rom1Speeds[(exmemcnt & EXMEMCNT_MASK_SLOT2_ROM_1ST_TIME)>>2]; u32 romSpeed2 = _rom2Speeds[(exmemcnt & EXMEMCNT_MASK_SLOT2_ROM_2ND_TIME)>>4]; u32 curclockbits = (exmemcnt & EXMEMCNT_MASK_SLOT2_CLOCKRATE)>>5; if(procnum==ARMCPU_ARM9 && arm7access) return false; if(procnum==ARMCPU_ARM7 && !arm7access) return false; //what we're interested in here is whether the rom/ram are too low -> too fast. then accesses won't have enough time to work. //i'm not sure if this gives us enough flexibility, but it is good enough for now. //should make the arguments to this function bitmasks later if we need better. if(sramSpeed < demandSRAMSpeed) return false; if(romSpeed1 < demand1stROMSpeed) return false; if(romSpeed2 < demand2ndROMSpeed) return false; if(clockbits != -1 && clockbits != (int)curclockbits) return false; return true; } desmume/src/libretro-common/include/features/000700 001750 001750 00000000000 12756420131 022466 5ustar00sergiosergio000000 000000 desmume/src/utils/AsmJit/x86/x86util.cpp000664 001750 001750 00000005500 12755534123 021142 0ustar00sergiosergio000000 000000 // [AsmJit] // Complete JIT Assembler for C++ Language. // // [License] // Zlib - See COPYING file in this package. #define ASMJIT_EXPORTS // [Dependencies - AsmJit] #include "../x86/x86defs.h" // [Api-Begin] #include "../core/apibegin.h" namespace AsmJit { // ============================================================================ // [AsmJit::_x86UtilJccFromCond] // ============================================================================ const uint32_t _x86UtilJccFromCond[20] = { kX86InstJO, kX86InstJNO, kX86InstJB, kX86InstJAE, kX86InstJE, kX86InstJNE, kX86InstJBE, kX86InstJA, kX86InstJS, kX86InstJNS, kX86InstJPE, kX86InstJPO, kX86InstJL, kX86InstJGE, kX86InstJLE, kX86InstJG, kInstNone, kInstNone, kInstNone, kInstNone }; // ============================================================================ // [AsmJit::_x86UtilMovccFromCond] // ============================================================================ const uint32_t _x86UtilMovccFromCond[20] = { kX86InstCMovO, kX86InstCMovNO, kX86InstCMovB, kX86InstCMovAE, kX86InstCMovE, kX86InstCMovNE, kX86InstCMovBE, kX86InstCMovA, kX86InstCMovS, kX86InstCMovNS, kX86InstCMovPE, kX86InstCMovPO, kX86InstCMovL, kX86InstCMovGE, kX86InstCMovLE, kX86InstCMovG, kInstNone, kInstNone, kInstNone, kInstNone }; // ============================================================================ // [AsmJit::_x86UtilSetccFromCond] // ============================================================================ const uint32_t _x86UtilSetccFromCond[20] = { kX86InstSetO, kX86InstSetNO, kX86InstSetB, kX86InstSetAE, kX86InstSetE, kX86InstSetNE, kX86InstSetBE, kX86InstSetA, kX86InstSetS, kX86InstSetNS, kX86InstSetPE, kX86InstSetPO, kX86InstSetL, kX86InstSetGE, kX86InstSetLE, kX86InstSetG, kInstNone, kInstNone, kInstNone, kInstNone }; // ============================================================================ // [AsmJit::_x86UtilReversedCond] // ============================================================================ const uint32_t _x86UtilReversedCond[20] = { /* x86CondO -> */ kX86CondO, /* x86CondNO -> */ kX86CondNO, /* x86CondB -> */ kX86CondA, /* x86CondAE -> */ kX86CondBE, /* x86CondE -> */ kX86CondE, /* x86CondNE -> */ kX86CondNE, /* x86CondBE -> */ kX86CondAE, /* x86CondA -> */ kX86CondB, /* x86CondS -> */ kX86CondS, /* x86CondNS -> */ kX86CondNS, /* x86CondPE -> */ kX86CondPE, /* x86CondPO -> */ kX86CondPO, /* x86CondL -> */ kX86CondG, /* x86CondGE -> */ kX86CondLE, /* x86CondLE -> */ kX86CondGE, /* x86CondG -> */ kX86CondL, /* kX86CondFpuUnordered -> */ kX86CondFpuUnordered, /* kX86CondFpuNotUnordered -> */ kX86CondFpuNotUnordered, 0x12, 0x13 }; } // AsmJit namespace #include "../core/apiend.h" desmume/src/libretro-common/include/rthreads/rsemaphore.h000664 001750 001750 00000003634 12755534123 025032 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2015 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (rsemaphore.h). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef __LIBRETRO_SDK_SEMAPHORE_H #define __LIBRETRO_SDK_SEMAPHORE_H #include RETRO_BEGIN_DECLS typedef struct ssem ssem_t; /** * ssem_create: * @value : initial value for the semaphore * * Create a new semaphore. * * Returns: pointer to new semaphore if successful, otherwise NULL. */ ssem_t *ssem_new(int value); void ssem_free(ssem_t *semaphore); int ssem_get(ssem_t *semaphore); void ssem_wait(ssem_t *semaphore); void ssem_signal(ssem_t *semaphore); RETRO_END_DECLS #endif /* __LIBRETRO_SDK_SEMAPHORE_H */ desmume/src/libretro-common/conversion/000700 001750 001750 00000000000 12756420131 021412 5ustar00sergiosergio000000 000000 desmume/src/utils/libfat/common.h000664 001750 001750 00000005425 12755534123 020207 0ustar00sergiosergio000000 000000 /* common.h Common definitions and included files for the FATlib Copyright (c) 2006 Michael "Chishm" Chisholm Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. 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. 3. The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. */ #ifndef _COMMON_H #define _COMMON_H #define BYTES_PER_READ 512 #include #ifndef _MSC_VER #include #endif // When compiling for NDS, make sure NDS is defined #ifndef NDS #if defined ARM9 || defined ARM7 #define NDS #endif #endif // Platform specific includes #if defined(__gamecube__) || defined (__wii__) #include #include #include #elif defined(NDS) #include #include #include #elif defined(GBA) #include #include #endif #include // Platform specific options #if defined (__wii__) #define DEFAULT_CACHE_PAGES 4 #define DEFAULT_SECTORS_PAGE 64 #define USE_LWP_LOCK #define USE_RTC_TIME #elif defined (__gamecube__) #define DEFAULT_CACHE_PAGES 4 #define DEFAULT_SECTORS_PAGE 64 #define USE_LWP_LOCK #define USE_RTC_TIME #elif defined (NDS) #define DEFAULT_CACHE_PAGES 4 #define DEFAULT_SECTORS_PAGE 8 #define USE_RTC_TIME #elif defined (GBA) #define DEFAULT_CACHE_PAGES 2 #define DEFAULT_SECTORS_PAGE 8 #define LIMIT_SECTORS 128 #else #define LIBFAT_PC 1 //any particular reason for this? #define DEFAULT_CACHE_PAGES 4 #define DEFAULT_SECTORS_PAGE 8 #endif #include "libfat_pc.h" #include "fat.h" #endif // _COMMON_H desmume/src/utils/AsmJit/core/assert.h000664 001750 001750 00000003012 12755534123 021064 0ustar00sergiosergio000000 000000 // [AsmJit] // Complete JIT Assembler for C++ Language. // // [License] // Zlib - See COPYING file in this package. // [Guard] #ifndef _ASMJIT_CORE_ASSERT_H #define _ASMJIT_CORE_ASSERT_H // [Dependencies - AsmJit] #include "../core/build.h" // [Api-Begin] #include "../core/apibegin.h" namespace AsmJit { //! @addtogroup AsmJit_Core //! @{ // ============================================================================ // [AsmJit::Assert] // ============================================================================ //! @brief Called in debug build on assertion failure. //! @param file Source file name where it happened. //! @param line Line in the source file. //! @param exp Expression what failed. //! //! If you have problems with assertions simply put a breakpoint into //! AsmJit::assertionFailure() method (AsmJit/Core/Assert.cpp file) and examine //! call stack. ASMJIT_API void assertionFailure(const char* file, int line, const char* exp); // ============================================================================ // [ASMJIT_ASSERT] // ============================================================================ #if defined(ASMJIT_DEBUG) #if !defined(ASMJIT_ASSERT) #define ASMJIT_ASSERT(exp) \ do { \ if (!(exp)) ::AsmJit::assertionFailure(__FILE__, __LINE__, #exp); \ } while(0) #endif #else #if !defined(ASMJIT_ASSERT) #define ASMJIT_ASSERT(exp) ASMJIT_NOP() #endif #endif // DEBUG //! @} } // AsmJit namespace // [Api-End] #include "../core/apiend.h" // [Guard] #endif // _ASMJIT_CORE_ASSERT_H desmume/src/libretro-common/include/compat/msvc/000700 001750 001750 00000000000 12756420131 023103 5ustar00sergiosergio000000 000000 desmume/src/libretro-common/gfx/scaler/000700 001750 001750 00000000000 12756420131 021262 5ustar00sergiosergio000000 000000 desmume/src/libretro-common/formats/jpeg/000700 001750 001750 00000000000 12756420131 021625 5ustar00sergiosergio000000 000000 desmume/src/libretro-common/file/nbio/test/nbio_test000755 001750 001750 00000036450 12755534123 024016 0ustar00sergiosergio000000 000000 ELF>`@@(4@8@$!@@@@@ÀÀ@@@@ÔÔ ØØ`Ø`Øà ðð`ð`ÐÐ@@DDPåtd@@„„Qåtd/lib64/ld-linux-x86-64.so.2GNU GNU³çÙƒž4Ñá:Z¤ßðuñ8ö5<¢k$S>*Y7p E1 Llibc.so.6fopenftellputsreallocabortmemsetfseekmemcmpfclosemallocfwritefread__libc_start_mainfree__gmon_start__GLIBC_2.2.5ui À` à`è`ð`ø````` ` (` 0` 8` @`H`HƒìH‹} H…ÀtèHƒÄÃÿ5j ÿ%l @ÿ%j héàÿÿÿÿ%b héÐÿÿÿÿ%Z héÀÿÿÿÿ%R hé°ÿÿÿÿ%J hé ÿÿÿÿ%B héÿÿÿÿ%: hé€ÿÿÿÿ%2 hépÿÿÿÿ%* hé`ÿÿÿÿ%" h éPÿÿÿÿ% h é@ÿÿÿÿ% h é0ÿÿÿÿ%  h é ÿÿÿÿ% h éÿÿÿÿ%j f1íI‰Ñ^H‰âHƒäðPTIÇÀ @HÇÁ°@HÇÇ" @èGÿÿÿôfD¸·`UH-°`HƒøH‰åv¸H…Àt]¿°`ÿàf„]Ã@f.„¾°`UHî°`HÁþH‰åH‰ðHÁè?HÆHÑþt¸H…Àt ]¿°`ÿà]ÃfD€=™ uUH‰åènÿÿÿ]Ɔ óÃ@¿è`Hƒ?u듸H…ÀtñUH‰åÿÐ]ézÿÿÿUH‰åHƒì ÆEÿHÇEð¾¿8@è¾H‰EèH‹Eè¾H‰Çè‡HUàH‹EèH‰ÖH‰ÇèH‰EðH‹EàH=t ¿A@èÕýÿÿH‹Eðº¾BH‰ÇèïýÿÿH‹EèH‰Çè-ëÆEÿH‹EèH‰Çè{ƒð„Àué¶Eÿƒð„Àt ¿W@è…ýÿÿH‹EèH‰ÇèÉÃUH‰åHƒì ÆEÿ¾¿8@èH‰EðHUàH‹EðH‰ÖH‰ÇèkH‰EèH‹EàH=t ¿s@è*ýÿÿHƒ}èt ¿@èýÿÿH‹EðH‰Çè'ëÆEÿH‹EðH‰ÇèÕƒð„Àué¶Eÿƒð„Àt ¿¼@èßüÿÿHUàH‹EðH‰ÖH‰ÇèóH‰EèH‹EàH=t ¿×@è²üÿÿH‹Eè¶õÿÿÄA†C ¿ dâõÿÿA†C  „ÊöÿÿA†C P ¤¿öÿÿsA†C n Äøÿÿ`A†C [ äRøÿÿ`A†C [ ’øÿÿ«A†C ¦ $úÿÿ¢A†C  DŸúÿÿMA†C H dÌúÿÿ,A†C g „ØúÿÿuA†C p D¤8ûÿÿeBBŽE B(ŒH0†H8ƒM@r8A0A(B BBBì`ûÿÿ0@@ 8@ $@Ø`à`õþÿo`@@€@ ‹ È`Pè@Ð@ þÿÿo°@ÿÿÿoðÿÿoŒ@ð`v@†@–@¦@¶@Æ@Ö@æ@ö@@@&@6@F@@@@@@@GCC: (GNU) 5.3.0,V@á,\7 @nX Ø@V@áØ8;‹»@Îint_딥V@ÄœÖù-‘Pä Ö‘optr w‘`, â‘Xµ ž Ýô @œ>ù -‘Pä!Ö‘o "â‘`ptr#w‘X ™;b" @œ!  ´@7 @nËØ8;‹»@Îint_ƒiˆ„ië•”R0§NØñ$ƒòb ÷vø’ù2ú Ùû(5ü0)ý8Šþ@ þH ðP  X b\` bh hbp  bt ¢px –F€ kT‚ hƒ xˆ ¦!{ Ä)˜ Ë*  Ò+¨ Ù,° à.-¸ &/bÀ ç1~Ä C–·œ\‚\çžbW¢b+§ •x †$ •Ž †” •Z6ž(ùfùí ® -len -opT 'T!œÂf7 @sœf,Ž‘X'M‘Tf‘hfù‘`\=S @§Jª @`œ˜Jf‘h![ @`œÄ[f‘hÌk"j @«œ"kf‘X­m-‘h[ @Izƒ-‘`µò•@¢œc•f‘hlen•-‘`M«·@Mœ¡«f‘hlen«¡‘`- ¶@,œÓ¶f‘h¿0@uœÿ¿f‘h Ž †pÿ €`% : ; I$ > $ >  .: ; '@–B4: ; I4: ; I <  I .?: ; 'I@–B% : ; I$ > $ >   I : ;  : ; I8 : ;I8 : ; I !I/ &I : ; I8 .?: ; 'I@–B: ; I4: ; I4: ; I : ; .?: ; '@–B : ; I.?: ; 'I@—B.?: ; '@—BÇbû /usr/lib/gcc/x86_64-unknown-linux-gnu/5.3.0/includenbio_test.cstddef.h V@„Kƒ0g» Y¼.J0­ »?„K/h»Ÿu ¼.J0­ h»Ÿ¬å »?KYŸe¦û ../usr/lib/gcc/x86_64-unknown-linux-gnu/5.3.0/include/usr/include/bits/usr/includenbio_stdio.cstddef.htypes.hstdio.hlibio.h 7 @åƒÉu Ø¯­¼Îƒ‘*'» ÈËó„gf<(vÉ󻼃»Y1»w¼Ÿ[„ƒuÖ 1»w¼Ÿ[ƒƒvÖ 1»„u ­’…¼»èW/Z¼ƒ»$Ÿw/#hKƒ­1󯼟ZØŸ[»&ƒp  1»uuu廟Y1ƒwƒ$1»v¼ŸZåô­»uÖ size_tGNU C99 5.3.0 -mtune=generic -march=x86-64 -g -std=gnu99/home/squarepusher/libretro-super/retroarch/libretro-common/file/nbio/testunsigned charmainnbio_tnbio_write_test_Boolshort unsigned intshort intnbio_test.cloopedsizetypenbio_read_test__off_t_IO_read_ptr_chain_shortbuf_IO_buf_baselong long unsigned intnbio_get_ptrlong long int_filenomodes_IO_read_end_flags_IO_buf_end_cur_column_old_offsetprogress_IO_markernbio_opennbio_iterate_IO_write_ptr_sbufdatanbio_resize_IO_save_basenbio_cancel_lock_flags2_modefilename_IO_write_end_IO_lock_t_IO_FILE_poserror_markers_vtable_offsetwritten_next__off64_t_IO_read_base_IO_save_endamount../nbio_stdio.c__pad1__pad2__pad3__pad4__pad5_unused2_IO_backup_basenbio_begin_readnbio_freehandlenbio_begin_write_IO_write_base@@<@`@€@@Œ@°@ Ð@ è@ 8@ `@ P@`@$@0@@ @Ø`à`è`ð`À`È```°` ñÿñÿè` @"Ð@5@K°`Zà`0@Ø`¬ñÿ¸V@ÄÈ @×ñÿä€`0ñÿêÐ@øè`ñÿà`ð`Ø`1@DÈ`Z @j| @ ``«½Ð°`×d$@ë@¢÷ *>``K^ mh`z0@‰·@M–°@e¦ª @`¶¸`D`@*ÊÝò°`þ" @j @«7 @s- A0@uK @`\p°`| –@,  8@init.ccrtstuff.c__JCR_LIST__deregister_tm_clones__do_global_dtors_auxcompleted.6945__do_global_dtors_aux_fini_array_entryframe_dummy__frame_dummy_init_array_entrynbio_test.cnbio_write_testnbio_read_testnbio_stdio.cmodes__FRAME_END____JCR_END____init_array_end_DYNAMIC__init_array_start__GNU_EH_FRAME_HDR_GLOBAL_OFFSET_TABLE___libc_csu_finifree@@GLIBC_2.2.5abort@@GLIBC_2.2.5_ITM_deregisterTMCloneTableputs@@GLIBC_2.2.5fread@@GLIBC_2.2.5_edatafclose@@GLIBC_2.2.5nbio_resizememset@@GLIBC_2.2.5__libc_start_main@@GLIBC_2.2.5memcmp@@GLIBC_2.2.5__data_startftell@@GLIBC_2.2.5__gmon_start____dso_handle_IO_stdin_usednbio_get_ptr__libc_csu_initnbio_begin_readmalloc@@GLIBC_2.2.5fseek@@GLIBC_2.2.5realloc@@GLIBC_2.2.5__bss_startmainnbio_iteratenbio_openfopen@@GLIBC_2.2.5_Jv_RegisterClassesnbio_freenbio_begin_writefwrite@@GLIBC_2.2.5__TMC_END___ITM_registerTMCloneTablenbio_cancel.symtab.strtab.shstrtab.interp.note.ABI-tag.note.gnu.build-id.gnu.hash.dynsym.dynstr.gnu.version.gnu.version_r.rela.dyn.rela.plt.init.plt.got.text.fini.rodata.eh_frame_hdr.eh_frame.init_array.fini_array.jcr.dynamic.got.plt.data.bss.comment.debug_aranges.debug_info.debug_abbrev.debug_line.debug_str@#@ 1<@<$Döÿÿo`@`N €@€€V@‹^ÿÿÿoŒ@Œ kþÿÿo°@° zÐ@ЄBè@èPŽ8@8‰`@`ð”P@P`@`£$@$ ©0@0ì±@„¿ @ 4ÉØ`ØÕà`àáè`èæð`ðИÀ`ÀïÈ`Ȉø```P þ°`°0° Á`!'¢5§ 4A0Û"AÚ2L & #9 8/¢desmume/src/libretro-common/memmap/memmap.c000664 001750 001750 00000011166 12755534123 022150 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2015 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (memmap.c). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include #include #ifndef PROT_READ #define PROT_READ 0x1 /* Page can be read */ #endif #ifndef PROT_WRITE #define PROT_WRITE 0x2 /* Page can be written. */ #endif #ifndef PROT_READWRITE #define PROT_READWRITE 0x3 /* Page can be written to and read from. */ #endif #ifndef PROT_EXEC #define PROT_EXEC 0x4 /* Page can be executed. */ #endif #ifndef PROT_NONE #define PROT_NONE 0x0 /* Page can not be accessed. */ #endif #ifndef MAP_FAILED #define MAP_FAILED ((void *) -1) #endif #ifdef _WIN32 void* mmap(void *addr, size_t len, int prot, int flags, int fildes, size_t offset) { void *map = (void*)NULL; HANDLE handle = INVALID_HANDLE_VALUE; switch (prot) { case PROT_READ: default: { handle = CreateFileMapping((HANDLE) _get_osfhandle(fildes), 0, PAGE_READONLY, 0, len, 0); if (!handle) break; map = (void*)MapViewOfFile(handle, FILE_MAP_READ, 0, 0, len); CloseHandle(handle); break; } case PROT_WRITE: { handle = CreateFileMapping((HANDLE) _get_osfhandle(fildes),0,PAGE_READWRITE,0, len, 0); if (!handle) break; map = (void*)MapViewOfFile(handle, FILE_MAP_WRITE, 0, 0, len); CloseHandle(handle); break; } case PROT_READWRITE: { handle = CreateFileMapping((HANDLE) _get_osfhandle(fildes),0,PAGE_READWRITE,0, len, 0); if (!handle) break; map = (void*)MapViewOfFile(handle, FILE_MAP_ALL_ACCESS, 0, 0, len); CloseHandle(handle); break; } } if (map == (void*)NULL) return((void*)MAP_FAILED); return((void*) ((int8_t*)map + offset)); } int munmap(void *addr, size_t length) { if (!UnmapViewOfFile(addr)) return -1; return 0; } int mprotect(void *addr, size_t len, int prot) { /* Incomplete, just assumes PAGE_EXECUTE_READWRITE right now * instead of correctly handling prot */ prot = 0; if (prot & (PROT_READ | PROT_WRITE | PROT_EXEC)) prot = PAGE_EXECUTE_READWRITE; return VirtualProtect(addr, len, prot, 0); } #elif !defined(HAVE_MMAN) void* mmap(void *addr, size_t len, int prot, int flags, int fildes, size_t offset) { return malloc(len); } int munmap(void *addr, size_t len) { free(addr); return 0; } int mprotect(void *addr, size_t len, int prot) { /* stub - not really needed at this point since this codepath has no dynarecs */ return 0; } #endif #if defined(__MACH__) && defined(__arm__) #include #endif int memsync(void *start, void *end) { size_t len = (char*)end - (char*)start; #if defined(__MACH__) && defined(__arm__) sys_dcache_flush(start ,len); sys_icache_invalidate(start, len); return 0; #elif defined(__arm__) && !defined(__QNX__) (void)len; __clear_cache(start, end); return 0; #elif defined(HAVE_MMAN) return msync(start, len, MS_SYNC | MS_INVALIDATE #ifdef __QNX__ MS_CACHE_ONLY #endif ); #else (void)len; return 0; #endif } int memprotect(void *addr, size_t len) { return mprotect(addr, len, PROT_READ | PROT_WRITE | PROT_EXEC); } desmume/src/utils/AsmJit/core/cpuinfo.h000664 001750 001750 00000006653 12755534123 021244 0ustar00sergiosergio000000 000000 // [AsmJit] // Complete JIT Assembler for C++ Language. // // [License] // Zlib - See COPYING file in this package. // [Guard] #ifndef _ASMJIT_CORE_CPUINFO_H #define _ASMJIT_CORE_CPUINFO_H // [Dependencies - AsmJit] #include "../core/build.h" // [Api-Begin] #include "../core/apibegin.h" namespace AsmJit { //! @addtogroup AsmJit_Core //! @{ // ============================================================================ // [AsmJit::CpuInfo] // ============================================================================ //! @brief Informations about host cpu. struct CpuInfo { // -------------------------------------------------------------------------- // [Construction / Destruction] // -------------------------------------------------------------------------- inline CpuInfo(uint32_t size = sizeof(CpuInfo)) : _size(size) { } // -------------------------------------------------------------------------- // [Accessors] // -------------------------------------------------------------------------- //! @brief Get CPU vendor string. inline const char* getVendorString() const { return _vendorString; } //! @brief Get CPU brand string. inline const char* getBrandString() const { return _brandString; } //! @brief Get CPU vendor ID. inline uint32_t getVendorId() const { return _vendorId; } //! @brief Get CPU family ID. inline uint32_t getFamily() const { return _family; } //! @brief Get CPU model ID. inline uint32_t getModel() const { return _model; } //! @brief Get CPU stepping. inline uint32_t getStepping() const { return _stepping; } //! @brief Get CPU count. inline uint32_t getNumberOfProcessors() const { return _numberOfProcessors; } //! @brief Get CPU features. inline uint32_t getFeatures() const { return _features; } //! @brief Get CPU bugs. inline uint32_t getBugs() const { return _bugs; } //! @brief Get whether CPU has feature @a feature. inline bool hasFeature(uint32_t feature) { return (_features & feature) != 0; } //! @brief Get whether CPU has bug @a bug. inline bool hasBug(uint32_t bug) { return (_bugs & bug) != 0; } // -------------------------------------------------------------------------- // [Statics] // -------------------------------------------------------------------------- //! @brief Detect number of processors. ASMJIT_API static uint32_t detectNumberOfProcessors(); //! @brief Get global instance of @ref CpuInfo. ASMJIT_API static const CpuInfo* getGlobal(); // -------------------------------------------------------------------------- // [Members] // -------------------------------------------------------------------------- //! @brief Size of CpuInfo structure (in bytes). uint32_t _size; //! @brief Cpu short vendor string. char _vendorString[16]; //! @brief Cpu long vendor string (brand). char _brandString[64]; //! @brief Cpu vendor id (see @c AsmJit::CpuInfo::VendorId enum). uint32_t _vendorId; //! @brief Cpu family ID. uint32_t _family; //! @brief Cpu model ID. uint32_t _model; //! @brief Cpu stepping. uint32_t _stepping; //! @brief Number of processors or cores. uint32_t _numberOfProcessors; //! @brief Cpu features bitfield, see @c AsmJit::CpuInfo::Feature enum). uint32_t _features; //! @brief Cpu bugs bitfield, see @c AsmJit::CpuInfo::Bug enum). uint32_t _bugs; }; //! @} } // AsmJit namespace // [Api-End] #include "../core/apiend.h" // [Guard] #endif // _ASMJIT_CORE_CPUINFO_H desmume/src/libretro-common/formats/bmp/000700 001750 001750 00000000000 12756420131 021456 5ustar00sergiosergio000000 000000 desmume/src/libretro-common/include/formats/image.h000664 001750 001750 00000004567 12755534123 023614 0ustar00sergiosergio000000 000000 /* RetroArch - A frontend for libretro. * Copyright (C) 2010-2014 - Hans-Kristian Arntzen * Copyright (C) 2011-2016 - Daniel De Matteis * * RetroArch is free software: you can redistribute it and/or modify it under the terms * of the GNU General Public License as published by the Free Software Found- * ation, either version 3 of the License, or (at your option) any later version. * * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along with RetroArch. * If not, see . */ #ifndef __RARCH_IMAGE_CONTEXT_H #define __RARCH_IMAGE_CONTEXT_H #include #include #include RETRO_BEGIN_DECLS enum image_process_code { IMAGE_PROCESS_ERROR = -2, IMAGE_PROCESS_ERROR_END = -1, IMAGE_PROCESS_NEXT = 0, IMAGE_PROCESS_END = 1 }; struct texture_image { unsigned width; unsigned height; uint32_t *pixels; }; enum image_type_enum { IMAGE_TYPE_NONE = 0, IMAGE_TYPE_PNG, IMAGE_TYPE_JPEG, IMAGE_TYPE_BMP, IMAGE_TYPE_TGA }; bool image_texture_set_color_shifts(unsigned *r_shift, unsigned *g_shift, unsigned *b_shift, unsigned *a_shift); bool image_texture_color_convert(unsigned r_shift, unsigned g_shift, unsigned b_shift, unsigned a_shift, struct texture_image *out_img); bool image_texture_load(struct texture_image *img, const char *path); void image_texture_free(struct texture_image *img); void image_texture_set_rgba(void); void image_texture_unset_rgba(void); /* Image transfer */ void image_transfer_free(void *data, enum image_type_enum type); void *image_transfer_new(enum image_type_enum type); bool image_transfer_start(void *data, enum image_type_enum type); void image_transfer_set_buffer_ptr( void *data, enum image_type_enum type, void *ptr); int image_transfer_process( void *data, enum image_type_enum type, uint32_t **buf, size_t size, unsigned *width, unsigned *height); bool image_transfer_iterate(void *data, enum image_type_enum type); bool image_transfer_is_valid(void *data, enum image_type_enum type); RETRO_END_DECLS #endif desmume/src/libretro-common/include/libco.h000664 001750 001750 00000004373 12755534123 022142 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2016 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (libco.h). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef LIBCO_H #define LIBCO_H #include #ifdef LIBCO_C #ifdef LIBCO_MP #define thread_local __thread #else #define thread_local #endif #endif RETRO_BEGIN_DECLS typedef void* cothread_t; /** * co_active: * * Gets the currently active context. * * Returns: active context. **/ cothread_t co_active(void); /** * co_create: * @int : stack size * @funcptr : thread entry function callback * * Create a co_thread. * * Returns: cothread if successful, otherwise NULL. */ cothread_t co_create(unsigned int, void (*)(void)); /** * co_delete: * @cothread : cothread object * * Frees a co_thread. */ void co_delete(cothread_t cothread); /** * co_switch: * @cothread : cothread object to switch to * * Do a context switch to @cothread. */ void co_switch(cothread_t cothread); RETRO_END_DECLS /* ifndef LIBCO_H */ #endif desmume/src/readwrite.h000664 001750 001750 00000004466 12755534123 016310 0ustar00sergiosergio000000 000000 /* Copyright (C) 2008-2015 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the this software. If not, see . */ #ifndef _READWRITE_H_ #define _READWRITE_H_ #include #include #include #include #include "types.h" class EMUFILE; //well. just for the sake of consistency int write8le(u8 b, EMUFILE *fp); int write16le(u16 b, EMUFILE* os); int write32le(u32 b, EMUFILE* os); int write64le(u64 b, EMUFILE* os); int read8le(u8 *Bufo, EMUFILE*is); int read16le(u16 *Bufo, EMUFILE*is); int read32le(u32 *Bufo, EMUFILE*is); int read64le(u64 *Bufo, EMUFILE*is); static INLINE int write8le(u8* b, EMUFILE *fp) { return write8le(*b,fp); } static INLINE int write_double_le(double b, EMUFILE*is) { u64 temp = double_to_u64(b); int ret = write64le(temp,is); return ret; } static INLINE int read16le(s16 *Bufo, EMUFILE*is) { return read16le((u16*)Bufo,is); } static INLINE int read32le(s32 *Bufo, EMUFILE*is) { return read32le((u32*)Bufo,is); } static INLINE int read_double_le(double *Bufo, EMUFILE*is) { u64 temp; int ret = read64le(&temp,is); *Bufo = u64_to_double(temp); return ret; } int read16le(u16 *Bufo, std::istream *is); template static INLINE int readle(T *Bufo, EMUFILE*is) { retro_assert(sizeof(T)==1||sizeof(T)==2||sizeof(T)==4||sizeof(T)==8); switch(sizeof(T)) { case 1: return read8le((u8*)Bufo,is); case 2: return read16le((u16*)Bufo,is); case 4: return read32le((u32*)Bufo,is); case 8: return read64le((u64*)Bufo,is); default: break; } return 0; } int readbool(bool *b, EMUFILE* is); void writebool(bool b, EMUFILE* os); int readbuffer(std::vector &vec, EMUFILE* is); int writebuffer(std::vector& vec, EMUFILE* os); #endif desmume/gpu-moderender.diff000664 001750 001750 00000010071 12755534123 017116 0ustar00sergiosergio000000 000000 diff --git a/desmume/src/GPU.cpp b/desmume/src/GPU.cpp index 993f452..fb36fff 100644 --- a/desmume/src/GPU.cpp +++ b/desmume/src/GPU.cpp @@ -1307,23 +1307,13 @@ FORCEINLINE void apply_rot_fun(GPU *gpu, const BGxPARMS ¶m, const u16 LG, co rot_scale_op(gpu, param, LG, wh, ht, map, tile, pal); } - -template -FORCEINLINE void rotBG2(GPU *gpu, const BGxPARMS ¶m, const u16 LG) -{ - const size_t num = gpu->currBgNum; - const u16 *pal = (u16 *)(MMU.ARM9_VMEM + gpu->core * ADDRESS_STEP_1KB); -// printf("rot mode\n"); - apply_rot_fun< rot_tiled_8bit_entry >(gpu, param, LG, gpu->BG_map_ram[num], gpu->BG_tile_ram[num], pal); -} - template FORCEINLINE void extRotBG2(GPU *gpu, const BGxPARMS ¶m, const u16 LG) { const size_t num = gpu->currBgNum; struct _DISPCNT * dispCnt = &(gpu->dispx_st)->dispx_DISPCNT.bits; - u16 *pal = NULL; + u16 *pal = (u16 *)(MMU.ARM9_VMEM + gpu->core * ADDRESS_STEP_1KB); switch(gpu->BGTypes[num]) { @@ -1339,10 +1329,11 @@ FORCEINLINE void extRotBG2(GPU *gpu, const BGxPARMS ¶m, const u16 LG) case BGType_AffineExt_256x1: // 256 colors - pal = (u16 *)(MMU.ARM9_VMEM + gpu->core * ADDRESS_STEP_1KB); apply_rot_fun< rot_256_map >(gpu, param, LG, gpu->BG_bmp_ram[num], 0, pal); break; - + case BGType_Affine: + apply_rot_fun< rot_tiled_8bit_entry >(gpu, param, LG, gpu->BG_map_ram[num], gpu->BG_tile_ram[num], pal); + break; case BGType_AffineExt_Direct: // direct colors / BMP apply_rot_fun< rot_BMP_map >(gpu, param, LG, gpu->BG_bmp_ram[num], 0, NULL); @@ -1350,7 +1341,6 @@ FORCEINLINE void extRotBG2(GPU *gpu, const BGxPARMS ¶m, const u16 LG) case BGType_Large8bpp: // large screen 256 colors - pal = (u16 *)(MMU.ARM9_VMEM + gpu->core * ADDRESS_STEP_1KB); apply_rot_fun< rot_256_map >(gpu, param, LG, gpu->BG_bmp_large_ram[num], 0, pal); break; @@ -1359,39 +1349,8 @@ FORCEINLINE void extRotBG2(GPU *gpu, const BGxPARMS ¶m, const u16 LG) } } -/*****************************************************************************/ -// BACKGROUND RENDERING -HELPER FUNCTIONS- -/*****************************************************************************/ - -#if 0 -static void lineNull(GPU *gpu) -{ -} -#endif - template void lineText(GPU *gpu) { - const u16 vofs = gpu->getVOFS(gpu->currBgNum); - const u16 hofs = gpu->getHOFS(gpu->currBgNum); - renderline_textBG(gpu, hofs, gpu->currLine + vofs, 256); -} - -template void lineRot(GPU *gpu) -{ - BGxPARMS ¶ms = (gpu->currBgNum == 2) ? (gpu->dispx_st)->dispx_BG2PARMS : (gpu->dispx_st)->dispx_BG3PARMS; - - rotBG2(gpu, params, 256); - params.BGxX += params.BGxPB; - params.BGxY += params.BGxPD; -} - -template void lineExtRot(GPU *gpu) -{ - BGxPARMS ¶ms = (gpu->currBgNum == 2) ? (gpu->dispx_st)->dispx_BG2PARMS : (gpu->dispx_st)->dispx_BG3PARMS; - - extRotBG2(gpu, params, 256); - params.BGxX += params.BGxPB; - params.BGxY += params.BGxPD; } /*****************************************************************************/ @@ -2954,10 +2913,20 @@ template void GPU::modeRender(const size_t layer) { switch(GPU_mode2type[dispCnt().BG_Mode][layer]) { - case BGType_Text: lineText(this); break; - case BGType_Affine: lineRot(this); break; - case BGType_AffineExt: lineExtRot(this); break; - case BGType_Large8bpp: lineExtRot(this); break; + case BGType_Text: + renderline_textBG(this, getHOFS(layer), currLine + getVOFS(layer), 256); + break; + case BGType_Affine: + case BGType_AffineExt: + case BGType_Large8bpp: + { + BGxPARMS ¶ms = (layer == 2) ? (dispx_st)->dispx_BG2PARMS : (dispx_st)->dispx_BG3PARMS; + + extRotBG2(this, params, 256); + params.BGxX += params.BGxPB; + params.BGxY += params.BGxPD; + } + break; case BGType_Invalid: PROGINFO("Attempting to render an invalid BG type\n"); break; desmume/src/addons/slot2_guitarGrip.cpp000664 001750 001750 00000003043 12755534123 021353 0ustar00sergiosergio000000 000000 /* Copyright (C) 2009 CrazyMax Copyright (C) 2009-2013 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the this software. If not, see . */ #include "../slot2.h" static u8 guitarKeyStatus; class Slot2_GuitarGrip : public ISlot2Interface { private: public: virtual Slot2Info const* info() { static Slot2InfoSimple info("Guitar Grip", "Guitar Grip for Guitar Hero games", 0x04); return &info; } virtual void connect() { guitarKeyStatus = 0; } virtual u8 readByte(u8 PROCNUM, u32 addr) { if (addr == 0x0A000000) return (~guitarKeyStatus); return (addr & 1)?0xF9:0xFF; } virtual u16 readWord(u8 PROCNUM, u32 addr) { return 0xF9FF; } virtual u32 readLong(u8 PROCNUM, u32 addr) { return 0xF9FFF9FF; } }; ISlot2Interface* construct_Slot2_GuitarGrip() { return new Slot2_GuitarGrip(); } void guitarGrip_setKey(bool green, bool red, bool yellow, bool blue) { guitarKeyStatus = 0 | (green << 6) | (red << 5) | (yellow << 4) | (blue << 3); } desmume/src/libretro-common/formats/tga/000700 001750 001750 00000000000 12756420131 021453 5ustar00sergiosergio000000 000000 desmume/src/libretro-common/vulkan/000700 001750 001750 00000000000 12756420131 020525 5ustar00sergiosergio000000 000000 desmume/src/utils/emufat.cpp000664 001750 001750 00000173703 12755534123 017277 0ustar00sergiosergio000000 000000 /* Copyright 2009-2015 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the this software. If not, see . */ //based on Arduino SdFat Library ( http://code.google.com/p/sdfatlib/ ) //Copyright (C) 2009 by William Greiman //based on mkdosfs - utility to create FAT/MS-DOS filesystems //Copyright (C) 1991 Linus Torvalds //Copyright (C) 1992-1993 Remy Card //Copyright (C) 1993-1994 David Hudson //Copyright (C) 1998 H. Peter Anvin //Copyright (C) 1998-2005 Roman Hodek #include "emufat.h" #include #include #include #include #include "../emufile.h" #define LE16(x) (x) #define LE32(x) (x) #define MAX_CLUST_12 ((1 << 12) - 16) #define MAX_CLUST_16 ((1 << 16) - 16) #define MIN_CLUST_32 65529 /* M$ says the high 4 bits of a FAT32 FAT entry are reserved and don't belong * to the cluster number. So the max. cluster# is based on 2^28 */ #define MAX_CLUST_32 ((1 << 28) - 16) #define FAT12_THRESHOLD 4085 #define MSDOS_EXT_SIGN 0x29 /* extended boot sector signature */ #define MSDOS_FAT12_SIGN "FAT12 " /* FAT12 filesystem signature */ #define MSDOS_FAT16_SIGN "FAT16 " /* FAT16 filesystem signature */ #define MSDOS_FAT32_SIGN "FAT32 " /* FAT32 filesystem signature */ static const int sector_size = 512; #define BLOCK_SIZE 512 #define HARD_SECTOR_SIZE 512 #define SECTORS_PER_BLOCK ( BLOCK_SIZE / HARD_SECTOR_SIZE ) #define FAT_EOF (0x0ffffff8) #define BOOT_SIGN 0xAA55 /* Boot sector magic number */ struct __PACKED fat32_fsinfo { u32 reserved1; /* Nothing as far as I can tell */ u32 signature; /* 0x61417272L */ u32 free_clusters; /* Free cluster count. -1 if unknown */ u32 next_cluster; /* Most recently allocated cluster. * Unused under Linux. */ u32 reserved2[4]; }; //see mkdosfs for the disassembly static const u8 mkdosfs_bootcode_fat32[420] = { 0x0E, 0x1F, 0xBE, 0x77, 0x7C, 0xAC, 0x22, 0xC0, 0x74, 0x0B, 0x56, 0xB4, 0x0E, 0xBB, 0x07, 0x00, 0xCD, 0x10, 0x5E, 0xEB, 0xF0, 0x32, 0xE4, 0xCD, 0x16, 0xCD, 0x19, 0xEB, 0xFE, 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x6E, 0x6F, 0x74, 0x20, 0x61, 0x20, 0x62, 0x6F, 0x6F, 0x74, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x64, 0x69, 0x73, 0x6B, 0x2E, 0x20, 0x20, 0x50, 0x6C, 0x65, 0x61, 0x73, 0x65, 0x20, 0x69, 0x6E, 0x73, 0x65, 0x72, 0x74, 0x20, 0x61, 0x20, 0x62, 0x6F, 0x6F, 0x74, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x66, 0x6C, 0x6F, 0x70, 0x70, 0x79, 0x20, 0x61, 0x6E, 0x64, 0x0D, 0x0A, 0x70, 0x72, 0x65, 0x73, 0x73, 0x20, 0x61, 0x6E, 0x79, 0x20, 0x6B, 0x65, 0x79, 0x20, 0x74, 0x6F, 0x20, 0x74, 0x72, 0x79, 0x20, 0x61, 0x67, 0x61, 0x69, 0x6E, 0x20, 0x2E, 0x2E, 0x2E, 0x20, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; EmuFat::EmuFat(const char* fname, bool readonly) : m_readonly(readonly) , m_owns(true) { m_pFile = new EMUFILE_FILE(fname,readonly?"rb":"rb+"); } EmuFat::EmuFat() : m_readonly(false) , m_owns(true) { m_pFile = new EMUFILE_MEMORY(); } EmuFat::EmuFat(EMUFILE* fileNotToDelete) : m_pFile(fileNotToDelete) , m_owns(false) , m_readonly(false) { } EmuFat::~EmuFat() { cacheFlush(); if(m_owns) delete m_pFile; } u8 EmuFat::cacheRawBlock(u32 blockNumber, u8 action) { if (cache_.cacheBlockNumber_ != blockNumber) { if (!cacheFlush()) return false; if (!readBlock(blockNumber, cache_.cacheBuffer_.data)) return false; cache_.cacheBlockNumber_ = blockNumber; } cache_.cacheDirty_ |= action; return true; } u8 EmuFat::cacheZeroBlock(u32 blockNumber) { if (!cacheFlush()) return false; // loop take less flash than memset(cacheBuffer_.data, 0, 512); for (u16 i = 0; i < 512; i++) { cache_.cacheBuffer_.data[i] = 0; } cache_.cacheBlockNumber_ = blockNumber; cacheSetDirty(); return true; } void EmuFat::cacheReset() { reconstruct(&cache_); } u8 EmuFat::cacheFlush() { if (cache_.cacheDirty_) { if (!writeBlock(cache_.cacheBlockNumber_, cache_.cacheBuffer_.data)) { return false; } // mirror FAT tables if (cache_.cacheMirrorBlock_) { if (!writeBlock(cache_.cacheMirrorBlock_, cache_.cacheBuffer_.data)) { return false; } cache_.cacheMirrorBlock_ = 0; } cache_.cacheDirty_ = 0; } return true; } u8 EmuFat::readBlock(u32 block, u8* dst) { m_pFile->fseek(block*512,SEEK_SET); m_pFile->fread(dst,512); if(m_pFile->fail()) { m_pFile->unfail(); return 0; } return 1; } u8 EmuFat::writeBlock(u32 blockNumber, const u8* src) { m_pFile->fseek(blockNumber*512,SEEK_SET); m_pFile->fwrite(src,512); if(m_pFile->fail()) { m_pFile->unfail(); return 0; } return 1; } u8 EmuFat::readData(u32 block, u16 offset, u16 count, u8* dst) { m_pFile->fseek(block*512+offset,SEEK_SET); m_pFile->fread(dst,count); if(m_pFile->fail()) { m_pFile->unfail(); return 0; } return 1; } void EmuFat::truncate(u32 size) { m_pFile->truncate(size); } //------------------------------------------------------------------------------------- inline int cdiv (int a, int b) { return (a + b - 1) / b; } bool calculateClusterSize(TFat32BootSector* bsp, u32 avail_sectors, u32& cluster_count, u32& fat_length, int size_fat_by_user, int &size_fat) { TFat32BootSector &bs = *bsp; const u32 fatdata = avail_sectors; int maxclustsize = bsp->sectorsPerCluster; u32 fatlength12, fatlength16, fatlength32; u32 maxclust12, maxclust16, maxclust32; u32 clust12, clust16, clust32; do { printf( "Trying with %d sectors/cluster:\n", bs.sectorsPerCluster ); /* The factor 2 below avoids cut-off errors for nr_fats == 1. * The "nr_fats*3" is for the reserved first two FAT entries */ clust12 = 2*((u64) fatdata *sector_size + bs.fatCount*3) / (2*(int) bs.sectorsPerCluster * sector_size + bs.fatCount*3); fatlength12 = cdiv (((clust12+2) * 3 + 1) >> 1, sector_size); /* Need to recalculate number of clusters, since the unused parts of the * FATS and data area together could make up space for an additional, * not really present cluster. */ clust12 = (fatdata - bs.fatCount*fatlength12)/bs.sectorsPerCluster; maxclust12 = (fatlength12 * 2 * sector_size) / 3; if (maxclust12 > MAX_CLUST_12) maxclust12 = MAX_CLUST_12; printf( "FAT12: #clu=%u, fatlen=%u, maxclu=%u, limit=%u\n", clust12, fatlength12, maxclust12, MAX_CLUST_12 ); if (clust12 > maxclust12-2) { clust12 = 0; printf( "FAT12: too much clusters\n" ); } clust16 = ((u64) fatdata *sector_size + bs.fatCount*4) / ((int) bs.sectorsPerCluster * sector_size + bs.fatCount*2); fatlength16 = cdiv ((clust16+2) * 2, sector_size); /* Need to recalculate number of clusters, since the unused parts of the * FATS and data area together could make up space for an additional, * not really present cluster. */ clust16 = (fatdata - bs.fatCount*fatlength16)/bs.sectorsPerCluster; maxclust16 = (fatlength16 * sector_size) / 2; if (maxclust16 > MAX_CLUST_16) maxclust16 = MAX_CLUST_16; printf( "FAT16: #clu=%u, fatlen=%u, maxclu=%u, limit=%u\n", clust16, fatlength16, maxclust16, MAX_CLUST_16 ); if (clust16 > maxclust16-2) { printf( "FAT16: too much clusters\n" ); clust16 = 0; } /* The < 4078 avoids that the filesystem will be misdetected as having a * 12 bit FAT. */ if (clust16 < FAT12_THRESHOLD && !(size_fat_by_user && size_fat == 16)) { printf( clust16 < FAT12_THRESHOLD ? "FAT16: would be misdetected as FAT12\n" : "FAT16: too much clusters\n" ); clust16 = 0; } clust32 = ((u64) fatdata *sector_size + bs.fatCount*8) / ((int) bs.sectorsPerCluster * sector_size + bs.fatCount*4); fatlength32 = cdiv ((clust32+2) * 4, sector_size); /* Need to recalculate number of clusters, since the unused parts of the * FATS and data area together could make up space for an additional, * not really present cluster. */ clust32 = (fatdata - bs.fatCount*fatlength32)/bs.sectorsPerCluster; maxclust32 = (fatlength32 * sector_size) / 4; if (maxclust32 > MAX_CLUST_32) maxclust32 = MAX_CLUST_32; if (clust32 && clust32 < MIN_CLUST_32 && !(size_fat_by_user && size_fat == 32)) { clust32 = 0; printf( "FAT32: not enough clusters (%d)\n", MIN_CLUST_32); } printf( "FAT32: #clu=%u, fatlen=%u, maxclu=%u, limit=%u\n", clust32, fatlength32, maxclust32, MAX_CLUST_32 ); if (clust32 > maxclust32) { clust32 = 0; printf( "FAT32: too much clusters\n" ); } if ((clust12 && (size_fat == 0 || size_fat == 12)) || (clust16 && (size_fat == 0 || size_fat == 16)) || (clust32 && size_fat == 32)) break; bs.sectorsPerCluster <<= 1; } while (bs.sectorsPerCluster && bs.sectorsPerCluster <= maxclustsize); /* Use the optimal FAT size if not specified; * FAT32 is (not yet) choosen automatically */ if (!size_fat) { size_fat = (clust16 > clust12) ? 16 : 12; printf( "Choosing %d bits for FAT\n", size_fat ); } switch (size_fat) { case 12: cluster_count = clust12; fat_length = fatlength12; bs.sectorsPerFat16 = LE16(fatlength12); break; case 16: if (clust16 < FAT12_THRESHOLD) { if (size_fat_by_user) { printf("WARNING: Not enough clusters for a " "16 bit FAT! The filesystem will be\n" "misinterpreted as having a 12 bit FAT without " "mount option \"fat=16\".\n" ); return false; } else { printf("This filesystem has an unfortunate size. " "A 12 bit FAT cannot provide\n" "enough clusters, but a 16 bit FAT takes up a little " "bit more space so that\n" "the total number of clusters becomes less than the " "threshold value for\n" "distinction between 12 and 16 bit FATs.\n" ); return false; } } cluster_count = clust16; fat_length = fatlength16; bs.sectorsPerFat16 = LE16(fatlength16); break; case 32: if (clust32 < MIN_CLUST_32) printf("WARNING: Not enough clusters for a 32 bit FAT!\n"); cluster_count = clust32; fat_length = fatlength32; bs.sectorsPerFat16 = LE16(0); bs.fat32.sectorsPerFat32 = LE32(fatlength32); break; } return true; } static void mark_FAT_cluster (int size_fat, u8* fat, int cluster, unsigned int value) { switch( size_fat ) { case 12: value &= 0x0fff; if (((cluster * 3) & 0x1) == 0) { fat[3 * cluster / 2] = (unsigned char) (value & 0x00ff); fat[(3 * cluster / 2) + 1] = (unsigned char) ((fat[(3 * cluster / 2) + 1] & 0x00f0) | ((value & 0x0f00) >> 8)); } else { fat[3 * cluster / 2] = (unsigned char) ((fat[3 * cluster / 2] & 0x000f) | ((value & 0x000f) << 4)); fat[(3 * cluster / 2) + 1] = (unsigned char) ((value & 0x0ff0) >> 4); } break; case 16: value &= 0xffff; fat[2 * cluster] = (unsigned char) (value & 0x00ff); fat[(2 * cluster) + 1] = (unsigned char) (value >> 8); break; case 32: value &= 0xfffffff; fat[4 * cluster] = (unsigned char) (value & 0x000000ff); fat[(4 * cluster) + 1] = (unsigned char) ((value & 0x0000ff00) >> 8); fat[(4 * cluster) + 2] = (unsigned char) ((value & 0x00ff0000) >> 16); fat[(4 * cluster) + 3] = (unsigned char) ((value & 0xff000000) >> 24); break; } } //use 36M as minimum fat32 size (or else mkdosfs complains) //this function assumes fat32. it could be redone to be intelligent by making another pass through mkdosfs and analyzing it again //but we onnly targeted fat32 our first time through bool EmuFatVolume::formatNew(u32 sectors) { u32 volumeStartBlock = 0; TFat32BootSector bsrec; memset(&bsrec,0,sizeof(TFat32BootSector)); TFat32BootSector *bs = &bsrec; //perform same analysis (we guess) as mkdosfs //"fake values" bs->sectorsPerTrack = 32; bs->headCount = 64; //def_hd_params: bs->mediaType = 0xF8; bs->rootDirEntryCount = LE16(512); //Default to 512 entries - N.B. this is overwritten later static const u32 BLOCK_SIZE_BITS = 9; const u32 sz_mb = (sectors+(1<<(20-BLOCK_SIZE_BITS))-1) >> (20-BLOCK_SIZE_BITS); bs->sectorsPerCluster = sz_mb > 16*1024 ? 32 : sz_mb > 8*1024 ? 16 : sz_mb > 260 ? 8 : 1; //(fat16 and fat12 would start at 4 sectors per cluster) memcpy (bs->oemName, "mkdosfs", 8); bs->rootDirEntryCount = 0; //Under FAT32, the root dir is in a cluster chain, and this is signalled by bs.dir_entries being 0 bs->fat32.vi.volume_id = 0; //not generating a volume id.. just use 0 for determinism's sake memcpy(bs->fat32.vi.volume_label," ",11); bs->jmpToBootCode[0] = 0xEB; bs->jmpToBootCode[1] = 0x58; //this value is only for fat32 //Patch in the correct offset to the boot code bs->jmpToBootCode[2] = 0x90; memcpy(bs->fat32.boot_code,mkdosfs_bootcode_fat32,420); bs->boot_sign[0] = 0x55; bs->boot_sign[1] = 0xAA; bs->reservedSectorCount = LE16(32); bs->fatCount = 2; bs->hiddenSectors = LE32(0); u32 fatdata = sectors - cdiv (bs->rootDirEntryCount * 32, 512) - bs->reservedSectorCount; u32 cluster_count; u32 fat_length; int size_fat = 32; if(!calculateClusterSize(bs, fatdata, cluster_count, fat_length, 1, size_fat)) return false; //TODO - this function whacks values we set earlier. gross. either mkdosfs is sloppy or i dont understand it. //anyway, whack that dup code switch(size_fat) { case 12: memcpy(bs->oldfat.vi.fs_type, MSDOS_FAT12_SIGN, 8); break; case 16: memcpy(bs->oldfat.vi.fs_type, MSDOS_FAT16_SIGN, 8); break; case 32: memcpy(bs->fat32.vi.fs_type, MSDOS_FAT32_SIGN, 8); break; } bs->bytesPerSector = 512; //set up additional FAT32 fields bs->fat32.fat32Flags = LE16(0); bs->fat32.fat32Version = LE16(0); bs->fat32.fat32RootCluster = LE32(2); bs->fat32.fat32FSInfo = LE16(1); u32 backup_boot = (bs->reservedSectorCount>= 7) ? 6 : (bs->reservedSectorCount >= 2) ? bs->reservedSectorCount-1 : 0; printf( "Using sector %d as backup boot sector (0 = none)\n",backup_boot ); bs->fat32.fat32BackBootBlock = LE16(backup_boot); memset(bs->fat32.fat32Reserved,0,sizeof(bs->fat32.fat32Reserved)); if(sectors>= 65536) { bs->totalSectors16 = LE16(0); bs->totalSectors32 = LE32(sectors); } else { bs->totalSectors16 = LE16(sectors); bs->totalSectors32 = LE32(0); } if (!cluster_count) { //if (sectors_per_cluster) /* If yes, die if we'd spec'd sectors per cluster */ // die ("Too many clusters for file system - try more sectors per cluster"); //else printf("Attempting to create a too large file system"); return false; } u32 start_data_sector = (bs->reservedSectorCount + bs->fatCount * fat_length) * (sector_size/512); u32 start_data_block = (start_data_sector + SECTORS_PER_BLOCK - 1) / SECTORS_PER_BLOCK; if (sectors < start_data_block + 32) /* Arbitrary undersize file system! */ { printf("Too few blocks for viable file system"); return false; } bs->fat32.vi.ext_boot_sign = MSDOS_EXT_SIGN; //Make the file allocation tables! u8* fat = new u8[fat_length * sector_size]; memset( fat, 0, fat_length * sector_size ); mark_FAT_cluster (size_fat, fat, 0, 0xffffffff); /* Initial fat entries */ mark_FAT_cluster (size_fat, fat, 1, 0xffffffff); fat[0] = bs->mediaType; /* Put media type in first byte! */ if (size_fat == 32) { /* Mark cluster 2 as EOF (used for root dir) */ mark_FAT_cluster (size_fat, fat, 2, FAT_EOF); } u32 size_root_dir = (size_fat == 32) ? bs->sectorsPerCluster*sector_size : bs->rootDirEntryCount * sizeof (TDirectoryEntry); //u8* root_dir = new u8[size_root_dir]; //memset(root_dir, 0, size_root_dir); u32 size_root_dir_in_sectors = size_root_dir/512; u8* info_sector = NULL; if (size_fat == 32) { /* For FAT32, create an info sector */ fat32_fsinfo *info; info_sector = new u8[sector_size]; memset(info_sector, 0, sector_size); /* fsinfo structure is at offset 0x1e0 in info sector by observation */ info = (fat32_fsinfo *)(info_sector + 0x1e0); /* Info sector magic */ info_sector[0] = 'R'; info_sector[1] = 'R'; info_sector[2] = 'a'; info_sector[3] = 'A'; /* Magic for fsinfo structure */ info->signature = LE32(0x61417272); /* We've allocated cluster 2 for the root dir. */ info->free_clusters = LE32(cluster_count - 1); info->next_cluster = LE32(2); /* Info sector also must have boot sign */ *(u16 *)(info_sector + 0x1fe) = LE16(BOOT_SIGN); } //------------- //write_tables() u8* blank_sector = new u8[512]; memset(blank_sector,0,512); dev_->cacheReset(); dev_->truncate(0); dev_->truncate(sectors*512); /* clear all reserved sectors */ for(int i=0;ireservedSectorCount;i++) dev_->writeBlock(0,blank_sector); /* seek back to sector 0 and write the boot sector */ dev_->writeBlock(0,(const u8*)bs); /* on FAT32, write the info sector and backup boot sector */ if (size_fat == 32) { dev_->writeBlock(bs->fat32.fat32FSInfo,info_sector); if(bs->fat32.fat32BackBootBlock) dev_->writeBlock(bs->fat32.fat32BackBootBlock,(const u8*)bs); } /* seek to start of FATS and write them all */ int ctr=bs->reservedSectorCount; for (int i=0;ifatCount;i++) for(int j=0;jwriteBlock(ctr,fat+j*sector_size); /* Write the root directory directly after the last FAT. This is the root * dir area on FAT12/16, and the first cluster on FAT32. */ for(int i=0;iwriteBlock(ctr,blank_sector); delete[] blank_sector; delete[] info_sector; delete[] fat; return init(dev_,0); //return true; } //well, there are a lot of ways to format a disk. this is just a simple one. //it would be nice if someone who understood fat better could modify the root //directory setup to use reasonable code instead of magic arrays bool EmuFatVolume::format(u32 sectors) { //u32 volumeStartBlock = 0; //dev_->truncate(0); //dev_->truncate(sectors*512); //if (!dev_->cacheRawBlock(volumeStartBlock, EmuFat::CACHE_FOR_WRITE)) return false; //memset(&dev_->cache_.cacheBuffer_,0,sizeof(dev_->cache_.cacheBuffer_)); //TFat32BootSector* bs = &dev_->cache_.cacheBuffer_.fbs; //TBiosParmBlock* bpb = &bs->bpb; //bs->jmpToBootCode[0] = 0xEB; //bs->jmpToBootCode[1] = 0x3C; //bs->jmpToBootCode[2] = 0x90; //memcpy(bs->oemName,"mkdosfs",8); //bs->driveNumber = 0; //bs->reserved1 = 0; //bs->bootSignature = 0x29; //bs->volumeSerialNumber = 0; //memcpy(bs->volumeLabel," ",11); //memcpy(bs->fileSystemType,"FAT16 ",8); //memcpy(bs->bootCode,mkdosfs_bootcode,420); //bs->bootSectorSig0 = 0x55; //bs->bootSectorSig1 = 0xAA; //bpb->bytesPerSector = 512; //bpb->sectorsPerCluster = 4; //bpb->reservedSectorCount = 1; //bpb->fatCount = 2; //bpb->rootDirEntryCount = 512; //bpb->totalSectors16 = 0; //bpb->mediaType = 0xF8; //bpb->sectorsPerFat16 = 32; //bpb->sectorsPerTrack = 32; //bpb->headCount = 64; //bpb->hiddenSectors = 0; //bpb->totalSectors32 = sectors; //bpb->fat32Flags = 0xbe0d; //bpb->fat32Version = 0x20Fd; //bpb->fat32RootCluster = 0x20202020; //bpb->fat32FSInfo = 0x2020; //bpb->fat32BackBootBlock = 0x2020; //if(!dev_->cacheFlush()) // return false; //if (!dev_->cacheRawBlock(1, EmuFat::CACHE_FOR_WRITE)) return false; //static const u8 rootEntry[8] = //{ // 0xF8, 0xFF, 0xFF, 0xFF, //} ; //memcpy(dev_->cache_.cacheBuffer_.data,rootEntry,4); //if(!dev_->cacheFlush()) // return false; //if (!dev_->cacheRawBlock(33, EmuFat::CACHE_FOR_WRITE)) return false; //memcpy(dev_->cache_.cacheBuffer_.data,rootEntry,4); //if(!dev_->cacheFlush()) // return false; //return init(dev_,0); return false; } bool EmuFatVolume::init(EmuFat* dev, u8 part) { u32 volumeStartBlock = 0; dev_ = dev; // if part == 0 assume super floppy with FAT boot sector in block zero // if part > 0 assume mbr volume with partition table if (part) { if (part > 4) return false; if (!dev->cacheRawBlock(volumeStartBlock, EmuFat::CACHE_FOR_READ)) return false; TPartitionRecord* p = &dev->cache_.cacheBuffer_.mbr.part[part-1]; if ((p->boot & 0X7F) !=0 || p->totalSectors < 100 || p->firstSector == 0) { // not a valid partition return false; } volumeStartBlock = p->firstSector; } if (!dev->cacheRawBlock(volumeStartBlock, EmuFat::CACHE_FOR_READ)) return false; TFat32BootSector* bs = &dev->cache_.cacheBuffer_.fbs; if (bs->bytesPerSector != 512 || bs->fatCount == 0 || bs->reservedSectorCount == 0 || bs->sectorsPerCluster == 0) { // not valid FAT volume return false; } fatCount_ = bs->fatCount; blocksPerCluster_ = bs->sectorsPerCluster; // determine shift that is same as multiply by blocksPerCluster_ clusterSizeShift_ = 0; while (blocksPerCluster_ != (1 << clusterSizeShift_)) { // error if not power of 2 if (clusterSizeShift_++ > 7) return false; } blocksPerFat_ = bs->sectorsPerFat16 ? bs->sectorsPerFat16 : bs->fat32.sectorsPerFat32; fatStartBlock_ = volumeStartBlock + bs->reservedSectorCount; // count for FAT16 zero for FAT32 rootDirEntryCount_ = bs->rootDirEntryCount; // directory start for FAT16 dataStart for FAT32 rootDirStart_ = fatStartBlock_ + bs->fatCount * blocksPerFat_; // data start for FAT16 and FAT32 dataStartBlock_ = rootDirStart_ + ((32 * bs->rootDirEntryCount + 511)/512); // total blocks for FAT16 or FAT32 u32 totalBlocks = bs->totalSectors16 ? bs->totalSectors16 : bs->totalSectors32; // total data blocks clusterCount_ = totalBlocks - (dataStartBlock_ - volumeStartBlock); // divide by cluster size to get cluster count clusterCount_ >>= clusterSizeShift_; // FAT type is determined by cluster count if (clusterCount_ < 4085) { fatType_ = 12; } else if (clusterCount_ < 65525) { fatType_ = 16; } else { rootDirStart_ = bs->fat32.fat32RootCluster; fatType_ = 32; } return true; } u8 EmuFatVolume::allocContiguous(u32 count, u32* curCluster) { // start of group u32 bgnCluster; // flag to save place to start next search u8 setStart; // set search start cluster if (*curCluster) { // try to make file contiguous bgnCluster = *curCluster + 1; // don't save new start location setStart = false; } else { // start at likely place for free cluster bgnCluster = allocSearchStart_; // save next search start if one cluster setStart = 1 == count; } // end of group u32 endCluster = bgnCluster; // last cluster of FAT u32 fatEnd = clusterCount_ + 1; // search the FAT for free clusters for (u32 n = 0;; n++, endCluster++) { // can't find space checked all clusters if (n >= clusterCount_) return false; // past end - start from beginning of FAT if (endCluster > fatEnd) { bgnCluster = endCluster = 2; } u32 f; if (!fatGet(endCluster, &f)) return false; if (f != 0) { // cluster in use try next cluster as bgnCluster bgnCluster = endCluster + 1; } else if ((endCluster - bgnCluster + 1) == count) { // done - found space break; } } // mark end of chain if (!fatPutEOC(endCluster)) return false; // link clusters while (endCluster > bgnCluster) { if (!fatPut(endCluster - 1, endCluster)) return false; endCluster--; } if (*curCluster != 0) { // connect chains if (!fatPut(*curCluster, bgnCluster)) return false; } // return first cluster number to caller *curCluster = bgnCluster; // remember possible next free cluster if (setStart) allocSearchStart_ = bgnCluster + 1; return true; } u8 EmuFatVolume::fatGet(u32 cluster, u32* value) const { if (cluster > (clusterCount_ + 1)) return false; u32 lba = fatStartBlock_; lba += fatType_ == 16 ? cluster >> 8 : cluster >> 7; if (lba != dev_->cache_.cacheBlockNumber_) { if (!dev_->cacheRawBlock(lba, EmuFat::CACHE_FOR_READ)) return false; } if (fatType_ == 16) { *value = dev_->cache_.cacheBuffer_.fat16[cluster & 0XFF]; } else { *value = dev_->cache_.cacheBuffer_.fat32[cluster & 0X7F] & FAT32MASK; } return true; } // Store a FAT entry u8 EmuFatVolume::fatPut(u32 cluster, u32 value) { // error if reserved cluster if (cluster < 2) return false; // error if not in FAT if (cluster > (clusterCount_ + 1)) return false; // calculate block address for entry u32 lba = fatStartBlock_; lba += fatType_ == 16 ? cluster >> 8 : cluster >> 7; if (lba != dev_->cache_.cacheBlockNumber_) { if (!dev_->cacheRawBlock(lba, EmuFat::CACHE_FOR_READ)) return false; } // store entry if (fatType_ == 16) { dev_->cache_.cacheBuffer_.fat16[cluster & 0xFF] = value; } else { dev_->cache_.cacheBuffer_.fat32[cluster & 0x7F] = value; } dev_->cacheSetDirty(); // mirror second FAT if (fatCount_ > 1) dev_->cache_.cacheMirrorBlock_ = lba + blocksPerFat_; return true; } // return the size in bytes of a cluster chain u8 EmuFatVolume::chainSize(u32 cluster, u32* size) const { u32 s = 0; do { if (!fatGet(cluster, &cluster)) return false; s += 512UL << clusterSizeShift_; } while (!isEOC(cluster)); *size = s; return true; } // free a cluster chain u8 EmuFatVolume::freeChain(u32 cluster) { // clear free cluster location allocSearchStart_ = 2; do { u32 next; if (!fatGet(cluster, &next)) return false; // free cluster if (!fatPut(cluster, 0)) return false; cluster = next; } while (!isEOC(cluster)); return true; } u8 EmuFatVolume::readData(u32 block, u16 offset, u16 count, u8* dst) { return dev_->readData(block, offset, count, dst); } u8 EmuFatVolume::writeBlock(u32 block, const u8* dst) { return dev_->writeBlock(block, dst); } //----------------------------------------------------------------------------------- //EmuFatFile: // add a cluster to a file u8 EmuFatFile::addCluster() { if (!vol_->allocContiguous(1, &curCluster_)) return false; // if first cluster of file link to directory entry if (firstCluster_ == 0) { firstCluster_ = curCluster_; flags_ |= F_FILE_DIR_DIRTY; } return true; } // Add a cluster to a directory file and zero the cluster. // return with first block of cluster in the cache u8 EmuFatFile::addDirCluster(void) { if (!addCluster()) return false; // zero data in cluster insure first cluster is in cache u32 block = vol_->clusterStartBlock(curCluster_); for (u8 i = vol_->blocksPerCluster_; i != 0; i--) { if (!vol_->dev_->cacheZeroBlock(block + i - 1)) return false; } // Increase directory file size by cluster size fileSize_ += 512UL << vol_->clusterSizeShift_; return true; } // cache a file's directory entry // return pointer to cached entry or null for failure TDirectoryEntry* EmuFatFile::cacheDirEntry(u8 action) { if (!vol_->dev_->cacheRawBlock(dirBlock_, action)) return NULL; return vol_->dev_->cache_.cacheBuffer_.dir + dirIndex_; } /** * Close a file and force cached data and directory information * to be written to the storage device. * * \return The value one, true, is returned for success and * the value zero, false, is returned for failure. * Reasons for failure include no file is open or an I/O error. */ u8 EmuFatFile::close(void) { if (!sync())return false; type_ = FAT_FILE_TYPE_CLOSED; return true; } /** * Check for contiguous file and return its raw block range. * * \param[out] bgnBlock the first block address for the file. * \param[out] endBlock the last block address for the file. * * \return The value one, true, is returned for success and * the value zero, false, is returned for failure. * Reasons for failure include file is not contiguous, file has zero length * or an I/O error occurred. */ u8 EmuFatFile::contiguousRange(u32* bgnBlock, u32* endBlock) { // error if no blocks if (firstCluster_ == 0) return false; for (u32 c = firstCluster_; ; c++) { u32 next; if (!vol_->fatGet(c, &next)) return false; // check for contiguous if (next != (c + 1)) { // error if not end of chain if (!vol_->isEOC(next)) return false; *bgnBlock = vol_->clusterStartBlock(firstCluster_); *endBlock = vol_->clusterStartBlock(c) + vol_->blocksPerCluster_ - 1; return true; } } } //------------------------------------------------------------------------------ /** * Create and open a new contiguous file of a specified size. * * \note This function only supports short DOS 8.3 names. * See open() for more information. * * \param[in] dirFile The directory where the file will be created. * \param[in] fileName A valid DOS 8.3 file name. * \param[in] size The desired file size. * * \return The value one, true, is returned for success and * the value zero, false, is returned for failure. * Reasons for failure include \a fileName contains * an invalid DOS 8.3 file name, the FAT volume has not been initialized, * a file is already open, the file already exists, the root * directory is full or an I/O error. * */ u8 EmuFatFile::createContiguous(EmuFatFile* dirFile, const char* fileName, u32 size) { // don't allow zero length file if (size == 0) return false; if (!open(dirFile, fileName, EO_CREAT | EO_EXCL | EO_RDWR)) return false; // calculate number of clusters needed u32 count = ((size - 1) >> (vol_->clusterSizeShift_ + 9)) + 1; // allocate clusters if (!vol_->allocContiguous(count, &firstCluster_)) { remove(); return false; } fileSize_ = size; // insure sync() will update dir entry flags_ |= F_FILE_DIR_DIRTY; return sync(); } /** * Return a files directory entry * * \param[out] dir Location for return of the files directory entry. * * \return The value one, true, is returned for success and * the value zero, false, is returned for failure. */ u8 EmuFatFile::dirEntry(TDirectoryEntry* dir) { // make sure fields on SD are correct if (!sync()) return false; // read entry TDirectoryEntry* p = cacheDirEntry(EmuFat::CACHE_FOR_READ); if (!p) return false; // copy to caller's struct memcpy(dir, p, sizeof(TDirectoryEntry)); return true; } /** * Format the name field of \a dir into the 13 byte array * \a name in standard 8.3 short name format. * * \param[in] dir The directory structure containing the name. * \param[out] name A 13 byte char array for the formatted name. */ void EmuFatFile::dirName(const TDirectoryEntry& dir, char* name) { u8 j = 0; for (u8 i = 0; i < 11; i++) { if (dir.name[i] == ' ')continue; if (i == 8) name[j++] = '.'; name[j++] = dir.name[i]; } name[j] = 0; } // format directory name field from a 8.3 name string u8 EmuFatFile::make83Name(const char* str, u8* name) { u8 c; u8 n = 7; // max index for part before dot u8 i = 0; // blank fill name and extension while (i < 11) name[i++] = ' '; i = 0; while ((c = *str++) != '\0') { if (c == '.') { if (n == 10) return false; // only one dot allowed n = 10; // max index for full 8.3 name i = 8; // place for extension } else { // illegal FAT characters static const char* px = "\\/:*?\"<>"; const char* p = px; u8 b; while ((b = *p++)) if (b == c) return false; // check size and only allow ASCII printable characters if (i > n || c < 0X21 || c > 0X7E)return false; // only upper case allowed in 8.3 names - convert lower to upper name[i++] = c < 'a' || c > 'z' ? c : c + ('A' - 'a'); } } // must have a file name, extension is optional return name[0] != ' '; } /** Make a new directory. * * \param[in] dir An open SdFat instance for the directory that will containing * the new directory. * * \param[in] dirName A valid 8.3 DOS name for the new directory. * * \return The value one, true, is returned for success and * the value zero, false, is returned for failure. * Reasons for failure include this SdFile is already open, \a dir is not a * directory, \a dirName is invalid or already exists in \a dir. */ u8 EmuFatFile::makeDir(EmuFatFile* dir, const char* dirName) { TDirectoryEntry d; // create a normal file if (!open(dir, dirName, EO_CREAT | EO_EXCL | EO_RDWR)) return false; // convert SdFile to directory flags_ = EO_READ; type_ = FAT_FILE_TYPE_SUBDIR; // allocate and zero first cluster if (!addDirCluster())return false; // force entry to SD if (!sync()) return false; // cache entry - should already be in cache due to sync() call TDirectoryEntry* p = cacheDirEntry(EmuFat::CACHE_FOR_WRITE); if (!p) return false; // change directory entry attribute p->attributes = DIR_ATT_DIRECTORY; // make entry for '.' memcpy(&d, p, sizeof(d)); for (u8 i = 1; i < 11; i++) d.name[i] = ' '; d.name[0] = '.'; // cache block for '.' and '..' u32 block = vol_->clusterStartBlock(firstCluster_); if (!vol_->dev_->cacheRawBlock(block, EmuFat::CACHE_FOR_WRITE)) return false; // copy '.' to block memcpy(&vol_->dev_->cache_.cacheBuffer_.dir[0], &d, sizeof(d)); // make entry for '..' d.name[1] = '.'; if (dir->isRoot()) { d.firstClusterLow = 0; d.firstClusterHigh = 0; } else { d.firstClusterLow = dir->firstCluster_ & 0XFFFF; d.firstClusterHigh = dir->firstCluster_ >> 16; } // copy '..' to block memcpy(&vol_->dev_->cache_.cacheBuffer_.dir[1], &d, sizeof(d)); // set position after '..' curPosition_ = 2 * sizeof(d); // write first block return vol_->dev_->cacheFlush(); } /** * Open a file or directory by name. * * \param[in] dirFile An open SdFat instance for the directory containing the * file to be opened. * * \param[in] fileName A valid 8.3 DOS name for a file to be opened. * * \param[in] oflag Values for \a oflag are constructed by a bitwise-inclusive * OR of flags from the following list * * O_READ - Open for reading. * * O_RDONLY - Same as O_READ. * * O_WRITE - Open for writing. * * O_WRONLY - Same as O_WRITE. * * O_RDWR - Open for reading and writing. * * O_APPEND - If set, the file offset shall be set to the end of the * file prior to each write. * * O_CREAT - If the file exists, this flag has no effect except as noted * under O_EXCL below. Otherwise, the file shall be created * * O_EXCL - If O_CREAT and O_EXCL are set, open() shall fail if the file exists. * * O_SYNC - Call sync() after each write. This flag should not be used with * write(uint8_t), write_P(PGM_P), writeln_P(PGM_P), or the Arduino Print class. * These functions do character at a time writes so sync() will be called * after each byte. * * O_TRUNC - If the file exists and is a regular file, and the file is * successfully opened and is not read only, its length shall be truncated to 0. * * \note Directory files must be opened read only. Write and truncation is * not allowed for directory files. * * \return The value one, true, is returned for success and * the value zero, false, is returned for failure. * Reasons for failure include this SdFile is already open, \a difFile is not * a directory, \a fileName is invalid, the file does not exist * or can't be opened in the access mode specified by oflag. */ u8 EmuFatFile::open(EmuFatFile* dirFile, const char* fileName, u8 oflag) { u8 dname[11]; TDirectoryEntry* p; // error if already open if (isOpen())return false; if (!make83Name(fileName, dname)) return false; vol_ = dirFile->vol_; dirFile->rewind(); // bool for empty entry found u8 emptyFound = false; // search for file while (dirFile->curPosition_ < dirFile->fileSize_) { u8 index = 0XF & (dirFile->curPosition_ >> 5); p = dirFile->readDirCache(); if (p == NULL) return false; if (p->name[0] == DIR_NAME_FREE || p->name[0] == DIR_NAME_DELETED) { // remember first empty slot if (!emptyFound) { emptyFound = true; dirIndex_ = index; dirBlock_ = vol_->dev_->cache_.cacheBlockNumber_; } // done if no entries follow if (p->name[0] == DIR_NAME_FREE) break; } else if (!memcmp(dname, p->name, 11)) { // don't open existing file if O_CREAT and O_EXCL if ((oflag & (EO_CREAT | EO_EXCL)) == (EO_CREAT | EO_EXCL)) return false; // open found file return openCachedEntry(0XF & index, oflag); } } // only create file if O_CREAT and O_WRITE if ((oflag & (EO_CREAT | EO_WRITE)) != (EO_CREAT | EO_WRITE)) return false; // cache found slot or add cluster if end of file if (emptyFound) { p = cacheDirEntry(EmuFat::CACHE_FOR_WRITE); if (!p) return false; } else { if (dirFile->type_ == FAT_FILE_TYPE_ROOT16) return false; // add and zero cluster for dirFile - first cluster is in cache for write if (!dirFile->addDirCluster()) return false; // use first entry in cluster dirIndex_ = 0; p = vol_->dev_->cache_.cacheBuffer_.dir; } // initialize as empty file memset(p, 0, sizeof(TDirectoryEntry)); memcpy(p->name, dname, 11); // set timestamps if (dateTime_) { // call user function dateTime_(&p->creationDate, &p->creationTime); } else { // use default date/time p->creationDate = FAT_DEFAULT_DATE; p->creationTime = FAT_DEFAULT_TIME; } p->lastAccessDate = p->creationDate; p->lastWriteDate = p->creationDate; p->lastWriteTime = p->creationTime; // force write of entry to SD if (!vol_->dev_->cacheFlush()) return false; // open entry in cache return openCachedEntry(dirIndex_, oflag); } /** * Open a file by index. * * \param[in] dirFile An open SdFat instance for the directory. * * \param[in] index The \a index of the directory entry for the file to be * opened. The value for \a index is (directory file position)/32. * * \param[in] oflag Values for \a oflag are constructed by a bitwise-inclusive * OR of flags O_READ, O_WRITE, O_TRUNC, and O_SYNC. * * See open() by fileName for definition of flags and return values. * */ u8 EmuFatFile::open(EmuFatFile* dirFile, u16 index, u8 oflag) { // error if already open if (isOpen())return false; // don't open existing file if O_CREAT and O_EXCL - user call error if ((oflag & (EO_CREAT | EO_EXCL)) == (EO_CREAT | EO_EXCL)) return false; vol_ = dirFile->vol_; // seek to location of entry if (!dirFile->seekSet(32 * index)) return false; // read entry into cache TDirectoryEntry* p = dirFile->readDirCache(); if (p == NULL) return false; // error if empty slot or '.' or '..' if (p->name[0] == DIR_NAME_FREE || p->name[0] == DIR_NAME_DELETED || p->name[0] == '.') { return false; } // open cached entry return openCachedEntry(index & 0XF, oflag); } //------------------------------------------------------------------------------ // open a cached directory entry. Assumes vol_ is initializes u8 EmuFatFile::openCachedEntry(u8 dirIndex, u8 oflag) { // location of entry in cache TDirectoryEntry* p = vol_->dev_->cache_.cacheBuffer_.dir + dirIndex; // write or truncate is an error for a directory or read-only file if (p->attributes & (DIR_ATT_READ_ONLY | DIR_ATT_DIRECTORY)) { if (oflag & (EO_WRITE | EO_TRUNC)) return false; } // remember location of directory entry on SD dirIndex_ = dirIndex; dirBlock_ = vol_->dev_->cache_.cacheBlockNumber_; // copy first cluster number for directory fields firstCluster_ = (u32)p->firstClusterHigh << 16; firstCluster_ |= p->firstClusterLow; // make sure it is a normal file or subdirectory if (DIR_IS_FILE(p)) { fileSize_ = p->fileSize; type_ = FAT_FILE_TYPE_NORMAL; } else if (DIR_IS_SUBDIR(p)) { if (!vol_->chainSize(firstCluster_, &fileSize_)) return false; type_ = FAT_FILE_TYPE_SUBDIR; } else { return false; } // save open flags for read/write flags_ = oflag & (EO_ACCMODE | EO_SYNC | EO_APPEND); // set to start of file curCluster_ = 0; curPosition_ = 0; // truncate file to zero length if requested if (oflag & EO_TRUNC) return truncate(0); return true; } //------------------------------------------------------------------------------ /** * Open a volume's root directory. * * \param[in] vol The FAT volume containing the root directory to be opened. * * \return The value one, true, is returned for success and * the value zero, false, is returned for failure. * Reasons for failure include the FAT volume has not been initialized * or it a FAT12 volume. */ u8 EmuFatFile::openRoot(EmuFatVolume* vol) { // error if file is already open if (isOpen()) return false; if (vol->fatType() == 16) { type_ = FAT_FILE_TYPE_ROOT16; firstCluster_ = 0; fileSize_ = 32 * vol->rootDirEntryCount(); } else if (vol->fatType() == 32) { type_ = FAT_FILE_TYPE_ROOT32; firstCluster_ = vol->rootDirStart(); if (!vol->chainSize(firstCluster_, &fileSize_)) return false; } else { // volume is not initialized or FAT12 return false; } vol_ = vol; // read only flags_ = EO_READ; // set to start of file curCluster_ = 0; curPosition_ = 0; // root has no directory entry dirBlock_ = 0; dirIndex_ = 0; return true; } //------------------------------------------------------------------------------ /** * Read data from a file starting at the current position. * * \param[out] buf Pointer to the location that will receive the data. * * \param[in] nbyte Maximum number of bytes to read. * * \return For success read() returns the number of bytes read. * A value less than \a nbyte, including zero, will be returned * if end of file is reached. * If an error occurs, read() returns -1. Possible errors include * read() called before a file has been opened, corrupt file system * or an I/O error occurred. */ s32 EmuFatFile::read(void* buf, u32 nbyte) { u8* dst = reinterpret_cast(buf); // error if not open or write only if (!isOpen() || !(flags_ & EO_READ)) return -1; // max bytes left in file if (nbyte > (fileSize_ - curPosition_)) nbyte = fileSize_ - curPosition_; // amount left to read u32 toRead = nbyte; while (toRead > 0) { u32 block; // raw device block number u16 offset = curPosition_ & 0x1FF; // offset in block if (type_ == FAT_FILE_TYPE_ROOT16) { block = vol_->rootDirStart() + (curPosition_ >> 9); } else { u8 blockOfCluster = vol_->blockOfCluster(curPosition_); if (offset == 0 && blockOfCluster == 0) { // start of new cluster if (curPosition_ == 0) { // use first cluster in file curCluster_ = firstCluster_; } else { // get next cluster from FAT if (!vol_->fatGet(curCluster_, &curCluster_)) return -1; } } block = vol_->clusterStartBlock(curCluster_) + blockOfCluster; } u32 n = toRead; // amount to be read from current block if (n > (512UL - offset)) n = 512 - offset; // no buffering needed if n == 512 or user requests no buffering if ((unbufferedRead() || n == 512) && block != vol_->dev_->cache_.cacheBlockNumber_) { if (!vol_->readData(block, offset, n, dst)) return -1; dst += n; } else { // read block to cache and copy data to caller if (!vol_->dev_->cacheRawBlock(block, EmuFat::CACHE_FOR_READ)) return -1; u8* src = vol_->dev_->cache_.cacheBuffer_.data + offset; u8* end = src + n; while (src != end) *dst++ = *src++; } curPosition_ += n; toRead -= n; } return nbyte; } //------------------------------------------------------------------------------ /** * Read the next directory entry from a directory file. * * \param[out] dir The dir_t struct that will receive the data. * * \return For success readDir() returns the number of bytes read. * A value of zero will be returned if end of file is reached. * If an error occurs, readDir() returns -1. Possible errors include * readDir() called before a directory has been opened, this is not * a directory file or an I/O error occurred. */ s8 EmuFatFile::readDir(TDirectoryEntry* dir) { s16 n; // if not a directory file or miss-positioned return an error if (!isDir() || (0x1F & curPosition_)) return -1; while ((n = read(dir, sizeof(TDirectoryEntry))) == sizeof(TDirectoryEntry)) { // last entry if DIR_NAME_FREE if (dir->name[0] == DIR_NAME_FREE) break; // skip empty entries and entry for . and .. if (dir->name[0] == DIR_NAME_DELETED || dir->name[0] == '.') continue; // return if normal file or subdirectory if (DIR_IS_FILE_OR_SUBDIR(dir)) return (s8)n; } // error, end of file, or past last entry return n < 0 ? -1 : 0; } // Read next directory entry into the cache // Assumes file is correctly positioned TDirectoryEntry* EmuFatFile::readDirCache(void) { // error if not directory if (!isDir()) return NULL; // index of entry in cache u8 i = (curPosition_ >> 5) & 0XF; // use read to locate and cache block if (read() < 0) return NULL; // advance to next entry curPosition_ += 31; // return pointer to entry return (vol_->dev_->cache_.cacheBuffer_.dir + i); } //------------------------------------------------------------------------------ /** * Remove a file. * * The directory entry and all data for the file are deleted. * * \note This function should not be used to delete the 8.3 version of a * file that has a long name. For example if a file has the long name * "New Text Document.txt" you should not delete the 8.3 name "NEWTEX~1.TXT". * * \return The value one, true, is returned for success and * the value zero, false, is returned for failure. * Reasons for failure include the file read-only, is a directory, * or an I/O error occurred. */ u8 EmuFatFile::remove(void) { // free any clusters - will fail if read-only or directory if (!truncate(0)) return false; // cache directory entry TDirectoryEntry* d = cacheDirEntry(EmuFat::CACHE_FOR_WRITE); if (!d) return false; // mark entry deleted d->name[0] = DIR_NAME_DELETED; // set this SdFile closed type_ = FAT_FILE_TYPE_CLOSED; // write entry to SD return vol_->dev_->cacheFlush(); } //------------------------------------------------------------------------------ /** * Remove a file. * * The directory entry and all data for the file are deleted. * * \param[in] dirFile The directory that contains the file. * \param[in] fileName The name of the file to be removed. * * \note This function should not be used to delete the 8.3 version of a * file that has a long name. For example if a file has the long name * "New Text Document.txt" you should not delete the 8.3 name "NEWTEX~1.TXT". * * \return The value one, true, is returned for success and * the value zero, false, is returned for failure. * Reasons for failure include the file is a directory, is read only, * \a dirFile is not a directory, \a fileName is not found * or an I/O error occurred. */ u8 EmuFatFile::remove(EmuFatFile* dirFile, const char* fileName) { EmuFatFile file; if (!file.open(dirFile, fileName, EO_WRITE)) return false; return file.remove(); } //------------------------------------------------------------------------------ /** Remove a directory file. * * The directory file will be removed only if it is empty and is not the * root directory. rmDir() follows DOS and Windows and ignores the * read-only attribute for the directory. * * \note This function should not be used to delete the 8.3 version of a * directory that has a long name. For example if a directory has the * long name "New folder" you should not delete the 8.3 name "NEWFOL~1". * * \return The value one, true, is returned for success and * the value zero, false, is returned for failure. * Reasons for failure include the file is not a directory, is the root * directory, is not empty, or an I/O error occurred. */ u8 EmuFatFile::rmDir(void) { // must be open subdirectory if (!isSubDir()) return false; rewind(); // make sure directory is empty while (curPosition_ < fileSize_) { TDirectoryEntry* p = readDirCache(); if (p == NULL) return false; // done if past last used entry if (p->name[0] == DIR_NAME_FREE) break; // skip empty slot or '.' or '..' if (p->name[0] == DIR_NAME_DELETED || p->name[0] == '.') continue; // error not empty if (DIR_IS_FILE_OR_SUBDIR(p)) return false; } // convert empty directory to normal file for remove type_ = FAT_FILE_TYPE_NORMAL; flags_ |= EO_WRITE; return remove(); } //------------------------------------------------------------------------------ /** Recursively delete a directory and all contained files. * * This is like the Unix/Linux 'rm -rf *' if called with the root directory * hence the name. * * Warning - This will remove all contents of the directory including * subdirectories. The directory will then be removed if it is not root. * The read-only attribute for files will be ignored. * * \note This function should not be used to delete the 8.3 version of * a directory that has a long name. See remove() and rmDir(). * * \return The value one, true, is returned for success and * the value zero, false, is returned for failure. */ u8 EmuFatFile::rmRfStar(void) { rewind(); while (curPosition_ < fileSize_) { EmuFatFile f; // remember position u16 index = curPosition_/32; TDirectoryEntry* p = readDirCache(); if (!p) return false; // done if past last entry if (p->name[0] == DIR_NAME_FREE) break; // skip empty slot or '.' or '..' if (p->name[0] == DIR_NAME_DELETED || p->name[0] == '.') continue; // skip if part of long file name or volume label in root if (!DIR_IS_FILE_OR_SUBDIR(p)) continue; if (!f.open(this, index, EO_READ)) return false; if (f.isSubDir()) { // recursively delete return rmRfStar(); } else { // ignore read-only f.flags_ |= EO_WRITE; if (!f.remove()) return false; } // position to next entry if required if (curPosition_ != (32*(index + 1))) { if (!seekSet(32*(index + 1))) return false; } } // don't try to delete root if (isRoot()) return true; return rmDir(); } u8 EmuFatFile::seekSet(u32 pos) { // error if file not open or seek past end of file if (!isOpen() || pos > fileSize_) return false; if (type_ == FAT_FILE_TYPE_ROOT16) { curPosition_ = pos; return true; } if (pos == 0) { // set position to start of file curCluster_ = 0; curPosition_ = 0; return true; } // calculate cluster index for cur and new position u32 nCur = (curPosition_ - 1) >> (vol_->clusterSizeShift_ + 9); u32 nNew = (pos - 1) >> (vol_->clusterSizeShift_ + 9); if (nNew < nCur || curPosition_ == 0) { // must follow chain from first cluster curCluster_ = firstCluster_; } else { // advance from curPosition nNew -= nCur; } while (nNew--) { if (!vol_->fatGet(curCluster_, &curCluster_)) return false; } curPosition_ = pos; return true; } //------------------------------------------------------------------------------ /** * The sync() call causes all modified data and directory fields * to be written to the storage device. * * \return The value one, true, is returned for success and * the value zero, false, is returned for failure. * Reasons for failure include a call to sync() before a file has been * opened or an I/O error. */ u8 EmuFatFile::sync(void) { // only allow open files and directories if (!isOpen()) return false; if (flags_ & F_FILE_DIR_DIRTY) { TDirectoryEntry* d = cacheDirEntry(EmuFat::CACHE_FOR_WRITE); if (!d) return false; // do not set filesize for dir files if (!isDir()) d->fileSize = fileSize_; // update first cluster fields d->firstClusterLow = firstCluster_ & 0XFFFF; d->firstClusterHigh = firstCluster_ >> 16; // set modify time if user supplied a callback date/time function if (dateTime_) { dateTime_(&d->lastWriteDate, &d->lastWriteTime); d->lastAccessDate = d->lastWriteDate; } // clear directory dirty flags_ &= ~F_FILE_DIR_DIRTY; } return vol_->dev_->cacheFlush(); } //------------------------------------------------------------------------------ /** * Set a file's timestamps in its directory entry. * * \param[in] flags Values for \a flags are constructed by a bitwise-inclusive * OR of flags from the following list * * T_ACCESS - Set the file's last access date. * * T_CREATE - Set the file's creation date and time. * * T_WRITE - Set the file's last write/modification date and time. * * \param[in] year Valid range 1980 - 2107 inclusive. * * \param[in] month Valid range 1 - 12 inclusive. * * \param[in] day Valid range 1 - 31 inclusive. * * \param[in] hour Valid range 0 - 23 inclusive. * * \param[in] minute Valid range 0 - 59 inclusive. * * \param[in] second Valid range 0 - 59 inclusive * * \note It is possible to set an invalid date since there is no check for * the number of days in a month. * * \note * Modify and access timestamps may be overwritten if a date time callback * function has been set by dateTimeCallback(). * * \return The value one, true, is returned for success and * the value zero, false, is returned for failure. */ u8 EmuFatFile::timestamp(u8 flags, u16 year, u8 month, u8 day, u8 hour, u8 minute, u8 second) { if (!isOpen() || year < 1980 || year > 2107 || month < 1 || month > 12 || day < 1 || day > 31 || hour > 23 || minute > 59 || second > 59) { return false; } TDirectoryEntry* d = cacheDirEntry(EmuFat::CACHE_FOR_WRITE); if (!d) return false; u16 dirDate = FAT_DATE(year, month, day); u16 dirTime = FAT_TIME(hour, minute, second); if (flags & T_ACCESS) { d->lastAccessDate = dirDate; } if (flags & T_CREATE) { d->creationDate = dirDate; d->creationTime = dirTime; // seems to be units of 1/100 second not 1/10 as Microsoft states d->creationTimeTenths = second & 1 ? 100 : 0; } if (flags & T_WRITE) { d->lastWriteDate = dirDate; d->lastWriteTime = dirTime; } vol_->dev_->cacheSetDirty(); return sync(); } //------------------------------------------------------------------------------ /** * Truncate a file to a specified length. The current file position * will be maintained if it is less than or equal to \a length otherwise * it will be set to end of file. * * \param[in] length The desired length for the file. * * \return The value one, true, is returned for success and * the value zero, false, is returned for failure. * Reasons for failure include file is read only, file is a directory, * \a length is greater than the current file size or an I/O error occurs. */ u8 EmuFatFile::truncate(u32 length) { // error if not a normal file or read-only if (!isFile() || !(flags_ & EO_WRITE)) return false; // error if length is greater than current size if (length > fileSize_) return false; // fileSize and length are zero - nothing to do if (fileSize_ == 0) return true; // remember position for seek after truncation u32 newPos = curPosition_ > length ? length : curPosition_; // position to last cluster in truncated file if (!seekSet(length)) return false; if (length == 0) { // free all clusters if (!vol_->freeChain(firstCluster_)) return false; firstCluster_ = 0; } else { u32 toFree; if (!vol_->fatGet(curCluster_, &toFree)) return false; if (!vol_->isEOC(toFree)) { // free extra clusters if (!vol_->freeChain(toFree)) return false; // current cluster is end of chain if (!vol_->fatPutEOC(curCluster_)) return false; } } fileSize_ = length; // need to update directory entry flags_ |= F_FILE_DIR_DIRTY; if (!sync()) return false; // set file to correct position return seekSet(newPos); } /** * Write data to an open file. * * \note Data is moved to the cache but may not be written to the * storage device until sync() is called. * * \param[in] buf Pointer to the location of the data to be written. * * \param[in] nbyte Number of bytes to write. * * \return For success write() returns the number of bytes written, always * \a nbyte. If an error occurs, write() returns -1. Possible errors * include write() is called before a file has been opened, write is called * for a read-only file, device is full, a corrupt file system or an I/O error. * */ s32 EmuFatFile::write(const void* buf, u32 nbyte) { // convert void* to uint8_t* - must be before goto statements const u8* src = reinterpret_cast(buf); // number of bytes left to write - must be before goto statements u32 nToWrite = nbyte; // error if not a normal file or is read-only if (!isFile() || !(flags_ & EO_WRITE)) goto writeErrorReturn; // seek to end of file if append flag if ((flags_ & EO_APPEND) && curPosition_ != fileSize_) { if (!seekEnd()) goto writeErrorReturn; } while (nToWrite > 0) { u8 blockOfCluster = vol_->blockOfCluster(curPosition_); u16 blockOffset = curPosition_ & 0X1FF; if (blockOfCluster == 0 && blockOffset == 0) { // start of new cluster if (curCluster_ == 0) { if (firstCluster_ == 0) { // allocate first cluster of file if (!addCluster()) goto writeErrorReturn; } else { curCluster_ = firstCluster_; } } else { u32 next; if (!vol_->fatGet(curCluster_, &next)) return false; if (vol_->isEOC(next)) { // add cluster if at end of chain if (!addCluster()) goto writeErrorReturn; } else { curCluster_ = next; } } } // max space in block u32 n = 512 - blockOffset; // lesser of space and amount to write if (n > nToWrite) n = nToWrite; // block for data write u32 block = vol_->clusterStartBlock(curCluster_) + blockOfCluster; if (n == 512) { // full block - don't need to use cache // invalidate cache if block is in cache if (vol_->dev_->cache_.cacheBlockNumber_ == block) { vol_->dev_->cache_.cacheBlockNumber_ = 0XFFFFFFFF; } if (!vol_->writeBlock(block, src)) goto writeErrorReturn; src += 512; } else { if (blockOffset == 0 && curPosition_ >= fileSize_) { // start of new block don't need to read into cache if (!vol_->dev_->cacheFlush()) goto writeErrorReturn; vol_->dev_->cache_.cacheBlockNumber_ = block; vol_->dev_->cacheSetDirty(); } else { // rewrite part of block if (!vol_->dev_->cacheRawBlock(block, EmuFat::CACHE_FOR_WRITE)) { goto writeErrorReturn; } } u8* dst = vol_->dev_->cache_.cacheBuffer_.data + blockOffset; u8* end = dst + n; while (dst != end) *dst++ = *src++; } nToWrite -= n; curPosition_ += n; } if (curPosition_ > fileSize_) { // update fileSize and insure sync will update dir entry fileSize_ = curPosition_; flags_ |= F_FILE_DIR_DIRTY; } else if (dateTime_ && nbyte) { // insure sync will update modified date and time flags_ |= F_FILE_DIR_DIRTY; } if (flags_ & EO_SYNC) { if (!sync()) goto writeErrorReturn; } return nbyte; writeErrorReturn: // return for write error writeError = true; return -1; } desmume/src/libretro-common/gfx/scaler/scaler_int.c000664 001750 001750 00000023542 12755534123 023601 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2015 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (scaler_int.c). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include #include #ifdef SCALER_NO_SIMD #undef __SSE2__ #endif #if defined(__SSE2__) #include #ifdef _WIN32 #include #endif #endif /* ARGB8888 scaler is split in two: * * First, horizontal scaler is applied. * Here, all 8-bit channels are expanded to 16-bit. Values are then shifted 7 to left to occupy 15 bits. * The sign bit is kept empty as we have to do signed multiplication for the filter. * A mulhi [(a * b) >> 16] is applied which loses some precision, but is very efficient for SIMD. * It is accurate enough for 8-bit purposes. * * The fixed point 1.0 for filter is (1 << 14). After horizontal scale, the output is kept * with 16-bit channels, and will now have 13 bits of precision as [(a * (1 << 14)) >> 16] is effectively a right shift by 2. * * Vertical scaler takes the 13 bit channels, and performs the same mulhi steps. * Another 2 bits of precision is lost, which ends up as 11 bits. * Scaling is now complete. Channels are shifted right by 3, and saturated into 8-bit values. * * The C version of scalers perform the exact same operations as the SIMD code for testing purposes. */ #if defined(__SSE2__) void scaler_argb8888_vert(const struct scaler_ctx *ctx, void *output_, int stride) { int h, w, y; const uint64_t *input = ctx->scaled.frame; uint32_t *output = (uint32_t*)output_; const int16_t *filter_vert = ctx->vert.filter; for (h = 0; h < ctx->out_height; h++, filter_vert += ctx->vert.filter_stride, output += stride >> 2) { const uint64_t *input_base = input + ctx->vert.filter_pos[h] * (ctx->scaled.stride >> 3); for (w = 0; w < ctx->out_width; w++) { __m128i final; __m128i res = _mm_setzero_si128(); const uint64_t *input_base_y = input_base + w; for (y = 0; (y + 1) < ctx->vert.filter_len; y += 2, input_base_y += (ctx->scaled.stride >> 2)) { __m128i coeff = _mm_set_epi64x(filter_vert[y + 1] * 0x0001000100010001ll, filter_vert[y + 0] * 0x0001000100010001ll); __m128i col = _mm_set_epi64x(input_base_y[ctx->scaled.stride >> 3], input_base_y[0]); res = _mm_adds_epi16(_mm_mulhi_epi16(col, coeff), res); } for (; y < ctx->vert.filter_len; y++, input_base_y += (ctx->scaled.stride >> 3)) { __m128i coeff = _mm_set_epi64x(0, filter_vert[y] * 0x0001000100010001ll); __m128i col = _mm_set_epi64x(0, input_base_y[0]); res = _mm_adds_epi16(_mm_mulhi_epi16(col, coeff), res); } res = _mm_adds_epi16(_mm_srli_si128(res, 8), res); res = _mm_srai_epi16(res, (7 - 2 - 2)); final = _mm_packus_epi16(res, res); output[w] = _mm_cvtsi128_si32(final); } } } #else void scaler_argb8888_vert(const struct scaler_ctx *ctx, void *output_, int stride) { int h, w, y; const uint64_t *input = ctx->scaled.frame; uint32_t *output = (uint32_t*)output_; const int16_t *filter_vert = ctx->vert.filter; for (h = 0; h < ctx->out_height; h++, filter_vert += ctx->vert.filter_stride, output += stride >> 2) { const uint64_t *input_base = input + ctx->vert.filter_pos[h] * (ctx->scaled.stride >> 3); for (w = 0; w < ctx->out_width; w++) { int16_t res_a = 0; int16_t res_r = 0; int16_t res_g = 0; int16_t res_b = 0; const uint64_t *input_base_y = input_base + w; for (y = 0; y < ctx->vert.filter_len; y++, input_base_y += (ctx->scaled.stride >> 3)) { uint64_t col = *input_base_y; int16_t a = (col >> 48) & 0xffff; int16_t r = (col >> 32) & 0xffff; int16_t g = (col >> 16) & 0xffff; int16_t b = (col >> 0) & 0xffff; int16_t coeff = filter_vert[y]; res_a += (a * coeff) >> 16; res_r += (r * coeff) >> 16; res_g += (g * coeff) >> 16; res_b += (b * coeff) >> 16; } res_a >>= (7 - 2 - 2); res_r >>= (7 - 2 - 2); res_g >>= (7 - 2 - 2); res_b >>= (7 - 2 - 2); output[w] = (clamp_8bit(res_a) << 24) | (clamp_8bit(res_r) << 16) | (clamp_8bit(res_g) << 8) | (clamp_8bit(res_b) << 0); } } } #endif #if defined(__SSE2__) void scaler_argb8888_horiz(const struct scaler_ctx *ctx, const void *input_, int stride) { int h, w, x; const uint32_t *input = (const uint32_t*)input_; uint64_t *output = ctx->scaled.frame; for (h = 0; h < ctx->scaled.height; h++, input += stride >> 2, output += ctx->scaled.stride >> 3) { const int16_t *filter_horiz = ctx->horiz.filter; for (w = 0; w < ctx->scaled.width; w++, filter_horiz += ctx->horiz.filter_stride) { __m128i res = _mm_setzero_si128(); const uint32_t *input_base_x = input + ctx->horiz.filter_pos[w]; for (x = 0; (x + 1) < ctx->horiz.filter_len; x += 2) { __m128i coeff = _mm_set_epi64x(filter_horiz[x + 1] * 0x0001000100010001ll, filter_horiz[x + 0] * 0x0001000100010001ll); __m128i col = _mm_unpacklo_epi8(_mm_set_epi64x(0, ((uint64_t)input_base_x[x + 1] << 32) | input_base_x[x + 0]), _mm_setzero_si128()); col = _mm_slli_epi16(col, 7); res = _mm_adds_epi16(_mm_mulhi_epi16(col, coeff), res); } for (; x < ctx->horiz.filter_len; x++) { __m128i coeff = _mm_set_epi64x(0, filter_horiz[x] * 0x0001000100010001ll); __m128i col = _mm_unpacklo_epi8(_mm_set_epi32(0, 0, 0, input_base_x[x]), _mm_setzero_si128()); col = _mm_slli_epi16(col, 7); res = _mm_adds_epi16(_mm_mulhi_epi16(col, coeff), res); } res = _mm_adds_epi16(_mm_srli_si128(res, 8), res); #ifdef __x86_64__ output[w] = _mm_cvtsi128_si64(res); #else /* 32-bit doesn't have si64. Do it in two steps. */ union { uint32_t *u32; uint64_t *u64; } u; u.u64 = output + w; u.u32[0] = _mm_cvtsi128_si32(res); u.u32[1] = _mm_cvtsi128_si32(_mm_srli_si128(res, 4)); #endif } } } #else static INLINE uint64_t build_argb64(uint16_t a, uint16_t r, uint16_t g, uint16_t b) { return ((uint64_t)a << 48) | ((uint64_t)r << 32) | ((uint64_t)g << 16) | ((uint64_t)b << 0); } void scaler_argb8888_horiz(const struct scaler_ctx *ctx, const void *input_, int stride) { int h, w, x; const uint32_t *input = (uint32_t*)input_; uint64_t *output = ctx->scaled.frame; for (h = 0; h < ctx->scaled.height; h++, input += stride >> 2, output += ctx->scaled.stride >> 3) { const int16_t *filter_horiz = ctx->horiz.filter; for (w = 0; w < ctx->scaled.width; w++, filter_horiz += ctx->horiz.filter_stride) { const uint32_t *input_base_x = input + ctx->horiz.filter_pos[w]; int16_t res_a = 0; int16_t res_r = 0; int16_t res_g = 0; int16_t res_b = 0; for (x = 0; x < ctx->horiz.filter_len; x++) { uint32_t col = input_base_x[x]; int16_t a = (col >> (24 - 7)) & (0xff << 7); int16_t r = (col >> (16 - 7)) & (0xff << 7); int16_t g = (col >> ( 8 - 7)) & (0xff << 7); int16_t b = (col << ( 0 + 7)) & (0xff << 7); int16_t coeff = filter_horiz[x]; res_a += (a * coeff) >> 16; res_r += (r * coeff) >> 16; res_g += (g * coeff) >> 16; res_b += (b * coeff) >> 16; } output[w] = build_argb64(res_a, res_r, res_g, res_b); } } } #endif void scaler_argb8888_point_special(const struct scaler_ctx *ctx, void *output_, const void *input_, int out_width, int out_height, int in_width, int in_height, int out_stride, int in_stride) { int h, w; const uint32_t *input = NULL; uint32_t *output = NULL; int x_pos = (1 << 15) * in_width / out_width - (1 << 15); int x_step = (1 << 16) * in_width / out_width; int y_pos = (1 << 15) * in_height / out_height - (1 << 15); int y_step = (1 << 16) * in_height / out_height; (void)ctx; if (x_pos < 0) x_pos = 0; if (y_pos < 0) y_pos = 0; input = (const uint32_t*)input_; output = (uint32_t*)output_; for (h = 0; h < out_height; h++, y_pos += y_step, output += out_stride >> 2) { int x = x_pos; const uint32_t *inp = input + (y_pos >> 16) * (in_stride >> 2); for (w = 0; w < out_width; w++, x += x_step) output[w] = inp[x >> 16]; } } desmume/src/libretro-common/formats/png/test/000700 001750 001750 00000000000 12756420131 022443 5ustar00sergiosergio000000 000000 desmume/src/libretro-common/compat/compat_strl.c000664 001750 001750 00000004037 12755534123 023231 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2015 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (compat_strl.c). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include #include #include #include /* Implementation of strlcpy()/strlcat() based on OpenBSD. */ #ifndef __MACH__ size_t strlcpy(char *dest, const char *source, size_t size) { size_t src_size = 0; size_t n = size; if (n) while (--n && (*dest++ = *source++)) src_size++; if (!n) { if (size) *dest = '\0'; while (*source++) src_size++; } return src_size; } size_t strlcat(char *dest, const char *source, size_t size) { size_t len = strlen(dest); dest += len; if (len > size) size = 0; else size -= len; return len + strlcpy(dest, source, size); } #endif desmume/src/utils/AsmJit/core/assembler.h000664 001750 001750 00000042405 12755534123 021551 0ustar00sergiosergio000000 000000 // [AsmJit] // Complete JIT Assembler for C++ Language. // // [License] // Zlib - See COPYING file in this package. // [Guard] #ifndef _ASMJIT_CORE_ASSEMBLER_H #define _ASMJIT_CORE_ASSEMBLER_H // [Dependencies - AsmJit] #include "../core/buffer.h" #include "../core/context.h" #include "../core/defs.h" #include "../core/logger.h" #include "../core/podvector.h" #include "../core/zonememory.h" // [Api-Begin] #include "../core/apibegin.h" namespace AsmJit { //! @addtogroup AsmJit_Core //! @{ // ============================================================================ // [AsmJit::Assembler] // ============================================================================ //! @brief Base class for @ref Assembler. //! //! This class implements core setialization API only. The platform specific //! methods and intrinsics is implemented by derived classes. //! //! @sa @c Assembler. struct Assembler { // -------------------------------------------------------------------------- // [Construction / Destruction] // -------------------------------------------------------------------------- //! @brief Creates Assembler instance. ASMJIT_API Assembler(Context* context); //! @brief Destroys Assembler instance ASMJIT_API virtual ~Assembler(); // -------------------------------------------------------------------------- // [LabelLink] // -------------------------------------------------------------------------- //! @brief Data structure used to link linked-labels. struct LabelLink { //! @brief Previous link. LabelLink* prev; //! @brief Offset. sysint_t offset; //! @brief Inlined displacement. sysint_t displacement; //! @brief RelocId if link must be absolute when relocated. sysint_t relocId; }; // -------------------------------------------------------------------------- // [LabelData] // -------------------------------------------------------------------------- //! @brief Label data. struct LabelData { //! @brief Label offset. sysint_t offset; //! @brief Label links chain. LabelLink* links; }; // -------------------------------------------------------------------------- // [RelocData] // -------------------------------------------------------------------------- // X86 architecture uses 32-bit absolute addressing model by memory operands, // but 64-bit mode uses relative addressing model (RIP + displacement). In // code we are always using relative addressing model for referencing labels // and embedded data. In 32-bit mode we must patch all references to absolute // address before we can call generated function. We are patching only memory // operands. //! @brief Code relocation data (relative vs absolute addresses). struct RelocData { //! @brief Type of relocation. uint32_t type; //! @brief Size of relocation (4 or 8 bytes). uint32_t size; //! @brief Offset from code begin address. sysint_t offset; //! @brief Relative displacement or absolute address. union { //! @brief Relative displacement from code begin address (not to @c offset). sysint_t destination; //! @brief Absolute address where to jump; void* address; }; }; // -------------------------------------------------------------------------- // [Context] // -------------------------------------------------------------------------- //! @brief Get code generator. inline Context* getContext() const { return _context; } // -------------------------------------------------------------------------- // [Memory Management] // -------------------------------------------------------------------------- //! @brief Get zone memory manager. inline ZoneMemory* getZoneMemory() const { return const_cast(&_zoneMemory); } // -------------------------------------------------------------------------- // [Logging] // -------------------------------------------------------------------------- //! @brief Get logger. inline Logger* getLogger() const { return _logger; } //! @brief Set logger to @a logger. ASMJIT_API virtual void setLogger(Logger* logger); // -------------------------------------------------------------------------- // [Error Handling] // -------------------------------------------------------------------------- //! @brief Get error code. inline uint32_t getError() const { return _error; } //! @brief Set error code. //! //! This method is virtual, because higher classes can use it to catch all //! errors. ASMJIT_API virtual void setError(uint32_t error); // -------------------------------------------------------------------------- // [Properties] // -------------------------------------------------------------------------- //! @brief Get assembler property. ASMJIT_API virtual uint32_t getProperty(uint32_t propertyId) const; //! @brief Set assembler property. ASMJIT_API virtual void setProperty(uint32_t propertyId, uint32_t value); // -------------------------------------------------------------------------- // [Capacity] // -------------------------------------------------------------------------- //! @brief Get capacity of internal code buffer. inline size_t getCapacity() const { return _buffer.getCapacity(); } // -------------------------------------------------------------------------- // [Offset] // -------------------------------------------------------------------------- //! @brief Return current offset in buffer. inline size_t getOffset() const { return _buffer.getOffset(); } //! @brief Set offset to @a o and returns previous offset. //! //! This method can be used to truncate code (previous offset is not //! recorded) or to overwrite instruction stream at position @a o. //! //! @return Previous offset value that can be uset to set offset back later. inline size_t toOffset(size_t o) { return _buffer.toOffset(o); } // -------------------------------------------------------------------------- // [GetCode / GetCodeSize] // -------------------------------------------------------------------------- //! @brief Return start of assembler code buffer. //! //! Note that buffer address can change if you emit instruction or something //! else. Use this pointer only when you finished or make sure you do not //! use returned pointer after emitting. inline uint8_t* getCode() const { return _buffer.getData(); } //! @brief Return current offset in buffer (same as getOffset() + getTramplineSize()). inline size_t getCodeSize() const { return _buffer.getOffset() + getTrampolineSize(); } // -------------------------------------------------------------------------- // [TakeCode] // -------------------------------------------------------------------------- //! @brief Take internal code buffer and NULL all pointers (you take the ownership). ASMJIT_API uint8_t* takeCode(); // -------------------------------------------------------------------------- // [Clear / Reset] // -------------------------------------------------------------------------- //! @brief Clear everything, but not deallocate buffers. ASMJIT_API void clear(); //! @brief Reset everything (means also to free all buffers). ASMJIT_API void reset(); //! @brief Called by clear() and reset() to clear all data related to derived //! class implementation. ASMJIT_API virtual void _purge(); // -------------------------------------------------------------------------- // [EnsureSpace] // -------------------------------------------------------------------------- //! @brief Ensure space for next instruction. //! //! Note that this method can return false. It's rare and probably you never //! get this, but in some situations it's still possible. inline bool ensureSpace() { return _buffer.ensureSpace(); } // -------------------------------------------------------------------------- // [GetTrampolineSize] // -------------------------------------------------------------------------- //! @brief Get size of all possible trampolines needed to successfuly generate //! relative jumps to absolute addresses. This value is only non-zero if jmp //! of call instructions were used with immediate operand (this means jump or //! call absolute address directly). //! //! Currently only _emitJmpOrCallReloc() method can increase trampoline size //! value. inline size_t getTrampolineSize() const { return _trampolineSize; } // -------------------------------------------------------------------------- // [Buffer - Getters] // -------------------------------------------------------------------------- //! @brief Get byte at position @a pos. inline uint8_t getByteAt(size_t pos) const { return _buffer.getByteAt(pos); } //! @brief Get word at position @a pos. inline uint16_t getWordAt(size_t pos) const { return _buffer.getWordAt(pos); } //! @brief Get dword at position @a pos. inline uint32_t getDWordAt(size_t pos) const { return _buffer.getDWordAt(pos); } //! @brief Get qword at position @a pos. inline uint64_t getQWordAt(size_t pos) const { return _buffer.getQWordAt(pos); } //! @brief Get int32_t at position @a pos. inline int32_t getInt32At(size_t pos) const { return (int32_t)_buffer.getDWordAt(pos); } //! @brief Get int64_t at position @a pos. inline int64_t getInt64At(size_t pos) const { return (int64_t)_buffer.getQWordAt(pos); } //! @brief Get intptr_t at position @a pos. inline intptr_t getIntPtrTAt(size_t pos) const { return _buffer.getIntPtrTAt(pos); } //! @brief Get uintptr_t at position @a pos. inline uintptr_t getUIntPtrTAt(size_t pos) const { return _buffer.getUIntPtrTAt(pos); } //! @brief Get uintptr_t at position @a pos. inline size_t getSizeTAt(size_t pos) const { return _buffer.getSizeTAt(pos); } // -------------------------------------------------------------------------- // [Buffer - Setters] // -------------------------------------------------------------------------- //! @brief Set byte at position @a pos. inline void setByteAt(size_t pos, uint8_t x) { _buffer.setByteAt(pos, x); } //! @brief Set word at position @a pos. inline void setWordAt(size_t pos, uint16_t x) { _buffer.setWordAt(pos, x); } //! @brief Set dword at position @a pos. inline void setDWordAt(size_t pos, uint32_t x) { _buffer.setDWordAt(pos, x); } //! @brief Set qword at position @a pos. inline void setQWordAt(size_t pos, uint64_t x) { _buffer.setQWordAt(pos, x); } //! @brief Set int32_t at position @a pos. inline void setInt32At(size_t pos, int32_t x) { _buffer.setDWordAt(pos, (uint32_t)x); } //! @brief Set int64_t at position @a pos. inline void setInt64At(size_t pos, int64_t x) { _buffer.setQWordAt(pos, (uint64_t)x); } //! @brief Set intptr_t at position @a pos. inline void setIntPtrTAt(size_t pos, intptr_t x) { _buffer.setIntPtrTAt(pos, x); } //! @brief Set uintptr_t at position @a pos. inline void setUInt64At(size_t pos, uintptr_t x) { _buffer.setUIntPtrTAt(pos, x); } //! @brief Set size_t at position @a pos. inline void setSizeTAt(size_t pos, size_t x) { _buffer.setSizeTAt(pos, x); } // -------------------------------------------------------------------------- // [CanEmit] // -------------------------------------------------------------------------- //! @brief Get whether the instruction can be emitted. //! //! This function behaves like @c ensureSpace(), but it also checks if //! assembler is in error state and in that case it returns @c false. //! Assembler internally always uses this function before new instruction is //! emitted. //! //! It's implemented like: //! return ensureSpace() && !getError(); inline bool canEmit() { // If there is an error, we can't emit another instruction until last error // is cleared by calling @c setError(kErrorOk). If something caused the // error while generating code it's probably fatal in all cases. You can't // use generated code anymore, because you are not sure about the status. if (_error) return false; // The ensureSpace() method returns true on success and false on failure. We // are catching return value and setting error code here. if (ensureSpace()) return true; // If we are here, there is memory allocation error. Note that this is HEAP // allocation error, virtual allocation error can be caused only by // AsmJit::VirtualMemory class! setError(kErrorNoHeapMemory); return false; } // -------------------------------------------------------------------------- // [Emit] // // These functions are not protected against buffer overrun. Each place of // code which calls these functions ensures that there is some space using // canEmit() method. Emitters are internally protected in AsmJit::Buffer, // but only in debug builds. // -------------------------------------------------------------------------- //! @brief Emit Byte to internal buffer. inline void _emitByte(uint8_t x) { _buffer.emitByte(x); } //! @brief Emit word (2 bytes) to internal buffer. inline void _emitWord(uint16_t x) { _buffer.emitWord(x); } //! @brief Emit dword (4 bytes) to internal buffer. inline void _emitDWord(uint32_t x) { _buffer.emitDWord(x); } //! @brief Emit qword (8 bytes) to internal buffer. inline void _emitQWord(uint64_t x) { _buffer.emitQWord(x); } //! @brief Emit Int32 (4 bytes) to internal buffer. inline void _emitInt32(int32_t x) { _buffer.emitDWord((uint32_t)x); } //! @brief Emit Int64 (8 bytes) to internal buffer. inline void _emitInt64(int64_t x) { _buffer.emitQWord((uint64_t)x); } //! @brief Emit intptr_t (4 or 8 bytes) to internal buffer. inline void _emitIntPtrT(intptr_t x) { _buffer.emitIntPtrT(x); } //! @brief Emit uintptr_t (4 or 8 bytes) to internal buffer. inline void _emitUIntPtrT(uintptr_t x) { _buffer.emitUIntPtrT(x); } //! @brief Emit size_t (4 or 8 bytes) to internal buffer. inline void _emitSizeT(size_t x) { _buffer.emitSizeT(x); } //! @brief Embed data into instruction stream. ASMJIT_API void embed(const void* data, size_t len); // -------------------------------------------------------------------------- // [Reloc] // -------------------------------------------------------------------------- //! @brief Relocate code to a given address @a dst. //! //! @param dst Where the relocated code should me stored. The pointer can be //! address returned by virtual memory allocator or your own address if you //! want only to store the code for later reuse (or load, etc...). //! @param addressBase Base address used for relocation. When using JIT code //! generation, this will be the same as @a dst, only casted to system //! integer type. But when generating code for remote process then the value //! can be different. //! //! @retval The bytes used. Code-generator can create trampolines which are //! used when calling other functions inside the JIT code. However, these //! trampolines can be unused so the relocCode() returns the exact size needed //! for the function. //! //! A given buffer will be overwritten, to get number of bytes required use //! @c getCodeSize(). virtual size_t relocCode(void* dst, sysuint_t addressBase) const = 0; //! @brief Simplifed version of @c relocCode() method designed for JIT. //! //! @overload inline size_t relocCode(void* dst) const { return relocCode(dst, (uintptr_t)dst); } // -------------------------------------------------------------------------- // [Make] // -------------------------------------------------------------------------- //! @brief Make is convenience method to make currently serialized code and //! return pointer to generated function. //! //! What you need is only to cast this pointer to your function type and call //! it. Note that if there was an error and calling @c getError() method not //! returns @c kErrorOk (zero) then this function always return @c NULL and //! error value remains the same. virtual void* make() = 0; // -------------------------------------------------------------------------- // [Helpers] // -------------------------------------------------------------------------- ASMJIT_API LabelLink* _newLabelLink(); // -------------------------------------------------------------------------- // [Members] // -------------------------------------------------------------------------- //! @brief ZoneMemory management. ZoneMemory _zoneMemory; //! @brief Binary code buffer. Buffer _buffer; //! @brief Context (for example @ref JitContext). Context* _context; //! @brief Logger. Logger* _logger; //! @brief Error code. uint32_t _error; //! @brief Properties. uint32_t _properties; //! @brief Emit flags for next instruction (cleared after emit). uint32_t _emitOptions; //! @brief Size of possible trampolines. uint32_t _trampolineSize; //! @brief Inline comment that will be logged by the next instruction and //! set to NULL. const char* _inlineComment; //! @brief Linked list of unused links (@c LabelLink* structures) LabelLink* _unusedLinks; //! @brief Labels data. PodVector _labels; //! @brief Relocations data. PodVector _relocData; }; //! @} } // AsmJit namespace // [Api-End] #include "../core/apiend.h" // [Guard] #endif // _ASMJIT_CORE_ASSEMBLER_H desmume/src/addons/slot1_retail_mcrom_debug.cpp000664 001750 001750 00000012310 12755534123 023055 0ustar00sergiosergio000000 000000 /* Copyright (C) 2013-2015 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the this software. If not, see . */ #include "slot1comp_mc.h" #include "slot1comp_rom.h" #include "slot1comp_protocol.h" #include #include #include "../slot1.h" #include "../path.h" #include "../NDSSystem.h" #include "../utils/fsnitro.h" //quick architecture overview: //MCROM receives GC bus commands from MMU.cpp //those are passed on to the protocol component for parsing //protocol calls back into MCROM via ISlot1Comp_Protocol_Client interface for things the protocol doesnt know about (the contents of the rom, chiefly) //MCROM utilizes the rom component for address logic and delivering data class Slot1_Retail_DEBUG : public ISlot1Interface, public ISlot1Comp_Protocol_Client { private: Slot1Comp_Protocol protocol; Slot1Comp_Rom rom; FILE *fpROM; FS_NITRO *fs; u16 curr_file_id; string pathData; public: virtual Slot1Info const* info() { static Slot1InfoSimple info("Retail DEBUG","Slot1 Retail (standard) card emulation + FS Nitro DEBUG", 0x04); return &info; } virtual void connect() { protocol.reset(this); protocol.chipId = gameInfo.chipID; protocol.gameCode = T1ReadLong((u8*)gameInfo.header.gameCode,0); curr_file_id = 0xFFFF; fpROM = NULL; fs = NULL; if (!CommonSettings.loadToMemory) { printf("NitroFS: change load type to \"Load to RAM\"\n"); return; } pathData = path.getpath(path.SLOT1D) + path.GetRomNameWithoutExtension(); printf("Path to Slot1 data: %s\n", pathData.c_str()); fs = new FS_NITRO(gameInfo.romdata); fs->rebuildFAT(pathData); } virtual u8 auxspi_transaction(int PROCNUM, u8 value) { return g_Slot1Comp_MC.auxspi_transaction(PROCNUM,value); } virtual void auxspi_reset(int PROCNUM) { g_Slot1Comp_MC.auxspi_reset(PROCNUM); } virtual void write_command(u8 PROCNUM, GC_Command command) { protocol.write_command(command); } virtual void write_GCDATAIN(u8 PROCNUM, u32 val) { protocol.write_GCDATAIN(PROCNUM, val); } virtual u32 read_GCDATAIN(u8 PROCNUM) { return protocol.read_GCDATAIN(PROCNUM); } virtual void post_fakeboot(int PROCNUM) { // The BIOS leaves the card in NORMAL mode protocol.mode = eCardMode_NORMAL; } virtual void savestate(EMUFILE* os) { protocol.savestate(os); rom.savestate(os); } virtual void loadstate(EMUFILE* is) { protocol.loadstate(is); rom.loadstate(is); } virtual void slot1client_startOperation(eSlot1Operation operation) { if (protocol.operation == eSlot1Operation_B7_Read) { u16 file_id = 0xFFFF; u32 offset = 0; bool bFromFile = false; if (fs && fs->isFAT(protocol.address)) { fs->rebuildFAT(protocol.address, protocol.length, pathData); } else { if (fs && fs->getFileIdByAddr(protocol.address, file_id, offset)) { if (file_id != curr_file_id) { string tmp = fs->getFullPathByFileID(file_id); printf("%04X:[%08X, ofs %08X] %s\n", file_id, protocol.address, offset, tmp.c_str()); if (fpROM) { fclose(fpROM); fpROM = NULL; } tmp = pathData + tmp; fpROM = fopen(tmp.c_str(), "rb"); if (fpROM) { bFromFile = true; printf("\t * found at disk, offset %08X\n", offset); if (fseek(fpROM, offset, SEEK_SET) != 0) { printf("\t\t - ERROR seek file position\n"); } } } else { if (fpROM) { bFromFile = true; if (ftell(fpROM) != offset) { printf("\t * new file seek %08Xh\n", offset); fseek(fpROM, offset, SEEK_SET); } } } } } if (!bFromFile && fpROM) { fclose(fpROM); fpROM = NULL; } curr_file_id = file_id; } rom.start(operation, protocol.address); } private: u32 slot1client_read_GCDATAIN(eSlot1Operation operation) { if (protocol.operation == eSlot1Operation_B7_Read) { u32 address = rom.getAddress(); if (fs && fs->isFAT(address)) { u32 res = fs->getFATRecord(address); if (res != 0xFFFFFFFF) { rom.incAddress(); return res; } } else if (fpROM) { u32 data = 0; u32 readed = fread(&data, 1, 4, fpROM); if (readed) { rom.incAddress(); if (readed < 4) data |= ((u32)0xFFFFFFFF << (readed * 8)); return data; } fclose(fpROM); fpROM = NULL; } } return rom.read(); } }; ISlot1Interface* construct_Slot1_Retail_DEBUG() { return new Slot1_Retail_DEBUG(); } desmume/src/utils/libfat/file_allocation_table.h000664 001750 001750 00000005565 12755534123 023217 0ustar00sergiosergio000000 000000 /* file_allocation_table.h Reading, writing and manipulation of the FAT structure on a FAT partition Copyright (c) 2006 Michael "Chishm" Chisholm Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. 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. 3. The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. */ #ifndef _FAT_H #define _FAT_H #include "common.h" #include "partition.h" #define CLUSTER_EOF_16 0xFFFF #define CLUSTER_EOF 0x0FFFFFFF #define CLUSTER_FREE 0x00000000 #define CLUSTER_ROOT 0x00000000 #define CLUSTER_FIRST 0x00000002 #define CLUSTER_ERROR 0xFFFFFFFF #define CLUSTERS_PER_FAT12 4085 #define CLUSTERS_PER_FAT16 65525 #ifdef __cplusplus extern "C" { #endif uint32_t _FAT_fat_nextCluster(PARTITION* partition, uint32_t cluster); uint32_t _FAT_fat_linkFreeCluster(PARTITION* partition, uint32_t cluster); uint32_t _FAT_fat_linkFreeClusterCleared (PARTITION* partition, uint32_t cluster); bool _FAT_fat_clearLinks (PARTITION* partition, uint32_t cluster); uint32_t _FAT_fat_trimChain (PARTITION* partition, uint32_t startCluster, unsigned int chainLength); uint32_t _FAT_fat_lastCluster (PARTITION* partition, uint32_t cluster); unsigned int _FAT_fat_freeClusterCount (PARTITION* partition); static inline sec_t _FAT_fat_clusterToSector (PARTITION* partition, uint32_t cluster) { return (cluster >= CLUSTER_FIRST) ? ((cluster - CLUSTER_FIRST) * (sec_t)partition->sectorsPerCluster) + partition->dataStart : partition->rootDirStart; } static inline bool _FAT_fat_isValidCluster (PARTITION* partition, uint32_t cluster) { return (cluster >= CLUSTER_FIRST) && (cluster <= partition->fat.lastCluster /* This will catch CLUSTER_ERROR */); } #ifdef __cplusplus } #endif #endif // _FAT_H desmume/src/utils/xstring.cpp000664 001750 001750 00000004577 12755534123 017516 0ustar00sergiosergio000000 000000 //taken from fceux on 10/27/08 //subsequently modified for desmume /* Copyright (C) 2008-2009 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the this software. If not, see . */ #include "xstring.h" #include #include ///Sub-String replacement routine /// \brief convert input string into vector of string tokens /// /// \note consecutive delimiters will be treated as single delimiter /// \note delimiters are _not_ included in return data /// /// \param input string to be parsed /// \param delims list of delimiters. std::vector tokenize_str(const std::string & str, const std::string & delims=", \t") { using namespace std; // Skip delims at beginning, find start of first token string::size_type lastPos = str.find_first_not_of(delims, 0); // Find next delimiter @ end of token string::size_type pos = str.find_first_of(delims, lastPos); // output vector vector tokens; while (string::npos != pos || string::npos != lastPos) { // Found a token, add it to the vector. tokens.push_back(str.substr(lastPos, pos - lastPos)); // Skip delims. Note the "not_of". this is beginning of token lastPos = str.find_first_not_of(delims, pos); // Find next delimiter at end of token. pos = str.find_first_of(delims, lastPos); } return tokens; } std::string stditoa(int n) { char tempbuf[16]; sprintf(tempbuf, "%d", n); return tempbuf; } // replace all instances of victim with replacement std::string mass_replace(const std::string &source, const std::string &victim, const std::string &replacement) { std::string answer = source; std::string::size_type j = 0; while ((j = answer.find(victim, j)) != std::string::npos ) { answer.replace(j, victim.length(), replacement); j+= replacement.length(); } return answer; } desmume/src/slot2.h000664 001750 001750 00000011705 12755534123 015357 0ustar00sergiosergio000000 000000 /* Copyright (C) 2009-2015 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the this software. If not, see . */ #ifndef __SLOT2_H__ #define __SLOT2_H__ #include #include "types.h" #define GBA_SRAM_FILE_EXT "sav" class EMUFILE; class Slot2Info { public: virtual const char* name() const = 0; virtual const char* descr() const = 0; virtual const u8 id() const = 0; }; class Slot2InfoSimple : public Slot2Info { public: Slot2InfoSimple(const char* _name, const char* _descr, const u8 _id) : mName(_name) , mDescr(_descr) , mID(_id) { } virtual const char* name() const { return mName; } virtual const char* descr() const { return mDescr; } virtual const u8 id() const { return mID; } private: const char* mName, *mDescr; const u8 mID; }; class ISlot2Interface { public: //called to get info about device (description) virtual Slot2Info const* info() = 0; //called once when the emulator starts up, or when the device springs into existence virtual bool init() { return true; } //called when the emulator connects the device virtual void connect() { } //called when the emulator disconnects the device virtual void disconnect() { } //called when the emulator shuts down, or when the device disappears from existence virtual void shutdown() { } virtual void writeByte(u8 PROCNUM, u32 addr, u8 val) {}; virtual void writeWord(u8 PROCNUM, u32 addr, u16 val) {}; virtual void writeLong(u8 PROCNUM, u32 addr, u32 val) {}; virtual u8 readByte(u8 PROCNUM, u32 addr) { return 0xFF; }; virtual u16 readWord(u8 PROCNUM, u32 addr) { return 0xFFFF; }; virtual u32 readLong(u8 PROCNUM, u32 addr) { return 0xFFFFFFFF; }; virtual void savestate(EMUFILE* os) {} virtual void loadstate(EMUFILE* is) {} }; typedef ISlot2Interface* TISlot2InterfaceConstructor(); enum NDS_SLOT2_TYPE { NDS_SLOT2_NONE, // 0xFF NDS_SLOT2_AUTO, // 0xFE - Auto-select NDS_SLOT2_CFLASH, // 0x01 - Compact flash NDS_SLOT2_RUMBLEPAK, // 0x02 - RumblePak NDS_SLOT2_GBACART, // 0x03 - GBA cartrindge in slot NDS_SLOT2_GUITARGRIP, // 0x04 - Guitar Grip NDS_SLOT2_EXPMEMORY, // 0x05 - Memory Expansion Pak NDS_SLOT2_EASYPIANO, // 0x06 - Easy Piano NDS_SLOT2_PADDLE, // 0x07 - Arkanoids DS paddle NDS_SLOT2_PASSME, // 0x08 - PassME/Homebrew NDS_SLOT2_COUNT // use for counter addons - MUST TO BE LAST!!! }; extern ISlot2Interface* slot2_device; //the current slot2 device instance extern ISlot2Interface* slot2_List[NDS_SLOT2_COUNT]; extern NDS_SLOT2_TYPE slot2_selected_type; void slot2_Init(); bool slot2_Connect(); void slot2_Disconnect(); void slot2_Shutdown(); void slot2_Savestate(EMUFILE* os); void slot2_Loadstate(EMUFILE* is); //just disconnects and reconnects the device. ideally, the disconnection and connection would be called with sensible timing void slot2_Reset(); //change the current device bool slot2_Change(NDS_SLOT2_TYPE type); void slot2_setDeviceByType(NDS_SLOT2_TYPE theType); bool slot2_getTypeByID(u8 ID, NDS_SLOT2_TYPE &type); //change the current device by ID bool slot2_ChangeByID(u8 ID); //check on the current device NDS_SLOT2_TYPE slot2_GetCurrentType(); NDS_SLOT2_TYPE slot2_GetSelectedType(); //determine which device type is appropriate for the loaded ROM NDS_SLOT2_TYPE slot2_DetermineType(); NDS_SLOT2_TYPE slot2_DetermineTypeByGameCode(const char *theGameCode); template bool slot2_write(u32 addr, T val); template bool slot2_read(u32 addr, T &val); // ================================================================================= extern std::string GBACartridge_RomPath; extern std::string GBACartridge_SRAMPath; extern void (*FeedbackON)(bool enable); // feedback on/off enum ADDON_CFLASH_MODE { ADDON_CFLASH_MODE_Path, ADDON_CFLASH_MODE_File, ADDON_CFLASH_MODE_RomPath }; extern ADDON_CFLASH_MODE CFlash_Mode; extern std::string CFlash_Path; inline bool CFlash_IsUsingPath() { return CFlash_Mode==ADDON_CFLASH_MODE_Path || CFlash_Mode==ADDON_CFLASH_MODE_RomPath; } u16 Paddle_GetValue(); void Paddle_SetValue(u16 theValue); extern void guitarGrip_setKey(bool green, bool red, bool yellow, bool blue); // Guitar grip keys extern void piano_setKey(bool c, bool cs, bool d, bool ds, bool e, bool f, bool fs, bool g, bool gs, bool a, bool as, bool b, bool hic); //piano keys #endif //__SLOT_H__ desmume/src/libretro-common/include/streams/memory_stream.h000664 001750 001750 00000004244 12755534123 025410 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2015 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (memory_stream.h). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef _LIBRETRO_SDK_FILE_MEMORY_STREAM_H #define _LIBRETRO_SDK_FILE_MEMORY_STREAM_H #include #include typedef struct memstream memstream_t; memstream_t *memstream_open(unsigned writing); void memstream_close(memstream_t *stream); size_t memstream_read(memstream_t *stream, void *data, size_t bytes); size_t memstream_write(memstream_t *stream, const void *data, size_t bytes); int memstream_getc(memstream_t *stream); void memstream_putc(memstream_t *stream, int c); char *memstream_gets(memstream_t *stream, char *buffer, size_t len); size_t memstream_pos(memstream_t *stream); void memstream_rewind(memstream_t *stream); int memstream_seek(memstream_t *stream, int offset, int whence); void memstream_set_buffer(uint8_t *buffer, size_t size); size_t memstream_get_last_size(void); #endif desmume/src/utils/AsmJit/x86/x86defs.cpp000664 001750 001750 00000353732 12755534123 021123 0ustar00sergiosergio000000 000000 // [AsmJit] // Complete JIT Assembler for C++ Language. // // [License] // Zlib - See COPYING file in this package. #define ASMJIT_EXPORTS // [Dependencies - AsmJit] #include "../x86/x86defs.h" // [Api-Begin] #include "../core/apibegin.h" namespace AsmJit { // ============================================================================ // [AsmJit::x86InstName] // ============================================================================ // Following {DATA SECTION} is auto-generated by generate-defs.py tool using // X86InstInfo data. // // ${X86_INST_DATA:BEGIN} const char x86InstName[] = "\0" "adc\0" "add\0" "addpd\0" "addps\0" "addsd\0" "addss\0" "addsubpd\0" "addsubps\0" "amd_prefetch\0" "amd_prefetchw\0" "and\0" "andnpd\0" "andnps\0" "andpd\0" "andps\0" "blendpd\0" "blendps\0" "blendvpd\0" "blendvps\0" "bsf\0" "bsr\0" "bswap\0" "bt\0" "btc\0" "btr\0" "bts\0" "call\0" "cbw\0" "cdq\0" "cdqe\0" "clc\0" "cld\0" "clflush\0" "cmc\0" "cmova\0" "cmovae\0" "cmovb\0" "cmovbe\0" "cmovc\0" "cmove\0" "cmovg\0" "cmovge\0" "cmovl\0" "cmovle\0" "cmovna\0" "cmovnae\0" "cmovnb\0" "cmovnbe\0" "cmovnc\0" "cmovne\0" "cmovng\0" "cmovnge\0" "cmovnl\0" "cmovnle\0" "cmovno\0" "cmovnp\0" "cmovns\0" "cmovnz\0" "cmovo\0" "cmovp\0" "cmovpe\0" "cmovpo\0" "cmovs\0" "cmovz\0" "cmp\0" "cmppd\0" "cmpps\0" "cmpsd\0" "cmpss\0" "cmpxchg\0" "cmpxchg16b\0" "cmpxchg8b\0" "comisd\0" "comiss\0" "cpuid\0" "cqo\0" "crc32\0" "cvtdq2pd\0" "cvtdq2ps\0" "cvtpd2dq\0" "cvtpd2pi\0" "cvtpd2ps\0" "cvtpi2pd\0" "cvtpi2ps\0" "cvtps2dq\0" "cvtps2pd\0" "cvtps2pi\0" "cvtsd2si\0" "cvtsd2ss\0" "cvtsi2sd\0" "cvtsi2ss\0" "cvtss2sd\0" "cvtss2si\0" "cvttpd2dq\0" "cvttpd2pi\0" "cvttps2dq\0" "cvttps2pi\0" "cvttsd2si\0" "cvttss2si\0" "cwd\0" "cwde\0" "daa\0" "das\0" "dec\0" "div\0" "divpd\0" "divps\0" "divsd\0" "divss\0" "dppd\0" "dpps\0" "emms\0" "enter\0" "extractps\0" "f2xm1\0" "fabs\0" "fadd\0" "faddp\0" "fbld\0" "fbstp\0" "fchs\0" "fclex\0" "fcmovb\0" "fcmovbe\0" "fcmove\0" "fcmovnb\0" "fcmovnbe\0" "fcmovne\0" "fcmovnu\0" "fcmovu\0" "fcom\0" "fcomi\0" "fcomip\0" "fcomp\0" "fcompp\0" "fcos\0" "fdecstp\0" "fdiv\0" "fdivp\0" "fdivr\0" "fdivrp\0" "femms\0" "ffree\0" "fiadd\0" "ficom\0" "ficomp\0" "fidiv\0" "fidivr\0" "fild\0" "fimul\0" "fincstp\0" "finit\0" "fist\0" "fistp\0" "fisttp\0" "fisub\0" "fisubr\0" "fld\0" "fld1\0" "fldcw\0" "fldenv\0" "fldl2e\0" "fldl2t\0" "fldlg2\0" "fldln2\0" "fldpi\0" "fldz\0" "fmul\0" "fmulp\0" "fnclex\0" "fninit\0" "fnop\0" "fnsave\0" "fnstcw\0" "fnstenv\0" "fnstsw\0" "fpatan\0" "fprem\0" "fprem1\0" "fptan\0" "frndint\0" "frstor\0" "fsave\0" "fscale\0" "fsin\0" "fsincos\0" "fsqrt\0" "fst\0" "fstcw\0" "fstenv\0" "fstp\0" "fstsw\0" "fsub\0" "fsubp\0" "fsubr\0" "fsubrp\0" "ftst\0" "fucom\0" "fucomi\0" "fucomip\0" "fucomp\0" "fucompp\0" "fwait\0" "fxam\0" "fxch\0" "fxrstor\0" "fxsave\0" "fxtract\0" "fyl2x\0" "fyl2xp1\0" "haddpd\0" "haddps\0" "hsubpd\0" "hsubps\0" "idiv\0" "imul\0" "inc\0" "int3\0" "ja\0" "jae\0" "jb\0" "jbe\0" "jc\0" "je\0" "jg\0" "jge\0" "jl\0" "jle\0" "jna\0" "jnae\0" "jnb\0" "jnbe\0" "jnc\0" "jne\0" "jng\0" "jnge\0" "jnl\0" "jnle\0" "jno\0" "jnp\0" "jns\0" "jnz\0" "jo\0" "jp\0" "jpe\0" "jpo\0" "js\0" "jz\0" "jmp\0" "lddqu\0" "ldmxcsr\0" "lahf\0" "lea\0" "leave\0" "lfence\0" "maskmovdqu\0" "maskmovq\0" "maxpd\0" "maxps\0" "maxsd\0" "maxss\0" "mfence\0" "minpd\0" "minps\0" "minsd\0" "minss\0" "monitor\0" "mov\0" "movapd\0" "movaps\0" "movbe\0" "movd\0" "movddup\0" "movdq2q\0" "movdqa\0" "movdqu\0" "movhlps\0" "movhpd\0" "movhps\0" "movlhps\0" "movlpd\0" "movlps\0" "movmskpd\0" "movmskps\0" "movntdq\0" "movntdqa\0" "movnti\0" "movntpd\0" "movntps\0" "movntq\0" "movq\0" "movq2dq\0" "movsd\0" "movshdup\0" "movsldup\0" "movss\0" "movsx\0" "movsxd\0" "movupd\0" "movups\0" "movzx\0" "mov_ptr\0" "mpsadbw\0" "mul\0" "mulpd\0" "mulps\0" "mulsd\0" "mulss\0" "mwait\0" "neg\0" "nop\0" "not\0" "or\0" "orpd\0" "orps\0" "pabsb\0" "pabsd\0" "pabsw\0" "packssdw\0" "packsswb\0" "packusdw\0" "packuswb\0" "paddb\0" "paddd\0" "paddq\0" "paddsb\0" "paddsw\0" "paddusb\0" "paddusw\0" "paddw\0" "palignr\0" "pand\0" "pandn\0" "pause\0" "pavgb\0" "pavgw\0" "pblendvb\0" "pblendw\0" "pcmpeqb\0" "pcmpeqd\0" "pcmpeqq\0" "pcmpeqw\0" "pcmpestri\0" "pcmpestrm\0" "pcmpgtb\0" "pcmpgtd\0" "pcmpgtq\0" "pcmpgtw\0" "pcmpistri\0" "pcmpistrm\0" "pextrb\0" "pextrd\0" "pextrq\0" "pextrw\0" "pf2id\0" "pf2iw\0" "pfacc\0" "pfadd\0" "pfcmpeq\0" "pfcmpge\0" "pfcmpgt\0" "pfmax\0" "pfmin\0" "pfmul\0" "pfnacc\0" "pfpnacc\0" "pfrcp\0" "pfrcpit1\0" "pfrcpit2\0" "pfrsqit1\0" "pfrsqrt\0" "pfsub\0" "pfsubr\0" "phaddd\0" "phaddsw\0" "phaddw\0" "phminposuw\0" "phsubd\0" "phsubsw\0" "phsubw\0" "pi2fd\0" "pi2fw\0" "pinsrb\0" "pinsrd\0" "pinsrq\0" "pinsrw\0" "pmaddubsw\0" "pmaddwd\0" "pmaxsb\0" "pmaxsd\0" "pmaxsw\0" "pmaxub\0" "pmaxud\0" "pmaxuw\0" "pminsb\0" "pminsd\0" "pminsw\0" "pminub\0" "pminud\0" "pminuw\0" "pmovmskb\0" "pmovsxbd\0" "pmovsxbq\0" "pmovsxbw\0" "pmovsxdq\0" "pmovsxwd\0" "pmovsxwq\0" "pmovzxbd\0" "pmovzxbq\0" "pmovzxbw\0" "pmovzxdq\0" "pmovzxwd\0" "pmovzxwq\0" "pmuldq\0" "pmulhrsw\0" "pmulhuw\0" "pmulhw\0" "pmulld\0" "pmullw\0" "pmuludq\0" "pop\0" "popad\0" "popcnt\0" "popfd\0" "popfq\0" "por\0" "prefetch\0" "psadbw\0" "pshufb\0" "pshufd\0" "pshufw\0" "pshufhw\0" "pshuflw\0" "psignb\0" "psignd\0" "psignw\0" "pslld\0" "pslldq\0" "psllq\0" "psllw\0" "psrad\0" "psraw\0" "psrld\0" "psrldq\0" "psrlq\0" "psrlw\0" "psubb\0" "psubd\0" "psubq\0" "psubsb\0" "psubsw\0" "psubusb\0" "psubusw\0" "psubw\0" "pswapd\0" "ptest\0" "punpckhbw\0" "punpckhdq\0" "punpckhqdq\0" "punpckhwd\0" "punpcklbw\0" "punpckldq\0" "punpcklqdq\0" "punpcklwd\0" "push\0" "pushad\0" "pushfd\0" "pushfq\0" "pxor\0" "rcl\0" "rcpps\0" "rcpss\0" "rcr\0" "rdtsc\0" "rdtscp\0" "rep lodsb\0" "rep lodsd\0" "rep lodsq\0" "rep lodsw\0" "rep movsb\0" "rep movsd\0" "rep movsq\0" "rep movsw\0" "rep stosb\0" "rep stosd\0" "rep stosq\0" "rep stosw\0" "repe cmpsb\0" "repe cmpsd\0" "repe cmpsq\0" "repe cmpsw\0" "repe scasb\0" "repe scasd\0" "repe scasq\0" "repe scasw\0" "repne cmpsb\0" "repne cmpsd\0" "repne cmpsq\0" "repne cmpsw\0" "repne scasb\0" "repne scasd\0" "repne scasq\0" "repne scasw\0" "ret\0" "rol\0" "ror\0" "roundpd\0" "roundps\0" "roundsd\0" "roundss\0" "rsqrtps\0" "rsqrtss\0" "sahf\0" "sal\0" "sar\0" "sbb\0" "seta\0" "setae\0" "setb\0" "setbe\0" "setc\0" "sete\0" "setg\0" "setge\0" "setl\0" "setle\0" "setna\0" "setnae\0" "setnb\0" "setnbe\0" "setnc\0" "setne\0" "setng\0" "setnge\0" "setnl\0" "setnle\0" "setno\0" "setnp\0" "setns\0" "setnz\0" "seto\0" "setp\0" "setpe\0" "setpo\0" "sets\0" "setz\0" "sfence\0" "shl\0" "shld\0" "shr\0" "shrd\0" "shufpd\0" "shufps\0" "sqrtpd\0" "sqrtps\0" "sqrtsd\0" "sqrtss\0" "stc\0" "std\0" "stmxcsr\0" "sub\0" "subpd\0" "subps\0" "subsd\0" "subss\0" "test\0" "ucomisd\0" "ucomiss\0" "ud2\0" "unpckhpd\0" "unpckhps\0" "unpcklpd\0" "unpcklps\0" "xadd\0" "xchg\0" "xor\0" "xorpd\0" "xorps\0" ; #define INDEX_kInstNone 0 #define INDEX_kX86InstAdc 1 #define INDEX_kX86InstAdd 5 #define INDEX_kX86InstAddPD 9 #define INDEX_kX86InstAddPS 15 #define INDEX_kX86InstAddSD 21 #define INDEX_kX86InstAddSS 27 #define INDEX_kX86InstAddSubPD 33 #define INDEX_kX86InstAddSubPS 42 #define INDEX_kX86InstAmdPrefetch 51 #define INDEX_kX86InstAmdPrefetchW 64 #define INDEX_kX86InstAnd 78 #define INDEX_kX86InstAndnPD 82 #define INDEX_kX86InstAndnPS 89 #define INDEX_kX86InstAndPD 96 #define INDEX_kX86InstAndPS 102 #define INDEX_kX86InstBlendPD 108 #define INDEX_kX86InstBlendPS 116 #define INDEX_kX86InstBlendVPD 124 #define INDEX_kX86InstBlendVPS 133 #define INDEX_kX86InstBsf 142 #define INDEX_kX86InstBsr 146 #define INDEX_kX86InstBSwap 150 #define INDEX_kX86InstBt 156 #define INDEX_kX86InstBtc 159 #define INDEX_kX86InstBtr 163 #define INDEX_kX86InstBts 167 #define INDEX_kX86InstCall 171 #define INDEX_kX86InstCbw 176 #define INDEX_kX86InstCdq 180 #define INDEX_kX86InstCdqe 184 #define INDEX_kX86InstClc 189 #define INDEX_kX86InstCld 193 #define INDEX_kX86InstClFlush 197 #define INDEX_kX86InstCmc 205 #define INDEX_kX86InstCMovA 209 #define INDEX_kX86InstCMovAE 215 #define INDEX_kX86InstCMovB 222 #define INDEX_kX86InstCMovBE 228 #define INDEX_kX86InstCMovC 235 #define INDEX_kX86InstCMovE 241 #define INDEX_kX86InstCMovG 247 #define INDEX_kX86InstCMovGE 253 #define INDEX_kX86InstCMovL 260 #define INDEX_kX86InstCMovLE 266 #define INDEX_kX86InstCMovNA 273 #define INDEX_kX86InstCMovNAE 280 #define INDEX_kX86InstCMovNB 288 #define INDEX_kX86InstCMovNBE 295 #define INDEX_kX86InstCMovNC 303 #define INDEX_kX86InstCMovNE 310 #define INDEX_kX86InstCMovNG 317 #define INDEX_kX86InstCMovNGE 324 #define INDEX_kX86InstCMovNL 332 #define INDEX_kX86InstCMovNLE 339 #define INDEX_kX86InstCMovNO 347 #define INDEX_kX86InstCMovNP 354 #define INDEX_kX86InstCMovNS 361 #define INDEX_kX86InstCMovNZ 368 #define INDEX_kX86InstCMovO 375 #define INDEX_kX86InstCMovP 381 #define INDEX_kX86InstCMovPE 387 #define INDEX_kX86InstCMovPO 394 #define INDEX_kX86InstCMovS 401 #define INDEX_kX86InstCMovZ 407 #define INDEX_kX86InstCmp 413 #define INDEX_kX86InstCmpPD 417 #define INDEX_kX86InstCmpPS 423 #define INDEX_kX86InstCmpSD 429 #define INDEX_kX86InstCmpSS 435 #define INDEX_kX86InstCmpXCHG 441 #define INDEX_kX86InstCmpXCHG16B 449 #define INDEX_kX86InstCmpXCHG8B 460 #define INDEX_kX86InstComISD 470 #define INDEX_kX86InstComISS 477 #define INDEX_kX86InstCpuId 484 #define INDEX_kX86InstCqo 490 #define INDEX_kX86InstCrc32 494 #define INDEX_kX86InstCvtDQ2PD 500 #define INDEX_kX86InstCvtDQ2PS 509 #define INDEX_kX86InstCvtPD2DQ 518 #define INDEX_kX86InstCvtPD2PI 527 #define INDEX_kX86InstCvtPD2PS 536 #define INDEX_kX86InstCvtPI2PD 545 #define INDEX_kX86InstCvtPI2PS 554 #define INDEX_kX86InstCvtPS2DQ 563 #define INDEX_kX86InstCvtPS2PD 572 #define INDEX_kX86InstCvtPS2PI 581 #define INDEX_kX86InstCvtSD2SI 590 #define INDEX_kX86InstCvtSD2SS 599 #define INDEX_kX86InstCvtSI2SD 608 #define INDEX_kX86InstCvtSI2SS 617 #define INDEX_kX86InstCvtSS2SD 626 #define INDEX_kX86InstCvtSS2SI 635 #define INDEX_kX86InstCvttPD2DQ 644 #define INDEX_kX86InstCvttPD2PI 654 #define INDEX_kX86InstCvttPS2DQ 664 #define INDEX_kX86InstCvttPS2PI 674 #define INDEX_kX86InstCvttSD2SI 684 #define INDEX_kX86InstCvttSS2SI 694 #define INDEX_kX86InstCwd 704 #define INDEX_kX86InstCwde 708 #define INDEX_kX86InstDaa 713 #define INDEX_kX86InstDas 717 #define INDEX_kX86InstDec 721 #define INDEX_kX86InstDiv 725 #define INDEX_kX86InstDivPD 729 #define INDEX_kX86InstDivPS 735 #define INDEX_kX86InstDivSD 741 #define INDEX_kX86InstDivSS 747 #define INDEX_kX86InstDpPD 753 #define INDEX_kX86InstDpPS 758 #define INDEX_kX86InstEmms 763 #define INDEX_kX86InstEnter 768 #define INDEX_kX86InstExtractPS 774 #define INDEX_kX86InstF2XM1 784 #define INDEX_kX86InstFAbs 790 #define INDEX_kX86InstFAdd 795 #define INDEX_kX86InstFAddP 800 #define INDEX_kX86InstFBLd 806 #define INDEX_kX86InstFBStP 811 #define INDEX_kX86InstFCHS 817 #define INDEX_kX86InstFClex 822 #define INDEX_kX86InstFCMovB 828 #define INDEX_kX86InstFCMovBE 835 #define INDEX_kX86InstFCMovE 843 #define INDEX_kX86InstFCMovNB 850 #define INDEX_kX86InstFCMovNBE 858 #define INDEX_kX86InstFCMovNE 867 #define INDEX_kX86InstFCMovNU 875 #define INDEX_kX86InstFCMovU 883 #define INDEX_kX86InstFCom 890 #define INDEX_kX86InstFComI 895 #define INDEX_kX86InstFComIP 901 #define INDEX_kX86InstFComP 908 #define INDEX_kX86InstFComPP 914 #define INDEX_kX86InstFCos 921 #define INDEX_kX86InstFDecStP 926 #define INDEX_kX86InstFDiv 934 #define INDEX_kX86InstFDivP 939 #define INDEX_kX86InstFDivR 945 #define INDEX_kX86InstFDivRP 951 #define INDEX_kX86InstFEmms 958 #define INDEX_kX86InstFFree 964 #define INDEX_kX86InstFIAdd 970 #define INDEX_kX86InstFICom 976 #define INDEX_kX86InstFIComP 982 #define INDEX_kX86InstFIDiv 989 #define INDEX_kX86InstFIDivR 995 #define INDEX_kX86InstFILd 1002 #define INDEX_kX86InstFIMul 1007 #define INDEX_kX86InstFIncStP 1013 #define INDEX_kX86InstFInit 1021 #define INDEX_kX86InstFISt 1027 #define INDEX_kX86InstFIStP 1032 #define INDEX_kX86InstFISttP 1038 #define INDEX_kX86InstFISub 1045 #define INDEX_kX86InstFISubR 1051 #define INDEX_kX86InstFLd 1058 #define INDEX_kX86InstFLd1 1062 #define INDEX_kX86InstFLdCw 1067 #define INDEX_kX86InstFLdEnv 1073 #define INDEX_kX86InstFLdL2E 1080 #define INDEX_kX86InstFLdL2T 1087 #define INDEX_kX86InstFLdLg2 1094 #define INDEX_kX86InstFLdLn2 1101 #define INDEX_kX86InstFLdPi 1108 #define INDEX_kX86InstFLdZ 1114 #define INDEX_kX86InstFMul 1119 #define INDEX_kX86InstFMulP 1124 #define INDEX_kX86InstFNClex 1130 #define INDEX_kX86InstFNInit 1137 #define INDEX_kX86InstFNop 1144 #define INDEX_kX86InstFNSave 1149 #define INDEX_kX86InstFNStCw 1156 #define INDEX_kX86InstFNStEnv 1163 #define INDEX_kX86InstFNStSw 1171 #define INDEX_kX86InstFPAtan 1178 #define INDEX_kX86InstFPRem 1185 #define INDEX_kX86InstFPRem1 1191 #define INDEX_kX86InstFPTan 1198 #define INDEX_kX86InstFRndInt 1204 #define INDEX_kX86InstFRstor 1212 #define INDEX_kX86InstFSave 1219 #define INDEX_kX86InstFScale 1225 #define INDEX_kX86InstFSin 1232 #define INDEX_kX86InstFSinCos 1237 #define INDEX_kX86InstFSqrt 1245 #define INDEX_kX86InstFSt 1251 #define INDEX_kX86InstFStCw 1255 #define INDEX_kX86InstFStEnv 1261 #define INDEX_kX86InstFStP 1268 #define INDEX_kX86InstFStSw 1273 #define INDEX_kX86InstFSub 1279 #define INDEX_kX86InstFSubP 1284 #define INDEX_kX86InstFSubR 1290 #define INDEX_kX86InstFSubRP 1296 #define INDEX_kX86InstFTst 1303 #define INDEX_kX86InstFUCom 1308 #define INDEX_kX86InstFUComI 1314 #define INDEX_kX86InstFUComIP 1321 #define INDEX_kX86InstFUComP 1329 #define INDEX_kX86InstFUComPP 1336 #define INDEX_kX86InstFWait 1344 #define INDEX_kX86InstFXam 1350 #define INDEX_kX86InstFXch 1355 #define INDEX_kX86InstFXRstor 1360 #define INDEX_kX86InstFXSave 1368 #define INDEX_kX86InstFXtract 1375 #define INDEX_kX86InstFYL2X 1383 #define INDEX_kX86InstFYL2XP1 1389 #define INDEX_kX86InstHAddPD 1397 #define INDEX_kX86InstHAddPS 1404 #define INDEX_kX86InstHSubPD 1411 #define INDEX_kX86InstHSubPS 1418 #define INDEX_kX86InstIDiv 1425 #define INDEX_kX86InstIMul 1430 #define INDEX_kX86InstInc 1435 #define INDEX_kX86InstInt3 1439 #define INDEX_kX86InstJA 1444 #define INDEX_kX86InstJAE 1447 #define INDEX_kX86InstJB 1451 #define INDEX_kX86InstJBE 1454 #define INDEX_kX86InstJC 1458 #define INDEX_kX86InstJE 1461 #define INDEX_kX86InstJG 1464 #define INDEX_kX86InstJGE 1467 #define INDEX_kX86InstJL 1471 #define INDEX_kX86InstJLE 1474 #define INDEX_kX86InstJNA 1478 #define INDEX_kX86InstJNAE 1482 #define INDEX_kX86InstJNB 1487 #define INDEX_kX86InstJNBE 1491 #define INDEX_kX86InstJNC 1496 #define INDEX_kX86InstJNE 1500 #define INDEX_kX86InstJNG 1504 #define INDEX_kX86InstJNGE 1508 #define INDEX_kX86InstJNL 1513 #define INDEX_kX86InstJNLE 1517 #define INDEX_kX86InstJNO 1522 #define INDEX_kX86InstJNP 1526 #define INDEX_kX86InstJNS 1530 #define INDEX_kX86InstJNZ 1534 #define INDEX_kX86InstJO 1538 #define INDEX_kX86InstJP 1541 #define INDEX_kX86InstJPE 1544 #define INDEX_kX86InstJPO 1548 #define INDEX_kX86InstJS 1552 #define INDEX_kX86InstJZ 1555 #define INDEX_kX86InstJmp 1558 #define INDEX_kX86InstLdDQU 1562 #define INDEX_kX86InstLdMXCSR 1568 #define INDEX_kX86InstLahf 1576 #define INDEX_kX86InstLea 1581 #define INDEX_kX86InstLeave 1585 #define INDEX_kX86InstLFence 1591 #define INDEX_kX86InstMaskMovDQU 1598 #define INDEX_kX86InstMaskMovQ 1609 #define INDEX_kX86InstMaxPD 1618 #define INDEX_kX86InstMaxPS 1624 #define INDEX_kX86InstMaxSD 1630 #define INDEX_kX86InstMaxSS 1636 #define INDEX_kX86InstMFence 1642 #define INDEX_kX86InstMinPD 1649 #define INDEX_kX86InstMinPS 1655 #define INDEX_kX86InstMinSD 1661 #define INDEX_kX86InstMinSS 1667 #define INDEX_kX86InstMonitor 1673 #define INDEX_kX86InstMov 1681 #define INDEX_kX86InstMovAPD 1685 #define INDEX_kX86InstMovAPS 1692 #define INDEX_kX86InstMovBE 1699 #define INDEX_kX86InstMovD 1705 #define INDEX_kX86InstMovDDup 1710 #define INDEX_kX86InstMovDQ2Q 1718 #define INDEX_kX86InstMovDQA 1726 #define INDEX_kX86InstMovDQU 1733 #define INDEX_kX86InstMovHLPS 1740 #define INDEX_kX86InstMovHPD 1748 #define INDEX_kX86InstMovHPS 1755 #define INDEX_kX86InstMovLHPS 1762 #define INDEX_kX86InstMovLPD 1770 #define INDEX_kX86InstMovLPS 1777 #define INDEX_kX86InstMovMskPD 1784 #define INDEX_kX86InstMovMskPS 1793 #define INDEX_kX86InstMovNTDQ 1802 #define INDEX_kX86InstMovNTDQA 1810 #define INDEX_kX86InstMovNTI 1819 #define INDEX_kX86InstMovNTPD 1826 #define INDEX_kX86InstMovNTPS 1834 #define INDEX_kX86InstMovNTQ 1842 #define INDEX_kX86InstMovQ 1849 #define INDEX_kX86InstMovQ2DQ 1854 #define INDEX_kX86InstMovSD 1862 #define INDEX_kX86InstMovSHDup 1868 #define INDEX_kX86InstMovSLDup 1877 #define INDEX_kX86InstMovSS 1886 #define INDEX_kX86InstMovSX 1892 #define INDEX_kX86InstMovSXD 1898 #define INDEX_kX86InstMovUPD 1905 #define INDEX_kX86InstMovUPS 1912 #define INDEX_kX86InstMovZX 1919 #define INDEX_kX86InstMovPtr 1925 #define INDEX_kX86InstMPSADBW 1933 #define INDEX_kX86InstMul 1941 #define INDEX_kX86InstMulPD 1945 #define INDEX_kX86InstMulPS 1951 #define INDEX_kX86InstMulSD 1957 #define INDEX_kX86InstMulSS 1963 #define INDEX_kX86InstMWait 1969 #define INDEX_kX86InstNeg 1975 #define INDEX_kX86InstNop 1979 #define INDEX_kX86InstNot 1983 #define INDEX_kX86InstOr 1987 #define INDEX_kX86InstOrPD 1990 #define INDEX_kX86InstOrPS 1995 #define INDEX_kX86InstPAbsB 2000 #define INDEX_kX86InstPAbsD 2006 #define INDEX_kX86InstPAbsW 2012 #define INDEX_kX86InstPackSSDW 2018 #define INDEX_kX86InstPackSSWB 2027 #define INDEX_kX86InstPackUSDW 2036 #define INDEX_kX86InstPackUSWB 2045 #define INDEX_kX86InstPAddB 2054 #define INDEX_kX86InstPAddD 2060 #define INDEX_kX86InstPAddQ 2066 #define INDEX_kX86InstPAddSB 2072 #define INDEX_kX86InstPAddSW 2079 #define INDEX_kX86InstPAddUSB 2086 #define INDEX_kX86InstPAddUSW 2094 #define INDEX_kX86InstPAddW 2102 #define INDEX_kX86InstPAlignR 2108 #define INDEX_kX86InstPAnd 2116 #define INDEX_kX86InstPAndN 2121 #define INDEX_kX86InstPause 2127 #define INDEX_kX86InstPAvgB 2133 #define INDEX_kX86InstPAvgW 2139 #define INDEX_kX86InstPBlendVB 2145 #define INDEX_kX86InstPBlendW 2154 #define INDEX_kX86InstPCmpEqB 2162 #define INDEX_kX86InstPCmpEqD 2170 #define INDEX_kX86InstPCmpEqQ 2178 #define INDEX_kX86InstPCmpEqW 2186 #define INDEX_kX86InstPCmpEStrI 2194 #define INDEX_kX86InstPCmpEStrM 2204 #define INDEX_kX86InstPCmpGtB 2214 #define INDEX_kX86InstPCmpGtD 2222 #define INDEX_kX86InstPCmpGtQ 2230 #define INDEX_kX86InstPCmpGtW 2238 #define INDEX_kX86InstPCmpIStrI 2246 #define INDEX_kX86InstPCmpIStrM 2256 #define INDEX_kX86InstPExtrB 2266 #define INDEX_kX86InstPExtrD 2273 #define INDEX_kX86InstPExtrQ 2280 #define INDEX_kX86InstPExtrW 2287 #define INDEX_kX86InstPF2ID 2294 #define INDEX_kX86InstPF2IW 2300 #define INDEX_kX86InstPFAcc 2306 #define INDEX_kX86InstPFAdd 2312 #define INDEX_kX86InstPFCmpEQ 2318 #define INDEX_kX86InstPFCmpGE 2326 #define INDEX_kX86InstPFCmpGT 2334 #define INDEX_kX86InstPFMax 2342 #define INDEX_kX86InstPFMin 2348 #define INDEX_kX86InstPFMul 2354 #define INDEX_kX86InstPFNAcc 2360 #define INDEX_kX86InstPFPNAcc 2367 #define INDEX_kX86InstPFRcp 2375 #define INDEX_kX86InstPFRcpIt1 2381 #define INDEX_kX86InstPFRcpIt2 2390 #define INDEX_kX86InstPFRSqIt1 2399 #define INDEX_kX86InstPFRSqrt 2408 #define INDEX_kX86InstPFSub 2416 #define INDEX_kX86InstPFSubR 2422 #define INDEX_kX86InstPHAddD 2429 #define INDEX_kX86InstPHAddSW 2436 #define INDEX_kX86InstPHAddW 2444 #define INDEX_kX86InstPHMinPOSUW 2451 #define INDEX_kX86InstPHSubD 2462 #define INDEX_kX86InstPHSubSW 2469 #define INDEX_kX86InstPHSubW 2477 #define INDEX_kX86InstPI2FD 2484 #define INDEX_kX86InstPI2FW 2490 #define INDEX_kX86InstPInsRB 2496 #define INDEX_kX86InstPInsRD 2503 #define INDEX_kX86InstPInsRQ 2510 #define INDEX_kX86InstPInsRW 2517 #define INDEX_kX86InstPMAddUBSW 2524 #define INDEX_kX86InstPMAddWD 2534 #define INDEX_kX86InstPMaxSB 2542 #define INDEX_kX86InstPMaxSD 2549 #define INDEX_kX86InstPMaxSW 2556 #define INDEX_kX86InstPMaxUB 2563 #define INDEX_kX86InstPMaxUD 2570 #define INDEX_kX86InstPMaxUW 2577 #define INDEX_kX86InstPMinSB 2584 #define INDEX_kX86InstPMinSD 2591 #define INDEX_kX86InstPMinSW 2598 #define INDEX_kX86InstPMinUB 2605 #define INDEX_kX86InstPMinUD 2612 #define INDEX_kX86InstPMinUW 2619 #define INDEX_kX86InstPMovMskB 2626 #define INDEX_kX86InstPMovSXBD 2635 #define INDEX_kX86InstPMovSXBQ 2644 #define INDEX_kX86InstPMovSXBW 2653 #define INDEX_kX86InstPMovSXDQ 2662 #define INDEX_kX86InstPMovSXWD 2671 #define INDEX_kX86InstPMovSXWQ 2680 #define INDEX_kX86InstPMovZXBD 2689 #define INDEX_kX86InstPMovZXBQ 2698 #define INDEX_kX86InstPMovZXBW 2707 #define INDEX_kX86InstPMovZXDQ 2716 #define INDEX_kX86InstPMovZXWD 2725 #define INDEX_kX86InstPMovZXWQ 2734 #define INDEX_kX86InstPMulDQ 2743 #define INDEX_kX86InstPMulHRSW 2750 #define INDEX_kX86InstPMulHUW 2759 #define INDEX_kX86InstPMulHW 2767 #define INDEX_kX86InstPMulLD 2774 #define INDEX_kX86InstPMulLW 2781 #define INDEX_kX86InstPMulUDQ 2788 #define INDEX_kX86InstPop 2796 #define INDEX_kX86InstPopAD 2800 #define INDEX_kX86InstPopCnt 2806 #define INDEX_kX86InstPopFD 2813 #define INDEX_kX86InstPopFQ 2819 #define INDEX_kX86InstPOr 2825 #define INDEX_kX86InstPrefetch 2829 #define INDEX_kX86InstPSADBW 2838 #define INDEX_kX86InstPShufB 2845 #define INDEX_kX86InstPShufD 2852 #define INDEX_kX86InstPShufW 2859 #define INDEX_kX86InstPShufHW 2866 #define INDEX_kX86InstPShufLW 2874 #define INDEX_kX86InstPSignB 2882 #define INDEX_kX86InstPSignD 2889 #define INDEX_kX86InstPSignW 2896 #define INDEX_kX86InstPSllD 2903 #define INDEX_kX86InstPSllDQ 2909 #define INDEX_kX86InstPSllQ 2916 #define INDEX_kX86InstPSllW 2922 #define INDEX_kX86InstPSraD 2928 #define INDEX_kX86InstPSraW 2934 #define INDEX_kX86InstPSrlD 2940 #define INDEX_kX86InstPSrlDQ 2946 #define INDEX_kX86InstPSrlQ 2953 #define INDEX_kX86InstPSrlW 2959 #define INDEX_kX86InstPSubB 2965 #define INDEX_kX86InstPSubD 2971 #define INDEX_kX86InstPSubQ 2977 #define INDEX_kX86InstPSubSB 2983 #define INDEX_kX86InstPSubSW 2990 #define INDEX_kX86InstPSubUSB 2997 #define INDEX_kX86InstPSubUSW 3005 #define INDEX_kX86InstPSubW 3013 #define INDEX_kX86InstPSwapD 3019 #define INDEX_kX86InstPTest 3026 #define INDEX_kX86InstPunpckHBW 3032 #define INDEX_kX86InstPunpckHDQ 3042 #define INDEX_kX86InstPunpckHQDQ 3052 #define INDEX_kX86InstPunpckHWD 3063 #define INDEX_kX86InstPunpckLBW 3073 #define INDEX_kX86InstPunpckLDQ 3083 #define INDEX_kX86InstPunpckLQDQ 3093 #define INDEX_kX86InstPunpckLWD 3104 #define INDEX_kX86InstPush 3114 #define INDEX_kX86InstPushAD 3119 #define INDEX_kX86InstPushFD 3126 #define INDEX_kX86InstPushFQ 3133 #define INDEX_kX86InstPXor 3140 #define INDEX_kX86InstRcl 3145 #define INDEX_kX86InstRcpPS 3149 #define INDEX_kX86InstRcpSS 3155 #define INDEX_kX86InstRcr 3161 #define INDEX_kX86InstRdtsc 3165 #define INDEX_kX86InstRdtscP 3171 #define INDEX_kX86InstRepLodSB 3178 #define INDEX_kX86InstRepLodSD 3188 #define INDEX_kX86InstRepLodSQ 3198 #define INDEX_kX86InstRepLodSW 3208 #define INDEX_kX86InstRepMovSB 3218 #define INDEX_kX86InstRepMovSD 3228 #define INDEX_kX86InstRepMovSQ 3238 #define INDEX_kX86InstRepMovSW 3248 #define INDEX_kX86InstRepStoSB 3258 #define INDEX_kX86InstRepStoSD 3268 #define INDEX_kX86InstRepStoSQ 3278 #define INDEX_kX86InstRepStoSW 3288 #define INDEX_kX86InstRepECmpSB 3298 #define INDEX_kX86InstRepECmpSD 3309 #define INDEX_kX86InstRepECmpSQ 3320 #define INDEX_kX86InstRepECmpSW 3331 #define INDEX_kX86InstRepEScaSB 3342 #define INDEX_kX86InstRepEScaSD 3353 #define INDEX_kX86InstRepEScaSQ 3364 #define INDEX_kX86InstRepEScaSW 3375 #define INDEX_kX86InstRepNECmpSB 3386 #define INDEX_kX86InstRepNECmpSD 3398 #define INDEX_kX86InstRepNECmpSQ 3410 #define INDEX_kX86InstRepNECmpSW 3422 #define INDEX_kX86InstRepNEScaSB 3434 #define INDEX_kX86InstRepNEScaSD 3446 #define INDEX_kX86InstRepNEScaSQ 3458 #define INDEX_kX86InstRepNEScaSW 3470 #define INDEX_kX86InstRet 3482 #define INDEX_kX86InstRol 3486 #define INDEX_kX86InstRor 3490 #define INDEX_kX86InstRoundPD 3494 #define INDEX_kX86InstRoundPS 3502 #define INDEX_kX86InstRoundSD 3510 #define INDEX_kX86InstRoundSS 3518 #define INDEX_kX86InstRSqrtPS 3526 #define INDEX_kX86InstRSqrtSS 3534 #define INDEX_kX86InstSahf 3542 #define INDEX_kX86InstSal 3547 #define INDEX_kX86InstSar 3551 #define INDEX_kX86InstSbb 3555 #define INDEX_kX86InstSetA 3559 #define INDEX_kX86InstSetAE 3564 #define INDEX_kX86InstSetB 3570 #define INDEX_kX86InstSetBE 3575 #define INDEX_kX86InstSetC 3581 #define INDEX_kX86InstSetE 3586 #define INDEX_kX86InstSetG 3591 #define INDEX_kX86InstSetGE 3596 #define INDEX_kX86InstSetL 3602 #define INDEX_kX86InstSetLE 3607 #define INDEX_kX86InstSetNA 3613 #define INDEX_kX86InstSetNAE 3619 #define INDEX_kX86InstSetNB 3626 #define INDEX_kX86InstSetNBE 3632 #define INDEX_kX86InstSetNC 3639 #define INDEX_kX86InstSetNE 3645 #define INDEX_kX86InstSetNG 3651 #define INDEX_kX86InstSetNGE 3657 #define INDEX_kX86InstSetNL 3664 #define INDEX_kX86InstSetNLE 3670 #define INDEX_kX86InstSetNO 3677 #define INDEX_kX86InstSetNP 3683 #define INDEX_kX86InstSetNS 3689 #define INDEX_kX86InstSetNZ 3695 #define INDEX_kX86InstSetO 3701 #define INDEX_kX86InstSetP 3706 #define INDEX_kX86InstSetPE 3711 #define INDEX_kX86InstSetPO 3717 #define INDEX_kX86InstSetS 3723 #define INDEX_kX86InstSetZ 3728 #define INDEX_kX86InstSFence 3733 #define INDEX_kX86InstShl 3740 #define INDEX_kX86InstShld 3744 #define INDEX_kX86InstShr 3749 #define INDEX_kX86InstShrd 3753 #define INDEX_kX86InstShufPD 3758 #define INDEX_kX86InstShufPS 3765 #define INDEX_kX86InstSqrtPD 3772 #define INDEX_kX86InstSqrtPS 3779 #define INDEX_kX86InstSqrtSD 3786 #define INDEX_kX86InstSqrtSS 3793 #define INDEX_kX86InstStc 3800 #define INDEX_kX86InstStd 3804 #define INDEX_kX86InstStMXCSR 3808 #define INDEX_kX86InstSub 3816 #define INDEX_kX86InstSubPD 3820 #define INDEX_kX86InstSubPS 3826 #define INDEX_kX86InstSubSD 3832 #define INDEX_kX86InstSubSS 3838 #define INDEX_kX86InstTest 3844 #define INDEX_kX86InstUComISD 3849 #define INDEX_kX86InstUComISS 3857 #define INDEX_kX86InstUd2 3865 #define INDEX_kX86InstUnpckHPD 3869 #define INDEX_kX86InstUnpckHPS 3878 #define INDEX_kX86InstUnpckLPD 3887 #define INDEX_kX86InstUnpckLPS 3896 #define INDEX_kX86InstXadd 3905 #define INDEX_kX86InstXchg 3910 #define INDEX_kX86InstXor 3915 #define INDEX_kX86InstXorPD 3919 #define INDEX_kX86InstXorPS 3925 // ${X86_INST_DATA:END} // ============================================================================ // [AsmJit::x86InstInfo] // ============================================================================ #define INST(_Code_, _Name_, _Group_, _Flags_, _OpFlags0_, _OpFlags1_, _OpReg_, _OpCode0_, _OpCode1_) \ { _Code_, INDEX_##_Code_, _Group_, _Flags_, { _OpFlags0_, _OpFlags1_ }, _OpReg_, { _OpCode0_, _OpCode1_ } } #define G(_Group_) kX86InstGroup##_Group_ #define F(_Flags_) kX86InstFlag##_Flags_ #define O(_Op_) kX86InstOp##_Op_ const X86InstInfo x86InstInfo[] = { // Instruction code | Instruction name | Instruction group| Instruction flags| Operand flags[0] | Operand flags[1] | r| opCode[0] | opcode[1] INST(kInstNone , "" , G(None) , F(None) , 0 , 0 , 0, 0 , 0), INST(kX86InstAdc , "adc" , G(Arith) , F(Lockable) , O(GqdwbMem) , O(GqdwbMem)|O(Imm) , 2, 0x00000010, 0x00000080), INST(kX86InstAdd , "add" , G(Arith) , F(Lockable) , O(GqdwbMem) , O(GqdwbMem)|O(Imm) , 0, 0x00000000, 0x00000080), INST(kX86InstAddPD , "addpd" , G(MmuRmI) , F(None) , O(Xmm) , O(XmmMem) , 0, 0x66000F58, 0), INST(kX86InstAddPS , "addps" , G(MmuRmI) , F(None) , O(Xmm) , O(XmmMem) , 0, 0x00000F58, 0), INST(kX86InstAddSD , "addsd" , G(MmuRmI) , F(None) , O(Xmm) , O(XmmMem) , 0, 0xF2000F58, 0), INST(kX86InstAddSS , "addss" , G(MmuRmI) , F(None) , O(Xmm) , O(XmmMem) , 0, 0xF3000F58, 0), INST(kX86InstAddSubPD , "addsubpd" , G(MmuRmI) , F(None) , O(Xmm) , O(XmmMem) , 0, 0x66000FD0, 0), INST(kX86InstAddSubPS , "addsubps" , G(MmuRmI) , F(None) , O(Xmm) , O(XmmMem) , 0, 0xF2000FD0, 0), INST(kX86InstAmdPrefetch , "amd_prefetch" , G(Mem) , F(None) , O(Mem) , 0 , 0, 0x00000F0D, 0), INST(kX86InstAmdPrefetchW , "amd_prefetchw" , G(Mem) , F(None) , O(Mem) , 0 , 1, 0x00000F0D, 0), INST(kX86InstAnd , "and" , G(Arith) , F(Lockable) , O(GqdwbMem) , O(GqdwbMem)|O(Imm) , 4, 0x00000020, 0x00000080), INST(kX86InstAndnPD , "andnpd" , G(MmuRmI) , F(None) , O(Xmm) , O(XmmMem) , 0, 0x66000F55, 0), INST(kX86InstAndnPS , "andnps" , G(MmuRmI) , F(None) , O(Xmm) , O(XmmMem) , 0, 0x00000F55, 0), INST(kX86InstAndPD , "andpd" , G(MmuRmI) , F(None) , O(Xmm) , O(XmmMem) , 0, 0x66000F54, 0), INST(kX86InstAndPS , "andps" , G(MmuRmI) , F(None) , O(Xmm) , O(XmmMem) , 0, 0x00000F54, 0), INST(kX86InstBlendPD , "blendpd" , G(MmuRmImm8) , F(None) , O(Xmm) , O(XmmMem) , 0, 0x660F3A0D, 0), INST(kX86InstBlendPS , "blendps" , G(MmuRmImm8) , F(None) , O(Xmm) , O(XmmMem) , 0, 0x660F3A0C, 0), INST(kX86InstBlendVPD , "blendvpd" , G(MmuRmI) , F(None) , O(Xmm) , O(XmmMem) , 0, 0x660F3815, 0), INST(kX86InstBlendVPS , "blendvps" , G(MmuRmI) , F(None) , O(Xmm) , O(XmmMem) , 0, 0x660F3814, 0), INST(kX86InstBsf , "bsf" , G(RegRm) , F(None) , O(Gqdw) , O(GqdwMem) , 0, 0x00000FBC, 0), INST(kX86InstBsr , "bsr" , G(RegRm) , F(None) , O(Gqdw) , O(GqdwMem) , 0, 0x00000FBD, 0), INST(kX86InstBSwap , "bswap" , G(BSwap) , F(None) , O(Gqd) , 0 , 0, 0 , 0), INST(kX86InstBt , "bt" , G(BTest) , F(None) , O(Gqdw)|O(Mem) , O(Gqdw)|O(Imm) , 4, 0x00000FA3, 0x00000FBA), INST(kX86InstBtc , "btc" , G(BTest) , F(Lockable) , O(Gqdw)|O(Mem) , O(Gqdw)|O(Imm) , 7, 0x00000FBB, 0x00000FBA), INST(kX86InstBtr , "btr" , G(BTest) , F(Lockable) , O(Gqdw)|O(Mem) , O(Gqdw)|O(Imm) , 6, 0x00000FB3, 0x00000FBA), INST(kX86InstBts , "bts" , G(BTest) , F(Lockable) , O(Gqdw)|O(Mem) , O(Gqdw)|O(Imm) , 5, 0x00000FAB, 0x00000FBA), INST(kX86InstCall , "call" , G(Call) , F(Jump) , O(Gqd) |O(Mem) , 0 , 0, 0 , 0), INST(kX86InstCbw , "cbw" , G(Emit) , F(Special) , 0 , 0 , 0, 0x66000098, 0), INST(kX86InstCdq , "cdq" , G(Emit) , F(Special) , 0 , 0 , 0, 0x00000099, 0), INST(kX86InstCdqe , "cdqe" , G(Emit) , F(Special) , 0 , 0 , 0, 0x48000098, 0), INST(kX86InstClc , "clc" , G(Emit) , F(None) , 0 , 0 , 0, 0x000000F8, 0), INST(kX86InstCld , "cld" , G(Emit) , F(None) , 0 , 0 , 0, 0x000000FC, 0), INST(kX86InstClFlush , "clflush" , G(Mem) , F(None) , O(Mem) , 0 , 7, 0x00000FAE, 0), INST(kX86InstCmc , "cmc" , G(Emit) , F(None) , 0 , 0 , 0, 0x000000F5, 0), INST(kX86InstCMovA , "cmova" , G(RegRm) , F(None) , O(Gqdw) , O(GqdwMem) , 0, 0x00000F47, 0), INST(kX86InstCMovAE , "cmovae" , G(RegRm) , F(None) , O(Gqdw) , O(GqdwMem) , 0, 0x00000F43, 0), INST(kX86InstCMovB , "cmovb" , G(RegRm) , F(None) , O(Gqdw) , O(GqdwMem) , 0, 0x00000F42, 0), INST(kX86InstCMovBE , "cmovbe" , G(RegRm) , F(None) , O(Gqdw) , O(GqdwMem) , 0, 0x00000F46, 0), INST(kX86InstCMovC , "cmovc" , G(RegRm) , F(None) , O(Gqdw) , O(GqdwMem) , 0, 0x00000F42, 0), INST(kX86InstCMovE , "cmove" , G(RegRm) , F(None) , O(Gqdw) , O(GqdwMem) , 0, 0x00000F44, 0), INST(kX86InstCMovG , "cmovg" , G(RegRm) , F(None) , O(Gqdw) , O(GqdwMem) , 0, 0x00000F4F, 0), INST(kX86InstCMovGE , "cmovge" , G(RegRm) , F(None) , O(Gqdw) , O(GqdwMem) , 0, 0x00000F4D, 0), INST(kX86InstCMovL , "cmovl" , G(RegRm) , F(None) , O(Gqdw) , O(GqdwMem) , 0, 0x00000F4C, 0), INST(kX86InstCMovLE , "cmovle" , G(RegRm) , F(None) , O(Gqdw) , O(GqdwMem) , 0, 0x00000F4E, 0), INST(kX86InstCMovNA , "cmovna" , G(RegRm) , F(None) , O(Gqdw) , O(GqdwMem) , 0, 0x00000F46, 0), INST(kX86InstCMovNAE , "cmovnae" , G(RegRm) , F(None) , O(Gqdw) , O(GqdwMem) , 0, 0x00000F42, 0), INST(kX86InstCMovNB , "cmovnb" , G(RegRm) , F(None) , O(Gqdw) , O(GqdwMem) , 0, 0x00000F43, 0), INST(kX86InstCMovNBE , "cmovnbe" , G(RegRm) , F(None) , O(Gqdw) , O(GqdwMem) , 0, 0x00000F47, 0), INST(kX86InstCMovNC , "cmovnc" , G(RegRm) , F(None) , O(Gqdw) , O(GqdwMem) , 0, 0x00000F43, 0), INST(kX86InstCMovNE , "cmovne" , G(RegRm) , F(None) , O(Gqdw) , O(GqdwMem) , 0, 0x00000F45, 0), INST(kX86InstCMovNG , "cmovng" , G(RegRm) , F(None) , O(Gqdw) , O(GqdwMem) , 0, 0x00000F4E, 0), INST(kX86InstCMovNGE , "cmovnge" , G(RegRm) , F(None) , O(Gqdw) , O(GqdwMem) , 0, 0x00000F4C, 0), INST(kX86InstCMovNL , "cmovnl" , G(RegRm) , F(None) , O(Gqdw) , O(GqdwMem) , 0, 0x00000F4D, 0), INST(kX86InstCMovNLE , "cmovnle" , G(RegRm) , F(None) , O(Gqdw) , O(GqdwMem) , 0, 0x00000F4F, 0), INST(kX86InstCMovNO , "cmovno" , G(RegRm) , F(None) , O(Gqdw) , O(GqdwMem) , 0, 0x00000F41, 0), INST(kX86InstCMovNP , "cmovnp" , G(RegRm) , F(None) , O(Gqdw) , O(GqdwMem) , 0, 0x00000F4B, 0), INST(kX86InstCMovNS , "cmovns" , G(RegRm) , F(None) , O(Gqdw) , O(GqdwMem) , 0, 0x00000F49, 0), INST(kX86InstCMovNZ , "cmovnz" , G(RegRm) , F(None) , O(Gqdw) , O(GqdwMem) , 0, 0x00000F45, 0), INST(kX86InstCMovO , "cmovo" , G(RegRm) , F(None) , O(Gqdw) , O(GqdwMem) , 0, 0x00000F40, 0), INST(kX86InstCMovP , "cmovp" , G(RegRm) , F(None) , O(Gqdw) , O(GqdwMem) , 0, 0x00000F4A, 0), INST(kX86InstCMovPE , "cmovpe" , G(RegRm) , F(None) , O(Gqdw) , O(GqdwMem) , 0, 0x00000F4A, 0), INST(kX86InstCMovPO , "cmovpo" , G(RegRm) , F(None) , O(Gqdw) , O(GqdwMem) , 0, 0x00000F4B, 0), INST(kX86InstCMovS , "cmovs" , G(RegRm) , F(None) , O(Gqdw) , O(GqdwMem) , 0, 0x00000F48, 0), INST(kX86InstCMovZ , "cmovz" , G(RegRm) , F(None) , O(Gqdw) , O(GqdwMem) , 0, 0x00000F44, 0), INST(kX86InstCmp , "cmp" , G(Arith) , F(None) , O(GqdwbMem) , O(GqdwbMem)|O(Imm) , 7, 0x00000038, 0x00000080), INST(kX86InstCmpPD , "cmppd" , G(MmuRmImm8) , F(None) , O(Xmm) , O(XmmMem) , 0, 0x66000FC2, 0), INST(kX86InstCmpPS , "cmpps" , G(MmuRmImm8) , F(None) , O(Xmm) , O(XmmMem) , 0, 0x00000FC2, 0), INST(kX86InstCmpSD , "cmpsd" , G(MmuRmImm8) , F(None) , O(Xmm) , O(XmmMem) , 0, 0xF2000FC2, 0), INST(kX86InstCmpSS , "cmpss" , G(MmuRmImm8) , F(None) , O(Xmm) , O(XmmMem) , 0, 0xF3000FC2, 0), INST(kX86InstCmpXCHG , "cmpxchg" , G(RmReg) , F(Special)|F(Lockable), 0 , 0 , 0, 0x00000FB0, 0), INST(kX86InstCmpXCHG16B , "cmpxchg16b" , G(Mem) , F(Special) , O(Mem) , 0 , 1, 0x00000FC7, 1 /* RexW */), INST(kX86InstCmpXCHG8B , "cmpxchg8b" , G(Mem) , F(Special) , O(Mem) , 0 , 1, 0x00000FC7, 0), INST(kX86InstComISD , "comisd" , G(MmuRmI) , F(None) , O(Xmm) , O(XmmMem) , 0, 0x66000F2F, 0), INST(kX86InstComISS , "comiss" , G(MmuRmI) , F(None) , O(Xmm) , O(XmmMem) , 0, 0x00000F2F, 0), INST(kX86InstCpuId , "cpuid" , G(Emit) , F(Special) , 0 , 0 , 0, 0x00000FA2, 0), INST(kX86InstCqo , "cqo" , G(Emit) , F(Special) , 0 , 0 , 0, 0x48000099, 0), // TODO, set RexW bit instead? INST(kX86InstCrc32 , "crc32" , G(Crc32) , F(None) , O(Gqd) , O(GqdwbMem) , 0, 0xF20F38F0, 0), INST(kX86InstCvtDQ2PD , "cvtdq2pd" , G(MmuRmI) , F(Mov) , O(Xmm) , O(XmmMem) , 0, 0xF3000FE6, 0), INST(kX86InstCvtDQ2PS , "cvtdq2ps" , G(MmuRmI) , F(Mov) , O(Xmm) , O(XmmMem) , 0, 0x00000F5B, 0), INST(kX86InstCvtPD2DQ , "cvtpd2dq" , G(MmuRmI) , F(Mov) , O(Xmm) , O(XmmMem) , 0, 0xF2000FE6, 0), INST(kX86InstCvtPD2PI , "cvtpd2pi" , G(MmuRmI) , F(Mov) , O(Mm) , O(XmmMem) , 0, 0x66000F2D, 0), INST(kX86InstCvtPD2PS , "cvtpd2ps" , G(MmuRmI) , F(Mov) , O(Xmm) , O(XmmMem) , 0, 0x66000F5A, 0), INST(kX86InstCvtPI2PD , "cvtpi2pd" , G(MmuRmI) , F(Mov) , O(Xmm) , O(MmMem) , 0, 0x66000F2A, 0), INST(kX86InstCvtPI2PS , "cvtpi2ps" , G(MmuRmI) , F(None) , O(Xmm) , O(MmMem) , 0, 0x00000F2A, 0), INST(kX86InstCvtPS2DQ , "cvtps2dq" , G(MmuRmI) , F(Mov) , O(Xmm) , O(XmmMem) , 0, 0x66000F5B, 0), INST(kX86InstCvtPS2PD , "cvtps2pd" , G(MmuRmI) , F(Mov) , O(Xmm) , O(XmmMem) , 0, 0x00000F5A, 0), INST(kX86InstCvtPS2PI , "cvtps2pi" , G(MmuRmI) , F(Mov) , O(Mm) , O(XmmMem) , 0, 0x00000F2D, 0), INST(kX86InstCvtSD2SI , "cvtsd2si" , G(MmuRmI) , F(Mov) , O(Gqd) , O(XmmMem) , 0, 0xF2000F2D, 0), INST(kX86InstCvtSD2SS , "cvtsd2ss" , G(MmuRmI) , F(None) , O(Xmm) , O(XmmMem) , 0, 0xF2000F5A, 0), INST(kX86InstCvtSI2SD , "cvtsi2sd" , G(MmuRmI) , F(None) , O(Xmm) , O(Gqd)|O(Mem) , 0, 0xF2000F2A, 0), INST(kX86InstCvtSI2SS , "cvtsi2ss" , G(MmuRmI) , F(None) , O(Xmm) , O(Gqd)|O(Mem) , 0, 0xF3000F2A, 0), INST(kX86InstCvtSS2SD , "cvtss2sd" , G(MmuRmI) , F(None) , O(Xmm) , O(XmmMem) , 0, 0xF3000F5A, 0), INST(kX86InstCvtSS2SI , "cvtss2si" , G(MmuRmI) , F(None) , O(Gqd) , O(XmmMem) , 0, 0xF3000F2D, 0), INST(kX86InstCvttPD2DQ , "cvttpd2dq" , G(MmuRmI) , F(Mov) , O(Xmm) , O(XmmMem) , 0, 0x66000FE6, 0), INST(kX86InstCvttPD2PI , "cvttpd2pi" , G(MmuRmI) , F(Mov) , O(Mm) , O(XmmMem) , 0, 0x66000F2C, 0), INST(kX86InstCvttPS2DQ , "cvttps2dq" , G(MmuRmI) , F(Mov) , O(Xmm) , O(XmmMem) , 0, 0xF3000F5B, 0), INST(kX86InstCvttPS2PI , "cvttps2pi" , G(MmuRmI) , F(Mov) , O(Mm) , O(XmmMem) , 0, 0x00000F2C, 0), INST(kX86InstCvttSD2SI , "cvttsd2si" , G(MmuRmI) , F(None) , O(Gqd) , O(XmmMem) , 0, 0xF2000F2C, 0), INST(kX86InstCvttSS2SI , "cvttss2si" , G(MmuRmI) , F(None) , O(Gqd) , O(XmmMem) , 0, 0xF3000F2C, 0), INST(kX86InstCwd , "cwd" , G(Emit) , F(Special) , 0 , 0 , 0, 0x66000099, 0), INST(kX86InstCwde , "cwde" , G(Emit) , F(Special) , 0 , 0 , 0, 0x00000098, 0), INST(kX86InstDaa , "daa" , G(Emit) , F(Special) , 0 , 0 , 0, 0x00000027, 0), INST(kX86InstDas , "das" , G(Emit) , F(Special) , 0 , 0 , 0, 0x0000002F, 0), INST(kX86InstDec , "dec" , G(IncDec) , F(Lockable) , O(GqdwbMem) , 0 , 1, 0x00000048, 0x000000FE), INST(kX86InstDiv , "div" , G(Rm) , F(Special) , 0 , 0 , 6, 0x000000F6, 0), INST(kX86InstDivPD , "divpd" , G(MmuRmI) , F(None) , O(Xmm) , O(XmmMem) , 0, 0x66000F5E, 0), INST(kX86InstDivPS , "divps" , G(MmuRmI) , F(None) , O(Xmm) , O(XmmMem) , 0, 0x00000F5E, 0), INST(kX86InstDivSD , "divsd" , G(MmuRmI) , F(None) , O(Xmm) , O(XmmMem) , 0, 0xF2000F5E, 0), INST(kX86InstDivSS , "divss" , G(MmuRmI) , F(None) , O(Xmm) , O(XmmMem) , 0, 0xF3000F5E, 0), INST(kX86InstDpPD , "dppd" , G(MmuRmImm8) , F(None) , O(Xmm) , O(XmmMem) , 0, 0x660F3A41, 0), INST(kX86InstDpPS , "dpps" , G(MmuRmImm8) , F(None) , O(Xmm) , O(XmmMem) , 0, 0x660F3A40, 0), INST(kX86InstEmms , "emms" , G(Emit) , F(None) , 0 , 0 , 0, 0x00000F77, 0), INST(kX86InstEnter , "enter" , G(Enter) , F(Special) , 0 , 0 , 0, 0x000000C8, 0), INST(kX86InstExtractPS , "extractps" , G(MmuRmImm8) , F(None) , O(Xmm) , O(XmmMem) , 0, 0x660F3A17, 0), INST(kX86InstF2XM1 , "f2xm1" , G(Emit) , F(Fpu) , 0 , 0 , 0, 0x0000D9F0, 0), INST(kX86InstFAbs , "fabs" , G(Emit) , F(Fpu) , 0 , 0 , 0, 0x0000D9E1, 0), INST(kX86InstFAdd , "fadd" , G(X87StM) , F(Fpu) , 0 , 0 , 0, 0xD8DCC0C0, 0), INST(kX86InstFAddP , "faddp" , G(X87StI) , F(Fpu) , 0 , 0 , 0, 0x0000DEC0, 0), INST(kX86InstFBLd , "fbld" , G(Mem) , F(Fpu) , O(Mem) , 0 , 4, 0x000000DF, 0), INST(kX86InstFBStP , "fbstp" , G(Mem) , F(Fpu) , O(Mem) , 0 , 6, 0x000000DF, 0), INST(kX86InstFCHS , "fchs" , G(Emit) , F(Fpu) , 0 , 0 , 0, 0x0000D9E0, 0), INST(kX86InstFClex , "fclex" , G(Emit) , F(Fpu) , 0 , 0 , 0, 0x9B00DBE2, 0), INST(kX86InstFCMovB , "fcmovb" , G(X87StI) , F(Fpu) , 0 , 0 , 0, 0x0000DAC0, 0), INST(kX86InstFCMovBE , "fcmovbe" , G(X87StI) , F(Fpu) , 0 , 0 , 0, 0x0000DAD0, 0), INST(kX86InstFCMovE , "fcmove" , G(X87StI) , F(Fpu) , 0 , 0 , 0, 0x0000DAC8, 0), INST(kX86InstFCMovNB , "fcmovnb" , G(X87StI) , F(Fpu) , 0 , 0 , 0, 0x0000DBC0, 0), INST(kX86InstFCMovNBE , "fcmovnbe" , G(X87StI) , F(Fpu) , 0 , 0 , 0, 0x0000DBD0, 0), INST(kX86InstFCMovNE , "fcmovne" , G(X87StI) , F(Fpu) , 0 , 0 , 0, 0x0000DBC8, 0), INST(kX86InstFCMovNU , "fcmovnu" , G(X87StI) , F(Fpu) , 0 , 0 , 0, 0x0000DBD8, 0), INST(kX86InstFCMovU , "fcmovu" , G(X87StI) , F(Fpu) , 0 , 0 , 0, 0x0000DAD8, 0), INST(kX86InstFCom , "fcom" , G(X87StM) , F(Fpu) , 0 , 0 , 2, 0xD8DCD0D0, 0), INST(kX86InstFComI , "fcomi" , G(X87StI) , F(Fpu) , 0 , 0 , 0, 0x0000DBF0, 0), INST(kX86InstFComIP , "fcomip" , G(X87StI) , F(Fpu) , 0 , 0 , 0, 0x0000DFF0, 0), INST(kX86InstFComP , "fcomp" , G(X87StM) , F(Fpu) , 0 , 0 , 3, 0xD8DCD8D8, 0), INST(kX86InstFComPP , "fcompp" , G(Emit) , F(Fpu) , 0 , 0 , 0, 0x0000DED9, 0), INST(kX86InstFCos , "fcos" , G(Emit) , F(Fpu) , 0 , 0 , 0, 0x0000D9FF, 0), INST(kX86InstFDecStP , "fdecstp" , G(Emit) , F(Fpu) , 0 , 0 , 0, 0x0000D9F6, 0), INST(kX86InstFDiv , "fdiv" , G(X87StM) , F(Fpu) , 0 , 0 , 6, 0xD8DCF0F8, 0), INST(kX86InstFDivP , "fdivp" , G(X87StI) , F(Fpu) , 0 , 0 , 0, 0x0000DEF8, 0), INST(kX86InstFDivR , "fdivr" , G(X87StM) , F(Fpu) , 0 , 0 , 7, 0xD8DCF8F0, 0), INST(kX86InstFDivRP , "fdivrp" , G(X87StI) , F(Fpu) , 0 , 0 , 0, 0x0000DEF0, 0), INST(kX86InstFEmms , "femms" , G(Emit) , F(Fpu) , 0 , 0 , 0, 0x00000F0E, 0), INST(kX86InstFFree , "ffree" , G(X87StI) , F(Fpu) , 0 , 0 , 0, 0x0000DDC0, 0), INST(kX86InstFIAdd , "fiadd" , G(X87Mem) , F(Fpu) , O(StM2_4) , 0 , 0, 0xDEDA0000, 0), INST(kX86InstFICom , "ficom" , G(X87Mem) , F(Fpu) , O(StM2_4) , 0 , 2, 0xDEDA0000, 0), INST(kX86InstFIComP , "ficomp" , G(X87Mem) , F(Fpu) , O(StM2_4) , 0 , 3, 0xDEDA0000, 0), INST(kX86InstFIDiv , "fidiv" , G(X87Mem) , F(Fpu) , O(StM2_4) , 0 , 6, 0xDEDA0000, 0), INST(kX86InstFIDivR , "fidivr" , G(X87Mem) , F(Fpu) , O(StM2_4) , 0 , 7, 0xDEDA0000, 0), INST(kX86InstFILd , "fild" , G(X87Mem) , F(Fpu) , O(StM2_4_8) , 0 , 0, 0xDFDBDF05, 0), INST(kX86InstFIMul , "fimul" , G(X87Mem) , F(Fpu) , O(StM2_4) , 0 , 1, 0xDEDA0000, 0), INST(kX86InstFIncStP , "fincstp" , G(Emit) , F(Fpu) , 0 , 0 , 0, 0x0000D9F7, 0), INST(kX86InstFInit , "finit" , G(Emit) , F(Fpu) , 0 , 0 , 0, 0x9B00DBE3, 0), INST(kX86InstFISt , "fist" , G(X87Mem) , F(Fpu) , O(StM2_4) , 0 , 2, 0xDFDB0000, 0), INST(kX86InstFIStP , "fistp" , G(X87Mem) , F(Fpu) , O(StM2_4_8) , 0 , 3, 0xDFDBDF07, 0), INST(kX86InstFISttP , "fisttp" , G(X87Mem) , F(Fpu) , O(StM2_4_8) , 0 , 1, 0xDFDBDD01, 0), INST(kX86InstFISub , "fisub" , G(X87Mem) , F(Fpu) , O(StM2_4) , 0 , 4, 0xDEDA0000, 0), INST(kX86InstFISubR , "fisubr" , G(X87Mem) , F(Fpu) , O(StM2_4) , 0 , 5, 0xDEDA0000, 0), INST(kX86InstFLd , "fld" , G(X87FldFst) , F(Fpu) , O(StM4_8_10) , 0 , 0, 0x00D9DD00, 0xD9C0DB05), INST(kX86InstFLd1 , "fld1" , G(Emit) , F(Fpu) , 0 , 0 , 0, 0x0000D9E8, 0), INST(kX86InstFLdCw , "fldcw" , G(Mem) , F(Fpu) , O(Mem) , 0 , 5, 0x000000D9, 0), INST(kX86InstFLdEnv , "fldenv" , G(Mem) , F(Fpu) , O(Mem) , 0 , 4, 0x000000D9, 0), INST(kX86InstFLdL2E , "fldl2e" , G(Emit) , F(Fpu) , 0 , 0 , 0, 0x0000D9EA, 0), INST(kX86InstFLdL2T , "fldl2t" , G(Emit) , F(Fpu) , 0 , 0 , 0, 0x0000D9E9, 0), INST(kX86InstFLdLg2 , "fldlg2" , G(Emit) , F(Fpu) , 0 , 0 , 0, 0x0000D9EC, 0), INST(kX86InstFLdLn2 , "fldln2" , G(Emit) , F(Fpu) , 0 , 0 , 0, 0x0000D9ED, 0), INST(kX86InstFLdPi , "fldpi" , G(Emit) , F(Fpu) , 0 , 0 , 0, 0x0000D9EB, 0), INST(kX86InstFLdZ , "fldz" , G(Emit) , F(Fpu) , 0 , 0 , 0, 0x0000D9EE, 0), INST(kX86InstFMul , "fmul" , G(X87StM) , F(Fpu) , 0 , 0 , 1, 0xD8DCC8C8, 0), INST(kX86InstFMulP , "fmulp" , G(X87StI) , F(Fpu) , 0 , 0 , 0, 0x0000DEC8, 0), INST(kX86InstFNClex , "fnclex" , G(Emit) , F(Fpu) , 0 , 0 , 0, 0x0000DBE2, 0), INST(kX86InstFNInit , "fninit" , G(Emit) , F(Fpu) , 0 , 0 , 0, 0x0000DBE3, 0), INST(kX86InstFNop , "fnop" , G(Emit) , F(Fpu) , 0 , 0 , 0, 0x0000D9D0, 0), INST(kX86InstFNSave , "fnsave" , G(Mem) , F(Fpu) , O(Mem) , 0 , 6, 0x000000DD, 0), INST(kX86InstFNStCw , "fnstcw" , G(Mem) , F(Fpu) , O(Mem) , 0 , 7, 0x000000D9, 0), INST(kX86InstFNStEnv , "fnstenv" , G(Mem) , F(Fpu) , O(Mem) , 0 , 6, 0x000000D9, 0), INST(kX86InstFNStSw , "fnstsw" , G(X87Status) , F(Fpu) , O(Mem) , 0 , 7, 0x000000DD, 0x0000DFE0), INST(kX86InstFPAtan , "fpatan" , G(Emit) , F(Fpu) , 0 , 0 , 0, 0x0000D9F3, 0), INST(kX86InstFPRem , "fprem" , G(Emit) , F(Fpu) , 0 , 0 , 0, 0x0000D9F8, 0), INST(kX86InstFPRem1 , "fprem1" , G(Emit) , F(Fpu) , 0 , 0 , 0, 0x0000D9F5, 0), INST(kX86InstFPTan , "fptan" , G(Emit) , F(Fpu) , 0 , 0 , 0, 0x0000D9F2, 0), INST(kX86InstFRndInt , "frndint" , G(Emit) , F(Fpu) , 0 , 0 , 0, 0x0000D9FC, 0), INST(kX86InstFRstor , "frstor" , G(Mem) , F(Fpu) , O(Mem) , 0 , 4, 0x000000DD, 0), INST(kX86InstFSave , "fsave" , G(Mem) , F(Fpu) , O(Mem) , 0 , 6, 0x9B0000DD, 0), INST(kX86InstFScale , "fscale" , G(Emit) , F(Fpu) , 0 , 0 , 0, 0x0000D9FD, 0), INST(kX86InstFSin , "fsin" , G(Emit) , F(Fpu) , 0 , 0 , 0, 0x0000D9FE, 0), INST(kX86InstFSinCos , "fsincos" , G(Emit) , F(Fpu) , 0 , 0 , 0, 0x0000D9FB, 0), INST(kX86InstFSqrt , "fsqrt" , G(Emit) , F(Fpu) , 0 , 0 , 0, 0x0000D9FA, 0), INST(kX86InstFSt , "fst" , G(X87FldFst) , F(Fpu) , O(StM4_8) , 0 , 2, 0x00D9DD02, 0xDDD00000), INST(kX86InstFStCw , "fstcw" , G(Mem) , F(Fpu) , O(Mem) , 0 , 7, 0x9B0000D9, 0), INST(kX86InstFStEnv , "fstenv" , G(Mem) , F(Fpu) , O(Mem) , 0 , 6, 0x9B0000D9, 0), INST(kX86InstFStP , "fstp" , G(X87FldFst) , F(Fpu) , O(StM4_8_10) , 0 , 3, 0x00D9DD03, 0xDDD8DB07), INST(kX86InstFStSw , "fstsw" , G(X87Status) , F(Fpu) , O(Mem) , 0 , 7, 0x9B0000DD, 0x9B00DFE0), INST(kX86InstFSub , "fsub" , G(X87StM) , F(Fpu) , 0 , 0 , 4, 0xD8DCE0E8, 0), INST(kX86InstFSubP , "fsubp" , G(X87StI) , F(Fpu) , 0 , 0 , 0, 0x0000DEE8, 0), INST(kX86InstFSubR , "fsubr" , G(X87StM) , F(Fpu) , 0 , 0 , 5, 0xD8DCE8E0, 0), INST(kX86InstFSubRP , "fsubrp" , G(X87StI) , F(Fpu) , 0 , 0 , 0, 0x0000DEE0, 0), INST(kX86InstFTst , "ftst" , G(Emit) , F(Fpu) , 0 , 0 , 0, 0x0000D9E4, 0), INST(kX86InstFUCom , "fucom" , G(X87StI) , F(Fpu) , 0 , 0 , 0, 0x0000DDE0, 0), INST(kX86InstFUComI , "fucomi" , G(X87StI) , F(Fpu) , 0 , 0 , 0, 0x0000DBE8, 0), INST(kX86InstFUComIP , "fucomip" , G(X87StI) , F(Fpu) , 0 , 0 , 0, 0x0000DFE8, 0), INST(kX86InstFUComP , "fucomp" , G(X87StI) , F(Fpu) , 0 , 0 , 0, 0x0000DDE8, 0), INST(kX86InstFUComPP , "fucompp" , G(Emit) , F(Fpu) , 0 , 0 , 0, 0x0000DAE9, 0), INST(kX86InstFWait , "fwait" , G(Emit) , F(Fpu) , 0 , 0 , 0, 0x000000DB, 0), INST(kX86InstFXam , "fxam" , G(Emit) , F(Fpu) , 0 , 0 , 0, 0x0000D9E5, 0), INST(kX86InstFXch , "fxch" , G(X87StI) , F(Fpu) , 0 , 0 , 0, 0x0000D9C8, 0), INST(kX86InstFXRstor , "fxrstor" , G(Mem) , F(Fpu) , 0 , 0 , 1, 0x00000FAE, 0), INST(kX86InstFXSave , "fxsave" , G(Mem) , F(Fpu) , 0 , 0 , 0, 0x00000FAE, 0), INST(kX86InstFXtract , "fxtract" , G(Emit) , F(Fpu) , 0 , 0 , 0, 0x0000D9F4, 0), INST(kX86InstFYL2X , "fyl2x" , G(Emit) , F(Fpu) , 0 , 0 , 0, 0x0000D9F1, 0), INST(kX86InstFYL2XP1 , "fyl2xp1" , G(Emit) , F(Fpu) , 0 , 0 , 0, 0x0000D9F9, 0), INST(kX86InstHAddPD , "haddpd" , G(MmuRmI) , F(None) , O(Xmm) , O(XmmMem) , 0, 0x66000F7C, 0), INST(kX86InstHAddPS , "haddps" , G(MmuRmI) , F(None) , O(Xmm) , O(XmmMem) , 0, 0xF2000F7C, 0), INST(kX86InstHSubPD , "hsubpd" , G(MmuRmI) , F(None) , O(Xmm) , O(XmmMem) , 0, 0x66000F7D, 0), INST(kX86InstHSubPS , "hsubps" , G(MmuRmI) , F(None) , O(Xmm) , O(XmmMem) , 0, 0xF2000F7D, 0), INST(kX86InstIDiv , "idiv" , G(Rm) , F(Special) , 0 , 0 , 7, 0x000000F6, 0), INST(kX86InstIMul , "imul" , G(IMul) , F(Special) , 0 , 0 , 0, 0 , 0), INST(kX86InstInc , "inc" , G(IncDec) , F(Lockable) , O(GqdwbMem) , 0 , 0, 0x00000040, 0x000000FE), INST(kX86InstInt3 , "int3" , G(Emit) , F(None) , 0 , 0 , 0, 0x000000CC, 0), INST(kX86InstJA , "ja" , G(Jcc) , F(Jump) , 0 , 0 , 0, 0x7 , 0), INST(kX86InstJAE , "jae" , G(Jcc) , F(Jump) , 0 , 0 , 0, 0x3 , 0), INST(kX86InstJB , "jb" , G(Jcc) , F(Jump) , 0 , 0 , 0, 0x2 , 0), INST(kX86InstJBE , "jbe" , G(Jcc) , F(Jump) , 0 , 0 , 0, 0x6 , 0), INST(kX86InstJC , "jc" , G(Jcc) , F(Jump) , 0 , 0 , 0, 0x2 , 0), INST(kX86InstJE , "je" , G(Jcc) , F(Jump) , 0 , 0 , 0, 0x4 , 0), INST(kX86InstJG , "jg" , G(Jcc) , F(Jump) , 0 , 0 , 0, 0xF , 0), INST(kX86InstJGE , "jge" , G(Jcc) , F(Jump) , 0 , 0 , 0, 0xD , 0), INST(kX86InstJL , "jl" , G(Jcc) , F(Jump) , 0 , 0 , 0, 0xC , 0), INST(kX86InstJLE , "jle" , G(Jcc) , F(Jump) , 0 , 0 , 0, 0xE , 0), INST(kX86InstJNA , "jna" , G(Jcc) , F(Jump) , 0 , 0 , 0, 0x6 , 0), INST(kX86InstJNAE , "jnae" , G(Jcc) , F(Jump) , 0 , 0 , 0, 0x2 , 0), INST(kX86InstJNB , "jnb" , G(Jcc) , F(Jump) , 0 , 0 , 0, 0x3 , 0), INST(kX86InstJNBE , "jnbe" , G(Jcc) , F(Jump) , 0 , 0 , 0, 0x7 , 0), INST(kX86InstJNC , "jnc" , G(Jcc) , F(Jump) , 0 , 0 , 0, 0x3 , 0), INST(kX86InstJNE , "jne" , G(Jcc) , F(Jump) , 0 , 0 , 0, 0x5 , 0), INST(kX86InstJNG , "jng" , G(Jcc) , F(Jump) , 0 , 0 , 0, 0xE , 0), INST(kX86InstJNGE , "jnge" , G(Jcc) , F(Jump) , 0 , 0 , 0, 0xC , 0), INST(kX86InstJNL , "jnl" , G(Jcc) , F(Jump) , 0 , 0 , 0, 0xD , 0), INST(kX86InstJNLE , "jnle" , G(Jcc) , F(Jump) , 0 , 0 , 0, 0xF , 0), INST(kX86InstJNO , "jno" , G(Jcc) , F(Jump) , 0 , 0 , 0, 0x1 , 0), INST(kX86InstJNP , "jnp" , G(Jcc) , F(Jump) , 0 , 0 , 0, 0xB , 0), INST(kX86InstJNS , "jns" , G(Jcc) , F(Jump) , 0 , 0 , 0, 0x9 , 0), INST(kX86InstJNZ , "jnz" , G(Jcc) , F(Jump) , 0 , 0 , 0, 0x5 , 0), INST(kX86InstJO , "jo" , G(Jcc) , F(Jump) , 0 , 0 , 0, 0x0 , 0), INST(kX86InstJP , "jp" , G(Jcc) , F(Jump) , 0 , 0 , 0, 0xA , 0), INST(kX86InstJPE , "jpe" , G(Jcc) , F(Jump) , 0 , 0 , 0, 0xA , 0), INST(kX86InstJPO , "jpo" , G(Jcc) , F(Jump) , 0 , 0 , 0, 0xB , 0), INST(kX86InstJS , "js" , G(Jcc) , F(Jump) , 0 , 0 , 0, 0x8 , 0), INST(kX86InstJZ , "jz" , G(Jcc) , F(Jump) , 0 , 0 , 0, 0x4 , 0), INST(kX86InstJmp , "jmp" , G(Jmp) , F(Jump) , 0 , 0 , 0, 0 , 0), INST(kX86InstLdDQU , "lddqu" , G(MmuRmI) , F(None) , O(Xmm) , O(Mem) , 0, 0xF2000FF0, 0), INST(kX86InstLdMXCSR , "ldmxcsr" , G(Mem) , F(None) , O(Mem) , 0 , 2, 0x00000FAE, 0), INST(kX86InstLahf , "lahf" , G(Emit) , F(Special) , 0 , 0 , 0, 0x0000009F, 0), INST(kX86InstLea , "lea" , G(Lea) , F(None) , O(Gqd) , O(Mem) , 0, 0 , 0), INST(kX86InstLeave , "leave" , G(Emit) , F(Special) , 0 , 0 , 0, 0x000000C9, 0), INST(kX86InstLFence , "lfence" , G(Emit) , F(None) , 0 , 0 , 0, 0x000FAEE8, 0), INST(kX86InstMaskMovDQU , "maskmovdqu" , G(MmuRmI) , F(Special) , O(Xmm) , O(Xmm) , 0, 0x66000F57, 0), INST(kX86InstMaskMovQ , "maskmovq" , G(MmuRmI) , F(Special) , O(Mm) , O(Mm) , 0, 0x00000FF7, 0), INST(kX86InstMaxPD , "maxpd" , G(MmuRmI) , F(None) , O(Xmm) , O(XmmMem) , 0, 0x66000F5F, 0), INST(kX86InstMaxPS , "maxps" , G(MmuRmI) , F(None) , O(Xmm) , O(XmmMem) , 0, 0x00000F5F, 0), INST(kX86InstMaxSD , "maxsd" , G(MmuRmI) , F(None) , O(Xmm) , O(XmmMem) , 0, 0xF2000F5F, 0), INST(kX86InstMaxSS , "maxss" , G(MmuRmI) , F(None) , O(Xmm) , O(XmmMem) , 0, 0xF3000F5F, 0), INST(kX86InstMFence , "mfence" , G(Emit) , F(None) , 0 , 0 , 0, 0x000FAEF0, 0), INST(kX86InstMinPD , "minpd" , G(MmuRmI) , F(None) , O(Xmm) , O(XmmMem) , 0, 0x66000F5D, 0), INST(kX86InstMinPS , "minps" , G(MmuRmI) , F(None) , O(Xmm) , O(XmmMem) , 0, 0x00000F5D, 0), INST(kX86InstMinSD , "minsd" , G(MmuRmI) , F(None) , O(Xmm) , O(XmmMem) , 0, 0xF2000F5D, 0), INST(kX86InstMinSS , "minss" , G(MmuRmI) , F(None) , O(Xmm) , O(XmmMem) , 0, 0xF3000F5D, 0), INST(kX86InstMonitor , "monitor" , G(Emit) , F(Special) , 0 , 0 , 0, 0x000F01C8, 0), INST(kX86InstMov , "mov" , G(Mov) , F(Mov) , O(GqdwbMem) , O(GqdwbMem)|O(Imm) , 0, 0 , 0), INST(kX86InstMovAPD , "movapd" , G(MmuMov) , F(Mov) , O(XmmMem) , O(XmmMem) , 0, 0x66000F28, 0x66000F29), INST(kX86InstMovAPS , "movaps" , G(MmuMov) , F(Mov) , O(XmmMem) , O(XmmMem) , 0, 0x00000F28, 0x00000F29), INST(kX86InstMovBE , "movbe" , G(MovBE) , F(Mov) , O(Gqdw)|O(Mem) , O(Gqdw)|O(Mem) , 0, 0x000F38F0, 0x000F38F1), INST(kX86InstMovD , "movd" , G(MmuMovD) , F(Mov) , O(Gd)|O(MmXmmMem) , O(Gd)|O(MmXmmMem) , 0, 0 , 0), INST(kX86InstMovDDup , "movddup" , G(MmuMov) , F(Mov) , O(Xmm) , O(XmmMem) , 0, 0xF2000F12, 0), INST(kX86InstMovDQ2Q , "movdq2q" , G(MmuMov) , F(Mov) , O(Mm) , O(Xmm) , 0, 0xF2000FD6, 0), INST(kX86InstMovDQA , "movdqa" , G(MmuMov) , F(Mov) , O(XmmMem) , O(XmmMem) , 0, 0x66000F6F, 0x66000F7F), INST(kX86InstMovDQU , "movdqu" , G(MmuMov) , F(Mov) , O(XmmMem) , O(XmmMem) , 0, 0xF3000F6F, 0xF3000F7F), INST(kX86InstMovHLPS , "movhlps" , G(MmuMov) , F(None) , O(Xmm) , O(Xmm) , 0, 0x00000F12, 0), INST(kX86InstMovHPD , "movhpd" , G(MmuMov) , F(None) , O(XmmMem) , O(XmmMem) , 0, 0x66000F16, 0x66000F17), INST(kX86InstMovHPS , "movhps" , G(MmuMov) , F(None) , O(XmmMem) , O(XmmMem) , 0, 0x00000F16, 0x00000F17), INST(kX86InstMovLHPS , "movlhps" , G(MmuMov) , F(None) , O(Xmm) , O(Xmm) , 0, 0x00000F16, 0), INST(kX86InstMovLPD , "movlpd" , G(MmuMov) , F(None) , O(XmmMem) , O(XmmMem) , 0, 0x66000F12, 0x66000F13), INST(kX86InstMovLPS , "movlps" , G(MmuMov) , F(None) , O(XmmMem) , O(XmmMem) , 0, 0x00000F12, 0x00000F13), INST(kX86InstMovMskPD , "movmskpd" , G(MmuMov) , F(Mov) , O(Gqd)|O(NoRex) , O(Xmm) , 0, 0x66000F50, 0), INST(kX86InstMovMskPS , "movmskps" , G(MmuMov) , F(Mov) , O(Gqd)|O(NoRex) , O(Xmm) , 0, 0x00000F50, 0), INST(kX86InstMovNTDQ , "movntdq" , G(MmuMov) , F(None) , O(Mem) , O(Xmm) , 0, 0 , 0x66000FE7), INST(kX86InstMovNTDQA , "movntdqa" , G(MmuMov) , F(Mov) , O(Xmm) , O(Mem) , 0, 0x660F382A, 0), INST(kX86InstMovNTI , "movnti" , G(MmuMov) , F(Mov) , O(Mem) , O(Gqd) , 0, 0 , 0x00000FC3), INST(kX86InstMovNTPD , "movntpd" , G(MmuMov) , F(None) , O(Mem) , O(Xmm) , 0, 0 , 0x66000F2B), INST(kX86InstMovNTPS , "movntps" , G(MmuMov) , F(None) , O(Mem) , O(Xmm) , 0, 0 , 0x00000F2B), INST(kX86InstMovNTQ , "movntq" , G(MmuMov) , F(None) , O(Mem) , O(Mm) , 0, 0 , 0x00000FE7), INST(kX86InstMovQ , "movq" , G(MmuMovQ) , F(Mov) , O(Gq)|O(MmXmmMem) , O(Gq)|O(MmXmmMem) , 0, 0 , 0), INST(kX86InstMovQ2DQ , "movq2dq" , G(MmuRmI) , F(Mov) , O(Xmm) , O(Mm) , 0, 0xF3000FD6, 0), INST(kX86InstMovSD , "movsd" , G(MmuMov) , F(None) , O(XmmMem) , O(XmmMem) , 0, 0xF2000F10, 0xF2000F11), INST(kX86InstMovSHDup , "movshdup" , G(MmuRmI) , F(Mov) , O(Xmm) , O(XmmMem) , 0, 0xF3000F16, 0), INST(kX86InstMovSLDup , "movsldup" , G(MmuRmI) , F(Mov) , O(Xmm) , O(XmmMem) , 0, 0xF3000F12, 0), INST(kX86InstMovSS , "movss" , G(MmuMov) , F(None) , O(XmmMem) , O(XmmMem) , 0, 0xF3000F10, 0xF3000F11), INST(kX86InstMovSX , "movsx" , G(MovSxMovZx) , F(None) , O(Gqdw) , O(GwbMem) , 0, 0x00000FBE, 0), INST(kX86InstMovSXD , "movsxd" , G(MovSxD) , F(None) , O(Gq) , O(GdMem) , 0, 0 , 0), INST(kX86InstMovUPD , "movupd" , G(MmuMov) , F(Mov) , O(XmmMem) , O(XmmMem) , 0, 0x66000F10, 0x66000F11), INST(kX86InstMovUPS , "movups" , G(MmuMov) , F(Mov) , O(XmmMem) , O(XmmMem) , 0, 0x00000F10, 0x00000F11), INST(kX86InstMovZX , "movzx" , G(MovSxMovZx) , F(Mov) , O(Gqdw) , O(GwbMem) , 0, 0x00000FB6, 0), INST(kX86InstMovPtr , "mov_ptr" , G(MovPtr) , F(Mov)|F(Special), O(Gqdwb) , O(Imm) , 0, 0 , 0), INST(kX86InstMPSADBW , "mpsadbw" , G(MmuRmImm8) , F(None) , O(Xmm) , O(XmmMem) , 0, 0x660F3A42, 0), INST(kX86InstMul , "mul" , G(Rm) , F(Special) , 0 , 0 , 4, 0x000000F6, 0), INST(kX86InstMulPD , "mulpd" , G(MmuRmI) , F(None) , O(Xmm) , O(XmmMem) , 0, 0x66000F59, 0), INST(kX86InstMulPS , "mulps" , G(MmuRmI) , F(None) , O(Xmm) , O(XmmMem) , 0, 0x00000F59, 0), INST(kX86InstMulSD , "mulsd" , G(MmuRmI) , F(None) , O(Xmm) , O(XmmMem) , 0, 0xF2000F59, 0), INST(kX86InstMulSS , "mulss" , G(MmuRmI) , F(None) , O(Xmm) , O(XmmMem) , 0, 0xF3000F59, 0), INST(kX86InstMWait , "mwait" , G(Emit) , F(Special) , 0 , 0 , 0, 0x000F01C9, 0), INST(kX86InstNeg , "neg" , G(Rm) , F(Lockable) , O(GqdwbMem) , 0 , 3, 0x000000F6, 0), INST(kX86InstNop , "nop" , G(Emit) , F(None) , 0 , 0 , 0, 0x00000090, 0), INST(kX86InstNot , "not" , G(Rm) , F(Lockable) , O(GqdwbMem) , 0 , 2, 0x000000F6, 0), INST(kX86InstOr , "or" , G(Arith) , F(Lockable) , O(GqdwbMem) , O(GqdwbMem)|O(Imm) , 1, 0x00000008, 0x00000080), INST(kX86InstOrPD , "orpd" , G(MmuRmI) , F(None) , O(Xmm) , O(XmmMem) , 0, 0x66000F56, 0), INST(kX86InstOrPS , "orps" , G(MmuRmI) , F(None) , O(Xmm) , O(XmmMem) , 0, 0x00000F56, 0), INST(kX86InstPAbsB , "pabsb" , G(MmuRmI) , F(None) , O(MmXmm) , O(MmXmmMem) , 0, 0x000F381C, 0), INST(kX86InstPAbsD , "pabsd" , G(MmuRmI) , F(None) , O(MmXmm) , O(MmXmmMem) , 0, 0x000F381E, 0), INST(kX86InstPAbsW , "pabsw" , G(MmuRmI) , F(None) , O(MmXmm) , O(MmXmmMem) , 0, 0x000F381D, 0), INST(kX86InstPackSSDW , "packssdw" , G(MmuRmI) , F(None) , O(MmXmm) , O(MmXmmMem) , 0, 0x00000F6B, 0), INST(kX86InstPackSSWB , "packsswb" , G(MmuRmI) , F(None) , O(MmXmm) , O(MmXmmMem) , 0, 0x00000F63, 0), INST(kX86InstPackUSDW , "packusdw" , G(MmuRmI) , F(None) , O(Xmm) , O(XmmMem) , 0, 0x660F382B, 0), INST(kX86InstPackUSWB , "packuswb" , G(MmuRmI) , F(None) , O(MmXmm) , O(MmXmmMem) , 0, 0x00000F67, 0), INST(kX86InstPAddB , "paddb" , G(MmuRmI) , F(None) , O(MmXmm) , O(MmXmmMem) , 0, 0x00000FFC, 0), INST(kX86InstPAddD , "paddd" , G(MmuRmI) , F(None) , O(MmXmm) , O(MmXmmMem) , 0, 0x00000FFE, 0), INST(kX86InstPAddQ , "paddq" , G(MmuRmI) , F(None) , O(MmXmm) , O(MmXmmMem) , 0, 0x00000FD4, 0), INST(kX86InstPAddSB , "paddsb" , G(MmuRmI) , F(None) , O(MmXmm) , O(MmXmmMem) , 0, 0x00000FEC, 0), INST(kX86InstPAddSW , "paddsw" , G(MmuRmI) , F(None) , O(MmXmm) , O(MmXmmMem) , 0, 0x00000FED, 0), INST(kX86InstPAddUSB , "paddusb" , G(MmuRmI) , F(None) , O(MmXmm) , O(MmXmmMem) , 0, 0x00000FDC, 0), INST(kX86InstPAddUSW , "paddusw" , G(MmuRmI) , F(None) , O(MmXmm) , O(MmXmmMem) , 0, 0x00000FDD, 0), INST(kX86InstPAddW , "paddw" , G(MmuRmI) , F(None) , O(MmXmm) , O(MmXmmMem) , 0, 0x00000FFD, 0), INST(kX86InstPAlignR , "palignr" , G(MmuRmImm8) , F(None) , O(MmXmm) , O(MmXmmMem) , 0, 0x000F3A0F, 0), INST(kX86InstPAnd , "pand" , G(MmuRmI) , F(None) , O(MmXmm) , O(MmXmmMem) , 0, 0x00000FDB, 0), INST(kX86InstPAndN , "pandn" , G(MmuRmI) , F(None) , O(MmXmm) , O(MmXmmMem) , 0, 0x00000FDF, 0), INST(kX86InstPause , "pause" , G(Emit) , F(None) , 0 , 0 , 0, 0xF3000090, 0), INST(kX86InstPAvgB , "pavgb" , G(MmuRmI) , F(None) , O(MmXmm) , O(MmXmmMem) , 0, 0x00000FE0, 0), INST(kX86InstPAvgW , "pavgw" , G(MmuRmI) , F(None) , O(MmXmm) , O(MmXmmMem) , 0, 0x00000FE3, 0), INST(kX86InstPBlendVB , "pblendvb" , G(MmuRmI) , F(None) , O(Xmm) , O(XmmMem) , 0, 0x660F3810, 0), INST(kX86InstPBlendW , "pblendw" , G(MmuRmImm8) , F(None) , O(Xmm) , O(XmmMem) , 0, 0x660F3A0E, 0), INST(kX86InstPCmpEqB , "pcmpeqb" , G(MmuRmI) , F(None) , O(MmXmm) , O(MmXmmMem) , 0, 0x00000F74, 0), INST(kX86InstPCmpEqD , "pcmpeqd" , G(MmuRmI) , F(None) , O(MmXmm) , O(MmXmmMem) , 0, 0x00000F76, 0), INST(kX86InstPCmpEqQ , "pcmpeqq" , G(MmuRmI) , F(None) , O(Xmm) , O(XmmMem) , 0, 0x660F3829, 0), INST(kX86InstPCmpEqW , "pcmpeqw" , G(MmuRmI) , F(None) , O(MmXmm) , O(MmXmmMem) , 0, 0x00000F75, 0), INST(kX86InstPCmpEStrI , "pcmpestri" , G(MmuRmImm8) , F(None) , O(Xmm) , O(XmmMem) , 0, 0x660F3A61, 0), INST(kX86InstPCmpEStrM , "pcmpestrm" , G(MmuRmImm8) , F(None) , O(Xmm) , O(XmmMem) , 0, 0x660F3A60, 0), INST(kX86InstPCmpGtB , "pcmpgtb" , G(MmuRmI) , F(None) , O(MmXmm) , O(MmXmmMem) , 0, 0x00000F64, 0), INST(kX86InstPCmpGtD , "pcmpgtd" , G(MmuRmI) , F(None) , O(MmXmm) , O(MmXmmMem) , 0, 0x00000F66, 0), INST(kX86InstPCmpGtQ , "pcmpgtq" , G(MmuRmI) , F(None) , O(Xmm) , O(XmmMem) , 0, 0x660F3837, 0), INST(kX86InstPCmpGtW , "pcmpgtw" , G(MmuRmI) , F(None) , O(MmXmm) , O(MmXmmMem) , 0, 0x00000F65, 0), INST(kX86InstPCmpIStrI , "pcmpistri" , G(MmuRmImm8) , F(None) , O(Xmm) , O(XmmMem) , 0, 0x660F3A63, 0), INST(kX86InstPCmpIStrM , "pcmpistrm" , G(MmuRmImm8) , F(None) , O(Xmm) , O(XmmMem) , 0, 0x660F3A62, 0), INST(kX86InstPExtrB , "pextrb" , G(MmuExtract) , F(None) , O(Gd)|O(Gb)|O(Mem) , O(Xmm) , 0, 0x000F3A14, 0), INST(kX86InstPExtrD , "pextrd" , G(MmuExtract) , F(None) , O(Gd) |O(Mem) , O(Xmm) , 0, 0x000F3A16, 0), INST(kX86InstPExtrQ , "pextrq" , G(MmuExtract) , F(None) , O(Gqd) |O(Mem) , O(Xmm) , 1, 0x000F3A16, 0), INST(kX86InstPExtrW , "pextrw" , G(MmuExtract) , F(None) , O(Gd) |O(Mem) , O(MmXmm) , 0, 0x000F3A15, 0), INST(kX86InstPF2ID , "pf2id" , G(MmuRm3dNow) , F(None) , O(Mm) , O(MmMem) , 0, 0x00000F0F, 0x1D), INST(kX86InstPF2IW , "pf2iw" , G(MmuRm3dNow) , F(None) , O(Mm) , O(MmMem) , 0, 0x00000F0F, 0x1C), INST(kX86InstPFAcc , "pfacc" , G(MmuRm3dNow) , F(None) , O(Mm) , O(MmMem) , 0, 0x00000F0F, 0xAE), INST(kX86InstPFAdd , "pfadd" , G(MmuRm3dNow) , F(None) , O(Mm) , O(MmMem) , 0, 0x00000F0F, 0x9E), INST(kX86InstPFCmpEQ , "pfcmpeq" , G(MmuRm3dNow) , F(None) , O(Mm) , O(MmMem) , 0, 0x00000F0F, 0xB0), INST(kX86InstPFCmpGE , "pfcmpge" , G(MmuRm3dNow) , F(None) , O(Mm) , O(MmMem) , 0, 0x00000F0F, 0x90), INST(kX86InstPFCmpGT , "pfcmpgt" , G(MmuRm3dNow) , F(None) , O(Mm) , O(MmMem) , 0, 0x00000F0F, 0xA0), INST(kX86InstPFMax , "pfmax" , G(MmuRm3dNow) , F(None) , O(Mm) , O(MmMem) , 0, 0x00000F0F, 0xA4), INST(kX86InstPFMin , "pfmin" , G(MmuRm3dNow) , F(None) , O(Mm) , O(MmMem) , 0, 0x00000F0F, 0x94), INST(kX86InstPFMul , "pfmul" , G(MmuRm3dNow) , F(None) , O(Mm) , O(MmMem) , 0, 0x00000F0F, 0xB4), INST(kX86InstPFNAcc , "pfnacc" , G(MmuRm3dNow) , F(None) , O(Mm) , O(MmMem) , 0, 0x00000F0F, 0x8A), INST(kX86InstPFPNAcc , "pfpnacc" , G(MmuRm3dNow) , F(None) , O(Mm) , O(MmMem) , 0, 0x00000F0F, 0x8E), INST(kX86InstPFRcp , "pfrcp" , G(MmuRm3dNow) , F(None) , O(Mm) , O(MmMem) , 0, 0x00000F0F, 0x96), INST(kX86InstPFRcpIt1 , "pfrcpit1" , G(MmuRm3dNow) , F(None) , O(Mm) , O(MmMem) , 0, 0x00000F0F, 0xA6), INST(kX86InstPFRcpIt2 , "pfrcpit2" , G(MmuRm3dNow) , F(None) , O(Mm) , O(MmMem) , 0, 0x00000F0F, 0xB6), INST(kX86InstPFRSqIt1 , "pfrsqit1" , G(MmuRm3dNow) , F(None) , O(Mm) , O(MmMem) , 0, 0x00000F0F, 0xA7), INST(kX86InstPFRSqrt , "pfrsqrt" , G(MmuRm3dNow) , F(None) , O(Mm) , O(MmMem) , 0, 0x00000F0F, 0x97), INST(kX86InstPFSub , "pfsub" , G(MmuRm3dNow) , F(None) , O(Mm) , O(MmMem) , 0, 0x00000F0F, 0x9A), INST(kX86InstPFSubR , "pfsubr" , G(MmuRm3dNow) , F(None) , O(Mm) , O(MmMem) , 0, 0x00000F0F, 0xAA), INST(kX86InstPHAddD , "phaddd" , G(MmuRmI) , F(None) , O(MmXmm) , O(MmXmmMem) , 0, 0x000F3802, 0), INST(kX86InstPHAddSW , "phaddsw" , G(MmuRmI) , F(None) , O(MmXmm) , O(MmXmmMem) , 0, 0x000F3803, 0), INST(kX86InstPHAddW , "phaddw" , G(MmuRmI) , F(None) , O(MmXmm) , O(MmXmmMem) , 0, 0x000F3801, 0), INST(kX86InstPHMinPOSUW , "phminposuw" , G(MmuRmI) , F(None) , O(Xmm) , O(XmmMem) , 0, 0x660F3841, 0), INST(kX86InstPHSubD , "phsubd" , G(MmuRmI) , F(None) , O(MmXmm) , O(MmXmmMem) , 0, 0x000F3806, 0), INST(kX86InstPHSubSW , "phsubsw" , G(MmuRmI) , F(None) , O(MmXmm) , O(MmXmmMem) , 0, 0x000F3807, 0), INST(kX86InstPHSubW , "phsubw" , G(MmuRmI) , F(None) , O(MmXmm) , O(MmXmmMem) , 0, 0x000F3805, 0), INST(kX86InstPI2FD , "pi2fd" , G(MmuRm3dNow) , F(None) , O(Mm) , O(MmMem) , 0, 0x00000F0F, 0x0D), INST(kX86InstPI2FW , "pi2fw" , G(MmuRm3dNow) , F(None) , O(Mm) , O(MmMem) , 0, 0x00000F0F, 0x0C), INST(kX86InstPInsRB , "pinsrb" , G(MmuRmImm8) , F(None) , O(Xmm) , O(Gd) | O(Mem) , 0, 0x660F3A20, 0), INST(kX86InstPInsRD , "pinsrd" , G(MmuRmImm8) , F(None) , O(Xmm) , O(Gd) | O(Mem) , 0, 0x660F3A22, 0), INST(kX86InstPInsRQ , "pinsrq" , G(MmuRmImm8) , F(None) , O(Xmm) , O(Gq) | O(Mem) , 0, 0x660F3A22, 0), INST(kX86InstPInsRW , "pinsrw" , G(MmuRmImm8) , F(None) , O(MmXmm) , O(Gd) | O(Mem) , 0, 0x00000FC4, 0), INST(kX86InstPMAddUBSW , "pmaddubsw" , G(MmuRmI) , F(None) , O(MmXmm) , O(MmXmmMem) , 0, 0x000F3804, 0), INST(kX86InstPMAddWD , "pmaddwd" , G(MmuRmI) , F(None) , O(MmXmm) , O(MmXmmMem) , 0, 0x00000FF5, 0), INST(kX86InstPMaxSB , "pmaxsb" , G(MmuRmI) , F(None) , O(Xmm) , O(XmmMem) , 0, 0x660F383C, 0), INST(kX86InstPMaxSD , "pmaxsd" , G(MmuRmI) , F(None) , O(Xmm) , O(XmmMem) , 0, 0x660F383D, 0), INST(kX86InstPMaxSW , "pmaxsw" , G(MmuRmI) , F(None) , O(MmXmm) , O(MmXmmMem) , 0, 0x00000FEE, 0), INST(kX86InstPMaxUB , "pmaxub" , G(MmuRmI) , F(None) , O(MmXmm) , O(MmXmmMem) , 0, 0x00000FDE, 0), INST(kX86InstPMaxUD , "pmaxud" , G(MmuRmI) , F(None) , O(Xmm) , O(XmmMem) , 0, 0x660F383F, 0), INST(kX86InstPMaxUW , "pmaxuw" , G(MmuRmI) , F(None) , O(Xmm) , O(XmmMem) , 0, 0x660F383E, 0), INST(kX86InstPMinSB , "pminsb" , G(MmuRmI) , F(None) , O(Xmm) , O(XmmMem) , 0, 0x660F3838, 0), INST(kX86InstPMinSD , "pminsd" , G(MmuRmI) , F(None) , O(Xmm) , O(XmmMem) , 0, 0x660F3839, 0), INST(kX86InstPMinSW , "pminsw" , G(MmuRmI) , F(None) , O(MmXmm) , O(MmXmmMem) , 0, 0x00000FEA, 0), INST(kX86InstPMinUB , "pminub" , G(MmuRmI) , F(None) , O(MmXmm) , O(MmXmmMem) , 0, 0x00000FDA, 0), INST(kX86InstPMinUD , "pminud" , G(MmuRmI) , F(None) , O(Xmm) , O(XmmMem) , 0, 0x660F383B, 0), INST(kX86InstPMinUW , "pminuw" , G(MmuRmI) , F(None) , O(Xmm) , O(XmmMem) , 0, 0x660F383A, 0), INST(kX86InstPMovMskB , "pmovmskb" , G(MmuRmI) , F(Mov) , O(Gqd) , O(MmXmm) , 0, 0x00000FD7, 0), INST(kX86InstPMovSXBD , "pmovsxbd" , G(MmuRmI) , F(Mov) , O(Xmm) , O(XmmMem) , 0, 0x660F3821, 0), INST(kX86InstPMovSXBQ , "pmovsxbq" , G(MmuRmI) , F(Mov) , O(Xmm) , O(XmmMem) , 0, 0x660F3822, 0), INST(kX86InstPMovSXBW , "pmovsxbw" , G(MmuRmI) , F(Mov) , O(Xmm) , O(XmmMem) , 0, 0x660F3820, 0), INST(kX86InstPMovSXDQ , "pmovsxdq" , G(MmuRmI) , F(Mov) , O(Xmm) , O(XmmMem) , 0, 0x660F3825, 0), INST(kX86InstPMovSXWD , "pmovsxwd" , G(MmuRmI) , F(Mov) , O(Xmm) , O(XmmMem) , 0, 0x660F3823, 0), INST(kX86InstPMovSXWQ , "pmovsxwq" , G(MmuRmI) , F(Mov) , O(Xmm) , O(XmmMem) , 0, 0x660F3824, 0), INST(kX86InstPMovZXBD , "pmovzxbd" , G(MmuRmI) , F(Mov) , O(Xmm) , O(XmmMem) , 0, 0x660F3831, 0), INST(kX86InstPMovZXBQ , "pmovzxbq" , G(MmuRmI) , F(Mov) , O(Xmm) , O(XmmMem) , 0, 0x660F3832, 0), INST(kX86InstPMovZXBW , "pmovzxbw" , G(MmuRmI) , F(Mov) , O(Xmm) , O(XmmMem) , 0, 0x660F3830, 0), INST(kX86InstPMovZXDQ , "pmovzxdq" , G(MmuRmI) , F(Mov) , O(Xmm) , O(XmmMem) , 0, 0x660F3835, 0), INST(kX86InstPMovZXWD , "pmovzxwd" , G(MmuRmI) , F(Mov) , O(Xmm) , O(XmmMem) , 0, 0x660F3833, 0), INST(kX86InstPMovZXWQ , "pmovzxwq" , G(MmuRmI) , F(Mov) , O(Xmm) , O(XmmMem) , 0, 0x660F3834, 0), INST(kX86InstPMulDQ , "pmuldq" , G(MmuRmI) , F(None) , O(Xmm) , O(XmmMem) , 0, 0x660F3828, 0), INST(kX86InstPMulHRSW , "pmulhrsw" , G(MmuRmI) , F(None) , O(MmXmm) , O(MmXmmMem) , 0, 0x000F380B, 0), INST(kX86InstPMulHUW , "pmulhuw" , G(MmuRmI) , F(None) , O(MmXmm) , O(MmXmmMem) , 0, 0x00000FE4, 0), INST(kX86InstPMulHW , "pmulhw" , G(MmuRmI) , F(None) , O(MmXmm) , O(MmXmmMem) , 0, 0x00000FE5, 0), INST(kX86InstPMulLD , "pmulld" , G(MmuRmI) , F(None) , O(Xmm) , O(XmmMem) , 0, 0x660F3840, 0), INST(kX86InstPMulLW , "pmullw" , G(MmuRmI) , F(None) , O(MmXmm) , O(MmXmmMem) , 0, 0x00000FD5, 0), INST(kX86InstPMulUDQ , "pmuludq" , G(MmuRmI) , F(None) , O(MmXmm) , O(MmXmmMem) , 0, 0x00000FF4, 0), INST(kX86InstPop , "pop" , G(Pop) , F(Special) , 0 , 0 , 0, 0x00000058, 0x0000008F), INST(kX86InstPopAD , "popad" , G(Emit) , F(Special) , 0 , 0 , 0, 0x00000061, 0), INST(kX86InstPopCnt , "popcnt" , G(RegRm) , F(None) , O(Gqdw) , O(GqdwMem) , 0, 0xF3000FB8, 0), INST(kX86InstPopFD , "popfd" , G(Emit) , F(Special) , 0 , 0 , 0, 0x0000009D, 0), INST(kX86InstPopFQ , "popfq" , G(Emit) , F(Special) , 0 , 0 , 0, 0x0000009D, 0), INST(kX86InstPOr , "por" , G(MmuRmI) , F(None) , O(MmXmm) , O(MmXmmMem) , 0, 0x00000FEB, 0), INST(kX86InstPrefetch , "prefetch" , G(MmuPrefetch) , F(None) , O(Mem) , O(Imm) , 0, 0 , 0), INST(kX86InstPSADBW , "psadbw" , G(MmuRmI) , F(None) , O(MmXmm) , O(MmXmmMem) , 0, 0x00000FF6, 0), INST(kX86InstPShufB , "pshufb" , G(MmuRmI) , F(Mov) , O(MmXmm) , O(MmXmmMem) , 0, 0x000F3800, 0), INST(kX86InstPShufD , "pshufd" , G(MmuRmImm8) , F(Mov) , O(Xmm) , O(XmmMem) , 0, 0x66000F70, 0), INST(kX86InstPShufW , "pshufw" , G(MmuRmImm8) , F(Mov) , O(MmXmm) , O(MmXmmMem) , 0, 0x00000F70, 0), INST(kX86InstPShufHW , "pshufhw" , G(MmuRmImm8) , F(Mov) , O(Xmm) , O(XmmMem) , 0, 0xF3000F70, 0), INST(kX86InstPShufLW , "pshuflw" , G(MmuRmImm8) , F(Mov) , O(Xmm) , O(XmmMem) , 0, 0xF2000F70, 0), INST(kX86InstPSignB , "psignb" , G(MmuRmI) , F(None) , O(MmXmm) , O(MmXmmMem) , 0, 0x000F3808, 0), INST(kX86InstPSignD , "psignd" , G(MmuRmI) , F(None) , O(MmXmm) , O(MmXmmMem) , 0, 0x000F380A, 0), INST(kX86InstPSignW , "psignw" , G(MmuRmI) , F(None) , O(MmXmm) , O(MmXmmMem) , 0, 0x000F3809, 0), INST(kX86InstPSllD , "pslld" , G(MmuRmI) , F(None) , O(MmXmm) , O(MmXmmMem)|O(Imm) , 6, 0x00000FF2, 0x00000F72), INST(kX86InstPSllDQ , "pslldq" , G(MmuRmI) , F(None) , O(Xmm) , O(Imm) , 7, 0 , 0x66000F73), INST(kX86InstPSllQ , "psllq" , G(MmuRmI) , F(None) , O(MmXmm) , O(MmXmmMem)|O(Imm) , 6, 0x00000FF3, 0x00000F73), INST(kX86InstPSllW , "psllw" , G(MmuRmI) , F(None) , O(MmXmm) , O(MmXmmMem)|O(Imm) , 6, 0x00000FF1, 0x00000F71), INST(kX86InstPSraD , "psrad" , G(MmuRmI) , F(None) , O(MmXmm) , O(MmXmmMem)|O(Imm) , 4, 0x00000FE2, 0x00000F72), INST(kX86InstPSraW , "psraw" , G(MmuRmI) , F(None) , O(MmXmm) , O(MmXmmMem)|O(Imm) , 4, 0x00000FE1, 0x00000F71), INST(kX86InstPSrlD , "psrld" , G(MmuRmI) , F(None) , O(MmXmm) , O(MmXmmMem)|O(Imm) , 2, 0x00000FD2, 0x00000F72), INST(kX86InstPSrlDQ , "psrldq" , G(MmuRmI) , F(None) , O(Xmm) , O(Imm) , 3, 0 , 0x66000F73), INST(kX86InstPSrlQ , "psrlq" , G(MmuRmI) , F(None) , O(MmXmm) , O(MmXmmMem)|O(Imm) , 2, 0x00000FD3, 0x00000F73), INST(kX86InstPSrlW , "psrlw" , G(MmuRmI) , F(None) , O(MmXmm) , O(MmXmmMem)|O(Imm) , 2, 0x00000FD1, 0x00000F71), INST(kX86InstPSubB , "psubb" , G(MmuRmI) , F(None) , O(MmXmm) , O(MmXmmMem) , 0, 0x00000FF8, 0), INST(kX86InstPSubD , "psubd" , G(MmuRmI) , F(None) , O(MmXmm) , O(MmXmmMem) , 0, 0x00000FFA, 0), INST(kX86InstPSubQ , "psubq" , G(MmuRmI) , F(None) , O(MmXmm) , O(MmXmmMem) , 0, 0x00000FFB, 0), INST(kX86InstPSubSB , "psubsb" , G(MmuRmI) , F(None) , O(MmXmm) , O(MmXmmMem) , 0, 0x00000FE8, 0), INST(kX86InstPSubSW , "psubsw" , G(MmuRmI) , F(None) , O(MmXmm) , O(MmXmmMem) , 0, 0x00000FE9, 0), INST(kX86InstPSubUSB , "psubusb" , G(MmuRmI) , F(None) , O(MmXmm) , O(MmXmmMem) , 0, 0x00000FD8, 0), INST(kX86InstPSubUSW , "psubusw" , G(MmuRmI) , F(None) , O(MmXmm) , O(MmXmmMem) , 0, 0x00000FD9, 0), INST(kX86InstPSubW , "psubw" , G(MmuRmI) , F(None) , O(MmXmm) , O(MmXmmMem) , 0, 0x00000FF9, 0), INST(kX86InstPSwapD , "pswapd" , G(MmuRm3dNow) , F(None) , O(Mm) , O(MmMem) , 0, 0x00000F0F, 0xBB), INST(kX86InstPTest , "ptest" , G(MmuRmI) , F(None) , O(Xmm) , O(XmmMem) , 0, 0x660F3817, 0), INST(kX86InstPunpckHBW , "punpckhbw" , G(MmuRmI) , F(None) , O(MmXmm) , O(MmXmmMem) , 0, 0x00000F68, 0), INST(kX86InstPunpckHDQ , "punpckhdq" , G(MmuRmI) , F(None) , O(MmXmm) , O(MmXmmMem) , 0, 0x00000F6A, 0), INST(kX86InstPunpckHQDQ , "punpckhqdq" , G(MmuRmI) , F(None) , O(Xmm) , O(XmmMem) , 0, 0x66000F6D, 0), INST(kX86InstPunpckHWD , "punpckhwd" , G(MmuRmI) , F(None) , O(MmXmm) , O(MmXmmMem) , 0, 0x00000F69, 0), INST(kX86InstPunpckLBW , "punpcklbw" , G(MmuRmI) , F(None) , O(MmXmm) , O(MmXmmMem) , 0, 0x00000F60, 0), INST(kX86InstPunpckLDQ , "punpckldq" , G(MmuRmI) , F(None) , O(MmXmm) , O(MmXmmMem) , 0, 0x00000F62, 0), INST(kX86InstPunpckLQDQ , "punpcklqdq" , G(MmuRmI) , F(None) , O(Xmm) , O(XmmMem) , 0, 0x66000F6C, 0), INST(kX86InstPunpckLWD , "punpcklwd" , G(MmuRmI) , F(None) , O(MmXmm) , O(MmXmmMem) , 0, 0x00000F61, 0), INST(kX86InstPush , "push" , G(Push) , F(Special) , 0 , 0 , 6, 0x00000050, 0x000000FF), INST(kX86InstPushAD , "pushad" , G(Emit) , F(Special) , 0 , 0 , 0, 0x00000060, 0), INST(kX86InstPushFD , "pushfd" , G(Emit) , F(Special) , 0 , 0 , 0, 0x0000009C, 0), INST(kX86InstPushFQ , "pushfq" , G(Emit) , F(Special) , 0 , 0 , 0, 0x0000009C, 0), INST(kX86InstPXor , "pxor" , G(MmuRmI) , F(None) , O(MmXmm) , O(MmXmmMem) , 0, 0x00000FEF, 0), INST(kX86InstRcl , "rcl" , G(Rot) , F(Special) , O(GqdwbMem) , O(Gb)|O(Imm) , 2, 0 , 0), INST(kX86InstRcpPS , "rcpps" , G(MmuRmI) , F(Mov) , O(Xmm) , O(XmmMem) , 0, 0x00000F53, 0), INST(kX86InstRcpSS , "rcpss" , G(MmuRmI) , F(Mov) , O(Xmm) , O(XmmMem) , 0, 0xF3000F53, 0), INST(kX86InstRcr , "rcr" , G(Rot) , F(Special) , O(GqdwbMem) , O(Gb)|O(Imm) , 3, 0 , 0), INST(kX86InstRdtsc , "rdtsc" , G(Emit) , F(Special) , 0 , 0 , 0, 0x00000F31, 0), INST(kX86InstRdtscP , "rdtscp" , G(Emit) , F(Special) , 0 , 0 , 0, 0x000F01F9, 0), INST(kX86InstRepLodSB , "rep lodsb" , G(Rep) , F(Special) , O(Mem) , 0 , 0, 0xF30000AC, 1 /* Size of mem */), INST(kX86InstRepLodSD , "rep lodsd" , G(Rep) , F(Special) , O(Mem) , 0 , 0, 0xF30000AC, 4 /* Size of mem */), INST(kX86InstRepLodSQ , "rep lodsq" , G(Rep) , F(Special) , O(Mem) , 0 , 0, 0xF30000AC, 8 /* Size of mem */), INST(kX86InstRepLodSW , "rep lodsw" , G(Rep) , F(Special) , O(Mem) , 0 , 0, 0xF30000AC, 2 /* Size of mem */), INST(kX86InstRepMovSB , "rep movsb" , G(Rep) , F(Special) , O(Mem) , O(Mem) , 0, 0xF30000A4, 1 /* Size of mem */), INST(kX86InstRepMovSD , "rep movsd" , G(Rep) , F(Special) , O(Mem) , O(Mem) , 0, 0xF30000A4, 4 /* Size of mem */), INST(kX86InstRepMovSQ , "rep movsq" , G(Rep) , F(Special) , O(Mem) , O(Mem) , 0, 0xF30000A4, 8 /* Size of mem */), INST(kX86InstRepMovSW , "rep movsw" , G(Rep) , F(Special) , O(Mem) , O(Mem) , 0, 0xF30000A4, 2 /* Size of mem */), INST(kX86InstRepStoSB , "rep stosb" , G(Rep) , F(Special) , O(Mem) , 0 , 0, 0xF30000AA, 1 /* Size of mem */), INST(kX86InstRepStoSD , "rep stosd" , G(Rep) , F(Special) , O(Mem) , 0 , 0, 0xF30000AA, 4 /* Size of mem */), INST(kX86InstRepStoSQ , "rep stosq" , G(Rep) , F(Special) , O(Mem) , 0 , 0, 0xF30000AA, 8 /* Size of mem */), INST(kX86InstRepStoSW , "rep stosw" , G(Rep) , F(Special) , O(Mem) , 0 , 0, 0xF30000AA, 2 /* Size of mem */), INST(kX86InstRepECmpSB , "repe cmpsb" , G(Rep) , F(Special) , O(Mem) , O(Mem) , 0, 0xF30000A6, 1 /* Size of mem */), INST(kX86InstRepECmpSD , "repe cmpsd" , G(Rep) , F(Special) , O(Mem) , O(Mem) , 0, 0xF30000A6, 4 /* Size of mem */), INST(kX86InstRepECmpSQ , "repe cmpsq" , G(Rep) , F(Special) , O(Mem) , O(Mem) , 0, 0xF30000A6, 8 /* Size of mem */), INST(kX86InstRepECmpSW , "repe cmpsw" , G(Rep) , F(Special) , O(Mem) , O(Mem) , 0, 0xF30000A6, 2 /* Size of mem */), INST(kX86InstRepEScaSB , "repe scasb" , G(Rep) , F(Special) , O(Mem) , O(Mem) , 0, 0xF30000AE, 1 /* Size of mem */), INST(kX86InstRepEScaSD , "repe scasd" , G(Rep) , F(Special) , O(Mem) , O(Mem) , 0, 0xF30000AE, 4 /* Size of mem */), INST(kX86InstRepEScaSQ , "repe scasq" , G(Rep) , F(Special) , O(Mem) , O(Mem) , 0, 0xF30000AE, 8 /* Size of mem */), INST(kX86InstRepEScaSW , "repe scasw" , G(Rep) , F(Special) , O(Mem) , O(Mem) , 0, 0xF30000AE, 2 /* Size of mem */), INST(kX86InstRepNECmpSB , "repne cmpsb" , G(Rep) , F(Special) , O(Mem) , O(Mem) , 0, 0xF20000A6, 1 /* Size of mem */), INST(kX86InstRepNECmpSD , "repne cmpsd" , G(Rep) , F(Special) , O(Mem) , O(Mem) , 0, 0xF20000A6, 4 /* Size of mem */), INST(kX86InstRepNECmpSQ , "repne cmpsq" , G(Rep) , F(Special) , O(Mem) , O(Mem) , 0, 0xF20000A6, 8 /* Size of mem */), INST(kX86InstRepNECmpSW , "repne cmpsw" , G(Rep) , F(Special) , O(Mem) , O(Mem) , 0, 0xF20000A6, 2 /* Size of mem */), INST(kX86InstRepNEScaSB , "repne scasb" , G(Rep) , F(Special) , O(Mem) , O(Mem) , 0, 0xF20000AE, 1 /* Size of mem */), INST(kX86InstRepNEScaSD , "repne scasd" , G(Rep) , F(Special) , O(Mem) , O(Mem) , 0, 0xF20000AE, 4 /* Size of mem */), INST(kX86InstRepNEScaSQ , "repne scasq" , G(Rep) , F(Special) , O(Mem) , O(Mem) , 0, 0xF20000AE, 8 /* Size of mem */), INST(kX86InstRepNEScaSW , "repne scasw" , G(Rep) , F(Special) , O(Mem) , O(Mem) , 0, 0xF20000AE, 2 /* Size of mem */), INST(kX86InstRet , "ret" , G(Ret) , F(Special) , 0 , 0 , 0, 0 , 0), INST(kX86InstRol , "rol" , G(Rot) , F(Special) , O(GqdwbMem) , O(Gb)|O(Imm) , 0, 0 , 0), INST(kX86InstRor , "ror" , G(Rot) , F(Special) , O(GqdwbMem) , O(Gb)|O(Imm) , 1, 0 , 0), INST(kX86InstRoundPD , "roundpd" , G(MmuRmImm8) , F(Mov) , O(Xmm) , O(XmmMem) , 0, 0x660F3A09, 0), INST(kX86InstRoundPS , "roundps" , G(MmuRmImm8) , F(Mov) , O(Xmm) , O(XmmMem) , 0, 0x660F3A08, 0), INST(kX86InstRoundSD , "roundsd" , G(MmuRmImm8) , F(None) , O(Xmm) , O(XmmMem) , 0, 0x660F3A0B, 0), INST(kX86InstRoundSS , "roundss" , G(MmuRmImm8) , F(None) , O(Xmm) , O(XmmMem) , 0, 0x660F3A0A, 0), INST(kX86InstRSqrtPS , "rsqrtps" , G(MmuRmI) , F(Mov) , O(Xmm) , O(XmmMem) , 0, 0x00000F52, 0), INST(kX86InstRSqrtSS , "rsqrtss" , G(MmuRmI) , F(None) , O(Xmm) , O(XmmMem) , 0, 0xF3000F52, 0), INST(kX86InstSahf , "sahf" , G(Emit) , F(Special) , 0 , 0 , 0, 0x0000009E, 0), INST(kX86InstSal , "sal" , G(Rot) , F(Special) , O(GqdwbMem) , O(Gb)|O(Imm) , 4, 0 , 0), INST(kX86InstSar , "sar" , G(Rot) , F(Special) , O(GqdwbMem) , O(Gb)|O(Imm) , 7, 0 , 0), INST(kX86InstSbb , "sbb" , G(Arith) , F(Lockable) , O(GqdwbMem) , O(GqdwbMem)|O(Imm) , 3, 0x00000018, 0x00000080), INST(kX86InstSetA , "seta" , G(RmByte) , F(None) , O(GbMem) , 0 , 0, 0x00000F97, 0), INST(kX86InstSetAE , "setae" , G(RmByte) , F(None) , O(GbMem) , 0 , 0, 0x00000F93, 0), INST(kX86InstSetB , "setb" , G(RmByte) , F(None) , O(GbMem) , 0 , 0, 0x00000F92, 0), INST(kX86InstSetBE , "setbe" , G(RmByte) , F(None) , O(GbMem) , 0 , 0, 0x00000F96, 0), INST(kX86InstSetC , "setc" , G(RmByte) , F(None) , O(GbMem) , 0 , 0, 0x00000F92, 0), INST(kX86InstSetE , "sete" , G(RmByte) , F(None) , O(GbMem) , 0 , 0, 0x00000F94, 0), INST(kX86InstSetG , "setg" , G(RmByte) , F(None) , O(GbMem) , 0 , 0, 0x00000F9F, 0), INST(kX86InstSetGE , "setge" , G(RmByte) , F(None) , O(GbMem) , 0 , 0, 0x00000F9D, 0), INST(kX86InstSetL , "setl" , G(RmByte) , F(None) , O(GbMem) , 0 , 0, 0x00000F9C, 0), INST(kX86InstSetLE , "setle" , G(RmByte) , F(None) , O(GbMem) , 0 , 0, 0x00000F9E, 0), INST(kX86InstSetNA , "setna" , G(RmByte) , F(None) , O(GbMem) , 0 , 0, 0x00000F96, 0), INST(kX86InstSetNAE , "setnae" , G(RmByte) , F(None) , O(GbMem) , 0 , 0, 0x00000F92, 0), INST(kX86InstSetNB , "setnb" , G(RmByte) , F(None) , O(GbMem) , 0 , 0, 0x00000F93, 0), INST(kX86InstSetNBE , "setnbe" , G(RmByte) , F(None) , O(GbMem) , 0 , 0, 0x00000F97, 0), INST(kX86InstSetNC , "setnc" , G(RmByte) , F(None) , O(GbMem) , 0 , 0, 0x00000F93, 0), INST(kX86InstSetNE , "setne" , G(RmByte) , F(None) , O(GbMem) , 0 , 0, 0x00000F95, 0), INST(kX86InstSetNG , "setng" , G(RmByte) , F(None) , O(GbMem) , 0 , 0, 0x00000F9E, 0), INST(kX86InstSetNGE , "setnge" , G(RmByte) , F(None) , O(GbMem) , 0 , 0, 0x00000F9C, 0), INST(kX86InstSetNL , "setnl" , G(RmByte) , F(None) , O(GbMem) , 0 , 0, 0x00000F9D, 0), INST(kX86InstSetNLE , "setnle" , G(RmByte) , F(None) , O(GbMem) , 0 , 0, 0x00000F9F, 0), INST(kX86InstSetNO , "setno" , G(RmByte) , F(None) , O(GbMem) , 0 , 0, 0x00000F91, 0), INST(kX86InstSetNP , "setnp" , G(RmByte) , F(None) , O(GbMem) , 0 , 0, 0x00000F9B, 0), INST(kX86InstSetNS , "setns" , G(RmByte) , F(None) , O(GbMem) , 0 , 0, 0x00000F99, 0), INST(kX86InstSetNZ , "setnz" , G(RmByte) , F(None) , O(GbMem) , 0 , 0, 0x00000F95, 0), INST(kX86InstSetO , "seto" , G(RmByte) , F(None) , O(GbMem) , 0 , 0, 0x00000F90, 0), INST(kX86InstSetP , "setp" , G(RmByte) , F(None) , O(GbMem) , 0 , 0, 0x00000F9A, 0), INST(kX86InstSetPE , "setpe" , G(RmByte) , F(None) , O(GbMem) , 0 , 0, 0x00000F9A, 0), INST(kX86InstSetPO , "setpo" , G(RmByte) , F(None) , O(GbMem) , 0 , 0, 0x00000F9B, 0), INST(kX86InstSetS , "sets" , G(RmByte) , F(None) , O(GbMem) , 0 , 0, 0x00000F98, 0), INST(kX86InstSetZ , "setz" , G(RmByte) , F(None) , O(GbMem) , 0 , 0, 0x00000F94, 0), INST(kX86InstSFence , "sfence" , G(Emit) , F(None) , 0 , 0 , 0, 0x000FAEF8, 0), INST(kX86InstShl , "shl" , G(Rot) , F(Special) , O(GqdwbMem) , O(Gb)|O(Imm) , 4, 0 , 0), INST(kX86InstShld , "shld" , G(ShldShrd) , F(Special) , O(GqdwbMem) , O(Gb) , 0, 0x00000FA4, 0), INST(kX86InstShr , "shr" , G(Rot) , F(Special) , O(GqdwbMem) , O(Gb)|O(Imm) , 5, 0 , 0), INST(kX86InstShrd , "shrd" , G(ShldShrd) , F(Special) , O(GqdwbMem) , O(Gqdwb) , 0, 0x00000FAC, 0), INST(kX86InstShufPD , "shufpd" , G(MmuRmImm8) , F(None) , O(Xmm) , O(XmmMem) , 0, 0x66000FC6, 0), INST(kX86InstShufPS , "shufps" , G(MmuRmImm8) , F(None) , O(Xmm) , O(XmmMem) , 0, 0x00000FC6, 0), INST(kX86InstSqrtPD , "sqrtpd" , G(MmuRmI) , F(Mov) , O(Xmm) , O(XmmMem) , 0, 0x66000F51, 0), INST(kX86InstSqrtPS , "sqrtps" , G(MmuRmI) , F(Mov) , O(Xmm) , O(XmmMem) , 0, 0x00000F51, 0), INST(kX86InstSqrtSD , "sqrtsd" , G(MmuRmI) , F(None) , O(Xmm) , O(XmmMem) , 0, 0xF2000F51, 0), INST(kX86InstSqrtSS , "sqrtss" , G(MmuRmI) , F(None) , O(Xmm) , O(XmmMem) , 0, 0xF3000F51, 0), INST(kX86InstStc , "stc" , G(Emit) , F(None) , 0 , 0 , 0, 0x000000F9, 0), INST(kX86InstStd , "std" , G(Emit) , F(None) , 0 , 0 , 0, 0x000000FD, 0), INST(kX86InstStMXCSR , "stmxcsr" , G(Mem) , F(None) , O(Mem) , 0 , 3, 0x00000FAE, 0), INST(kX86InstSub , "sub" , G(Arith) , F(Lockable) , O(GqdwbMem) , O(GqdwbMem)|O(Imm) , 5, 0x00000028, 0x00000080), INST(kX86InstSubPD , "subpd" , G(MmuRmI) , F(None) , O(Xmm) , O(XmmMem) , 0, 0x66000F5C, 0), INST(kX86InstSubPS , "subps" , G(MmuRmI) , F(None) , O(Xmm) , O(XmmMem) , 0, 0x00000F5C, 0), INST(kX86InstSubSD , "subsd" , G(MmuRmI) , F(None) , O(Xmm) , O(XmmMem) , 0, 0xF2000F5C, 0), INST(kX86InstSubSS , "subss" , G(MmuRmI) , F(None) , O(Xmm) , O(XmmMem) , 0, 0xF3000F5C, 0), INST(kX86InstTest , "test" , G(Test) , F(None) , O(GqdwbMem) , O(Gqdwb)|O(Imm) , 0, 0 , 0), INST(kX86InstUComISD , "ucomisd" , G(MmuRmI) , F(None) , O(Xmm) , O(XmmMem) , 0, 0x66000F2E, 0), INST(kX86InstUComISS , "ucomiss" , G(MmuRmI) , F(None) , O(Xmm) , O(XmmMem) , 0, 0x00000F2E, 0), INST(kX86InstUd2 , "ud2" , G(Emit) , F(None) , 0 , 0 , 0, 0x00000F0B, 0), INST(kX86InstUnpckHPD , "unpckhpd" , G(MmuRmI) , F(None) , O(Xmm) , O(XmmMem) , 0, 0x66000F15, 0), INST(kX86InstUnpckHPS , "unpckhps" , G(MmuRmI) , F(None) , O(Xmm) , O(XmmMem) , 0, 0x00000F15, 0), INST(kX86InstUnpckLPD , "unpcklpd" , G(MmuRmI) , F(None) , O(Xmm) , O(XmmMem) , 0, 0x66000F14, 0), INST(kX86InstUnpckLPS , "unpcklps" , G(MmuRmI) , F(None) , O(Xmm) , O(XmmMem) , 0, 0x00000F14, 0), INST(kX86InstXadd , "xadd" , G(RmReg) , F(Lockable) , O(GqdwbMem) , O(Gqdwb) , 0, 0x00000FC0, 0), INST(kX86InstXchg , "xchg" , G(Xchg) , F(Lockable) , O(GqdwbMem) , O(Gqdwb) , 0, 0 , 0), INST(kX86InstXor , "xor" , G(Arith) , F(Lockable) , O(GqdwbMem) , O(GqdwbMem)|O(Imm) , 6, 0x00000030, 0x00000080), INST(kX86InstXorPD , "xorpd" , G(MmuRmI) , F(None) , O(Xmm) , O(XmmMem) , 0, 0x66000F57, 0), INST(kX86InstXorPS , "xorps" , G(MmuRmI) , F(None) , O(Xmm) , O(XmmMem) , 0, 0x00000F57, 0) }; #undef G #undef F #undef O #undef INST // ============================================================================ // [AsmJit::x86VarInfo] // ============================================================================ #define C(_Class_) kX86VarClass##_Class_ #define F(_Flag_) kX86VarFlag##_Flag_ const X86VarInfo x86VarInfo[] = { /* 0 */ { kX86RegTypeGpd , 4 , C(Gp) , 0 , "Gpd" }, /* 1 */ { kX86RegTypeGpq , 8 , C(Gp) , 0 , "Gpq" }, /* 2 */ { kX86RegTypeX87 , 4 , C(X87), F(SP) , "X87" }, /* 3 */ { kX86RegTypeX87 , 4 , C(X87), F(SP) , "X87.SS" }, /* 4 */ { kX86RegTypeX87 , 8 , C(X87), F(DP) , "X87.SD" }, /* 5 */ { kX86RegTypeMm , 8 , C(Mm) , 0 , "Mm" }, /* 6 */ { kX86RegTypeXmm , 16, C(Xmm), 0 , "Xmm" }, /* 7 */ { kX86RegTypeXmm , 4 , C(Xmm), F(SP) , "Xmm.SS" }, /* 8 */ { kX86RegTypeXmm , 8 , C(Xmm), F(DP) , "Xmm.SD" }, /* 9 */ { kX86RegTypeXmm , 16, C(Xmm), F(SP) | F(Packed), "Xmm.PS" }, /* 10 */ { kX86RegTypeXmm , 16, C(Xmm), F(DP) | F(Packed), "Xmm.PD" } }; #undef F #undef C } // AsmJit namespace #include "../core/apiend.h" desmume/src/utils/libfat/file_allocation_table.c000664 001750 001750 00000026476 12755534123 023216 0ustar00sergiosergio000000 000000 /* file_allocation_table.c Reading, writing and manipulation of the FAT structure on a FAT partition Copyright (c) 2006 Michael "Chishm" Chisholm Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. 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. 3. The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 "file_allocation_table.h" #include "partition.h" /* Gets the cluster linked from input cluster */ uint32_t _FAT_fat_nextCluster(PARTITION* partition, uint32_t cluster) { uint32_t nextCluster = CLUSTER_FREE; sec_t sector; int offset; if (cluster == CLUSTER_FREE) { return CLUSTER_FREE; } switch (partition->filesysType) { case FS_UNKNOWN: return CLUSTER_ERROR; break; case FS_FAT12: { uint32_t nextCluster_h; sector = partition->fat.fatStart + (((cluster * 3) / 2) / BYTES_PER_READ); offset = ((cluster * 3) / 2) % BYTES_PER_READ; _FAT_cache_readLittleEndianValue (partition->cache, &nextCluster, sector, offset, sizeof(uint8_t)); offset++; if (offset >= BYTES_PER_READ) { offset = 0; sector++; } nextCluster_h = 0; _FAT_cache_readLittleEndianValue (partition->cache, &nextCluster_h, sector, offset, sizeof(uint8_t)); nextCluster |= (nextCluster_h << 8); if (cluster & 0x01) { nextCluster = nextCluster >> 4; } else { nextCluster &= 0x0FFF; } if (nextCluster >= 0x0FF7) { nextCluster = CLUSTER_EOF; } break; } case FS_FAT16: sector = partition->fat.fatStart + ((cluster << 1) / BYTES_PER_READ); offset = (cluster % (BYTES_PER_READ >> 1)) << 1; _FAT_cache_readLittleEndianValue (partition->cache, &nextCluster, sector, offset, sizeof(uint16_t)); if (nextCluster >= 0xFFF7) { nextCluster = CLUSTER_EOF; } break; case FS_FAT32: sector = partition->fat.fatStart + ((cluster << 2) / BYTES_PER_READ); offset = (cluster % (BYTES_PER_READ >> 2)) << 2; _FAT_cache_readLittleEndianValue (partition->cache, &nextCluster, sector, offset, sizeof(uint32_t)); if (nextCluster >= 0x0FFFFFF7) { nextCluster = CLUSTER_EOF; } break; default: return CLUSTER_ERROR; break; } return nextCluster; } /* writes value into the correct offset within a partition's FAT, based on the cluster number. */ static bool _FAT_fat_writeFatEntry (PARTITION* partition, uint32_t cluster, uint32_t value) { sec_t sector; int offset; uint32_t oldValue; if ((cluster < CLUSTER_FIRST) || (cluster > partition->fat.lastCluster /* This will catch CLUSTER_ERROR */)) { return false; } switch (partition->filesysType) { case FS_UNKNOWN: return false; break; case FS_FAT12: sector = partition->fat.fatStart + (((cluster * 3) / 2) / BYTES_PER_READ); offset = ((cluster * 3) / 2) % BYTES_PER_READ; if (cluster & 0x01) { _FAT_cache_readLittleEndianValue (partition->cache, &oldValue, sector, offset, sizeof(uint8_t)); value = (value << 4) | (oldValue & 0x0F); _FAT_cache_writeLittleEndianValue (partition->cache, value & 0xFF, sector, offset, sizeof(uint8_t)); offset++; if (offset >= BYTES_PER_READ) { offset = 0; sector++; } _FAT_cache_writeLittleEndianValue (partition->cache, (value >> 8) & 0xFF, sector, offset, sizeof(uint8_t)); } else { _FAT_cache_writeLittleEndianValue (partition->cache, value, sector, offset, sizeof(uint8_t)); offset++; if (offset >= BYTES_PER_READ) { offset = 0; sector++; } _FAT_cache_readLittleEndianValue (partition->cache, &oldValue, sector, offset, sizeof(uint8_t)); value = ((value >> 8) & 0x0F) | (oldValue & 0xF0); _FAT_cache_writeLittleEndianValue (partition->cache, value, sector, offset, sizeof(uint8_t)); } break; case FS_FAT16: sector = partition->fat.fatStart + ((cluster << 1) / BYTES_PER_READ); offset = (cluster % (BYTES_PER_READ >> 1)) << 1; _FAT_cache_writeLittleEndianValue (partition->cache, value, sector, offset, sizeof(uint16_t)); break; case FS_FAT32: sector = partition->fat.fatStart + ((cluster << 2) / BYTES_PER_READ); offset = (cluster % (BYTES_PER_READ >> 2)) << 2; _FAT_cache_writeLittleEndianValue (partition->cache, value, sector, offset, sizeof(uint32_t)); break; default: return false; break; } return true; } /*----------------------------------------------------------------- gets the first available free cluster, sets it to end of file, links the input cluster to it then returns the cluster number If an error occurs, return CLUSTER_ERROR -----------------------------------------------------------------*/ uint32_t _FAT_fat_linkFreeCluster(PARTITION* partition, uint32_t cluster) { uint32_t firstFree; uint32_t curLink; uint32_t lastCluster; bool loopedAroundFAT = false; lastCluster = partition->fat.lastCluster; if (cluster > lastCluster) { return CLUSTER_ERROR; } // Check if the cluster already has a link, and return it if so curLink = _FAT_fat_nextCluster(partition, cluster); if ((curLink >= CLUSTER_FIRST) && (curLink <= lastCluster)) { return curLink; // Return the current link - don't allocate a new one } // Get a free cluster firstFree = partition->fat.firstFree; // Start at first valid cluster if (firstFree < CLUSTER_FIRST) { firstFree = CLUSTER_FIRST; } // Search until a free cluster is found while (_FAT_fat_nextCluster(partition, firstFree) != CLUSTER_FREE) { firstFree++; if (firstFree > lastCluster) { if (loopedAroundFAT) { // If couldn't get a free cluster then return an error partition->fat.firstFree = firstFree; return CLUSTER_ERROR; } else { // Try looping back to the beginning of the FAT // This was suggested by loopy firstFree = CLUSTER_FIRST; loopedAroundFAT = true; } } } partition->fat.firstFree = firstFree; if ((cluster >= CLUSTER_FIRST) && (cluster < lastCluster)) { // Update the linked from FAT entry _FAT_fat_writeFatEntry (partition, cluster, firstFree); } // Create the linked to FAT entry _FAT_fat_writeFatEntry (partition, firstFree, CLUSTER_EOF); return firstFree; } /*----------------------------------------------------------------- gets the first available free cluster, sets it to end of file, links the input cluster to it, clears the new cluster to 0 valued bytes, then returns the cluster number If an error occurs, return CLUSTER_ERROR -----------------------------------------------------------------*/ uint32_t _FAT_fat_linkFreeClusterCleared (PARTITION* partition, uint32_t cluster) { uint32_t newCluster; uint32_t i; uint8_t emptySector[BYTES_PER_READ]; // Link the cluster newCluster = _FAT_fat_linkFreeCluster(partition, cluster); if (newCluster == CLUSTER_FREE || newCluster == CLUSTER_ERROR) { return CLUSTER_ERROR; } // Clear all the sectors within the cluster memset (emptySector, 0, BYTES_PER_READ); for (i = 0; i < partition->sectorsPerCluster; i++) { _FAT_cache_writeSectors (partition->cache, _FAT_fat_clusterToSector (partition, newCluster) + i, 1, emptySector); } return newCluster; } /*----------------------------------------------------------------- _FAT_fat_clearLinks frees any cluster used by a file -----------------------------------------------------------------*/ bool _FAT_fat_clearLinks (PARTITION* partition, uint32_t cluster) { uint32_t nextCluster; if ((cluster < CLUSTER_FIRST) || (cluster > partition->fat.lastCluster /* This will catch CLUSTER_ERROR */)) return false; // If this clears up more space in the FAT before the current free pointer, move it backwards if (cluster < partition->fat.firstFree) { partition->fat.firstFree = cluster; } while ((cluster != CLUSTER_EOF) && (cluster != CLUSTER_FREE) && (cluster != CLUSTER_ERROR)) { // Store next cluster before erasing the link nextCluster = _FAT_fat_nextCluster (partition, cluster); // Erase the link _FAT_fat_writeFatEntry (partition, cluster, CLUSTER_FREE); // Move onto next cluster cluster = nextCluster; } return true; } /*----------------------------------------------------------------- _FAT_fat_trimChain Drop all clusters past the chainLength. If chainLength is 0, all clusters are dropped. If chainLength is 1, the first cluster is kept and the rest are dropped, and so on. Return the last cluster left in the chain. -----------------------------------------------------------------*/ uint32_t _FAT_fat_trimChain (PARTITION* partition, uint32_t startCluster, unsigned int chainLength) { uint32_t nextCluster; if (chainLength == 0) { // Drop the entire chain _FAT_fat_clearLinks (partition, startCluster); return CLUSTER_FREE; } else { // Find the last cluster in the chain, and the one after it chainLength--; nextCluster = _FAT_fat_nextCluster (partition, startCluster); while ((chainLength > 0) && (nextCluster != CLUSTER_FREE) && (nextCluster != CLUSTER_EOF)) { chainLength--; startCluster = nextCluster; nextCluster = _FAT_fat_nextCluster (partition, startCluster); } // Drop all clusters after the last in the chain if (nextCluster != CLUSTER_FREE && nextCluster != CLUSTER_EOF) { _FAT_fat_clearLinks (partition, nextCluster); } // Mark the last cluster in the chain as the end of the file _FAT_fat_writeFatEntry (partition, startCluster, CLUSTER_EOF); return startCluster; } } /*----------------------------------------------------------------- _FAT_fat_lastCluster Trace the cluster links until the last one is found -----------------------------------------------------------------*/ uint32_t _FAT_fat_lastCluster (PARTITION* partition, uint32_t cluster) { while ((_FAT_fat_nextCluster(partition, cluster) != CLUSTER_FREE) && (_FAT_fat_nextCluster(partition, cluster) != CLUSTER_EOF)) { cluster = _FAT_fat_nextCluster(partition, cluster); } return cluster; } /*----------------------------------------------------------------- _FAT_fat_freeClusterCount Return the number of free clusters available -----------------------------------------------------------------*/ unsigned int _FAT_fat_freeClusterCount (PARTITION* partition) { unsigned int count = 0; uint32_t curCluster; for (curCluster = CLUSTER_FIRST; curCluster <= partition->fat.lastCluster; curCluster++) { if (_FAT_fat_nextCluster(partition, curCluster) == CLUSTER_FREE) { count++; } } return count; } desmume/src/libretro-common/include/rthreads/async_job.h000664 001750 001750 00000003273 12755534123 024633 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2015 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (async_job.h). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef __LIBRETRO_SDK_ASYNC_JOB_H #define __LIBRETRO_SDK_ASYNC_JOB_H typedef struct async_job async_job_t; typedef void (*async_task_t)(void *payload); async_job_t *async_job_new(void); void async_job_free(async_job_t *ajob); int async_job_add(async_job_t *ajob, async_task_t task, void *payload); #endif /* __LIBRETRO_SDK_ASYNC_JOB_H */ desmume/src/libretro/jni/Android.mk000664 001750 001750 00000002077 12755534123 020460 0ustar00sergiosergio000000 000000 HAVE_GRIFFIN := 0 LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) CORE_DIR = ../.. JIT= DESMUME_JIT=0 ifeq ($(TARGET_ARCH),arm) LOCAL_CXXFLAGS := -DANDROID_ARM LOCAL_ARM_MODE := arm DESMUME_JIT_ARM = 1 JIT = -D__RETRO_ARM__ -DHAVE_JIT endif ifeq ($(TARGET_ARCH),x86) LOCAL_CXXFLAGS := -DANDROID_X86 DESMUME_JIT = 1 JIT = -DHAVE_JIT endif ifeq ($(TARGET_ARCH),mips) LOCAL_CXXFLAGS := -DANDROID_MIPS -D__mips__ -D__MIPSEL__ endif ifeq ($(TARGET_ARCH),mips64) LOCAL_CXXFLAGS := -DANDROID_MIPS -D__mips__ -D__MIPSEL__ endif LOCAL_MODULE := libretro include ../../../Makefile.common LOCAL_SRC_FILES := $(SOURCES_CXX) $(SOURCES_C) GLOBAL_DEFINES := $(JIT) -fexceptions LOCAL_CXXFLAGS += -O3 -D__LIBRETRO__ -Wno-write-strings -DANDROID -DFRONTEND_SUPPORTS_RGB565 $(GLOBAL_DEFINES) $(INCDIR) LOCAL_CFLAGS = -O3 -D__LIBRETRO__ -Wno-psabi -Wno-write-strings -DANDROID -DFRONTEND_SUPPORTS_RGB565 $(GLOBAL_DEFINES) $(INCDIR) LOCAL_C_INCLUDES = -I$(CORE_DIR)/libretro/zlib -iquote $(CORE_DIR) -iquote $(CORE_DIR)/libretro LOCAL_LDLIBS += -lz include $(BUILD_SHARED_LIBRARY) desmume/src/emufile.h000664 001750 001750 00000020306 12755534123 015737 0ustar00sergiosergio000000 000000 /* The MIT License Copyright (C) 2009-2014 DeSmuME team Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ //don't use emufile for files bigger than 2GB! you have been warned! some day this will be fixed. #ifndef EMUFILE_H #define EMUFILE_H #include #include #include #include #include #include #include #include "types.h" #ifdef HOST_WINDOWS #include #else #include #endif class EMUFILE_MEMORY; class EMUFILE { protected: bool failbit; public: EMUFILE() : failbit(false) {} //returns a new EMUFILE which is guranteed to be in memory. the EMUFILE you call this on may be deleted. use the returned EMUFILE in its place virtual EMUFILE* memwrap() = 0; virtual ~EMUFILE() {} static bool readAllBytes(std::vector* buf, const std::string& fname); bool fail(bool unset=false) { bool ret = failbit; if(unset) unfail(); return ret; } void unfail() { failbit=false; } bool eof() { return size()==ftell(); } size_t fread(const void *ptr, size_t bytes){ return _fread(ptr,bytes); } void unget() { fseek(-1,SEEK_CUR); } //virtuals public: virtual FILE *get_fp() = 0; virtual int fprintf(const char *format, ...) = 0; virtual int fgetc() = 0; virtual int fputc(int c) = 0; virtual size_t _fread(const void *ptr, size_t bytes) = 0; //removing these return values for now so we can find any code that might be using them and make sure //they handle the return values correctly virtual void fwrite(const void *ptr, size_t bytes) = 0; void write64le(u64* val); void write64le(u64 val); size_t read64le(u64* val); u64 read64le(); void write32le(u32* val); void write32le(s32* val) { write32le((u32*)val); } void write32le(u32 val); size_t read32le(u32* val); size_t read32le(s32* val); u32 read32le(); void write16le(u16* val); void write16le(s16* val) { write16le((u16*)val); } void write16le(u16 val); size_t read16le(s16* Bufo); size_t read16le(u16* val); u16 read16le(); void write8le(u8* val); void write8le(u8 val); size_t read8le(u8* val); u8 read8le(); void writedouble(double* val); void writedouble(double val); double readdouble(); size_t readdouble(double* val); virtual int fseek(int offset, int origin) = 0; virtual int ftell() = 0; virtual int size() = 0; virtual void fflush() = 0; virtual void truncate(s32 length) = 0; void writeMemoryStream(EMUFILE_MEMORY* ms); void readMemoryStream(EMUFILE_MEMORY* ms); }; //todo - handle read-only specially? class EMUFILE_MEMORY : public EMUFILE { protected: std::vector *vec; bool ownvec; s32 pos, len; void reserve(u32 amt) { if(vec->size() < amt) vec->resize(amt); } public: EMUFILE_MEMORY(std::vector *underlying) : vec(underlying), ownvec(false), pos(0), len((s32)underlying->size()) { } EMUFILE_MEMORY(u32 preallocate) : vec(new std::vector()), ownvec(true), pos(0), len(0) { vec->resize(preallocate); len = preallocate; } EMUFILE_MEMORY() : vec(new std::vector()), ownvec(true), pos(0), len(0) { vec->reserve(1024); } EMUFILE_MEMORY(void* buf, s32 size) : vec(new std::vector()), ownvec(true), pos(0), len(size) { vec->resize(size); if(size != 0) memcpy(&vec->front(),buf,size); } ~EMUFILE_MEMORY() { if(ownvec) delete vec; } virtual EMUFILE* memwrap(); virtual void truncate(s32 length) { vec->resize(length); len = length; if(pos>length) pos=length; } u8* buf() { if(size()==0) reserve(1); return &(*vec)[0]; } std::vector* get_vec() const { return vec; }; virtual FILE *get_fp() { return NULL; } virtual int fprintf(const char *format, ...) { std::va_list argptr; va_start(argptr, format); //we dont generate straight into the buffer because it will null terminate (one more byte than we want) int amt = vsnprintf(0,0,format,argptr); char* tempbuf = new char[amt+1]; va_end(argptr); va_start(argptr, format); vsprintf(tempbuf,format,argptr); fwrite(tempbuf,amt); delete[] tempbuf; va_end(argptr); return amt; }; virtual int fgetc() { u8 temp; //need an optimized codepath //if(_fread(&temp,1) != 1) // return EOF; //else return temp; u32 remain = len-pos; if(remain<1) { failbit = true; return -1; } temp = buf()[pos]; pos++; return temp; } virtual int fputc(int c) { u8 temp = (u8)c; //TODO //if(fwrite(&temp,1)!=1) return EOF; fwrite(&temp,1); return 0; } virtual size_t _fread(const void *ptr, size_t bytes); //removing these return values for now so we can find any code that might be using them and make sure //they handle the return values correctly virtual void fwrite(const void *ptr, size_t bytes){ reserve(pos+(s32)bytes); memcpy(buf()+pos,ptr,bytes); pos += (s32)bytes; len = std::max(pos,len); } virtual int fseek(int offset, int origin){ //work differently for read-only...? switch(origin) { case SEEK_SET: pos = offset; break; case SEEK_CUR: pos += offset; break; case SEEK_END: pos = size()+offset; break; default: assert(false); } reserve(pos); return 0; } virtual int ftell() { return pos; } virtual void fflush() {} void trim() { vec->resize(len); } virtual int size() { return (int)len; } }; class EMUFILE_FILE : public EMUFILE { protected: FILE* fp; std::string fname; char mode[16]; long mFilePosition; bool mPositionCacheEnabled; enum eCondition { eCondition_Clean, eCondition_Unknown, eCondition_Read, eCondition_Write } mCondition; private: void open(const char* fname, const char* mode) { mPositionCacheEnabled = false; mCondition = eCondition_Clean; fp = fopen(fname,mode); if(!fp) failbit = true; this->fname = fname; strcpy(this->mode,mode); } public: EMUFILE_FILE(const std::string& fname, const char* mode) { open(fname.c_str(),mode); } EMUFILE_FILE(const char* fname, const char* mode) { open(fname,mode); } void EnablePositionCache(); virtual ~EMUFILE_FILE() { if(NULL != fp) fclose(fp); } virtual FILE *get_fp() { return fp; } virtual EMUFILE* memwrap(); bool is_open() { return fp != NULL; } void DemandCondition(eCondition cond); virtual void truncate(s32 length); virtual int fprintf(const char *format, ...) { std::va_list argptr; va_start(argptr, format); int ret = ::vfprintf(fp, format, argptr); va_end(argptr); return ret; }; virtual int fgetc() { return ::fgetc(fp); } virtual int fputc(int c) { return ::fputc(c, fp); } virtual size_t _fread(const void *ptr, size_t bytes); //removing these return values for now so we can find any code that might be using them and make sure //they handle the return values correctly virtual void fwrite(const void *ptr, size_t bytes); virtual int fseek(int offset, int origin); virtual int ftell(); virtual int size() { int oldpos = ftell(); fseek(0,SEEK_END); int len = ftell(); fseek(oldpos,SEEK_SET); return len; } virtual void fflush() { ::fflush(fp); } }; #endif desmume/src/libretro-common/net/000700 001750 001750 00000000000 12756420131 020013 5ustar00sergiosergio000000 000000 desmume/src/armcpu.h000664 001750 001750 00000022472 12755534123 015606 0ustar00sergiosergio000000 000000 /* Copyright (C) 2006 yopyop Copyright (C) 2006-2015 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the this software. If not, see . */ #ifndef ARM_CPU #define ARM_CPU #include "types.h" #include "MMU.h" #define CONDITION(i) ((i)>>28) #define REG_POS(i,n) (((i)>>n) & 0xF) #define CODE(i) (((i)>>25)&0x7) #define OPCODE(i) (((i)>>21)&0xF) #define SIGNEBIT(i) (((i)>>20) & 1) #define EXCEPTION_RESET 0x00 #define EXCEPTION_UNDEFINED_INSTRUCTION 0x04 #define EXCEPTION_SWI 0x08 #define EXCEPTION_PREFETCH_ABORT 0x0C #define EXCEPTION_DATA_ABORT 0x10 #define EXCEPTION_RESERVED_0x14 0x14 #define EXCEPTION_IRQ 0x18 #define EXCEPTION_FAST_IRQ 0x1C #define INSTRUCTION_INDEX(i) ((((i)>>16)&0xFF0)|(((i)>>4)&0xF)) inline u32 ROR(u32 i, u32 j) { return ((((u32)(i))>>(j)) | (((u32)(i))<<(32-(j)))); } template inline T UNSIGNED_OVERFLOW(T a,T b,T c) { return BIT31(((a)&(b)) | (((a)|(b))&(~c))); } template inline T UNSIGNED_UNDERFLOW(T a,T b,T c) { return BIT31(((~a)&(b)) | (((~a)|(b))&(c))); } template inline T SIGNED_OVERFLOW(T a,T b,T c) { return BIT31(((a)&(b)&(~c)) | ((~a)&(~(b))&(c))); } template inline T SIGNED_UNDERFLOW(T a,T b,T c) { return BIT31(((a)&(~(b))&(~c)) | ((~a)&(b)&(c))); } #if !defined(bswap32) #define bswap32(val) \ ( (val << 24) & 0xFF000000) | \ ( (val << 8) & 0x00FF0000) | \ ( (val >> 8) & 0x0000FF00) | \ ( (val >> 24) & 0x000000FF) #endif #if !defined(bswap64) #define bswap64(x) \ ( (x << 56) & 0xff00000000000000ULL ) | \ ( (x << 40) & 0x00ff000000000000ULL ) | \ ( (x << 24) & 0x0000ff0000000000ULL ) | \ ( (x << 8) & 0x000000ff00000000ULL ) | \ ( (x >> 8) & 0x00000000ff000000ULL ) | \ ( (x >> 24) & 0x0000000000ff0000ULL ) | \ ( (x >> 40) & 0x000000000000ff00ULL ) | \ ( (x >> 56) & 0x00000000000000ffULL ) #endif // ============================= CPRS flags funcs inline bool CarryFrom(s32 left, s32 right) { u32 res = (0xFFFFFFFFU - (u32)left); return ((u32)right > res); } inline bool BorrowFrom(s32 left, s32 right) { return ((u32)right > (u32)left); } inline bool OverflowFromADD(s32 alu_out, s32 left, s32 right) { return ((left >= 0 && right >= 0) || (left < 0 && right < 0)) && ((left < 0 && alu_out >= 0) || (left >= 0 && alu_out < 0)); } inline bool OverflowFromSUB(s32 alu_out, s32 left, s32 right) { return ((left < 0 && right >= 0) || (left >= 0 && right < 0)) && ((left < 0 && alu_out >= 0) || (left >= 0 && alu_out < 0)); } //zero 15-feb-2009 - these werent getting used and they were getting in my way //#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 static const u8 arm_cond_table[16*16] = { // N=0, Z=0, C=0, V=0 0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF, // 0x00 0x00,0xFF,0xFF,0x00,0xFF,0x00,0xFF,0x20, // 0x00 // N=0, Z=0, C=0, V=1 0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0x00, // 0x10 0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0x20, // N=0, Z=0, C=1, V=0 0x00,0xFF,0xFF,0x00,0x00,0xFF,0x00,0xFF, // 0x20 0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x20, // N=0, Z=0, C=1, V=1 0x00,0xFF,0xFF,0x00,0x00,0xFF,0xFF,0x00, // 0x30 0xFF,0x00,0x00,0xFF,0x00,0xFF,0xFF,0x20, // N=0, Z=1, C=0, V=0 0xFF,0x00,0x00,0xFF,0x00,0xFF,0x00,0xFF, // 0x40 0x00,0xFF,0xFF,0x00,0x00,0xFF,0xFF,0x20, // N=0, Z=1, C=0, V=1 0xFF,0x00,0x00,0xFF,0x00,0xFF,0xFF,0x00, // 0x50 0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0x20, // N=0, Z=1, C=1, V=0 0xFF,0x00,0xFF,0x00,0x00,0xFF,0x00,0xFF, // 0x60 0x00,0xFF,0xFF,0x00,0x00,0xFF,0xFF,0x20, // N=0, Z=1, C=1, V=1 0xFF,0x00,0xFF,0x00,0x00,0xFF,0xFF,0x00, // 0x70 0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0x20, // N=1, Z=0, C=0, V=0 0x00,0xFF,0x00,0xFF,0xFF,0x00,0x00,0xFF, // 0x80 0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0x20, // N=1, Z=0, C=0, V=1 0x00,0xFF,0x00,0xFF,0xFF,0x00,0xFF,0x00, // 0x90 0x00,0xFF,0xFF,0x00,0xFF,0x00,0xFF,0x20, // N=1, Z=0, C=1, V=0 0x00,0xFF,0xFF,0x00,0xFF,0x00,0x00,0xFF, // 0xA0 0xFF,0x00,0x00,0xFF,0x00,0xFF,0xFF,0x20, // N=1, Z=0, C=1, V=1 0x00,0xFF,0xFF,0x00,0xFF,0x00,0xFF,0x00, // 0xB0 0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x20, // N=1, Z=1, C=0, V=0 0xFF,0x00,0x00,0xFF,0xFF,0x00,0x00,0xFF, // 0xC0 0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0x20, // N=1, Z=1, C=0, V=1 0xFF,0x00,0x00,0xFF,0xFF,0x00,0xFF,0x00, // 0xD0 0x00,0xFF,0xFF,0x00,0x00,0xFF,0xFF,0x20, // N=1, Z=1, C=1, V=0 0xFF,0x00,0xFF,0x00,0xFF,0x00,0x00,0xFF, // 0xE0 0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0x20, // N=1, Z=1, C=1, V=1 0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00, // 0xF0 0x00,0xFF,0xFF,0x00,0x00,0xFF,0xFF,0x20 }; #define TEST_COND(cond, inst, CPSR) ((arm_cond_table[((CPSR.val >> 24) & 0xf0)|(cond)]) & (1 << (inst))) enum Mode { USR = 0x10, FIQ = 0x11, IRQ = 0x12, SVC = 0x13, ABT = 0x17, UND = 0x1B, SYS = 0x1F }; typedef union { struct { #ifdef MSB_FIRST u32 N : 1, Z : 1, C : 1, V : 1, Q : 1, RAZ : 19, I : 1, F : 1, T : 1, mode : 5; #else u32 mode : 5, T : 1, F : 1, I : 1, RAZ : 19, Q : 1, V : 1, C : 1, Z : 1, N : 1; #endif } bits; u32 val; } Status_Reg; /** * 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; 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; void SetControlInterface(const armcpu_ctrl_iface *theCtrlInterface); armcpu_ctrl_iface* GetControlInterface(); void SetControlInterfaceData(void *theData); void* GetControlInterfaceData(); void SetCurrentMemoryInterface(armcpu_memory_iface *theMemInterface); armcpu_memory_iface* GetCurrentMemoryInterface(); void SetCurrentMemoryInterfaceData(void *theData); void* GetCurrentMemoryInterfaceData(); void SetBaseMemoryInterface(const armcpu_memory_iface *theMemInterface); armcpu_memory_iface* GetBaseMemoryInterface(); void SetBaseMemoryInterfaceData(void *theData); void* GetBaseMemoryInterfaceData(); void ResetMemoryInterfaceToBase(); void changeCPSR(); 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; u32 intVector; u8 LDTBit; //1 : ARMv5 style 0 : non ARMv5 (earlier) BOOL waitIRQ; BOOL halt_IE_and_IF; //the cpu is halted, waiting for IE&IF to signal something u8 intrWaitARM_state; BOOL BIOS_loaded; u32 (* *swi_tab)(); // flag indicating if the processor is stalled (for debugging) int stalled; #if defined(_M_X64) || defined(__x86_64__) u8 cond_table[16*16]; #endif /** 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; /** the memory interface */ armcpu_memory_iface *mem_if; // This is the memory interface currently in use. armcpu_memory_iface base_mem_if; // This is the CPU's base memory interface. /** the ctrl interface */ armcpu_ctrl_iface ctrl_iface; }; int armcpu_new( armcpu_t *armcpu, u32 id); void armcpu_init(armcpu_t *armcpu, u32 adr); u32 armcpu_switchMode(armcpu_t *armcpu, u8 mode); BOOL armcpu_irqException(armcpu_t *armcpu); BOOL armcpu_flagIrq( armcpu_t *armcpu); void armcpu_exception(armcpu_t *cpu, u32 number); u32 TRAPUNDEF(armcpu_t* cpu); u32 armcpu_Wait4IRQ(armcpu_t *cpu); extern armcpu_t NDS_ARM7; extern armcpu_t NDS_ARM9; extern const armcpu_ctrl_iface arm_default_ctrl_iface; template u32 armcpu_exec(); #ifdef HAVE_JIT template u32 armcpu_exec(); #endif void setIF(int PROCNUM, u32 flag); static INLINE void NDS_makeIrq(int PROCNUM, u32 num) { setIF(PROCNUM,1< #endif #endif #endif desmume/src/libretro-common/000700 001750 001750 00000000000 12756420131 017225 5ustar00sergiosergio000000 000000 desmume/src/cp15.h000664 001750 001750 00000010443 12755534123 015062 0ustar00sergiosergio000000 000000 /* Copyright (C) 2006 yopyop Copyright (C) 2006-2015 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the this software. If not, see . */ #ifndef __CP15_H__ #define __CP15_H__ #include #include "types.h" class EMUFILE; #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 #define CP15_SIZEBINARY(val) (1 << (CP15_SIZEIDENTIFIER(val)+1)) #define CP15_SIZEIDENTIFIER(val) ((((val) >> 1) & 0x1F)) #define CP15_MASKFROMREG(val) (~((CP15_SIZEBINARY(val)-1) | 0x3F)) #define CP15_SETFROMREG(val) ((val) & CP15_MASKFROMREG(val)) struct armcp15_t { public: u32 IDCode; u32 cacheType; u32 TCMSize; u32 ctrl; u32 DCConfig; u32 ICConfig; u32 writeBuffCtrl; u32 und; u32 DaccessPerm; u32 IaccessPerm; u32 protectBaseSize[8]; 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] ; void setSingleRegionAccess(u8 num, u32 mask, u32 set); void maskPrecalc(); public: armcp15_t() : IDCode(0x41059461), cacheType(0x0F0D2112), TCMSize(0x00140180), ctrl(0x00012078), DCConfig(0), ICConfig(0), writeBuffCtrl(0), und(0), DaccessPerm(0x22222222), IaccessPerm(0x22222222), cacheOp(0), DcacheLock(0), IcacheLock(0), ITCMRegion(0x0C), DTCMRegion(0x0080000A), processID(0), RAM_TAG(0), testState(0), cacheDbg(0) { //printf("CP15 Reset\n"); memset(&protectBaseSize[0], 0, sizeof(protectBaseSize)); memset(®ionWriteMask_USR[0], 0, sizeof(regionWriteMask_USR)); memset(®ionWriteMask_SYS[0], 0, sizeof(regionWriteMask_SYS)); memset(®ionReadMask_USR[0], 0, sizeof(regionReadMask_USR)); memset(®ionReadMask_SYS[0], 0, sizeof(regionReadMask_SYS)); memset(®ionExecuteMask_USR[0], 0, sizeof(regionExecuteMask_USR)); memset(®ionExecuteMask_SYS[0], 0, sizeof(regionExecuteMask_SYS)); memset(®ionWriteSet_USR[0], 0, sizeof(regionWriteSet_USR)); memset(®ionWriteSet_SYS[0], 0, sizeof(regionWriteSet_SYS)); memset(®ionReadSet_USR[0], 0, sizeof(regionReadSet_USR)); memset(®ionReadSet_SYS[0], 0, sizeof(regionReadSet_SYS)); memset(®ionExecuteSet_USR[0], 0, sizeof(regionExecuteSet_USR)); memset(®ionExecuteSet_SYS[0], 0, sizeof(regionExecuteSet_SYS)); } BOOL dataProcess(u8 CRd, u8 CRn, u8 CRm, u8 opcode1, u8 opcode2); BOOL load(u8 CRd, u8 adr); BOOL store(u8 CRd, u8 adr); BOOL moveCP2ARM(u32 * R, u8 CRn, u8 CRm, u8 opcode1, u8 opcode2); BOOL moveARM2CP(u32 val, u8 CRn, u8 CRm, u8 opcode1, u8 opcode2); BOOL isAccessAllowed(u32 address,u32 access); // savestate void saveone(EMUFILE* os); bool loadone(EMUFILE* is); }; extern armcp15_t cp15; #endif /* __CP15_H__*/ desmume/src/libretro-common/utils/sha1.c000664 001750 001750 00000036013 12755534123 021412 0ustar00sergiosergio000000 000000 /* * sha1.h * * Copyright (C) 1998, 2009 * Paul E. Jones * All Rights Reserved * ***************************************************************************** * $Id: sha1.h 12 2009-06-22 19:34:25Z paulej $ ***************************************************************************** * * Description: * This class implements the Secure Hashing Standard as defined * in FIPS PUB 180-1 published April 17, 1995. * * Many of the variable names in the SHA1Context, especially the * single character names, were used because those were the names * used in the publication. * * Please read the file sha1.c for more information. * */ #ifndef _SHA1_H_ #define _SHA1_H_ /* * This structure will hold context information for the hashing * operation */ typedef struct SHA1Context { unsigned Message_Digest[5]; /* Message Digest (output) */ unsigned Length_Low; /* Message length in bits */ unsigned Length_High; /* Message length in bits */ unsigned char Message_Block[64]; /* 512-bit message blocks */ int Message_Block_Index; /* Index into message block array */ int Computed; /* Is the digest computed? */ int Corrupted; /* Is the message digest corruped? */ } SHA1Context; /* * Function Prototypes */ void SHA1Reset(SHA1Context *); int SHA1Result(SHA1Context *); void SHA1Input( SHA1Context *, const unsigned char *, unsigned); #endif /* * sha1.c * * Copyright (C) 1998, 2009 * Paul E. Jones * All Rights Reserved * ***************************************************************************** * $Id: sha1.c 12 2009-06-22 19:34:25Z paulej $ ***************************************************************************** * * Description: * This file implements the Secure Hashing Standard as defined * in FIPS PUB 180-1 published April 17, 1995. * * The Secure Hashing Standard, which uses the Secure Hashing * Algorithm (SHA), produces a 160-bit message digest for a * given data stream. In theory, it is highly improbable that * two messages will produce the same message digest. Therefore, * this algorithm can serve as a means of providing a "fingerprint" * for a message. * * Portability Issues: * SHA-1 is defined in terms of 32-bit "words". This code was * written with the expectation that the processor has at least * a 32-bit machine word size. If the machine word size is larger, * the code should still function properly. One caveat to that * is that the input functions taking characters and character * arrays assume that only 8 bits of information are stored in each * character. * * Caveats: * SHA-1 is designed to work with messages less than 2^64 bits * long. Although SHA-1 allows a message digest to be generated for * messages of any number of bits less than 2^64, this * implementation only works with messages with a length that is a * multiple of the size of an 8-bit character. * */ /*#include "sha1.h"*/ /* * Define the circular shift macro */ #define SHA1CircularShift(bits,word) \ ((((word) << (bits)) & 0xFFFFFFFF) | \ ((word) >> (32-(bits)))) /* Function prototypes */ void SHA1ProcessMessageBlock(SHA1Context *); void SHA1PadMessage(SHA1Context *); /* * SHA1Reset * * Description: * This function will initialize the SHA1Context in preparation * for computing a new message digest. * * Parameters: * context: [in/out] * The context to reset. * * Returns: * Nothing. * * Comments: * */ void SHA1Reset(SHA1Context *context) { context->Length_Low = 0; context->Length_High = 0; context->Message_Block_Index = 0; context->Message_Digest[0] = 0x67452301; context->Message_Digest[1] = 0xEFCDAB89; context->Message_Digest[2] = 0x98BADCFE; context->Message_Digest[3] = 0x10325476; context->Message_Digest[4] = 0xC3D2E1F0; context->Computed = 0; context->Corrupted = 0; } /* * SHA1Result * * Description: * This function will return the 160-bit message digest into the * Message_Digest array within the SHA1Context provided * * Parameters: * context: [in/out] * The context to use to calculate the SHA-1 hash. * * Returns: * 1 if successful, 0 if it failed. * * Comments: * */ int SHA1Result(SHA1Context *context) { if (context->Corrupted) return 0; if (!context->Computed) { SHA1PadMessage(context); context->Computed = 1; } return 1; } /* * SHA1Input * * Description: * This function accepts an array of octets as the next portion of * the message. * * Parameters: * context: [in/out] * The SHA-1 context to update * message_array: [in] * An array of characters representing the next portion of the * message. * length: [in] * The length of the message in message_array * * Returns: * Nothing. * * Comments: * */ void SHA1Input( SHA1Context *context, const unsigned char *message_array, unsigned length) { if (!length) return; if (context->Computed || context->Corrupted) { context->Corrupted = 1; return; } while(length-- && !context->Corrupted) { context->Message_Block[context->Message_Block_Index++] = (*message_array & 0xFF); context->Length_Low += 8; /* Force it to 32 bits */ context->Length_Low &= 0xFFFFFFFF; if (context->Length_Low == 0) { context->Length_High++; /* Force it to 32 bits */ context->Length_High &= 0xFFFFFFFF; if (context->Length_High == 0) { /* Message is too long */ context->Corrupted = 1; } } if (context->Message_Block_Index == 64) SHA1ProcessMessageBlock(context); message_array++; } } /* * SHA1ProcessMessageBlock * * Description: * This function will process the next 512 bits of the message * stored in the Message_Block array. * * Parameters: * None. * * Returns: * Nothing. * * Comments: * Many of the variable names in the SHAContext, especially the * single character names, were used because those were the names * used in the publication. * * */ void SHA1ProcessMessageBlock(SHA1Context *context) { const unsigned K[] = /* Constants defined in SHA-1 */ { 0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xCA62C1D6 }; int t; /* Loop counter */ unsigned temp; /* Temporary word value */ unsigned W[80]; /* Word sequence */ unsigned A, B, C, D, E; /* Word buffers */ /* * Initialize the first 16 words in the array W */ for(t = 0; t < 16; t++) { W[t] = ((unsigned) context->Message_Block[t * 4]) << 24; W[t] |= ((unsigned) context->Message_Block[t * 4 + 1]) << 16; W[t] |= ((unsigned) context->Message_Block[t * 4 + 2]) << 8; W[t] |= ((unsigned) context->Message_Block[t * 4 + 3]); } for(t = 16; t < 80; t++) { W[t] = SHA1CircularShift(1,W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]); } A = context->Message_Digest[0]; B = context->Message_Digest[1]; C = context->Message_Digest[2]; D = context->Message_Digest[3]; E = context->Message_Digest[4]; for(t = 0; t < 20; t++) { temp = SHA1CircularShift(5,A) + ((B & C) | ((~B) & D)) + E + W[t] + K[0]; temp &= 0xFFFFFFFF; E = D; D = C; C = SHA1CircularShift(30,B); B = A; A = temp; } for(t = 20; t < 40; t++) { temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[1]; temp &= 0xFFFFFFFF; E = D; D = C; C = SHA1CircularShift(30,B); B = A; A = temp; } for(t = 40; t < 60; t++) { temp = SHA1CircularShift(5,A) + ((B & C) | (B & D) | (C & D)) + E + W[t] + K[2]; temp &= 0xFFFFFFFF; E = D; D = C; C = SHA1CircularShift(30,B); B = A; A = temp; } for(t = 60; t < 80; t++) { temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[3]; temp &= 0xFFFFFFFF; E = D; D = C; C = SHA1CircularShift(30,B); B = A; A = temp; } context->Message_Digest[0] = (context->Message_Digest[0] + A) & 0xFFFFFFFF; context->Message_Digest[1] = (context->Message_Digest[1] + B) & 0xFFFFFFFF; context->Message_Digest[2] = (context->Message_Digest[2] + C) & 0xFFFFFFFF; context->Message_Digest[3] = (context->Message_Digest[3] + D) & 0xFFFFFFFF; context->Message_Digest[4] = (context->Message_Digest[4] + E) & 0xFFFFFFFF; context->Message_Block_Index = 0; } /* * SHA1PadMessage * * Description: * According to the standard, the message must be padded to an even * 512 bits. The first padding bit must be a '1'. The last 64 * bits represent the length of the original message. All bits in * between should be 0. This function will pad the message * according to those rules by filling the Message_Block array * accordingly. It will also call SHA1ProcessMessageBlock() * appropriately. When it returns, it can be assumed that the * message digest has been computed. * * Parameters: * context: [in/out] * The context to pad * * Returns: * Nothing. * * Comments: * */ void SHA1PadMessage(SHA1Context *context) { /* * Check to see if the current message block is too small to hold * the initial padding bits and length. If so, we will pad the * block, process it, and then continue padding into a second * block. */ if (context->Message_Block_Index > 55) { context->Message_Block[context->Message_Block_Index++] = 0x80; while(context->Message_Block_Index < 64) context->Message_Block[context->Message_Block_Index++] = 0; SHA1ProcessMessageBlock(context); while(context->Message_Block_Index < 56) context->Message_Block[context->Message_Block_Index++] = 0; } else { context->Message_Block[context->Message_Block_Index++] = 0x80; while(context->Message_Block_Index < 56) context->Message_Block[context->Message_Block_Index++] = 0; } /* * Store the message length as the last 8 octets */ context->Message_Block[56] = (context->Length_High >> 24) & 0xFF; context->Message_Block[57] = (context->Length_High >> 16) & 0xFF; context->Message_Block[58] = (context->Length_High >> 8) & 0xFF; context->Message_Block[59] = (context->Length_High) & 0xFF; context->Message_Block[60] = (context->Length_Low >> 24) & 0xFF; context->Message_Block[61] = (context->Length_Low >> 16) & 0xFF; context->Message_Block[62] = (context->Length_Low >> 8) & 0xFF; context->Message_Block[63] = (context->Length_Low) & 0xFF; SHA1ProcessMessageBlock(context); } /* * sha.cpp * * Copyright (C) 1998, 2009 * Paul E. Jones * All Rights Reserved * ***************************************************************************** * $Id: sha.c 12 2009-06-22 19:34:25Z paulej $ ***************************************************************************** * * Description: * This utility will display the message digest (fingerprint) for * the specified file(s). * * Portability Issues: * None. */ #include #include #ifdef WIN32 #include #endif #include /*#include "sha1.h"*/ /* * Function prototype */ void usage(void); /* * main * * Description: * This is the entry point for the program * * Parameters: * argc: [in] * This is the count of arguments in the argv array * argv: [in] * This is an array of filenames for which to compute message * digests * * Returns: * Nothing. * * Comments: * */ int main(int argc, char *argv[]) { SHA1Context sha; /* SHA-1 context */ FILE *fp; /* File pointer for reading files*/ char c; /* Character read from file */ int i; /* Counter */ int reading_stdin; /* Are we reading standard in? */ int read_stdin = 0; /* Have we read stdin? */ /* * Check the program arguments and print usage information if -? * or --help is passed as the first argument. */ if (argc > 1 && (!strcmp(argv[1],"-?") || !strcmp(argv[1],"--help"))) { usage(); return 1; } /* * For each filename passed in on the command line, calculate the * SHA-1 value and display it. */ for(i = 0; i < argc; i++) { /* * We start the counter at 0 to guarantee entry into the for * loop. So if 'i' is zero, we will increment it now. If there * is no argv[1], we will use STDIN below. */ if (i == 0) i++; if (argc == 1 || !strcmp(argv[i],"-")) { #ifdef WIN32 setmode(fileno(stdin), _O_BINARY); #endif fp = stdin; reading_stdin = 1; } else { if (!(fp = fopen(argv[i],"rb"))) { fprintf(stderr, "sha: unable to open file %s\n", argv[i]); return 2; } reading_stdin = 0; } /* * We do not want to read STDIN multiple times */ if (reading_stdin) { if (read_stdin) continue; read_stdin = 1; } /* * Reset the SHA-1 context and process input */ SHA1Reset(&sha); c = fgetc(fp); while(!feof(fp)) { SHA1Input(&sha, &c, 1); c = fgetc(fp); } if (!reading_stdin) fclose(fp); if (!SHA1Result(&sha)) { fprintf(stderr, "sha: could not compute message digest for %s\n", reading_stdin?"STDIN":argv[i]); } else { printf( "%08X %08X %08X %08X %08X - %s\n", sha.Message_Digest[0], sha.Message_Digest[1], sha.Message_Digest[2], sha.Message_Digest[3], sha.Message_Digest[4], reading_stdin?"STDIN":argv[i]); } } return 0; } /* * usage * * Description: * This function will display program usage information to the * user. * * Parameters: * None. * * Returns: * Nothing. * * Comments: * */ void usage(void) { printf("usage: sha [ ...]\n"); printf("\tThis program will display the message digest\n"); printf("\tfor files using the Secure Hashing Algorithm (SHA-1).\n"); } desmume/src/libretro-common/formats/png/000700 001750 001750 00000000000 12756420131 021464 5ustar00sergiosergio000000 000000 desmume/src/libretro-common/include/string/000700 001750 001750 00000000000 12756420131 022156 5ustar00sergiosergio000000 000000 desmume/src/libretro-common/gfx/math/000700 001750 001750 00000000000 12756420131 020742 5ustar00sergiosergio000000 000000 desmume/src/libretro-common/gfx/scaler/scaler.c000664 001750 001750 00000024611 12755534123 022725 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2015 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (scaler.c). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include #include #include #include #include #include #include #include /** * scaler_alloc: * @elem_size : size of the elements to be used. * @siz : size of the image that the scaler needs to handle. * * Allocate and returns a scaler object. * * Returns: pointer to a scaler object of type 'void *' on success, * NULL in case of error. Has to be freed manually. **/ void *scaler_alloc(size_t elem_size, size_t size) { void *ptr = calloc(elem_size, size); if (!ptr) return NULL; return ptr; } /** * scaler_free: * @ptr : pointer to scaler object. * * Frees a scaler object. **/ void scaler_free(void *ptr) { if (ptr) free(ptr); } static bool allocate_frames(struct scaler_ctx *ctx) { ctx->scaled.stride = ((ctx->out_width + 7) & ~7) * sizeof(uint64_t); ctx->scaled.width = ctx->out_width; ctx->scaled.height = ctx->in_height; ctx->scaled.frame = (uint64_t*) scaler_alloc(sizeof(uint64_t), (ctx->scaled.stride * ctx->scaled.height) >> 3); if (!ctx->scaled.frame) return false; if (ctx->in_fmt != SCALER_FMT_ARGB8888) { ctx->input.stride = ((ctx->in_width + 7) & ~7) * sizeof(uint32_t); ctx->input.frame = (uint32_t*) scaler_alloc(sizeof(uint32_t), (ctx->input.stride * ctx->in_height) >> 2); if (!ctx->input.frame) return false; } if (ctx->out_fmt != SCALER_FMT_ARGB8888) { ctx->output.stride = ((ctx->out_width + 7) & ~7) * sizeof(uint32_t); ctx->output.frame = (uint32_t*) scaler_alloc(sizeof(uint32_t), (ctx->output.stride * ctx->out_height) >> 2); if (!ctx->output.frame) return false; } return true; } /** * set_direct_pix_conv: * @ctx : pointer to scaler context object. * * Bind a pixel converter callback function to the 'direct_pixconv' function pointer * of the scaler context object. * * Returns: true if a pixel converter function callback could be bound, false if not. * If false, the function callback 'direct_pixconv' is still unbound. **/ static bool set_direct_pix_conv(struct scaler_ctx *ctx) { if (ctx->in_fmt == ctx->out_fmt) { ctx->direct_pixconv = conv_copy; return true; } switch (ctx->in_fmt) { case SCALER_FMT_0RGB1555: switch (ctx->out_fmt) { case SCALER_FMT_ARGB8888: ctx->direct_pixconv = conv_0rgb1555_argb8888; break; case SCALER_FMT_RGB565: ctx->direct_pixconv = conv_0rgb1555_rgb565; break; case SCALER_FMT_BGR24: ctx->direct_pixconv = conv_0rgb1555_bgr24; break; default: break; } break; case SCALER_FMT_RGB565: switch (ctx->out_fmt) { case SCALER_FMT_ARGB8888: ctx->direct_pixconv = conv_rgb565_argb8888; break; case SCALER_FMT_BGR24: ctx->direct_pixconv = conv_rgb565_bgr24; break; case SCALER_FMT_0RGB1555: ctx->direct_pixconv = conv_rgb565_0rgb1555; break; default: break; } break; case SCALER_FMT_BGR24: switch (ctx->out_fmt) { case SCALER_FMT_ARGB8888: ctx->direct_pixconv = conv_bgr24_argb8888; break; default: break; } break; case SCALER_FMT_ARGB8888: switch (ctx->out_fmt) { case SCALER_FMT_0RGB1555: ctx->direct_pixconv = conv_argb8888_0rgb1555; break; case SCALER_FMT_BGR24: ctx->direct_pixconv = conv_argb8888_bgr24; break; case SCALER_FMT_ABGR8888: ctx->direct_pixconv = conv_argb8888_abgr8888; break; case SCALER_FMT_RGBA4444: ctx->direct_pixconv = conv_argb8888_rgba4444; break; default: break; } break; case SCALER_FMT_YUYV: switch (ctx->out_fmt) { case SCALER_FMT_ARGB8888: ctx->direct_pixconv = conv_yuyv_argb8888; break; default: break; } break; case SCALER_FMT_RGBA4444: switch (ctx->out_fmt) { case SCALER_FMT_ARGB8888: ctx->direct_pixconv = conv_rgba4444_argb8888; break; case SCALER_FMT_RGB565: ctx->direct_pixconv = conv_rgba4444_rgb565; break; default: break; } break; case SCALER_FMT_ABGR8888: /* FIXME/TODO */ break; } if (!ctx->direct_pixconv) return false; return true; } static bool set_pix_conv(struct scaler_ctx *ctx) { switch (ctx->in_fmt) { case SCALER_FMT_ARGB8888: /* No need to convert :D */ break; case SCALER_FMT_0RGB1555: ctx->in_pixconv = conv_0rgb1555_argb8888; break; case SCALER_FMT_RGB565: ctx->in_pixconv = conv_rgb565_argb8888; break; case SCALER_FMT_BGR24: ctx->in_pixconv = conv_bgr24_argb8888; break; case SCALER_FMT_RGBA4444: ctx->in_pixconv = conv_rgba4444_argb8888; break; default: return false; } switch (ctx->out_fmt) { case SCALER_FMT_ARGB8888: /* No need to convert :D */ break; case SCALER_FMT_RGBA4444: ctx->out_pixconv = conv_argb8888_rgba4444; break; case SCALER_FMT_0RGB1555: ctx->out_pixconv = conv_argb8888_0rgb1555; break; case SCALER_FMT_BGR24: ctx->out_pixconv = conv_argb8888_bgr24; break; default: return false; } return true; } bool scaler_ctx_gen_filter(struct scaler_ctx *ctx) { scaler_ctx_gen_reset(ctx); if (ctx->in_width == ctx->out_width && ctx->in_height == ctx->out_height) ctx->unscaled = true; /* Only pixel format conversion ... */ else { ctx->scaler_horiz = scaler_argb8888_horiz; ctx->scaler_vert = scaler_argb8888_vert; ctx->unscaled = false; } ctx->scaler_special = NULL; if (!allocate_frames(ctx)) return false; if (ctx->unscaled) { if (!set_direct_pix_conv(ctx)) return false; } else { if (!set_pix_conv(ctx)) return false; } if (!ctx->unscaled && !scaler_gen_filter(ctx)) return false; return true; } void scaler_ctx_gen_reset(struct scaler_ctx *ctx) { scaler_free(ctx->horiz.filter); scaler_free(ctx->horiz.filter_pos); scaler_free(ctx->vert.filter); scaler_free(ctx->vert.filter_pos); scaler_free(ctx->scaled.frame); scaler_free(ctx->input.frame); scaler_free(ctx->output.frame); memset(&ctx->horiz, 0, sizeof(ctx->horiz)); memset(&ctx->vert, 0, sizeof(ctx->vert)); memset(&ctx->scaled, 0, sizeof(ctx->scaled)); memset(&ctx->input, 0, sizeof(ctx->input)); memset(&ctx->output, 0, sizeof(ctx->output)); } /** * scaler_ctx_scale: * @ctx : pointer to scaler context object. * @output : pointer to output image. * @input : pointer to input image. * * Scales an input image to an output image. **/ void scaler_ctx_scale(struct scaler_ctx *ctx, void *output, const void *input) { const void *input_frame = input; void *output_frame = output; int input_stride = ctx->in_stride; int output_stride = ctx->out_stride; if (ctx->unscaled) { /* Just perform straight pixel conversion. */ ctx->direct_pixconv(output, input, ctx->out_width, ctx->out_height, ctx->out_stride, ctx->in_stride); return; } if (ctx->in_fmt != SCALER_FMT_ARGB8888) { ctx->in_pixconv(ctx->input.frame, input, ctx->in_width, ctx->in_height, ctx->input.stride, ctx->in_stride); input_frame = ctx->input.frame; input_stride = ctx->input.stride; } if (ctx->out_fmt != SCALER_FMT_ARGB8888) { output_frame = ctx->output.frame; output_stride = ctx->output.stride; } if (ctx->scaler_special) { /* Take some special, and (hopefully) more optimized path. */ ctx->scaler_special(ctx, output_frame, input_frame, ctx->out_width, ctx->out_height, ctx->in_width, ctx->in_height, output_stride, input_stride); } else { /* Take generic filter path. */ if (ctx->scaler_horiz) ctx->scaler_horiz(ctx, input_frame, input_stride); if (ctx->scaler_vert) ctx->scaler_vert (ctx, output, output_stride); } if (ctx->out_fmt != SCALER_FMT_ARGB8888) ctx->out_pixconv(output, ctx->output.frame, ctx->out_width, ctx->out_height, ctx->out_stride, ctx->output.stride); } desmume/src/addons/slot2_paddle.cpp000664 001750 001750 00000007625 12755534123 020501 0ustar00sergiosergio000000 000000 /* Copyright (C) 2011-2015 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the this software. If not, see . */ /* this device seems to have a 12bit value (like 20.12 fixed point.. get it?) located at 0x0A000000 clockwise = right = increases. it returns the correct little endian bytes through byte reads. through halfword reads, it returns the LSB twice through full word reads, it returns the LSB four times. after that everything is 0x00. if the slot2 timings are wrong, then this device will return glitchy or 0xFF output. so this emulation code will attempt to validate that. arkanoid was setting REG_EXMEMCNT = 0x082F the rom returns 0xEFFF for all addresses and should be used to detect this device writing any byte to SRAM or writing any halfword/word to rom results in a reset or some kind of recalibrate the resulting value may be 0x000,0x001, or 0xFFF. seems mostly random, though once it is reset, resetting again won't change it. you must wait until the paddle has been moved. conclusion: The emulation in all the handling of erroneous cases is not perfect, and some other users of the paddle (do any other games use it?) maybe legally configure the paddle differently, which could be rejected here; in which case this code will need finetuning */ #include #include "../slot2.h" #include "../NDSSystem.h" class Slot2_Paddle : public ISlot2Interface { private: void calibrate() { nds.paddle = 0; } bool Validate(u32 procnum, bool rom) { if(rom) return ValidateSlot2Access(procnum, 0, 0, 0, -1); else return ValidateSlot2Access(procnum, 18, 0, 0, 1); } public: virtual Slot2Info const* info() { static Slot2InfoSimple info("Paddle Controller", "Taito Paddle Controller", 0x07); return &info; } virtual void writeByte(u8 PROCNUM, u32 addr, u8 val) { if (addr < 0x0A000000) calibrate(); } virtual void writeWord(u8 PROCNUM, u32 addr, u16 val) { if (addr < 0x0A000000) calibrate(); } virtual void writeLong(u8 PROCNUM, u32 addr, u32 val) { if (addr < 0x0A000000) calibrate(); } virtual u8 readByte(u8 PROCNUM, u32 addr) { //printf("paddle: read 08 at 0x%08X\n", addr); if (!Validate(PROCNUM, (addr < 0x0A000000))) return 0xFF; if (addr < 0x0A000000) return (addr & 1)?0xFF:0xEF; if (addr == 0x0A000000) return (nds.paddle & 0xFF); if (addr == 0x0A000001) return ((nds.paddle >> 8) & 0x0F); return 0x00; } virtual u16 readWord(u8 PROCNUM, u32 addr) { //printf("paddle: read 16 at 0x%08X\n", addr); if (!Validate(PROCNUM, (addr < 0x0A000000))) return 0xFFFF; if (addr < 0x0A000000) return 0xEFFF; if (addr == 0x0A000000) { u8 val = (nds.paddle & 0xFF); return (val | (val << 8)); } return 0x0000; } virtual u32 readLong(u8 PROCNUM, u32 addr) { //printf("paddle: read 32 at 0x%08X\n", addr); if (!Validate(PROCNUM, (addr < 0x0A000000))) return 0xFFFFFFFF; if (addr < 0x0A000000) return 0xEFFFEFFF; if (addr == 0x0A000000) { u8 val = (nds.paddle & 0xFF); return (val | (val << 8) | (val << 16) | (val << 24)); } return 0x00000000; } }; u16 Paddle_GetValue() { return nds.paddle; } void Paddle_SetValue(u16 theValue) { nds.paddle = theValue; } ISlot2Interface* construct_Slot2_Paddle() { return new Slot2_Paddle(); } desmume/src/addons/slot1comp_protocol.h000664 001750 001750 00000007200 12755534123 021421 0ustar00sergiosergio000000 000000 /* Copyright (C) 2013-2015 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the this software. If not, see . */ //this file contains the components used for emulating standard gamecard protocol. //this largely means the complex boot-up process. //i think there's no reason why proprietary cards couldn't speak any protocol they wish, as long as they didn't mind being unbootable. //TODO - could this be refactored into a base class? that's probably more reasonable. but we've gone with this modular mix-in architecture so... not yet. #ifndef _SLOT1COMP_PROTOCOL_H #define _SLOT1COMP_PROTOCOL_H #include "../types.h" #include "../MMU.h" class EMUFILE; enum eSlot1Operation { //---------- //RAW mode operations //before encrypted communications can be established, some values from the rom header must be read. //this is the only way to read the header, actually, since the only reading commands available to games (after KEY2 mode is set) are eSlot1Operation_00_ReadHeader_Unencrypted, //it's not clear why this exists eSlot1Operation_9F_Dummy, eSlot1Operation_90_ChipID, //---------- //---------- //KEY1 mode operations eSlot1Operation_1x_ChipID, eSlot1Operation_2x_SecureAreaLoad, //---------- //---------- //NORMAL mode operations //the main rom data reading command eSlot1Operation_B7_Read, eSlot1Operation_B8_ChipID, //---------- eSlot1Operation_Unknown }; class ISlot1Comp_Protocol_Client { public: virtual void slot1client_startOperation(eSlot1Operation operation) {} virtual u32 slot1client_read_GCDATAIN(eSlot1Operation operation) = 0; virtual void slot1client_write_GCDATAIN(eSlot1Operation operation, u32 val) {} }; class Slot1Comp_Protocol { public: void savestate(EMUFILE* os); void loadstate(EMUFILE* is); //set some kind of protocol/hardware reset state void reset(ISlot1Comp_Protocol_Client* client); //signals from the GC bus void write_command(GC_Command command); void write_GCDATAIN(u8 PROCNUM, u32 val); u32 read_GCDATAIN(u8 PROCNUM); //helpers for write_command() void write_command_RAW(GC_Command command); void write_command_KEY1(GC_Command command); void write_command_NORMAL(GC_Command command); //operations not related to obscurities of the protocol or otherwise unknown are passed through to the client here ISlot1Comp_Protocol_Client* client; //--state-- //the major operational mode. the protocol shifts modes and interprets commands into operations differently depending on the mode eCardMode mode; //the current operational state eSlot1Operation operation; //the command we're currently crunching on GC_Command command; //most operations are defined in terms of returning a series of bytes //the meaning of these varies by operation. they are provided publicly as a service to clients u32 address; s32 length, delay; //the expected length and delay of this state //chipId which should be returned by the various chipId commands u32 chipId; //gameCode used by the protocol KEY1 crypto u32 gameCode; }; #endif //_SLOT1COMP_PROTOCOL_Hdesmume/src/libretro-common/include/gfx/math/matrix_3x3.h000664 001750 001750 00000006720 12755534123 024566 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2016 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (matrix_3x3.h). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef __LIBRETRO_SDK_GFX_MATH_MATRIX_3X3_H__ #define __LIBRETRO_SDK_GFX_MATH_MATRIX_3X3_H__ #include typedef struct math_matrix_3x3 { float data[9]; } math_matrix_3x3; #define MAT_ELEM_3X3(mat, r, c) ((mat).data[3 * (r) + (c)]) void matrix_3x3_inits(math_matrix_3x3 *mat, const float n11, const float n12, const float n13, const float n21, const float n22, const float n23, const float n31, const float n32, const float n33); void matrix_3x3_identity(math_matrix_3x3 *mat); void matrix_3x3_transpose(math_matrix_3x3 *out, const math_matrix_3x3 *in); void matrix_3x3_multiply(math_matrix_3x3 *out, const math_matrix_3x3 *a, const math_matrix_3x3 *b); void matrix_3x3_divide_scalar(math_matrix_3x3 *mat, const float s); float matrix_3x3_determinant(const math_matrix_3x3 *mat); void matrix_3x3_adjoint(math_matrix_3x3 *mat); bool matrix_3x3_invert(math_matrix_3x3 *mat); bool matrix_3x3_square_to_quad(const float dx0, const float dy0, const float dx1, const float dy1, const float dx3, const float dy3, const float dx2, const float dy2, math_matrix_3x3 *mat); bool matrix_3x3_quad_to_square(const float sx0, const float sy0, const float sx1, const float sy1, const float sx2, const float sy2, const float sx3, const float sy3, math_matrix_3x3 *mat); bool matrix_3x3_quad_to_quad(const float dx0, const float dy0, const float dx1, const float dy1, const float dx2, const float dy2, const float dx3, const float dy3, const float sx0, const float sy0, const float sx1, const float sy1, const float sx2, const float sy2, const float sx3, const float sy3, math_matrix_3x3 *mat); #endif desmume/src/utils/AsmJit/core/compileritem.h000664 001750 001750 00000044530 12755534123 022266 0ustar00sergiosergio000000 000000 // [AsmJit] // Complete JIT Assembler for C++ Language. // // [License] // Zlib - See COPYING file in this package. // [Guard] #ifndef _ASMJIT_CORE_COMPILERITEM_H #define _ASMJIT_CORE_COMPILERITEM_H // [Dependencies - AsmJit] #include "../core/compiler.h" // [Api-Begin] #include "../core/apibegin.h" namespace AsmJit { // ============================================================================ // [AsmJit::CompilerItem] // ============================================================================ //! @brief Compiler item. //! //! @ref CompilerItem represents items generated by compiler by calling its //! methods to build functions, instruction stream, bind labels, etc... Each //! item contains its type information and virtual methods which are called at //! various compilation steps. struct CompilerItem { ASMJIT_NO_COPY(CompilerItem) // -------------------------------------------------------------------------- // [Construction / Destruction] // -------------------------------------------------------------------------- //! @brief Create new @ref CompilerItem. //! //! @note Always use @ref Compiler to create an item! ASMJIT_API CompilerItem(Compiler* compiler, uint32_t type); //! @brief Destroy @ref CompilerItem. //! //! @note @ref Compiler keeps links into all items so it can destroy them //! when code generation finished or in the case that @ref Compiler was //! destroyed early (for example if an error happened). Never destroy items //! manually! ASMJIT_API virtual ~CompilerItem(); // -------------------------------------------------------------------------- // [Accessors] // -------------------------------------------------------------------------- //! @brief Get associated compiler instance. inline Compiler* getCompiler() const { return _compiler; } //! @brief Get previous item in the compiler stream. inline CompilerItem* getPrev() const { return _prev; } //! @brief Get next item in the compiler stream. inline CompilerItem* getNext() const { return _next; } //! @brief Get comment string. inline const char* getComment() const { return _comment; } //! @brief Get type of item, see @ref kCompilerItem. inline uint32_t getType() const { return _type; } //! @brief Get whether the item was translated. inline bool isTranslated() const { return _isTranslated; } //! @brief Get whether the item is unreachable. inline bool isUnreachable() const { return _isUnreachable; } //! @brief Get the item offset in the compiler stream. //! //! The offset is not byte offset, each item increments offset by 1 and this //! value is then used by register allocator. The offset is set by compiler //! by the register allocator, don't use it in your code. inline uint32_t getOffset() const { return _offset; } // -------------------------------------------------------------------------- // [Interface] // -------------------------------------------------------------------------- //! @brief Step 1. Extract item variables, update statistics, ... ASMJIT_API virtual void prepare(CompilerContext& cc); //! @brief Step 2. Translate instruction, alloc variables, ... ASMJIT_API virtual CompilerItem* translate(CompilerContext& cc); //! @brief Step 3. Emit to @c Assembler. ASMJIT_API virtual void emit(Assembler& a); //! @brief Step 4. Last post step (verify, add data, etc). ASMJIT_API virtual void post(Assembler& a); // -------------------------------------------------------------------------- // [Misc] // -------------------------------------------------------------------------- //! @brief Get maximum size of of this when serialized into @ref Assembler //! item in bytes. ASMJIT_API virtual int getMaxSize() const; //! @brief Try to unuse the variable @a. //! //! Returns @c true only if the variable will be unused by the instruction, //! otherwise @c false is returned. ASMJIT_API virtual bool _tryUnuseVar(CompilerVar* v); // -------------------------------------------------------------------------- // [Comment] // -------------------------------------------------------------------------- //! @brief Set comment string to @a str. ASMJIT_API void setComment(const char* str); //! @brief Format comment string using @a fmt string and variable argument list. ASMJIT_API void formatComment(const char* fmt, ...); // -------------------------------------------------------------------------- // [Protected] // -------------------------------------------------------------------------- protected: //! @brief Mark item as translated and return next. inline CompilerItem* translated() { ASMJIT_ASSERT(_isTranslated == false); _isTranslated = true; return _next; } // -------------------------------------------------------------------------- // [Members] // -------------------------------------------------------------------------- public: //! @brief Compiler which owns this item. Compiler* _compiler; //! @brief Previous item. CompilerItem* _prev; //! @brief Next item. CompilerItem* _next; //! @brief Inline comment string, initially set to NULL. const char* _comment; //! @brief Type of the item, see @ref kCompilerItem. uint32_t _type : 8; //! @brief Whether the item was translated, see @c translate(). uint32_t _isTranslated : 1; //! @brief Whether the item is unreachable. uint32_t _isUnreachable : 1; //! @brief Reserved for future use. uint32_t _reserved : 22; //! @brief Stream offset (not byte-offset). uint32_t _offset; }; // ============================================================================ // [AsmJit::CompilerMark] // ============================================================================ //! @brief Compiler mark item. //! //! This item does nothing and it's only used by @ref Compiler to mark some //! specific location in the compiler stream. struct CompilerMark : public CompilerItem { ASMJIT_NO_COPY(CompilerMark) // -------------------------------------------------------------------------- // [Construction / Destruction] // -------------------------------------------------------------------------- //! @brief Create a new @ref CompilerMark instance. ASMJIT_API CompilerMark(Compiler* compiler); //! @brief Destroy the @ref CompilerMark instance. ASMJIT_API virtual ~CompilerMark(); // -------------------------------------------------------------------------- // [Misc] // -------------------------------------------------------------------------- ASMJIT_API virtual int getMaxSize() const; }; // ============================================================================ // [AsmJit::CompilerComment] // ============================================================================ //! @brief Compiler comment item. //! //! Comments allows to comment your assembler stream for better debugging //! and visualization. Comments are usually ignored in release builds unless //! the logger is present. struct CompilerComment : public CompilerItem { ASMJIT_NO_COPY(CompilerComment) // -------------------------------------------------------------------------- // [Construction / Destruction] // -------------------------------------------------------------------------- //! @brief Create a new @ref CompilerComment instance. ASMJIT_API CompilerComment(Compiler* compiler, const char* comment = NULL); //! @brief Destroy the @ref CompilerComment instance. ASMJIT_API virtual ~CompilerComment(); // -------------------------------------------------------------------------- // [Interface] // -------------------------------------------------------------------------- ASMJIT_API virtual void emit(Assembler& a); // -------------------------------------------------------------------------- // [Misc] // -------------------------------------------------------------------------- ASMJIT_API virtual int getMaxSize() const; }; // ============================================================================ // [AsmJit::CompilerEmbed] // ============================================================================ //! @brief Compiler embed item. //! //! Embed item is used to embed data into final assembler stream. The data is //! considered to be RAW, there is no analysis. struct CompilerEmbed : public CompilerItem { ASMJIT_NO_COPY(CompilerEmbed) // -------------------------------------------------------------------------- // [Construction / Destruction] // -------------------------------------------------------------------------- //! @brief Create a new @ref CompilerEmbed instance. ASMJIT_API CompilerEmbed(Compiler* compiler, const void* data, size_t length); //! @brief Destroy the @ref CompilerEmbed instance. ASMJIT_API virtual ~CompilerEmbed(); // -------------------------------------------------------------------------- // [Accessors] // -------------------------------------------------------------------------- //! @brief Get pointer to embedded data. uint8_t* getData() const { return const_cast(_data); } //! @brief Get length of embedded data. size_t getLength() const { return _length; } // -------------------------------------------------------------------------- // [Interface] // -------------------------------------------------------------------------- ASMJIT_API virtual void emit(Assembler& a); // -------------------------------------------------------------------------- // [Misc] // -------------------------------------------------------------------------- ASMJIT_API virtual int getMaxSize() const; // -------------------------------------------------------------------------- // [Members] // -------------------------------------------------------------------------- //! @brief Data length. size_t _length; //! @brief Data buffer (that will be embedded to the assembler stream). uint8_t _data[sizeof(void*)]; }; // ============================================================================ // [AsmJit::CompilerAlign] // ============================================================================ //! @brief Compiler align item. struct CompilerAlign : public CompilerItem { ASMJIT_NO_COPY(CompilerAlign) // -------------------------------------------------------------------------- // [Construction / Destruction] // -------------------------------------------------------------------------- //! @brief Create a new @ref CompilerAlign instance. ASMJIT_API CompilerAlign(Compiler* compiler, uint32_t size = 0); //! @brief Destroy the @ref CompilerAlign instance. ASMJIT_API virtual ~CompilerAlign(); // -------------------------------------------------------------------------- // [Accessors] // -------------------------------------------------------------------------- //! @brief Get align size in bytes. inline uint32_t getSize() const { return _size; } //! @brief Set align size in bytes to @a size. inline void setSize(uint32_t size) { _size = size; } // -------------------------------------------------------------------------- // [Misc] // -------------------------------------------------------------------------- ASMJIT_API virtual int getMaxSize() const; // -------------------------------------------------------------------------- // [Members] // -------------------------------------------------------------------------- //! @brief Align size. uint32_t _size; }; // ============================================================================ // [AsmJit::CompilerHint] // ============================================================================ //! @brief Compiler variable hint item. struct CompilerHint : public CompilerItem { ASMJIT_NO_COPY(CompilerHint) // -------------------------------------------------------------------------- // [Construction / Destruction] // -------------------------------------------------------------------------- //! @brief Create a new @ref CompilerHint instance. ASMJIT_API CompilerHint(Compiler* compiler, CompilerVar* var, uint32_t hintId, uint32_t hintValue); //! @brief Destroy the @ref CompilerHint instance. ASMJIT_API virtual ~CompilerHint(); // -------------------------------------------------------------------------- // [Accessors] // -------------------------------------------------------------------------- //! @brief Get variable. inline CompilerVar* getVar() const { return _var; } //! @brief Get hint it (see @ref kVarHint). inline uint32_t getHintId() const { return _hintId; } //! @brief Set hint it (see @ref kVarHint). inline void setHintId(uint32_t hintId) { _hintId = hintId; } //! @brief Get hint value. inline uint32_t getHintValue() const { return _hintValue; } //! @brief Set hint value. inline void setHintValue(uint32_t hintValue) { _hintValue = hintValue; } // -------------------------------------------------------------------------- // [Members] // -------------------------------------------------------------------------- //! @brief Variable. CompilerVar* _var; //! @brief Variable hint id. uint32_t _hintId; //! @brief Variable hint value. uint32_t _hintValue; }; // ============================================================================ // [AsmJit::CompilerTarget] // ============================================================================ //! @brief Compiler target item. struct CompilerTarget : public CompilerItem { ASMJIT_NO_COPY(CompilerTarget) // -------------------------------------------------------------------------- // [Construction / Destruction] // -------------------------------------------------------------------------- //! @brief Create a new @ref CompilerTarget instance. ASMJIT_API CompilerTarget(Compiler* compiler, const Label& target); //! @brief Destroy the @ref CompilerTarget instance. ASMJIT_API virtual ~CompilerTarget(); // -------------------------------------------------------------------------- // [Accessors] // -------------------------------------------------------------------------- //! @brief Return label bound to this target. inline const Label& getLabel() const { return _label; } //! @brief Get first jmp instruction. inline CompilerInst* getFrom() const { return _from; } //! @brief Get register allocator state for this target. inline CompilerState* getState() const { return _state; } //! @brief Get number of jumps to this target. inline uint32_t getJumpsCount() const { return _jumpsCount; } // -------------------------------------------------------------------------- // [Misc] // -------------------------------------------------------------------------- ASMJIT_API virtual int getMaxSize() const; // -------------------------------------------------------------------------- // [Members] // -------------------------------------------------------------------------- //! @brief Label. Label _label; //! @brief First jump instruction that points to this target (label). CompilerInst* _from; //! @brief State at this location. CompilerState* _state; //! @brief Count of jumps here. uint32_t _jumpsCount; }; // ============================================================================ // [AsmJit::CompilerInst] // ============================================================================ //! @brief Compiler instruction item. struct CompilerInst : public CompilerItem { ASMJIT_NO_COPY(CompilerInst) // -------------------------------------------------------------------------- // [Construction / Destruction] // -------------------------------------------------------------------------- //! @brief Create a new @ref CompilerInst instance. ASMJIT_API CompilerInst(Compiler* compiler, uint32_t code, Operand* opData, uint32_t opCount); //! @brief Destroy the @ref CompilerInst instance. ASMJIT_API virtual ~CompilerInst(); // -------------------------------------------------------------------------- // [Accessors] // -------------------------------------------------------------------------- //! @brief Get instruction code, see @c kInstCode. inline uint32_t getCode() const { return _code; } //! @brief Set instruction code to @a code. //! //! Please do not modify instruction code if you are not know what you are //! doing. Incorrect instruction code or operands can raise assertion() at //! runtime. inline void setCode(uint32_t code) { _code = code; } //! @brief Get emit options (compiler specific). inline uint32_t getEmitOptions() const { return _emitOptions; } //! @brief Get instruction flags (compiler specific). inline uint32_t getInstFlags() const { return _instFlags; } //! @brief Get whether the instruction has flag @a flag. inline bool hasInstFlag(uint8_t flag) const { return (_instFlags & flag) != 0; } //! @brief Set instruction @a flag. inline void setInstFlag(uint8_t flag) { _instFlags |= flag; } //! @brief Clear instruction @a flag. inline void clearInstFlag(uint8_t flag) { _instFlags &= ~flag; } //! @brief Get count of operands in operands array. inline uint32_t getOperandsCount() const { return _operandsCount; } //! @brief Get count of variables in variables array. inline uint32_t getVariablesCount() const { return _variablesCount; } //! @brief Get operands array (3 operands total). inline Operand* getOperands() { return _operands; } //! @brief Get operands array (3 operands total). inline const Operand* getOperands() const { return _operands; } // -------------------------------------------------------------------------- // [GetJumpTarget] // -------------------------------------------------------------------------- //! @brief Get possible jump target. //! //! If this instruction is conditional or normal jump then return value is //! the label location (@ref CompilerTarget), otherwise the return value is //! @c NULL. ASMJIT_API virtual CompilerTarget* getJumpTarget() const; // -------------------------------------------------------------------------- // [Members] // -------------------------------------------------------------------------- //! @brief Instruction code, see @c kInstCode. uint32_t _code; //! @brief Emit options. uint8_t _emitOptions; //! @brief Instruction flags. uint8_t _instFlags; //! @brief Operands count. uint8_t _operandsCount; //! @brief Variables count. uint8_t _variablesCount; //! @brief Operands. Operand* _operands; }; } // AsmJit namespace // [Api-End] #include "../core/apiend.h" // [Guard] #endif // _ASMJIT_CORE_COMPILERITEM_H desmume/src/mc.h000664 001750 001750 00000012761 12755534123 014716 0ustar00sergiosergio000000 000000 /* Copyright (C) 2006 thoduv Copyright (C) 2006 Theo Berkau Copyright (C) 2008-2015 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the this software. If not, see . */ #ifndef __MC_H__ #define __MC_H__ #include #include #include #include "types.h" #define MAX_SAVE_TYPES 13 #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_32MBITS 0x400000 #define MC_SIZE_64MBITS 0x800000 #define MC_SIZE_128MBITS 0x1000000 #define MC_SIZE_256MBITS 0x2000000 #define MC_SIZE_512MBITS 0x4000000 class EMUFILE; class EMUFILE_FILE; //This "backup device" represents a typical retail NDS save memory accessible via AUXSPI. //It is managed as a core emulator service for historical reasons which are bad, //and possible infrastructural simplification reasons which are good. //Slot-1 devices will map their AUXSPI accesses through to the core-managed BackupDevice to access it for the running software. class BackupDevice { public: BackupDevice(); ~BackupDevice(); //signals the save system that we are in MOVIE mode. doesnt load up a rom, and never saves it. initializes for that case. void reset(); void close_rom(); void forceManualBackupType(); void reset_hardware(); std::string getFilename() { return filename; } u8 readByte(u32 addr, const u8 init); u16 readWord(u32 addr, const u16 init); u32 readLong(u32 addr, const u32 init); u8 readByte(const u8 init); u16 readWord(const u16 init); u32 readLong(const u32 init); void writeByte(u32 addr, u8 val); void writeWord(u32 addr, u16 val); void writeLong(u32 addr, u32 val); void writeByte(u8 val); void writeWord(u16 val); void writeLong(u32 val); void seek(u32 pos); void flushBackup(); u8 searchFileSaveType(u32 size); bool save_state(EMUFILE* os); bool load_state(EMUFILE* is); //commands from mmu void reset_command() { reset_command_state = true; }; u8 data_command(u8, u8); //this info was saved before the last reset (used for savestate compatibility) struct SavedInfo { u32 addr_size; } savedInfo; void ensure(u32 addr, EMUFILE_FILE *fpOut = NULL); void ensure(u32 addr, u8 val, EMUFILE_FILE *fpOut = NULL); //and these are used by old savestates void load_old_state(u32 addr_size, u8* data, u32 datasize); static u32 addr_size_for_old_save_size(int bupmem_size); static u32 addr_size_for_old_save_type(int bupmem_type); static u32 pad_up_size(u32 startSize); void raw_applyUserSettings(u32& size, bool manual = false); u32 trim(void *buf, u32 size); u32 fillLeft(u32 size); u32 get_save_duc_size(const char* filename); u32 get_save_nogba_size(const char* filename); u32 get_save_nogba_size(u8 *data); u32 get_save_raw_size(const char* filename); bool import_duc(const char* filename, u32 force_size = 0); bool import_no_gba(const char *fname, u32 force_size = 0); bool import_raw(const char* filename, u32 force_size = 0); bool export_no_gba(const char* fname); bool export_raw(const char* filename); bool no_gba_unpack(u8 *&buf, u32 &size); struct { u32 size,padSize,type,addr_size,mem_size; } info; u32 importDataSize(const char *filename); bool importData(const char *filename, u32 force_size = 0); bool exportData(const char *filename); //the value contained in memory when shipped from factory (before user program ever writes to it). more details commented elsewhere. u8 uninitializedValue; private: EMUFILE_FILE *fpMC; std::string filename; u32 fsize; int readFooter(); bool write(u8 val); u8 read(); bool saveBuffer(u8 *data, u32 size, bool _rewind, bool _truncate = false); bool write_enable; bool reset_command_state; u32 com; //persistent command actually handled u32 addr_size, addr_counter; u32 addr; u8 write_protect; std::vector data_autodetect; enum STATE { DETECTING = 0, RUNNING = 1 } state; enum MOTION_INIT_STATE { MOTION_INIT_STATE_IDLE, MOTION_INIT_STATE_RECEIVED_4, MOTION_INIT_STATE_RECEIVED_4_B, MOTION_INIT_STATE_FE, MOTION_INIT_STATE_FD, MOTION_INIT_STATE_FB }; enum MOTION_FLAG { MOTION_FLAG_NONE=0, MOTION_FLAG_ENABLED=1, MOTION_FLAG_SENSORMODE=2 }; u8 motionInitState, motionFlag; void checkReset(); void detect(); }; void backup_setManualBackupType(int type); void backup_forceManualBackupType(); struct SAVE_TYPE { const char* descr; int media_type; int size; int addr_size; }; extern const SAVE_TYPE save_types[]; #endif /*__FW_H__*/ desmume/src/utils/AsmJit/core/assert.cpp000664 001750 001750 00000001275 12755534123 021430 0ustar00sergiosergio000000 000000 // [AsmJit] // Complete JIT Assembler for C++ Language. // // [License] // Zlib - See COPYING file in this package. #define ASMJIT_EXPORTS // [Dependencies - AsmJit] #include "../core/assert.h" // [Api-Begin] #include "../core/apibegin.h" // helpers namespace AsmJit { // ============================================================================ // [AsmJit::Assert] // ============================================================================ void assertionFailure(const char* file, int line, const char* exp) { fprintf(stderr, "*** ASSERTION FAILURE at %s (line %d)\n" "*** %s\n", file, line, exp); exit(1); } } // AsmJit namespace // [Api-End] #include "../core/apiend.h" desmume/src/emufile.cpp000664 001750 001750 00000014530 12755534123 016274 0ustar00sergiosergio000000 000000 /* The MIT License Copyright (C) 2009-2014 DeSmuME team Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #if !defined(WIN32) #include #endif #if defined(PSP) //forward declaration - PSP/Vita doesn't have this so have to bake it in int ftruncate(int fd, off_t length); #elif defined(VITA) int ftruncate(int fd, off_t length) { /* TODO/FIXME - can't be bothered to implement this right now - doesn't seem to matter either */ } #endif #include "emufile.h" #include bool EMUFILE::readAllBytes(std::vector* dstbuf, const std::string& fname) { EMUFILE_FILE file(fname.c_str(),"rb"); if(file.fail()) return false; int size = file.size(); dstbuf->resize(size); file.fread(&dstbuf->at(0),size); return true; } size_t EMUFILE_MEMORY::_fread(const void *ptr, size_t bytes){ u32 remain = len-pos; u32 todo = std::min(remain,(u32)bytes); if(len==0) { failbit = true; return 0; } if(todo<=4) { u8* src = buf()+pos; u8* dst = (u8*)ptr; for(size_t i=0;ibuf(),size()); return mem; } EMUFILE* EMUFILE_MEMORY::memwrap() { return this; } void EMUFILE::write64le(u64* val) { write64le(*val); } void EMUFILE::write64le(u64 val) { val = LOCAL_TO_LE_64(val); fwrite(&val,8); } size_t EMUFILE::read64le(u64 *Bufo) { u64 buf; if(fread((char*)&buf,8) != 8) return 0; *Bufo = LE_TO_LOCAL_64(buf); return 1; } u64 EMUFILE::read64le() { u64 temp; read64le(&temp); return temp; } void EMUFILE::write32le(u32* val) { write32le(*val); } void EMUFILE::write32le(u32 val) { val = LOCAL_TO_LE_32(val); fwrite(&val,4); } size_t EMUFILE::read32le(s32* Bufo) { return read32le((u32*)Bufo); } size_t EMUFILE::read32le(u32* Bufo) { u32 buf; if(fread(&buf,4)<4) return 0; *Bufo = LE_TO_LOCAL_32(buf); return 1; } u32 EMUFILE::read32le() { u32 ret; read32le(&ret); return ret; } void EMUFILE::write16le(u16* val) { write16le(*val); } void EMUFILE::write16le(u16 val) { val = LOCAL_TO_LE_16(val); fwrite(&val,2); } size_t EMUFILE::read16le(s16* Bufo) { return read16le((u16*)Bufo); } size_t EMUFILE::read16le(u16* Bufo) { u32 buf; if(fread(&buf,2)<2) return 0; *Bufo = LE_TO_LOCAL_16(buf); return 1; } u16 EMUFILE::read16le() { u16 ret; read16le(&ret); return ret; } void EMUFILE::write8le(u8* val) { write8le(*val); } void EMUFILE::write8le(u8 val) { fwrite(&val,1); } size_t EMUFILE::read8le(u8* val) { return fread(val,1); } u8 EMUFILE::read8le() { u8 temp; fread(&temp,1); return temp; } void EMUFILE::writedouble(double* val) { write64le(double_to_u64(*val)); } void EMUFILE::writedouble(double val) { write64le(double_to_u64(val)); } double EMUFILE::readdouble() { double temp; readdouble(&temp); return temp; } size_t EMUFILE::readdouble(double* val) { u64 temp; size_t ret = read64le(&temp); *val = u64_to_double(temp); return ret; } void EMUFILE::writeMemoryStream(EMUFILE_MEMORY* ms) { s32 size = (s32)ms->size(); write32le(size); if(size>0) { std::vector* vec = ms->get_vec(); fwrite(&vec->at(0),size); } } void EMUFILE::readMemoryStream(EMUFILE_MEMORY* ms) { s32 size = read32le(); if(size != 0) { std::vector temp(size); fread(&temp[0],size); ms->fwrite(&temp[0],size); } } desmume/src/libretro-common/include/formats/rxml.h000664 001750 001750 00000006657 12755534123 023516 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2016 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (rxml.h). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef __LIBRETRO_SDK_FORMAT_RXML_H__ #define __LIBRETRO_SDK_FORMAT_RXML_H__ #include RETRO_BEGIN_DECLS /* Total NIH. Very trivial "XML" implementation for use in RetroArch. * Error checking is minimal. Invalid documents may lead to very * buggy behavior, but memory corruption should never happen. * * Only parts of standard that RetroArch cares about is supported. * Nothing more, nothing less. "Clever" XML documents will * probably break the implementation. * * Do *NOT* try to use this for anything else. You have been warned. */ typedef struct rxml_document rxml_document_t; struct rxml_attrib_node { char *attrib; char *value; struct rxml_attrib_node *next; }; struct rxml_node { char *name; char *data; struct rxml_attrib_node *attrib; struct rxml_node *children; struct rxml_node *next; /* Dummy. Used by libxml2 compat. * Is always set to 0, so XML_ELEMENT_NODE check goes through. */ int type; }; rxml_document_t *rxml_load_document(const char *path); void rxml_free_document(rxml_document_t *doc); struct rxml_node *rxml_root_node(rxml_document_t *doc); /* Drop const-correctness here to avoid warnings * when used as libxml2 compat. * xmlGetProp() returns xmlChar*, which is supposed * to be passed to xmlFree(). */ char *rxml_node_attrib(struct rxml_node *node, const char *attrib); #ifdef RXML_LIBXML2_COMPAT /* Compat for part of libxml2 that RetroArch uses. */ #define LIBXML_TEST_VERSION ((void)0) typedef char xmlChar; /* It's really unsigned char, but it doesn't matter. */ typedef struct rxml_node *xmlNodePtr; typedef void *xmlParserCtxtPtr; typedef rxml_document_t *xmlDocPtr; #define XML_ELEMENT_NODE (0) #define xmlNewParserCtxt() ((void*)-1) #define xmlCtxtReadFile(ctx, path, a, b) rxml_load_document(path) #define xmlGetProp(node, prop) rxml_node_attrib(node, prop) #define xmlFree(p) ((void)0) #define xmlNodeGetContent(node) (node->data) #define xmlDocGetRootElement(doc) rxml_root_node(doc) #define xmlFreeDoc(doc) rxml_free_document(doc) #define xmlFreeParserCtxt(ctx) ((void)0) #endif RETRO_END_DECLS #endif desmume/src/GPU.h000664 001750 001750 00000105355 12755534123 014754 0ustar00sergiosergio000000 000000 /* Copyright (C) 2006 yopyop Copyright (C) 2006-2007 Theo Berkau Copyright (C) 2007 shash Copyright (C) 2009-2015 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the this software. If not, see . */ #ifndef GPU_H #define GPU_H #include #include #include "types.h" #ifdef ENABLE_SSE2 #include #endif class EMUFILE; struct MMU_struct; //#undef FORCEINLINE //#define FORCEINLINE #define GPU_FRAMEBUFFER_NATIVE_WIDTH 256 #define GPU_FRAMEBUFFER_NATIVE_HEIGHT 192 #define GPU_VRAM_BLOCK_LINES 256 void gpu_savestate(EMUFILE* os); bool gpu_loadstate(EMUFILE* is, int size); /******************************************************************************* this structure is for display control, it holds flags for general display *******************************************************************************/ #ifdef MSB_FIRST 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_mapping: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_mapping: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 union FragmentColor { u32 color; struct { u8 r,g,b,a; }; }; typedef union { struct _DISPCNT bits; u32 val; } DISPCNT; #define BGxENABLED(cnt,num) ((num<8)? ((cnt.val>>8) & num):0) enum BlendFunc { NoBlend, Blend, Increase, Decrease }; /******************************************************************************* 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 MSB_FIRST 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 MSB_FIRST 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 MSB_FIRST 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 { enum CAPX { _128, _256 } capx; u32 val; BOOL enabled; u8 EVA; u8 EVB; u8 writeBlock; u8 writeOffset; u16 capy; u8 srcA; u8 srcB; u8 readBlock; u8 readOffset; u8 capSrc; } ; /******************************************************************************* 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 ; enum GPUEngineID { GPUEngineID_Main = 0, GPUEngineID_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 #define ADDRESS_STEP_128KB 0x20000 #define ADDRESS_STEP_256KB 0x40000 #define ADDRESS_STEP_512KB 0x80000 #define ADDRESS_MASK_256KB (ADDRESS_STEP_256KB-1) #ifdef MSB_FIRST 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 { u32 Fraction:8; s32 Integer:20; u32 pad: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 MSB_FIRST 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; // (00: Normal, 01: Transparent, 10: Object window, 11: Bitmap) enum GPU_OBJ_MODE { GPU_OBJ_MODE_Normal = 0, GPU_OBJ_MODE_Transparent = 1, GPU_OBJ_MODE_Window = 2, GPU_OBJ_MODE_Bitmap = 3 }; typedef union { u16 attr[4]; struct { #ifdef MSB_FIRST //attr0 unsigned Shape:2; unsigned Depth:1; unsigned Mosaic:1; unsigned Mode:2; unsigned RotScale:2; unsigned Y:8; //attr1 unsigned Size:2; unsigned VFlip:1; unsigned HFlip:1; unsigned RotScalIndex:3; signed X:9; //attr2 unsigned PaletteIndex:4; unsigned Priority:2; unsigned TileIndex:10; //attr3 unsigned attr3:16; // Whenever this is used, you will need to explicitly convert endianness. #else //attr0 unsigned Y:8; unsigned RotScale:2; unsigned Mode:2; unsigned Mosaic:1; unsigned Depth:1; unsigned Shape:2; //attr1 signed X:9; unsigned RotScalIndex:3; unsigned HFlip:1; unsigned VFlip:1; unsigned Size:2; //attr2 unsigned TileIndex:10; unsigned Priority:2; unsigned PaletteIndex:4; //attr3 unsigned attr3:16; // Whenever this is used, you will need to explicitly convert endianness. #endif }; } OAMAttributes; enum SpriteRenderMode { SpriteRenderMode_Sprite1D = 0, SpriteRenderMode_Sprite2D = 1 }; typedef struct { s16 x; s16 y; } SpriteSize; typedef u8 TBlendTable[32][32]; #define NB_PRIORITIES 4 #define NB_BG 4 //this structure holds information for rendering. typedef struct { u8 PixelsX[256]; u8 BGs[NB_BG], nbBGs; u8 pad[1]; u16 nbPixelsX; //256+8: u8 pad2[248]; //things were slower when i organized this struct this way. whatever. //u8 PixelsX[256]; //int BGs[NB_BG], nbBGs; //int nbPixelsX; ////<-- 256 + 24 //u8 pad2[256-24]; } itemsForPriority_t; #define MMU_ABG 0x06000000 #define MMU_BBG 0x06200000 #define MMU_AOBJ 0x06400000 #define MMU_BOBJ 0x06600000 #define MMU_LCDC 0x06800000 enum GPULayerID { GPULayerID_BG0 = 0, GPULayerID_BG1 = 1, GPULayerID_BG2 = 2, GPULayerID_BG3 = 3, GPULayerID_OBJ = 4, GPULayerID_None = 5 }; enum BGType { BGType_Invalid = 0, BGType_Text = 1, BGType_Affine = 2, BGType_Large8bpp = 3, BGType_AffineExt = 4, BGType_AffineExt_256x16 = 5, BGType_AffineExt_256x1 = 6, BGType_AffineExt_Direct = 7 }; enum GPUDisplayMode { GPUDisplayMode_Off = 0, GPUDisplayMode_Normal = 1, GPUDisplayMode_VRAM = 2, GPUDisplayMode_MainMemory = 3 }; enum GPUMasterBrightMode { GPUMasterBrightMode_Disable = 0, GPUMasterBrightMode_Up = 1, GPUMasterBrightMode_Down = 2, GPUMasterBrightMode_Reserved = 3 }; enum GPULayerType { GPULayerType_3D = 0, GPULayerType_BG = 1, GPULayerType_OBJ = 2 }; enum NDSDisplayID { NDSDisplayID_Main = 0, NDSDisplayID_Touch = 1 }; typedef struct { u8 blockIndexDisplayVRAM; bool isBlockUsed[4]; } VRAM3DUsageProperties; typedef struct { bool isCustomSizeRequested; // true - The user requested a custom size; false - The user requested the native size size_t customWidth; // The custom buffer width, measured in pixels size_t customHeight; // The custom buffer height, measured in pixels u16 *masterCustomBuffer; // Pointer to the head of the master custom buffer. u16 *masterNativeBuffer; // Pointer to the head of the master native buffer. u16 *customBuffer[2]; // Pointer to a display's custom size framebuffer u16 *nativeBuffer[2]; // Pointer to a display's native size framebuffer bool didPerformCustomRender[2]; // true - The display performed a custom render; false - The display performed a native render size_t renderedWidth[2]; // The display rendered at this width, measured in pixels size_t renderedHeight[2]; // The display rendered at this height, measured in pixels u16 *renderedBuffer[2]; // The display rendered to this buffer } NDSDisplayInfo; #define VRAM_NO_3D_USAGE 0xFF class GPUEngineBase { protected: static CACHE_ALIGN u16 _fadeInColors[17][0x8000]; static CACHE_ALIGN u16 _fadeOutColors[17][0x8000]; static CACHE_ALIGN u8 _blendTable555[17][17][32][32]; static const CACHE_ALIGN SpriteSize _sprSizeTab[4][4]; static const CACHE_ALIGN BGType _mode2type[8][4]; static const CACHE_ALIGN u16 _sizeTab[8][4][2]; static const CACHE_ALIGN u8 _winEmpty[GPU_FRAMEBUFFER_NATIVE_WIDTH]; static struct MosaicLookup { struct TableEntry { u8 begin, trunc; } table[16][256]; MosaicLookup() { for(int m=0;m<16;m++) for(int i=0;i<256;i++) { int mosaic = m+1; TableEntry &te = table[m][i]; te.begin = (i%mosaic==0); te.trunc = i/mosaic*mosaic; } } TableEntry *width, *height; int widthValue, heightValue; } _mosaicLookup; CACHE_ALIGN u16 _sprColor[GPU_FRAMEBUFFER_NATIVE_WIDTH]; CACHE_ALIGN u8 _sprAlpha[GPU_FRAMEBUFFER_NATIVE_WIDTH]; CACHE_ALIGN u8 _sprType[GPU_FRAMEBUFFER_NATIVE_WIDTH]; CACHE_ALIGN u8 _sprPrio[GPU_FRAMEBUFFER_NATIVE_WIDTH]; CACHE_ALIGN u8 _sprWin[GPU_FRAMEBUFFER_NATIVE_WIDTH]; bool _enableLayer[5]; itemsForPriority_t _itemsForPriority[NB_PRIORITIES]; struct MosaicColor { u16 bg[4][256]; struct Obj { u16 color; u8 alpha; u8 opaque; } obj[256]; } _mosaicColors; GPUEngineID _engineID; u8 _bgPrio[5]; bool _bg0HasHighestPrio; OAMAttributes *_oamList; u32 _sprMem; u8 _sprBoundary; u8 _sprBMPBoundary; u8 _sprBMPMode; u32 _sprEnable; u16 *_currentFadeInColors; u16 *_currentFadeOutColors; bool _blend1; bool _blend2[8]; TBlendTable *_blendTable; u32 _BG_bmp_large_ram[4]; u32 _BG_bmp_ram[4]; u32 _BG_tile_ram[4]; u32 _BG_map_ram[4]; BGType _BGTypes[4]; GPUDisplayMode _dispMode; u8 _vramBlock; CACHE_ALIGN u8 _sprNum[256]; CACHE_ALIGN u8 _h_win[2][GPU_FRAMEBUFFER_NATIVE_WIDTH]; const u8 *_curr_win[2]; NDSDisplayID _targetDisplayID; u16 *_VRAMaddrNative; u16 *_VRAMaddrCustom; bool _curr_mosaic_enabled; int _finalColorBckFuncID; int _finalColor3DFuncID; int _finalColorSpriteFuncID; SpriteRenderMode _spriteRenderMode; u8 *_bgPixels; u8 _WIN0H0; u8 _WIN0H1; u8 _WIN0V0; u8 _WIN0V1; u8 _WIN1H0; u8 _WIN1H1; u8 _WIN1V0; u8 _WIN1V1; u8 _WININ0; bool _WININ0_SPECIAL; u8 _WININ1; bool _WININ1_SPECIAL; u8 _WINOUT; bool _WINOUT_SPECIAL; u8 _WINOBJ; bool _WINOBJ_SPECIAL; u8 _WIN0_ENABLED; u8 _WIN1_ENABLED; u8 _WINOBJ_ENABLED; u16 _BLDCNT; u8 _BLDALPHA_EVA; u8 _BLDALPHA_EVB; u8 _BLDY_EVY; void _InitLUTs(); void _Reset_Base(); void _MosaicSpriteLinePixel(const size_t x, u16 l, u16 *dst, u8 *dst_alpha, u8 *typeTab, u8 *prioTab); void _MosaicSpriteLine(u16 l, u16 *dst, u8 *dst_alpha, u8 *typeTab, u8 *prioTab); template void _LineLarge8bpp(); template void _RenderLine_TextBG(u16 XBG, u16 YBG, u16 LG); template void _RotBG2(const BGxPARMS ¶m, const u16 LG); template void _ExtRotBG2(const BGxPARMS ¶m, const u16 LG); template void _LineText(); template void _LineRot(); template void _LineExtRot(); // check whether (x,y) is within the rectangle (including wraparounds) template u8 _WithinRect(const size_t x) const; template void _RenderLine_CheckWindows(const size_t srcX, bool &draw, bool &effect) const; template void _RenderLine_Layer(const u16 l, u16 *dstLine, const size_t dstLineWidth, const size_t dstLineCount); template void _RenderLine_MasterBrightness(u16 *dstLine, const size_t dstLineWidth, const size_t dstLineCount); template void _UpdateWINH(); template void _SetupWindows(); template void _ModeRender(); template FORCEINLINE FASTCALL bool _master_setFinalBGColor(const size_t srcX, const size_t dstX, const u16 *dstLine, const u8 *bgPixelsLine, u16 &outColor); template FORCEINLINE FASTCALL void _master_setFinal3dColor(const size_t srcX, const size_t dstX, u16 *dstLine, u8 *bgPixelsLine, const FragmentColor src); template FORCEINLINE FASTCALL void _master_setFinalOBJColor(const size_t srcX, const size_t dstX, u16 *dstLine, u8 *bgPixelsLine, const u16 src, const u8 alpha, const u8 type); template void _SetFinalColorBG(const size_t srcX, const size_t dstX, u16 *dstLine, u8 *bgPixelsLine, u16 src); template void _SetFinalColor3D(const size_t srcX, const size_t dstX, u16 *dstLine, u8 *bgPixelsLine, const FragmentColor src); template void _SetFinalColorSprite(const size_t srcX, const size_t dstX, u16 *dstLine, u8 *bgPixelsLine, const u16 src, const u8 alpha, const u8 type); u16 _FinalColorBlend(const u16 colA, const u16 colB); FORCEINLINE u16 _FinalColorBlendFunc(const u16 colA, const u16 colB, const TBlendTable *blendTable); void _RenderSpriteBMP(const u8 spriteNum, const u16 l, u16 *dst, const u32 srcadr, u8 *dst_alpha, u8 *typeTab, u8 *prioTab, const u8 prio, const size_t lg, size_t sprX, size_t x, const s32 xdir, const u8 alpha); void _RenderSprite256(const u8 spriteNum, const u16 l, u16 *dst, const u32 srcadr, const u16 *pal, u8 *dst_alpha, u8 *typeTab, u8 *prioTab, const u8 prio, const size_t lg, size_t sprX, size_t x, const s32 xdir, const u8 alpha); void _RenderSprite16(const u16 l, u16 *dst, const u32 srcadr, const u16 *pal, u8 *dst_alpha, u8 *typeTab, u8 *prioTab, const u8 prio, const size_t lg, size_t sprX, size_t x, const s32 xdir, const u8 alpha); void _RenderSpriteWin(const u8 *src, const bool col256, const size_t lg, size_t sprX, size_t x, const s32 xdir); bool _ComputeSpriteVars(const OAMAttributes &spriteInfo, const u16 l, SpriteSize &sprSize, s32 &sprX, s32 &sprY, s32 &x, s32 &y, s32 &lg, s32 &xdir); u32 _SpriteAddressBMP(const OAMAttributes &spriteInfo, const SpriteSize sprSize, const s32 y); template void _SpriteRenderPerform(u16 *dst, u8 *dst_alpha, u8 *typeTab, u8 *prioTab); public: GPUEngineBase(); virtual ~GPUEngineBase(); virtual void Reset(); void ResortBGLayers(); void SetMasterBrightness(const u16 val); void SetupFinalPixelBlitter(); void SetVideoProp(const u32 ctrlBits); void SetBGProp(const size_t num, const u16 ctrlBits); template void RenderLine(const u16 l, bool skip); // some structs are becoming redundant // some functions too (no need to recopy some vars as it is done by MMU) REG_DISPx *dispx_st; //this indicates whether this gpu is handling debug tools bool debug; _BGxCNT & bgcnt(int num) { return (dispx_st)->dispx_BGxCNT[num].bits; } const _DISPCNT& dispCnt() const { return dispx_st->dispx_DISPCNT.bits; } u16 BGSize[4][2]; u8 BGExtPalSlot[4]; bool isCustomRenderingNeeded; bool is3DEnabled; u8 vramBGLayer; u8 vramBlockBGIndex; u8 vramBlockOBJIndex; u16 *customBuffer; u16 *nativeBuffer; size_t renderedWidth; size_t renderedHeight; u16 *renderedBuffer; u16 *workingScanline; GPUMasterBrightMode MasterBrightMode; u32 MasterBrightFactor; u32 currLine; u16 *currDst; bool need_update_winh[2]; struct AffineInfo { AffineInfo() : x(0), y(0) {} u32 x, y; } affineInfo[2]; bool GetEnableState(); void SetEnableState(bool theState); bool GetLayerEnableState(const size_t layerIndex); void SetLayerEnableState(const size_t layerIndex, bool theState); template FORCEINLINE void ____setFinalColorBck(const u16 color, const size_t srcX); template FORCEINLINE void ___setFinalColorBck(u16 color, const size_t srcX, const bool opaque); template FORCEINLINE void __setFinalColorBck(u16 color, const size_t srcX, const bool opaque); void UpdateVRAM3DUsageProperties_BGLayer(const size_t bankIndex, VRAM3DUsageProperties &outProperty); void UpdateVRAM3DUsageProperties_OBJLayer(const size_t bankIndex, VRAM3DUsageProperties &outProperty); void setAffineStart(const size_t layer, int xy, u32 val); void setAffineStartWord(const size_t layer, int xy, u16 val, int word); u32 getAffineStart(const size_t layer, int xy); void refreshAffineStartRegs(const int num, const int xy); void SpriteRender(u16 *dst, u8 *dst_alpha, u8 *typeTab, u8 *prioTab); void ModeRenderDebug(const GPULayerID layerID); template void HandleDisplayModeOff(u16 *dstLine, const size_t l, const size_t dstLineWidth, const size_t dstLineCount); template void HandleDisplayModeNormal(u16 *dstLine, const size_t l, const size_t dstLineWidth, const size_t dstLineCount); template void HandleDisplayModeVRAM(u16 *dstLine, const size_t l, const size_t dstLineWidth, const size_t dstLineCount); template void HandleDisplayModeMainMemory(u16 *dstLine, const size_t l, const size_t dstLineWidth, const size_t dstLineCount); u32 GetHOFS(const size_t bg) const; u32 GetVOFS(const size_t bg) const; void UpdateBLDALPHA(); void SetBLDALPHA(const u16 val); void SetBLDALPHA_EVA(const u8 val); void SetBLDALPHA_EVB(const u8 val); // Blending void SetBLDCNT_LOW(const u8 val); void SetBLDCNT_HIGH(const u8 val); void SetBLDCNT(const u16 val); void SetBLDY_EVY(const u8 val); void SetWIN0_H(const u16 val); void SetWIN0_H0(const u8 val); void SetWIN0_H1(const u8 val); void SetWIN0_V(const u16 val); void SetWIN0_V0(const u8 val); void SetWIN0_V1(const u8 val); void SetWIN1_H(const u16 val); void SetWIN1_H0(const u8 val); void SetWIN1_H1(const u8 val); void SetWIN1_V(const u16 val); void SetWIN1_V0(const u8 val); void SetWIN1_V1(const u8 val); void SetWININ(const u16 val); void SetWININ0(const u8 val); void SetWININ1(const u8 val); void SetWINOUT16(const u16 val); void SetWINOUT(const u8 val); void SetWINOBJ(const u8 val); int GetFinalColorBckFuncID() const; void SetFinalColorBckFuncID(int funcID); NDSDisplayID GetDisplayByID() const; void SetDisplayByID(const NDSDisplayID theDisplayID); GPUEngineID GetEngineID() const; virtual void SetCustomFramebufferSize(size_t w, size_t h); void BlitNativeToCustomFramebuffer(); void REG_DISPx_pack_test(); }; class GPUEngineA : public GPUEngineBase { protected: FragmentColor *_3DFramebufferRGBA6665; u16 *_3DFramebufferRGBA5551; template void _RenderLine_Layer(const u16 l, u16 *dstLine, const size_t dstLineWidth, const size_t dstLineCount); template void _RenderLine_DisplayCapture(const u16 l); void _RenderLine_DispCapture_FIFOToBuffer(u16 *fifoLineBuffer); template void _RenderLine_DispCapture_Copy(const u16 *__restrict src, u16 *__restrict dst, const size_t captureLengthExt, const size_t captureLineCount); u16 _RenderLine_DispCapture_BlendFunc(const u16 srcA, const u16 srcB, const u8 blendEVA, const u8 blendEVB); #ifdef ENABLE_SSE2 __m128i _RenderLine_DispCapture_BlendFunc_SSE2(__m128i &srcA, __m128i &srcB, const __m128i &blendEVA, const __m128i &blendEVB); #endif template void _RenderLine_DispCapture_BlendToCustomDstBuffer(const u16 *__restrict srcA, const u16 *__restrict srcB, u16 *__restrict dst, const u8 blendEVA, const u8 blendEVB, const size_t length, size_t l); template void _RenderLine_DispCapture_Blend(const u16 *__restrict srcA, const u16 *__restrict srcB, u16 *__restrict dst, const size_t captureLengthExt, const size_t l); public: DISPCAPCNT dispCapCnt; GPUEngineA(); ~GPUEngineA(); virtual void Reset(); void SetDISPCAPCNT(u32 val); GPUDisplayMode GetDisplayMode() const; u8 GetVRAMBlock() const; FragmentColor* Get3DFramebufferRGBA6665() const; u16* Get3DFramebufferRGBA5551() const; virtual void SetCustomFramebufferSize(size_t w, size_t h); template void RenderLine(const u16 l, bool skip); }; class GPUEngineB : public GPUEngineBase { protected: template void _RenderLine_Layer(const u16 l, u16 *dstLine, const size_t dstLineWidth, const size_t dstLineCount); public: GPUEngineB(); virtual void Reset(); template void RenderLine(const u16 l, bool skip); }; class NDSDisplay { private: NDSDisplayID _ID; GPUEngineBase *_gpu; public: NDSDisplay(); NDSDisplay(const NDSDisplayID displayID); NDSDisplay(const NDSDisplayID displayID, GPUEngineBase *theEngine); GPUEngineBase* GetEngine(); void SetEngine(GPUEngineBase *theEngine); GPUEngineID GetEngineID(); void SetEngineByID(const GPUEngineID theID); }; class GPUSubsystem { private: GPUEngineA *_engineMain; GPUEngineB *_engineSub; NDSDisplay *_displayMain; NDSDisplay *_displayTouch; bool _willAutoBlitNativeToCustomBuffer; VRAM3DUsageProperties _VRAM3DUsage; u16 *_customVRAM; u16 *_customVRAMBlank; CACHE_ALIGN u16 _nativeFramebuffer[GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT * 2]; u16 *_customFramebuffer; NDSDisplayInfo _displayInfo; public: GPUSubsystem(); ~GPUSubsystem(); void Reset(); VRAM3DUsageProperties& GetVRAM3DUsageProperties(); const NDSDisplayInfo& GetDisplayInfo(); // Frontends need to call this whenever they need to read the video buffers from the emulator core void SetDisplayDidCustomRender(NDSDisplayID displayID, bool theState); GPUEngineA* GetEngineMain(); GPUEngineB* GetEngineSub(); NDSDisplay* GetDisplayMain(); NDSDisplay* GetDisplayTouch(); u16* GetNativeFramebuffer(); u16* GetNativeFramebuffer(const NDSDisplayID theDisplayID); u16* GetCustomFramebuffer(); u16* GetCustomFramebuffer(const NDSDisplayID theDisplayID); u16* GetCustomVRAMBuffer(); u16* GetCustomVRAMBlankBuffer(); size_t GetCustomFramebufferWidth() const; size_t GetCustomFramebufferHeight() const; void SetCustomFramebufferSize(size_t w, size_t h); void UpdateVRAM3DUsageProperties(); // Normally, the GPUs will automatically blit their native buffers to the master // framebuffer at the end of V-blank so that all rendered graphics are contained // within a single common buffer. This is necessary for when someone wants to read // the NDS framebuffers, but the reader can only read a single buffer at a time. // Certain functions, such as taking screenshots, as well as many frontends running // the NDS video displays, require that they read from only a single buffer. // // However, if SetWillAutoBlitNativeToCustomBuffer() is passed "false", then the // frontend becomes responsible for calling GetDisplayInfo() and reading the native // and custom buffers properly for each display. If a single buffer is still needed // for certain cases, then the frontend must manually call // GPUEngineBase::BlitNativeToCustomFramebuffer() for each GPU before reading the // master framebuffer. bool GetWillAutoBlitNativeToCustomBuffer() const; void SetWillAutoBlitNativeToCustomBuffer(const bool willAutoBlit); void RenderLine(const u16 l, bool skip = false); void ClearWithColor(const u16 colorBGRA5551); }; extern GPUSubsystem *GPU; extern MMU_struct MMU; inline FragmentColor MakeFragmentColor(const u8 r, const u8 g, const u8 b, const u8 a) { FragmentColor ret; ret.r = r; ret.g = g; ret.b = b; ret.a = a; return ret; } #endif desmume/src/libretro-common/include/libretro.h000664 001750 001750 00000307731 12755534123 022700 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2016 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this libretro API header (libretro.h). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef LIBRETRO_H__ #define LIBRETRO_H__ #include #include #include #ifdef __cplusplus extern "C" { #endif #ifndef __cplusplus #if defined(_MSC_VER) && !defined(SN_TARGET_PS3) /* Hack applied for MSVC when compiling in C89 mode * as it isn't C99-compliant. */ #define bool unsigned char #define true 1 #define false 0 #else #include #endif #endif #ifndef RETRO_CALLCONV # if defined(__GNUC__) && defined(__i386__) && !defined(__x86_64__) # define RETRO_CALLCONV __attribute__((cdecl)) # elif defined(_MSC_VER) && defined(_M_X86) && !defined(_M_X64) # define RETRO_CALLCONV __cdecl # else # define RETRO_CALLCONV /* all other platforms only have one calling convention each */ # endif #endif #ifndef RETRO_API # if defined(_WIN32) || defined(__CYGWIN__) || defined(__MINGW32__) # ifdef RETRO_IMPORT_SYMBOLS # ifdef __GNUC__ # define RETRO_API RETRO_CALLCONV __attribute__((__dllimport__)) # else # define RETRO_API RETRO_CALLCONV __declspec(dllimport) # endif # else # ifdef __GNUC__ # define RETRO_API RETRO_CALLCONV __attribute__((__dllexport__)) # else # define RETRO_API RETRO_CALLCONV __declspec(dllexport) # endif # endif # else # if defined(__GNUC__) && __GNUC__ >= 4 && !defined(__CELLOS_LV2__) # define RETRO_API RETRO_CALLCONV __attribute__((__visibility__("default"))) # else # define RETRO_API RETRO_CALLCONV # endif # endif #endif /* Used for checking API/ABI mismatches that can break libretro * implementations. * It is not incremented for compatible changes to the API. */ #define RETRO_API_VERSION 1 /* * Libretro's fundamental device abstractions. * * Libretro's input system consists of some standardized device types, * such as a joypad (with/without analog), mouse, keyboard, lightgun * and a pointer. * * The functionality of these devices are fixed, and individual cores * map their own concept of a controller to libretro's abstractions. * This makes it possible for frontends to map the abstract types to a * real input device, and not having to worry about binding input * correctly to arbitrary controller layouts. */ #define RETRO_DEVICE_TYPE_SHIFT 8 #define RETRO_DEVICE_MASK ((1 << RETRO_DEVICE_TYPE_SHIFT) - 1) #define RETRO_DEVICE_SUBCLASS(base, id) (((id + 1) << RETRO_DEVICE_TYPE_SHIFT) | base) /* Input disabled. */ #define RETRO_DEVICE_NONE 0 /* The JOYPAD is called RetroPad. It is essentially a Super Nintendo * controller, but with additional L2/R2/L3/R3 buttons, similar to a * PS1 DualShock. */ #define RETRO_DEVICE_JOYPAD 1 /* The mouse is a simple mouse, similar to Super Nintendo's mouse. * X and Y coordinates are reported relatively to last poll (poll callback). * It is up to the libretro implementation to keep track of where the mouse * pointer is supposed to be on the screen. * The frontend must make sure not to interfere with its own hardware * mouse pointer. */ #define RETRO_DEVICE_MOUSE 2 /* KEYBOARD device lets one poll for raw key pressed. * It is poll based, so input callback will return with the current * pressed state. * For event/text based keyboard input, see * RETRO_ENVIRONMENT_SET_KEYBOARD_CALLBACK. */ #define RETRO_DEVICE_KEYBOARD 3 /* Lightgun X/Y coordinates are reported relatively to last poll, * similar to mouse. */ #define RETRO_DEVICE_LIGHTGUN 4 /* The ANALOG device is an extension to JOYPAD (RetroPad). * Similar to DualShock it adds two analog sticks. * This is treated as a separate device type as it returns values in the * full analog range of [-0x8000, 0x7fff]. Positive X axis is right. * Positive Y axis is down. * Only use ANALOG type when polling for analog values of the axes. */ #define RETRO_DEVICE_ANALOG 5 /* Abstracts the concept of a pointing mechanism, e.g. touch. * This allows libretro to query in absolute coordinates where on the * screen a mouse (or something similar) is being placed. * For a touch centric device, coordinates reported are the coordinates * of the press. * * Coordinates in X and Y are reported as: * [-0x7fff, 0x7fff]: -0x7fff corresponds to the far left/top of the screen, * and 0x7fff corresponds to the far right/bottom of the screen. * The "screen" is here defined as area that is passed to the frontend and * later displayed on the monitor. * * The frontend is free to scale/resize this screen as it sees fit, however, * (X, Y) = (-0x7fff, -0x7fff) will correspond to the top-left pixel of the * game image, etc. * * To check if the pointer coordinates are valid (e.g. a touch display * actually being touched), PRESSED returns 1 or 0. * * If using a mouse on a desktop, PRESSED will usually correspond to the * left mouse button, but this is a frontend decision. * PRESSED will only return 1 if the pointer is inside the game screen. * * For multi-touch, the index variable can be used to successively query * more presses. * If index = 0 returns true for _PRESSED, coordinates can be extracted * with _X, _Y for index = 0. One can then query _PRESSED, _X, _Y with * index = 1, and so on. * Eventually _PRESSED will return false for an index. No further presses * are registered at this point. */ #define RETRO_DEVICE_POINTER 6 /* Buttons for the RetroPad (JOYPAD). * The placement of these is equivalent to placements on the * Super Nintendo controller. * L2/R2/L3/R3 buttons correspond to the PS1 DualShock. */ #define RETRO_DEVICE_ID_JOYPAD_B 0 #define RETRO_DEVICE_ID_JOYPAD_Y 1 #define RETRO_DEVICE_ID_JOYPAD_SELECT 2 #define RETRO_DEVICE_ID_JOYPAD_START 3 #define RETRO_DEVICE_ID_JOYPAD_UP 4 #define RETRO_DEVICE_ID_JOYPAD_DOWN 5 #define RETRO_DEVICE_ID_JOYPAD_LEFT 6 #define RETRO_DEVICE_ID_JOYPAD_RIGHT 7 #define RETRO_DEVICE_ID_JOYPAD_A 8 #define RETRO_DEVICE_ID_JOYPAD_X 9 #define RETRO_DEVICE_ID_JOYPAD_L 10 #define RETRO_DEVICE_ID_JOYPAD_R 11 #define RETRO_DEVICE_ID_JOYPAD_L2 12 #define RETRO_DEVICE_ID_JOYPAD_R2 13 #define RETRO_DEVICE_ID_JOYPAD_L3 14 #define RETRO_DEVICE_ID_JOYPAD_R3 15 /* Index / Id values for ANALOG device. */ #define RETRO_DEVICE_INDEX_ANALOG_LEFT 0 #define RETRO_DEVICE_INDEX_ANALOG_RIGHT 1 #define RETRO_DEVICE_ID_ANALOG_X 0 #define RETRO_DEVICE_ID_ANALOG_Y 1 /* Id values for MOUSE. */ #define RETRO_DEVICE_ID_MOUSE_X 0 #define RETRO_DEVICE_ID_MOUSE_Y 1 #define RETRO_DEVICE_ID_MOUSE_LEFT 2 #define RETRO_DEVICE_ID_MOUSE_RIGHT 3 #define RETRO_DEVICE_ID_MOUSE_WHEELUP 4 #define RETRO_DEVICE_ID_MOUSE_WHEELDOWN 5 #define RETRO_DEVICE_ID_MOUSE_MIDDLE 6 #define RETRO_DEVICE_ID_MOUSE_HORIZ_WHEELUP 7 #define RETRO_DEVICE_ID_MOUSE_HORIZ_WHEELDOWN 8 /* Id values for LIGHTGUN types. */ #define RETRO_DEVICE_ID_LIGHTGUN_X 0 #define RETRO_DEVICE_ID_LIGHTGUN_Y 1 #define RETRO_DEVICE_ID_LIGHTGUN_TRIGGER 2 #define RETRO_DEVICE_ID_LIGHTGUN_CURSOR 3 #define RETRO_DEVICE_ID_LIGHTGUN_TURBO 4 #define RETRO_DEVICE_ID_LIGHTGUN_PAUSE 5 #define RETRO_DEVICE_ID_LIGHTGUN_START 6 /* Id values for POINTER. */ #define RETRO_DEVICE_ID_POINTER_X 0 #define RETRO_DEVICE_ID_POINTER_Y 1 #define RETRO_DEVICE_ID_POINTER_PRESSED 2 /* Returned from retro_get_region(). */ #define RETRO_REGION_NTSC 0 #define RETRO_REGION_PAL 1 /* Id values for LANGUAGE */ enum retro_language { RETRO_LANGUAGE_ENGLISH = 0, RETRO_LANGUAGE_JAPANESE = 1, RETRO_LANGUAGE_FRENCH = 2, RETRO_LANGUAGE_SPANISH = 3, RETRO_LANGUAGE_GERMAN = 4, RETRO_LANGUAGE_ITALIAN = 5, RETRO_LANGUAGE_DUTCH = 6, RETRO_LANGUAGE_PORTUGUESE = 7, RETRO_LANGUAGE_RUSSIAN = 8, RETRO_LANGUAGE_KOREAN = 9, RETRO_LANGUAGE_CHINESE_TRADITIONAL = 10, RETRO_LANGUAGE_CHINESE_SIMPLIFIED = 11, RETRO_LANGUAGE_ESPERANTO = 12, RETRO_LANGUAGE_POLISH = 13, RETRO_LANGUAGE_LAST, /* Ensure sizeof(enum) == sizeof(int) */ RETRO_LANGUAGE_DUMMY = INT_MAX }; /* Passed to retro_get_memory_data/size(). * If the memory type doesn't apply to the * implementation NULL/0 can be returned. */ #define RETRO_MEMORY_MASK 0xff /* Regular save RAM. This RAM is usually found on a game cartridge, * backed up by a battery. * If save game data is too complex for a single memory buffer, * the SAVE_DIRECTORY (preferably) or SYSTEM_DIRECTORY environment * callback can be used. */ #define RETRO_MEMORY_SAVE_RAM 0 /* Some games have a built-in clock to keep track of time. * This memory is usually just a couple of bytes to keep track of time. */ #define RETRO_MEMORY_RTC 1 /* System ram lets a frontend peek into a game systems main RAM. */ #define RETRO_MEMORY_SYSTEM_RAM 2 /* Video ram lets a frontend peek into a game systems video RAM (VRAM). */ #define RETRO_MEMORY_VIDEO_RAM 3 /* Keysyms used for ID in input state callback when polling RETRO_KEYBOARD. */ enum retro_key { RETROK_UNKNOWN = 0, RETROK_FIRST = 0, RETROK_BACKSPACE = 8, RETROK_TAB = 9, RETROK_CLEAR = 12, RETROK_RETURN = 13, RETROK_PAUSE = 19, RETROK_ESCAPE = 27, RETROK_SPACE = 32, RETROK_EXCLAIM = 33, RETROK_QUOTEDBL = 34, RETROK_HASH = 35, RETROK_DOLLAR = 36, RETROK_AMPERSAND = 38, RETROK_QUOTE = 39, RETROK_LEFTPAREN = 40, RETROK_RIGHTPAREN = 41, RETROK_ASTERISK = 42, RETROK_PLUS = 43, RETROK_COMMA = 44, RETROK_MINUS = 45, RETROK_PERIOD = 46, RETROK_SLASH = 47, RETROK_0 = 48, RETROK_1 = 49, RETROK_2 = 50, RETROK_3 = 51, RETROK_4 = 52, RETROK_5 = 53, RETROK_6 = 54, RETROK_7 = 55, RETROK_8 = 56, RETROK_9 = 57, RETROK_COLON = 58, RETROK_SEMICOLON = 59, RETROK_LESS = 60, RETROK_EQUALS = 61, RETROK_GREATER = 62, RETROK_QUESTION = 63, RETROK_AT = 64, RETROK_LEFTBRACKET = 91, RETROK_BACKSLASH = 92, RETROK_RIGHTBRACKET = 93, RETROK_CARET = 94, RETROK_UNDERSCORE = 95, RETROK_BACKQUOTE = 96, RETROK_a = 97, RETROK_b = 98, RETROK_c = 99, RETROK_d = 100, RETROK_e = 101, RETROK_f = 102, RETROK_g = 103, RETROK_h = 104, RETROK_i = 105, RETROK_j = 106, RETROK_k = 107, RETROK_l = 108, RETROK_m = 109, RETROK_n = 110, RETROK_o = 111, RETROK_p = 112, RETROK_q = 113, RETROK_r = 114, RETROK_s = 115, RETROK_t = 116, RETROK_u = 117, RETROK_v = 118, RETROK_w = 119, RETROK_x = 120, RETROK_y = 121, RETROK_z = 122, RETROK_DELETE = 127, RETROK_KP0 = 256, RETROK_KP1 = 257, RETROK_KP2 = 258, RETROK_KP3 = 259, RETROK_KP4 = 260, RETROK_KP5 = 261, RETROK_KP6 = 262, RETROK_KP7 = 263, RETROK_KP8 = 264, RETROK_KP9 = 265, RETROK_KP_PERIOD = 266, RETROK_KP_DIVIDE = 267, RETROK_KP_MULTIPLY = 268, RETROK_KP_MINUS = 269, RETROK_KP_PLUS = 270, RETROK_KP_ENTER = 271, RETROK_KP_EQUALS = 272, RETROK_UP = 273, RETROK_DOWN = 274, RETROK_RIGHT = 275, RETROK_LEFT = 276, RETROK_INSERT = 277, RETROK_HOME = 278, RETROK_END = 279, RETROK_PAGEUP = 280, RETROK_PAGEDOWN = 281, RETROK_F1 = 282, RETROK_F2 = 283, RETROK_F3 = 284, RETROK_F4 = 285, RETROK_F5 = 286, RETROK_F6 = 287, RETROK_F7 = 288, RETROK_F8 = 289, RETROK_F9 = 290, RETROK_F10 = 291, RETROK_F11 = 292, RETROK_F12 = 293, RETROK_F13 = 294, RETROK_F14 = 295, RETROK_F15 = 296, RETROK_NUMLOCK = 300, RETROK_CAPSLOCK = 301, RETROK_SCROLLOCK = 302, RETROK_RSHIFT = 303, RETROK_LSHIFT = 304, RETROK_RCTRL = 305, RETROK_LCTRL = 306, RETROK_RALT = 307, RETROK_LALT = 308, RETROK_RMETA = 309, RETROK_LMETA = 310, RETROK_LSUPER = 311, RETROK_RSUPER = 312, RETROK_MODE = 313, RETROK_COMPOSE = 314, RETROK_HELP = 315, RETROK_PRINT = 316, RETROK_SYSREQ = 317, RETROK_BREAK = 318, RETROK_MENU = 319, RETROK_POWER = 320, RETROK_EURO = 321, RETROK_UNDO = 322, RETROK_LAST, RETROK_DUMMY = INT_MAX /* Ensure sizeof(enum) == sizeof(int) */ }; enum retro_mod { RETROKMOD_NONE = 0x0000, RETROKMOD_SHIFT = 0x01, RETROKMOD_CTRL = 0x02, RETROKMOD_ALT = 0x04, RETROKMOD_META = 0x08, RETROKMOD_NUMLOCK = 0x10, RETROKMOD_CAPSLOCK = 0x20, RETROKMOD_SCROLLOCK = 0x40, RETROKMOD_DUMMY = INT_MAX /* Ensure sizeof(enum) == sizeof(int) */ }; /* If set, this call is not part of the public libretro API yet. It can * change or be removed at any time. */ #define RETRO_ENVIRONMENT_EXPERIMENTAL 0x10000 /* Environment callback to be used internally in frontend. */ #define RETRO_ENVIRONMENT_PRIVATE 0x20000 /* Environment commands. */ #define RETRO_ENVIRONMENT_SET_ROTATION 1 /* const unsigned * -- * Sets screen rotation of graphics. * Is only implemented if rotation can be accelerated by hardware. * Valid values are 0, 1, 2, 3, which rotates screen by 0, 90, 180, * 270 degrees counter-clockwise respectively. */ #define RETRO_ENVIRONMENT_GET_OVERSCAN 2 /* bool * -- * Boolean value whether or not the implementation should use overscan, * or crop away overscan. */ #define RETRO_ENVIRONMENT_GET_CAN_DUPE 3 /* bool * -- * Boolean value whether or not frontend supports frame duping, * passing NULL to video frame callback. */ /* Environ 4, 5 are no longer supported (GET_VARIABLE / SET_VARIABLES), * and reserved to avoid possible ABI clash. */ #define RETRO_ENVIRONMENT_SET_MESSAGE 6 /* const struct retro_message * -- * Sets a message to be displayed in implementation-specific manner * for a certain amount of 'frames'. * Should not be used for trivial messages, which should simply be * logged via RETRO_ENVIRONMENT_GET_LOG_INTERFACE (or as a * fallback, stderr). */ #define RETRO_ENVIRONMENT_SHUTDOWN 7 /* N/A (NULL) -- * Requests the frontend to shutdown. * Should only be used if game has a specific * way to shutdown the game from a menu item or similar. */ #define RETRO_ENVIRONMENT_SET_PERFORMANCE_LEVEL 8 /* const unsigned * -- * Gives a hint to the frontend how demanding this implementation * is on a system. E.g. reporting a level of 2 means * this implementation should run decently on all frontends * of level 2 and up. * * It can be used by the frontend to potentially warn * about too demanding implementations. * * The levels are "floating". * * This function can be called on a per-game basis, * as certain games an implementation can play might be * particularly demanding. * If called, it should be called in retro_load_game(). */ #define RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY 9 /* const char ** -- * Returns the "system" directory of the frontend. * This directory can be used to store system specific * content such as BIOSes, configuration data, etc. * The returned value can be NULL. * If so, no such directory is defined, * and it's up to the implementation to find a suitable directory. * * NOTE: Some cores used this folder also for "save" data such as * memory cards, etc, for lack of a better place to put it. * This is now discouraged, and if possible, cores should try to * use the new GET_SAVE_DIRECTORY. */ #define RETRO_ENVIRONMENT_SET_PIXEL_FORMAT 10 /* const enum retro_pixel_format * -- * Sets the internal pixel format used by the implementation. * The default pixel format is RETRO_PIXEL_FORMAT_0RGB1555. * This pixel format however, is deprecated (see enum retro_pixel_format). * If the call returns false, the frontend does not support this pixel * format. * * This function should be called inside retro_load_game() or * retro_get_system_av_info(). */ #define RETRO_ENVIRONMENT_SET_INPUT_DESCRIPTORS 11 /* const struct retro_input_descriptor * -- * Sets an array of retro_input_descriptors. * It is up to the frontend to present this in a usable way. * The array is terminated by retro_input_descriptor::description * being set to NULL. * This function can be called at any time, but it is recommended * to call it as early as possible. */ #define RETRO_ENVIRONMENT_SET_KEYBOARD_CALLBACK 12 /* const struct retro_keyboard_callback * -- * Sets a callback function used to notify core about keyboard events. */ #define RETRO_ENVIRONMENT_SET_DISK_CONTROL_INTERFACE 13 /* const struct retro_disk_control_callback * -- * Sets an interface which frontend can use to eject and insert * disk images. * This is used for games which consist of multiple images and * must be manually swapped out by the user (e.g. PSX). */ #define RETRO_ENVIRONMENT_SET_HW_RENDER 14 /* struct retro_hw_render_callback * -- * Sets an interface to let a libretro core render with * hardware acceleration. * Should be called in retro_load_game(). * If successful, libretro cores will be able to render to a * frontend-provided framebuffer. * The size of this framebuffer will be at least as large as * max_width/max_height provided in get_av_info(). * If HW rendering is used, pass only RETRO_HW_FRAME_BUFFER_VALID or * NULL to retro_video_refresh_t. */ #define RETRO_ENVIRONMENT_GET_VARIABLE 15 /* struct retro_variable * -- * Interface to acquire user-defined information from environment * that cannot feasibly be supported in a multi-system way. * 'key' should be set to a key which has already been set by * SET_VARIABLES. * 'data' will be set to a value or NULL. */ #define RETRO_ENVIRONMENT_SET_VARIABLES 16 /* const struct retro_variable * -- * Allows an implementation to signal the environment * which variables it might want to check for later using * GET_VARIABLE. * This allows the frontend to present these variables to * a user dynamically. * This should be called as early as possible (ideally in * retro_set_environment). * * 'data' points to an array of retro_variable structs * terminated by a { NULL, NULL } element. * retro_variable::key should be namespaced to not collide * with other implementations' keys. E.g. A core called * 'foo' should use keys named as 'foo_option'. * retro_variable::value should contain a human readable * description of the key as well as a '|' delimited list * of expected values. * * The number of possible options should be very limited, * i.e. it should be feasible to cycle through options * without a keyboard. * * First entry should be treated as a default. * * Example entry: * { "foo_option", "Speed hack coprocessor X; false|true" } * * Text before first ';' is description. This ';' must be * followed by a space, and followed by a list of possible * values split up with '|'. * * Only strings are operated on. The possible values will * generally be displayed and stored as-is by the frontend. */ #define RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE 17 /* bool * -- * Result is set to true if some variables are updated by * frontend since last call to RETRO_ENVIRONMENT_GET_VARIABLE. * Variables should be queried with GET_VARIABLE. */ #define RETRO_ENVIRONMENT_SET_SUPPORT_NO_GAME 18 /* const bool * -- * If true, the libretro implementation supports calls to * retro_load_game() with NULL as argument. * Used by cores which can run without particular game data. * This should be called within retro_set_environment() only. */ #define RETRO_ENVIRONMENT_GET_LIBRETRO_PATH 19 /* const char ** -- * Retrieves the absolute path from where this libretro * implementation was loaded. * NULL is returned if the libretro was loaded statically * (i.e. linked statically to frontend), or if the path cannot be * determined. * Mostly useful in cooperation with SET_SUPPORT_NO_GAME as assets can * be loaded without ugly hacks. */ /* Environment 20 was an obsolete version of SET_AUDIO_CALLBACK. * It was not used by any known core at the time, * and was removed from the API. */ #define RETRO_ENVIRONMENT_SET_AUDIO_CALLBACK 22 /* const struct retro_audio_callback * -- * Sets an interface which is used to notify a libretro core about audio * being available for writing. * The callback can be called from any thread, so a core using this must * have a thread safe audio implementation. * It is intended for games where audio and video are completely * asynchronous and audio can be generated on the fly. * This interface is not recommended for use with emulators which have * highly synchronous audio. * * The callback only notifies about writability; the libretro core still * has to call the normal audio callbacks * to write audio. The audio callbacks must be called from within the * notification callback. * The amount of audio data to write is up to the implementation. * Generally, the audio callback will be called continously in a loop. * * Due to thread safety guarantees and lack of sync between audio and * video, a frontend can selectively disallow this interface based on * internal configuration. A core using this interface must also * implement the "normal" audio interface. * * A libretro core using SET_AUDIO_CALLBACK should also make use of * SET_FRAME_TIME_CALLBACK. */ #define RETRO_ENVIRONMENT_SET_FRAME_TIME_CALLBACK 21 /* const struct retro_frame_time_callback * -- * Lets the core know how much time has passed since last * invocation of retro_run(). * The frontend can tamper with the timing to fake fast-forward, * slow-motion, frame stepping, etc. * In this case the delta time will use the reference value * in frame_time_callback.. */ #define RETRO_ENVIRONMENT_GET_RUMBLE_INTERFACE 23 /* struct retro_rumble_interface * -- * Gets an interface which is used by a libretro core to set * state of rumble motors in controllers. * A strong and weak motor is supported, and they can be * controlled indepedently. */ #define RETRO_ENVIRONMENT_GET_INPUT_DEVICE_CAPABILITIES 24 /* uint64_t * -- * Gets a bitmask telling which device type are expected to be * handled properly in a call to retro_input_state_t. * Devices which are not handled or recognized always return * 0 in retro_input_state_t. * Example bitmask: caps = (1 << RETRO_DEVICE_JOYPAD) | (1 << RETRO_DEVICE_ANALOG). * Should only be called in retro_run(). */ #define RETRO_ENVIRONMENT_GET_SENSOR_INTERFACE (25 | RETRO_ENVIRONMENT_EXPERIMENTAL) /* struct retro_sensor_interface * -- * Gets access to the sensor interface. * The purpose of this interface is to allow * setting state related to sensors such as polling rate, * enabling/disable it entirely, etc. * Reading sensor state is done via the normal * input_state_callback API. */ #define RETRO_ENVIRONMENT_GET_CAMERA_INTERFACE (26 | RETRO_ENVIRONMENT_EXPERIMENTAL) /* struct retro_camera_callback * -- * Gets an interface to a video camera driver. * A libretro core can use this interface to get access to a * video camera. * New video frames are delivered in a callback in same * thread as retro_run(). * * GET_CAMERA_INTERFACE should be called in retro_load_game(). * * Depending on the camera implementation used, camera frames * will be delivered as a raw framebuffer, * or as an OpenGL texture directly. * * The core has to tell the frontend here which types of * buffers can be handled properly. * An OpenGL texture can only be handled when using a * libretro GL core (SET_HW_RENDER). * It is recommended to use a libretro GL core when * using camera interface. * * The camera is not started automatically. The retrieved start/stop * functions must be used to explicitly * start and stop the camera driver. */ #define RETRO_ENVIRONMENT_GET_LOG_INTERFACE 27 /* struct retro_log_callback * -- * Gets an interface for logging. This is useful for * logging in a cross-platform way * as certain platforms cannot use use stderr for logging. * It also allows the frontend to * show logging information in a more suitable way. * If this interface is not used, libretro cores should * log to stderr as desired. */ #define RETRO_ENVIRONMENT_GET_PERF_INTERFACE 28 /* struct retro_perf_callback * -- * Gets an interface for performance counters. This is useful * for performance logging in a cross-platform way and for detecting * architecture-specific features, such as SIMD support. */ #define RETRO_ENVIRONMENT_GET_LOCATION_INTERFACE 29 /* struct retro_location_callback * -- * Gets access to the location interface. * The purpose of this interface is to be able to retrieve * location-based information from the host device, * such as current latitude / longitude. */ #define RETRO_ENVIRONMENT_GET_CONTENT_DIRECTORY 30 /* Old name, kept for compatibility. */ #define RETRO_ENVIRONMENT_GET_CORE_ASSETS_DIRECTORY 30 /* const char ** -- * Returns the "core assets" directory of the frontend. * This directory can be used to store specific assets that the * core relies upon, such as art assets, * input data, etc etc. * The returned value can be NULL. * If so, no such directory is defined, * and it's up to the implementation to find a suitable directory. */ #define RETRO_ENVIRONMENT_GET_SAVE_DIRECTORY 31 /* const char ** -- * Returns the "save" directory of the frontend. * This directory can be used to store SRAM, memory cards, * high scores, etc, if the libretro core * cannot use the regular memory interface (retro_get_memory_data()). * * NOTE: libretro cores used to check GET_SYSTEM_DIRECTORY for * similar things before. * They should still check GET_SYSTEM_DIRECTORY if they want to * be backwards compatible. * The path here can be NULL. It should only be non-NULL if the * frontend user has set a specific save path. */ #define RETRO_ENVIRONMENT_SET_SYSTEM_AV_INFO 32 /* const struct retro_system_av_info * -- * Sets a new av_info structure. This can only be called from * within retro_run(). * This should *only* be used if the core is completely altering the * internal resolutions, aspect ratios, timings, sampling rate, etc. * Calling this can require a full reinitialization of video/audio * drivers in the frontend, * * so it is important to call it very sparingly, and usually only with * the users explicit consent. * An eventual driver reinitialize will happen so that video and * audio callbacks * happening after this call within the same retro_run() call will * target the newly initialized driver. * * This callback makes it possible to support configurable resolutions * in games, which can be useful to * avoid setting the "worst case" in max_width/max_height. * * ***HIGHLY RECOMMENDED*** Do not call this callback every time * resolution changes in an emulator core if it's * expected to be a temporary change, for the reasons of possible * driver reinitialization. * This call is not a free pass for not trying to provide * correct values in retro_get_system_av_info(). If you need to change * things like aspect ratio or nominal width/height, * use RETRO_ENVIRONMENT_SET_GEOMETRY, which is a softer variant * of SET_SYSTEM_AV_INFO. * * If this returns false, the frontend does not acknowledge a * changed av_info struct. */ #define RETRO_ENVIRONMENT_SET_PROC_ADDRESS_CALLBACK 33 /* const struct retro_get_proc_address_interface * -- * Allows a libretro core to announce support for the * get_proc_address() interface. * This interface allows for a standard way to extend libretro where * use of environment calls are too indirect, * e.g. for cases where the frontend wants to call directly into the core. * * If a core wants to expose this interface, SET_PROC_ADDRESS_CALLBACK * **MUST** be called from within retro_set_environment(). */ #define RETRO_ENVIRONMENT_SET_SUBSYSTEM_INFO 34 /* const struct retro_subsystem_info * -- * This environment call introduces the concept of libretro "subsystems". * A subsystem is a variant of a libretro core which supports * different kinds of games. * The purpose of this is to support e.g. emulators which might * have special needs, e.g. Super Nintendo's Super GameBoy, Sufami Turbo. * It can also be used to pick among subsystems in an explicit way * if the libretro implementation is a multi-system emulator itself. * * Loading a game via a subsystem is done with retro_load_game_special(), * and this environment call allows a libretro core to expose which * subsystems are supported for use with retro_load_game_special(). * A core passes an array of retro_game_special_info which is terminated * with a zeroed out retro_game_special_info struct. * * If a core wants to use this functionality, SET_SUBSYSTEM_INFO * **MUST** be called from within retro_set_environment(). */ #define RETRO_ENVIRONMENT_SET_CONTROLLER_INFO 35 /* const struct retro_controller_info * -- * This environment call lets a libretro core tell the frontend * which controller types are recognized in calls to * retro_set_controller_port_device(). * * Some emulators such as Super Nintendo * support multiple lightgun types which must be specifically * selected from. * It is therefore sometimes necessary for a frontend to be able * to tell the core about a special kind of input device which is * not covered by the libretro input API. * * In order for a frontend to understand the workings of an input device, * it must be a specialized type * of the generic device types already defined in the libretro API. * * Which devices are supported can vary per input port. * The core must pass an array of const struct retro_controller_info which * is terminated with a blanked out struct. Each element of the struct * corresponds to an ascending port index to * retro_set_controller_port_device(). * Even if special device types are set in the libretro core, * libretro should only poll input based on the base input device types. */ #define RETRO_ENVIRONMENT_SET_MEMORY_MAPS (36 | RETRO_ENVIRONMENT_EXPERIMENTAL) /* const struct retro_memory_map * -- * This environment call lets a libretro core tell the frontend * about the memory maps this core emulates. * This can be used to implement, for example, cheats in a core-agnostic way. * * Should only be used by emulators; it doesn't make much sense for * anything else. * It is recommended to expose all relevant pointers through * retro_get_memory_* as well. * * Can be called from retro_init and retro_load_game. */ #define RETRO_ENVIRONMENT_SET_GEOMETRY 37 /* const struct retro_game_geometry * -- * This environment call is similar to SET_SYSTEM_AV_INFO for changing * video parameters, but provides a guarantee that drivers will not be * reinitialized. * This can only be called from within retro_run(). * * The purpose of this call is to allow a core to alter nominal * width/heights as well as aspect ratios on-the-fly, which can be * useful for some emulators to change in run-time. * * max_width/max_height arguments are ignored and cannot be changed * with this call as this could potentially require a reinitialization or a * non-constant time operation. * If max_width/max_height are to be changed, SET_SYSTEM_AV_INFO is required. * * A frontend must guarantee that this environment call completes in * constant time. */ #define RETRO_ENVIRONMENT_GET_USERNAME 38 /* const char ** * Returns the specified username of the frontend, if specified by the user. * This username can be used as a nickname for a core that has online facilities * or any other mode where personalization of the user is desirable. * The returned value can be NULL. * If this environ callback is used by a core that requires a valid username, * a default username should be specified by the core. */ #define RETRO_ENVIRONMENT_GET_LANGUAGE 39 /* unsigned * -- * Returns the specified language of the frontend, if specified by the user. * It can be used by the core for localization purposes. */ #define RETRO_ENVIRONMENT_GET_CURRENT_SOFTWARE_FRAMEBUFFER (40 | RETRO_ENVIRONMENT_EXPERIMENTAL) /* struct retro_framebuffer * -- * Returns a preallocated framebuffer which the core can use for rendering * the frame into when not using SET_HW_RENDER. * The framebuffer returned from this call must not be used * after the current call to retro_run() returns. * * The goal of this call is to allow zero-copy behavior where a core * can render directly into video memory, avoiding extra bandwidth cost by copying * memory from core to video memory. * * If this call succeeds and the core renders into it, * the framebuffer pointer and pitch can be passed to retro_video_refresh_t. * If the buffer from GET_CURRENT_SOFTWARE_FRAMEBUFFER is to be used, * the core must pass the exact * same pointer as returned by GET_CURRENT_SOFTWARE_FRAMEBUFFER; * i.e. passing a pointer which is offset from the * buffer is undefined. The width, height and pitch parameters * must also match exactly to the values obtained from GET_CURRENT_SOFTWARE_FRAMEBUFFER. * * It is possible for a frontend to return a different pixel format * than the one used in SET_PIXEL_FORMAT. This can happen if the frontend * needs to perform conversion. * * It is still valid for a core to render to a different buffer * even if GET_CURRENT_SOFTWARE_FRAMEBUFFER succeeds. * * A frontend must make sure that the pointer obtained from this function is * writeable (and readable). */ enum retro_hw_render_interface_type { RETRO_HW_RENDER_INTERFACE_VULKAN = 0, RETRO_HW_RENDER_INTERFACE_DUMMY = INT_MAX }; /* Base struct. All retro_hw_render_interface_* types * contain at least these fields. */ struct retro_hw_render_interface { enum retro_hw_render_interface_type interface_type; unsigned interface_version; }; #define RETRO_ENVIRONMENT_GET_HW_RENDER_INTERFACE (41 | RETRO_ENVIRONMENT_EXPERIMENTAL) /* const struct retro_hw_render_interface ** -- * Returns an API specific rendering interface for accessing API specific data. * Not all HW rendering APIs support or need this. * The contents of the returned pointer is specific to the rendering API * being used. See the various headers like libretro_vulkan.h, etc. * * GET_HW_RENDER_INTERFACE cannot be called before context_reset has been called. * Similarly, after context_destroyed callback returns, * the contents of the HW_RENDER_INTERFACE are invalidated. */ #define RETRO_ENVIRONMENT_SET_SUPPORT_ACHIEVEMENTS (42 | RETRO_ENVIRONMENT_EXPERIMENTAL) /* const bool * -- * If true, the libretro implementation supports achievements * either via memory descriptors set with RETRO_ENVIRONMENT_SET_MEMORY_MAPS * or via retro_get_memory_data/retro_get_memory_size. * * This must be called before the first call to retro_run. */ enum retro_hw_render_context_negotiation_interface_type { RETRO_HW_RENDER_CONTEXT_NEGOTIATION_INTERFACE_VULKAN = 0, RETRO_HW_RENDER_CONTEXT_NEGOTIATION_INTERFACE_DUMMY = INT_MAX }; /* Base struct. All retro_hw_render_context_negotiation_interface_* types * contain at least these fields. */ struct retro_hw_render_context_negotiation_interface { enum retro_hw_render_context_negotiation_interface_type interface_type; unsigned interface_version; }; #define RETRO_ENVIRONMENT_SET_HW_RENDER_CONTEXT_NEGOTIATION_INTERFACE (43 | RETRO_ENVIRONMENT_EXPERIMENTAL) /* const struct retro_hw_render_context_negotiation_interface * -- * Sets an interface which lets the libretro core negotiate with frontend how a context is created. * The semantics of this interface depends on which API is used in SET_HW_RENDER earlier. * This interface will be used when the frontend is trying to create a HW rendering context, * so it will be used after SET_HW_RENDER, but before the context_reset callback. */ #define RETRO_MEMDESC_CONST (1 << 0) /* The frontend will never change this memory area once retro_load_game has returned. */ #define RETRO_MEMDESC_BIGENDIAN (1 << 1) /* The memory area contains big endian data. Default is little endian. */ #define RETRO_MEMDESC_ALIGN_2 (1 << 16) /* All memory access in this area is aligned to their own size, or 2, whichever is smaller. */ #define RETRO_MEMDESC_ALIGN_4 (2 << 16) #define RETRO_MEMDESC_ALIGN_8 (3 << 16) #define RETRO_MEMDESC_MINSIZE_2 (1 << 24) /* All memory in this region is accessed at least 2 bytes at the time. */ #define RETRO_MEMDESC_MINSIZE_4 (2 << 24) #define RETRO_MEMDESC_MINSIZE_8 (3 << 24) struct retro_memory_descriptor { uint64_t flags; /* Pointer to the start of the relevant ROM or RAM chip. * It's strongly recommended to use 'offset' if possible, rather than * doing math on the pointer. * * If the same byte is mapped my multiple descriptors, their descriptors * must have the same pointer. * If 'start' does not point to the first byte in the pointer, put the * difference in 'offset' instead. * * May be NULL if there's nothing usable here (e.g. hardware registers and * open bus). No flags should be set if the pointer is NULL. * It's recommended to minimize the number of descriptors if possible, * but not mandatory. */ void *ptr; size_t offset; /* This is the location in the emulated address space * where the mapping starts. */ size_t start; /* Which bits must be same as in 'start' for this mapping to apply. * The first memory descriptor to claim a certain byte is the one * that applies. * A bit which is set in 'start' must also be set in this. * Can be zero, in which case each byte is assumed mapped exactly once. * In this case, 'len' must be a power of two. */ size_t select; /* If this is nonzero, the set bits are assumed not connected to the * memory chip's address pins. */ size_t disconnect; /* This one tells the size of the current memory area. * If, after start+disconnect are applied, the address is higher than * this, the highest bit of the address is cleared. * * If the address is still too high, the next highest bit is cleared. * Can be zero, in which case it's assumed to be infinite (as limited * by 'select' and 'disconnect'). */ size_t len; /* To go from emulated address to physical address, the following * order applies: * Subtract 'start', pick off 'disconnect', apply 'len', add 'offset'. */ /* The address space name must consist of only a-zA-Z0-9_-, * should be as short as feasible (maximum length is 8 plus the NUL), * and may not be any other address space plus one or more 0-9A-F * at the end. * However, multiple memory descriptors for the same address space is * allowed, and the address space name can be empty. NULL is treated * as empty. * * Address space names are case sensitive, but avoid lowercase if possible. * The same pointer may exist in multiple address spaces. * * Examples: * blank+blank - valid (multiple things may be mapped in the same namespace) * 'Sp'+'Sp' - valid (multiple things may be mapped in the same namespace) * 'A'+'B' - valid (neither is a prefix of each other) * 'S'+blank - valid ('S' is not in 0-9A-F) * 'a'+blank - valid ('a' is not in 0-9A-F) * 'a'+'A' - valid (neither is a prefix of each other) * 'AR'+blank - valid ('R' is not in 0-9A-F) * 'ARB'+blank - valid (the B can't be part of the address either, because * there is no namespace 'AR') * blank+'B' - not valid, because it's ambigous which address space B1234 * would refer to. * The length can't be used for that purpose; the frontend may want * to append arbitrary data to an address, without a separator. */ const char *addrspace; /* TODO: When finalizing this one, add a description field, which should be * "WRAM" or something roughly equally long. */ /* TODO: When finalizing this one, replace 'select' with 'limit', which tells * which bits can vary and still refer to the same address (limit = ~select). * TODO: limit? range? vary? something else? */ /* TODO: When finalizing this one, if 'len' is above what 'select' (or * 'limit') allows, it's bankswitched. Bankswitched data must have both 'len' * and 'select' != 0, and the mappings don't tell how the system switches the * banks. */ /* TODO: When finalizing this one, fix the 'len' bit removal order. * For len=0x1800, pointer 0x1C00 should go to 0x1400, not 0x0C00. * Algorithm: Take bits highest to lowest, but if it goes above len, clear * the most recent addition and continue on the next bit. * TODO: Can the above be optimized? Is "remove the lowest bit set in both * pointer and 'len'" equivalent? */ /* TODO: Some emulators (MAME?) emulate big endian systems by only accessing * the emulated memory in 32-bit chunks, native endian. But that's nothing * compared to Darek Mihocka * (section Emulation 103 - Nearly Free Byte Reversal) - he flips the ENTIRE * RAM backwards! I'll want to represent both of those, via some flags. * * I suspect MAME either didn't think of that idea, or don't want the #ifdef. * Not sure which, nor do I really care. */ /* TODO: Some of those flags are unused and/or don't really make sense. Clean * them up. */ }; /* The frontend may use the largest value of 'start'+'select' in a * certain namespace to infer the size of the address space. * * If the address space is larger than that, a mapping with .ptr=NULL * should be at the end of the array, with .select set to all ones for * as long as the address space is big. * * Sample descriptors (minus .ptr, and RETRO_MEMFLAG_ on the flags): * SNES WRAM: * .start=0x7E0000, .len=0x20000 * (Note that this must be mapped before the ROM in most cases; some of the * ROM mappers * try to claim $7E0000, or at least $7E8000.) * SNES SPC700 RAM: * .addrspace="S", .len=0x10000 * SNES WRAM mirrors: * .flags=MIRROR, .start=0x000000, .select=0xC0E000, .len=0x2000 * .flags=MIRROR, .start=0x800000, .select=0xC0E000, .len=0x2000 * SNES WRAM mirrors, alternate equivalent descriptor: * .flags=MIRROR, .select=0x40E000, .disconnect=~0x1FFF * (Various similar constructions can be created by combining parts of * the above two.) * SNES LoROM (512KB, mirrored a couple of times): * .flags=CONST, .start=0x008000, .select=0x408000, .disconnect=0x8000, .len=512*1024 * .flags=CONST, .start=0x400000, .select=0x400000, .disconnect=0x8000, .len=512*1024 * SNES HiROM (4MB): * .flags=CONST, .start=0x400000, .select=0x400000, .len=4*1024*1024 * .flags=CONST, .offset=0x8000, .start=0x008000, .select=0x408000, .len=4*1024*1024 * SNES ExHiROM (8MB): * .flags=CONST, .offset=0, .start=0xC00000, .select=0xC00000, .len=4*1024*1024 * .flags=CONST, .offset=4*1024*1024, .start=0x400000, .select=0xC00000, .len=4*1024*1024 * .flags=CONST, .offset=0x8000, .start=0x808000, .select=0xC08000, .len=4*1024*1024 * .flags=CONST, .offset=4*1024*1024+0x8000, .start=0x008000, .select=0xC08000, .len=4*1024*1024 * Clarify the size of the address space: * .ptr=NULL, .select=0xFFFFFF * .len can be implied by .select in many of them, but was included for clarity. */ struct retro_memory_map { const struct retro_memory_descriptor *descriptors; unsigned num_descriptors; }; struct retro_controller_description { /* Human-readable description of the controller. Even if using a generic * input device type, this can be set to the particular device type the * core uses. */ const char *desc; /* Device type passed to retro_set_controller_port_device(). If the device * type is a sub-class of a generic input device type, use the * RETRO_DEVICE_SUBCLASS macro to create an ID. * * E.g. RETRO_DEVICE_SUBCLASS(RETRO_DEVICE_JOYPAD, 1). */ unsigned id; }; struct retro_controller_info { const struct retro_controller_description *types; unsigned num_types; }; struct retro_subsystem_memory_info { /* The extension associated with a memory type, e.g. "psram". */ const char *extension; /* The memory type for retro_get_memory(). This should be at * least 0x100 to avoid conflict with standardized * libretro memory types. */ unsigned type; }; struct retro_subsystem_rom_info { /* Describes what the content is (SGB BIOS, GB ROM, etc). */ const char *desc; /* Same definition as retro_get_system_info(). */ const char *valid_extensions; /* Same definition as retro_get_system_info(). */ bool need_fullpath; /* Same definition as retro_get_system_info(). */ bool block_extract; /* This is set if the content is required to load a game. * If this is set to false, a zeroed-out retro_game_info can be passed. */ bool required; /* Content can have multiple associated persistent * memory types (retro_get_memory()). */ const struct retro_subsystem_memory_info *memory; unsigned num_memory; }; struct retro_subsystem_info { /* Human-readable string of the subsystem type, e.g. "Super GameBoy" */ const char *desc; /* A computer friendly short string identifier for the subsystem type. * This name must be [a-z]. * E.g. if desc is "Super GameBoy", this can be "sgb". * This identifier can be used for command-line interfaces, etc. */ const char *ident; /* Infos for each content file. The first entry is assumed to be the * "most significant" content for frontend purposes. * E.g. with Super GameBoy, the first content should be the GameBoy ROM, * as it is the most "significant" content to a user. * If a frontend creates new file paths based on the content used * (e.g. savestates), it should use the path for the first ROM to do so. */ const struct retro_subsystem_rom_info *roms; /* Number of content files associated with a subsystem. */ unsigned num_roms; /* The type passed to retro_load_game_special(). */ unsigned id; }; typedef void (RETRO_CALLCONV *retro_proc_address_t)(void); /* libretro API extension functions: * (None here so far). * * Get a symbol from a libretro core. * Cores should only return symbols which are actual * extensions to the libretro API. * * Frontends should not use this to obtain symbols to standard * libretro entry points (static linking or dlsym). * * The symbol name must be equal to the function name, * e.g. if void retro_foo(void); exists, the symbol must be called "retro_foo". * The returned function pointer must be cast to the corresponding type. */ typedef retro_proc_address_t (RETRO_CALLCONV *retro_get_proc_address_t)(const char *sym); struct retro_get_proc_address_interface { retro_get_proc_address_t get_proc_address; }; enum retro_log_level { RETRO_LOG_DEBUG = 0, RETRO_LOG_INFO, RETRO_LOG_WARN, RETRO_LOG_ERROR, RETRO_LOG_DUMMY = INT_MAX }; /* Logging function. Takes log level argument as well. */ typedef void (RETRO_CALLCONV *retro_log_printf_t)(enum retro_log_level level, const char *fmt, ...); struct retro_log_callback { retro_log_printf_t log; }; /* Performance related functions */ /* ID values for SIMD CPU features */ #define RETRO_SIMD_SSE (1 << 0) #define RETRO_SIMD_SSE2 (1 << 1) #define RETRO_SIMD_VMX (1 << 2) #define RETRO_SIMD_VMX128 (1 << 3) #define RETRO_SIMD_AVX (1 << 4) #define RETRO_SIMD_NEON (1 << 5) #define RETRO_SIMD_SSE3 (1 << 6) #define RETRO_SIMD_SSSE3 (1 << 7) #define RETRO_SIMD_MMX (1 << 8) #define RETRO_SIMD_MMXEXT (1 << 9) #define RETRO_SIMD_SSE4 (1 << 10) #define RETRO_SIMD_SSE42 (1 << 11) #define RETRO_SIMD_AVX2 (1 << 12) #define RETRO_SIMD_VFPU (1 << 13) #define RETRO_SIMD_PS (1 << 14) #define RETRO_SIMD_AES (1 << 15) #define RETRO_SIMD_VFPV3 (1 << 16) #define RETRO_SIMD_VFPV4 (1 << 17) #define RETRO_SIMD_POPCNT (1 << 18) #define RETRO_SIMD_MOVBE (1 << 19) typedef uint64_t retro_perf_tick_t; typedef int64_t retro_time_t; struct retro_perf_counter { const char *ident; retro_perf_tick_t start; retro_perf_tick_t total; retro_perf_tick_t call_cnt; bool registered; }; /* Returns current time in microseconds. * Tries to use the most accurate timer available. */ typedef retro_time_t (RETRO_CALLCONV *retro_perf_get_time_usec_t)(void); /* A simple counter. Usually nanoseconds, but can also be CPU cycles. * Can be used directly if desired (when creating a more sophisticated * performance counter system). * */ typedef retro_perf_tick_t (RETRO_CALLCONV *retro_perf_get_counter_t)(void); /* Returns a bit-mask of detected CPU features (RETRO_SIMD_*). */ typedef uint64_t (RETRO_CALLCONV *retro_get_cpu_features_t)(void); /* Asks frontend to log and/or display the state of performance counters. * Performance counters can always be poked into manually as well. */ typedef void (RETRO_CALLCONV *retro_perf_log_t)(void); /* Register a performance counter. * ident field must be set with a discrete value and other values in * retro_perf_counter must be 0. * Registering can be called multiple times. To avoid calling to * frontend redundantly, you can check registered field first. */ typedef void (RETRO_CALLCONV *retro_perf_register_t)(struct retro_perf_counter *counter); /* Starts a registered counter. */ typedef void (RETRO_CALLCONV *retro_perf_start_t)(struct retro_perf_counter *counter); /* Stops a registered counter. */ typedef void (RETRO_CALLCONV *retro_perf_stop_t)(struct retro_perf_counter *counter); /* For convenience it can be useful to wrap register, start and stop in macros. * E.g.: * #ifdef LOG_PERFORMANCE * #define RETRO_PERFORMANCE_INIT(perf_cb, name) static struct retro_perf_counter name = {#name}; if (!name.registered) perf_cb.perf_register(&(name)) * #define RETRO_PERFORMANCE_START(perf_cb, name) perf_cb.perf_start(&(name)) * #define RETRO_PERFORMANCE_STOP(perf_cb, name) perf_cb.perf_stop(&(name)) * #else * ... Blank macros ... * #endif * * These can then be used mid-functions around code snippets. * * extern struct retro_perf_callback perf_cb; * Somewhere in the core. * * void do_some_heavy_work(void) * { * RETRO_PERFORMANCE_INIT(cb, work_1; * RETRO_PERFORMANCE_START(cb, work_1); * heavy_work_1(); * RETRO_PERFORMANCE_STOP(cb, work_1); * * RETRO_PERFORMANCE_INIT(cb, work_2); * RETRO_PERFORMANCE_START(cb, work_2); * heavy_work_2(); * RETRO_PERFORMANCE_STOP(cb, work_2); * } * * void retro_deinit(void) * { * perf_cb.perf_log(); * Log all perf counters here for example. * } */ struct retro_perf_callback { retro_perf_get_time_usec_t get_time_usec; retro_get_cpu_features_t get_cpu_features; retro_perf_get_counter_t get_perf_counter; retro_perf_register_t perf_register; retro_perf_start_t perf_start; retro_perf_stop_t perf_stop; retro_perf_log_t perf_log; }; /* FIXME: Document the sensor API and work out behavior. * It will be marked as experimental until then. */ enum retro_sensor_action { RETRO_SENSOR_ACCELEROMETER_ENABLE = 0, RETRO_SENSOR_ACCELEROMETER_DISABLE, RETRO_SENSOR_DUMMY = INT_MAX }; /* Id values for SENSOR types. */ #define RETRO_SENSOR_ACCELEROMETER_X 0 #define RETRO_SENSOR_ACCELEROMETER_Y 1 #define RETRO_SENSOR_ACCELEROMETER_Z 2 typedef bool (RETRO_CALLCONV *retro_set_sensor_state_t)(unsigned port, enum retro_sensor_action action, unsigned rate); typedef float (RETRO_CALLCONV *retro_sensor_get_input_t)(unsigned port, unsigned id); struct retro_sensor_interface { retro_set_sensor_state_t set_sensor_state; retro_sensor_get_input_t get_sensor_input; }; enum retro_camera_buffer { RETRO_CAMERA_BUFFER_OPENGL_TEXTURE = 0, RETRO_CAMERA_BUFFER_RAW_FRAMEBUFFER, RETRO_CAMERA_BUFFER_DUMMY = INT_MAX }; /* Starts the camera driver. Can only be called in retro_run(). */ typedef bool (RETRO_CALLCONV *retro_camera_start_t)(void); /* Stops the camera driver. Can only be called in retro_run(). */ typedef void (RETRO_CALLCONV *retro_camera_stop_t)(void); /* Callback which signals when the camera driver is initialized * and/or deinitialized. * retro_camera_start_t can be called in initialized callback. */ typedef void (RETRO_CALLCONV *retro_camera_lifetime_status_t)(void); /* A callback for raw framebuffer data. buffer points to an XRGB8888 buffer. * Width, height and pitch are similar to retro_video_refresh_t. * First pixel is top-left origin. */ typedef void (RETRO_CALLCONV *retro_camera_frame_raw_framebuffer_t)(const uint32_t *buffer, unsigned width, unsigned height, size_t pitch); /* A callback for when OpenGL textures are used. * * texture_id is a texture owned by camera driver. * Its state or content should be considered immutable, except for things like * texture filtering and clamping. * * texture_target is the texture target for the GL texture. * These can include e.g. GL_TEXTURE_2D, GL_TEXTURE_RECTANGLE, and possibly * more depending on extensions. * * affine points to a packed 3x3 column-major matrix used to apply an affine * transform to texture coordinates. (affine_matrix * vec3(coord_x, coord_y, 1.0)) * After transform, normalized texture coord (0, 0) should be bottom-left * and (1, 1) should be top-right (or (width, height) for RECTANGLE). * * GL-specific typedefs are avoided here to avoid relying on gl.h in * the API definition. */ typedef void (RETRO_CALLCONV *retro_camera_frame_opengl_texture_t)(unsigned texture_id, unsigned texture_target, const float *affine); struct retro_camera_callback { /* Set by libretro core. * Example bitmask: caps = (1 << RETRO_CAMERA_BUFFER_OPENGL_TEXTURE) | (1 << RETRO_CAMERA_BUFFER_RAW_FRAMEBUFFER). */ uint64_t caps; /* Desired resolution for camera. Is only used as a hint. */ unsigned width; unsigned height; /* Set by frontend. */ retro_camera_start_t start; retro_camera_stop_t stop; /* Set by libretro core if raw framebuffer callbacks will be used. */ retro_camera_frame_raw_framebuffer_t frame_raw_framebuffer; /* Set by libretro core if OpenGL texture callbacks will be used. */ retro_camera_frame_opengl_texture_t frame_opengl_texture; /* Set by libretro core. Called after camera driver is initialized and * ready to be started. * Can be NULL, in which this callback is not called. */ retro_camera_lifetime_status_t initialized; /* Set by libretro core. Called right before camera driver is * deinitialized. * Can be NULL, in which this callback is not called. */ retro_camera_lifetime_status_t deinitialized; }; /* Sets the interval of time and/or distance at which to update/poll * location-based data. * * To ensure compatibility with all location-based implementations, * values for both interval_ms and interval_distance should be provided. * * interval_ms is the interval expressed in milliseconds. * interval_distance is the distance interval expressed in meters. */ typedef void (RETRO_CALLCONV *retro_location_set_interval_t)(unsigned interval_ms, unsigned interval_distance); /* Start location services. The device will start listening for changes to the * current location at regular intervals (which are defined with * retro_location_set_interval_t). */ typedef bool (RETRO_CALLCONV *retro_location_start_t)(void); /* Stop location services. The device will stop listening for changes * to the current location. */ typedef void (RETRO_CALLCONV *retro_location_stop_t)(void); /* Get the position of the current location. Will set parameters to * 0 if no new location update has happened since the last time. */ typedef bool (RETRO_CALLCONV *retro_location_get_position_t)(double *lat, double *lon, double *horiz_accuracy, double *vert_accuracy); /* Callback which signals when the location driver is initialized * and/or deinitialized. * retro_location_start_t can be called in initialized callback. */ typedef void (RETRO_CALLCONV *retro_location_lifetime_status_t)(void); struct retro_location_callback { retro_location_start_t start; retro_location_stop_t stop; retro_location_get_position_t get_position; retro_location_set_interval_t set_interval; retro_location_lifetime_status_t initialized; retro_location_lifetime_status_t deinitialized; }; enum retro_rumble_effect { RETRO_RUMBLE_STRONG = 0, RETRO_RUMBLE_WEAK = 1, RETRO_RUMBLE_DUMMY = INT_MAX }; /* Sets rumble state for joypad plugged in port 'port'. * Rumble effects are controlled independently, * and setting e.g. strong rumble does not override weak rumble. * Strength has a range of [0, 0xffff]. * * Returns true if rumble state request was honored. * Calling this before first retro_run() is likely to return false. */ typedef bool (RETRO_CALLCONV *retro_set_rumble_state_t)(unsigned port, enum retro_rumble_effect effect, uint16_t strength); struct retro_rumble_interface { retro_set_rumble_state_t set_rumble_state; }; /* Notifies libretro that audio data should be written. */ typedef void (RETRO_CALLCONV *retro_audio_callback_t)(void); /* True: Audio driver in frontend is active, and callback is * expected to be called regularily. * False: Audio driver in frontend is paused or inactive. * Audio callback will not be called until set_state has been * called with true. * Initial state is false (inactive). */ typedef void (RETRO_CALLCONV *retro_audio_set_state_callback_t)(bool enabled); struct retro_audio_callback { retro_audio_callback_t callback; retro_audio_set_state_callback_t set_state; }; /* Notifies a libretro core of time spent since last invocation * of retro_run() in microseconds. * * It will be called right before retro_run() every frame. * The frontend can tamper with timing to support cases like * fast-forward, slow-motion and framestepping. * * In those scenarios the reference frame time value will be used. */ typedef int64_t retro_usec_t; typedef void (RETRO_CALLCONV *retro_frame_time_callback_t)(retro_usec_t usec); struct retro_frame_time_callback { retro_frame_time_callback_t callback; /* Represents the time of one frame. It is computed as * 1000000 / fps, but the implementation will resolve the * rounding to ensure that framestepping, etc is exact. */ retro_usec_t reference; }; /* Pass this to retro_video_refresh_t if rendering to hardware. * Passing NULL to retro_video_refresh_t is still a frame dupe as normal. * */ #define RETRO_HW_FRAME_BUFFER_VALID ((void*)-1) /* Invalidates the current HW context. * Any GL state is lost, and must not be deinitialized explicitly. * If explicit deinitialization is desired by the libretro core, * it should implement context_destroy callback. * If called, all GPU resources must be reinitialized. * Usually called when frontend reinits video driver. * Also called first time video driver is initialized, * allowing libretro core to initialize resources. */ typedef void (RETRO_CALLCONV *retro_hw_context_reset_t)(void); /* Gets current framebuffer which is to be rendered to. * Could change every frame potentially. */ typedef uintptr_t (RETRO_CALLCONV *retro_hw_get_current_framebuffer_t)(void); /* Get a symbol from HW context. */ typedef retro_proc_address_t (RETRO_CALLCONV *retro_hw_get_proc_address_t)(const char *sym); enum retro_hw_context_type { RETRO_HW_CONTEXT_NONE = 0, /* OpenGL 2.x. Driver can choose to use latest compatibility context. */ RETRO_HW_CONTEXT_OPENGL = 1, /* OpenGL ES 2.0. */ RETRO_HW_CONTEXT_OPENGLES2 = 2, /* Modern desktop core GL context. Use version_major/ * version_minor fields to set GL version. */ RETRO_HW_CONTEXT_OPENGL_CORE = 3, /* OpenGL ES 3.0 */ RETRO_HW_CONTEXT_OPENGLES3 = 4, /* OpenGL ES 3.1+. Set version_major/version_minor. For GLES2 and GLES3, * use the corresponding enums directly. */ RETRO_HW_CONTEXT_OPENGLES_VERSION = 5, /* Vulkan, see RETRO_ENVIRONMENT_GET_HW_RENDER_INTERFACE. */ RETRO_HW_CONTEXT_VULKAN = 6, RETRO_HW_CONTEXT_DUMMY = INT_MAX }; struct retro_hw_render_callback { /* Which API to use. Set by libretro core. */ enum retro_hw_context_type context_type; /* Called when a context has been created or when it has been reset. * An OpenGL context is only valid after context_reset() has been called. * * When context_reset is called, OpenGL resources in the libretro * implementation are guaranteed to be invalid. * * It is possible that context_reset is called multiple times during an * application lifecycle. * If context_reset is called without any notification (context_destroy), * the OpenGL context was lost and resources should just be recreated * without any attempt to "free" old resources. */ retro_hw_context_reset_t context_reset; /* Set by frontend. * TODO: This is rather obsolete. The frontend should not * be providing preallocated framebuffers. */ retro_hw_get_current_framebuffer_t get_current_framebuffer; /* Set by frontend. */ retro_hw_get_proc_address_t get_proc_address; /* Set if render buffers should have depth component attached. * TODO: Obsolete. */ bool depth; /* Set if stencil buffers should be attached. * TODO: Obsolete. */ bool stencil; /* If depth and stencil are true, a packed 24/8 buffer will be added. * Only attaching stencil is invalid and will be ignored. */ /* Use conventional bottom-left origin convention. If false, * standard libretro top-left origin semantics are used. * TODO: Move to GL specific interface. */ bool bottom_left_origin; /* Major version number for core GL context or GLES 3.1+. */ unsigned version_major; /* Minor version number for core GL context or GLES 3.1+. */ unsigned version_minor; /* If this is true, the frontend will go very far to avoid * resetting context in scenarios like toggling fullscreen, etc. * TODO: Obsolete? Maybe frontend should just always assume this ... */ bool cache_context; /* The reset callback might still be called in extreme situations * such as if the context is lost beyond recovery. * * For optimal stability, set this to false, and allow context to be * reset at any time. */ /* A callback to be called before the context is destroyed in a * controlled way by the frontend. */ retro_hw_context_reset_t context_destroy; /* OpenGL resources can be deinitialized cleanly at this step. * context_destroy can be set to NULL, in which resources will * just be destroyed without any notification. * * Even when context_destroy is non-NULL, it is possible that * context_reset is called without any destroy notification. * This happens if context is lost by external factors (such as * notified by GL_ARB_robustness). * * In this case, the context is assumed to be already dead, * and the libretro implementation must not try to free any OpenGL * resources in the subsequent context_reset. */ /* Creates a debug context. */ bool debug_context; }; /* Callback type passed in RETRO_ENVIRONMENT_SET_KEYBOARD_CALLBACK. * Called by the frontend in response to keyboard events. * down is set if the key is being pressed, or false if it is being released. * keycode is the RETROK value of the char. * character is the text character of the pressed key. (UTF-32). * key_modifiers is a set of RETROKMOD values or'ed together. * * The pressed/keycode state can be indepedent of the character. * It is also possible that multiple characters are generated from a * single keypress. * Keycode events should be treated separately from character events. * However, when possible, the frontend should try to synchronize these. * If only a character is posted, keycode should be RETROK_UNKNOWN. * * Similarily if only a keycode event is generated with no corresponding * character, character should be 0. */ typedef void (RETRO_CALLCONV *retro_keyboard_event_t)(bool down, unsigned keycode, uint32_t character, uint16_t key_modifiers); struct retro_keyboard_callback { retro_keyboard_event_t callback; }; /* Callbacks for RETRO_ENVIRONMENT_SET_DISK_CONTROL_INTERFACE. * Should be set for implementations which can swap out multiple disk * images in runtime. * * If the implementation can do this automatically, it should strive to do so. * However, there are cases where the user must manually do so. * * Overview: To swap a disk image, eject the disk image with * set_eject_state(true). * Set the disk index with set_image_index(index). Insert the disk again * with set_eject_state(false). */ /* If ejected is true, "ejects" the virtual disk tray. * When ejected, the disk image index can be set. */ typedef bool (RETRO_CALLCONV *retro_set_eject_state_t)(bool ejected); /* Gets current eject state. The initial state is 'not ejected'. */ typedef bool (RETRO_CALLCONV *retro_get_eject_state_t)(void); /* Gets current disk index. First disk is index 0. * If return value is >= get_num_images(), no disk is currently inserted. */ typedef unsigned (RETRO_CALLCONV *retro_get_image_index_t)(void); /* Sets image index. Can only be called when disk is ejected. * The implementation supports setting "no disk" by using an * index >= get_num_images(). */ typedef bool (RETRO_CALLCONV *retro_set_image_index_t)(unsigned index); /* Gets total number of images which are available to use. */ typedef unsigned (RETRO_CALLCONV *retro_get_num_images_t)(void); struct retro_game_info; /* Replaces the disk image associated with index. * Arguments to pass in info have same requirements as retro_load_game(). * Virtual disk tray must be ejected when calling this. * * Replacing a disk image with info = NULL will remove the disk image * from the internal list. * As a result, calls to get_image_index() can change. * * E.g. replace_image_index(1, NULL), and previous get_image_index() * returned 4 before. * Index 1 will be removed, and the new index is 3. */ typedef bool (RETRO_CALLCONV *retro_replace_image_index_t)(unsigned index, const struct retro_game_info *info); /* Adds a new valid index (get_num_images()) to the internal disk list. * This will increment subsequent return values from get_num_images() by 1. * This image index cannot be used until a disk image has been set * with replace_image_index. */ typedef bool (RETRO_CALLCONV *retro_add_image_index_t)(void); struct retro_disk_control_callback { retro_set_eject_state_t set_eject_state; retro_get_eject_state_t get_eject_state; retro_get_image_index_t get_image_index; retro_set_image_index_t set_image_index; retro_get_num_images_t get_num_images; retro_replace_image_index_t replace_image_index; retro_add_image_index_t add_image_index; }; enum retro_pixel_format { /* 0RGB1555, native endian. * 0 bit must be set to 0. * This pixel format is default for compatibility concerns only. * If a 15/16-bit pixel format is desired, consider using RGB565. */ RETRO_PIXEL_FORMAT_0RGB1555 = 0, /* XRGB8888, native endian. * X bits are ignored. */ RETRO_PIXEL_FORMAT_XRGB8888 = 1, /* RGB565, native endian. * This pixel format is the recommended format to use if a 15/16-bit * format is desired as it is the pixel format that is typically * available on a wide range of low-power devices. * * It is also natively supported in APIs like OpenGL ES. */ RETRO_PIXEL_FORMAT_RGB565 = 2, /* Ensure sizeof() == sizeof(int). */ RETRO_PIXEL_FORMAT_UNKNOWN = INT_MAX }; struct retro_message { const char *msg; /* Message to be displayed. */ unsigned frames; /* Duration in frames of message. */ }; /* Describes how the libretro implementation maps a libretro input bind * to its internal input system through a human readable string. * This string can be used to better let a user configure input. */ struct retro_input_descriptor { /* Associates given parameters with a description. */ unsigned port; unsigned device; unsigned index; unsigned id; /* Human readable description for parameters. * The pointer must remain valid until * retro_unload_game() is called. */ const char *description; }; struct retro_system_info { /* All pointers are owned by libretro implementation, and pointers must * remain valid until retro_deinit() is called. */ const char *library_name; /* Descriptive name of library. Should not * contain any version numbers, etc. */ const char *library_version; /* Descriptive version of core. */ const char *valid_extensions; /* A string listing probably content * extensions the core will be able to * load, separated with pipe. * I.e. "bin|rom|iso". * Typically used for a GUI to filter * out extensions. */ /* If true, retro_load_game() is guaranteed to provide a valid pathname * in retro_game_info::path. * ::data and ::size are both invalid. * * If false, ::data and ::size are guaranteed to be valid, but ::path * might not be valid. * * This is typically set to true for libretro implementations that must * load from file. * Implementations should strive for setting this to false, as it allows * the frontend to perform patching, etc. */ bool need_fullpath; /* If true, the frontend is not allowed to extract any archives before * loading the real content. * Necessary for certain libretro implementations that load games * from zipped archives. */ bool block_extract; }; struct retro_game_geometry { unsigned base_width; /* Nominal video width of game. */ unsigned base_height; /* Nominal video height of game. */ unsigned max_width; /* Maximum possible width of game. */ unsigned max_height; /* Maximum possible height of game. */ float aspect_ratio; /* Nominal aspect ratio of game. If * aspect_ratio is <= 0.0, an aspect ratio * of base_width / base_height is assumed. * A frontend could override this setting, * if desired. */ }; struct retro_system_timing { double fps; /* FPS of video content. */ double sample_rate; /* Sampling rate of audio. */ }; struct retro_system_av_info { struct retro_game_geometry geometry; struct retro_system_timing timing; }; struct retro_variable { /* Variable to query in RETRO_ENVIRONMENT_GET_VARIABLE. * If NULL, obtains the complete environment string if more * complex parsing is necessary. * The environment string is formatted as key-value pairs * delimited by semicolons as so: * "key1=value1;key2=value2;..." */ const char *key; /* Value to be obtained. If key does not exist, it is set to NULL. */ const char *value; }; struct retro_game_info { const char *path; /* Path to game, UTF-8 encoded. * Usually used as a reference. * May be NULL if rom was loaded from stdin * or similar. * retro_system_info::need_fullpath guaranteed * that this path is valid. */ const void *data; /* Memory buffer of loaded game. Will be NULL * if need_fullpath was set. */ size_t size; /* Size of memory buffer. */ const char *meta; /* String of implementation specific meta-data. */ }; #define RETRO_MEMORY_ACCESS_WRITE (1 << 0) /* The core will write to the buffer provided by retro_framebuffer::data. */ #define RETRO_MEMORY_ACCESS_READ (1 << 1) /* The core will read from retro_framebuffer::data. */ #define RETRO_MEMORY_TYPE_CACHED (1 << 0) /* The memory in data is cached. * If not cached, random writes and/or reading from the buffer is expected to be very slow. */ struct retro_framebuffer { void *data; /* The framebuffer which the core can render into. Set by frontend in GET_CURRENT_SOFTWARE_FRAMEBUFFER. The initial contents of data are unspecified. */ unsigned width; /* The framebuffer width used by the core. Set by core. */ unsigned height; /* The framebuffer height used by the core. Set by core. */ size_t pitch; /* The number of bytes between the beginning of a scanline, and beginning of the next scanline. Set by frontend in GET_CURRENT_SOFTWARE_FRAMEBUFFER. */ enum retro_pixel_format format; /* The pixel format the core must use to render into data. This format could differ from the format used in SET_PIXEL_FORMAT. Set by frontend in GET_CURRENT_SOFTWARE_FRAMEBUFFER. */ unsigned access_flags; /* How the core will access the memory in the framebuffer. RETRO_MEMORY_ACCESS_* flags. Set by core. */ unsigned memory_flags; /* Flags telling core how the memory has been mapped. RETRO_MEMORY_TYPE_* flags. Set by frontend in GET_CURRENT_SOFTWARE_FRAMEBUFFER. */ }; /* Callbacks */ /* Environment callback. Gives implementations a way of performing * uncommon tasks. Extensible. */ typedef bool (RETRO_CALLCONV *retro_environment_t)(unsigned cmd, void *data); /* Render a frame. Pixel format is 15-bit 0RGB1555 native endian * unless changed (see RETRO_ENVIRONMENT_SET_PIXEL_FORMAT). * * Width and height specify dimensions of buffer. * Pitch specifices length in bytes between two lines in buffer. * * For performance reasons, it is highly recommended to have a frame * that is packed in memory, i.e. pitch == width * byte_per_pixel. * Certain graphic APIs, such as OpenGL ES, do not like textures * that are not packed in memory. */ typedef void (RETRO_CALLCONV *retro_video_refresh_t)(const void *data, unsigned width, unsigned height, size_t pitch); /* Renders a single audio frame. Should only be used if implementation * generates a single sample at a time. * Format is signed 16-bit native endian. */ typedef void (RETRO_CALLCONV *retro_audio_sample_t)(int16_t left, int16_t right); /* Renders multiple audio frames in one go. * * One frame is defined as a sample of left and right channels, interleaved. * I.e. int16_t buf[4] = { l, r, l, r }; would be 2 frames. * Only one of the audio callbacks must ever be used. */ typedef size_t (RETRO_CALLCONV *retro_audio_sample_batch_t)(const int16_t *data, size_t frames); /* Polls input. */ typedef void (RETRO_CALLCONV *retro_input_poll_t)(void); /* Queries for input for player 'port'. device will be masked with * RETRO_DEVICE_MASK. * * Specialization of devices such as RETRO_DEVICE_JOYPAD_MULTITAP that * have been set with retro_set_controller_port_device() * will still use the higher level RETRO_DEVICE_JOYPAD to request input. */ typedef int16_t (RETRO_CALLCONV *retro_input_state_t)(unsigned port, unsigned device, unsigned index, unsigned id); /* Sets callbacks. retro_set_environment() is guaranteed to be called * before retro_init(). * * The rest of the set_* functions are guaranteed to have been called * before the first call to retro_run() is made. */ RETRO_API void retro_set_environment(retro_environment_t); RETRO_API void retro_set_video_refresh(retro_video_refresh_t); RETRO_API void retro_set_audio_sample(retro_audio_sample_t); RETRO_API void retro_set_audio_sample_batch(retro_audio_sample_batch_t); RETRO_API void retro_set_input_poll(retro_input_poll_t); RETRO_API void retro_set_input_state(retro_input_state_t); /* Library global initialization/deinitialization. */ RETRO_API void retro_init(void); RETRO_API void retro_deinit(void); /* Must return RETRO_API_VERSION. Used to validate ABI compatibility * when the API is revised. */ RETRO_API unsigned retro_api_version(void); /* Gets statically known system info. Pointers provided in *info * must be statically allocated. * Can be called at any time, even before retro_init(). */ RETRO_API void retro_get_system_info(struct retro_system_info *info); /* Gets information about system audio/video timings and geometry. * Can be called only after retro_load_game() has successfully completed. * NOTE: The implementation of this function might not initialize every * variable if needed. * E.g. geom.aspect_ratio might not be initialized if core doesn't * desire a particular aspect ratio. */ RETRO_API void retro_get_system_av_info(struct retro_system_av_info *info); /* Sets device to be used for player 'port'. * By default, RETRO_DEVICE_JOYPAD is assumed to be plugged into all * available ports. * Setting a particular device type is not a guarantee that libretro cores * will only poll input based on that particular device type. It is only a * hint to the libretro core when a core cannot automatically detect the * appropriate input device type on its own. It is also relevant when a * core can change its behavior depending on device type. */ RETRO_API void retro_set_controller_port_device(unsigned port, unsigned device); /* Resets the current game. */ RETRO_API void retro_reset(void); /* Runs the game for one video frame. * During retro_run(), input_poll callback must be called at least once. * * If a frame is not rendered for reasons where a game "dropped" a frame, * this still counts as a frame, and retro_run() should explicitly dupe * a frame if GET_CAN_DUPE returns true. * In this case, the video callback can take a NULL argument for data. */ RETRO_API void retro_run(void); /* Returns the amount of data the implementation requires to serialize * internal state (save states). * Between calls to retro_load_game() and retro_unload_game(), the * returned size is never allowed to be larger than a previous returned * value, to ensure that the frontend can allocate a save state buffer once. */ RETRO_API size_t retro_serialize_size(void); /* Serializes internal state. If failed, or size is lower than * retro_serialize_size(), it should return false, true otherwise. */ RETRO_API bool retro_serialize(void *data, size_t size); RETRO_API bool retro_unserialize(const void *data, size_t size); RETRO_API void retro_cheat_reset(void); RETRO_API void retro_cheat_set(unsigned index, bool enabled, const char *code); /* Loads a game. */ RETRO_API bool retro_load_game(const struct retro_game_info *game); /* Loads a "special" kind of game. Should not be used, * except in extreme cases. */ RETRO_API bool retro_load_game_special( unsigned game_type, const struct retro_game_info *info, size_t num_info ); /* Unloads a currently loaded game. */ RETRO_API void retro_unload_game(void); /* Gets region of game. */ RETRO_API unsigned retro_get_region(void); /* Gets region of memory. */ RETRO_API void *retro_get_memory_data(unsigned id); RETRO_API size_t retro_get_memory_size(unsigned id); #ifdef __cplusplus } #endif #endif desmume/src/libretro-common/include/formats/000700 001750 001750 00000000000 12756420131 022323 5ustar00sergiosergio000000 000000 desmume/src/addons/slot2_auto.cpp000664 001750 001750 00000004614 12755534123 020213 0ustar00sergiosergio000000 000000 /* Copyright (C) 2013-2015 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the this software. If not, see . */ #include #include "../slot2.h" class Slot2_Auto : public ISlot2Interface { private: ISlot2Interface *mSelectedImplementation; public: Slot2_Auto() : mSelectedImplementation(NULL) { } virtual Slot2Info const* info() { static Slot2InfoSimple info("Auto","Slot2 (auto-selection) device emulation", 0xFE); return &info; } virtual void connect() { slot2_selected_type = slot2_DetermineType(); mSelectedImplementation = slot2_List[slot2_selected_type]; mSelectedImplementation->connect(); printf("Slot2 auto-selected device type: %s (0x%02X)\n", mSelectedImplementation->info()->name(), mSelectedImplementation->info()->id()); } virtual void disconnect() { if(mSelectedImplementation) mSelectedImplementation->disconnect(); mSelectedImplementation = NULL; } virtual void writeByte(u8 PROCNUM, u32 addr, u8 val) { mSelectedImplementation->writeByte(PROCNUM, addr, val); } virtual void writeWord(u8 PROCNUM, u32 addr, u16 val) { mSelectedImplementation->writeWord(PROCNUM, addr, val); } virtual void writeLong(u8 PROCNUM, u32 addr, u32 val) { mSelectedImplementation->writeLong(PROCNUM, addr, val); } virtual u8 readByte(u8 PROCNUM, u32 addr) { return mSelectedImplementation->readByte(PROCNUM, addr); } virtual u16 readWord(u8 PROCNUM, u32 addr) { return mSelectedImplementation->readWord(PROCNUM, addr); } virtual u32 readLong(u8 PROCNUM, u32 addr) { return mSelectedImplementation->readLong(PROCNUM, addr); } virtual void savestate(EMUFILE* os) { mSelectedImplementation->savestate(os); } virtual void loadstate(EMUFILE* is) { mSelectedImplementation->loadstate(is); } }; ISlot2Interface* construct_Slot2_Auto() { return new Slot2_Auto(); } desmume/src/utils/AsmJit/core/apibegin.h000664 001750 001750 00000002160 12755534123 021344 0ustar00sergiosergio000000 000000 // [AsmJit] // Complete JIT Assembler for C++ Language. // // [License] // Zlib - See COPYING file in this package. // [MSVC] #if defined(_MSC_VER) // Disable some warnings we know about #pragma warning(push) #pragma warning(disable: 4127) // conditional expression is constant #pragma warning(disable: 4251) // struct needs to have dll-interface to be used // by clients of struct ... #pragma warning(disable: 4275) // non dll-interface struct ... used as base for // dll-interface struct #pragma warning(disable: 4355) // this used in base member initializer list #pragma warning(disable: 4800) // forcing value to bool 'true' or 'false' // Rename symbols. #ifndef vsnprintf #define vsnprintf _vsnprintf #endif #ifndef snprintf #define snprintf _snprintf #endif #endif // _MSC_VER // [GNUC] #if defined(__GNUC__) // GCC warnings fix: I can't understand why GCC has no interface to push/pop // specific warnings. // # if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) >= 402001 // # pragma GCC diagnostic ignored "-w" // # endif #endif // __GNUC__ desmume/src/libretro-common/include/compat/intrinsics.h000664 001750 001750 00000005036 12755534123 024517 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2016 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (intrinsics.h). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef __LIBRETRO_SDK_COMPAT_INTRINSICS_H #define __LIBRETRO_SDK_COMPAT_INTRINSICS_H #include #include #include #include #include #ifdef _MSC_VER #if (_MSC_VER > 1310) #include #endif #endif RETRO_BEGIN_DECLS /* Count Leading Zero, unsigned 16bit input value */ static INLINE unsigned compat_clz_u16(uint16_t val) { #ifdef __GNUC__ return __builtin_clz(val << 16 | 0x8000); #else unsigned ret = 0; while(!(val & 0x8000) && ret < 16) { val <<= 1; ret++; } return ret; #endif } /* Count Trailing Zero */ #if defined(__GNUC__) && !defined(RARCH_CONSOLE) static INLINE int compat_ctz(unsigned x) { return __builtin_ctz(x); } #elif _MSC_VER >= 1400 static INLINE int compat_ctz(unsigned x) { unsigned long r = 0; _BitScanReverse((unsigned long*)&r, x); return (int)r; } #else /* Only checks at nibble granularity, * because that's what we need. */ static INLINE int compat_ctz(unsigned x) { if (x & 0x000f) return 0; if (x & 0x00f0) return 4; if (x & 0x0f00) return 8; if (x & 0xf000) return 12; return 16; } #endif RETRO_END_DECLS #endif desmume/src/slot1.h000664 001750 001750 00000010553 12755534123 015356 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2015 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the this software. If not, see . */ #ifndef __SLOT1_H__ #define __SLOT1_H__ #include #include "types.h" #include "MMU.h" class EMUFILE; class Slot1Info { public: virtual const char* name() const = 0; virtual const char* descr()const = 0; virtual const u8 id() const = 0; }; class Slot1InfoSimple : public Slot1Info { public: Slot1InfoSimple(const char* _name, const char* _descr, const u8 _id) : mName(_name) , mDescr(_descr) , mID(_id) { } virtual const char* name() const { return mName; } virtual const char* descr() const { return mDescr; } virtual const u8 id() const { return mID; } private: const char* mName, *mDescr; const u8 mID; }; class ISlot1Interface { public: //called to get info about device (description) virtual Slot1Info const* info() = 0; //called once when the emulator starts up, or when the device springs into existence virtual bool init() { return true; } //called when the emulator connects the device virtual void connect() { } //called when the emulator disconnects the device virtual void disconnect() { } //called when the emulator shuts down, or when the device disappears from existence virtual void shutdown() { } //called then the cpu begins a new command/block on the GC bus virtual void write_command(u8 PROCNUM, GC_Command command) { } //called when the cpu writes to the GC bus virtual void write_GCDATAIN(u8 PROCNUM, u32 val) { } //called when the cpu reads from the GC bus virtual u32 read_GCDATAIN(u8 PROCNUM) { return 0xFFFFFFFF; } //transfers a byte to the slot-1 device via auxspi, and returns the incoming byte //cpu is provided for diagnostic purposes only.. the slot-1 device wouldn't know which CPU it is. virtual u8 auxspi_transaction(int PROCNUM, u8 value) { return 0x00; } //called when the auxspi burst is ended (SPI chipselect in is going low) virtual void auxspi_reset(int PROCNUM) {} //called when NDS_FakeBoot terminates, emulate in here the BIOS behaviour virtual void post_fakeboot(int PROCNUM) {} virtual void savestate(EMUFILE* os) {} virtual void loadstate(EMUFILE* is) {} }; typedef ISlot1Interface* TISlot1InterfaceConstructor(); enum NDS_SLOT1_TYPE { NDS_SLOT1_NONE, // 0xFF - None NDS_SLOT1_RETAIL_AUTO, // 0xFE - autodetect which kind of retail card to use NDS_SLOT1_R4, // 0x03 - R4 flash card NDS_SLOT1_RETAIL_NAND, // 0x02 - Made in Ore/WarioWare D.I.Y. NDS_SLOT1_RETAIL_MCROM, // 0x01 - a standard MC (eeprom, flash, fram) -bearing retail card. Also supports motion, for now, because that's the way we originally coded it NDS_SLOT1_RETAIL_DEBUG, // 0x04 - for romhacking and fan-made translations NDS_SLOT1_COUNT //use to count addons - MUST BE LAST!!! }; extern ISlot1Interface* slot1_device; //the current slot1 device instance extern ISlot1Interface* slot1_List[NDS_SLOT1_COUNT]; extern NDS_SLOT1_TYPE slot1_selected_type; void slot1_Init(); bool slot1_Connect(); void slot1_Disconnect(); void slot1_Shutdown(); void slot1_Savestate(EMUFILE* os); void slot1_Loadstate(EMUFILE* is); //just disconnects and reconnects the device. ideally, the disconnection and connection would be called with sensible timing void slot1_Reset(); bool slot1_getTypeByID(u8 ID, NDS_SLOT1_TYPE &type); //change the current device bool slot1_Change(NDS_SLOT1_TYPE type); //change the current device by ID bool slot1_ChangeByID(u8 ID); //check on the current device NDS_SLOT1_TYPE slot1_GetCurrentType(); NDS_SLOT1_TYPE slot1_GetSelectedType(); extern bool slot1_R4_path_type; void slot1_SetFatDir(const std::string& dir, bool sameAsRom = false); std::string slot1_GetFatDir(); EMUFILE* slot1_GetFatImage(); #endif //__SLOT1_H__ desmume/src/utils/task.cpp000664 001750 001750 00000006745 12755534123 016761 0ustar00sergiosergio000000 000000 /* Copyright (C) 2009-2013 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the this software. If not, see . */ #include "types.h" #include "task.h" #include #include class Task::Impl { private: sthread_t *_thread; bool _isThreadRunning; public: Impl(); ~Impl(); void start(void); void execute(const TWork &work, void *param); void* finish(); void shutdown(); slock_t *mutex; scond_t *condWork; TWork workFunc; void *workFuncParam; void *ret; bool exitThread; }; static void taskProc(void *arg) { Task::Impl *ctx = (Task::Impl *)arg; do { slock_lock(ctx->mutex); while (!ctx->workFunc && !ctx->exitThread) scond_wait(ctx->condWork, ctx->mutex); if (ctx->workFunc) ctx->ret = ctx->workFunc(ctx->workFuncParam); else ctx->ret = NULL; ctx->workFunc = NULL; scond_signal(ctx->condWork); slock_unlock(ctx->mutex); } while(!ctx->exitThread); } Task::Impl::Impl() { _isThreadRunning = false; workFunc = NULL; workFuncParam = NULL; ret = NULL; exitThread = false; mutex = slock_new(); condWork = scond_new(); } Task::Impl::~Impl() { shutdown(); slock_free(mutex); scond_free(condWork); } void Task::Impl::start(void) { slock_lock(this->mutex); if (this->_isThreadRunning) { slock_unlock(this->mutex); return; } this->workFunc = NULL; this->workFuncParam = NULL; this->ret = NULL; this->exitThread = false; this->_isThreadRunning = true; this->_thread = (sthread_t*)sthread_create(&taskProc, this); slock_unlock(this->mutex); } void Task::Impl::execute(const TWork &work, void *param) { slock_lock(this->mutex); if (!work || !this->_isThreadRunning) goto end; this->workFunc = work; this->workFuncParam = param; scond_signal(this->condWork); end: slock_unlock(this->mutex); } void* Task::Impl::finish() { void *returnValue = NULL; slock_lock(this->mutex); if (!this->_isThreadRunning) goto end; while (this->workFunc != NULL) scond_wait(this->condWork, this->mutex); returnValue = this->ret; end: slock_unlock(this->mutex); return returnValue; } void Task::Impl::shutdown() { slock_lock(this->mutex); if (!this->_isThreadRunning) goto end; this->workFunc = NULL; this->exitThread = true; scond_signal(this->condWork); slock_unlock(this->mutex); sthread_join(this->_thread); slock_lock(this->mutex); this->_isThreadRunning = false; end: slock_unlock(this->mutex); } void Task::start(void) { impl->start(); } void Task::shutdown() { impl->shutdown(); } Task::Task() : impl(new Task::Impl()) {} Task::~Task() { delete impl; } void Task::execute(const TWork &work, void* param) { impl->execute(work,param); } void* Task::finish() { return impl->finish(); } desmume/src/utils/AsmJit/x86/x86compiler.cpp000664 001750 001750 00000052271 12755534123 022006 0ustar00sergiosergio000000 000000 // [AsmJit] // Complete JIT Assembler for C++ Language. // // [License] // Zlib - See COPYING file in this package. #define ASMJIT_EXPORTS // [Dependencies - AsmJit] #include "../core/intutil.h" #include "../core/stringutil.h" #include "../x86/x86assembler.h" #include "../x86/x86compiler.h" #include "../x86/x86compilercontext.h" #include "../x86/x86compilerfunc.h" #include "../x86/x86compileritem.h" #include "../x86/x86util.h" // [Api-Begin] #include "../core/apibegin.h" namespace AsmJit { // ============================================================================ // [AsmJit::CompilerUtil] // ============================================================================ bool CompilerUtil::isStack16ByteAligned() { // Stack is always aligned to 16-bytes when using 64-bit OS. bool result = (sizeof(uintptr_t) == 8); // Modern Linux, APPLE and UNIX guarantees stack alignment to 16 bytes by // default. I'm really not sure about all UNIX operating systems, because // 16-byte alignment is an addition to an older specification. #if (defined(__linux__) || \ defined(__linux) || \ defined(linux) || \ defined(__unix__) || \ defined(__FreeBSD__) || \ defined(__NetBSD__) || \ defined(__OpenBSD__) || \ defined(__DARWIN__) || \ defined(__APPLE__) ) result = true; #endif // __linux__ return result; } // ============================================================================ // [AsmJit::X86Compiler - Construction / Destruction] // ============================================================================ X86Compiler::X86Compiler(Context* context) : Compiler(context) { _properties |= IntUtil::maskFromIndex(kX86PropertyOptimizedAlign); } X86Compiler::~X86Compiler() { } // ============================================================================ // [AsmJit::Compiler - Function Builder] // ============================================================================ X86CompilerFuncDecl* X86Compiler::newFunc_(uint32_t convention, uint32_t returnType, const uint32_t* arguments, uint32_t argumentsCount) { ASMJIT_ASSERT(_func == NULL); X86CompilerFuncDecl* func = Compiler_newItem(this); _func = func; _varNameId = 0; func->setPrototype(convention, returnType, arguments, argumentsCount); addItem(func); bind(func->_entryLabel); func->_createVariables(); return func; } X86CompilerFuncDecl* X86Compiler::endFunc() { X86CompilerFuncDecl* func = getFunc(); ASMJIT_ASSERT(func != NULL); bind(func->_exitLabel); addItem(func->_end); func->setFuncFlag(kFuncFlagIsFinished); _func = NULL; return func; } // ============================================================================ // [AsmJit::Compiler - EmitInstruction] // ============================================================================ static inline X86CompilerInst* X86Compiler_newInstruction(X86Compiler* self, uint32_t code, Operand* opData, uint32_t opCount) { if (code >= _kX86InstJBegin && code <= _kX86InstJEnd) { void* p = self->_zoneMemory.alloc(sizeof(X86CompilerJmpInst)); return new(p) X86CompilerJmpInst(self, code, opData, opCount); } else { void* p = self->_zoneMemory.alloc(sizeof(X86CompilerInst) + opCount * sizeof(Operand)); return new(p) X86CompilerInst(self, code, opData, opCount); } } void X86Compiler::_emitInstruction(uint32_t code) { X86CompilerInst* inst = X86Compiler_newInstruction(this, code, NULL, 0); if (inst == NULL) { setError(kErrorNoHeapMemory); return; } addItem(inst); if (_cc != NULL) { inst->_offset = _cc->_currentOffset; inst->prepare(*_cc); } } void X86Compiler::_emitInstruction(uint32_t code, const Operand* o0) { Operand* operands = reinterpret_cast(_zoneMemory.alloc(1 * sizeof(Operand))); if (operands == NULL) { setError(kErrorNoHeapMemory); return; } operands[0] = *o0; X86CompilerInst* inst = X86Compiler_newInstruction(this, code, operands, 1); if (inst == NULL) { setError(kErrorNoHeapMemory); return; } addItem(inst); if (_cc != NULL) { inst->_offset = _cc->_currentOffset; inst->prepare(*_cc); } } void X86Compiler::_emitInstruction(uint32_t code, const Operand* o0, const Operand* o1) { Operand* operands = reinterpret_cast(_zoneMemory.alloc(2 * sizeof(Operand))); if (operands == NULL) { setError(kErrorNoHeapMemory); return; } operands[0] = *o0; operands[1] = *o1; X86CompilerInst* inst = X86Compiler_newInstruction(this, code, operands, 2); if (inst == NULL) { setError(kErrorNoHeapMemory); return; } addItem(inst); if (_cc) { inst->_offset = _cc->_currentOffset; inst->prepare(*_cc); } } void X86Compiler::_emitInstruction(uint32_t code, const Operand* o0, const Operand* o1, const Operand* o2) { Operand* operands = reinterpret_cast(_zoneMemory.alloc(3 * sizeof(Operand))); if (operands == NULL) { setError(kErrorNoHeapMemory); return; } operands[0] = *o0; operands[1] = *o1; operands[2] = *o2; X86CompilerInst* inst = X86Compiler_newInstruction(this, code, operands, 3); if (inst == NULL) { setError(kErrorNoHeapMemory); return; } addItem(inst); if (_cc != NULL) { inst->_offset = _cc->_currentOffset; inst->prepare(*_cc); } } void X86Compiler::_emitInstruction(uint32_t code, const Operand* o0, const Operand* o1, const Operand* o2, const Operand* o3) { Operand* operands = reinterpret_cast(_zoneMemory.alloc(4 * sizeof(Operand))); if (operands == NULL) { setError(kErrorNoHeapMemory); return; } operands[0] = *o0; operands[1] = *o1; operands[2] = *o2; operands[3] = *o3; X86CompilerInst* inst = X86Compiler_newInstruction(this, code, operands, 4); if (inst == NULL) { setError(kErrorNoHeapMemory); return; } addItem(inst); if (_cc != NULL) { inst->_offset = _cc->_currentOffset; inst->prepare(*_cc); } } void X86Compiler::_emitInstruction(uint32_t code, const Operand* o0, const Operand* o1, const Operand* o2, const Operand* o3, const Operand* o4) { Operand* operands = reinterpret_cast(_zoneMemory.alloc(5 * sizeof(Operand))); if (operands == NULL) { setError(kErrorNoHeapMemory); return; } operands[0] = *o0; operands[1] = *o1; operands[2] = *o2; operands[3] = *o3; operands[4] = *o4; X86CompilerInst* inst = X86Compiler_newInstruction(this, code, operands, 5); if (inst == NULL) { setError(kErrorNoHeapMemory); return; } addItem(inst); if (_cc != NULL) { inst->_offset = _cc->_currentOffset; inst->prepare(*_cc); } } void X86Compiler::_emitJcc(uint32_t code, const Label* label, uint32_t hint) { if (hint == kCondHintNone) { _emitInstruction(code, label); } else { Imm imm(hint); _emitInstruction(code, label, &imm); } } X86CompilerFuncCall* X86Compiler::_emitCall(const Operand* o0) { X86CompilerFuncDecl* func = getFunc(); if (func == NULL) { setError(kErrorNoFunction); return NULL; } X86CompilerFuncCall* call = Compiler_newItem(this, func, o0); if (call == NULL) { setError(kErrorNoHeapMemory); return NULL; } addItem(call); return call; } void X86Compiler::_emitReturn(const Operand* first, const Operand* second) { X86CompilerFuncDecl* func = getFunc(); if (func == NULL) { setError(kErrorNoFunction); return; } X86CompilerFuncRet* ret = Compiler_newItem(this, func, first, second); if (ret == NULL) { setError(kErrorNoHeapMemory); return; } addItem(ret); } // ============================================================================ // [AsmJit::Compiler - Align] // ============================================================================ void X86Compiler::align(uint32_t m) { addItem(Compiler_newItem(this, m)); } // ============================================================================ // [AsmJit::Compiler - Label] // ============================================================================ Label X86Compiler::newLabel() { Label label; label._base.id = static_cast(_targets.getLength()) | kOperandIdTypeLabel; CompilerTarget* target = Compiler_newItem(this, label); _targets.append(target); return label; } void X86Compiler::bind(const Label& label) { uint32_t id = label.getId() & kOperandIdValueMask; ASMJIT_ASSERT(id != kInvalidValue); ASMJIT_ASSERT(id < _targets.getLength()); addItem(_targets[id]); } // ============================================================================ // [AsmJit::Compiler - Variables] // ============================================================================ X86CompilerVar* X86Compiler::_newVar(const char* name, uint32_t type, uint32_t size) { X86CompilerVar* var = reinterpret_cast(_zoneMemory.alloc(sizeof(X86CompilerVar))); if (var == NULL) return NULL; char nameBuffer[32]; if (name == NULL) { sprintf(nameBuffer, "var_%d", _varNameId); name = nameBuffer; _varNameId++; } var->_name = _zoneMemory.sdup(name); var->_id = static_cast(_vars.getLength()) | kOperandIdTypeVar; var->_type = static_cast(type); var->_class = x86VarInfo[type].getClass(); var->_priority = 10; var->_isRegArgument = false; var->_isMemArgument = false; var->_isCalculated = false; var->_unused = 0; var->_size = size; var->firstItem = NULL; var->lastItem = NULL; var->funcScope = getFunc(); var->funcCall = NULL; var->homeRegisterIndex = kRegIndexInvalid; var->prefRegisterMask = 0; var->homeMemoryOffset = 0; var->homeMemoryData = NULL; var->regIndex = kRegIndexInvalid; var->workOffset = kInvalidValue; var->nextActive = NULL; var->prevActive = NULL; var->state = kVarStateUnused; var->changed = false; var->saveOnUnuse = false; var->regReadCount = 0; var->regWriteCount = 0; var->regRwCount = 0; var->regGpbLoCount = 0; var->regGpbHiCount = 0; var->memReadCount = 0; var->memWriteCount = 0; var->memRwCount = 0; var->tPtr = NULL; _vars.append(var); return var; } GpVar X86Compiler::newGpVar(uint32_t varType, const char* name) { ASMJIT_ASSERT((varType < kX86VarTypeCount) && (x86VarInfo[varType].getClass() & kX86VarClassGp) != 0); #if defined(ASMJIT_X86) if (x86VarInfo[varType].getSize() > 4) { varType = kX86VarTypeGpd; if (_logger) _logger->logString("*** COMPILER WARNING: QWORD variable translated to DWORD, FIX YOUR CODE! ***\n"); } #endif // ASMJIT_X86 X86CompilerVar* var = _newVar(name, varType, x86VarInfo[varType].getSize()); return var->asGpVar(); } GpVar X86Compiler::getGpArg(uint32_t argIndex) { X86CompilerFuncDecl* func = getFunc(); GpVar var; if (func != NULL) { X86FuncDecl* decl = func->getDecl(); if (argIndex < decl->getArgumentsCount()) { X86CompilerVar* cv = func->getVar(argIndex); var._var.id = cv->getId(); var._var.size = cv->getSize(); var._var.regCode = x86VarInfo[cv->getType()].getCode(); var._var.varType = cv->getType(); } } return var; } MmVar X86Compiler::newMmVar(uint32_t varType, const char* name) { ASMJIT_ASSERT((varType < kX86VarTypeCount) && (x86VarInfo[varType].getClass() & kX86VarClassMm) != 0); X86CompilerVar* var = _newVar(name, varType, 8); return var->asMmVar(); } MmVar X86Compiler::getMmArg(uint32_t argIndex) { X86CompilerFuncDecl* func = getFunc(); MmVar var; if (func != NULL) { const X86FuncDecl* decl = func->getDecl(); if (argIndex < decl->getArgumentsCount()) { X86CompilerVar* cv = func->getVar(argIndex); var._var.id = cv->getId(); var._var.size = cv->getSize(); var._var.regCode = x86VarInfo[cv->getType()].getCode(); var._var.varType = cv->getType(); } } return var; } XmmVar X86Compiler::newXmmVar(uint32_t varType, const char* name) { ASMJIT_ASSERT((varType < kX86VarTypeCount) && (x86VarInfo[varType].getClass() & kX86VarClassXmm) != 0); X86CompilerVar* var = _newVar(name, varType, 16); return var->asXmmVar(); } XmmVar X86Compiler::getXmmArg(uint32_t argIndex) { X86CompilerFuncDecl* func = getFunc(); XmmVar var; if (func != NULL) { const X86FuncDecl* decl = func->getDecl(); if (argIndex < decl->getArgumentsCount()) { X86CompilerVar* cv = func->getVar(argIndex); var._var.id = cv->getId(); var._var.size = cv->getSize(); var._var.regCode = x86VarInfo[cv->getType()].getCode(); var._var.varType = cv->getType(); } } return var; } void X86Compiler::_vhint(Var& var, uint32_t hintId, uint32_t hintValue) { if (var.getId() == kInvalidValue) return; X86CompilerVar* cv = _getVar(var.getId()); ASMJIT_ASSERT(cv != NULL); X86CompilerHint* item = Compiler_newItem(this, cv, hintId, hintValue); addItem(item); } void X86Compiler::alloc(Var& var) { _vhint(var, kVarHintAlloc, kInvalidValue); } void X86Compiler::alloc(Var& var, uint32_t regIndex) { if (regIndex > 31) return; _vhint(var, kVarHintAlloc, IntUtil::maskFromIndex(regIndex)); } void X86Compiler::alloc(Var& var, const Reg& reg) { _vhint(var, kVarHintAlloc, IntUtil::maskFromIndex(reg.getRegIndex())); } void X86Compiler::save(Var& var) { _vhint(var, kVarHintSave, kInvalidValue); } void X86Compiler::spill(Var& var) { _vhint(var, kVarHintSpill, kInvalidValue); } void X86Compiler::unuse(Var& var) { _vhint(var, kVarHintUnuse, kInvalidValue); } uint32_t X86Compiler::getPriority(Var& var) const { if (var.getId() == kInvalidValue) return kInvalidValue; X86CompilerVar* vdata = _getVar(var.getId()); ASMJIT_ASSERT(vdata != NULL); return vdata->getPriority(); } void X86Compiler::setPriority(Var& var, uint32_t priority) { if (var.getId() == kInvalidValue) return; X86CompilerVar* vdata = _getVar(var.getId()); ASMJIT_ASSERT(vdata != NULL); if (priority > 100) priority = 100; vdata->_priority = static_cast(priority); } bool X86Compiler::getSaveOnUnuse(Var& var) const { if (var.getId() == kInvalidValue) return false; X86CompilerVar* vdata = _getVar(var.getId()); ASMJIT_ASSERT(vdata != NULL); return (bool)vdata->saveOnUnuse; } void X86Compiler::setSaveOnUnuse(Var& var, bool value) { if (var.getId() == kInvalidValue) return; X86CompilerVar* vdata = _getVar(var.getId()); ASMJIT_ASSERT(vdata != NULL); vdata->saveOnUnuse = value; } void X86Compiler::rename(Var& var, const char* name) { if (var.getId() == kInvalidValue) return; X86CompilerVar* vdata = _getVar(var.getId()); ASMJIT_ASSERT(vdata != NULL); vdata->_name = _zoneMemory.sdup(name); } // ============================================================================ // [AsmJit::Compiler - State] // ============================================================================ X86CompilerState* X86Compiler::_newState(uint32_t memVarsCount) { X86CompilerState* state = reinterpret_cast(_zoneMemory.alloc( sizeof(X86CompilerState) + memVarsCount * sizeof(void*))); return state; } // ============================================================================ // [AsmJit::Compiler - Make] // ============================================================================ void* X86Compiler::make() { X86Assembler x86Asm(_context); x86Asm._properties = _properties; x86Asm.setLogger(_logger); serialize(x86Asm); if (this->getError()) return NULL; if (x86Asm.getError()) { setError(x86Asm.getError()); return NULL; } void* result = x86Asm.make(); if (_logger) { _logger->logFormat("*** COMPILER SUCCESS - Wrote %u bytes, code: %u, trampolines: %u.\n\n", (unsigned int)x86Asm.getCodeSize(), (unsigned int)x86Asm.getOffset(), (unsigned int)x86Asm.getTrampolineSize()); } return result; } void X86Compiler::serialize(Assembler& a) { X86CompilerContext x86Context(this); X86Assembler& x86Asm = static_cast(a); CompilerItem* start = _first; CompilerItem* stop = NULL; // Register all labels. x86Asm.registerLabels(_targets.getLength()); // Make code. for (;;) { _cc = NULL; // ------------------------------------------------------------------------ // [Find Function] // ------------------------------------------------------------------------ for (;;) { if (start == NULL) return; if (start->getType() == kCompilerItemFuncDecl) break; start->emit(x86Asm); start = start->getNext(); } // ------------------------------------------------------------------------ // [Setup CompilerContext] // ------------------------------------------------------------------------ stop = static_cast(start)->getEnd(); x86Context._func = static_cast(start); x86Context._start = start; x86Context._stop = stop; x86Context._extraBlock = stop->getPrev(); // Detect whether the function generation was finished. if (!x86Context._func->isFinished() || x86Context._func->getEnd()->getPrev() == NULL) { setError(kErrorIncompleteFunction); return; } // ------------------------------------------------------------------------ // Step 1: // - Assign/increment offset of each item. // - Extract variables from instructions. // - Prepare variables for register allocator: // - Update read(r) / write(w) / read/write(x) statistics. // - Update register / memory usage statistics. // - Find scope (first / last item) of variables. // ------------------------------------------------------------------------ CompilerItem* cur; for (cur = start; ; cur = cur->getNext()) { cur->prepare(x86Context); if (cur == stop) break; } // We set compiler context also to Compiler so newly emitted instructions // can call CompilerItem::prepare() on itself. _cc = &x86Context; // ------------------------------------------------------------------------ // Step 2: // - Translate special instructions (imul, cmpxchg8b, ...). // - Alloc registers. // - Translate forward jumps. // - Alloc memory operands (variables related). // - Emit function prolog. // - Emit function epilog. // - Patch memory operands (variables related). // - Dump function prototype and variable statistics (if enabled). // ------------------------------------------------------------------------ // Translate special instructions and run alloc registers. cur = start; do { do { // Assign current offset of each item back to CompilerContext. x86Context._currentOffset = cur->_offset; // Assign previous item to compiler so each variable spill/alloc will // be emitted before. _current = cur->getPrev(); cur = cur->translate(x86Context); } while (cur); x86Context._isUnreachable = true; size_t len = x86Context._backCode.getLength(); while (x86Context._backPos < len) { cur = x86Context._backCode[x86Context._backPos++]->getNext(); if (!cur->isTranslated()) break; cur = NULL; } } while (cur); // Translate forward jumps. { ForwardJumpData* j = x86Context._forwardJumps; while (j != NULL) { x86Context._assignState(j->state); _current = j->inst->getPrev(); j->inst->doJump(x86Context); j = j->next; } } // Alloc memory operands (variables related). x86Context._allocMemoryOperands(); // Emit function prolog / epilog. x86Context.getFunc()->_preparePrologEpilog(x86Context); _current = x86Context._func->getEntryTarget(); x86Context.getFunc()->_emitProlog(x86Context); _current = x86Context._func->getExitTarget(); x86Context.getFunc()->_emitEpilog(x86Context); // Patch memory operands (variables related). _current = _last; x86Context._patchMemoryOperands(start, stop); // Dump function prototype and variable statistics (if enabled). if (_logger) x86Context.getFunc()->_dumpFunction(x86Context); // ------------------------------------------------------------------------ // Hack: need to register labels that was created by the Step 2. // ------------------------------------------------------------------------ if (x86Asm._labels.getLength() < _targets.getLength()) x86Asm.registerLabels(_targets.getLength() - x86Asm._labels.getLength()); CompilerItem* extraBlock = x86Context._extraBlock; // ------------------------------------------------------------------------ // Step 3: // - Emit instructions to Assembler stream. // ------------------------------------------------------------------------ for (cur = start; ; cur = cur->getNext()) { cur->emit(x86Asm); if (cur == extraBlock) break; } // ------------------------------------------------------------------------ // Step 4: // - Emit everything else (post action). // ------------------------------------------------------------------------ for (cur = start; ; cur = cur->getNext()) { cur->post(x86Asm); if (cur == extraBlock) break; } start = extraBlock->getNext(); x86Context._clear(); } } } // AsmJit namespace // [Api-End] #include "../core/apiend.h" desmume/src/libretro-common/conversion/float_to_s16.c000664 001750 001750 00000015104 12755534123 024101 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2016 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (float_to_s16.c). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include #include #if defined(__SSE2__) #include #elif defined(__ALTIVEC__) #include #endif #include #include /** * convert_float_to_s16_C: * @out : output buffer * @in : input buffer * @samples : size of samples to be converted * * Converts floating point * to signed integer 16-bit. * * C implementation callback function. **/ void convert_float_to_s16_C(int16_t *out, const float *in, size_t samples) { size_t i; for (i = 0; i < samples; i++) { int32_t val = (int32_t)(in[i] * 0x8000); out[i] = (val > 0x7FFF) ? 0x7FFF : (val < -0x8000 ? -0x8000 : (int16_t)val); } } #if defined(__SSE2__) /** * convert_float_to_s16_SSE2: * @out : output buffer * @in : input buffer * @samples : size of samples to be converted * * Converts floating point * to signed integer 16-bit. * * SSE2 implementation callback function. **/ void convert_float_to_s16_SSE2(int16_t *out, const float *in, size_t samples) { size_t i; __m128 factor = _mm_set1_ps((float)0x8000); for (i = 0; i + 8 <= samples; i += 8, in += 8, out += 8) { __m128 input_l = _mm_loadu_ps(in + 0); __m128 input_r = _mm_loadu_ps(in + 4); __m128 res_l = _mm_mul_ps(input_l, factor); __m128 res_r = _mm_mul_ps(input_r, factor); __m128i ints_l = _mm_cvtps_epi32(res_l); __m128i ints_r = _mm_cvtps_epi32(res_r); __m128i packed = _mm_packs_epi32(ints_l, ints_r); _mm_storeu_si128((__m128i *)out, packed); } convert_float_to_s16_C(out, in, samples - i); } #elif defined(__ALTIVEC__) /** * convert_float_to_s16_altivec: * @out : output buffer * @in : input buffer * @samples : size of samples to be converted * * Converts floating point * to signed integer 16-bit. * * AltiVec implementation callback function. **/ void convert_float_to_s16_altivec(int16_t *out, const float *in, size_t samples) { int samples_in = samples; /* Unaligned loads/store is a bit expensive, * so we optimize for the good path (very likely). */ if (((uintptr_t)out & 15) + ((uintptr_t)in & 15) == 0) { size_t i; for (i = 0; i + 8 <= samples; i += 8, in += 8, out += 8) { vector float input0 = vec_ld( 0, in); vector float input1 = vec_ld(16, in); vector signed int result0 = vec_cts(input0, 15); vector signed int result1 = vec_cts(input1, 15); vec_st(vec_packs(result0, result1), 0, out); } samples_in -= i; } convert_float_to_s16_C(out, in, samples_in); } #elif defined(__ARM_NEON__) && !defined(VITA) void convert_float_s16_asm(int16_t *out, const float *in, size_t samples); /** * convert_float_to_s16_neon: * @out : output buffer * @in : input buffer * @samples : size of samples to be converted * * Converts floating point * to signed integer 16-bit. * * ARM NEON implementation callback function. **/ static void convert_float_to_s16_neon(int16_t *out, const float *in, size_t samples) { size_t aligned_samples = samples & ~7; if (aligned_samples) convert_float_s16_asm(out, in, aligned_samples); convert_float_to_s16_C(out + aligned_samples, in + aligned_samples, samples - aligned_samples); } #elif defined(_MIPS_ARCH_ALLEGREX) /** * convert_float_to_s16_ALLEGREX: * @out : output buffer * @in : input buffer * @samples : size of samples to be converted * * Converts floating point * to signed integer 16-bit. * * MIPS ALLEGREX implementation callback function. **/ void convert_float_to_s16_ALLEGREX(int16_t *out, const float *in, size_t samples) { size_t i; #ifdef DEBUG /* Make sure the buffers are 16 byte aligned, this should be * the default behaviour of malloc in the PSPSDK. * Assume alignment. */ retro_assert(((uintptr_t)in & 0xf) == 0); retro_assert(((uintptr_t)out & 0xf) == 0); #endif for (i = 0; i + 8 <= samples; i += 8) { __asm__ ( ".set push \n" ".set noreorder \n" "lv.q c100, 0(%0) \n" "lv.q c110, 16(%0) \n" "vf2in.q c100, c100, 31 \n" "vf2in.q c110, c110, 31 \n" "vi2s.q c100, c100 \n" "vi2s.q c102, c110 \n" "sv.q c100, 0(%1) \n" ".set pop \n" :: "r"(in + i), "r"(out + i)); } for (; i < samples; i++) { int32_t val = (int32_t)(in[i] * 0x8000); out[i] = (val > 0x7FFF) ? 0x7FFF : (val < -0x8000 ? -0x8000 : (int16_t)val); } } #endif /** * convert_float_to_s16_init_simd: * * Sets up function pointers for conversion * functions based on CPU features. **/ void convert_float_to_s16_init_simd(void) { unsigned cpu = cpu_features_get(); (void)cpu; #if defined(__ARM_NEON__) && !defined(VITA) convert_float_to_s16_arm = (cpu & RETRO_SIMD_NEON) ? convert_float_to_s16_neon : convert_float_to_s16_C; #endif } desmume/src/addons/slot1_retail_mcrom.cpp000664 001750 001750 00000005522 12755534123 021716 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2015 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the this software. If not, see . */ #include "slot1comp_mc.h" #include "slot1comp_rom.h" #include "slot1comp_protocol.h" #include "../slot1.h" #include "../NDSSystem.h" //quick architecture overview: //MCROM receives GC bus commands from MMU.cpp //those are passed on to the protocol component for parsing //protocol calls back into MCROM via ISlot1Comp_Protocol_Client interface for things the protocol doesnt know about (the contents of the rom, chiefly) //MCROM utilizes the rom component for address logic and delivering data class Slot1_Retail_MCROM : public ISlot1Interface, public ISlot1Comp_Protocol_Client { private: Slot1Comp_Protocol protocol; Slot1Comp_Rom rom; public: virtual Slot1Info const* info() { static Slot1InfoSimple info("Retail MC+ROM", "Slot1 Retail MC+ROM (standard) card emulation", 0x01); return &info; } virtual void connect() { protocol.reset(this); protocol.chipId = gameInfo.chipID; protocol.gameCode = T1ReadLong((u8*)gameInfo.header.gameCode,0); g_Slot1Comp_MC.connect(); } virtual u8 auxspi_transaction(int PROCNUM, u8 value) { return g_Slot1Comp_MC.auxspi_transaction(PROCNUM,value); } virtual void auxspi_reset(int PROCNUM) { g_Slot1Comp_MC.auxspi_reset(PROCNUM); } virtual void write_command(u8 PROCNUM, GC_Command command) { protocol.write_command(command); } virtual void write_GCDATAIN(u8 PROCNUM, u32 val) { protocol.write_GCDATAIN(PROCNUM, val); } virtual u32 read_GCDATAIN(u8 PROCNUM) { return protocol.read_GCDATAIN(PROCNUM); } virtual void slot1client_startOperation(eSlot1Operation operation) { rom.start(operation,protocol.address); } virtual void post_fakeboot(int PROCNUM) { // The BIOS leaves the card in NORMAL mode protocol.mode = eCardMode_NORMAL; } virtual void savestate(EMUFILE* os) { protocol.savestate(os); rom.savestate(os); } virtual void loadstate(EMUFILE* is) { protocol.loadstate(is); rom.loadstate(is); } private: u32 slot1client_read_GCDATAIN(eSlot1Operation operation) { return rom.read(); } }; ISlot1Interface* construct_Slot1_Retail_MCROM() { return new Slot1_Retail_MCROM(); } desmume/src/utils/AsmJit/COPYING.txt000664 001750 001750 00000001566 12755534123 020347 0ustar00sergiosergio000000 000000 Copyright (c) 2008-2012, Petr Kobalicek This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. desmume/src/mic.h000664 001750 001750 00000002065 12755534123 015063 0ustar00sergiosergio000000 000000 /* Copyright (C) 2009-2015 DeSmuME Team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the this software. If not, see . */ #ifndef MIC_H #define MIC_H #include "types.h" class EMUFILE; #ifdef WIN32 static char MicSampleName[256]; bool LoadSample(const char *name); #endif extern int MicDisplay; #ifdef FAKE_MIC void Mic_DoNoise(BOOL); #endif BOOL Mic_Init(void); void Mic_Reset(void); void Mic_DeInit(void); u8 Mic_ReadSample(void); void mic_savestate(EMUFILE* os); bool mic_loadstate(EMUFILE* is, int size); #endif // MIC_H desmume/src/utils/AsmJit/AsmJit.h000664 001750 001750 00000031402 12755534123 020026 0ustar00sergiosergio000000 000000 // [AsmJit] // Complete JIT Assembler for C++ Language. // // [License] // Zlib - See COPYING file in this package. // [Guard] #ifndef _ASMJIT_ASMJIT_H #define _ASMJIT_ASMJIT_H //! @mainpage //! //! @brief AsmJit is a complete x86/x64 JIT Assembler for C++ language. //! //! It supports FPU, MMX, 3dNow, SSE, SSE2, SSE3 and SSE4 intrinsics, powerful //! compiler that helps to write portable functions for 32-bit (x86) and 64-bit //! (x64) architectures. AsmJit can be used to create functions at runtime that //! can be called from existing (but also generated) C/C++ code. //! //! AsmJit is a cross-platform library that supports various compilers and //! operating systems. Currently only limitation is x86 (32-bit) or x64 (64-bit) //! processor. Currently tested operating systems are Windows (32-bit and 64-bit), //! Linux (32-bit and 64-bit) and MacOSX (32-bit and 64-bit). //! //! @section AsmJit_Main_Introduction Introduction //! //! AsmJit library contains two main classes for code generation with different //! goals. First main code generation class is called @c AsmJit::Assembler and //! contains low level API that can be used to generate JIT binary code. It //! directly emits binary stream that represents encoded x86/x64 assembler //! opcodes. Together with operands and labels it can be used to generate //! complete code. For details look to @ref AsmJit_Core and @ref AsmJit_Compiler //! sections. //! //! There is also class named @c AsmJit::Compiler that allows to develop //! cross-platform assembler code without worring about function calling //! conventions and registers allocation. It can be also used to write 32-bit //! and 64-bit portable code. Compiler is recommended class to use for code //! generation. //! //! Everything in AsmJit library is in @c AsmJit namespace. //! //! @section AsmJit_Main_CodeGeneration Code Generation //! //! - @ref AsmJit_Core "Assembler core" - Operands, intrinsics and low-level assembler. //! - @ref AsmJit_Compiler "Compiler" - High level code generation. //! - @ref AsmJit_CpuInfo "Cpu Information" - Get information about host processor. //! - @ref AsmJit_Logging "Logging" - Logging and error handling. //! - @ref AsmJit_MemoryManagement "Memory Management" - Virtual memory management. //! //! @section AsmJit_Main_Configuration Configuration, Definitions and Utilities //! //! - @ref AsmJit_Config "Configuration" - Macros used to configure AsmJit. //! //! @section AsmJit_Main_HomePage AsmJit Homepage //! //! - http://code.google.com/p/asmjit/ //! //! @section AsmJit_Main_ResourcesX86 External X86/X64 Assembler Resources //! - http://www.agner.org/optimize/ //! - http://www.mark.masmcode.com/ (Assembler Tips) //! - http://avisynth.org/mediawiki/Filter_SDK/Assembler_optimizing (Optimizing) //! - http://www.ragestorm.net/distorm/ (Disassembling) //! //! @section AsmJit_Main_Terminology Terminology //! //! - Non-volatile (preserved) register - Register that can't be changed //! by callee (callee must save and restore it if it want to use it inside). //! //! - Volatile (non-preserved) register - The opossite. Register that can //! be freely used by callee. The caller must free all registers before calling //! other function. //! @defgroup AsmJit_Core Assembler core (operands, intrinsics and low-level assembler). //! //! Contains classes related to @c AsmJit::Assembler that're directly used //! to generate machine code stream. It's one of oldest and fastest method //! to generate machine code using AsmJit library. //! //! - See @c AsmJit::Assembler class for low level code generation //! documentation. //! - See @c AsmJit::Operand for AsmJit operand's overview. //! //! @section AsmJit_Core_Registers Registers //! //! There are static objects that represents X86 and X64 registers. They can //! be used directly (like @c eax, @c mm, @c xmm, ...) or created through //! these functions: //! //! - @c AsmJit::mk_gpb() - make general purpose byte register //! - @c AsmJit::mk_gpw() - make general purpose word register //! - @c AsmJit::mk_gpd() - make general purpose dword register //! - @c AsmJit::mk_gpq() - make general purpose qword register //! - @c AsmJit::mk_mm() - make mmx register //! - @c AsmJit::mk_xmm() - make sse register //! - @c AsmJit::st() - make x87 register //! //! @section AsmJit_Core_Addressing Addressing //! //! X86 and x64 architectures contains several addressing modes and most ones //! are possible with AsmJit library. Memory represents are represented by //! @c AsmJit::Mem class. These functions are used to make operands that //! represents memory addresses: //! //! - @c AsmJit::ptr() //! - @c AsmJit::byte_ptr() //! - @c AsmJit::word_ptr() //! - @c AsmJit::dword_ptr() //! - @c AsmJit::qword_ptr() //! - @c AsmJit::tword_ptr() //! - @c AsmJit::dqword_ptr() //! - @c AsmJit::mmword_ptr() //! - @c AsmJit::xmmword_ptr() //! - @c AsmJit::sysint_ptr() //! //! Most useful function to make pointer should be @c AsmJit::ptr(). It creates //! pointer to the target with unspecified size. Unspecified size works in all //! intrinsics where are used registers (this means that size is specified by //! register operand or by instruction itself). For example @c AsmJit::ptr() //! can't be used with @c AsmJit::Assembler::inc() instruction. In this case //! size must be specified and it's also reason to make difference between //! pointer sizes. //! //! Supported are simple address forms (register + displacement) and complex //! address forms (register + (register << shift) + displacement). //! //! @section AsmJit_Core_Immediates Immediates //! //! Immediate values are constants thats passed directly after instruction //! opcode. To create such value use @c AsmJit::imm() or @c AsmJit::uimm() //! methods to create signed or unsigned immediate value. //! //! @sa @c AsmJit::Compiler. //! @defgroup AsmJit_Compiler Compiler (high-level code generation). //! //! Contains classes related to @c AsmJit::Compiler that can be used //! to generate code using high-level constructs. //! //! - See @c Compiler class for high level code generation //! documentation - calling conventions, function declaration //! and variables management. //! @defgroup AsmJit_Config Configuration. //! //! Contains macros that can be redefined to fit into any project. //! @defgroup AsmJit_CpuInfo CPU information. //! //! X86 or x64 cpuid instruction allows to get information about processor //! vendor and it's features. It's always used to detect features like MMX, //! SSE and other newer ones. //! //! AsmJit library supports low level cpuid call implemented internally as //! C++ function using inline assembler or intrinsics and also higher level //! CPU features detection. The low level function (also used by higher level //! one) is @c AsmJit::cpuid(). //! //! AsmJit library also contains higher level function @c AsmJit::getCpuInfo() //! that returns features detected by the library. The detection process is //! done only once and it's cached for all next calls. @c AsmJit::CpuInfo //! structure not contains only information through @c AsmJit::cpuid(), but //! there is also small multiplatform code to detect number of processors //! (or cores) through operating system API. //! //! It's recommended to use @c AsmJit::cpuInfo to detect and check for //! host processor features. //! //! Example how to use AsmJit::cpuid(): //! //! @code //! // All functions and structures are in AsmJit namesapce. //! using namespace AsmJit; //! //! // Here will be retrieved result of cpuid call. //! CpuId out; //! //! // Use cpuid function to do the job. //! cpuid(0 /* eax */, &out /* eax, ebx, ecx, edx */); //! //! // Id eax argument to cpuid is 0, ebx, ecx and edx registers //! // are filled with cpu vendor. //! char vendor[13]; //! memcpy(i->vendor, &out.ebx, 4); //! memcpy(i->vendor + 4, &out.edx, 4); //! memcpy(i->vendor + 8, &out.ecx, 4); //! vendor[12] = '\0'; //! //! // Print vendor //! puts(vendor); //! @endcode //! //! If you want to use AsmJit::cpuid() function instead of higher level //! @c AsmJit::getCpuInfo(), please read processor manuals provided by Intel, //! AMD or other manufacturers for cpuid instruction details. //! //! Example of using @c AsmJit::getCpuInfo(): //! //! @code //! // All functions and structures are in AsmJit namesapce. //! using namespace AsmJit; //! //! // Call to cpuInfo return CpuInfo structure that shouldn't be modified. //! // Make it const by default. //! const CpuInfo *i = getCpuInfo(); //! //! // Now you are able to get specific features. //! //! // Processor has SSE2 //! if (i->features & kX86FeatureSse2) //! { //! // your code... //! } //! // Processor has MMX //! else if (i->features & kX86Feature_MMX) //! { //! // your code... //! } //! // Processor is old, no SSE2 or MMX support. //! else //! { //! // your code... //! } //! @endcode //! //! Better example is in AsmJit/Test/testcpu.cpp file. //! //! @sa AsmJit::cpuid, @c AsmJit::cpuInfo. //! @defgroup AsmJit_Logging Logging and error handling. //! //! Contains classes related to loging assembler output. Currently logging //! is implemented in @c AsmJit::Logger class.You can override //! @c AsmJit::Logger::log() to log messages into your stream. There is also //! @c FILE based logger implemented in @c AsmJit::FileLogger class. //! //! To log your assembler output to FILE stream use this code: //! //! @code //! // Create assembler //! Assembler a; //! //! // Create and set file based logger //! FileLogger logger(stderr); //! a.setLogger(&logger); //! @endcode //! //! You can see that logging goes through @c Assembler. If you are using //! @c Compiler and you want to log messages in correct assembler order, //! you should look at @ref Compiler::comment() method. It allows you to //! insert text message into items stream so the @c Compiler is able to //! send messages to @ref Assembler in correct order. //! //! @sa @c AsmJit::Logger, @c AsmJit::FileLogger. //! @defgroup AsmJit_MemoryManagement Virtual memory management. //! //! Using @c AsmJit::Assembler or @c AsmJit::Compiler to generate machine //! code is not final step. Each generated code needs to run in memory //! that is not protected against code execution. To alloc this code it's //! needed to use operating system functions provided to enable execution //! code in specified memory block or to allocate memory that is not //! protected. The solution is always to use @c See AsmJit::Assembler::make() //! and @c AsmJit::Compiler::make() functions that can allocate memory and //! relocate code for you. But AsmJit also contains classes for manual memory //! management thats internally used by AsmJit but can be used by programmers //! too. //! //! Memory management contains low level and high level classes related to //! allocating and freeing virtual memory. Low level class is //! @c AsmJit::VirtualMemory that can allocate and free full pages of //! virtual memory provided by operating system. Higher level class is //! @c AsmJit::MemoryManager that is able to manage complete allocation and //! free mechanism. It internally uses larger chunks of memory to make //! allocation fast and effective. //! //! Using @c AsmJit::VirtualMemory::alloc() is cross-platform way how to //! allocate this kind of memory without worrying about operating system //! and it's API. Each memory block that is no longer needed should be //! freed by @c AsmJit::VirtualMemory::free() method. If you want better //! comfort and malloc()/free() interface, look at the //! @c AsmJit::MemoryManager class. //! //! @sa @c AsmJit::VirtualMemory, @ AsmJit::MemoryManager. //! @addtogroup AsmJit_Config //! @{ //! @def ASMJIT_WINDOWS //! @brief Macro that is declared if AsmJit is compiled for Windows. //! @def ASMJIT_POSIX //! @brief Macro that is declared if AsmJit is compiled for unix like //! operating system. //! @def ASMJIT_API //! @brief Attribute that's added to classes that can be exported if AsmJit //! is compiled as a dll library. //! @def ASMJIT_MALLOC //! @brief Function to call to allocate dynamic memory. //! @def ASMJIT_REALLOC //! @brief Function to call to reallocate dynamic memory. //! @def ASMJIT_FREE //! @brief Function to call to free dynamic memory. //! @def ASMJIT_ASSERT //! @brief Assertion macro. Default implementation calls //! @c AsmJit::assertionFailure() function. //! @} //! @namespace AsmJit //! @brief Main AsmJit library namespace. //! //! There are not other namespaces used in AsmJit library. // ---------------------------------------------------------------------------- // [Dependencies - Core] // ---------------------------------------------------------------------------- #include "core.h" // ---------------------------------------------------------------------------- // [Dependencies - X86 / X64] // ---------------------------------------------------------------------------- #if defined(ASMJIT_X86) || defined(ASMJIT_X64) #include "x86.h" #endif // ASMJIT_X86 || ASMJIT_X64 // [Guard] #endif // _ASMJIT_ASMJIT_H desmume/src/libretro-common/include/file/file_path.h000664 001750 001750 00000030663 12755534123 023725 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2015 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (file_path.h). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef __LIBRETRO_SDK_FILE_PATH_H #define __LIBRETRO_SDK_FILE_PATH_H #include #include #include #include #include #include #include RETRO_BEGIN_DECLS /* Order in this enum is equivalent to negative sort order in filelist * (i.e. DIRECTORY is on top of PLAIN_FILE) */ enum { RARCH_FILETYPE_UNSET, RARCH_PLAIN_FILE, RARCH_COMPRESSED_FILE_IN_ARCHIVE, RARCH_COMPRESSED_ARCHIVE, RARCH_DIRECTORY, RARCH_FILE_UNSUPPORTED }; /** * path_is_compressed_file: * @path : path * * Checks if path is a compressed file. * * Returns: true (1) if path is a compressed file, otherwise false (0). **/ bool path_is_compressed_file(const char *path); /** * path_contains_compressed_file: * @path : path * * Checks if path contains a compressed file. * * Currently we only check for hash symbol (#) inside the pathname. * If path is ever expanded to a general URI, we should check for that here. * * Example: Somewhere in the path there might be a compressed file * E.g.: /path/to/file.7z#mygame.img * * Returns: true (1) if path contains compressed file, otherwise false (0). **/ bool path_contains_compressed_file(const char *path); /** * path_file_exists: * @path : path * * Checks if a file already exists at the specified path (@path). * * Returns: true (1) if file already exists, otherwise false (0). */ bool path_file_exists(const char *path); /** * path_get_extension: * @path : path * * Gets extension of file. Only '.'s * after the last slash are considered. * * Returns: extension part from the path. */ const char *path_get_extension(const char *path); /** * path_remove_extension: * @path : path * * Removes the extension from the path and returns the result. * Removes all text after and including the last '.'. * Only '.'s after the last slash are considered. * * Returns: path with the extension part removed. */ char *path_remove_extension(char *path); /** * path_basename: * @path : path * * Get basename from @path. * * Returns: basename from path. **/ const char *path_basename(const char *path); /** * path_basedir: * @path : path * * Extracts base directory by mutating path. * Keeps trailing '/'. **/ void path_basedir(char *path); /** * path_parent_dir: * @path : path * * Extracts parent directory by mutating path. * Assumes that path is a directory. Keeps trailing '/'. **/ void path_parent_dir(char *path); /** * path_resolve_realpath: * @buf : buffer for path * @size : size of buffer * * Turns relative paths into absolute path. * If relative, rebases on current working dir. **/ void path_resolve_realpath(char *buf, size_t size); /** * path_is_absolute: * @path : path * * Checks if @path is an absolute path or a relative path. * * Returns: true (1) if path is absolute, false (1) if path is relative. **/ bool path_is_absolute(const char *path); /** * fill_pathname: * @out_path : output path * @in_path : input path * @replace : what to replace * @size : buffer size of output path * * FIXME: Verify * * Replaces filename extension with 'replace' and outputs result to out_path. * The extension here is considered to be the string from the last '.' * to the end. * * Only '.'s after the last slash are considered as extensions. * If no '.' is present, in_path and replace will simply be concatenated. * 'size' is buffer size of 'out_path'. * E.g.: in_path = "/foo/bar/baz/boo.c", replace = ".asm" => * out_path = "/foo/bar/baz/boo.asm" * E.g.: in_path = "/foo/bar/baz/boo.c", replace = "" => * out_path = "/foo/bar/baz/boo" */ void fill_pathname(char *out_path, const char *in_path, const char *replace, size_t size); /** * fill_dated_filename: * @out_filename : output filename * @ext : extension of output filename * @size : buffer size of output filename * * Creates a 'dated' filename prefixed by 'RetroArch', and * concatenates extension (@ext) to it. * * E.g.: * out_filename = "RetroArch-{month}{day}-{Hours}{Minutes}.{@ext}" **/ void fill_dated_filename(char *out_filename, const char *ext, size_t size); /** * fill_pathname_noext: * @out_path : output path * @in_path : input path * @replace : what to replace * @size : buffer size of output path * * Appends a filename extension 'replace' to 'in_path', and outputs * result in 'out_path'. * * Assumes in_path has no extension. If an extension is still * present in 'in_path', it will be ignored. * */ void fill_pathname_noext(char *out_path, const char *in_path, const char *replace, size_t size); /** * find_last_slash: * @str : input path * * Gets a pointer to the last slash in the input path. * * Returns: a pointer to the last slash in the input path. **/ char *find_last_slash(const char *str); /** * fill_pathname_dir: * @in_dir : input directory path * @in_basename : input basename to be appended to @in_dir * @replace : replacement to be appended to @in_basename * @size : size of buffer * * Appends basename of 'in_basename', to 'in_dir', along with 'replace'. * Basename of in_basename is the string after the last '/' or '\\', * i.e the filename without directories. * * If in_basename has no '/' or '\\', the whole 'in_basename' will be used. * 'size' is buffer size of 'in_dir'. * * E.g..: in_dir = "/tmp/some_dir", in_basename = "/some_content/foo.c", * replace = ".asm" => in_dir = "/tmp/some_dir/foo.c.asm" **/ void fill_pathname_dir(char *in_dir, const char *in_basename, const char *replace, size_t size); /** * fill_pathname_base: * @out : output path * @in_path : input path * @size : size of output path * * Copies basename of @in_path into @out_path. **/ void fill_pathname_base(char *out_path, const char *in_path, size_t size); void fill_pathname_base_noext(char *out_dir, const char *in_path, size_t size); void fill_pathname_base_ext(char *out, const char *in_path, const char *ext, size_t size); /** * fill_pathname_basedir: * @out_dir : output directory * @in_path : input path * @size : size of output directory * * Copies base directory of @in_path into @out_path. * If in_path is a path without any slashes (relative current directory), * @out_path will get path "./". **/ void fill_pathname_basedir(char *out_path, const char *in_path, size_t size); void fill_pathname_basedir_noext(char *out_dir, const char *in_path, size_t size); /** * fill_pathname_parent_dir: * @out_dir : output directory * @in_dir : input directory * @size : size of output directory * * Copies parent directory of @in_dir into @out_dir. * Assumes @in_dir is a directory. Keeps trailing '/'. **/ void fill_pathname_parent_dir(char *out_dir, const char *in_dir, size_t size); /** * fill_pathname_resolve_relative: * @out_path : output path * @in_refpath : input reference path * @in_path : input path * @size : size of @out_path * * Joins basedir of @in_refpath together with @in_path. * If @in_path is an absolute path, out_path = in_path. * E.g.: in_refpath = "/foo/bar/baz.a", in_path = "foobar.cg", * out_path = "/foo/bar/foobar.cg". **/ void fill_pathname_resolve_relative(char *out_path, const char *in_refpath, const char *in_path, size_t size); /** * fill_pathname_join: * @out_path : output path * @dir : directory * @path : path * @size : size of output path * * Joins a directory (@dir) and path (@path) together. * Makes sure not to get two consecutive slashes * between directory and path. **/ void fill_pathname_join(char *out_path, const char *dir, const char *path, size_t size); void fill_pathname_join_special_ext(char *out_path, const char *dir, const char *path, const char *last, const char *ext, size_t size); void fill_pathname_join_concat(char *out_path, const char *dir, const char *path, const char *concat, size_t size); void fill_pathname_join_noext(char *out_path, const char *dir, const char *path, size_t size); /** * fill_pathname_join_delim: * @out_path : output path * @dir : directory * @path : path * @delim : delimiter * @size : size of output path * * Joins a directory (@dir) and path (@path) together * using the given delimiter (@delim). **/ void fill_pathname_join_delim(char *out_path, const char *dir, const char *path, const char delim, size_t size); void fill_pathname_join_delim_concat(char *out_path, const char *dir, const char *path, const char delim, const char *concat, size_t size); /** * fill_short_pathname_representation: * @out_rep : output representation * @in_path : input path * @size : size of output representation * * Generates a short representation of path. It should only * be used for displaying the result; the output representation is not * binding in any meaningful way (for a normal path, this is the same as basename) * In case of more complex URLs, this should cut everything except for * the main image file. * * E.g.: "/path/to/game.img" -> game.img * "/path/to/myarchive.7z#folder/to/game.img" -> game.img */ void fill_short_pathname_representation(char* out_rep, const char *in_path, size_t size); void fill_short_pathname_representation_noext(char* out_rep, const char *in_path, size_t size); void fill_pathname_expand_special(char *out_path, const char *in_path, size_t size); void fill_pathname_abbreviate_special(char *out_path, const char *in_path, size_t size); /** * path_char_is_slash: * @c : character * * Checks if character (@c) is a slash. * * Returns: true (1) if character is a slash, otherwise false (0). */ static INLINE bool path_char_is_slash(char c) { #ifdef _WIN32 return (c == '/') || (c == '\\'); #else return (c == '/'); #endif } /** * path_default_slash: * * Gets the default slash separator. * * Returns: default slash separator. */ static INLINE const char *path_default_slash(void) { #ifdef _WIN32 return "\\"; #else return "/"; #endif } /** * fill_pathname_slash: * @path : path * @size : size of path * * Assumes path is a directory. Appends a slash * if not already there. **/ void fill_pathname_slash(char *path, size_t size); #ifndef RARCH_CONSOLE void fill_pathname_application_path(char *buf, size_t size); #endif /** * path_mkdir: * @dir : directory * * Create directory on filesystem. * * Returns: true (1) if directory could be created, otherwise false (0). **/ bool path_mkdir(const char *dir); RETRO_END_DECLS #endif desmume/src/libretro-common/formats/png/test/Makefile000664 001750 001750 00000001621 12755534123 024125 0ustar00sergiosergio000000 000000 TARGET := rpng LIBRETRO_PNG_DIR := .. LIBRETRO_COMM_DIR := ../../.. HAVE_IMLIB2=1 LDFLAGS += -lz ifeq ($(HAVE_IMLIB2),1) CFLAGS += -DHAVE_IMLIB2 LDFLAGS += -lImlib2 endif SOURCES_C := \ rpng_test.c \ $(LIBRETRO_PNG_DIR)/rpng.c \ $(LIBRETRO_PNG_DIR)/rpng_encode.c \ $(LIBRETRO_COMM_DIR)/compat/compat_strl.c \ $(LIBRETRO_COMM_DIR)/file/nbio/nbio_stdio.c \ $(LIBRETRO_COMM_DIR)/file/archive_file.c \ $(LIBRETRO_COMM_DIR)/file/archive_file_zlib.c \ $(LIBRETRO_COMM_DIR)//file/file_path.c \ $(LIBRETRO_COMM_DIR)//file/retro_stat.c \ $(LIBRETRO_COMM_DIR)/streams/file_stream.c \ $(LIBRETRO_COMM_DIR)/lists/string_list.c OBJS := $(SOURCES_C:.c=.o) CFLAGS += -Wall -pedantic -std=gnu99 -O0 -g -DHAVE_ZLIB -DRPNG_TEST -I$(LIBRETRO_COMM_DIR)/include all: $(TARGET) %.o: %.c $(CC) -c -o $@ $< $(CFLAGS) $(TARGET): $(OBJS) $(CC) -o $@ $^ $(LDFLAGS) clean: rm -f $(TARGET) $(OBJS) .PHONY: clean desmume/src/libretro-common/include/formats/rtga.h000664 001750 001750 00000003450 12755534123 023455 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2016 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (rtga.h). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef __LIBRETRO_SDK_FORMAT_RTGA_H__ #define __LIBRETRO_SDK_FORMAT_RTGA_H__ #include #include #include #include RETRO_BEGIN_DECLS typedef struct rtga rtga_t; int rtga_process_image(rtga_t *rtga, void **buf, size_t size, unsigned *width, unsigned *height); bool rtga_set_buf_ptr(rtga_t *rtga, void *data); void rtga_free(rtga_t *rtga); rtga_t *rtga_alloc(void); RETRO_END_DECLS #endif desmume/src/libretro-common/compat/compat_ifaddrs.c000664 001750 001750 00000046111 12755534123 023660 0ustar00sergiosergio000000 000000 /* Copyright (c) 2013, Kenneth MacKay 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. 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 HOLDER 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 #include #include #include #include #include #include #include typedef struct NetlinkList { struct NetlinkList *m_next; struct nlmsghdr *m_data; unsigned int m_size; } NetlinkList; static int netlink_socket(void) { int l_socket = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE); if(l_socket < 0) { return -1; } struct sockaddr_nl l_addr; memset(&l_addr, 0, sizeof(l_addr)); l_addr.nl_family = AF_NETLINK; if(bind(l_socket, (struct sockaddr *)&l_addr, sizeof(l_addr)) < 0) { close(l_socket); return -1; } return l_socket; } static int netlink_send(int p_socket, int p_request) { struct { struct nlmsghdr m_hdr; struct rtgenmsg m_msg; } l_data; memset(&l_data, 0, sizeof(l_data)); l_data.m_hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtgenmsg)); l_data.m_hdr.nlmsg_type = p_request; l_data.m_hdr.nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST; l_data.m_hdr.nlmsg_pid = 0; l_data.m_hdr.nlmsg_seq = p_socket; l_data.m_msg.rtgen_family = AF_UNSPEC; struct sockaddr_nl l_addr; memset(&l_addr, 0, sizeof(l_addr)); l_addr.nl_family = AF_NETLINK; return (sendto(p_socket, &l_data.m_hdr, l_data.m_hdr.nlmsg_len, 0, (struct sockaddr *)&l_addr, sizeof(l_addr))); } static int netlink_recv(int p_socket, void *p_buffer, size_t p_len) { struct msghdr l_msg; struct iovec l_iov = { p_buffer, p_len }; struct sockaddr_nl l_addr; for(;;) { l_msg.msg_name = (void *)&l_addr; l_msg.msg_namelen = sizeof(l_addr); l_msg.msg_iov = &l_iov; l_msg.msg_iovlen = 1; l_msg.msg_control = NULL; l_msg.msg_controllen = 0; l_msg.msg_flags = 0; int l_result = recvmsg(p_socket, &l_msg, 0); if(l_result < 0) { if(errno == EINTR) { continue; } return -2; } if(l_msg.msg_flags & MSG_TRUNC) { // buffer was too small return -1; } return l_result; } } static struct nlmsghdr *getNetlinkResponse(int p_socket, int *p_size, int *p_done) { size_t l_size = 4096; void *l_buffer = NULL; for(;;) { free(l_buffer); l_buffer = malloc(l_size); if (l_buffer == NULL) { return NULL; } int l_read = netlink_recv(p_socket, l_buffer, l_size); *p_size = l_read; if(l_read == -2) { free(l_buffer); return NULL; } if(l_read >= 0) { pid_t l_pid = getpid(); struct nlmsghdr *l_hdr; for(l_hdr = (struct nlmsghdr *)l_buffer; NLMSG_OK(l_hdr, (unsigned int)l_read); l_hdr = (struct nlmsghdr *)NLMSG_NEXT(l_hdr, l_read)) { if((pid_t)l_hdr->nlmsg_pid != l_pid || (int)l_hdr->nlmsg_seq != p_socket) { continue; } if(l_hdr->nlmsg_type == NLMSG_DONE) { *p_done = 1; break; } if(l_hdr->nlmsg_type == NLMSG_ERROR) { free(l_buffer); return NULL; } } return l_buffer; } l_size *= 2; } } static NetlinkList *newListItem(struct nlmsghdr *p_data, unsigned int p_size) { NetlinkList *l_item = malloc(sizeof(NetlinkList)); if (l_item == NULL) { return NULL; } l_item->m_next = NULL; l_item->m_data = p_data; l_item->m_size = p_size; return l_item; } static void freeResultList(NetlinkList *p_list) { NetlinkList *l_cur; while(p_list) { l_cur = p_list; p_list = p_list->m_next; free(l_cur->m_data); free(l_cur); } } static NetlinkList *getResultList(int p_socket, int p_request) { if(netlink_send(p_socket, p_request) < 0) { return NULL; } NetlinkList *l_list = NULL; NetlinkList *l_end = NULL; int l_size; int l_done = 0; while(!l_done) { struct nlmsghdr *l_hdr = getNetlinkResponse(p_socket, &l_size, &l_done); if(!l_hdr) { // error freeResultList(l_list); return NULL; } NetlinkList *l_item = newListItem(l_hdr, l_size); if (!l_item) { freeResultList(l_list); return NULL; } if(!l_list) { l_list = l_item; } else { l_end->m_next = l_item; } l_end = l_item; } return l_list; } static size_t maxSize(size_t a, size_t b) { return (a > b ? a : b); } static size_t calcAddrLen(sa_family_t p_family, int p_dataSize) { switch(p_family) { case AF_INET: return sizeof(struct sockaddr_in); case AF_INET6: return sizeof(struct sockaddr_in6); case AF_PACKET: return maxSize(sizeof(struct sockaddr_ll), offsetof(struct sockaddr_ll, sll_addr) + p_dataSize); default: return maxSize(sizeof(struct sockaddr), offsetof(struct sockaddr, sa_data) + p_dataSize); } } static void makeSockaddr(sa_family_t p_family, struct sockaddr *p_dest, void *p_data, size_t p_size) { switch(p_family) { case AF_INET: memcpy(&((struct sockaddr_in*)p_dest)->sin_addr, p_data, p_size); break; case AF_INET6: memcpy(&((struct sockaddr_in6*)p_dest)->sin6_addr, p_data, p_size); break; case AF_PACKET: memcpy(((struct sockaddr_ll*)p_dest)->sll_addr, p_data, p_size); ((struct sockaddr_ll*)p_dest)->sll_halen = p_size; break; default: memcpy(p_dest->sa_data, p_data, p_size); break; } p_dest->sa_family = p_family; } static void addToEnd(struct ifaddrs **p_resultList, struct ifaddrs *p_entry) { if(!*p_resultList) { *p_resultList = p_entry; } else { struct ifaddrs *l_cur = *p_resultList; while(l_cur->ifa_next) { l_cur = l_cur->ifa_next; } l_cur->ifa_next = p_entry; } } static int interpretLink(struct nlmsghdr *p_hdr, struct ifaddrs **p_resultList) { struct ifinfomsg *l_info = (struct ifinfomsg *)NLMSG_DATA(p_hdr); size_t l_nameSize = 0; size_t l_addrSize = 0; size_t l_dataSize = 0; size_t l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifinfomsg)); struct rtattr *l_rta; for(l_rta = IFLA_RTA(l_info); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize)) { size_t l_rtaDataSize = RTA_PAYLOAD(l_rta); switch(l_rta->rta_type) { case IFLA_ADDRESS: case IFLA_BROADCAST: l_addrSize += NLMSG_ALIGN(calcAddrLen(AF_PACKET, l_rtaDataSize)); break; case IFLA_IFNAME: l_nameSize += NLMSG_ALIGN(l_rtaSize + 1); break; case IFLA_STATS: l_dataSize += NLMSG_ALIGN(l_rtaSize); break; default: break; } } struct ifaddrs *l_entry = malloc(sizeof(struct ifaddrs) + sizeof(int) + l_nameSize + l_addrSize + l_dataSize); if (l_entry == NULL) { return -1; } memset(l_entry, 0, sizeof(struct ifaddrs)); l_entry->ifa_name = ""; char *l_index = ((char *)l_entry) + sizeof(struct ifaddrs); char *l_name = l_index + sizeof(int); char *l_addr = l_name + l_nameSize; char *l_data = l_addr + l_addrSize; // save the interface index so we can look it up when handling the addresses. memcpy(l_index, &l_info->ifi_index, sizeof(int)); l_entry->ifa_flags = l_info->ifi_flags; l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifinfomsg)); for(l_rta = IFLA_RTA(l_info); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize)) { void *l_rtaData = RTA_DATA(l_rta); size_t l_rtaDataSize = RTA_PAYLOAD(l_rta); switch(l_rta->rta_type) { case IFLA_ADDRESS: case IFLA_BROADCAST: { size_t l_addrLen = calcAddrLen(AF_PACKET, l_rtaDataSize); makeSockaddr(AF_PACKET, (struct sockaddr *)l_addr, l_rtaData, l_rtaDataSize); ((struct sockaddr_ll *)l_addr)->sll_ifindex = l_info->ifi_index; ((struct sockaddr_ll *)l_addr)->sll_hatype = l_info->ifi_type; if(l_rta->rta_type == IFLA_ADDRESS) { l_entry->ifa_addr = (struct sockaddr *)l_addr; } else { l_entry->ifa_broadaddr = (struct sockaddr *)l_addr; } l_addr += NLMSG_ALIGN(l_addrLen); break; } case IFLA_IFNAME: strncpy(l_name, l_rtaData, l_rtaDataSize); l_name[l_rtaDataSize] = '\0'; l_entry->ifa_name = l_name; break; case IFLA_STATS: memcpy(l_data, l_rtaData, l_rtaDataSize); l_entry->ifa_data = l_data; break; default: break; } } addToEnd(p_resultList, l_entry); return 0; } static struct ifaddrs *findInterface(int p_index, struct ifaddrs **p_links, int p_numLinks) { int l_num = 0; struct ifaddrs *l_cur = *p_links; while(l_cur && l_num < p_numLinks) { char *l_indexPtr = ((char *)l_cur) + sizeof(struct ifaddrs); int l_index; memcpy(&l_index, l_indexPtr, sizeof(int)); if(l_index == p_index) { return l_cur; } l_cur = l_cur->ifa_next; ++l_num; } return NULL; } static int interpretAddr(struct nlmsghdr *p_hdr, struct ifaddrs **p_resultList, int p_numLinks) { struct ifaddrmsg *l_info = (struct ifaddrmsg *)NLMSG_DATA(p_hdr); struct ifaddrs *l_interface = findInterface(l_info->ifa_index, p_resultList, p_numLinks); if(l_info->ifa_family == AF_PACKET) { return 0; } size_t l_nameSize = 0; size_t l_addrSize = 0; int l_addedNetmask = 0; size_t l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifaddrmsg)); struct rtattr *l_rta; for(l_rta = IFA_RTA(l_info); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize)) { size_t l_rtaDataSize = RTA_PAYLOAD(l_rta); switch(l_rta->rta_type) { case IFA_ADDRESS: case IFA_LOCAL: if((l_info->ifa_family == AF_INET || l_info->ifa_family == AF_INET6) && !l_addedNetmask) { // make room for netmask l_addrSize += NLMSG_ALIGN(calcAddrLen(l_info->ifa_family, l_rtaDataSize)); l_addedNetmask = 1; } case IFA_BROADCAST: l_addrSize += NLMSG_ALIGN(calcAddrLen(l_info->ifa_family, l_rtaDataSize)); break; case IFA_LABEL: l_nameSize += NLMSG_ALIGN(l_rtaSize + 1); break; default: break; } } struct ifaddrs *l_entry = malloc(sizeof(struct ifaddrs) + l_nameSize + l_addrSize); if (l_entry == NULL) { return -1; } memset(l_entry, 0, sizeof(struct ifaddrs)); l_entry->ifa_name = (l_interface ? l_interface->ifa_name : ""); char *l_name = ((char *)l_entry) + sizeof(struct ifaddrs); char *l_addr = l_name + l_nameSize; l_entry->ifa_flags = l_info->ifa_flags; if(l_interface) { l_entry->ifa_flags |= l_interface->ifa_flags; } l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifaddrmsg)); for(l_rta = IFA_RTA(l_info); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize)) { void *l_rtaData = RTA_DATA(l_rta); size_t l_rtaDataSize = RTA_PAYLOAD(l_rta); switch(l_rta->rta_type) { case IFA_ADDRESS: case IFA_BROADCAST: case IFA_LOCAL: { size_t l_addrLen = calcAddrLen(l_info->ifa_family, l_rtaDataSize); makeSockaddr(l_info->ifa_family, (struct sockaddr *)l_addr, l_rtaData, l_rtaDataSize); if(l_info->ifa_family == AF_INET6) { if(IN6_IS_ADDR_LINKLOCAL((struct in6_addr *)l_rtaData) || IN6_IS_ADDR_MC_LINKLOCAL((struct in6_addr *)l_rtaData)) { ((struct sockaddr_in6 *)l_addr)->sin6_scope_id = l_info->ifa_index; } } if(l_rta->rta_type == IFA_ADDRESS) { // apparently in a point-to-point network IFA_ADDRESS contains the dest address and IFA_LOCAL contains the local address if(l_entry->ifa_addr) { l_entry->ifa_dstaddr = (struct sockaddr *)l_addr; } else { l_entry->ifa_addr = (struct sockaddr *)l_addr; } } else if(l_rta->rta_type == IFA_LOCAL) { if(l_entry->ifa_addr) { l_entry->ifa_dstaddr = l_entry->ifa_addr; } l_entry->ifa_addr = (struct sockaddr *)l_addr; } else { l_entry->ifa_broadaddr = (struct sockaddr *)l_addr; } l_addr += NLMSG_ALIGN(l_addrLen); break; } case IFA_LABEL: strncpy(l_name, l_rtaData, l_rtaDataSize); l_name[l_rtaDataSize] = '\0'; l_entry->ifa_name = l_name; break; default: break; } } if(l_entry->ifa_addr && (l_entry->ifa_addr->sa_family == AF_INET || l_entry->ifa_addr->sa_family == AF_INET6)) { unsigned l_maxPrefix = (l_entry->ifa_addr->sa_family == AF_INET ? 32 : 128); unsigned l_prefix = (l_info->ifa_prefixlen > l_maxPrefix ? l_maxPrefix : l_info->ifa_prefixlen); char l_mask[16] = {0}; unsigned i; for(i=0; i<(l_prefix/8); ++i) { l_mask[i] = 0xff; } if(l_prefix % 8) { l_mask[i] = 0xff << (8 - (l_prefix % 8)); } makeSockaddr(l_entry->ifa_addr->sa_family, (struct sockaddr *)l_addr, l_mask, l_maxPrefix / 8); l_entry->ifa_netmask = (struct sockaddr *)l_addr; } addToEnd(p_resultList, l_entry); return 0; } static int interpretLinks(int p_socket, NetlinkList *p_netlinkList, struct ifaddrs **p_resultList) { int l_numLinks = 0; pid_t l_pid = getpid(); for(; p_netlinkList; p_netlinkList = p_netlinkList->m_next) { unsigned int l_nlsize = p_netlinkList->m_size; struct nlmsghdr *l_hdr; for(l_hdr = p_netlinkList->m_data; NLMSG_OK(l_hdr, l_nlsize); l_hdr = NLMSG_NEXT(l_hdr, l_nlsize)) { if((pid_t)l_hdr->nlmsg_pid != l_pid || (int)l_hdr->nlmsg_seq != p_socket) { continue; } if(l_hdr->nlmsg_type == NLMSG_DONE) { break; } if(l_hdr->nlmsg_type == RTM_NEWLINK) { if(interpretLink(l_hdr, p_resultList) == -1) { return -1; } ++l_numLinks; } } } return l_numLinks; } static int interpretAddrs(int p_socket, NetlinkList *p_netlinkList, struct ifaddrs **p_resultList, int p_numLinks) { pid_t l_pid = getpid(); for(; p_netlinkList; p_netlinkList = p_netlinkList->m_next) { unsigned int l_nlsize = p_netlinkList->m_size; struct nlmsghdr *l_hdr; for(l_hdr = p_netlinkList->m_data; NLMSG_OK(l_hdr, l_nlsize); l_hdr = NLMSG_NEXT(l_hdr, l_nlsize)) { if((pid_t)l_hdr->nlmsg_pid != l_pid || (int)l_hdr->nlmsg_seq != p_socket) { continue; } if(l_hdr->nlmsg_type == NLMSG_DONE) { break; } if(l_hdr->nlmsg_type == RTM_NEWADDR) { if (interpretAddr(l_hdr, p_resultList, p_numLinks) == -1) { return -1; } } } } return 0; } int getifaddrs(struct ifaddrs **ifap) { if(!ifap) { return -1; } *ifap = NULL; int l_socket = netlink_socket(); if(l_socket < 0) { return -1; } NetlinkList *l_linkResults = getResultList(l_socket, RTM_GETLINK); if(!l_linkResults) { close(l_socket); return -1; } NetlinkList *l_addrResults = getResultList(l_socket, RTM_GETADDR); if(!l_addrResults) { close(l_socket); freeResultList(l_linkResults); return -1; } int l_result = 0; int l_numLinks = interpretLinks(l_socket, l_linkResults, ifap); if(l_numLinks == -1 || interpretAddrs(l_socket, l_addrResults, ifap, l_numLinks) == -1) { l_result = -1; } freeResultList(l_linkResults); freeResultList(l_addrResults); close(l_socket); return l_result; } void freeifaddrs(struct ifaddrs *ifa) { struct ifaddrs *l_cur; while(ifa) { l_cur = ifa; ifa = ifa->ifa_next; free(l_cur); } } desmume/src/libretro-common/file/archive_file.c000664 001750 001750 00000043501 12755534123 022755 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2016 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (archive_file.c). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include #include #include #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef HAVE_MMAP #include #include #include #include #include #endif #include #include #include #include #include #include #include #ifndef CENTRAL_FILE_HEADER_SIGNATURE #define CENTRAL_FILE_HEADER_SIGNATURE 0x02014b50 #endif #ifndef END_OF_CENTRAL_DIR_SIGNATURE #define END_OF_CENTRAL_DIR_SIGNATURE 0x06054b50 #endif struct zip_extract_userdata { char *zip_path; char *first_extracted_file_path; const char *extraction_directory; size_t zip_path_size; struct string_list *ext; bool found_content; }; enum file_archive_compression_mode { ZLIB_MODE_UNCOMPRESSED = 0, ZLIB_MODE_DEFLATE = 8 }; typedef struct { #ifdef HAVE_MMAP int fd; #endif void *data; size_t size; } file_archive_file_data_t; #ifdef HAVE_MMAP /* Closes, unmaps and frees. */ static void file_archive_free(void *handle) { file_archive_file_data_t *data = (file_archive_file_data_t*)handle; if (!data) return; if (data->data) munmap(data->data, data->size); if (data->fd >= 0) close(data->fd); free(data); } static const uint8_t *file_archive_data(void *handle) { file_archive_file_data_t *data = (file_archive_file_data_t*)handle; if (!data) return NULL; return (const uint8_t*)data->data; } static size_t file_archive_size(void *handle) { file_archive_file_data_t *data = (file_archive_file_data_t*)handle; if (!data) return 0; return data->size; } static void *file_archive_open(const char *path) { file_archive_file_data_t *data = (file_archive_file_data_t*)calloc(1, sizeof(*data)); if (!data) return NULL; data->fd = open(path, O_RDONLY); /* Failed to open archive. */ if (data->fd < 0) goto error; data->size = path_get_size(path); if (!data->size) return data; data->data = mmap(NULL, data->size, PROT_READ, MAP_SHARED, data->fd, 0); if (data->data == MAP_FAILED) { data->data = NULL; /* Failed to mmap() file */ goto error; } return data; error: file_archive_free(data); return NULL; } #else /* Closes, unmaps and frees. */ static void file_archive_free(void *handle) { file_archive_file_data_t *data = (file_archive_file_data_t*)handle; if (!data) return; free(data->data); free(data); } static const uint8_t *file_archive_data(void *handle) { file_archive_file_data_t *data = (file_archive_file_data_t*)handle; if (!data) return NULL; return (const uint8_t*)data->data; } static size_t file_archive_size(void *handle) { file_archive_file_data_t *data = (file_archive_file_data_t*)handle; if (!data) return 0; return data->size; } static void *file_archive_open(const char *path) { ssize_t ret = -1; bool read_from_file = false; file_archive_file_data_t *data = (file_archive_file_data_t*) calloc(1, sizeof(*data)); if (!data) return NULL; read_from_file = filestream_read_file(path, &data->data, &ret); /* Failed to open archive? */ if (!read_from_file || ret < 0) goto error; data->size = ret; return data; error: file_archive_free(data); return NULL; } #endif static int file_archive_get_file_list_cb( const char *path, const char *valid_exts, const uint8_t *cdata, unsigned cmode, uint32_t csize, uint32_t size, uint32_t checksum, void *userdata) { union string_list_elem_attr attr; struct string_list *ext_list = NULL; const char *file_ext = NULL; struct string_list *list = (struct string_list*)userdata; (void)cdata; (void)cmode; (void)csize; (void)size; (void)checksum; memset(&attr, 0, sizeof(attr)); if (valid_exts) ext_list = string_split(valid_exts, "|"); if (ext_list) { /* Checks if this entry is a directory or a file. */ char last_char = path[strlen(path)-1]; /* Skip if directory. */ if (last_char == '/' || last_char == '\\' ) goto error; file_ext = path_get_extension(path); if (!file_ext || !string_list_find_elem_prefix(ext_list, ".", file_ext)) goto error; attr.i = RARCH_COMPRESSED_FILE_IN_ARCHIVE; string_list_free(ext_list); } return string_list_append(list, path, attr); error: string_list_free(ext_list); return 0; } static int file_archive_extract_cb(const char *name, const char *valid_exts, const uint8_t *cdata, unsigned cmode, uint32_t csize, uint32_t size, uint32_t checksum, void *userdata) { const char *ext = path_get_extension(name); struct zip_extract_userdata *data = (struct zip_extract_userdata*)userdata; /* Extract first content that matches our list. */ if (ext && string_list_find_elem(data->ext, ext)) { char new_path[PATH_MAX_LENGTH] = {0}; if (data->extraction_directory) fill_pathname_join(new_path, data->extraction_directory, path_basename(name), sizeof(new_path)); else fill_pathname_resolve_relative(new_path, data->zip_path, path_basename(name), sizeof(new_path)); data->first_extracted_file_path = strdup(new_path); data->found_content = file_archive_perform_mode(new_path, valid_exts, cdata, cmode, csize, size, 0, NULL); return 0; } return 1; } static uint32_t read_le(const uint8_t *data, unsigned size) { unsigned i; uint32_t val = 0; size *= 8; for (i = 0; i < size; i += 8) val |= (uint32_t)*data++ << i; return val; } static int file_archive_parse_file_iterate_step_internal( file_archive_transfer_t *state, char *filename, const uint8_t **cdata, unsigned *cmode, uint32_t *size, uint32_t *csize, uint32_t *checksum, unsigned *payback) { uint32_t offset; uint32_t namelength, extralength, commentlength, offsetNL, offsetEL; uint32_t signature = read_le(state->directory + 0, 4); if (signature != CENTRAL_FILE_HEADER_SIGNATURE) return 0; *cmode = read_le(state->directory + 10, 2); *checksum = read_le(state->directory + 16, 4); *csize = read_le(state->directory + 20, 4); *size = read_le(state->directory + 24, 4); namelength = read_le(state->directory + 28, 2); extralength = read_le(state->directory + 30, 2); commentlength = read_le(state->directory + 32, 2); if (namelength >= PATH_MAX_LENGTH) return -1; memcpy(filename, state->directory + 46, namelength); offset = read_le(state->directory + 42, 4); offsetNL = read_le(state->data + offset + 26, 2); offsetEL = read_le(state->data + offset + 28, 2); *cdata = state->data + offset + 30 + offsetNL + offsetEL; *payback = 46 + namelength + extralength + commentlength; return 1; } static int file_archive_parse_file_iterate_step(file_archive_transfer_t *state, const char *valid_exts, void *userdata, file_archive_file_cb file_cb) { const uint8_t *cdata = NULL; uint32_t checksum = 0; uint32_t size = 0; uint32_t csize = 0; unsigned cmode = 0; unsigned payload = 0; char filename[PATH_MAX_LENGTH] = {0}; int ret = file_archive_parse_file_iterate_step_internal(state, filename, &cdata, &cmode, &size, &csize, &checksum, &payload); if (ret != 1) return ret; #if 0 RARCH_LOG("OFFSET: %u, CSIZE: %u, SIZE: %u.\n", offset + 30 + offsetNL + offsetEL, csize, size); #endif if (!file_cb(filename, valid_exts, cdata, cmode, csize, size, checksum, userdata)) return 0; state->directory += payload; return 1; } static int file_archive_parse_file_init(file_archive_transfer_t *state, const char *file) { state->backend = file_archive_get_default_file_backend(); if (!state->backend) return -1; state->handle = file_archive_open(file); if (!state->handle) return -1; state->zip_size = file_archive_size(state->handle); if (state->zip_size < 22) return -1; state->data = file_archive_data(state->handle); state->footer = state->data + state->zip_size - 22; for (;; state->footer--) { if (state->footer <= state->data + 22) return -1; if (read_le(state->footer, 4) == END_OF_CENTRAL_DIR_SIGNATURE) { unsigned comment_len = read_le(state->footer + 20, 2); if (state->footer + 22 + comment_len == state->data + state->zip_size) break; } } state->directory = state->data + read_le(state->footer + 16, 4); return 0; } /** * file_archive_decompress_data_to_file: * @path : filename path of archive. * @valid_exts : Valid extensions of archive to be parsed. * If NULL, allow all. * @cdata : input data. * @csize : size of input data. * @size : output file size * @checksum : CRC32 checksum from input data. * * Decompress data to file. * * Returns: true (1) on success, otherwise false (0). **/ static int file_archive_decompress_data_to_file( file_archive_file_handle_t *handle, int ret, const char *path, const char *valid_exts, const uint8_t *cdata, uint32_t csize, uint32_t size, uint32_t checksum) { if (handle) { handle->backend->stream_free(handle->stream); free(handle->stream); } if (!handle || ret == -1) { ret = 0; goto end; } handle->real_checksum = handle->backend->stream_crc_calculate( 0, handle->data, size); #if 0 if (handle->real_checksum != checksum) { /* File CRC difers from ZIP CRC. */ printf("File CRC differs from ZIP CRC. File: 0x%x, ZIP: 0x%x.\n", (unsigned)handle->real_checksum, (unsigned)checksum); } #endif if (!filestream_write_file(path, handle->data, size)) { ret = false; goto end; } end: if (handle && handle->data) free(handle->data); return ret; } int file_archive_parse_file_iterate( file_archive_transfer_t *state, bool *returnerr, const char *file, const char *valid_exts, file_archive_file_cb file_cb, void *userdata) { if (!state) return -1; switch (state->type) { case ZLIB_TRANSFER_NONE: break; case ZLIB_TRANSFER_INIT: if (file_archive_parse_file_init(state, file) == 0) state->type = ZLIB_TRANSFER_ITERATE; else state->type = ZLIB_TRANSFER_DEINIT_ERROR; break; case ZLIB_TRANSFER_ITERATE: { int ret = file_archive_parse_file_iterate_step(state, valid_exts, userdata, file_cb); if (ret != 1) state->type = ZLIB_TRANSFER_DEINIT; if (ret == -1) state->type = ZLIB_TRANSFER_DEINIT_ERROR; } break; case ZLIB_TRANSFER_DEINIT_ERROR: *returnerr = false; case ZLIB_TRANSFER_DEINIT: if (state->handle) file_archive_free(state->handle); state->handle = NULL; break; } if (state->type == ZLIB_TRANSFER_DEINIT || state->type == ZLIB_TRANSFER_DEINIT_ERROR) return -1; return 0; } void file_archive_parse_file_iterate_stop(file_archive_transfer_t *state) { if (!state || !state->handle) return; state->type = ZLIB_TRANSFER_DEINIT; file_archive_parse_file_iterate(state, NULL, NULL, NULL, NULL, NULL); } /** * file_archive_parse_file: * @file : filename path of archive * @valid_exts : Valid extensions of archive to be parsed. * If NULL, allow all. * @file_cb : file_cb function pointer * @userdata : userdata to pass to file_cb function pointer. * * Low-level file parsing. Enumerates over all files and calls * file_cb with userdata. * * Returns: true (1) on success, otherwise false (0). **/ static bool file_archive_parse_file(const char *file, const char *valid_exts, file_archive_file_cb file_cb, void *userdata) { file_archive_transfer_t state = {0}; bool returnerr = true; state.type = ZLIB_TRANSFER_INIT; for (;;) { if (file_archive_parse_file_iterate(&state, &returnerr, file, valid_exts, file_cb, userdata) != 0) break; } return returnerr; } int file_archive_parse_file_progress(file_archive_transfer_t *state) { /* FIXME: this estimate is worse than before */ ptrdiff_t delta = state->directory - state->data; return delta * 100 / state->zip_size; } /** * file_archive_extract_first_content_file: * @zip_path : filename path to ZIP archive. * @zip_path_size : size of ZIP archive. * @valid_exts : valid extensions for a content file. * @extraction_directory : the directory to extract temporary * unzipped content to. * * Extract first content file from archive. * * Returns : true (1) on success, otherwise false (0). **/ bool file_archive_extract_first_content_file( char *zip_path, size_t zip_path_size, const char *valid_exts, const char *extraction_directory, char *out_path, size_t len) { struct string_list *list = NULL; bool ret = true; struct zip_extract_userdata userdata = {0}; /* We cannot unzip if the libretro * implementation does not have any valid extensions. */ if (!valid_exts) return false; list = string_split(valid_exts, "|"); if (!list) { ret = false; goto end; } userdata.zip_path = zip_path; userdata.zip_path_size = zip_path_size; userdata.extraction_directory = extraction_directory; userdata.ext = list; if (!file_archive_parse_file(zip_path, valid_exts, file_archive_extract_cb, &userdata)) { /* Parsing file archive failed. */ ret = false; goto end; } if (!userdata.found_content) { /* Didn't find any content that matched valid extensions * for libretro implementation. */ ret = false; goto end; } if (*userdata.first_extracted_file_path) strlcpy(out_path, userdata.first_extracted_file_path, len); end: if (userdata.first_extracted_file_path) free(userdata.first_extracted_file_path); if (list) string_list_free(list); return ret; } /** * file_archive_get_file_list: * @path : filename path of archive * * Returns: string listing of files from archive on success, otherwise NULL. **/ struct string_list *file_archive_get_file_list(const char *path, const char *valid_exts) { struct string_list *list = string_list_new(); if (!list) goto error; if (!file_archive_parse_file(path, valid_exts, file_archive_get_file_list_cb, list)) goto error; return list; error: if (list) string_list_free(list); return NULL; } bool file_archive_perform_mode(const char *path, const char *valid_exts, const uint8_t *cdata, unsigned cmode, uint32_t csize, uint32_t size, uint32_t crc32, void *userdata) { switch (cmode) { case ZLIB_MODE_UNCOMPRESSED: if (!filestream_write_file(path, cdata, size)) goto error; break; case ZLIB_MODE_DEFLATE: { int ret = 0; file_archive_file_handle_t handle = {0}; handle.backend = file_archive_get_default_file_backend(); if (!handle.backend->stream_decompress_data_to_file_init(&handle, cdata, csize, size)) goto error; do{ ret = handle.backend->stream_decompress_data_to_file_iterate( handle.stream); }while(ret == 0); if (!file_archive_decompress_data_to_file(&handle, ret, path, valid_exts, cdata, csize, size, crc32)) goto error; } break; default: goto error; } return true; error: return false; } const struct file_archive_file_backend *file_archive_get_default_file_backend(void) { return &zlib_backend; } desmume/src/Disassembler.h000664 001750 001750 00000001667 12755534123 016737 0ustar00sergiosergio000000 000000 /* Copyright (C) 2006 yopyop Copyright (C) 2006-2009 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the this software. If not, see . */ #ifndef DISASSEMBLER_H #define DISASSEMBLER_H #include "types.h" typedef char* (* DisasmOpFunc)(u32 adr, u32 i, char * txt); extern const DisasmOpFunc des_arm_instructions_set[4096]; extern const DisasmOpFunc des_thumb_instructions_set[1024]; #endif desmume/src/utils/dlditool.h000664 001750 001750 00000000314 12755534123 017260 0ustar00sergiosergio000000 000000 #ifndef _DLDITOOL_H #define _DLDITOOL_H #include #ifdef __cplusplus extern "C" { #endif int DLDI_tryPatch(void* data, size_t size, unsigned int device); #ifdef __cplusplus } #endif #endif desmume/src/libretro-common/gfx/scaler/pixconv.c000664 001750 001750 00000067477 12755534123 023163 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2015 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (pixconv.c). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include #include #include #include #include #include #ifdef SCALER_NO_SIMD #undef __SSE2__ #endif #if defined(__SSE2__) #include #endif void conv_rgb565_0rgb1555(void *output_, const void *input_, int width, int height, int out_stride, int in_stride) { int h; const uint16_t *input = (const uint16_t*)input_; uint16_t *output = (uint16_t*)output_; #if defined(__SSE2_) int max_width = width - 7; const __m128i hi_mask = _mm_set1_epi16(0x7fe0); const __m128i lo_mask = _mm_set1_epi16(0x1f); #endif for (h = 0; h < height; h++, output += out_stride >> 1, input += in_stride >> 1) { int w = 0; #if defined(__SSE2_) for (; w < max_width; w += 8) { const __m128i in = _mm_loadu_si128((const __m128i*)(input + w)); __m128i hi = _mm_and_si128(_mm_slli_epi16(in, 1), hi_mask); __m128i lo = _mm_and_si128(in, lo_mask); _mm_storeu_si128((__m128i*)(output + w), _mm_or_si128(hi, lo)); } #endif for (; w < width; w++) { uint16_t col = input[w]; uint16_t hi = (col >> 1) & 0x7fe0; uint16_t lo = col & 0x1f; output[w] = hi | lo; } } } void conv_0rgb1555_rgb565(void *output_, const void *input_, int width, int height, int out_stride, int in_stride) { int h; const uint16_t *input = (const uint16_t*)input_; uint16_t *output = (uint16_t*)output_; #if defined(__SSE2__) int max_width = width - 7; const __m128i hi_mask = _mm_set1_epi16( (int16_t)((0x1f << 11) | (0x1f << 6))); const __m128i lo_mask = _mm_set1_epi16(0x1f); const __m128i glow_mask = _mm_set1_epi16(1 << 5); #endif for (h = 0; h < height; h++, output += out_stride >> 1, input += in_stride >> 1) { int w = 0; #if defined(__SSE2__) for (; w < max_width; w += 8) { const __m128i in = _mm_loadu_si128((const __m128i*)(input + w)); __m128i rg = _mm_and_si128(_mm_slli_epi16(in, 1), hi_mask); __m128i b = _mm_and_si128(in, lo_mask); __m128i glow = _mm_and_si128(_mm_srli_epi16(in, 4), glow_mask); _mm_storeu_si128((__m128i*)(output + w), _mm_or_si128(rg, _mm_or_si128(b, glow))); } #endif for (; w < width; w++) { uint16_t col = input[w]; uint16_t rg = (col << 1) & ((0x1f << 11) | (0x1f << 6)); uint16_t b = col & 0x1f; uint16_t glow = (col >> 4) & (1 << 5); output[w] = rg | b | glow; } } } void conv_0rgb1555_argb8888(void *output_, const void *input_, int width, int height, int out_stride, int in_stride) { int h; const uint16_t *input = (const uint16_t*)input_; uint32_t *output = (uint32_t*)output_; #ifdef __SSE2__ const __m128i pix_mask_r = _mm_set1_epi16(0x1f << 10); const __m128i pix_mask_gb = _mm_set1_epi16(0x1f << 5); const __m128i mul15_mid = _mm_set1_epi16(0x4200); const __m128i mul15_hi = _mm_set1_epi16(0x0210); const __m128i a = _mm_set1_epi16(0x00ff); int max_width = width - 7; #endif for (h = 0; h < height; h++, output += out_stride >> 2, input += in_stride >> 1) { int w = 0; #ifdef __SSE2__ for (; w < max_width; w += 8) { __m128i res_lo_bg, res_hi_bg; __m128i res_lo_ra, res_hi_ra; __m128i res_lo, res_hi; const __m128i in = _mm_loadu_si128((const __m128i*)(input + w)); __m128i r = _mm_and_si128(in, pix_mask_r); __m128i g = _mm_and_si128(in, pix_mask_gb); __m128i b = _mm_and_si128(_mm_slli_epi16(in, 5), pix_mask_gb); r = _mm_mulhi_epi16(r, mul15_hi); g = _mm_mulhi_epi16(g, mul15_mid); b = _mm_mulhi_epi16(b, mul15_mid); res_lo_bg = _mm_unpacklo_epi8(b, g); res_hi_bg = _mm_unpackhi_epi8(b, g); res_lo_ra = _mm_unpacklo_epi8(r, a); res_hi_ra = _mm_unpackhi_epi8(r, a); res_lo = _mm_or_si128(res_lo_bg, _mm_slli_si128(res_lo_ra, 2)); res_hi = _mm_or_si128(res_hi_bg, _mm_slli_si128(res_hi_ra, 2)); _mm_storeu_si128((__m128i*)(output + w + 0), res_lo); _mm_storeu_si128((__m128i*)(output + w + 4), res_hi); } #endif for (; w < width; w++) { uint32_t col = input[w]; uint32_t r = (col >> 10) & 0x1f; uint32_t g = (col >> 5) & 0x1f; uint32_t b = (col >> 0) & 0x1f; r = (r << 3) | (r >> 2); g = (g << 3) | (g >> 2); b = (b << 3) | (b >> 2); output[w] = (0xffu << 24) | (r << 16) | (g << 8) | (b << 0); } } } void conv_rgb565_argb8888(void *output_, const void *input_, int width, int height, int out_stride, int in_stride) { int h; const uint16_t *input = (const uint16_t*)input_; uint32_t *output = (uint32_t*)output_; #if defined(__SSE2__) const __m128i pix_mask_r = _mm_set1_epi16(0x1f << 10); const __m128i pix_mask_g = _mm_set1_epi16(0x3f << 5); const __m128i pix_mask_b = _mm_set1_epi16(0x1f << 5); const __m128i mul16_r = _mm_set1_epi16(0x0210); const __m128i mul16_g = _mm_set1_epi16(0x2080); const __m128i mul16_b = _mm_set1_epi16(0x4200); const __m128i a = _mm_set1_epi16(0x00ff); int max_width = width - 7; #endif for (h = 0; h < height; h++, output += out_stride >> 2, input += in_stride >> 1) { int w = 0; #if defined(__SSE2__) for (; w < max_width; w += 8) { __m128i res_lo, res_hi; __m128i res_lo_bg, res_hi_bg, res_lo_ra, res_hi_ra; const __m128i in = _mm_loadu_si128((const __m128i*)(input + w)); __m128i r = _mm_and_si128(_mm_srli_epi16(in, 1), pix_mask_r); __m128i g = _mm_and_si128(in, pix_mask_g); __m128i b = _mm_and_si128(_mm_slli_epi16(in, 5), pix_mask_b); r = _mm_mulhi_epi16(r, mul16_r); g = _mm_mulhi_epi16(g, mul16_g); b = _mm_mulhi_epi16(b, mul16_b); res_lo_bg = _mm_unpacklo_epi8(b, g); res_hi_bg = _mm_unpackhi_epi8(b, g); res_lo_ra = _mm_unpacklo_epi8(r, a); res_hi_ra = _mm_unpackhi_epi8(r, a); res_lo = _mm_or_si128(res_lo_bg, _mm_slli_si128(res_lo_ra, 2)); res_hi = _mm_or_si128(res_hi_bg, _mm_slli_si128(res_hi_ra, 2)); _mm_storeu_si128((__m128i*)(output + w + 0), res_lo); _mm_storeu_si128((__m128i*)(output + w + 4), res_hi); } #endif for (; w < width; w++) { uint32_t col = input[w]; uint32_t r = (col >> 11) & 0x1f; uint32_t g = (col >> 5) & 0x3f; uint32_t b = (col >> 0) & 0x1f; r = (r << 3) | (r >> 2); g = (g << 2) | (g >> 4); b = (b << 3) | (b >> 2); output[w] = (0xffu << 24) | (r << 16) | (g << 8) | (b << 0); } } } void conv_argb8888_rgba4444(void *output_, const void *input_, int width, int height, int out_stride, int in_stride) { int h, w; const uint32_t *input = (const uint32_t*)input_; uint16_t *output = (uint16_t*)output_; for (h = 0; h < height; h++, output += out_stride >> 2, input += in_stride >> 1) { for (w = 0; w < width; w++) { uint32_t col = input[w]; uint32_t r = (col >> 16) & 0xf; uint32_t g = (col >> 8) & 0xf; uint32_t b = (col) & 0xf; uint32_t a = (col >> 24) & 0xf; r = (r >> 4) | r; g = (g >> 4) | g; b = (b >> 4) | b; a = (a >> 4) | a; output[w] = (r << 12) | (g << 8) | (b << 4) | a; } } } void conv_rgba4444_argb8888(void *output_, const void *input_, int width, int height, int out_stride, int in_stride) { int h, w; const uint16_t *input = (const uint16_t*)input_; uint32_t *output = (uint32_t*)output_; for (h = 0; h < height; h++, output += out_stride >> 2, input += in_stride >> 1) { for (w = 0; w < width; w++) { uint32_t col = input[w]; uint32_t r = (col >> 12) & 0xf; uint32_t g = (col >> 8) & 0xf; uint32_t b = (col >> 4) & 0xf; uint32_t a = (col >> 0) & 0xf; r = (r << 4) | r; g = (g << 4) | g; b = (b << 4) | b; a = (a << 4) | a; output[w] = (a << 24) | (r << 16) | (g << 8) | (b << 0); } } } void conv_rgba4444_rgb565(void *output_, const void *input_, int width, int height, int out_stride, int in_stride) { int h, w; const uint16_t *input = (const uint16_t*)input_; uint16_t *output = (uint16_t*)output_; for (h = 0; h < height; h++, output += out_stride >> 1, input += in_stride >> 1) { for (w = 0; w < width; w++) { uint32_t col = input[w]; uint32_t r = (col >> 12) & 0xf; uint32_t g = (col >> 8) & 0xf; uint32_t b = (col >> 4) & 0xf; output[w] = (r << 12) | (g << 7) | (b << 1); } } } #if defined(__SSE2__) /* :( TODO: Make this saner. */ static INLINE void store_bgr24_sse2(void *output, __m128i a, __m128i b, __m128i c, __m128i d) { const __m128i mask_0 = _mm_set_epi32(0, 0, 0, 0x00ffffff); const __m128i mask_1 = _mm_set_epi32(0, 0, 0x00ffffff, 0); const __m128i mask_2 = _mm_set_epi32(0, 0x00ffffff, 0, 0); const __m128i mask_3 = _mm_set_epi32(0x00ffffff, 0, 0, 0); __m128i a0 = _mm_and_si128(a, mask_0); __m128i a1 = _mm_srli_si128(_mm_and_si128(a, mask_1), 1); __m128i a2 = _mm_srli_si128(_mm_and_si128(a, mask_2), 2); __m128i a3 = _mm_srli_si128(_mm_and_si128(a, mask_3), 3); __m128i a4 = _mm_slli_si128(_mm_and_si128(b, mask_0), 12); __m128i a5 = _mm_slli_si128(_mm_and_si128(b, mask_1), 11); __m128i b0 = _mm_srli_si128(_mm_and_si128(b, mask_1), 5); __m128i b1 = _mm_srli_si128(_mm_and_si128(b, mask_2), 6); __m128i b2 = _mm_srli_si128(_mm_and_si128(b, mask_3), 7); __m128i b3 = _mm_slli_si128(_mm_and_si128(c, mask_0), 8); __m128i b4 = _mm_slli_si128(_mm_and_si128(c, mask_1), 7); __m128i b5 = _mm_slli_si128(_mm_and_si128(c, mask_2), 6); __m128i c0 = _mm_srli_si128(_mm_and_si128(c, mask_2), 10); __m128i c1 = _mm_srli_si128(_mm_and_si128(c, mask_3), 11); __m128i c2 = _mm_slli_si128(_mm_and_si128(d, mask_0), 4); __m128i c3 = _mm_slli_si128(_mm_and_si128(d, mask_1), 3); __m128i c4 = _mm_slli_si128(_mm_and_si128(d, mask_2), 2); __m128i c5 = _mm_slli_si128(_mm_and_si128(d, mask_3), 1); __m128i *out = (__m128i*)output; _mm_storeu_si128(out + 0, _mm_or_si128(a0, _mm_or_si128(a1, _mm_or_si128(a2, _mm_or_si128(a3, _mm_or_si128(a4, a5)))))); _mm_storeu_si128(out + 1, _mm_or_si128(b0, _mm_or_si128(b1, _mm_or_si128(b2, _mm_or_si128(b3, _mm_or_si128(b4, b5)))))); _mm_storeu_si128(out + 2, _mm_or_si128(c0, _mm_or_si128(c1, _mm_or_si128(c2, _mm_or_si128(c3, _mm_or_si128(c4, c5)))))); } #endif void conv_0rgb1555_bgr24(void *output_, const void *input_, int width, int height, int out_stride, int in_stride) { int h; const uint16_t *input = (const uint16_t*)input_; uint8_t *output = (uint8_t*)output_; #if defined(__SSE2__) const __m128i pix_mask_r = _mm_set1_epi16(0x1f << 10); const __m128i pix_mask_gb = _mm_set1_epi16(0x1f << 5); const __m128i mul15_mid = _mm_set1_epi16(0x4200); const __m128i mul15_hi = _mm_set1_epi16(0x0210); const __m128i a = _mm_set1_epi16(0x00ff); int max_width = width - 15; #endif for (h = 0; h < height; h++, output += out_stride, input += in_stride >> 1) { uint8_t *out = output; int w = 0; #if defined(__SSE2__) for (; w < max_width; w += 16, out += 48) { __m128i res_lo_bg0, res_lo_bg1, res_hi_bg0, res_hi_bg1, res_lo_ra0, res_lo_ra1, res_hi_ra0, res_hi_ra1, res_lo0, res_lo1, res_hi0, res_hi1; const __m128i in0 = _mm_loadu_si128((const __m128i*)(input + w + 0)); const __m128i in1 = _mm_loadu_si128((const __m128i*)(input + w + 8)); __m128i r0 = _mm_and_si128(in0, pix_mask_r); __m128i r1 = _mm_and_si128(in1, pix_mask_r); __m128i g0 = _mm_and_si128(in0, pix_mask_gb); __m128i g1 = _mm_and_si128(in1, pix_mask_gb); __m128i b0 = _mm_and_si128(_mm_slli_epi16(in0, 5), pix_mask_gb); __m128i b1 = _mm_and_si128(_mm_slli_epi16(in1, 5), pix_mask_gb); r0 = _mm_mulhi_epi16(r0, mul15_hi); r1 = _mm_mulhi_epi16(r1, mul15_hi); g0 = _mm_mulhi_epi16(g0, mul15_mid); g1 = _mm_mulhi_epi16(g1, mul15_mid); b0 = _mm_mulhi_epi16(b0, mul15_mid); b1 = _mm_mulhi_epi16(b1, mul15_mid); res_lo_bg0 = _mm_unpacklo_epi8(b0, g0); res_lo_bg1 = _mm_unpacklo_epi8(b1, g1); res_hi_bg0 = _mm_unpackhi_epi8(b0, g0); res_hi_bg1 = _mm_unpackhi_epi8(b1, g1); res_lo_ra0 = _mm_unpacklo_epi8(r0, a); res_lo_ra1 = _mm_unpacklo_epi8(r1, a); res_hi_ra0 = _mm_unpackhi_epi8(r0, a); res_hi_ra1 = _mm_unpackhi_epi8(r1, a); res_lo0 = _mm_or_si128(res_lo_bg0, _mm_slli_si128(res_lo_ra0, 2)); res_lo1 = _mm_or_si128(res_lo_bg1, _mm_slli_si128(res_lo_ra1, 2)); res_hi0 = _mm_or_si128(res_hi_bg0, _mm_slli_si128(res_hi_ra0, 2)); res_hi1 = _mm_or_si128(res_hi_bg1, _mm_slli_si128(res_hi_ra1, 2)); /* Non-POT pixel sizes ftl :( */ store_bgr24_sse2(out, res_lo0, res_hi0, res_lo1, res_hi1); } #endif for (; w < width; w++) { uint32_t col = input[w]; uint32_t b = (col >> 0) & 0x1f; uint32_t g = (col >> 5) & 0x1f; uint32_t r = (col >> 10) & 0x1f; b = (b << 3) | (b >> 2); g = (g << 3) | (g >> 2); r = (r << 3) | (r >> 2); *out++ = b; *out++ = g; *out++ = r; } } } void conv_rgb565_bgr24(void *output_, const void *input_, int width, int height, int out_stride, int in_stride) { int h; const uint16_t *input = (const uint16_t*)input_; uint8_t *output = (uint8_t*)output_; #if defined(__SSE2__) const __m128i pix_mask_r = _mm_set1_epi16(0x1f << 10); const __m128i pix_mask_g = _mm_set1_epi16(0x3f << 5); const __m128i pix_mask_b = _mm_set1_epi16(0x1f << 5); const __m128i mul16_r = _mm_set1_epi16(0x0210); const __m128i mul16_g = _mm_set1_epi16(0x2080); const __m128i mul16_b = _mm_set1_epi16(0x4200); const __m128i a = _mm_set1_epi16(0x00ff); int max_width = width - 15; #endif for (h = 0; h < height; h++, output += out_stride, input += in_stride >> 1) { uint8_t *out = output; int w = 0; #if defined(__SSE2__) for (; w < max_width; w += 16, out += 48) { __m128i res_lo_bg0, res_hi_bg0, res_lo_ra0, res_hi_ra0; __m128i res_lo_bg1, res_hi_bg1, res_lo_ra1, res_hi_ra1; __m128i res_lo0, res_hi0, res_lo1, res_hi1; const __m128i in0 = _mm_loadu_si128((const __m128i*)(input + w)); const __m128i in1 = _mm_loadu_si128((const __m128i*)(input + w + 8)); __m128i r0 = _mm_and_si128(_mm_srli_epi16(in0, 1), pix_mask_r); __m128i g0 = _mm_and_si128(in0, pix_mask_g); __m128i b0 = _mm_and_si128(_mm_slli_epi16(in0, 5), pix_mask_b); __m128i r1 = _mm_and_si128(_mm_srli_epi16(in1, 1), pix_mask_r); __m128i g1 = _mm_and_si128(in1, pix_mask_g); __m128i b1 = _mm_and_si128(_mm_slli_epi16(in1, 5), pix_mask_b); r0 = _mm_mulhi_epi16(r0, mul16_r); g0 = _mm_mulhi_epi16(g0, mul16_g); b0 = _mm_mulhi_epi16(b0, mul16_b); r1 = _mm_mulhi_epi16(r1, mul16_r); g1 = _mm_mulhi_epi16(g1, mul16_g); b1 = _mm_mulhi_epi16(b1, mul16_b); res_lo_bg0 = _mm_unpacklo_epi8(b0, g0); res_hi_bg0 = _mm_unpackhi_epi8(b0, g0); res_lo_ra0 = _mm_unpacklo_epi8(r0, a); res_hi_ra0 = _mm_unpackhi_epi8(r0, a); res_lo_bg1 = _mm_unpacklo_epi8(b1, g1); res_hi_bg1 = _mm_unpackhi_epi8(b1, g1); res_lo_ra1 = _mm_unpacklo_epi8(r1, a); res_hi_ra1 = _mm_unpackhi_epi8(r1, a); res_lo0 = _mm_or_si128(res_lo_bg0, _mm_slli_si128(res_lo_ra0, 2)); res_hi0 = _mm_or_si128(res_hi_bg0, _mm_slli_si128(res_hi_ra0, 2)); res_lo1 = _mm_or_si128(res_lo_bg1, _mm_slli_si128(res_lo_ra1, 2)); res_hi1 = _mm_or_si128(res_hi_bg1, _mm_slli_si128(res_hi_ra1, 2)); store_bgr24_sse2(out, res_lo0, res_hi0, res_lo1, res_hi1); } #endif for (; w < width; w++) { uint32_t col = input[w]; uint32_t r = (col >> 11) & 0x1f; uint32_t g = (col >> 5) & 0x3f; uint32_t b = (col >> 0) & 0x1f; r = (r << 3) | (r >> 2); g = (g << 2) | (g >> 4); b = (b << 3) | (b >> 2); *out++ = b; *out++ = g; *out++ = r; } } } void conv_bgr24_argb8888(void *output_, const void *input_, int width, int height, int out_stride, int in_stride) { int h, w; const uint8_t *input = (const uint8_t*)input_; uint32_t *output = (uint32_t*)output_; for (h = 0; h < height; h++, output += out_stride >> 2, input += in_stride) { const uint8_t *inp = input; for (w = 0; w < width; w++) { uint32_t b = *inp++; uint32_t g = *inp++; uint32_t r = *inp++; output[w] = (0xffu << 24) | (r << 16) | (g << 8) | (b << 0); } } } void conv_argb8888_0rgb1555(void *output_, const void *input_, int width, int height, int out_stride, int in_stride) { int h, w; const uint32_t *input = (const uint32_t*)input_; uint16_t *output = (uint16_t*)output_; for (h = 0; h < height; h++, output += out_stride >> 1, input += in_stride >> 2) { for (w = 0; w < width; w++) { uint32_t col = input[w]; uint16_t r = (col >> 19) & 0x1f; uint16_t g = (col >> 11) & 0x1f; uint16_t b = (col >> 3) & 0x1f; output[w] = (r << 10) | (g << 5) | (b << 0); } } } void conv_argb8888_bgr24(void *output_, const void *input_, int width, int height, int out_stride, int in_stride) { int h; const uint32_t *input = (const uint32_t*)input_; uint8_t *output = (uint8_t*)output_; #if defined(__SSE2__) int max_width = width - 15; #endif for (h = 0; h < height; h++, output += out_stride, input += in_stride >> 2) { uint8_t *out = output; int w = 0; #if defined(__SSE2__) for (; w < max_width; w += 16, out += 48) { store_bgr24_sse2(out, _mm_loadu_si128((const __m128i*)(input + w + 0)), _mm_loadu_si128((const __m128i*)(input + w + 4)), _mm_loadu_si128((const __m128i*)(input + w + 8)), _mm_loadu_si128((const __m128i*)(input + w + 12))); } #endif for (; w < width; w++) { uint32_t col = input[w]; *out++ = (uint8_t)(col >> 0); *out++ = (uint8_t)(col >> 8); *out++ = (uint8_t)(col >> 16); } } } void conv_argb8888_abgr8888(void *output_, const void *input_, int width, int height, int out_stride, int in_stride) { int h, w; const uint32_t *input = (const uint32_t*)input_; uint32_t *output = (uint32_t*)output_; for (h = 0; h < height; h++, output += out_stride >> 2, input += in_stride >> 2) { for (w = 0; w < width; w++) { uint32_t col = input[w]; output[w] = ((col << 16) & 0xff0000) | ((col >> 16) & 0xff) | (col & 0xff00ff00); } } } #define YUV_SHIFT 6 #define YUV_OFFSET (1 << (YUV_SHIFT - 1)) #define YUV_MAT_Y (1 << 6) #define YUV_MAT_U_G (-22) #define YUV_MAT_U_B (113) #define YUV_MAT_V_R (90) #define YUV_MAT_V_G (-46) void conv_yuyv_argb8888(void *output_, const void *input_, int width, int height, int out_stride, int in_stride) { int h; const uint8_t *input = (const uint8_t*)input_; uint32_t *output = (uint32_t*)output_; #if defined(__SSE2__) const __m128i mask_y = _mm_set1_epi16(0xffu); const __m128i mask_u = _mm_set1_epi32(0xffu << 8); const __m128i mask_v = _mm_set1_epi32(0xffu << 24); const __m128i chroma_offset = _mm_set1_epi16(128); const __m128i round_offset = _mm_set1_epi16(YUV_OFFSET); const __m128i yuv_mul = _mm_set1_epi16(YUV_MAT_Y); const __m128i u_g_mul = _mm_set1_epi16(YUV_MAT_U_G); const __m128i u_b_mul = _mm_set1_epi16(YUV_MAT_U_B); const __m128i v_r_mul = _mm_set1_epi16(YUV_MAT_V_R); const __m128i v_g_mul = _mm_set1_epi16(YUV_MAT_V_G); const __m128i a = _mm_cmpeq_epi16( _mm_setzero_si128(), _mm_setzero_si128()); #endif for (h = 0; h < height; h++, output += out_stride >> 2, input += in_stride) { const uint8_t *src = input; uint32_t *dst = output; int w = 0; #if defined(__SSE2__) /* Each loop processes 16 pixels. */ for (; w + 16 <= width; w += 16, src += 32, dst += 16) { __m128i u, v, u0_g, u1_g, u0_b, u1_b, v0_r, v1_r, v0_g, v1_g, r0, g0, b0, r1, g1, b1; __m128i res_lo_bg, res_hi_bg, res_lo_ra, res_hi_ra; __m128i res0, res1, res2, res3; __m128i yuv0 = _mm_loadu_si128((const __m128i*)(src + 0)); /* [Y0, U0, Y1, V0, Y2, U1, Y3, V1, ...] */ __m128i yuv1 = _mm_loadu_si128((const __m128i*)(src + 16)); /* [Y0, U0, Y1, V0, Y2, U1, Y3, V1, ...] */ __m128i _y0 = _mm_and_si128(yuv0, mask_y); /* [Y0, Y1, Y2, ...] (16-bit) */ __m128i u0 = _mm_and_si128(yuv0, mask_u); /* [0, U0, 0, 0, 0, U1, 0, 0, ...] */ __m128i v0 = _mm_and_si128(yuv0, mask_v); /* [0, 0, 0, V1, 0, , 0, V1, ...] */ __m128i _y1 = _mm_and_si128(yuv1, mask_y); /* [Y0, Y1, Y2, ...] (16-bit) */ __m128i u1 = _mm_and_si128(yuv1, mask_u); /* [0, U0, 0, 0, 0, U1, 0, 0, ...] */ __m128i v1 = _mm_and_si128(yuv1, mask_v); /* [0, 0, 0, V1, 0, , 0, V1, ...] */ /* Juggle around to get U and V in the same 16-bit format as Y. */ u0 = _mm_srli_si128(u0, 1); v0 = _mm_srli_si128(v0, 3); u1 = _mm_srli_si128(u1, 1); v1 = _mm_srli_si128(v1, 3); u = _mm_packs_epi32(u0, u1); v = _mm_packs_epi32(v0, v1); /* Apply YUV offsets (U, V) -= (-128, -128). */ u = _mm_sub_epi16(u, chroma_offset); v = _mm_sub_epi16(v, chroma_offset); /* Upscale chroma horizontally (nearest). */ u0 = _mm_unpacklo_epi16(u, u); u1 = _mm_unpackhi_epi16(u, u); v0 = _mm_unpacklo_epi16(v, v); v1 = _mm_unpackhi_epi16(v, v); /* Apply transformations. */ _y0 = _mm_mullo_epi16(_y0, yuv_mul); _y1 = _mm_mullo_epi16(_y1, yuv_mul); u0_g = _mm_mullo_epi16(u0, u_g_mul); u1_g = _mm_mullo_epi16(u1, u_g_mul); u0_b = _mm_mullo_epi16(u0, u_b_mul); u1_b = _mm_mullo_epi16(u1, u_b_mul); v0_r = _mm_mullo_epi16(v0, v_r_mul); v1_r = _mm_mullo_epi16(v1, v_r_mul); v0_g = _mm_mullo_epi16(v0, v_g_mul); v1_g = _mm_mullo_epi16(v1, v_g_mul); /* Add contibutions from the transformed components. */ r0 = _mm_srai_epi16(_mm_adds_epi16(_mm_adds_epi16(_y0, v0_r), round_offset), YUV_SHIFT); g0 = _mm_srai_epi16(_mm_adds_epi16( _mm_adds_epi16(_mm_adds_epi16(_y0, v0_g), u0_g), round_offset), YUV_SHIFT); b0 = _mm_srai_epi16(_mm_adds_epi16( _mm_adds_epi16(_y0, u0_b), round_offset), YUV_SHIFT); r1 = _mm_srai_epi16(_mm_adds_epi16( _mm_adds_epi16(_y1, v1_r), round_offset), YUV_SHIFT); g1 = _mm_srai_epi16(_mm_adds_epi16( _mm_adds_epi16(_mm_adds_epi16(_y1, v1_g), u1_g), round_offset), YUV_SHIFT); b1 = _mm_srai_epi16(_mm_adds_epi16( _mm_adds_epi16(_y1, u1_b), round_offset), YUV_SHIFT); /* Saturate into 8-bit. */ r0 = _mm_packus_epi16(r0, r1); g0 = _mm_packus_epi16(g0, g1); b0 = _mm_packus_epi16(b0, b1); /* Interleave into ARGB. */ res_lo_bg = _mm_unpacklo_epi8(b0, g0); res_hi_bg = _mm_unpackhi_epi8(b0, g0); res_lo_ra = _mm_unpacklo_epi8(r0, a); res_hi_ra = _mm_unpackhi_epi8(r0, a); res0 = _mm_unpacklo_epi16(res_lo_bg, res_lo_ra); res1 = _mm_unpackhi_epi16(res_lo_bg, res_lo_ra); res2 = _mm_unpacklo_epi16(res_hi_bg, res_hi_ra); res3 = _mm_unpackhi_epi16(res_hi_bg, res_hi_ra); _mm_storeu_si128((__m128i*)(dst + 0), res0); _mm_storeu_si128((__m128i*)(dst + 4), res1); _mm_storeu_si128((__m128i*)(dst + 8), res2); _mm_storeu_si128((__m128i*)(dst + 12), res3); } #endif /* Finish off the rest (if any) in C. */ for (; w < width; w += 2, src += 4, dst += 2) { int _y0 = src[0]; int u = src[1] - 128; int _y1 = src[2]; int v = src[3] - 128; uint8_t r0 = clamp_8bit((YUV_MAT_Y * _y0 + YUV_MAT_V_R * v + YUV_OFFSET) >> YUV_SHIFT); uint8_t g0 = clamp_8bit((YUV_MAT_Y * _y0 + YUV_MAT_U_G * u + YUV_MAT_V_G * v + YUV_OFFSET) >> YUV_SHIFT); uint8_t b0 = clamp_8bit((YUV_MAT_Y * _y0 + YUV_MAT_U_B * u + YUV_OFFSET) >> YUV_SHIFT); uint8_t r1 = clamp_8bit((YUV_MAT_Y * _y1 + YUV_MAT_V_R * v + YUV_OFFSET) >> YUV_SHIFT); uint8_t g1 = clamp_8bit((YUV_MAT_Y * _y1 + YUV_MAT_U_G * u + YUV_MAT_V_G * v + YUV_OFFSET) >> YUV_SHIFT); uint8_t b1 = clamp_8bit((YUV_MAT_Y * _y1 + YUV_MAT_U_B * u + YUV_OFFSET) >> YUV_SHIFT); dst[0] = 0xff000000u | (r0 << 16) | (g0 << 8) | (b0 << 0); dst[1] = 0xff000000u | (r1 << 16) | (g1 << 8) | (b1 << 0); } } } void conv_copy(void *output_, const void *input_, int width, int height, int out_stride, int in_stride) { int h; int copy_len = abs(out_stride); const uint8_t *input = (const uint8_t*)input_; uint8_t *output = (uint8_t*)output_; if (abs(in_stride) < copy_len) copy_len = abs(in_stride); for (h = 0; h < height; h++, output += out_stride, input += in_stride) memcpy(output, input, copy_len); } desmume/src/libretro-common/include/compat/strl.h000664 001750 001750 00000004020 12755534123 023306 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2016 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (strl.h). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef __LIBRETRO_SDK_COMPAT_STRL_H #define __LIBRETRO_SDK_COMPAT_STRL_H #include #include #ifdef HAVE_CONFIG_H #include "../../../config.h" #endif #include RETRO_BEGIN_DECLS #ifdef __MACH__ #ifndef HAVE_STRL #define HAVE_STRL #endif #endif #ifndef HAVE_STRL /* Avoid possible naming collisions during link since * we prefer to use the actual name. */ #define strlcpy(dst, src, size) strlcpy_retro__(dst, src, size) #define strlcat(dst, src, size) strlcat_retro__(dst, src, size) size_t strlcpy(char *dest, const char *source, size_t size); size_t strlcat(char *dest, const char *source, size_t size); #endif RETRO_END_DECLS #endif desmume/src/utils/advanscene.h000664 001750 001750 00000003655 12755534123 017570 0ustar00sergiosergio000000 000000 /* Copyright (C) 2011-2015 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the this software. If not, see . */ #include #include #include "../types.h" class EMUFILE; class ADVANsCEne { private: std::string database_path; time_t createTime; u32 crc32; char serial[6]; char version[4]; u8 versionBase[2]; u8 saveType; bool loaded; bool foundAsCrc, foundAsSerial; // XML std::string datName; std::string datVersion; std::string urlVersion; std::string urlDat; bool getXMLConfig(const char *in_filename); public: ADVANsCEne() : saveType(0xFF), crc32(0), loaded(false) { memset(versionBase, 0, sizeof(versionBase)); memset(version, 0, sizeof(version)); memset(serial, 0, sizeof(serial)); } void setDatabase(const char *path); std::string getDatabase() const { return database_path; } u32 convertDB(const char *in_filename, EMUFILE* output); u8 checkDB(const char *ROMserial, u32 crc); u32 getSaveType() { return saveType; } u32 getCRC32() { return crc32; } char *getSerial() { return serial; } bool isLoaded() { return loaded; } const char* getIdMethod() { if(foundAsSerial && foundAsCrc) return "Serial/CRC"; if(foundAsSerial) return "Serial"; if(foundAsCrc) return "CRC"; return ""; } std::string lastImportErrorMessage; }; extern ADVANsCEne advsc; desmume/src/utils/dlditool.c000664 001750 001750 00000133077 12755534123 017270 0ustar00sergiosergio000000 000000 /* dlditool - Dynamically Linked Disk Interface patch tool Copyright (C) 2006 Michael Chisholm (Chishm) Send all queries to chishm@hotmail.com This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * v1.24d - 2010-06-14 - zeromus * Modified for inclusion in desmume * v1.24 - 2007-08-02 - SmileyDude * Now using EXIT_SUCCESS and EXIT_FAILURE at the suggestion of MachinShin. * Defined EXIT_NO_DLDI_SECTION for when there is no DLDI section in a file. * Added cast to strcmp() call to appease the compiler. * v1.23 - 2007-01-23 - Chishm * Fixed bug when DLDI section doesn't exist * addr_t is now a signed int * v1.22 - 2007-01-12 - WinterMute * add search paths for dldi files * v1.21 - 2007-01-12 - Chishm * Improved error messages * v1.20 - 2007-01-11 - Chishm * Changed offset calculation method * v1.10 - 2007-01-07 - Chishm * Removed assumptions about endianess of computer * Word size shouldn't matter now either, except that an int type must be at least 32 bits long * Added *.sc.nds and *.gba.nds file extensions * Improved command line argument parsing * v1.01 - 2006-12-30 - Chishm * Minor bugfix parsing 3 arguments * v1.00 - 2006-12-25 - Chishm * Original release */ #define VERSION "v1.24" #include #include #include #include #include #include #include #ifndef _MSC_VER #include #include #include #else typedef int int32_t; #define MAXPATHLEN 1024 #endif #include typedef int32_t addr_t; typedef unsigned char data_t; #define FEATURE_MEDIUM_CANREAD 0x00000001 #define FEATURE_MEDIUM_CANWRITE 0x00000002 #define FEATURE_SLOT_GBA 0x00000010 #define FEATURE_SLOT_NDS 0x00000020 #define MAGIC_TOKEN 0xBF8DA5ED #define FIX_ALL 0x01 #define FIX_GLUE 0x02 #define FIX_GOT 0x04 #define FIX_BSS 0x08 #define DLDI_VERSION 1 #define EXIT_NO_DLDI_SECTION 2 enum DldiOffsets { DO_magicString = 0x00, // "\xED\xA5\x8D\xBF Chishm" DO_magicToken = 0x00, // 0xBF8DA5ED DO_magicShortString = 0x04, // " Chishm" DO_version = 0x0C, DO_driverSize = 0x0D, DO_fixSections = 0x0E, DO_allocatedSpace = 0x0F, DO_friendlyName = 0x10, DO_text_start = 0x40, // Data start DO_data_end = 0x44, // Data end DO_glue_start = 0x48, // Interworking glue start -- Needs address fixing DO_glue_end = 0x4C, // Interworking glue end DO_got_start = 0x50, // GOT start -- Needs address fixing DO_got_end = 0x54, // GOT end DO_bss_start = 0x58, // bss start -- Needs setting to zero DO_bss_end = 0x5C, // bss end // IO_INTERFACE data DO_ioType = 0x60, DO_features = 0x64, DO_startup = 0x68, DO_isInserted = 0x6C, DO_readSectors = 0x70, DO_writeSectors = 0x74, DO_clearStatus = 0x78, DO_shutdown = 0x7C, DO_code = 0x80 }; const data_t dldiMagicString[] = "\xED\xA5\x8D\xBF Chishm"; const char dldiFileExtension[] = ".dldi"; void printUsage (char* programName) { printf ("Usage:\n"); printf ("%s \n", programName); printf (" the dldi patch file to apply\n"); printf (" the application binary to apply the patch to\n"); return; } addr_t readAddr (data_t *mem, addr_t offset) { return (addr_t)( (mem[offset + 0] << 0) | (mem[offset + 1] << 8) | (mem[offset + 2] << 16) | (mem[offset + 3] << 24) ); } void writeAddr (data_t *mem, addr_t offset, addr_t value) { mem[offset + 0] = (data_t)(value >> 0); mem[offset + 1] = (data_t)(value >> 8); mem[offset + 2] = (data_t)(value >> 16); mem[offset + 3] = (data_t)(value >> 24); } int stringCaseInsensitiveCompare (const char *str1, const char *str2) { while (tolower(*str1) == tolower(*str2)) { if (*str1 == '\0') { return 0; } str1++; str2++; } return (tolower(*str1) - tolower(*str2)); } bool stringEndsWith (const char *str, const char *end) { const char* strEnd; if (strlen (str) < strlen(end)) { return false; } strEnd = &str[strlen (str) - strlen(end)]; return (stringCaseInsensitiveCompare (strEnd, end) == 0); } bool stringStartsWith (const char *str, const char *start) { return (strstr (str, start) == str); } addr_t quickFind (const data_t* data, const data_t* search, size_t dataLen, size_t searchLen) { const int32_t* dataChunk = (const int32_t*) data; int searchChunk = ((const int32_t*)search)[0]; addr_t i; addr_t dataChunkEnd = (addr_t)(dataLen / sizeof(int32_t)); for ( i = 0; i < dataChunkEnd; i++) { if (dataChunk[i] == searchChunk) { if ((i*sizeof(int32_t) + searchLen) > dataLen) { return -1; } if (memcmp (&data[i*sizeof(int32_t)], search, searchLen) == 0) { return i*sizeof(int32_t); } } } return -1; } FILE *openDLDIFile(const char *argv0, char *dldiFileName ) { FILE *dldiFile; char *dldiPATH; char appPath[MAXPATHLEN]; char appName[MAXPATHLEN]; char appPathName[MAXPATHLEN]; char *ptr, *lastSlash; struct stat buf; // add .dldi extension to filename if (!stringEndsWith (dldiFileName, dldiFileExtension)) { strcat (dldiFileName, dldiFileExtension); } printf ("Trying \"%s\"\n", dldiFileName); // try opening from current directory dldiFile = fopen(dldiFileName,"rb"); if ( NULL != dldiFile ) return dldiFile; // check if the filename has a path component // check both slash varieties, win32 understands both // if we have a directory separator don't bother with search paths if ( NULL != strstr(dldiFileName,"\\") ) return NULL; if ( NULL != strstr(dldiFileName,"/") ) return NULL; // check for DLDIPATH in environment dldiPATH = getenv("DLDIPATH"); if ( NULL != dldiPATH ) { strcpy(appPath,dldiPATH); if ( appPath[strlen(appPath)] != '\\' && appPath[strlen(appPath)] != '/' ) strcat(appPath,"/"); strcat ( appPath, dldiFileName ); printf ("Trying \"%s\"\n", appPath); dldiFile = fopen(appPath,"rb"); if ( NULL != dldiFile ) return dldiFile; } lastSlash = NULL; ptr = (char *)argv0; while ( *(ptr++) != 0 ) { if ( *ptr == '\\' || * ptr == '/' ) lastSlash = ptr; } if ( NULL != lastSlash ) { *(lastSlash++) = '\0'; strcpy(appPath, argv0); strcpy(appName, lastSlash); strcat(appPath, "/"); } else { strcpy(appPath, ""); strcpy(appName, argv0); } // finally try in the application path // if argv0 contains a directory separator we have a path component if ( NULL == strstr(appPath,"\\") && NULL == strstr(appPath,"/") ) { // no path in argv0 so search system path char *sysPATH = getenv("PATH"); char *nextPATH; char *thisPATH = sysPATH; printf("Searching system path\n%s\n",sysPATH); while(1) { nextPATH = strstr(thisPATH, ":" ); // find next PATH separator if ( NULL != nextPATH ) *(nextPATH++) = '\0'; // terminate string, point to next component strcpy(appPath,thisPATH); strcat(appPath,"/"); strcpy(appPathName,appPath); strcat(appPathName,appName); // add application name if ( stat(appPathName,&buf) == 0 ) // if it exists we found the path break; thisPATH = nextPATH; strcpy(appPath,""); // empty path if ( thisPATH == NULL) break; } } strcat(appPath,"dldi/"); // add dldi folder strcat(appPath,dldiFileName); // add dldi filename to path printf ("Trying \"%s\"\n", appPath); return fopen(appPath,"rb"); // no more places to check, just return this handle } //int main(int argc, char* argv[]) //{ // // char *dldiFileName = NULL; // char *appFileName = NULL; // // addr_t memOffset; // Offset of DLDI after the file is loaded into memory // addr_t patchOffset; // Position of patch destination in the file // addr_t relocationOffset; // Value added to all offsets within the patch to fix it properly // addr_t ddmemOffset; // Original offset used in the DLDI file // addr_t ddmemStart; // Start of range that offsets can be in the DLDI file // addr_t ddmemEnd; // End of range that offsets can be in the DLDI file // addr_t ddmemSize; // Size of range that offsets can be in the DLDI file // // addr_t addrIter; // // FILE* dldiFile; // FILE* appFile; // // data_t *pDH; // data_t *pAH; // // data_t *appFileData = NULL; // size_t appFileSize = 0; // data_t *dldiFileData = NULL; // size_t dldiFileSize = 0; // // int i; // // printf ("Dynamically Linked Disk Interface patch tool " VERSION " by Michael Chisholm (Chishm)\n\n"); // // for (i = 1; i < argc; i++) { // if (dldiFileName == NULL) { // dldiFileName = (char*) malloc (strlen (argv[i]) + 1 + sizeof(dldiFileExtension)); // if (!dldiFileName) { // return EXIT_FAILURE; // } // strcpy (dldiFileName, argv[i]); // } else if (appFileName == NULL) { // appFileName = (char*) malloc (strlen (argv[i]) + 1); // if (!appFileName) { // return EXIT_FAILURE; // } // strcpy (appFileName, argv[i]); // } else { // printUsage (argv[0]); // return EXIT_FAILURE; // } // } // // if ((dldiFileName == NULL) || (appFileName == NULL)) { // printUsage (argv[0]); // return EXIT_FAILURE; // } // // if (!(dldiFile = openDLDIFile(argv[0],dldiFileName))) { // printf ("Cannot open \"%s\" - %s\n", dldiFileName, strerror(errno)); // return EXIT_FAILURE; // } // // if (!(appFile = fopen (appFileName, "rb+"))) { // printf ("Cannot open \"%s\" - %s\n", appFileName, strerror(errno)); // return EXIT_FAILURE; // } // // // Load the app file and the DLDI patch file // fseek (appFile, 0, SEEK_END); // appFileSize = ftell(appFile); // appFileData = (data_t*) malloc (appFileSize); // fseek (appFile, 0, SEEK_SET); // // fseek (dldiFile, 0, SEEK_END); // dldiFileSize = ftell(dldiFile); // dldiFileData = (data_t*) malloc (dldiFileSize); // fseek (dldiFile, 0, SEEK_SET); // // if (!appFileData || !dldiFileData) { // fclose (appFile); // fclose (dldiFile); // if (appFileData) free (appFileData); // if (dldiFileData) free (dldiFileData); // printf ("Out of memory\n"); // return EXIT_FAILURE; // } // // fread (appFileData, 1, appFileSize, appFile); // fread (dldiFileData, 1, dldiFileSize, dldiFile); // fclose (dldiFile); // // // Find the DSDI reserved space in the file // patchOffset = quickFind (appFileData, dldiMagicString, appFileSize, sizeof(dldiMagicString)/sizeof(char)); // // if (patchOffset < 0) { // printf ("%s does not have a DLDI section\n", appFileName); // return EXIT_NO_DLDI_SECTION; // } // // pDH = dldiFileData; // pAH = &appFileData[patchOffset]; // // // Make sure the DLDI file is valid and usable // if (strcmp ((char*)dldiMagicString, (char*)&pDH[DO_magicString]) != 0) { // printf ("Invalid DLDI file\n"); // return EXIT_FAILURE; // } // if (pDH[DO_version] != DLDI_VERSION) { // printf ("Incorrect DLDI file version. Expected %d, found %d.\n", DLDI_VERSION, pDH[DO_version]); // return EXIT_FAILURE; // } // if (pDH[DO_driverSize] > pAH[DO_allocatedSpace]) { // printf ("Not enough space for patch. Available %d bytes, need %d bytes\n", ( 1 << pAH[DO_allocatedSpace]), ( 1 << pDH[DO_driverSize]) ); // return EXIT_FAILURE; // } // // memOffset = readAddr (pAH, DO_text_start); // if (memOffset == 0) { // memOffset = readAddr (pAH, DO_startup) - DO_code; // } // ddmemOffset = readAddr (pDH, DO_text_start); // relocationOffset = memOffset - ddmemOffset; // // printf ("Old driver: %s\n", &pAH[DO_friendlyName]); // printf ("New driver: %s\n", &pDH[DO_friendlyName]); // printf ("\n"); // printf ("Position in file: 0x%08X\n", patchOffset); // printf ("Position in memory: 0x%08X\n", memOffset); // printf ("Patch base address: 0x%08X\n", ddmemOffset); // printf ("Relocation offset: 0x%08X\n", relocationOffset); // printf ("\n"); // // ddmemStart = readAddr (pDH, DO_text_start); // ddmemSize = (1 << pDH[DO_driverSize]); // ddmemEnd = ddmemStart + ddmemSize; // // // Remember how much space is actually reserved // pDH[DO_allocatedSpace] = pAH[DO_allocatedSpace]; // // Copy the DLDI patch into the application // memcpy (pAH, pDH, dldiFileSize); // // // Fix the section pointers in the header // writeAddr (pAH, DO_text_start, readAddr (pAH, DO_text_start) + relocationOffset); // writeAddr (pAH, DO_data_end, readAddr (pAH, DO_data_end) + relocationOffset); // writeAddr (pAH, DO_glue_start, readAddr (pAH, DO_glue_start) + relocationOffset); // writeAddr (pAH, DO_glue_end, readAddr (pAH, DO_glue_end) + relocationOffset); // writeAddr (pAH, DO_got_start, readAddr (pAH, DO_got_start) + relocationOffset); // writeAddr (pAH, DO_got_end, readAddr (pAH, DO_got_end) + relocationOffset); // writeAddr (pAH, DO_bss_start, readAddr (pAH, DO_bss_start) + relocationOffset); // writeAddr (pAH, DO_bss_end, readAddr (pAH, DO_bss_end) + relocationOffset); // // Fix the function pointers in the header // writeAddr (pAH, DO_startup, readAddr (pAH, DO_startup) + relocationOffset); // writeAddr (pAH, DO_isInserted, readAddr (pAH, DO_isInserted) + relocationOffset); // writeAddr (pAH, DO_readSectors, readAddr (pAH, DO_readSectors) + relocationOffset); // writeAddr (pAH, DO_writeSectors, readAddr (pAH, DO_writeSectors) + relocationOffset); // writeAddr (pAH, DO_clearStatus, readAddr (pAH, DO_clearStatus) + relocationOffset); // writeAddr (pAH, DO_shutdown, readAddr (pAH, DO_shutdown) + relocationOffset); // // if (pDH[DO_fixSections] & FIX_ALL) { // // Search through and fix pointers within the data section of the file // for (addrIter = (readAddr(pDH, DO_text_start) - ddmemStart); addrIter < (readAddr(pDH, DO_data_end) - ddmemStart); addrIter++) { // if ((ddmemStart <= readAddr(pAH, addrIter)) && (readAddr(pAH, addrIter) < ddmemEnd)) { // writeAddr (pAH, addrIter, readAddr(pAH, addrIter) + relocationOffset); // } // } // } // // if (pDH[DO_fixSections] & FIX_GLUE) { // // Search through and fix pointers within the glue section of the file // for (addrIter = (readAddr(pDH, DO_glue_start) - ddmemStart); addrIter < (readAddr(pDH, DO_glue_end) - ddmemStart); addrIter++) { // if ((ddmemStart <= readAddr(pAH, addrIter)) && (readAddr(pAH, addrIter) < ddmemEnd)) { // writeAddr (pAH, addrIter, readAddr(pAH, addrIter) + relocationOffset); // } // } // } // // if (pDH[DO_fixSections] & FIX_GOT) { // // Search through and fix pointers within the Global Offset Table section of the file // for (addrIter = (readAddr(pDH, DO_got_start) - ddmemStart); addrIter < (readAddr(pDH, DO_got_end) - ddmemStart); addrIter++) { // if ((ddmemStart <= readAddr(pAH, addrIter)) && (readAddr(pAH, addrIter) < ddmemEnd)) { // writeAddr (pAH, addrIter, readAddr(pAH, addrIter) + relocationOffset); // } // } // } // // if (pDH[DO_fixSections] & FIX_BSS) { // // Initialise the BSS to 0 // memset (&pAH[readAddr(pDH, DO_bss_start) - ddmemStart] , 0, readAddr(pDH, DO_bss_end) - readAddr(pDH, DO_bss_start)); // } // // // Write the patch back to the file // fseek (appFile, patchOffset, SEEK_SET); // fwrite (pAH, 1, ddmemSize, appFile); // fclose (appFile); // // free (appFileData); // free (dldiFileData); // // printf ("Patched successfully\n"); // // return EXIT_SUCCESS; //} // Source File: mpcf.dldi // Time: 6/14/2010 9:38 PM // Orig. Offset: 0 / 0x00000000 // Length: 1876 / 0x00000754 (bytes) data_t mpcf_dldi[1876] = { 0xED, 0xA5, 0x8D, 0xBF, 0x20, 0x43, 0x68, 0x69, 0x73, 0x68, 0x6D, 0x00, 0x01, 0x0B, 0x0C, 0x00, 0x47, 0x42, 0x41, 0x20, 0x4D, 0x6F, 0x76, 0x69, 0x65, 0x20, 0x50, 0x6C, 0x61, 0x79, 0x65, 0x72, 0x20, 0x28, 0x43, 0x6F, 0x6D, 0x70, 0x61, 0x63, 0x74, 0x20, 0x46, 0x6C, 0x61, 0x73, 0x68, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xBF, 0x54, 0x07, 0x80, 0xBF, 0x98, 0x00, 0x80, 0xBF, 0x98, 0x00, 0x80, 0xBF, 0x50, 0x07, 0x80, 0xBF, 0x50, 0x07, 0x80, 0xBF, 0x54, 0x07, 0x80, 0xBF, 0x70, 0x07, 0x80, 0xBF, 0x4D, 0x50, 0x43, 0x46, 0x13, 0x00, 0x00, 0x00, 0x3C, 0x01, 0x80, 0xBF, 0x98, 0x01, 0x80, 0xBF, 0x78, 0x02, 0x80, 0xBF, 0xC8, 0x04, 0x80, 0xBF, 0xC8, 0x01, 0x80, 0xBF, 0x10, 0x07, 0x80, 0xBF, 0x0D, 0xC0, 0xA0, 0xE1, 0xF8, 0xDF, 0x2D, 0xE9, 0x04, 0xB0, 0x4C, 0xE2, 0x28, 0xD0, 0x4B, 0xE2, 0xF0, 0x6F, 0x9D, 0xE8, 0x1E, 0xFF, 0x2F, 0xE1, 0x10, 0x40, 0x2D, 0xE9, 0x2C, 0x40, 0x9F, 0xE5, 0x00, 0x30, 0xD4, 0xE5, 0x00, 0x00, 0x53, 0xE3, 0x24, 0x20, 0x9F, 0xE5, 0x05, 0x00, 0x00, 0x1A, 0x00, 0x00, 0x52, 0xE3, 0x1C, 0x00, 0x9F, 0xE5, 0x0F, 0xE0, 0xA0, 0x11, 0x12, 0xFF, 0x2F, 0x11, 0x01, 0x30, 0xA0, 0xE3, 0x00, 0x30, 0xC4, 0xE5, 0x10, 0x40, 0xBD, 0xE8, 0x1E, 0xFF, 0x2F, 0xE1, 0x54, 0x07, 0x80, 0xBF, 0x00, 0x00, 0x00, 0x00, 0x48, 0x07, 0x80, 0xBF, 0x04, 0xE0, 0x2D, 0xE5, 0x40, 0x30, 0x9F, 0xE5, 0x00, 0x00, 0x53, 0xE3, 0x04, 0xD0, 0x4D, 0xE2, 0x38, 0x00, 0x9F, 0xE5, 0x38, 0x10, 0x9F, 0xE5, 0x0F, 0xE0, 0xA0, 0x11, 0x13, 0xFF, 0x2F, 0x11, 0x30, 0x00, 0x9F, 0xE5, 0x00, 0x30, 0x90, 0xE5, 0x00, 0x00, 0x53, 0xE3, 0x28, 0x30, 0x9F, 0xE5, 0x02, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x53, 0xE3, 0x0F, 0xE0, 0xA0, 0x11, 0x13, 0xFF, 0x2F, 0x11, 0x04, 0xD0, 0x8D, 0xE2, 0x04, 0xE0, 0x9D, 0xE4, 0x1E, 0xFF, 0x2F, 0xE1, 0x00, 0x00, 0x00, 0x00, 0x48, 0x07, 0x80, 0xBF, 0x58, 0x07, 0x80, 0xBF, 0x4C, 0x07, 0x80, 0xBF, 0x00, 0x00, 0x00, 0x00, 0x09, 0x14, 0xA0, 0xE3, 0x06, 0x18, 0x81, 0xE2, 0xB0, 0x30, 0xD1, 0xE1, 0x03, 0x30, 0xE0, 0xE1, 0x03, 0x38, 0xA0, 0xE1, 0x23, 0x38, 0xA0, 0xE1, 0xFF, 0x30, 0x03, 0xE2, 0xB0, 0x30, 0xC1, 0xE1, 0xB0, 0x20, 0xD1, 0xE1, 0x04, 0xE0, 0x2D, 0xE5, 0xAA, 0xCC, 0xA0, 0xE3, 0x55, 0xEC, 0xE0, 0xE3, 0x03, 0x00, 0x52, 0xE1, 0xAA, 0xE0, 0x4E, 0xE2, 0x55, 0xC0, 0x8C, 0xE2, 0x00, 0x00, 0xA0, 0xE3, 0x03, 0x00, 0x00, 0x1A, 0xB0, 0xE0, 0xC1, 0xE1, 0xB0, 0x30, 0xD1, 0xE1, 0x0C, 0x00, 0x53, 0xE0, 0x01, 0x00, 0xA0, 0x13, 0x04, 0xE0, 0x9D, 0xE4, 0x1E, 0xFF, 0x2F, 0xE1, 0x26, 0x35, 0xA0, 0xE3, 0x03, 0x37, 0x83, 0xE2, 0x50, 0x20, 0xA0, 0xE3, 0xB0, 0x20, 0xC3, 0xE1, 0xB0, 0x00, 0xD3, 0xE1, 0x00, 0x08, 0xA0, 0xE1, 0x20, 0x08, 0xA0, 0xE1, 0xFF, 0x00, 0x00, 0xE2, 0x50, 0x00, 0x50, 0xE3, 0x00, 0x00, 0xA0, 0x13, 0x01, 0x00, 0xA0, 0x03, 0x1E, 0xFF, 0x2F, 0xE1, 0x09, 0x34, 0xA0, 0xE3, 0x0E, 0x38, 0x83, 0xE2, 0xB0, 0x20, 0xD3, 0xE1, 0x80, 0x00, 0x12, 0xE3, 0x0C, 0x00, 0x00, 0x0A, 0x00, 0x00, 0xA0, 0xE3, 0x01, 0x00, 0x00, 0xEA, 0x01, 0x00, 0x50, 0xE1, 0x08, 0x00, 0x00, 0x0A, 0x09, 0x34, 0xA0, 0xE3, 0x0E, 0x38, 0x83, 0xE2, 0xB0, 0x20, 0xD3, 0xE1, 0x26, 0x17, 0xA0, 0xE3, 0x96, 0x1C, 0x81, 0xE2, 0x80, 0x00, 0x12, 0xE3, 0x01, 0x00, 0x80, 0xE2, 0x80, 0x10, 0x81, 0xE2, 0xF4, 0xFF, 0xFF, 0x1A, 0x26, 0x15, 0xA0, 0xE3, 0x03, 0x17, 0x81, 0xE2, 0xB0, 0x30, 0xD1, 0xE1, 0x50, 0x30, 0x13, 0xE2, 0x01, 0x00, 0xA0, 0x13, 0x1E, 0xFF, 0x2F, 0x11, 0x26, 0x27, 0xA0, 0xE3, 0x96, 0x2C, 0x82, 0xE2, 0x03, 0x00, 0xA0, 0xE1, 0x80, 0x20, 0x82, 0xE2, 0x01, 0x00, 0x00, 0xEA, 0x02, 0x00, 0x50, 0xE1, 0x0A, 0x00, 0x00, 0x0A, 0xB0, 0x30, 0xD1, 0xE1, 0x50, 0x30, 0x13, 0xE2, 0x01, 0x00, 0x80, 0xE2, 0xF9, 0xFF, 0xFF, 0x0A, 0x26, 0x37, 0xA0, 0xE3, 0x96, 0x3C, 0x83, 0xE2, 0x7F, 0x30, 0x83, 0xE2, 0x03, 0x00, 0x50, 0xE1, 0x00, 0x00, 0xA0, 0xC3, 0x01, 0x00, 0xA0, 0xD3, 0x1E, 0xFF, 0x2F, 0xE1, 0x03, 0x00, 0xA0, 0xE1, 0x1E, 0xFF, 0x2F, 0xE1, 0xF0, 0x4B, 0x2D, 0xE9, 0x09, 0x34, 0xA0, 0xE3, 0x0E, 0x38, 0x83, 0xE2, 0xB0, 0xC0, 0xD3, 0xE1, 0x80, 0x00, 0x1C, 0xE3, 0x10, 0xD0, 0x4D, 0xE2, 0x01, 0x90, 0xA0, 0xE1, 0x02, 0xE0, 0xA0, 0xE1, 0x0C, 0x00, 0x00, 0x0A, 0x00, 0xC0, 0xA0, 0xE3, 0x01, 0x00, 0x00, 0xEA, 0x01, 0x00, 0x5C, 0xE1, 0x08, 0x00, 0x00, 0x0A, 0x09, 0x34, 0xA0, 0xE3, 0x0E, 0x38, 0x83, 0xE2, 0xB0, 0x20, 0xD3, 0xE1, 0x26, 0x17, 0xA0, 0xE3, 0x96, 0x1C, 0x81, 0xE2, 0x80, 0x00, 0x12, 0xE3, 0x01, 0xC0, 0x8C, 0xE2, 0x80, 0x10, 0x81, 0xE2, 0xF4, 0xFF, 0xFF, 0x1A, 0x26, 0xC5, 0xA0, 0xE3, 0x03, 0xC7, 0x8C, 0xE2, 0xB0, 0x30, 0xDC, 0xE1, 0x50, 0x30, 0x13, 0xE2, 0x26, 0x17, 0xA0, 0x03, 0x96, 0x1C, 0x81, 0x02, 0x03, 0x20, 0xA0, 0x01, 0x80, 0x10, 0x81, 0x02, 0x02, 0x00, 0x00, 0x0A, 0x0A, 0x00, 0x00, 0xEA, 0x01, 0x00, 0x52, 0xE1, 0x67, 0x00, 0x00, 0x0A, 0xB0, 0x30, 0xDC, 0xE1, 0x50, 0x00, 0x13, 0xE3, 0x01, 0x20, 0x82, 0xE2, 0xF9, 0xFF, 0xFF, 0x0A, 0x26, 0x37, 0xA0, 0xE3, 0x96, 0x3C, 0x83, 0xE2, 0x7F, 0x30, 0x83, 0xE2, 0x03, 0x00, 0x52, 0xE1, 0x5E, 0x00, 0x00, 0xCA, 0xFF, 0x00, 0x59, 0xE3, 0x00, 0x30, 0xA0, 0x83, 0x0C, 0x30, 0x8D, 0x85, 0x5E, 0x00, 0x00, 0x9A, 0x00, 0x38, 0xA0, 0xE1, 0x23, 0x38, 0xA0, 0xE1, 0xFF, 0x30, 0x03, 0xE2, 0x09, 0x54, 0xA0, 0xE3, 0x04, 0x30, 0x8D, 0xE5, 0x0C, 0x30, 0x9D, 0xE5, 0x20, 0x4C, 0xA0, 0xE1, 0x0E, 0xB0, 0xA0, 0xE1, 0x05, 0x60, 0xA0, 0xE1, 0x20, 0x74, 0xA0, 0xE1, 0x05, 0x20, 0xA0, 0xE1, 0x20, 0x18, 0xA0, 0xE1, 0x05, 0xC0, 0xA0, 0xE1, 0x05, 0x00, 0xA0, 0xE1, 0x05, 0xE0, 0xA0, 0xE1, 0x01, 0x57, 0x85, 0xE2, 0xB0, 0x30, 0xC5, 0xE1, 0x04, 0x30, 0x9D, 0xE5, 0x0F, 0x40, 0x04, 0xE2, 0x06, 0x68, 0x86, 0xE2, 0xB0, 0x30, 0xC6, 0xE1, 0xFF, 0x70, 0x07, 0xE2, 0x02, 0x27, 0x82, 0xE2, 0xFF, 0x10, 0x01, 0xE2, 0x0A, 0x08, 0x80, 0xE2, 0xE0, 0x40, 0x84, 0xE3, 0x03, 0xC7, 0x8C, 0xE2, 0x0E, 0xE8, 0x8E, 0xE2, 0x20, 0x30, 0xA0, 0xE3, 0xB0, 0x70, 0xC2, 0xE1, 0xB0, 0x10, 0xC0, 0xE1, 0xB0, 0x40, 0xCC, 0xE1, 0xB0, 0x30, 0xCE, 0xE1, 0x0B, 0x80, 0xA0, 0xE1, 0x01, 0x90, 0x59, 0xE2, 0x3E, 0x00, 0x00, 0x3A, 0x26, 0x25, 0xA0, 0xE3, 0x03, 0x27, 0x82, 0xE2, 0xB0, 0x30, 0xD2, 0xE1, 0x03, 0x38, 0xA0, 0xE1, 0x23, 0x38, 0xA0, 0xE1, 0xFF, 0x30, 0x03, 0xE2, 0x58, 0x00, 0x53, 0xE3, 0x26, 0x17, 0xA0, 0x13, 0x96, 0x1C, 0x81, 0x12, 0x02, 0x00, 0xA0, 0x11, 0x80, 0x10, 0x81, 0x12, 0x00, 0x20, 0xA0, 0x13, 0x02, 0x00, 0x00, 0x1A, 0x0D, 0x00, 0x00, 0xEA, 0x01, 0x00, 0x52, 0xE1, 0x26, 0x00, 0x00, 0x0A, 0xB0, 0x30, 0xD0, 0xE1, 0x03, 0x38, 0xA0, 0xE1, 0x23, 0x38, 0xA0, 0xE1, 0xFF, 0x30, 0x03, 0xE2, 0x58, 0x00, 0x53, 0xE3, 0x01, 0x20, 0x82, 0xE2, 0xF6, 0xFF, 0xFF, 0x1A, 0x26, 0x37, 0xA0, 0xE3, 0x96, 0x3C, 0x83, 0xE2, 0x7F, 0x30, 0x83, 0xE2, 0x03, 0x00, 0x52, 0xE1, 0x1A, 0x00, 0x00, 0xCA, 0x01, 0x00, 0x18, 0xE3, 0x0B, 0x10, 0xA0, 0x01, 0xFF, 0x20, 0xA0, 0x03, 0x09, 0x04, 0xA0, 0x03, 0x0E, 0x00, 0x00, 0x0A, 0x08, 0x10, 0xA0, 0xE1, 0xFF, 0x00, 0xA0, 0xE3, 0x09, 0xC4, 0xA0, 0xE3, 0xB0, 0x30, 0xDC, 0xE1, 0x03, 0x38, 0xA0, 0xE1, 0x23, 0x38, 0xA0, 0xE1, 0x01, 0x00, 0x40, 0xE2, 0x43, 0x24, 0xA0, 0xE1, 0x01, 0x00, 0x70, 0xE3, 0x01, 0x20, 0xC1, 0xE5, 0x00, 0x30, 0xC1, 0xE5, 0x02, 0x10, 0x81, 0xE2, 0xF5, 0xFF, 0xFF, 0x1A, 0x02, 0x8C, 0x88, 0xE2, 0xCD, 0xFF, 0xFF, 0xEA, 0x01, 0x20, 0x42, 0xE2, 0xB0, 0x30, 0xD0, 0xE1, 0x01, 0x00, 0x72, 0xE3, 0xB2, 0x30, 0xC1, 0xE0, 0xFA, 0xFF, 0xFF, 0x1A, 0x02, 0xBC, 0x8B, 0xE2, 0xC6, 0xFF, 0xFF, 0xEA, 0x00, 0x00, 0xA0, 0xE3, 0x10, 0xD0, 0x8D, 0xE2, 0xF0, 0x4B, 0xBD, 0xE8, 0x1E, 0xFF, 0x2F, 0xE1, 0x09, 0x38, 0xA0, 0xE1, 0x23, 0x38, 0xA0, 0xE1, 0x0C, 0x30, 0x8D, 0xE5, 0x9C, 0xFF, 0xFF, 0xEA, 0x01, 0x00, 0xA0, 0xE3, 0xF6, 0xFF, 0xFF, 0xEA, 0xF0, 0x4B, 0x2D, 0xE9, 0x09, 0x34, 0xA0, 0xE3, 0x0E, 0x38, 0x83, 0xE2, 0xB0, 0xC0, 0xD3, 0xE1, 0x80, 0x00, 0x1C, 0xE3, 0x10, 0xD0, 0x4D, 0xE2, 0x01, 0x90, 0xA0, 0xE1, 0x02, 0xE0, 0xA0, 0xE1, 0x0C, 0x00, 0x00, 0x0A, 0x00, 0xC0, 0xA0, 0xE3, 0x01, 0x00, 0x00, 0xEA, 0x01, 0x00, 0x5C, 0xE1, 0x08, 0x00, 0x00, 0x0A, 0x09, 0x34, 0xA0, 0xE3, 0x0E, 0x38, 0x83, 0xE2, 0xB0, 0x20, 0xD3, 0xE1, 0x26, 0x17, 0xA0, 0xE3, 0x96, 0x1C, 0x81, 0xE2, 0x80, 0x00, 0x12, 0xE3, 0x01, 0xC0, 0x8C, 0xE2, 0x80, 0x10, 0x81, 0xE2, 0xF4, 0xFF, 0xFF, 0x1A, 0x26, 0xC5, 0xA0, 0xE3, 0x03, 0xC7, 0x8C, 0xE2, 0xB0, 0x30, 0xDC, 0xE1, 0x50, 0x30, 0x13, 0xE2, 0x26, 0x17, 0xA0, 0x03, 0x96, 0x1C, 0x81, 0x02, 0x03, 0x20, 0xA0, 0x01, 0x80, 0x10, 0x81, 0x02, 0x02, 0x00, 0x00, 0x0A, 0x0A, 0x00, 0x00, 0xEA, 0x01, 0x00, 0x52, 0xE1, 0x65, 0x00, 0x00, 0x0A, 0xB0, 0x30, 0xDC, 0xE1, 0x50, 0x00, 0x13, 0xE3, 0x01, 0x20, 0x82, 0xE2, 0xF9, 0xFF, 0xFF, 0x0A, 0x26, 0x37, 0xA0, 0xE3, 0x96, 0x3C, 0x83, 0xE2, 0x7F, 0x30, 0x83, 0xE2, 0x03, 0x00, 0x52, 0xE1, 0x5C, 0x00, 0x00, 0xCA, 0xFF, 0x00, 0x59, 0xE3, 0x00, 0x30, 0xA0, 0x83, 0x0C, 0x30, 0x8D, 0x85, 0x5C, 0x00, 0x00, 0x9A, 0x00, 0x38, 0xA0, 0xE1, 0x23, 0x38, 0xA0, 0xE1, 0xFF, 0x30, 0x03, 0xE2, 0x09, 0x54, 0xA0, 0xE3, 0x04, 0x30, 0x8D, 0xE5, 0x0C, 0x30, 0x9D, 0xE5, 0x20, 0x4C, 0xA0, 0xE1, 0x0E, 0xB0, 0xA0, 0xE1, 0x05, 0x60, 0xA0, 0xE1, 0x20, 0x74, 0xA0, 0xE1, 0x05, 0x20, 0xA0, 0xE1, 0x20, 0x18, 0xA0, 0xE1, 0x05, 0xC0, 0xA0, 0xE1, 0x05, 0x00, 0xA0, 0xE1, 0x05, 0xE0, 0xA0, 0xE1, 0x01, 0x57, 0x85, 0xE2, 0xB0, 0x30, 0xC5, 0xE1, 0x04, 0x30, 0x9D, 0xE5, 0x0F, 0x40, 0x04, 0xE2, 0x06, 0x68, 0x86, 0xE2, 0xB0, 0x30, 0xC6, 0xE1, 0xFF, 0x70, 0x07, 0xE2, 0x02, 0x27, 0x82, 0xE2, 0xFF, 0x10, 0x01, 0xE2, 0x0A, 0x08, 0x80, 0xE2, 0xE0, 0x40, 0x84, 0xE3, 0x03, 0xC7, 0x8C, 0xE2, 0x0E, 0xE8, 0x8E, 0xE2, 0x30, 0x30, 0xA0, 0xE3, 0xB0, 0x70, 0xC2, 0xE1, 0xB0, 0x10, 0xC0, 0xE1, 0xB0, 0x40, 0xCC, 0xE1, 0xB0, 0x30, 0xCE, 0xE1, 0x0B, 0x80, 0xA0, 0xE1, 0x01, 0x90, 0x59, 0xE2, 0x3C, 0x00, 0x00, 0x3A, 0x26, 0x25, 0xA0, 0xE3, 0x03, 0x27, 0x82, 0xE2, 0xB0, 0x30, 0xD2, 0xE1, 0x03, 0x38, 0xA0, 0xE1, 0x23, 0x38, 0xA0, 0xE1, 0xFF, 0x30, 0x03, 0xE2, 0x58, 0x00, 0x53, 0xE3, 0x26, 0x17, 0xA0, 0x13, 0x96, 0x1C, 0x81, 0x12, 0x02, 0x00, 0xA0, 0x11, 0x80, 0x10, 0x81, 0x12, 0x00, 0x20, 0xA0, 0x13, 0x02, 0x00, 0x00, 0x1A, 0x0D, 0x00, 0x00, 0xEA, 0x01, 0x00, 0x52, 0xE1, 0x24, 0x00, 0x00, 0x0A, 0xB0, 0x30, 0xD0, 0xE1, 0x03, 0x38, 0xA0, 0xE1, 0x23, 0x38, 0xA0, 0xE1, 0xFF, 0x30, 0x03, 0xE2, 0x58, 0x00, 0x53, 0xE3, 0x01, 0x20, 0x82, 0xE2, 0xF6, 0xFF, 0xFF, 0x1A, 0x26, 0x37, 0xA0, 0xE3, 0x96, 0x3C, 0x83, 0xE2, 0x7F, 0x30, 0x83, 0xE2, 0x03, 0x00, 0x52, 0xE1, 0x18, 0x00, 0x00, 0xCA, 0x01, 0x00, 0x18, 0xE3, 0x0B, 0x10, 0xA0, 0x01, 0xFF, 0x20, 0xA0, 0x03, 0x09, 0x04, 0xA0, 0x03, 0x0C, 0x00, 0x00, 0x0A, 0x08, 0x10, 0xA0, 0xE1, 0xFF, 0x00, 0xA0, 0xE3, 0x09, 0xC4, 0xA0, 0xE3, 0x00, 0x30, 0xD1, 0xE5, 0x01, 0x20, 0xD1, 0xE5, 0x01, 0x00, 0x40, 0xE2, 0x02, 0x34, 0x83, 0xE1, 0x01, 0x00, 0x70, 0xE3, 0xB0, 0x30, 0xCC, 0xE1, 0x02, 0x10, 0x81, 0xE2, 0xF7, 0xFF, 0xFF, 0x1A, 0x02, 0x8C, 0x88, 0xE2, 0xCF, 0xFF, 0xFF, 0xEA, 0x01, 0x20, 0x42, 0xE2, 0xB2, 0x30, 0xD1, 0xE0, 0x01, 0x00, 0x72, 0xE3, 0xB0, 0x30, 0xC0, 0xE1, 0xFA, 0xFF, 0xFF, 0x1A, 0x02, 0xBC, 0x8B, 0xE2, 0xC8, 0xFF, 0xFF, 0xEA, 0x00, 0x00, 0xA0, 0xE3, 0x10, 0xD0, 0x8D, 0xE2, 0xF0, 0x4B, 0xBD, 0xE8, 0x1E, 0xFF, 0x2F, 0xE1, 0x09, 0x38, 0xA0, 0xE1, 0x23, 0x38, 0xA0, 0xE1, 0x0C, 0x30, 0x8D, 0xE5, 0x9E, 0xFF, 0xFF, 0xEA, 0x01, 0x00, 0xA0, 0xE3, 0xF6, 0xFF, 0xFF, 0xEA, 0x04, 0xE0, 0x2D, 0xE5, 0x04, 0xD0, 0x4D, 0xE2, 0xAA, 0xFE, 0xFF, 0xEB, 0x04, 0xD0, 0x8D, 0xE2, 0x04, 0xE0, 0x9D, 0xE4, 0x1E, 0xFF, 0x2F, 0xE1, 0x0D, 0xC0, 0xA0, 0xE1, 0xF8, 0xDF, 0x2D, 0xE9, 0x04, 0xB0, 0x4C, 0xE2, 0x28, 0xD0, 0x4B, 0xE2, 0xF0, 0x6F, 0x9D, 0xE8, 0x1E, 0xFF, 0x2F, 0xE1, 0xDC, 0x00, 0x80, 0xBF, 0x98, 0x00, 0x80, 0xBF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; //unsigned char mpcf_dldi[1876] data_t r4_dldi[2276] = { 0xED, 0xA5, 0x8D, 0xBF, 0x20, 0x43, 0x68, 0x69, 0x73, 0x68, 0x6D, 0x00, 0x01, 0x0D, 0x0E, 0x00, 0x52, 0x34, 0x28, 0x44, 0x53, 0x29, 0x20, 0x2D, 0x20, 0x52, 0x65, 0x76, 0x6F, 0x6C, 0x75, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x66, 0x6F, 0x72, 0x20, 0x44, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xBF, 0xE4, 0x08, 0x80, 0xBF, 0x98, 0x00, 0x80, 0xBF, 0xB8, 0x00, 0x80, 0xBF, 0xE0, 0x08, 0x80, 0xBF, 0xE0, 0x08, 0x80, 0xBF, 0xE4, 0x08, 0x80, 0xBF, 0x00, 0x09, 0x80, 0xBF, 0x52, 0x34, 0x54, 0x46, 0x23, 0x00, 0x00, 0x00, 0xF8, 0x03, 0x80, 0xBF, 0xD0, 0x03, 0x80, 0xBF, 0xD8, 0x04, 0x80, 0xBF, 0x24, 0x03, 0x80, 0xBF, 0x5C, 0x01, 0x80, 0xBF, 0x64, 0x01, 0x80, 0xBF, 0x0D, 0xC0, 0xA0, 0xE1, 0xF8, 0xDF, 0x2D, 0xE9, 0x04, 0xB0, 0x4C, 0xE2, 0x28, 0xD0, 0x4B, 0xE2, 0xF0, 0x6F, 0x9D, 0xE8, 0x1E, 0xFF, 0x2F, 0xE1, 0x00, 0xC0, 0x9F, 0xE5, 0x1C, 0xFF, 0x2F, 0xE1, 0x29, 0x05, 0x80, 0xBF, 0x00, 0xC0, 0x9F, 0xE5, 0x1C, 0xFF, 0x2F, 0xE1, 0x4D, 0x05, 0x80, 0xBF, 0x78, 0x47, 0xC0, 0x46, 0xD6, 0x01, 0x00, 0xEA, 0x10, 0x40, 0x2D, 0xE9, 0x2C, 0x40, 0x9F, 0xE5, 0x00, 0x30, 0xD4, 0xE5, 0x00, 0x00, 0x53, 0xE3, 0x24, 0x20, 0x9F, 0xE5, 0x05, 0x00, 0x00, 0x1A, 0x00, 0x00, 0x52, 0xE3, 0x1C, 0x00, 0x9F, 0xE5, 0x0F, 0xE0, 0xA0, 0x11, 0x12, 0xFF, 0x2F, 0x11, 0x01, 0x30, 0xA0, 0xE3, 0x00, 0x30, 0xC4, 0xE5, 0x10, 0x40, 0xBD, 0xE8, 0x1E, 0xFF, 0x2F, 0xE1, 0xE4, 0x08, 0x80, 0xBF, 0x00, 0x00, 0x00, 0x00, 0xD8, 0x08, 0x80, 0xBF, 0x04, 0xE0, 0x2D, 0xE5, 0x40, 0x30, 0x9F, 0xE5, 0x00, 0x00, 0x53, 0xE3, 0x04, 0xD0, 0x4D, 0xE2, 0x38, 0x00, 0x9F, 0xE5, 0x38, 0x10, 0x9F, 0xE5, 0x0F, 0xE0, 0xA0, 0x11, 0x13, 0xFF, 0x2F, 0x11, 0x30, 0x00, 0x9F, 0xE5, 0x00, 0x30, 0x90, 0xE5, 0x00, 0x00, 0x53, 0xE3, 0x28, 0x30, 0x9F, 0xE5, 0x02, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x53, 0xE3, 0x0F, 0xE0, 0xA0, 0x11, 0x13, 0xFF, 0x2F, 0x11, 0x04, 0xD0, 0x8D, 0xE2, 0x04, 0xE0, 0x9D, 0xE4, 0x1E, 0xFF, 0x2F, 0xE1, 0x00, 0x00, 0x00, 0x00, 0xD8, 0x08, 0x80, 0xBF, 0xE8, 0x08, 0x80, 0xBF, 0xDC, 0x08, 0x80, 0xBF, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xA0, 0xE3, 0x1E, 0xFF, 0x2F, 0xE1, 0x01, 0x00, 0xA0, 0xE3, 0x1E, 0xFF, 0x2F, 0xE1, 0x70, 0x40, 0x2D, 0xE9, 0x00, 0x50, 0xA0, 0xE1, 0x03, 0x00, 0xA0, 0xE1, 0x02, 0x40, 0xA0, 0xE1, 0x01, 0x60, 0xA0, 0xE1, 0xC4, 0xFF, 0xFF, 0xEB, 0x01, 0x33, 0xA0, 0xE3, 0xA4, 0x51, 0x83, 0xE5, 0x04, 0xE1, 0x86, 0xE0, 0x03, 0xC0, 0xA0, 0xE1, 0x41, 0x46, 0xA0, 0xE3, 0xA4, 0x31, 0x9C, 0xE5, 0x02, 0x05, 0x13, 0xE3, 0x09, 0x00, 0x00, 0x0A, 0x10, 0x30, 0x94, 0xE5, 0x0E, 0x00, 0x56, 0xE1, 0x23, 0x0C, 0xA0, 0xE1, 0x23, 0x24, 0xA0, 0xE1, 0x23, 0x18, 0xA0, 0xE1, 0x01, 0x20, 0xC6, 0x35, 0x02, 0x10, 0xC6, 0x35, 0x03, 0x00, 0xC6, 0x35, 0x00, 0x30, 0xC6, 0x35, 0x04, 0x60, 0x86, 0xE2, 0xA4, 0x31, 0x9C, 0xE5, 0x00, 0x00, 0x53, 0xE3, 0xEF, 0xFF, 0xFF, 0xBA, 0x70, 0x40, 0xBD, 0xE8, 0x1E, 0xFF, 0x2F, 0xE1, 0xF0, 0x41, 0x2D, 0xE9, 0x00, 0x80, 0xA0, 0xE1, 0x01, 0x70, 0xA0, 0xE1, 0x00, 0x50, 0xA0, 0xE3, 0x01, 0x43, 0xA0, 0xE3, 0x41, 0x66, 0xA0, 0xE3, 0x07, 0x00, 0xA0, 0xE1, 0xA5, 0xFF, 0xFF, 0xEB, 0xA4, 0x81, 0x84, 0xE5, 0xA4, 0x31, 0x94, 0xE5, 0x02, 0x05, 0x13, 0xE3, 0x02, 0x00, 0x00, 0x0A, 0x10, 0x30, 0x96, 0xE5, 0x00, 0x00, 0x53, 0xE3, 0x01, 0x50, 0xA0, 0x03, 0xA4, 0x31, 0x94, 0xE5, 0x00, 0x00, 0x53, 0xE3, 0xF6, 0xFF, 0xFF, 0xBA, 0x00, 0x00, 0x55, 0xE3, 0xF1, 0xFF, 0xFF, 0x0A, 0xF0, 0x41, 0xBD, 0xE8, 0x1E, 0xFF, 0x2F, 0xE1, 0xF0, 0x40, 0x2D, 0xE9, 0x0C, 0xD0, 0x4D, 0xE2, 0x00, 0xC0, 0xA0, 0xE1, 0x20, 0xEC, 0xA0, 0xE1, 0x00, 0x40, 0xA0, 0xE3, 0x20, 0x58, 0xA0, 0xE1, 0x20, 0x64, 0xA0, 0xE1, 0x44, 0x30, 0xE0, 0xE3, 0x0D, 0x00, 0xA0, 0xE1, 0x07, 0x30, 0xCD, 0xE5, 0x06, 0xE0, 0xCD, 0xE5, 0x05, 0x50, 0xCD, 0xE5, 0x04, 0x60, 0xCD, 0xE5, 0x02, 0x50, 0xA0, 0xE1, 0x03, 0xC0, 0xCD, 0xE5, 0x01, 0x60, 0xA0, 0xE1, 0x02, 0x40, 0xCD, 0xE5, 0x01, 0x40, 0xCD, 0xE5, 0x00, 0x40, 0xCD, 0xE5, 0x83, 0xFF, 0xFF, 0xEB, 0xE1, 0x34, 0xA0, 0xE3, 0x16, 0x37, 0x83, 0xE2, 0x01, 0x23, 0xA0, 0xE3, 0x06, 0x3A, 0x83, 0xE2, 0xA4, 0x31, 0x82, 0xE5, 0x05, 0xE1, 0x86, 0xE0, 0x0D, 0x70, 0xA0, 0xE1, 0x02, 0xC0, 0xA0, 0xE1, 0x41, 0x56, 0xA0, 0xE3, 0xA4, 0x31, 0x9C, 0xE5, 0x02, 0x05, 0x13, 0xE3, 0x0D, 0x00, 0x00, 0x0A, 0x0E, 0x00, 0x56, 0xE1, 0x09, 0x00, 0x00, 0x2A, 0x03, 0x00, 0x16, 0xE3, 0x03, 0x30, 0xD6, 0x15, 0x00, 0x20, 0xD6, 0x15, 0x01, 0x10, 0xD6, 0x15, 0x02, 0x00, 0xD6, 0x15, 0x03, 0x3C, 0xA0, 0x11, 0x01, 0x24, 0x82, 0x11, 0x00, 0x38, 0x83, 0x11, 0x00, 0x40, 0x96, 0x05, 0x03, 0x40, 0x82, 0x11, 0x10, 0x40, 0x85, 0xE5, 0x04, 0x60, 0x86, 0xE2, 0xA4, 0x31, 0x9C, 0xE5, 0x00, 0x00, 0x53, 0xE3, 0xEB, 0xFF, 0xFF, 0xBA, 0xA7, 0x04, 0xA0, 0xE3, 0x16, 0x07, 0x80, 0xE2, 0x43, 0x30, 0xE0, 0xE3, 0x06, 0x0A, 0x80, 0xE2, 0x0D, 0x10, 0xA0, 0xE1, 0x07, 0x30, 0xCD, 0xE5, 0xB1, 0xFF, 0xFF, 0xEB, 0x0C, 0xD0, 0x8D, 0xE2, 0xF0, 0x40, 0xBD, 0xE8, 0x1E, 0xFF, 0x2F, 0xE1, 0xF0, 0x40, 0x2D, 0xE9, 0x00, 0x70, 0x51, 0xE2, 0x04, 0xD0, 0x4D, 0xE2, 0x00, 0x50, 0xA0, 0xE1, 0x0A, 0x00, 0x00, 0x0A, 0x02, 0x40, 0xA0, 0xE1, 0x00, 0x60, 0xA0, 0xE3, 0x85, 0x04, 0xA0, 0xE1, 0x04, 0x10, 0xA0, 0xE1, 0x01, 0x60, 0x86, 0xE2, 0x80, 0x20, 0xA0, 0xE3, 0xB8, 0xFF, 0xFF, 0xEB, 0x06, 0x00, 0x57, 0xE1, 0x01, 0x50, 0x85, 0xE2, 0x02, 0x4C, 0x84, 0xE2, 0xF6, 0xFF, 0xFF, 0x1A, 0x01, 0x00, 0xA0, 0xE3, 0x04, 0xD0, 0x8D, 0xE2, 0xF0, 0x40, 0xBD, 0xE8, 0x1E, 0xFF, 0x2F, 0xE1, 0x04, 0xE0, 0x2D, 0xE5, 0xA7, 0x04, 0xA0, 0xE3, 0x14, 0xD0, 0x4D, 0xE2, 0x16, 0x07, 0x80, 0xE2, 0x00, 0xC0, 0xA0, 0xE3, 0x4F, 0xE0, 0xE0, 0xE3, 0x06, 0x0A, 0x80, 0xE2, 0x0C, 0x10, 0x8D, 0xE2, 0x01, 0x20, 0xA0, 0xE3, 0x04, 0x30, 0x8D, 0xE2, 0x0B, 0xE0, 0xCD, 0xE5, 0x04, 0xC0, 0xCD, 0xE5, 0x0A, 0xC0, 0xCD, 0xE5, 0x09, 0xC0, 0xCD, 0xE5, 0x08, 0xC0, 0xCD, 0xE5, 0x07, 0xC0, 0xCD, 0xE5, 0x06, 0xC0, 0xCD, 0xE5, 0x05, 0xC0, 0xCD, 0xE5, 0x38, 0xFF, 0xFF, 0xEB, 0x0C, 0x00, 0x9D, 0xE5, 0x14, 0xD0, 0x8D, 0xE2, 0x04, 0xE0, 0x9D, 0xE4, 0x1E, 0xFF, 0x2F, 0xE1, 0x04, 0xE0, 0x2D, 0xE5, 0x04, 0xD0, 0x4D, 0xE2, 0xE5, 0xFF, 0xFF, 0xEB, 0x07, 0x00, 0x00, 0xE2, 0x04, 0x00, 0x50, 0xE3, 0x00, 0x00, 0xA0, 0x13, 0x01, 0x00, 0xA0, 0x03, 0x04, 0xD0, 0x8D, 0xE2, 0x04, 0xE0, 0x9D, 0xE4, 0x1E, 0xFF, 0x2F, 0xE1, 0x04, 0xE0, 0x2D, 0xE5, 0x04, 0xD0, 0x4D, 0xE2, 0xDB, 0xFF, 0xFF, 0xEB, 0x07, 0x00, 0x00, 0xE2, 0x04, 0x00, 0x50, 0xE3, 0x00, 0x00, 0xA0, 0x13, 0x01, 0x00, 0xA0, 0x03, 0x04, 0xD0, 0x8D, 0xE2, 0x04, 0xE0, 0x9D, 0xE4, 0x1E, 0xFF, 0x2F, 0xE1, 0xF0, 0x41, 0x2D, 0xE9, 0x00, 0xC0, 0xA0, 0xE1, 0xA7, 0x04, 0xA0, 0xE3, 0x08, 0xD0, 0x4D, 0xE2, 0x16, 0x07, 0x80, 0xE2, 0x2C, 0x58, 0xA0, 0xE1, 0x01, 0x70, 0xA0, 0xE1, 0x00, 0x40, 0xA0, 0xE3, 0x2C, 0xEC, 0xA0, 0xE1, 0x2C, 0x64, 0xA0, 0xE1, 0x46, 0x30, 0xE0, 0xE3, 0x06, 0x0A, 0x80, 0xE2, 0x0D, 0x10, 0xA0, 0xE1, 0x07, 0x30, 0xCD, 0xE5, 0x05, 0x50, 0xCD, 0xE5, 0x03, 0xC0, 0xCD, 0xE5, 0x02, 0x50, 0xA0, 0xE1, 0x06, 0xE0, 0xCD, 0xE5, 0x04, 0x60, 0xCD, 0xE5, 0x00, 0x40, 0xCD, 0xE5, 0x02, 0x40, 0xCD, 0xE5, 0x01, 0x40, 0xCD, 0xE5, 0x58, 0xFF, 0xFF, 0xEB, 0xA1, 0x04, 0xA0, 0xE3, 0x16, 0x07, 0x80, 0xE2, 0x45, 0xC0, 0xE0, 0xE3, 0x03, 0x00, 0x17, 0xE3, 0x0D, 0x80, 0xA0, 0xE1, 0x06, 0x0A, 0x80, 0xE2, 0x07, 0x10, 0xA0, 0xE1, 0x05, 0x20, 0xA0, 0xE1, 0x0D, 0x30, 0xA0, 0xE1, 0x07, 0xC0, 0xCD, 0xE5, 0x03, 0x00, 0x00, 0x0A, 0x2F, 0xFF, 0xFF, 0xEB, 0x08, 0xD0, 0x8D, 0xE2, 0xF0, 0x41, 0xBD, 0xE8, 0x1E, 0xFF, 0x2F, 0xE1, 0xA1, 0x04, 0xA0, 0xE3, 0x16, 0x07, 0x80, 0xE2, 0x06, 0x0A, 0x80, 0xE2, 0x07, 0x10, 0xA0, 0xE1, 0x05, 0x20, 0xA0, 0xE1, 0x0D, 0x30, 0xA0, 0xE1, 0xF3, 0xFE, 0xFF, 0xEB, 0xF4, 0xFF, 0xFF, 0xEA, 0xF0, 0x40, 0x2D, 0xE9, 0x00, 0x70, 0x51, 0xE2, 0x04, 0xD0, 0x4D, 0xE2, 0x00, 0x50, 0xA0, 0xE1, 0x0A, 0x00, 0x00, 0x0A, 0x02, 0x40, 0xA0, 0xE1, 0x00, 0x60, 0xA0, 0xE3, 0x85, 0x04, 0xA0, 0xE1, 0x04, 0x10, 0xA0, 0xE1, 0x01, 0x60, 0x86, 0xE2, 0x80, 0x20, 0xA0, 0xE3, 0xC5, 0xFF, 0xFF, 0xEB, 0x06, 0x00, 0x57, 0xE1, 0x01, 0x50, 0x85, 0xE2, 0x02, 0x4C, 0x84, 0xE2, 0xF6, 0xFF, 0xFF, 0x1A, 0x01, 0x00, 0xA0, 0xE3, 0x04, 0xD0, 0x8D, 0xE2, 0xF0, 0x40, 0xBD, 0xE8, 0x1E, 0xFF, 0x2F, 0xE1, 0x10, 0xB5, 0x40, 0x23, 0x05, 0x4A, 0x5B, 0x42, 0x05, 0x4C, 0x13, 0x70, 0x00, 0x21, 0x43, 0x5C, 0x62, 0x1A, 0x01, 0x31, 0x13, 0x70, 0x08, 0x29, 0xF9, 0xD1, 0x10, 0xBD, 0xA1, 0x01, 0x00, 0x04, 0xAF, 0x01, 0x00, 0x04, 0x70, 0xB5, 0x05, 0x1C, 0x18, 0x1C, 0x0E, 0x1C, 0x14, 0x1C, 0xFF, 0xF7, 0xE7, 0xFF, 0x0A, 0x4B, 0xA4, 0x00, 0x80, 0x22, 0x09, 0x48, 0x1D, 0x60, 0xA4, 0x19, 0x19, 0x1C, 0x12, 0x04, 0x0B, 0x68, 0x13, 0x42, 0x04, 0xD0, 0x03, 0x68, 0xA6, 0x42, 0x00, 0xD2, 0x33, 0x60, 0x04, 0x36, 0x0B, 0x68, 0x00, 0x2B, 0xF4, 0xDB, 0x70, 0xBD, 0x00, 0x00, 0xA4, 0x01, 0x00, 0x04, 0x10, 0x00, 0x10, 0x04, 0x70, 0xB5, 0x0D, 0x1C, 0x14, 0x1C, 0x1E, 0x1C, 0xFF, 0xF7, 0xC8, 0xFF, 0x63, 0x00, 0x1B, 0x19, 0x07, 0x4A, 0x9B, 0x00, 0x99, 0x18, 0x07, 0x4A, 0x0A, 0x60, 0x07, 0x49, 0x5A, 0x18, 0x15, 0x60, 0x06, 0x4A, 0x9B, 0x18, 0x06, 0x4A, 0x1A, 0x60, 0x06, 0x4B, 0x1E, 0x60, 0x70, 0xBD, 0x00, 0x00, 0xB0, 0x00, 0x00, 0x04, 0x10, 0x00, 0x10, 0x04, 0xB4, 0x00, 0x00, 0x04, 0xB8, 0x00, 0x00, 0x04, 0x01, 0x00, 0x00, 0xAF, 0xA4, 0x01, 0x00, 0x04, 0x10, 0xB5, 0x0C, 0x1C, 0xFF, 0xF7, 0xA6, 0xFF, 0x06, 0x4B, 0x80, 0x22, 0x1C, 0x43, 0x06, 0x4B, 0x12, 0x04, 0x1C, 0x60, 0x19, 0x1C, 0x0B, 0x68, 0x13, 0x42, 0xFC, 0xD0, 0x03, 0x4B, 0x18, 0x68, 0x10, 0xBD, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA7, 0xA4, 0x01, 0x00, 0x04, 0x10, 0x00, 0x10, 0x04, 0x70, 0xB5, 0x82, 0xB0, 0x1E, 0x1C, 0x04, 0x0E, 0x6B, 0x46, 0x9C, 0x71, 0x04, 0x0C, 0x00, 0x25, 0x5C, 0x71, 0x04, 0x0A, 0xDD, 0x71, 0xD8, 0x70, 0x9D, 0x70, 0x5D, 0x70, 0x1D, 0x70, 0x30, 0x1C, 0x1C, 0x71, 0xFF, 0xF7, 0x91, 0xFF, 0x02, 0xB0, 0x70, 0xBD, 0x00, 0x00, 0x00, 0xB5, 0x80, 0x22, 0x81, 0xB0, 0x01, 0x1C, 0x92, 0x00, 0x00, 0x20, 0x02, 0x4B, 0xFF, 0xF7, 0xE1, 0xFF, 0x01, 0xB0, 0x00, 0xBD, 0x00, 0x00, 0xFF, 0x1F, 0x3F, 0xA9, 0x30, 0xB5, 0x83, 0xB0, 0x05, 0x1C, 0x08, 0x22, 0x04, 0x49, 0x68, 0x46, 0xFF, 0xF7, 0x2A, 0xFD, 0x29, 0x1C, 0x68, 0x46, 0xFF, 0xF7, 0xB8, 0xFF, 0x03, 0xB0, 0x30, 0xBD, 0xC8, 0x08, 0x80, 0xBF, 0xF0, 0xB5, 0x5F, 0x46, 0x56, 0x46, 0x4D, 0x46, 0x44, 0x46, 0xF0, 0xB4, 0x12, 0x18, 0x83, 0xB0, 0x94, 0x46, 0x04, 0x1C, 0x0F, 0x1C, 0x01, 0x93, 0x60, 0x45, 0x63, 0xD2, 0x38, 0x4A, 0x39, 0x4B, 0x90, 0x46, 0x9B, 0x46, 0x02, 0x32, 0x80, 0x23, 0x92, 0x46, 0x99, 0x46, 0x5B, 0x46, 0x42, 0x46, 0x13, 0x80, 0x06, 0x23, 0x52, 0x46, 0x13, 0x70, 0x42, 0x46, 0x13, 0x88, 0x4A, 0x46, 0x13, 0x42, 0xFA, 0xD1, 0x43, 0x46, 0x40, 0x22, 0x1A, 0x80, 0x5A, 0x46, 0x1A, 0x80, 0x01, 0x9B, 0x01, 0x2B, 0x4F, 0xD0, 0x02, 0x23, 0x52, 0x46, 0x2A, 0x49, 0x13, 0x70, 0x80, 0x22, 0x0B, 0x88, 0x13, 0x42, 0xFC, 0xD1, 0x01, 0x9B, 0x01, 0x2B, 0x08, 0xD9, 0x23, 0x04, 0x52, 0x46, 0x1B, 0x0E, 0x24, 0x49, 0x13, 0x70, 0x80, 0x22, 0x0B, 0x88, 0x13, 0x42, 0xFC, 0xD1, 0x23, 0x06, 0x52, 0x46, 0x1B, 0x0E, 0x1F, 0x49, 0x13, 0x70, 0x80, 0x22, 0x0B, 0x88, 0x13, 0x42, 0xFC, 0xD1, 0x1E, 0x4D, 0x1C, 0x4A, 0x00, 0x20, 0x80, 0x21, 0x3B, 0x78, 0x01, 0x37, 0x2B, 0x70, 0x13, 0x88, 0x0B, 0x42, 0xFC, 0xD1, 0x01, 0x34, 0xA4, 0x45, 0x02, 0xD9, 0x01, 0x30, 0x20, 0x28, 0xF3, 0xD1, 0x40, 0x23, 0x13, 0x80, 0x5B, 0x46, 0x13, 0x80, 0x12, 0x49, 0x52, 0x46, 0x05, 0x23, 0x13, 0x70, 0x80, 0x22, 0x0B, 0x88, 0x13, 0x42, 0xFC, 0xD1, 0x10, 0x48, 0x0E, 0x49, 0x00, 0x26, 0x80, 0x22, 0x01, 0x25, 0x06, 0x70, 0x0B, 0x88, 0x13, 0x42, 0xFC, 0xD1, 0x03, 0x78, 0x2B, 0x42, 0xF8, 0xD1, 0x40, 0x23, 0x0B, 0x80, 0xA4, 0x45, 0xA3, 0xD8, 0x03, 0xB0, 0x3C, 0xBC, 0x90, 0x46, 0x99, 0x46, 0xA2, 0x46, 0xAB, 0x46, 0xF0, 0xBD, 0x23, 0x0A, 0xDB, 0x00, 0x02, 0x22, 0x13, 0x43, 0x1B, 0x06, 0x1B, 0x0E, 0xA9, 0xE7, 0xA0, 0x01, 0x00, 0x04, 0x40, 0xA0, 0xFF, 0xFF, 0xA2, 0x01, 0x00, 0x04, 0x70, 0xB5, 0x14, 0x1C, 0x1E, 0x1C, 0x22, 0x4A, 0x22, 0x4B, 0x0D, 0x1C, 0x1A, 0x80, 0x01, 0x2E, 0x31, 0xD0, 0x03, 0x22, 0x20, 0x4B, 0x1F, 0x49, 0x1A, 0x70, 0x80, 0x22, 0x0B, 0x88, 0x13, 0x42, 0xFC, 0xD1, 0x03, 0x2E, 0x2E, 0xD0, 0x01, 0x2E, 0x03, 0xD9, 0x03, 0x04, 0x1A, 0x4A, 0x1B, 0x0E, 0x13, 0x70, 0x18, 0x49, 0x0B, 0x88, 0x1A, 0x06, 0xFB, 0xD4, 0x03, 0x06, 0x16, 0x4A, 0x1B, 0x0E, 0x13, 0x70, 0x08, 0x1C, 0x80, 0x22, 0x03, 0x88, 0x13, 0x42, 0xFC, 0xD1, 0x00, 0x2C, 0x0E, 0xD0, 0x11, 0x49, 0x10, 0x48, 0x00, 0x26, 0x80, 0x22, 0x0E, 0x70, 0x03, 0x88, 0x13, 0x42, 0xFC, 0xD1, 0x0B, 0x78, 0x01, 0x3C, 0x2B, 0x70, 0x00, 0x2C, 0x01, 0xD0, 0x01, 0x35, 0xF4, 0xE7, 0x09, 0x4B, 0x40, 0x22, 0x1A, 0x80, 0x70, 0xBD, 0x03, 0x0A, 0x03, 0x22, 0xDB, 0x00, 0x13, 0x43, 0x1B, 0x06, 0x1A, 0x0E, 0xC7, 0xE7, 0x03, 0x02, 0x04, 0x4A, 0x1B, 0x0E, 0x13, 0x70, 0xD1, 0xE7, 0x00, 0x00, 0x40, 0xA0, 0xFF, 0xFF, 0xA0, 0x01, 0x00, 0x04, 0xA2, 0x01, 0x00, 0x04, 0x0F, 0x00, 0x52, 0xE3, 0x04, 0xE0, 0x2D, 0xE5, 0x00, 0xC0, 0xA0, 0xE1, 0x02, 0xE0, 0xA0, 0xE1, 0x02, 0x00, 0x00, 0x9A, 0x00, 0x30, 0x81, 0xE1, 0x03, 0x00, 0x13, 0xE3, 0x09, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x5E, 0xE3, 0x05, 0x00, 0x00, 0x0A, 0x00, 0x20, 0xA0, 0xE3, 0x01, 0x30, 0xD1, 0xE4, 0x0C, 0x30, 0xC2, 0xE7, 0x01, 0x20, 0x82, 0xE2, 0x0E, 0x00, 0x52, 0xE1, 0xFA, 0xFF, 0xFF, 0x1A, 0x04, 0xE0, 0x9D, 0xE4, 0x1E, 0xFF, 0x2F, 0xE1, 0x00, 0x30, 0x91, 0xE5, 0x00, 0x30, 0x8C, 0xE5, 0x04, 0x20, 0x91, 0xE5, 0x04, 0x20, 0x8C, 0xE5, 0x08, 0x30, 0x91, 0xE5, 0x08, 0x30, 0x8C, 0xE5, 0x10, 0xE0, 0x4E, 0xE2, 0x0C, 0x30, 0x91, 0xE5, 0x0F, 0x00, 0x5E, 0xE3, 0x0C, 0x30, 0x8C, 0xE5, 0x10, 0x10, 0x81, 0xE2, 0x10, 0xC0, 0x8C, 0xE2, 0xF2, 0xFF, 0xFF, 0x8A, 0x03, 0x00, 0x5E, 0xE3, 0xE6, 0xFF, 0xFF, 0x9A, 0x04, 0xE0, 0x4E, 0xE2, 0x04, 0x30, 0x91, 0xE4, 0x03, 0x00, 0x5E, 0xE3, 0x04, 0x30, 0x8C, 0xE4, 0xFA, 0xFF, 0xFF, 0x8A, 0xE0, 0xFF, 0xFF, 0xEA, 0x0D, 0xC0, 0xA0, 0xE1, 0xF8, 0xDF, 0x2D, 0xE9, 0x04, 0xB0, 0x4C, 0xE2, 0x28, 0xD0, 0x4B, 0xE2, 0xF0, 0x6F, 0x9D, 0xE8, 0x1E, 0xFF, 0x2F, 0xE1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0xFC, 0x00, 0x80, 0xBF, 0xB8, 0x00, 0x80, 0xBF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; int DLDI_tryPatch(void* data, size_t size, unsigned int device) { // Find the DSDI reserved space in the file addr_t patchOffset = quickFind ((data_t*)data, dldiMagicString, size, sizeof(dldiMagicString)/sizeof(char)); //no DLDI section if (patchOffset < 0) return 0; data_t *pDH = device == 0?mpcf_dldi:r4_dldi; data_t *pAH = (data_t*)data + patchOffset; if (pDH[DO_driverSize] > pAH[DO_allocatedSpace]) { printf ("Not enough space for patch. Available %d bytes, need %d bytes\n", ( 1 << pAH[DO_allocatedSpace]), ( 1 << pDH[DO_driverSize]) ); return 0; } if(memcmp(&pAH[DO_friendlyName],"Default (No interface)",22)) { printf("Would have been a candidate for auto-patch DLDI, but there was already a patch installed."); return 0; } //----should be able to patch OK----- addr_t memOffset; // Offset of DLDI after the file is loaded into memory addr_t relocationOffset; // Value added to all offsets within the patch to fix it properly addr_t ddmemOffset; // Original offset used in the DLDI file addr_t ddmemStart; // Start of range that offsets can be in the DLDI file addr_t ddmemEnd; // End of range that offsets can be in the DLDI file addr_t ddmemSize; // Size of range that offsets can be in the DLDI file addr_t addrIter; memOffset = readAddr (pAH, DO_text_start); if (memOffset == 0) { memOffset = readAddr (pAH, DO_startup) - DO_code; } ddmemOffset = readAddr (pDH, DO_text_start); relocationOffset = memOffset - ddmemOffset; printf ("AUTO-PATCHING DLDI to MPCF! Lucky you!\n\n"); printf ("Old driver: %s\n", &pAH[DO_friendlyName]); printf ("New driver: %s\n", &pDH[DO_friendlyName]); printf ("\n"); printf ("Position in file: 0x%08X\n", patchOffset); printf ("Position in memory: 0x%08X\n", memOffset); printf ("Patch base address: 0x%08X\n", ddmemOffset); printf ("Relocation offset: 0x%08X\n", relocationOffset); printf ("\n"); ddmemStart = readAddr (pDH, DO_text_start); ddmemSize = (1 << pDH[DO_driverSize]); ddmemEnd = ddmemStart + ddmemSize; // Remember how much space is actually reserved pDH[DO_allocatedSpace] = pAH[DO_allocatedSpace]; // Copy the DLDI patch into the application memcpy (pAH, pDH, device == 0?sizeof(mpcf_dldi):sizeof(r4_dldi)); // Fix the section pointers in the header writeAddr (pAH, DO_text_start, readAddr (pAH, DO_text_start) + relocationOffset); writeAddr (pAH, DO_data_end, readAddr (pAH, DO_data_end) + relocationOffset); writeAddr (pAH, DO_glue_start, readAddr (pAH, DO_glue_start) + relocationOffset); writeAddr (pAH, DO_glue_end, readAddr (pAH, DO_glue_end) + relocationOffset); writeAddr (pAH, DO_got_start, readAddr (pAH, DO_got_start) + relocationOffset); writeAddr (pAH, DO_got_end, readAddr (pAH, DO_got_end) + relocationOffset); writeAddr (pAH, DO_bss_start, readAddr (pAH, DO_bss_start) + relocationOffset); writeAddr (pAH, DO_bss_end, readAddr (pAH, DO_bss_end) + relocationOffset); // Fix the function pointers in the header writeAddr (pAH, DO_startup, readAddr (pAH, DO_startup) + relocationOffset); writeAddr (pAH, DO_isInserted, readAddr (pAH, DO_isInserted) + relocationOffset); writeAddr (pAH, DO_readSectors, readAddr (pAH, DO_readSectors) + relocationOffset); writeAddr (pAH, DO_writeSectors, readAddr (pAH, DO_writeSectors) + relocationOffset); writeAddr (pAH, DO_clearStatus, readAddr (pAH, DO_clearStatus) + relocationOffset); writeAddr (pAH, DO_shutdown, readAddr (pAH, DO_shutdown) + relocationOffset); if (pDH[DO_fixSections] & FIX_ALL) { // Search through and fix pointers within the data section of the file for (addrIter = (readAddr(pDH, DO_text_start) - ddmemStart); addrIter < (readAddr(pDH, DO_data_end) - ddmemStart); addrIter++) { if ((ddmemStart <= readAddr(pAH, addrIter)) && (readAddr(pAH, addrIter) < ddmemEnd)) { writeAddr (pAH, addrIter, readAddr(pAH, addrIter) + relocationOffset); } } } if (pDH[DO_fixSections] & FIX_GLUE) { // Search through and fix pointers within the glue section of the file for (addrIter = (readAddr(pDH, DO_glue_start) - ddmemStart); addrIter < (readAddr(pDH, DO_glue_end) - ddmemStart); addrIter++) { if ((ddmemStart <= readAddr(pAH, addrIter)) && (readAddr(pAH, addrIter) < ddmemEnd)) { writeAddr (pAH, addrIter, readAddr(pAH, addrIter) + relocationOffset); } } } if (pDH[DO_fixSections] & FIX_GOT) { // Search through and fix pointers within the Global Offset Table section of the file for (addrIter = (readAddr(pDH, DO_got_start) - ddmemStart); addrIter < (readAddr(pDH, DO_got_end) - ddmemStart); addrIter++) { if ((ddmemStart <= readAddr(pAH, addrIter)) && (readAddr(pAH, addrIter) < ddmemEnd)) { writeAddr (pAH, addrIter, readAddr(pAH, addrIter) + relocationOffset); } } } if (pDH[DO_fixSections] & FIX_BSS) { // Initialise the BSS to 0 memset (&pAH[readAddr(pDH, DO_bss_start) - ddmemStart] , 0, readAddr(pDH, DO_bss_end) - readAddr(pDH, DO_bss_start)); } return 1; } desmume/src/utils/libfat/fatdir.c000664 001750 001750 00000043160 12755534123 020161 0ustar00sergiosergio000000 000000 /* fatdir.c Functions used by the newlib disc stubs to interface with this library Copyright (c) 2006 Michael "Chishm" Chisholm Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. 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. 3. The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 #ifndef _WIN32 #include #ifndef __LIBRETRO__ #include #endif #endif #if defined(_WIN32) && !defined(_MSC_VER) #ifndef ENOTSUP #define ENOTSUP 134 #endif #endif #include "fatdir.h" #include "cache.h" #include "file_allocation_table.h" #include "partition.h" #include "directory.h" #include "bit_ops.h" #include "filetime.h" #include "lock.h" int _FAT_stat_r (struct _reent *r, const char *path, struct stat *st) { PARTITION* partition = NULL; DIR_ENTRY dirEntry; // Get the partition this file is on partition = _FAT_partition_getPartitionFromPath (path); if (partition == NULL) { r->_errno = ENODEV; return -1; } // Move the path pointer to the start of the actual path if (strchr (path, ':') != NULL) { path = strchr (path, ':') + 1; } if (strchr (path, ':') != NULL) { r->_errno = EINVAL; return -1; } _FAT_lock(&partition->lock); // Search for the file on the disc if (!_FAT_directory_entryFromPath (partition, &dirEntry, path, NULL)) { _FAT_unlock(&partition->lock); r->_errno = ENOENT; return -1; } // Fill in the stat struct _FAT_directory_entryStat (partition, &dirEntry, st); _FAT_unlock(&partition->lock); return 0; } int _FAT_link_r (struct _reent *r, const char *existing, const char *newLink) { r->_errno = ENOTSUP; return -1; } int _FAT_unlink_r (struct _reent *r, const char *path) { PARTITION* partition = NULL; DIR_ENTRY dirEntry; DIR_ENTRY dirContents; uint32_t cluster; bool nextEntry; bool errorOccured = false; // Get the partition this directory is on partition = _FAT_partition_getPartitionFromPath (path); if (partition == NULL) { r->_errno = ENODEV; return -1; } // Make sure we aren't trying to write to a read-only disc if (partition->readOnly) { r->_errno = EROFS; return -1; } // Move the path pointer to the start of the actual path if (strchr (path, ':') != NULL) { path = strchr (path, ':') + 1; } if (strchr (path, ':') != NULL) { r->_errno = EINVAL; return -1; } _FAT_lock(&partition->lock); // Search for the file on the disc if (!_FAT_directory_entryFromPath (partition, &dirEntry, path, NULL)) { _FAT_unlock(&partition->lock); r->_errno = ENOENT; return -1; } cluster = _FAT_directory_entryGetCluster (partition, dirEntry.entryData); // If this is a directory, make sure it is empty if (_FAT_directory_isDirectory (&dirEntry)) { nextEntry = _FAT_directory_getFirstEntry (partition, &dirContents, cluster); while (nextEntry) { if (!_FAT_directory_isDot (&dirContents)) { // The directory had something in it that isn't a reference to itself or it's parent _FAT_unlock(&partition->lock); r->_errno = EPERM; return -1; } nextEntry = _FAT_directory_getNextEntry (partition, &dirContents); } } if (_FAT_fat_isValidCluster(partition, cluster)) { // Remove the cluster chain for this file if (!_FAT_fat_clearLinks (partition, cluster)) { r->_errno = EIO; errorOccured = true; } } // Remove the directory entry for this file if (!_FAT_directory_removeEntry (partition, &dirEntry)) { r->_errno = EIO; errorOccured = true; } // Flush any sectors in the disc cache if (!_FAT_cache_flush(partition->cache)) { r->_errno = EIO; errorOccured = true; } _FAT_unlock(&partition->lock); if (errorOccured) { return -1; } else { return 0; } } int _FAT_chdir_r (struct _reent *r, const char *path) { PARTITION* partition = NULL; // Get the partition this directory is on partition = _FAT_partition_getPartitionFromPath (path); if (partition == NULL) { r->_errno = ENODEV; return -1; } // Move the path pointer to the start of the actual path if (strchr (path, ':') != NULL) { path = strchr (path, ':') + 1; } if (strchr (path, ':') != NULL) { r->_errno = EINVAL; return -1; } _FAT_lock(&partition->lock); // Try changing directory if (_FAT_directory_chdir (partition, path)) { // Successful _FAT_unlock(&partition->lock); return 0; } else { // Failed _FAT_unlock(&partition->lock); r->_errno = ENOTDIR; return -1; } } int _FAT_rename_r (struct _reent *r, const char *oldName, const char *newName) { PARTITION* partition = NULL; DIR_ENTRY oldDirEntry; DIR_ENTRY newDirEntry; const char *pathEnd; uint32_t dirCluster; // Get the partition this directory is on partition = _FAT_partition_getPartitionFromPath (oldName); if (partition == NULL) { r->_errno = ENODEV; return -1; } _FAT_lock(&partition->lock); // Make sure the same partition is used for the old and new names if (partition != _FAT_partition_getPartitionFromPath (newName)) { _FAT_unlock(&partition->lock); r->_errno = EXDEV; return -1; } // Make sure we aren't trying to write to a read-only disc if (partition->readOnly) { _FAT_unlock(&partition->lock); r->_errno = EROFS; return -1; } // Move the path pointer to the start of the actual path if (strchr (oldName, ':') != NULL) { oldName = strchr (oldName, ':') + 1; } if (strchr (oldName, ':') != NULL) { _FAT_unlock(&partition->lock); r->_errno = EINVAL; return -1; } if (strchr (newName, ':') != NULL) { newName = strchr (newName, ':') + 1; } if (strchr (newName, ':') != NULL) { _FAT_unlock(&partition->lock); r->_errno = EINVAL; return -1; } // Search for the file on the disc if (!_FAT_directory_entryFromPath (partition, &oldDirEntry, oldName, NULL)) { _FAT_unlock(&partition->lock); r->_errno = ENOENT; return -1; } // Make sure there is no existing file / directory with the new name if (_FAT_directory_entryFromPath (partition, &newDirEntry, newName, NULL)) { _FAT_unlock(&partition->lock); r->_errno = EEXIST; return -1; } // Create the new file entry // Get the directory it has to go in pathEnd = strrchr (newName, DIR_SEPARATOR); if (pathEnd == NULL) { // No path was specified dirCluster = partition->cwdCluster; pathEnd = newName; } else { // Path was specified -- get the right dirCluster // Recycling newDirEntry, since it needs to be recreated anyway if (!_FAT_directory_entryFromPath (partition, &newDirEntry, newName, pathEnd) || !_FAT_directory_isDirectory(&newDirEntry)) { _FAT_unlock(&partition->lock); r->_errno = ENOTDIR; return -1; } dirCluster = _FAT_directory_entryGetCluster (partition, newDirEntry.entryData); // Move the pathEnd past the last DIR_SEPARATOR pathEnd += 1; } // Copy the entry data memcpy (&newDirEntry, &oldDirEntry, sizeof(DIR_ENTRY)); // Set the new name strncpy (newDirEntry.filename, pathEnd, MAX_FILENAME_LENGTH - 1); // Write the new entry if (!_FAT_directory_addEntry (partition, &newDirEntry, dirCluster)) { _FAT_unlock(&partition->lock); r->_errno = ENOSPC; return -1; } // Remove the old entry if (!_FAT_directory_removeEntry (partition, &oldDirEntry)) { _FAT_unlock(&partition->lock); r->_errno = EIO; return -1; } // Flush any sectors in the disc cache if (!_FAT_cache_flush (partition->cache)) { _FAT_unlock(&partition->lock); r->_errno = EIO; return -1; } _FAT_unlock(&partition->lock); return 0; } int _FAT_mkdir_r (struct _reent *r, const char *path, int mode) { PARTITION* partition = NULL; bool fileExists; DIR_ENTRY dirEntry; const char* pathEnd; uint32_t parentCluster, dirCluster; uint8_t newEntryData[DIR_ENTRY_DATA_SIZE]; partition = _FAT_partition_getPartitionFromPath (path); if (partition == NULL) { r->_errno = ENODEV; return -1; } // Move the path pointer to the start of the actual path if (strchr (path, ':') != NULL) { path = strchr (path, ':') + 1; } if (strchr (path, ':') != NULL) { r->_errno = EINVAL; return -1; } _FAT_lock(&partition->lock); // Search for the file/directory on the disc fileExists = _FAT_directory_entryFromPath (partition, &dirEntry, path, NULL); // Make sure it doesn't exist if (fileExists) { _FAT_unlock(&partition->lock); r->_errno = EEXIST; return -1; } if (partition->readOnly) { // We can't write to a read-only partition _FAT_unlock(&partition->lock); r->_errno = EROFS; return -1; } // Get the directory it has to go in pathEnd = strrchr (path, DIR_SEPARATOR); if (pathEnd == NULL) { // No path was specified parentCluster = partition->cwdCluster; pathEnd = path; } else { // Path was specified -- get the right parentCluster // Recycling dirEntry, since it needs to be recreated anyway if (!_FAT_directory_entryFromPath (partition, &dirEntry, path, pathEnd) || !_FAT_directory_isDirectory(&dirEntry)) { _FAT_unlock(&partition->lock); r->_errno = ENOTDIR; return -1; } parentCluster = _FAT_directory_entryGetCluster (partition, dirEntry.entryData); // Move the pathEnd past the last DIR_SEPARATOR pathEnd += 1; } // Create the entry data strncpy (dirEntry.filename, pathEnd, MAX_FILENAME_LENGTH - 1); memset (dirEntry.entryData, 0, DIR_ENTRY_DATA_SIZE); // Set the creation time and date dirEntry.entryData[DIR_ENTRY_cTime_ms] = 0; u16_to_u8array (dirEntry.entryData, DIR_ENTRY_cTime, _FAT_filetime_getTimeFromRTC()); u16_to_u8array (dirEntry.entryData, DIR_ENTRY_cDate, _FAT_filetime_getDateFromRTC()); u16_to_u8array (dirEntry.entryData, DIR_ENTRY_mTime, _FAT_filetime_getTimeFromRTC()); u16_to_u8array (dirEntry.entryData, DIR_ENTRY_mDate, _FAT_filetime_getDateFromRTC()); u16_to_u8array (dirEntry.entryData, DIR_ENTRY_aDate, _FAT_filetime_getDateFromRTC()); // Set the directory attribute dirEntry.entryData[DIR_ENTRY_attributes] = ATTRIB_DIR; // Get a cluster for the new directory dirCluster = _FAT_fat_linkFreeClusterCleared (partition, CLUSTER_FREE); if (!_FAT_fat_isValidCluster(partition, dirCluster)) { // No space left on disc for the cluster _FAT_unlock(&partition->lock); r->_errno = ENOSPC; return -1; } u16_to_u8array (dirEntry.entryData, DIR_ENTRY_cluster, dirCluster); u16_to_u8array (dirEntry.entryData, DIR_ENTRY_clusterHigh, dirCluster >> 16); // Write the new directory's entry to it's parent if (!_FAT_directory_addEntry (partition, &dirEntry, parentCluster)) { _FAT_unlock(&partition->lock); r->_errno = ENOSPC; return -1; } // Create the dot entry within the directory memset (newEntryData, 0, DIR_ENTRY_DATA_SIZE); memset (newEntryData, ' ', 11); newEntryData[DIR_ENTRY_name] = '.'; newEntryData[DIR_ENTRY_attributes] = ATTRIB_DIR; u16_to_u8array (newEntryData, DIR_ENTRY_cluster, dirCluster); u16_to_u8array (newEntryData, DIR_ENTRY_clusterHigh, dirCluster >> 16); // Write it to the directory, erasing that sector in the process _FAT_cache_eraseWritePartialSector ( partition->cache, newEntryData, _FAT_fat_clusterToSector (partition, dirCluster), 0, DIR_ENTRY_DATA_SIZE); // Create the double dot entry within the directory // if ParentDir == Rootdir then ".."" always link to Cluster 0 if(parentCluster == partition->rootDirCluster) parentCluster = FAT16_ROOT_DIR_CLUSTER; newEntryData[DIR_ENTRY_name + 1] = '.'; u16_to_u8array (newEntryData, DIR_ENTRY_cluster, parentCluster); u16_to_u8array (newEntryData, DIR_ENTRY_clusterHigh, parentCluster >> 16); // Write it to the directory _FAT_cache_writePartialSector ( partition->cache, newEntryData, _FAT_fat_clusterToSector (partition, dirCluster), DIR_ENTRY_DATA_SIZE, DIR_ENTRY_DATA_SIZE); // Flush any sectors in the disc cache if (!_FAT_cache_flush(partition->cache)) { _FAT_unlock(&partition->lock); r->_errno = EIO; return -1; } _FAT_unlock(&partition->lock); return 0; } // //int _FAT_statvfs_r (struct _reent *r, const char *path, struct statvfs *buf) //{ // PARTITION* partition = NULL; // unsigned int freeClusterCount; // // // Get the partition of the requested path // partition = _FAT_partition_getPartitionFromPath (path); // if (partition == NULL) { // r->_errno = ENODEV; // return -1; // } // // _FAT_lock(&partition->lock); // // freeClusterCount = _FAT_fat_freeClusterCount (partition); // // // FAT clusters = POSIX blocks // buf->f_bsize = partition->bytesPerCluster; // File system block size. // buf->f_frsize = partition->bytesPerCluster; // Fundamental file system block size. // // buf->f_blocks = partition->fat.lastCluster - CLUSTER_FIRST + 1; // Total number of blocks on file system in units of f_frsize. // buf->f_bfree = freeClusterCount; // Total number of free blocks. // buf->f_bavail = freeClusterCount; // Number of free blocks available to non-privileged process. // // // Treat requests for info on inodes as clusters // buf->f_files = partition->fat.lastCluster - CLUSTER_FIRST + 1; // Total number of file serial numbers. // buf->f_ffree = freeClusterCount; // Total number of free file serial numbers. // buf->f_favail = freeClusterCount; // Number of file serial numbers available to non-privileged process. // // // File system ID. 32bit ioType value // buf->f_fsid = _FAT_disc_hostType(partition->disc); // // // Bit mask of f_flag values. // buf->f_flag = ST_NOSUID /* No support for ST_ISUID and ST_ISGID file mode bits */ // | (partition->readOnly ? ST_RDONLY /* Read only file system */ : 0 ) ; // // Maximum filename length. // buf->f_namemax = MAX_FILENAME_LENGTH; // // _FAT_unlock(&partition->lock); // return 0; //} struct DIR_ITER* _FAT_diropen_r(struct _reent *r, struct DIR_ITER *dirState, const char *path) { DIR_ENTRY dirEntry; DIR_STATE_STRUCT* state = (DIR_STATE_STRUCT*) (dirState->dirStruct); bool fileExists; state->partition = _FAT_partition_getPartitionFromPath (path); if (state->partition == NULL) { r->_errno = ENODEV; return NULL; } // Move the path pointer to the start of the actual path if (strchr (path, ':') != NULL) { path = strchr (path, ':') + 1; } if (strchr (path, ':') != NULL) { r->_errno = EINVAL; return NULL; } _FAT_lock(&state->partition->lock); // Get the start cluster of the directory fileExists = _FAT_directory_entryFromPath (state->partition, &dirEntry, path, NULL); if (!fileExists) { _FAT_unlock(&state->partition->lock); r->_errno = ENOENT; return NULL; } // Make sure it is a directory if (! _FAT_directory_isDirectory (&dirEntry)) { _FAT_unlock(&state->partition->lock); r->_errno = ENOTDIR; return NULL; } // Save the start cluster for use when resetting the directory data state->startCluster = _FAT_directory_entryGetCluster (state->partition, dirEntry.entryData); // Get the first entry for use with a call to dirnext state->validEntry = _FAT_directory_getFirstEntry (state->partition, &(state->currentEntry), state->startCluster); // We are now using this entry state->inUse = true; _FAT_unlock(&state->partition->lock); return (struct DIR_ITER*) state; } int _FAT_dirreset_r (struct _reent *r, struct DIR_ITER *dirState) { DIR_STATE_STRUCT* state = (DIR_STATE_STRUCT*) (dirState->dirStruct); _FAT_lock(&state->partition->lock); // Make sure we are still using this entry if (!state->inUse) { _FAT_unlock(&state->partition->lock); r->_errno = EBADF; return -1; } // Get the first entry for use with a call to dirnext state->validEntry = _FAT_directory_getFirstEntry (state->partition, &(state->currentEntry), state->startCluster); _FAT_unlock(&state->partition->lock); return 0; } int _FAT_dirnext_r (struct _reent *r, struct DIR_ITER *dirState, char *filename, struct stat *filestat) { DIR_STATE_STRUCT* state = (DIR_STATE_STRUCT*) (dirState->dirStruct); _FAT_lock(&state->partition->lock); // Make sure we are still using this entry if (!state->inUse) { _FAT_unlock(&state->partition->lock); r->_errno = EBADF; return -1; } // Make sure there is another file to report on if (! state->validEntry) { _FAT_unlock(&state->partition->lock); r->_errno = ENOENT; return -1; } // Get the filename strncpy (filename, state->currentEntry.filename, MAX_FILENAME_LENGTH); // Get the stats, if requested if (filestat != NULL) { _FAT_directory_entryStat (state->partition, &(state->currentEntry), filestat); } // Look for the next entry for use next time state->validEntry = _FAT_directory_getNextEntry (state->partition, &(state->currentEntry)); _FAT_unlock(&state->partition->lock); return 0; } int _FAT_dirclose_r (struct _reent *r, struct DIR_ITER *dirState) { DIR_STATE_STRUCT* state = (DIR_STATE_STRUCT*) (dirState->dirStruct); // We are no longer using this entry _FAT_lock(&state->partition->lock); state->inUse = false; _FAT_unlock(&state->partition->lock); return 0; } desmume/src/utils/libfat/fatdir.h000664 001750 001750 00000005546 12755534123 020174 0ustar00sergiosergio000000 000000 /* fatdir.h Functions used by the newlib disc stubs to interface with this library Copyright (c) 2006 Michael "Chishm" Chisholm Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. 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. 3. The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. */ #ifndef _FATDIR_H #define _FATDIR_H #include #include #include "common.h" #include "directory.h" #ifndef LIBFAT_PC #include #include #include #endif #ifdef __cplusplus extern "C" { #endif typedef struct { PARTITION* partition; DIR_ENTRY currentEntry; uint32_t startCluster; bool inUse; bool validEntry; } DIR_STATE_STRUCT; extern int _FAT_stat_r (struct _reent *r, const char *path, struct stat *st); extern int _FAT_link_r (struct _reent *r, const char *existing, const char *newLink); extern int _FAT_unlink_r (struct _reent *r, const char *name); extern int _FAT_chdir_r (struct _reent *r, const char *name); extern int _FAT_rename_r (struct _reent *r, const char *oldName, const char *newName); extern int _FAT_mkdir_r (struct _reent *r, const char *path, int mode); extern int _FAT_statvfs_r (struct _reent *r, const char *path, struct statvfs *buf); /* Directory iterator functions */ extern struct DIR_ITER* _FAT_diropen_r(struct _reent *r, struct DIR_ITER *dirState, const char *path); extern int _FAT_dirreset_r (struct _reent *r, struct DIR_ITER *dirState); extern int _FAT_dirnext_r (struct _reent *r, struct DIR_ITER *dirState, char *filename, struct stat *filestat); extern int _FAT_dirclose_r (struct _reent *r, struct DIR_ITER *dirState); #ifdef __cplusplus } #endif #endif // _FATDIR_H desmume/src/libretro-common/queues/message_queue.c000664 001750 001750 00000014177 12755534123 023564 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2016 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (message_queue.c). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include #include #include #include #include #include struct queue_elem { unsigned duration; unsigned prio; char *msg; }; struct msg_queue { struct queue_elem **elems; size_t ptr; size_t size; char *tmp_msg; }; /** * msg_queue_new: * @size : maximum size of message * * Creates a message queue with maximum size different messages. * * Returns: NULL if allocation error, pointer to a message queue * if successful. Has to be freed manually. **/ msg_queue_t *msg_queue_new(size_t size) { msg_queue_t *queue = (msg_queue_t*)calloc(1, sizeof(*queue)); if (!queue) return NULL; queue->size = size + 1; queue->elems = (struct queue_elem**) calloc(queue->size,sizeof(struct queue_elem*)); if (!queue->elems) { free(queue); return NULL; } queue->ptr = 1; return queue; } /** * msg_queue_free: * @queue : pointer to queue object * * Frees message queue.. **/ void msg_queue_free(msg_queue_t *queue) { if (queue) { msg_queue_clear(queue); free(queue->elems); } free(queue); } /** * msg_queue_push: * @queue : pointer to queue object * @msg : message to add to the queue * @prio : priority level of the message * @duration : how many times the message can be pulled * before it vanishes (E.g. show a message for * 3 seconds @ 60fps = 180 duration). * * Push a new message onto the queue. **/ void msg_queue_push(msg_queue_t *queue, const char *msg, unsigned prio, unsigned duration) { size_t tmp_ptr = 0; struct queue_elem *new_elem = NULL; if (!queue || queue->ptr >= queue->size) return; new_elem = (struct queue_elem*) calloc(1, sizeof(struct queue_elem)); if (!new_elem) return; new_elem->prio = prio; new_elem->duration = duration; new_elem->msg = msg ? strdup(msg) : NULL; queue->elems[queue->ptr] = new_elem; tmp_ptr = queue->ptr++; while (tmp_ptr > 1) { struct queue_elem *parent = queue->elems[tmp_ptr >> 1]; struct queue_elem *child = queue->elems[tmp_ptr]; if (child->prio <= parent->prio) break; queue->elems[tmp_ptr >> 1] = child; queue->elems[tmp_ptr] = parent; tmp_ptr >>= 1; } } /** * msg_queue_clear: * @queue : pointer to queue object * * Clears out everything in the queue. **/ void msg_queue_clear(msg_queue_t *queue) { size_t i; if (!queue) return; for (i = 1; i < queue->ptr; i++) { if (queue->elems[i]) { free(queue->elems[i]->msg); free(queue->elems[i]); queue->elems[i] = NULL; } } queue->ptr = 1; free(queue->tmp_msg); queue->tmp_msg = NULL; } /** * msg_queue_pull: * @queue : pointer to queue object * * Pulls highest priority message in queue. * * Returns: NULL if no message in queue, otherwise a string * containing the message. **/ const char *msg_queue_pull(msg_queue_t *queue) { struct queue_elem *front = NULL, *last = NULL; size_t tmp_ptr = 1; (void)tmp_ptr; /* Nothing in queue. */ if (!queue || queue->ptr == 1) return NULL; front = (struct queue_elem*)queue->elems[1]; front->duration--; if (front->duration > 0) return front->msg; free(queue->tmp_msg); queue->tmp_msg = front->msg; front->msg = NULL; front = (struct queue_elem*)queue->elems[1]; last = (struct queue_elem*)queue->elems[--queue->ptr]; queue->elems[1] = last; free(front); for (;;) { struct queue_elem *parent = NULL; struct queue_elem *child = NULL; size_t switch_index = tmp_ptr; bool left = (tmp_ptr * 2 <= queue->ptr) && (queue->elems[tmp_ptr] < queue->elems[tmp_ptr * 2]); bool right = (tmp_ptr * 2 + 1 <= queue->ptr) && (queue->elems[tmp_ptr] < queue->elems[tmp_ptr * 2 + 1]); if (!left && !right) break; if (left && !right) switch_index <<= 1; else if (right && !left) switch_index += switch_index + 1; else { if (queue->elems[tmp_ptr * 2] >= queue->elems[tmp_ptr * 2 + 1]) switch_index <<= 1; else switch_index += switch_index + 1; } parent = (struct queue_elem*)queue->elems[tmp_ptr]; child = (struct queue_elem*)queue->elems[switch_index]; queue->elems[tmp_ptr] = child; queue->elems[switch_index] = parent; tmp_ptr = switch_index; } return queue->tmp_msg; } desmume/src/thumb_tabdef.inc000664 001750 001750 00000164776 12755534123 017303 0ustar00sergiosergio000000 000000 /* Copyright (C) 2006 yopyop Copyright (C) 2007-2012 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the this software. If not, see . */ /* 00 0000 0000 */ TABDECL(OP_LSL_0), // OP_LSL_0 /* 00 0000 0001 */ TABDECL(OP_LSL), // OP_LSL /* 00 0000 0010 */ TABDECL(OP_LSL), // OP_LSL /* 00 0000 0011 */ TABDECL(OP_LSL), // OP_LSL /* 00 0000 0100 */ TABDECL(OP_LSL), // OP_LSL /* 00 0000 0101 */ TABDECL(OP_LSL), // OP_LSL /* 00 0000 0110 */ TABDECL(OP_LSL), // OP_LSL /* 00 0000 0111 */ TABDECL(OP_LSL), // OP_LSL /* 00 0000 1000 */ TABDECL(OP_LSL), // OP_LSL /* 00 0000 1001 */ TABDECL(OP_LSL), // OP_LSL /* 00 0000 1010 */ TABDECL(OP_LSL), // OP_LSL /* 00 0000 1011 */ TABDECL(OP_LSL), // OP_LSL /* 00 0000 1100 */ TABDECL(OP_LSL), // OP_LSL /* 00 0000 1101 */ TABDECL(OP_LSL), // OP_LSL /* 00 0000 1110 */ TABDECL(OP_LSL), // OP_LSL /* 00 0000 1111 */ TABDECL(OP_LSL), // OP_LSL /* 00 0001 0000 */ TABDECL(OP_LSL), // OP_LSL /* 00 0001 0001 */ TABDECL(OP_LSL), // OP_LSL /* 00 0001 0010 */ TABDECL(OP_LSL), // OP_LSL /* 00 0001 0011 */ TABDECL(OP_LSL), // OP_LSL /* 00 0001 0100 */ TABDECL(OP_LSL), // OP_LSL /* 00 0001 0101 */ TABDECL(OP_LSL), // OP_LSL /* 00 0001 0110 */ TABDECL(OP_LSL), // OP_LSL /* 00 0001 0111 */ TABDECL(OP_LSL), // OP_LSL /* 00 0001 1000 */ TABDECL(OP_LSL), // OP_LSL /* 00 0001 1001 */ TABDECL(OP_LSL), // OP_LSL /* 00 0001 1010 */ TABDECL(OP_LSL), // OP_LSL /* 00 0001 1011 */ TABDECL(OP_LSL), // OP_LSL /* 00 0001 1100 */ TABDECL(OP_LSL), // OP_LSL /* 00 0001 1101 */ TABDECL(OP_LSL), // OP_LSL /* 00 0001 1110 */ TABDECL(OP_LSL), // OP_LSL /* 00 0001 1111 */ TABDECL(OP_LSL), // OP_LSL /* 00 0010 0000 */ TABDECL(OP_LSR_0), // OP_LSR_0 /* 00 0010 0001 */ TABDECL(OP_LSR), // OP_LSR /* 00 0010 0010 */ TABDECL(OP_LSR), // OP_LSR /* 00 0010 0011 */ TABDECL(OP_LSR), // OP_LSR /* 00 0010 0100 */ TABDECL(OP_LSR), // OP_LSR /* 00 0010 0101 */ TABDECL(OP_LSR), // OP_LSR /* 00 0010 0110 */ TABDECL(OP_LSR), // OP_LSR /* 00 0010 0111 */ TABDECL(OP_LSR), // OP_LSR /* 00 0010 1000 */ TABDECL(OP_LSR), // OP_LSR /* 00 0010 1001 */ TABDECL(OP_LSR), // OP_LSR /* 00 0010 1010 */ TABDECL(OP_LSR), // OP_LSR /* 00 0010 1011 */ TABDECL(OP_LSR), // OP_LSR /* 00 0010 1100 */ TABDECL(OP_LSR), // OP_LSR /* 00 0010 1101 */ TABDECL(OP_LSR), // OP_LSR /* 00 0010 1110 */ TABDECL(OP_LSR), // OP_LSR /* 00 0010 1111 */ TABDECL(OP_LSR), // OP_LSR /* 00 0011 0000 */ TABDECL(OP_LSR), // OP_LSR /* 00 0011 0001 */ TABDECL(OP_LSR), // OP_LSR /* 00 0011 0010 */ TABDECL(OP_LSR), // OP_LSR /* 00 0011 0011 */ TABDECL(OP_LSR), // OP_LSR /* 00 0011 0100 */ TABDECL(OP_LSR), // OP_LSR /* 00 0011 0101 */ TABDECL(OP_LSR), // OP_LSR /* 00 0011 0110 */ TABDECL(OP_LSR), // OP_LSR /* 00 0011 0111 */ TABDECL(OP_LSR), // OP_LSR /* 00 0011 1000 */ TABDECL(OP_LSR), // OP_LSR /* 00 0011 1001 */ TABDECL(OP_LSR), // OP_LSR /* 00 0011 1010 */ TABDECL(OP_LSR), // OP_LSR /* 00 0011 1011 */ TABDECL(OP_LSR), // OP_LSR /* 00 0011 1100 */ TABDECL(OP_LSR), // OP_LSR /* 00 0011 1101 */ TABDECL(OP_LSR), // OP_LSR /* 00 0011 1110 */ TABDECL(OP_LSR), // OP_LSR /* 00 0011 1111 */ TABDECL(OP_LSR), // OP_LSR /* 00 0100 0000 */ TABDECL(OP_ASR_0), // OP_ASR_0 /* 00 0100 0001 */ TABDECL(OP_ASR), // OP_ASR /* 00 0100 0010 */ TABDECL(OP_ASR), // OP_ASR /* 00 0100 0011 */ TABDECL(OP_ASR), // OP_ASR /* 00 0100 0100 */ TABDECL(OP_ASR), // OP_ASR /* 00 0100 0101 */ TABDECL(OP_ASR), // OP_ASR /* 00 0100 0110 */ TABDECL(OP_ASR), // OP_ASR /* 00 0100 0111 */ TABDECL(OP_ASR), // OP_ASR /* 00 0100 1000 */ TABDECL(OP_ASR), // OP_ASR /* 00 0100 1001 */ TABDECL(OP_ASR), // OP_ASR /* 00 0100 1010 */ TABDECL(OP_ASR), // OP_ASR /* 00 0100 1011 */ TABDECL(OP_ASR), // OP_ASR /* 00 0100 1100 */ TABDECL(OP_ASR), // OP_ASR /* 00 0100 1101 */ TABDECL(OP_ASR), // OP_ASR /* 00 0100 1110 */ TABDECL(OP_ASR), // OP_ASR /* 00 0100 1111 */ TABDECL(OP_ASR), // OP_ASR /* 00 0101 0000 */ TABDECL(OP_ASR), // OP_ASR /* 00 0101 0001 */ TABDECL(OP_ASR), // OP_ASR /* 00 0101 0010 */ TABDECL(OP_ASR), // OP_ASR /* 00 0101 0011 */ TABDECL(OP_ASR), // OP_ASR /* 00 0101 0100 */ TABDECL(OP_ASR), // OP_ASR /* 00 0101 0101 */ TABDECL(OP_ASR), // OP_ASR /* 00 0101 0110 */ TABDECL(OP_ASR), // OP_ASR /* 00 0101 0111 */ TABDECL(OP_ASR), // OP_ASR /* 00 0101 1000 */ TABDECL(OP_ASR), // OP_ASR /* 00 0101 1001 */ TABDECL(OP_ASR), // OP_ASR /* 00 0101 1010 */ TABDECL(OP_ASR), // OP_ASR /* 00 0101 1011 */ TABDECL(OP_ASR), // OP_ASR /* 00 0101 1100 */ TABDECL(OP_ASR), // OP_ASR /* 00 0101 1101 */ TABDECL(OP_ASR), // OP_ASR /* 00 0101 1110 */ TABDECL(OP_ASR), // OP_ASR /* 00 0101 1111 */ TABDECL(OP_ASR), // OP_ASR /* 00 0110 0000 */ TABDECL(OP_ADD_REG), // OP_ADD_REG /* 00 0110 0001 */ TABDECL(OP_ADD_REG), // OP_ADD_REG /* 00 0110 0010 */ TABDECL(OP_ADD_REG), // OP_ADD_REG /* 00 0110 0011 */ TABDECL(OP_ADD_REG), // OP_ADD_REG /* 00 0110 0100 */ TABDECL(OP_ADD_REG), // OP_ADD_REG /* 00 0110 0101 */ TABDECL(OP_ADD_REG), // OP_ADD_REG /* 00 0110 0110 */ TABDECL(OP_ADD_REG), // OP_ADD_REG /* 00 0110 0111 */ TABDECL(OP_ADD_REG), // OP_ADD_REG /* 00 0110 1000 */ TABDECL(OP_SUB_REG), // OP_SUB_REG /* 00 0110 1001 */ TABDECL(OP_SUB_REG), // OP_SUB_REG /* 00 0110 1010 */ TABDECL(OP_SUB_REG), // OP_SUB_REG /* 00 0110 1011 */ TABDECL(OP_SUB_REG), // OP_SUB_REG /* 00 0110 1100 */ TABDECL(OP_SUB_REG), // OP_SUB_REG /* 00 0110 1101 */ TABDECL(OP_SUB_REG), // OP_SUB_REG /* 00 0110 1110 */ TABDECL(OP_SUB_REG), // OP_SUB_REG /* 00 0110 1111 */ TABDECL(OP_SUB_REG), // OP_SUB_REG /* 00 0111 0000 */ TABDECL(OP_ADD_IMM3), // OP_ADD_IMM3 /* 00 0111 0001 */ TABDECL(OP_ADD_IMM3), // OP_ADD_IMM3 /* 00 0111 0010 */ TABDECL(OP_ADD_IMM3), // OP_ADD_IMM3 /* 00 0111 0011 */ TABDECL(OP_ADD_IMM3), // OP_ADD_IMM3 /* 00 0111 0100 */ TABDECL(OP_ADD_IMM3), // OP_ADD_IMM3 /* 00 0111 0101 */ TABDECL(OP_ADD_IMM3), // OP_ADD_IMM3 /* 00 0111 0110 */ TABDECL(OP_ADD_IMM3), // OP_ADD_IMM3 /* 00 0111 0111 */ TABDECL(OP_ADD_IMM3), // OP_ADD_IMM3 /* 00 0111 1000 */ TABDECL(OP_SUB_IMM3), // OP_SUB_IMM3 /* 00 0111 1001 */ TABDECL(OP_SUB_IMM3), // OP_SUB_IMM3 /* 00 0111 1010 */ TABDECL(OP_SUB_IMM3), // OP_SUB_IMM3 /* 00 0111 1011 */ TABDECL(OP_SUB_IMM3), // OP_SUB_IMM3 /* 00 0111 1100 */ TABDECL(OP_SUB_IMM3), // OP_SUB_IMM3 /* 00 0111 1101 */ TABDECL(OP_SUB_IMM3), // OP_SUB_IMM3 /* 00 0111 1110 */ TABDECL(OP_SUB_IMM3), // OP_SUB_IMM3 /* 00 0111 1111 */ TABDECL(OP_SUB_IMM3), // OP_SUB_IMM3 /* 00 1000 0000 */ TABDECL(OP_MOV_IMM8), // OP_MOV_IMM8 /* 00 1000 0001 */ TABDECL(OP_MOV_IMM8), // OP_MOV_IMM8 /* 00 1000 0010 */ TABDECL(OP_MOV_IMM8), // OP_MOV_IMM8 /* 00 1000 0011 */ TABDECL(OP_MOV_IMM8), // OP_MOV_IMM8 /* 00 1000 0100 */ TABDECL(OP_MOV_IMM8), // OP_MOV_IMM8 /* 00 1000 0101 */ TABDECL(OP_MOV_IMM8), // OP_MOV_IMM8 /* 00 1000 0110 */ TABDECL(OP_MOV_IMM8), // OP_MOV_IMM8 /* 00 1000 0111 */ TABDECL(OP_MOV_IMM8), // OP_MOV_IMM8 /* 00 1000 1000 */ TABDECL(OP_MOV_IMM8), // OP_MOV_IMM8 /* 00 1000 1001 */ TABDECL(OP_MOV_IMM8), // OP_MOV_IMM8 /* 00 1000 1010 */ TABDECL(OP_MOV_IMM8), // OP_MOV_IMM8 /* 00 1000 1011 */ TABDECL(OP_MOV_IMM8), // OP_MOV_IMM8 /* 00 1000 1100 */ TABDECL(OP_MOV_IMM8), // OP_MOV_IMM8 /* 00 1000 1101 */ TABDECL(OP_MOV_IMM8), // OP_MOV_IMM8 /* 00 1000 1110 */ TABDECL(OP_MOV_IMM8), // OP_MOV_IMM8 /* 00 1000 1111 */ TABDECL(OP_MOV_IMM8), // OP_MOV_IMM8 /* 00 1001 0000 */ TABDECL(OP_MOV_IMM8), // OP_MOV_IMM8 /* 00 1001 0001 */ TABDECL(OP_MOV_IMM8), // OP_MOV_IMM8 /* 00 1001 0010 */ TABDECL(OP_MOV_IMM8), // OP_MOV_IMM8 /* 00 1001 0011 */ TABDECL(OP_MOV_IMM8), // OP_MOV_IMM8 /* 00 1001 0100 */ TABDECL(OP_MOV_IMM8), // OP_MOV_IMM8 /* 00 1001 0101 */ TABDECL(OP_MOV_IMM8), // OP_MOV_IMM8 /* 00 1001 0110 */ TABDECL(OP_MOV_IMM8), // OP_MOV_IMM8 /* 00 1001 0111 */ TABDECL(OP_MOV_IMM8), // OP_MOV_IMM8 /* 00 1001 1000 */ TABDECL(OP_MOV_IMM8), // OP_MOV_IMM8 /* 00 1001 1001 */ TABDECL(OP_MOV_IMM8), // OP_MOV_IMM8 /* 00 1001 1010 */ TABDECL(OP_MOV_IMM8), // OP_MOV_IMM8 /* 00 1001 1011 */ TABDECL(OP_MOV_IMM8), // OP_MOV_IMM8 /* 00 1001 1100 */ TABDECL(OP_MOV_IMM8), // OP_MOV_IMM8 /* 00 1001 1101 */ TABDECL(OP_MOV_IMM8), // OP_MOV_IMM8 /* 00 1001 1110 */ TABDECL(OP_MOV_IMM8), // OP_MOV_IMM8 /* 00 1001 1111 */ TABDECL(OP_MOV_IMM8), // OP_MOV_IMM8 /* 00 1010 0000 */ TABDECL(OP_CMP_IMM8), // OP_CMP_IMM8 /* 00 1010 0001 */ TABDECL(OP_CMP_IMM8), // OP_CMP_IMM8 /* 00 1010 0010 */ TABDECL(OP_CMP_IMM8), // OP_CMP_IMM8 /* 00 1010 0011 */ TABDECL(OP_CMP_IMM8), // OP_CMP_IMM8 /* 00 1010 0100 */ TABDECL(OP_CMP_IMM8), // OP_CMP_IMM8 /* 00 1010 0101 */ TABDECL(OP_CMP_IMM8), // OP_CMP_IMM8 /* 00 1010 0110 */ TABDECL(OP_CMP_IMM8), // OP_CMP_IMM8 /* 00 1010 0111 */ TABDECL(OP_CMP_IMM8), // OP_CMP_IMM8 /* 00 1010 1000 */ TABDECL(OP_CMP_IMM8), // OP_CMP_IMM8 /* 00 1010 1001 */ TABDECL(OP_CMP_IMM8), // OP_CMP_IMM8 /* 00 1010 1010 */ TABDECL(OP_CMP_IMM8), // OP_CMP_IMM8 /* 00 1010 1011 */ TABDECL(OP_CMP_IMM8), // OP_CMP_IMM8 /* 00 1010 1100 */ TABDECL(OP_CMP_IMM8), // OP_CMP_IMM8 /* 00 1010 1101 */ TABDECL(OP_CMP_IMM8), // OP_CMP_IMM8 /* 00 1010 1110 */ TABDECL(OP_CMP_IMM8), // OP_CMP_IMM8 /* 00 1010 1111 */ TABDECL(OP_CMP_IMM8), // OP_CMP_IMM8 /* 00 1011 0000 */ TABDECL(OP_CMP_IMM8), // OP_CMP_IMM8 /* 00 1011 0001 */ TABDECL(OP_CMP_IMM8), // OP_CMP_IMM8 /* 00 1011 0010 */ TABDECL(OP_CMP_IMM8), // OP_CMP_IMM8 /* 00 1011 0011 */ TABDECL(OP_CMP_IMM8), // OP_CMP_IMM8 /* 00 1011 0100 */ TABDECL(OP_CMP_IMM8), // OP_CMP_IMM8 /* 00 1011 0101 */ TABDECL(OP_CMP_IMM8), // OP_CMP_IMM8 /* 00 1011 0110 */ TABDECL(OP_CMP_IMM8), // OP_CMP_IMM8 /* 00 1011 0111 */ TABDECL(OP_CMP_IMM8), // OP_CMP_IMM8 /* 00 1011 1000 */ TABDECL(OP_CMP_IMM8), // OP_CMP_IMM8 /* 00 1011 1001 */ TABDECL(OP_CMP_IMM8), // OP_CMP_IMM8 /* 00 1011 1010 */ TABDECL(OP_CMP_IMM8), // OP_CMP_IMM8 /* 00 1011 1011 */ TABDECL(OP_CMP_IMM8), // OP_CMP_IMM8 /* 00 1011 1100 */ TABDECL(OP_CMP_IMM8), // OP_CMP_IMM8 /* 00 1011 1101 */ TABDECL(OP_CMP_IMM8), // OP_CMP_IMM8 /* 00 1011 1110 */ TABDECL(OP_CMP_IMM8), // OP_CMP_IMM8 /* 00 1011 1111 */ TABDECL(OP_CMP_IMM8), // OP_CMP_IMM8 /* 00 1100 0000 */ TABDECL(OP_ADD_IMM8), // OP_ADD_IMM8 /* 00 1100 0001 */ TABDECL(OP_ADD_IMM8), // OP_ADD_IMM8 /* 00 1100 0010 */ TABDECL(OP_ADD_IMM8), // OP_ADD_IMM8 /* 00 1100 0011 */ TABDECL(OP_ADD_IMM8), // OP_ADD_IMM8 /* 00 1100 0100 */ TABDECL(OP_ADD_IMM8), // OP_ADD_IMM8 /* 00 1100 0101 */ TABDECL(OP_ADD_IMM8), // OP_ADD_IMM8 /* 00 1100 0110 */ TABDECL(OP_ADD_IMM8), // OP_ADD_IMM8 /* 00 1100 0111 */ TABDECL(OP_ADD_IMM8), // OP_ADD_IMM8 /* 00 1100 1000 */ TABDECL(OP_ADD_IMM8), // OP_ADD_IMM8 /* 00 1100 1001 */ TABDECL(OP_ADD_IMM8), // OP_ADD_IMM8 /* 00 1100 1010 */ TABDECL(OP_ADD_IMM8), // OP_ADD_IMM8 /* 00 1100 1011 */ TABDECL(OP_ADD_IMM8), // OP_ADD_IMM8 /* 00 1100 1100 */ TABDECL(OP_ADD_IMM8), // OP_ADD_IMM8 /* 00 1100 1101 */ TABDECL(OP_ADD_IMM8), // OP_ADD_IMM8 /* 00 1100 1110 */ TABDECL(OP_ADD_IMM8), // OP_ADD_IMM8 /* 00 1100 1111 */ TABDECL(OP_ADD_IMM8), // OP_ADD_IMM8 /* 00 1101 0000 */ TABDECL(OP_ADD_IMM8), // OP_ADD_IMM8 /* 00 1101 0001 */ TABDECL(OP_ADD_IMM8), // OP_ADD_IMM8 /* 00 1101 0010 */ TABDECL(OP_ADD_IMM8), // OP_ADD_IMM8 /* 00 1101 0011 */ TABDECL(OP_ADD_IMM8), // OP_ADD_IMM8 /* 00 1101 0100 */ TABDECL(OP_ADD_IMM8), // OP_ADD_IMM8 /* 00 1101 0101 */ TABDECL(OP_ADD_IMM8), // OP_ADD_IMM8 /* 00 1101 0110 */ TABDECL(OP_ADD_IMM8), // OP_ADD_IMM8 /* 00 1101 0111 */ TABDECL(OP_ADD_IMM8), // OP_ADD_IMM8 /* 00 1101 1000 */ TABDECL(OP_ADD_IMM8), // OP_ADD_IMM8 /* 00 1101 1001 */ TABDECL(OP_ADD_IMM8), // OP_ADD_IMM8 /* 00 1101 1010 */ TABDECL(OP_ADD_IMM8), // OP_ADD_IMM8 /* 00 1101 1011 */ TABDECL(OP_ADD_IMM8), // OP_ADD_IMM8 /* 00 1101 1100 */ TABDECL(OP_ADD_IMM8), // OP_ADD_IMM8 /* 00 1101 1101 */ TABDECL(OP_ADD_IMM8), // OP_ADD_IMM8 /* 00 1101 1110 */ TABDECL(OP_ADD_IMM8), // OP_ADD_IMM8 /* 00 1101 1111 */ TABDECL(OP_ADD_IMM8), // OP_ADD_IMM8 /* 00 1110 0000 */ TABDECL(OP_SUB_IMM8), // OP_SUB_IMM8 /* 00 1110 0001 */ TABDECL(OP_SUB_IMM8), // OP_SUB_IMM8 /* 00 1110 0010 */ TABDECL(OP_SUB_IMM8), // OP_SUB_IMM8 /* 00 1110 0011 */ TABDECL(OP_SUB_IMM8), // OP_SUB_IMM8 /* 00 1110 0100 */ TABDECL(OP_SUB_IMM8), // OP_SUB_IMM8 /* 00 1110 0101 */ TABDECL(OP_SUB_IMM8), // OP_SUB_IMM8 /* 00 1110 0110 */ TABDECL(OP_SUB_IMM8), // OP_SUB_IMM8 /* 00 1110 0111 */ TABDECL(OP_SUB_IMM8), // OP_SUB_IMM8 /* 00 1110 1000 */ TABDECL(OP_SUB_IMM8), // OP_SUB_IMM8 /* 00 1110 1001 */ TABDECL(OP_SUB_IMM8), // OP_SUB_IMM8 /* 00 1110 1010 */ TABDECL(OP_SUB_IMM8), // OP_SUB_IMM8 /* 00 1110 1011 */ TABDECL(OP_SUB_IMM8), // OP_SUB_IMM8 /* 00 1110 1100 */ TABDECL(OP_SUB_IMM8), // OP_SUB_IMM8 /* 00 1110 1101 */ TABDECL(OP_SUB_IMM8), // OP_SUB_IMM8 /* 00 1110 1110 */ TABDECL(OP_SUB_IMM8), // OP_SUB_IMM8 /* 00 1110 1111 */ TABDECL(OP_SUB_IMM8), // OP_SUB_IMM8 /* 00 1111 0000 */ TABDECL(OP_SUB_IMM8), // OP_SUB_IMM8 /* 00 1111 0001 */ TABDECL(OP_SUB_IMM8), // OP_SUB_IMM8 /* 00 1111 0010 */ TABDECL(OP_SUB_IMM8), // OP_SUB_IMM8 /* 00 1111 0011 */ TABDECL(OP_SUB_IMM8), // OP_SUB_IMM8 /* 00 1111 0100 */ TABDECL(OP_SUB_IMM8), // OP_SUB_IMM8 /* 00 1111 0101 */ TABDECL(OP_SUB_IMM8), // OP_SUB_IMM8 /* 00 1111 0110 */ TABDECL(OP_SUB_IMM8), // OP_SUB_IMM8 /* 00 1111 0111 */ TABDECL(OP_SUB_IMM8), // OP_SUB_IMM8 /* 00 1111 1000 */ TABDECL(OP_SUB_IMM8), // OP_SUB_IMM8 /* 00 1111 1001 */ TABDECL(OP_SUB_IMM8), // OP_SUB_IMM8 /* 00 1111 1010 */ TABDECL(OP_SUB_IMM8), // OP_SUB_IMM8 /* 00 1111 1011 */ TABDECL(OP_SUB_IMM8), // OP_SUB_IMM8 /* 00 1111 1100 */ TABDECL(OP_SUB_IMM8), // OP_SUB_IMM8 /* 00 1111 1101 */ TABDECL(OP_SUB_IMM8), // OP_SUB_IMM8 /* 00 1111 1110 */ TABDECL(OP_SUB_IMM8), // OP_SUB_IMM8 /* 00 1111 1111 */ TABDECL(OP_SUB_IMM8), // OP_SUB_IMM8 /* 01 0000 0000 */ TABDECL(OP_AND), // OP_AND /* 01 0000 0001 */ TABDECL(OP_EOR), // OP_EOR /* 01 0000 0010 */ TABDECL(OP_LSL_REG), // OP_LSL_REG /* 01 0000 0011 */ TABDECL(OP_LSR_REG), // OP_LSR_REG /* 01 0000 0100 */ TABDECL(OP_ASR_REG), // OP_ASR_REG /* 01 0000 0101 */ TABDECL(OP_ADC_REG), // OP_ADC_REG /* 01 0000 0110 */ TABDECL(OP_SBC_REG), // OP_SBC_REG /* 01 0000 0111 */ TABDECL(OP_ROR_REG), // OP_ROR_REG /* 01 0000 1000 */ TABDECL(OP_TST), // OP_TST /* 01 0000 1001 */ TABDECL(OP_NEG), // OP_NEG /* 01 0000 1010 */ TABDECL(OP_CMP), // OP_CMP /* 01 0000 1011 */ TABDECL(OP_CMN), // OP_CMN /* 01 0000 1100 */ TABDECL(OP_ORR), // OP_ORR /* 01 0000 1101 */ TABDECL(OP_MUL_REG), // OP_MUL_REG /* 01 0000 1110 */ TABDECL(OP_BIC), // OP_BIC /* 01 0000 1111 */ TABDECL(OP_MVN), // OP_MVN /* 01 0001 0000 */ TABDECL(OP_ADD_SPE), // OP_ADD_SPE /* 01 0001 0001 */ TABDECL(OP_ADD_SPE), // OP_ADD_SPE /* 01 0001 0010 */ TABDECL(OP_ADD_SPE), // OP_ADD_SPE /* 01 0001 0011 */ TABDECL(OP_ADD_SPE), // OP_ADD_SPE /* 01 0001 0100 */ TABDECL(OP_CMP_SPE), // OP_CMP_SPE /* 01 0001 0101 */ TABDECL(OP_CMP_SPE), // OP_CMP_SPE /* 01 0001 0110 */ TABDECL(OP_CMP_SPE), // OP_CMP_SPE /* 01 0001 0111 */ TABDECL(OP_CMP_SPE), // OP_CMP_SPE /* 01 0001 1000 */ TABDECL(OP_MOV_SPE), // OP_MOV_SPE /* 01 0001 1001 */ TABDECL(OP_MOV_SPE), // OP_MOV_SPE /* 01 0001 1010 */ TABDECL(OP_MOV_SPE), // OP_MOV_SPE /* 01 0001 1011 */ TABDECL(OP_MOV_SPE), // OP_MOV_SPE /* 01 0001 1100 */ TABDECL(OP_BX_THUMB), // OP_BX_THUMB /* 01 0001 1101 */ TABDECL(OP_BX_THUMB), // OP_BX_THUMB /* 01 0001 1110 */ TABDECL(OP_BLX_THUMB), // OP_BLX_THUMB /* 01 0001 1111 */ TABDECL(OP_BLX_THUMB), // OP_BLX_THUMB /* 01 0010 0000 */ TABDECL(OP_LDR_PCREL), // OP_LDR_PCREL /* 01 0010 0001 */ TABDECL(OP_LDR_PCREL), // OP_LDR_PCREL /* 01 0010 0010 */ TABDECL(OP_LDR_PCREL), // OP_LDR_PCREL /* 01 0010 0011 */ TABDECL(OP_LDR_PCREL), // OP_LDR_PCREL /* 01 0010 0100 */ TABDECL(OP_LDR_PCREL), // OP_LDR_PCREL /* 01 0010 0101 */ TABDECL(OP_LDR_PCREL), // OP_LDR_PCREL /* 01 0010 0110 */ TABDECL(OP_LDR_PCREL), // OP_LDR_PCREL /* 01 0010 0111 */ TABDECL(OP_LDR_PCREL), // OP_LDR_PCREL /* 01 0010 1000 */ TABDECL(OP_LDR_PCREL), // OP_LDR_PCREL /* 01 0010 1001 */ TABDECL(OP_LDR_PCREL), // OP_LDR_PCREL /* 01 0010 1010 */ TABDECL(OP_LDR_PCREL), // OP_LDR_PCREL /* 01 0010 1011 */ TABDECL(OP_LDR_PCREL), // OP_LDR_PCREL /* 01 0010 1100 */ TABDECL(OP_LDR_PCREL), // OP_LDR_PCREL /* 01 0010 1101 */ TABDECL(OP_LDR_PCREL), // OP_LDR_PCREL /* 01 0010 1110 */ TABDECL(OP_LDR_PCREL), // OP_LDR_PCREL /* 01 0010 1111 */ TABDECL(OP_LDR_PCREL), // OP_LDR_PCREL /* 01 0011 0000 */ TABDECL(OP_LDR_PCREL), // OP_LDR_PCREL /* 01 0011 0001 */ TABDECL(OP_LDR_PCREL), // OP_LDR_PCREL /* 01 0011 0010 */ TABDECL(OP_LDR_PCREL), // OP_LDR_PCREL /* 01 0011 0011 */ TABDECL(OP_LDR_PCREL), // OP_LDR_PCREL /* 01 0011 0100 */ TABDECL(OP_LDR_PCREL), // OP_LDR_PCREL /* 01 0011 0101 */ TABDECL(OP_LDR_PCREL), // OP_LDR_PCREL /* 01 0011 0110 */ TABDECL(OP_LDR_PCREL), // OP_LDR_PCREL /* 01 0011 0111 */ TABDECL(OP_LDR_PCREL), // OP_LDR_PCREL /* 01 0011 1000 */ TABDECL(OP_LDR_PCREL), // OP_LDR_PCREL /* 01 0011 1001 */ TABDECL(OP_LDR_PCREL), // OP_LDR_PCREL /* 01 0011 1010 */ TABDECL(OP_LDR_PCREL), // OP_LDR_PCREL /* 01 0011 1011 */ TABDECL(OP_LDR_PCREL), // OP_LDR_PCREL /* 01 0011 1100 */ TABDECL(OP_LDR_PCREL), // OP_LDR_PCREL /* 01 0011 1101 */ TABDECL(OP_LDR_PCREL), // OP_LDR_PCREL /* 01 0011 1110 */ TABDECL(OP_LDR_PCREL), // OP_LDR_PCREL /* 01 0011 1111 */ TABDECL(OP_LDR_PCREL), // OP_LDR_PCREL /* 01 0100 0000 */ TABDECL(OP_STR_REG_OFF), // OP_STR_REG_OFF /* 01 0100 0001 */ TABDECL(OP_STR_REG_OFF), // OP_STR_REG_OFF /* 01 0100 0010 */ TABDECL(OP_STR_REG_OFF), // OP_STR_REG_OFF /* 01 0100 0011 */ TABDECL(OP_STR_REG_OFF), // OP_STR_REG_OFF /* 01 0100 0100 */ TABDECL(OP_STR_REG_OFF), // OP_STR_REG_OFF /* 01 0100 0101 */ TABDECL(OP_STR_REG_OFF), // OP_STR_REG_OFF /* 01 0100 0110 */ TABDECL(OP_STR_REG_OFF), // OP_STR_REG_OFF /* 01 0100 0111 */ TABDECL(OP_STR_REG_OFF), // OP_STR_REG_OFF /* 01 0100 1000 */ TABDECL(OP_STRH_REG_OFF), // OP_STRH_REG_OFF /* 01 0100 1001 */ TABDECL(OP_STRH_REG_OFF), // OP_STRH_REG_OFF /* 01 0100 1010 */ TABDECL(OP_STRH_REG_OFF), // OP_STRH_REG_OFF /* 01 0100 1011 */ TABDECL(OP_STRH_REG_OFF), // OP_STRH_REG_OFF /* 01 0100 1100 */ TABDECL(OP_STRH_REG_OFF), // OP_STRH_REG_OFF /* 01 0100 1101 */ TABDECL(OP_STRH_REG_OFF), // OP_STRH_REG_OFF /* 01 0100 1110 */ TABDECL(OP_STRH_REG_OFF), // OP_STRH_REG_OFF /* 01 0100 1111 */ TABDECL(OP_STRH_REG_OFF), // OP_STRH_REG_OFF /* 01 0101 0000 */ TABDECL(OP_STRB_REG_OFF), // OP_STRB_REG_OFF /* 01 0101 0001 */ TABDECL(OP_STRB_REG_OFF), // OP_STRB_REG_OFF /* 01 0101 0010 */ TABDECL(OP_STRB_REG_OFF), // OP_STRB_REG_OFF /* 01 0101 0011 */ TABDECL(OP_STRB_REG_OFF), // OP_STRB_REG_OFF /* 01 0101 0100 */ TABDECL(OP_STRB_REG_OFF), // OP_STRB_REG_OFF /* 01 0101 0101 */ TABDECL(OP_STRB_REG_OFF), // OP_STRB_REG_OFF /* 01 0101 0110 */ TABDECL(OP_STRB_REG_OFF), // OP_STRB_REG_OFF /* 01 0101 0111 */ TABDECL(OP_STRB_REG_OFF), // OP_STRB_REG_OFF /* 01 0101 1000 */ TABDECL(OP_LDRSB_REG_OFF), // OP_LDRSB_REG_OFF /* 01 0101 1001 */ TABDECL(OP_LDRSB_REG_OFF), // OP_LDRSB_REG_OFF /* 01 0101 1010 */ TABDECL(OP_LDRSB_REG_OFF), // OP_LDRSB_REG_OFF /* 01 0101 1011 */ TABDECL(OP_LDRSB_REG_OFF), // OP_LDRSB_REG_OFF /* 01 0101 1100 */ TABDECL(OP_LDRSB_REG_OFF), // OP_LDRSB_REG_OFF /* 01 0101 1101 */ TABDECL(OP_LDRSB_REG_OFF), // OP_LDRSB_REG_OFF /* 01 0101 1110 */ TABDECL(OP_LDRSB_REG_OFF), // OP_LDRSB_REG_OFF /* 01 0101 1111 */ TABDECL(OP_LDRSB_REG_OFF), // OP_LDRSB_REG_OFF /* 01 0110 0000 */ TABDECL(OP_LDR_REG_OFF), // OP_LDR_REG_OFF /* 01 0110 0001 */ TABDECL(OP_LDR_REG_OFF), // OP_LDR_REG_OFF /* 01 0110 0010 */ TABDECL(OP_LDR_REG_OFF), // OP_LDR_REG_OFF /* 01 0110 0011 */ TABDECL(OP_LDR_REG_OFF), // OP_LDR_REG_OFF /* 01 0110 0100 */ TABDECL(OP_LDR_REG_OFF), // OP_LDR_REG_OFF /* 01 0110 0101 */ TABDECL(OP_LDR_REG_OFF), // OP_LDR_REG_OFF /* 01 0110 0110 */ TABDECL(OP_LDR_REG_OFF), // OP_LDR_REG_OFF /* 01 0110 0111 */ TABDECL(OP_LDR_REG_OFF), // OP_LDR_REG_OFF /* 01 0110 1000 */ TABDECL(OP_LDRH_REG_OFF), // OP_LDRH_REG_OFF /* 01 0110 1001 */ TABDECL(OP_LDRH_REG_OFF), // OP_LDRH_REG_OFF /* 01 0110 1010 */ TABDECL(OP_LDRH_REG_OFF), // OP_LDRH_REG_OFF /* 01 0110 1011 */ TABDECL(OP_LDRH_REG_OFF), // OP_LDRH_REG_OFF /* 01 0110 1100 */ TABDECL(OP_LDRH_REG_OFF), // OP_LDRH_REG_OFF /* 01 0110 1101 */ TABDECL(OP_LDRH_REG_OFF), // OP_LDRH_REG_OFF /* 01 0110 1110 */ TABDECL(OP_LDRH_REG_OFF), // OP_LDRH_REG_OFF /* 01 0110 1111 */ TABDECL(OP_LDRH_REG_OFF), // OP_LDRH_REG_OFF /* 01 0111 0000 */ TABDECL(OP_LDRB_REG_OFF), // OP_LDRB_REG_OFF /* 01 0111 0001 */ TABDECL(OP_LDRB_REG_OFF), // OP_LDRB_REG_OFF /* 01 0111 0010 */ TABDECL(OP_LDRB_REG_OFF), // OP_LDRB_REG_OFF /* 01 0111 0011 */ TABDECL(OP_LDRB_REG_OFF), // OP_LDRB_REG_OFF /* 01 0111 0100 */ TABDECL(OP_LDRB_REG_OFF), // OP_LDRB_REG_OFF /* 01 0111 0101 */ TABDECL(OP_LDRB_REG_OFF), // OP_LDRB_REG_OFF /* 01 0111 0110 */ TABDECL(OP_LDRB_REG_OFF), // OP_LDRB_REG_OFF /* 01 0111 0111 */ TABDECL(OP_LDRB_REG_OFF), // OP_LDRB_REG_OFF /* 01 0111 1000 */ TABDECL(OP_LDRSH_REG_OFF), // OP_LDRSH_REG_OFF /* 01 0111 1001 */ TABDECL(OP_LDRSH_REG_OFF), // OP_LDRSH_REG_OFF /* 01 0111 1010 */ TABDECL(OP_LDRSH_REG_OFF), // OP_LDRSH_REG_OFF /* 01 0111 1011 */ TABDECL(OP_LDRSH_REG_OFF), // OP_LDRSH_REG_OFF /* 01 0111 1100 */ TABDECL(OP_LDRSH_REG_OFF), // OP_LDRSH_REG_OFF /* 01 0111 1101 */ TABDECL(OP_LDRSH_REG_OFF), // OP_LDRSH_REG_OFF /* 01 0111 1110 */ TABDECL(OP_LDRSH_REG_OFF), // OP_LDRSH_REG_OFF /* 01 0111 1111 */ TABDECL(OP_LDRSH_REG_OFF), // OP_LDRSH_REG_OFF /* 01 1000 0000 */ TABDECL(OP_STR_IMM_OFF), // OP_STR_IMM_OFF /* 01 1000 0001 */ TABDECL(OP_STR_IMM_OFF), // OP_STR_IMM_OFF /* 01 1000 0010 */ TABDECL(OP_STR_IMM_OFF), // OP_STR_IMM_OFF /* 01 1000 0011 */ TABDECL(OP_STR_IMM_OFF), // OP_STR_IMM_OFF /* 01 1000 0100 */ TABDECL(OP_STR_IMM_OFF), // OP_STR_IMM_OFF /* 01 1000 0101 */ TABDECL(OP_STR_IMM_OFF), // OP_STR_IMM_OFF /* 01 1000 0110 */ TABDECL(OP_STR_IMM_OFF), // OP_STR_IMM_OFF /* 01 1000 0111 */ TABDECL(OP_STR_IMM_OFF), // OP_STR_IMM_OFF /* 01 1000 1000 */ TABDECL(OP_STR_IMM_OFF), // OP_STR_IMM_OFF /* 01 1000 1001 */ TABDECL(OP_STR_IMM_OFF), // OP_STR_IMM_OFF /* 01 1000 1010 */ TABDECL(OP_STR_IMM_OFF), // OP_STR_IMM_OFF /* 01 1000 1011 */ TABDECL(OP_STR_IMM_OFF), // OP_STR_IMM_OFF /* 01 1000 1100 */ TABDECL(OP_STR_IMM_OFF), // OP_STR_IMM_OFF /* 01 1000 1101 */ TABDECL(OP_STR_IMM_OFF), // OP_STR_IMM_OFF /* 01 1000 1110 */ TABDECL(OP_STR_IMM_OFF), // OP_STR_IMM_OFF /* 01 1000 1111 */ TABDECL(OP_STR_IMM_OFF), // OP_STR_IMM_OFF /* 01 1001 0000 */ TABDECL(OP_STR_IMM_OFF), // OP_STR_IMM_OFF /* 01 1001 0001 */ TABDECL(OP_STR_IMM_OFF), // OP_STR_IMM_OFF /* 01 1001 0010 */ TABDECL(OP_STR_IMM_OFF), // OP_STR_IMM_OFF /* 01 1001 0011 */ TABDECL(OP_STR_IMM_OFF), // OP_STR_IMM_OFF /* 01 1001 0100 */ TABDECL(OP_STR_IMM_OFF), // OP_STR_IMM_OFF /* 01 1001 0101 */ TABDECL(OP_STR_IMM_OFF), // OP_STR_IMM_OFF /* 01 1001 0110 */ TABDECL(OP_STR_IMM_OFF), // OP_STR_IMM_OFF /* 01 1001 0111 */ TABDECL(OP_STR_IMM_OFF), // OP_STR_IMM_OFF /* 01 1001 1000 */ TABDECL(OP_STR_IMM_OFF), // OP_STR_IMM_OFF /* 01 1001 1001 */ TABDECL(OP_STR_IMM_OFF), // OP_STR_IMM_OFF /* 01 1001 1010 */ TABDECL(OP_STR_IMM_OFF), // OP_STR_IMM_OFF /* 01 1001 1011 */ TABDECL(OP_STR_IMM_OFF), // OP_STR_IMM_OFF /* 01 1001 1100 */ TABDECL(OP_STR_IMM_OFF), // OP_STR_IMM_OFF /* 01 1001 1101 */ TABDECL(OP_STR_IMM_OFF), // OP_STR_IMM_OFF /* 01 1001 1110 */ TABDECL(OP_STR_IMM_OFF), // OP_STR_IMM_OFF /* 01 1001 1111 */ TABDECL(OP_STR_IMM_OFF), // OP_STR_IMM_OFF /* 01 1010 0000 */ TABDECL(OP_LDR_IMM_OFF), // OP_LDR_IMM_OFF /* 01 1010 0001 */ TABDECL(OP_LDR_IMM_OFF), // OP_LDR_IMM_OFF /* 01 1010 0010 */ TABDECL(OP_LDR_IMM_OFF), // OP_LDR_IMM_OFF /* 01 1010 0011 */ TABDECL(OP_LDR_IMM_OFF), // OP_LDR_IMM_OFF /* 01 1010 0100 */ TABDECL(OP_LDR_IMM_OFF), // OP_LDR_IMM_OFF /* 01 1010 0101 */ TABDECL(OP_LDR_IMM_OFF), // OP_LDR_IMM_OFF /* 01 1010 0110 */ TABDECL(OP_LDR_IMM_OFF), // OP_LDR_IMM_OFF /* 01 1010 0111 */ TABDECL(OP_LDR_IMM_OFF), // OP_LDR_IMM_OFF /* 01 1010 1000 */ TABDECL(OP_LDR_IMM_OFF), // OP_LDR_IMM_OFF /* 01 1010 1001 */ TABDECL(OP_LDR_IMM_OFF), // OP_LDR_IMM_OFF /* 01 1010 1010 */ TABDECL(OP_LDR_IMM_OFF), // OP_LDR_IMM_OFF /* 01 1010 1011 */ TABDECL(OP_LDR_IMM_OFF), // OP_LDR_IMM_OFF /* 01 1010 1100 */ TABDECL(OP_LDR_IMM_OFF), // OP_LDR_IMM_OFF /* 01 1010 1101 */ TABDECL(OP_LDR_IMM_OFF), // OP_LDR_IMM_OFF /* 01 1010 1110 */ TABDECL(OP_LDR_IMM_OFF), // OP_LDR_IMM_OFF /* 01 1010 1111 */ TABDECL(OP_LDR_IMM_OFF), // OP_LDR_IMM_OFF /* 01 1011 0000 */ TABDECL(OP_LDR_IMM_OFF), // OP_LDR_IMM_OFF /* 01 1011 0001 */ TABDECL(OP_LDR_IMM_OFF), // OP_LDR_IMM_OFF /* 01 1011 0010 */ TABDECL(OP_LDR_IMM_OFF), // OP_LDR_IMM_OFF /* 01 1011 0011 */ TABDECL(OP_LDR_IMM_OFF), // OP_LDR_IMM_OFF /* 01 1011 0100 */ TABDECL(OP_LDR_IMM_OFF), // OP_LDR_IMM_OFF /* 01 1011 0101 */ TABDECL(OP_LDR_IMM_OFF), // OP_LDR_IMM_OFF /* 01 1011 0110 */ TABDECL(OP_LDR_IMM_OFF), // OP_LDR_IMM_OFF /* 01 1011 0111 */ TABDECL(OP_LDR_IMM_OFF), // OP_LDR_IMM_OFF /* 01 1011 1000 */ TABDECL(OP_LDR_IMM_OFF), // OP_LDR_IMM_OFF /* 01 1011 1001 */ TABDECL(OP_LDR_IMM_OFF), // OP_LDR_IMM_OFF /* 01 1011 1010 */ TABDECL(OP_LDR_IMM_OFF), // OP_LDR_IMM_OFF /* 01 1011 1011 */ TABDECL(OP_LDR_IMM_OFF), // OP_LDR_IMM_OFF /* 01 1011 1100 */ TABDECL(OP_LDR_IMM_OFF), // OP_LDR_IMM_OFF /* 01 1011 1101 */ TABDECL(OP_LDR_IMM_OFF), // OP_LDR_IMM_OFF /* 01 1011 1110 */ TABDECL(OP_LDR_IMM_OFF), // OP_LDR_IMM_OFF /* 01 1011 1111 */ TABDECL(OP_LDR_IMM_OFF), // OP_LDR_IMM_OFF /* 01 1100 0000 */ TABDECL(OP_STRB_IMM_OFF), // OP_STRB_IMM_OFF /* 01 1100 0001 */ TABDECL(OP_STRB_IMM_OFF), // OP_STRB_IMM_OFF /* 01 1100 0010 */ TABDECL(OP_STRB_IMM_OFF), // OP_STRB_IMM_OFF /* 01 1100 0011 */ TABDECL(OP_STRB_IMM_OFF), // OP_STRB_IMM_OFF /* 01 1100 0100 */ TABDECL(OP_STRB_IMM_OFF), // OP_STRB_IMM_OFF /* 01 1100 0101 */ TABDECL(OP_STRB_IMM_OFF), // OP_STRB_IMM_OFF /* 01 1100 0110 */ TABDECL(OP_STRB_IMM_OFF), // OP_STRB_IMM_OFF /* 01 1100 0111 */ TABDECL(OP_STRB_IMM_OFF), // OP_STRB_IMM_OFF /* 01 1100 1000 */ TABDECL(OP_STRB_IMM_OFF), // OP_STRB_IMM_OFF /* 01 1100 1001 */ TABDECL(OP_STRB_IMM_OFF), // OP_STRB_IMM_OFF /* 01 1100 1010 */ TABDECL(OP_STRB_IMM_OFF), // OP_STRB_IMM_OFF /* 01 1100 1011 */ TABDECL(OP_STRB_IMM_OFF), // OP_STRB_IMM_OFF /* 01 1100 1100 */ TABDECL(OP_STRB_IMM_OFF), // OP_STRB_IMM_OFF /* 01 1100 1101 */ TABDECL(OP_STRB_IMM_OFF), // OP_STRB_IMM_OFF /* 01 1100 1110 */ TABDECL(OP_STRB_IMM_OFF), // OP_STRB_IMM_OFF /* 01 1100 1111 */ TABDECL(OP_STRB_IMM_OFF), // OP_STRB_IMM_OFF /* 01 1101 0000 */ TABDECL(OP_STRB_IMM_OFF), // OP_STRB_IMM_OFF /* 01 1101 0001 */ TABDECL(OP_STRB_IMM_OFF), // OP_STRB_IMM_OFF /* 01 1101 0010 */ TABDECL(OP_STRB_IMM_OFF), // OP_STRB_IMM_OFF /* 01 1101 0011 */ TABDECL(OP_STRB_IMM_OFF), // OP_STRB_IMM_OFF /* 01 1101 0100 */ TABDECL(OP_STRB_IMM_OFF), // OP_STRB_IMM_OFF /* 01 1101 0101 */ TABDECL(OP_STRB_IMM_OFF), // OP_STRB_IMM_OFF /* 01 1101 0110 */ TABDECL(OP_STRB_IMM_OFF), // OP_STRB_IMM_OFF /* 01 1101 0111 */ TABDECL(OP_STRB_IMM_OFF), // OP_STRB_IMM_OFF /* 01 1101 1000 */ TABDECL(OP_STRB_IMM_OFF), // OP_STRB_IMM_OFF /* 01 1101 1001 */ TABDECL(OP_STRB_IMM_OFF), // OP_STRB_IMM_OFF /* 01 1101 1010 */ TABDECL(OP_STRB_IMM_OFF), // OP_STRB_IMM_OFF /* 01 1101 1011 */ TABDECL(OP_STRB_IMM_OFF), // OP_STRB_IMM_OFF /* 01 1101 1100 */ TABDECL(OP_STRB_IMM_OFF), // OP_STRB_IMM_OFF /* 01 1101 1101 */ TABDECL(OP_STRB_IMM_OFF), // OP_STRB_IMM_OFF /* 01 1101 1110 */ TABDECL(OP_STRB_IMM_OFF), // OP_STRB_IMM_OFF /* 01 1101 1111 */ TABDECL(OP_STRB_IMM_OFF), // OP_STRB_IMM_OFF /* 01 1110 0000 */ TABDECL(OP_LDRB_IMM_OFF), // OP_LDRB_IMM_OFF /* 01 1110 0001 */ TABDECL(OP_LDRB_IMM_OFF), // OP_LDRB_IMM_OFF /* 01 1110 0010 */ TABDECL(OP_LDRB_IMM_OFF), // OP_LDRB_IMM_OFF /* 01 1110 0011 */ TABDECL(OP_LDRB_IMM_OFF), // OP_LDRB_IMM_OFF /* 01 1110 0100 */ TABDECL(OP_LDRB_IMM_OFF), // OP_LDRB_IMM_OFF /* 01 1110 0101 */ TABDECL(OP_LDRB_IMM_OFF), // OP_LDRB_IMM_OFF /* 01 1110 0110 */ TABDECL(OP_LDRB_IMM_OFF), // OP_LDRB_IMM_OFF /* 01 1110 0111 */ TABDECL(OP_LDRB_IMM_OFF), // OP_LDRB_IMM_OFF /* 01 1110 1000 */ TABDECL(OP_LDRB_IMM_OFF), // OP_LDRB_IMM_OFF /* 01 1110 1001 */ TABDECL(OP_LDRB_IMM_OFF), // OP_LDRB_IMM_OFF /* 01 1110 1010 */ TABDECL(OP_LDRB_IMM_OFF), // OP_LDRB_IMM_OFF /* 01 1110 1011 */ TABDECL(OP_LDRB_IMM_OFF), // OP_LDRB_IMM_OFF /* 01 1110 1100 */ TABDECL(OP_LDRB_IMM_OFF), // OP_LDRB_IMM_OFF /* 01 1110 1101 */ TABDECL(OP_LDRB_IMM_OFF), // OP_LDRB_IMM_OFF /* 01 1110 1110 */ TABDECL(OP_LDRB_IMM_OFF), // OP_LDRB_IMM_OFF /* 01 1110 1111 */ TABDECL(OP_LDRB_IMM_OFF), // OP_LDRB_IMM_OFF /* 01 1111 0000 */ TABDECL(OP_LDRB_IMM_OFF), // OP_LDRB_IMM_OFF /* 01 1111 0001 */ TABDECL(OP_LDRB_IMM_OFF), // OP_LDRB_IMM_OFF /* 01 1111 0010 */ TABDECL(OP_LDRB_IMM_OFF), // OP_LDRB_IMM_OFF /* 01 1111 0011 */ TABDECL(OP_LDRB_IMM_OFF), // OP_LDRB_IMM_OFF /* 01 1111 0100 */ TABDECL(OP_LDRB_IMM_OFF), // OP_LDRB_IMM_OFF /* 01 1111 0101 */ TABDECL(OP_LDRB_IMM_OFF), // OP_LDRB_IMM_OFF /* 01 1111 0110 */ TABDECL(OP_LDRB_IMM_OFF), // OP_LDRB_IMM_OFF /* 01 1111 0111 */ TABDECL(OP_LDRB_IMM_OFF), // OP_LDRB_IMM_OFF /* 01 1111 1000 */ TABDECL(OP_LDRB_IMM_OFF), // OP_LDRB_IMM_OFF /* 01 1111 1001 */ TABDECL(OP_LDRB_IMM_OFF), // OP_LDRB_IMM_OFF /* 01 1111 1010 */ TABDECL(OP_LDRB_IMM_OFF), // OP_LDRB_IMM_OFF /* 01 1111 1011 */ TABDECL(OP_LDRB_IMM_OFF), // OP_LDRB_IMM_OFF /* 01 1111 1100 */ TABDECL(OP_LDRB_IMM_OFF), // OP_LDRB_IMM_OFF /* 01 1111 1101 */ TABDECL(OP_LDRB_IMM_OFF), // OP_LDRB_IMM_OFF /* 01 1111 1110 */ TABDECL(OP_LDRB_IMM_OFF), // OP_LDRB_IMM_OFF /* 01 1111 1111 */ TABDECL(OP_LDRB_IMM_OFF), // OP_LDRB_IMM_OFF /* 10 0000 0000 */ TABDECL(OP_STRH_IMM_OFF), // OP_STRH_IMM_OFF /* 10 0000 0001 */ TABDECL(OP_STRH_IMM_OFF), // OP_STRH_IMM_OFF /* 10 0000 0010 */ TABDECL(OP_STRH_IMM_OFF), // OP_STRH_IMM_OFF /* 10 0000 0011 */ TABDECL(OP_STRH_IMM_OFF), // OP_STRH_IMM_OFF /* 10 0000 0100 */ TABDECL(OP_STRH_IMM_OFF), // OP_STRH_IMM_OFF /* 10 0000 0101 */ TABDECL(OP_STRH_IMM_OFF), // OP_STRH_IMM_OFF /* 10 0000 0110 */ TABDECL(OP_STRH_IMM_OFF), // OP_STRH_IMM_OFF /* 10 0000 0111 */ TABDECL(OP_STRH_IMM_OFF), // OP_STRH_IMM_OFF /* 10 0000 1000 */ TABDECL(OP_STRH_IMM_OFF), // OP_STRH_IMM_OFF /* 10 0000 1001 */ TABDECL(OP_STRH_IMM_OFF), // OP_STRH_IMM_OFF /* 10 0000 1010 */ TABDECL(OP_STRH_IMM_OFF), // OP_STRH_IMM_OFF /* 10 0000 1011 */ TABDECL(OP_STRH_IMM_OFF), // OP_STRH_IMM_OFF /* 10 0000 1100 */ TABDECL(OP_STRH_IMM_OFF), // OP_STRH_IMM_OFF /* 10 0000 1101 */ TABDECL(OP_STRH_IMM_OFF), // OP_STRH_IMM_OFF /* 10 0000 1110 */ TABDECL(OP_STRH_IMM_OFF), // OP_STRH_IMM_OFF /* 10 0000 1111 */ TABDECL(OP_STRH_IMM_OFF), // OP_STRH_IMM_OFF /* 10 0001 0000 */ TABDECL(OP_STRH_IMM_OFF), // OP_STRH_IMM_OFF /* 10 0001 0001 */ TABDECL(OP_STRH_IMM_OFF), // OP_STRH_IMM_OFF /* 10 0001 0010 */ TABDECL(OP_STRH_IMM_OFF), // OP_STRH_IMM_OFF /* 10 0001 0011 */ TABDECL(OP_STRH_IMM_OFF), // OP_STRH_IMM_OFF /* 10 0001 0100 */ TABDECL(OP_STRH_IMM_OFF), // OP_STRH_IMM_OFF /* 10 0001 0101 */ TABDECL(OP_STRH_IMM_OFF), // OP_STRH_IMM_OFF /* 10 0001 0110 */ TABDECL(OP_STRH_IMM_OFF), // OP_STRH_IMM_OFF /* 10 0001 0111 */ TABDECL(OP_STRH_IMM_OFF), // OP_STRH_IMM_OFF /* 10 0001 1000 */ TABDECL(OP_STRH_IMM_OFF), // OP_STRH_IMM_OFF /* 10 0001 1001 */ TABDECL(OP_STRH_IMM_OFF), // OP_STRH_IMM_OFF /* 10 0001 1010 */ TABDECL(OP_STRH_IMM_OFF), // OP_STRH_IMM_OFF /* 10 0001 1011 */ TABDECL(OP_STRH_IMM_OFF), // OP_STRH_IMM_OFF /* 10 0001 1100 */ TABDECL(OP_STRH_IMM_OFF), // OP_STRH_IMM_OFF /* 10 0001 1101 */ TABDECL(OP_STRH_IMM_OFF), // OP_STRH_IMM_OFF /* 10 0001 1110 */ TABDECL(OP_STRH_IMM_OFF), // OP_STRH_IMM_OFF /* 10 0001 1111 */ TABDECL(OP_STRH_IMM_OFF), // OP_STRH_IMM_OFF /* 10 0010 0000 */ TABDECL(OP_LDRH_IMM_OFF), // OP_LDRH_IMM_OFF /* 10 0010 0001 */ TABDECL(OP_LDRH_IMM_OFF), // OP_LDRH_IMM_OFF /* 10 0010 0010 */ TABDECL(OP_LDRH_IMM_OFF), // OP_LDRH_IMM_OFF /* 10 0010 0011 */ TABDECL(OP_LDRH_IMM_OFF), // OP_LDRH_IMM_OFF /* 10 0010 0100 */ TABDECL(OP_LDRH_IMM_OFF), // OP_LDRH_IMM_OFF /* 10 0010 0101 */ TABDECL(OP_LDRH_IMM_OFF), // OP_LDRH_IMM_OFF /* 10 0010 0110 */ TABDECL(OP_LDRH_IMM_OFF), // OP_LDRH_IMM_OFF /* 10 0010 0111 */ TABDECL(OP_LDRH_IMM_OFF), // OP_LDRH_IMM_OFF /* 10 0010 1000 */ TABDECL(OP_LDRH_IMM_OFF), // OP_LDRH_IMM_OFF /* 10 0010 1001 */ TABDECL(OP_LDRH_IMM_OFF), // OP_LDRH_IMM_OFF /* 10 0010 1010 */ TABDECL(OP_LDRH_IMM_OFF), // OP_LDRH_IMM_OFF /* 10 0010 1011 */ TABDECL(OP_LDRH_IMM_OFF), // OP_LDRH_IMM_OFF /* 10 0010 1100 */ TABDECL(OP_LDRH_IMM_OFF), // OP_LDRH_IMM_OFF /* 10 0010 1101 */ TABDECL(OP_LDRH_IMM_OFF), // OP_LDRH_IMM_OFF /* 10 0010 1110 */ TABDECL(OP_LDRH_IMM_OFF), // OP_LDRH_IMM_OFF /* 10 0010 1111 */ TABDECL(OP_LDRH_IMM_OFF), // OP_LDRH_IMM_OFF /* 10 0011 0000 */ TABDECL(OP_LDRH_IMM_OFF), // OP_LDRH_IMM_OFF /* 10 0011 0001 */ TABDECL(OP_LDRH_IMM_OFF), // OP_LDRH_IMM_OFF /* 10 0011 0010 */ TABDECL(OP_LDRH_IMM_OFF), // OP_LDRH_IMM_OFF /* 10 0011 0011 */ TABDECL(OP_LDRH_IMM_OFF), // OP_LDRH_IMM_OFF /* 10 0011 0100 */ TABDECL(OP_LDRH_IMM_OFF), // OP_LDRH_IMM_OFF /* 10 0011 0101 */ TABDECL(OP_LDRH_IMM_OFF), // OP_LDRH_IMM_OFF /* 10 0011 0110 */ TABDECL(OP_LDRH_IMM_OFF), // OP_LDRH_IMM_OFF /* 10 0011 0111 */ TABDECL(OP_LDRH_IMM_OFF), // OP_LDRH_IMM_OFF /* 10 0011 1000 */ TABDECL(OP_LDRH_IMM_OFF), // OP_LDRH_IMM_OFF /* 10 0011 1001 */ TABDECL(OP_LDRH_IMM_OFF), // OP_LDRH_IMM_OFF /* 10 0011 1010 */ TABDECL(OP_LDRH_IMM_OFF), // OP_LDRH_IMM_OFF /* 10 0011 1011 */ TABDECL(OP_LDRH_IMM_OFF), // OP_LDRH_IMM_OFF /* 10 0011 1100 */ TABDECL(OP_LDRH_IMM_OFF), // OP_LDRH_IMM_OFF /* 10 0011 1101 */ TABDECL(OP_LDRH_IMM_OFF), // OP_LDRH_IMM_OFF /* 10 0011 1110 */ TABDECL(OP_LDRH_IMM_OFF), // OP_LDRH_IMM_OFF /* 10 0011 1111 */ TABDECL(OP_LDRH_IMM_OFF), // OP_LDRH_IMM_OFF /* 10 0100 0000 */ TABDECL(OP_STR_SPREL), // OP_STR_SPREL /* 10 0100 0001 */ TABDECL(OP_STR_SPREL), // OP_STR_SPREL /* 10 0100 0010 */ TABDECL(OP_STR_SPREL), // OP_STR_SPREL /* 10 0100 0011 */ TABDECL(OP_STR_SPREL), // OP_STR_SPREL /* 10 0100 0100 */ TABDECL(OP_STR_SPREL), // OP_STR_SPREL /* 10 0100 0101 */ TABDECL(OP_STR_SPREL), // OP_STR_SPREL /* 10 0100 0110 */ TABDECL(OP_STR_SPREL), // OP_STR_SPREL /* 10 0100 0111 */ TABDECL(OP_STR_SPREL), // OP_STR_SPREL /* 10 0100 1000 */ TABDECL(OP_STR_SPREL), // OP_STR_SPREL /* 10 0100 1001 */ TABDECL(OP_STR_SPREL), // OP_STR_SPREL /* 10 0100 1010 */ TABDECL(OP_STR_SPREL), // OP_STR_SPREL /* 10 0100 1011 */ TABDECL(OP_STR_SPREL), // OP_STR_SPREL /* 10 0100 1100 */ TABDECL(OP_STR_SPREL), // OP_STR_SPREL /* 10 0100 1101 */ TABDECL(OP_STR_SPREL), // OP_STR_SPREL /* 10 0100 1110 */ TABDECL(OP_STR_SPREL), // OP_STR_SPREL /* 10 0100 1111 */ TABDECL(OP_STR_SPREL), // OP_STR_SPREL /* 10 0101 0000 */ TABDECL(OP_STR_SPREL), // OP_STR_SPREL /* 10 0101 0001 */ TABDECL(OP_STR_SPREL), // OP_STR_SPREL /* 10 0101 0010 */ TABDECL(OP_STR_SPREL), // OP_STR_SPREL /* 10 0101 0011 */ TABDECL(OP_STR_SPREL), // OP_STR_SPREL /* 10 0101 0100 */ TABDECL(OP_STR_SPREL), // OP_STR_SPREL /* 10 0101 0101 */ TABDECL(OP_STR_SPREL), // OP_STR_SPREL /* 10 0101 0110 */ TABDECL(OP_STR_SPREL), // OP_STR_SPREL /* 10 0101 0111 */ TABDECL(OP_STR_SPREL), // OP_STR_SPREL /* 10 0101 1000 */ TABDECL(OP_STR_SPREL), // OP_STR_SPREL /* 10 0101 1001 */ TABDECL(OP_STR_SPREL), // OP_STR_SPREL /* 10 0101 1010 */ TABDECL(OP_STR_SPREL), // OP_STR_SPREL /* 10 0101 1011 */ TABDECL(OP_STR_SPREL), // OP_STR_SPREL /* 10 0101 1100 */ TABDECL(OP_STR_SPREL), // OP_STR_SPREL /* 10 0101 1101 */ TABDECL(OP_STR_SPREL), // OP_STR_SPREL /* 10 0101 1110 */ TABDECL(OP_STR_SPREL), // OP_STR_SPREL /* 10 0101 1111 */ TABDECL(OP_STR_SPREL), // OP_STR_SPREL /* 10 0110 0000 */ TABDECL(OP_LDR_SPREL), // OP_LDR_SPREL /* 10 0110 0001 */ TABDECL(OP_LDR_SPREL), // OP_LDR_SPREL /* 10 0110 0010 */ TABDECL(OP_LDR_SPREL), // OP_LDR_SPREL /* 10 0110 0011 */ TABDECL(OP_LDR_SPREL), // OP_LDR_SPREL /* 10 0110 0100 */ TABDECL(OP_LDR_SPREL), // OP_LDR_SPREL /* 10 0110 0101 */ TABDECL(OP_LDR_SPREL), // OP_LDR_SPREL /* 10 0110 0110 */ TABDECL(OP_LDR_SPREL), // OP_LDR_SPREL /* 10 0110 0111 */ TABDECL(OP_LDR_SPREL), // OP_LDR_SPREL /* 10 0110 1000 */ TABDECL(OP_LDR_SPREL), // OP_LDR_SPREL /* 10 0110 1001 */ TABDECL(OP_LDR_SPREL), // OP_LDR_SPREL /* 10 0110 1010 */ TABDECL(OP_LDR_SPREL), // OP_LDR_SPREL /* 10 0110 1011 */ TABDECL(OP_LDR_SPREL), // OP_LDR_SPREL /* 10 0110 1100 */ TABDECL(OP_LDR_SPREL), // OP_LDR_SPREL /* 10 0110 1101 */ TABDECL(OP_LDR_SPREL), // OP_LDR_SPREL /* 10 0110 1110 */ TABDECL(OP_LDR_SPREL), // OP_LDR_SPREL /* 10 0110 1111 */ TABDECL(OP_LDR_SPREL), // OP_LDR_SPREL /* 10 0111 0000 */ TABDECL(OP_LDR_SPREL), // OP_LDR_SPREL /* 10 0111 0001 */ TABDECL(OP_LDR_SPREL), // OP_LDR_SPREL /* 10 0111 0010 */ TABDECL(OP_LDR_SPREL), // OP_LDR_SPREL /* 10 0111 0011 */ TABDECL(OP_LDR_SPREL), // OP_LDR_SPREL /* 10 0111 0100 */ TABDECL(OP_LDR_SPREL), // OP_LDR_SPREL /* 10 0111 0101 */ TABDECL(OP_LDR_SPREL), // OP_LDR_SPREL /* 10 0111 0110 */ TABDECL(OP_LDR_SPREL), // OP_LDR_SPREL /* 10 0111 0111 */ TABDECL(OP_LDR_SPREL), // OP_LDR_SPREL /* 10 0111 1000 */ TABDECL(OP_LDR_SPREL), // OP_LDR_SPREL /* 10 0111 1001 */ TABDECL(OP_LDR_SPREL), // OP_LDR_SPREL /* 10 0111 1010 */ TABDECL(OP_LDR_SPREL), // OP_LDR_SPREL /* 10 0111 1011 */ TABDECL(OP_LDR_SPREL), // OP_LDR_SPREL /* 10 0111 1100 */ TABDECL(OP_LDR_SPREL), // OP_LDR_SPREL /* 10 0111 1101 */ TABDECL(OP_LDR_SPREL), // OP_LDR_SPREL /* 10 0111 1110 */ TABDECL(OP_LDR_SPREL), // OP_LDR_SPREL /* 10 0111 1111 */ TABDECL(OP_LDR_SPREL), // OP_LDR_SPREL /* 10 1000 0000 */ TABDECL(OP_ADD_2PC), // OP_ADD_2PC /* 10 1000 0001 */ TABDECL(OP_ADD_2PC), // OP_ADD_2PC /* 10 1000 0010 */ TABDECL(OP_ADD_2PC), // OP_ADD_2PC /* 10 1000 0011 */ TABDECL(OP_ADD_2PC), // OP_ADD_2PC /* 10 1000 0100 */ TABDECL(OP_ADD_2PC), // OP_ADD_2PC /* 10 1000 0101 */ TABDECL(OP_ADD_2PC), // OP_ADD_2PC /* 10 1000 0110 */ TABDECL(OP_ADD_2PC), // OP_ADD_2PC /* 10 1000 0111 */ TABDECL(OP_ADD_2PC), // OP_ADD_2PC /* 10 1000 1000 */ TABDECL(OP_ADD_2PC), // OP_ADD_2PC /* 10 1000 1001 */ TABDECL(OP_ADD_2PC), // OP_ADD_2PC /* 10 1000 1010 */ TABDECL(OP_ADD_2PC), // OP_ADD_2PC /* 10 1000 1011 */ TABDECL(OP_ADD_2PC), // OP_ADD_2PC /* 10 1000 1100 */ TABDECL(OP_ADD_2PC), // OP_ADD_2PC /* 10 1000 1101 */ TABDECL(OP_ADD_2PC), // OP_ADD_2PC /* 10 1000 1110 */ TABDECL(OP_ADD_2PC), // OP_ADD_2PC /* 10 1000 1111 */ TABDECL(OP_ADD_2PC), // OP_ADD_2PC /* 10 1001 0000 */ TABDECL(OP_ADD_2PC), // OP_ADD_2PC /* 10 1001 0001 */ TABDECL(OP_ADD_2PC), // OP_ADD_2PC /* 10 1001 0010 */ TABDECL(OP_ADD_2PC), // OP_ADD_2PC /* 10 1001 0011 */ TABDECL(OP_ADD_2PC), // OP_ADD_2PC /* 10 1001 0100 */ TABDECL(OP_ADD_2PC), // OP_ADD_2PC /* 10 1001 0101 */ TABDECL(OP_ADD_2PC), // OP_ADD_2PC /* 10 1001 0110 */ TABDECL(OP_ADD_2PC), // OP_ADD_2PC /* 10 1001 0111 */ TABDECL(OP_ADD_2PC), // OP_ADD_2PC /* 10 1001 1000 */ TABDECL(OP_ADD_2PC), // OP_ADD_2PC /* 10 1001 1001 */ TABDECL(OP_ADD_2PC), // OP_ADD_2PC /* 10 1001 1010 */ TABDECL(OP_ADD_2PC), // OP_ADD_2PC /* 10 1001 1011 */ TABDECL(OP_ADD_2PC), // OP_ADD_2PC /* 10 1001 1100 */ TABDECL(OP_ADD_2PC), // OP_ADD_2PC /* 10 1001 1101 */ TABDECL(OP_ADD_2PC), // OP_ADD_2PC /* 10 1001 1110 */ TABDECL(OP_ADD_2PC), // OP_ADD_2PC /* 10 1001 1111 */ TABDECL(OP_ADD_2PC), // OP_ADD_2PC /* 10 1010 0000 */ TABDECL(OP_ADD_2SP), // OP_ADD_2SP /* 10 1010 0001 */ TABDECL(OP_ADD_2SP), // OP_ADD_2SP /* 10 1010 0010 */ TABDECL(OP_ADD_2SP), // OP_ADD_2SP /* 10 1010 0011 */ TABDECL(OP_ADD_2SP), // OP_ADD_2SP /* 10 1010 0100 */ TABDECL(OP_ADD_2SP), // OP_ADD_2SP /* 10 1010 0101 */ TABDECL(OP_ADD_2SP), // OP_ADD_2SP /* 10 1010 0110 */ TABDECL(OP_ADD_2SP), // OP_ADD_2SP /* 10 1010 0111 */ TABDECL(OP_ADD_2SP), // OP_ADD_2SP /* 10 1010 1000 */ TABDECL(OP_ADD_2SP), // OP_ADD_2SP /* 10 1010 1001 */ TABDECL(OP_ADD_2SP), // OP_ADD_2SP /* 10 1010 1010 */ TABDECL(OP_ADD_2SP), // OP_ADD_2SP /* 10 1010 1011 */ TABDECL(OP_ADD_2SP), // OP_ADD_2SP /* 10 1010 1100 */ TABDECL(OP_ADD_2SP), // OP_ADD_2SP /* 10 1010 1101 */ TABDECL(OP_ADD_2SP), // OP_ADD_2SP /* 10 1010 1110 */ TABDECL(OP_ADD_2SP), // OP_ADD_2SP /* 10 1010 1111 */ TABDECL(OP_ADD_2SP), // OP_ADD_2SP /* 10 1011 0000 */ TABDECL(OP_ADD_2SP), // OP_ADD_2SP /* 10 1011 0001 */ TABDECL(OP_ADD_2SP), // OP_ADD_2SP /* 10 1011 0010 */ TABDECL(OP_ADD_2SP), // OP_ADD_2SP /* 10 1011 0011 */ TABDECL(OP_ADD_2SP), // OP_ADD_2SP /* 10 1011 0100 */ TABDECL(OP_ADD_2SP), // OP_ADD_2SP /* 10 1011 0101 */ TABDECL(OP_ADD_2SP), // OP_ADD_2SP /* 10 1011 0110 */ TABDECL(OP_ADD_2SP), // OP_ADD_2SP /* 10 1011 0111 */ TABDECL(OP_ADD_2SP), // OP_ADD_2SP /* 10 1011 1000 */ TABDECL(OP_ADD_2SP), // OP_ADD_2SP /* 10 1011 1001 */ TABDECL(OP_ADD_2SP), // OP_ADD_2SP /* 10 1011 1010 */ TABDECL(OP_ADD_2SP), // OP_ADD_2SP /* 10 1011 1011 */ TABDECL(OP_ADD_2SP), // OP_ADD_2SP /* 10 1011 1100 */ TABDECL(OP_ADD_2SP), // OP_ADD_2SP /* 10 1011 1101 */ TABDECL(OP_ADD_2SP), // OP_ADD_2SP /* 10 1011 1110 */ TABDECL(OP_ADD_2SP), // OP_ADD_2SP /* 10 1011 1111 */ TABDECL(OP_ADD_2SP), // OP_ADD_2SP /* 10 1100 0000 */ TABDECL(OP_ADJUST_P_SP), // OP_ADJUST_P_SP /* 10 1100 0001 */ TABDECL(OP_ADJUST_P_SP), // OP_ADJUST_P_SP /* 10 1100 0010 */ TABDECL(OP_ADJUST_M_SP), // OP_ADJUST_M_SP /* 10 1100 0011 */ TABDECL(OP_ADJUST_M_SP), // OP_ADJUST_M_SP /* 10 1100 0100 */ TABDECL(OP_UND_THUMB), /* 10 1100 0101 */ TABDECL(OP_UND_THUMB), /* 10 1100 0110 */ TABDECL(OP_UND_THUMB), /* 10 1100 0111 */ TABDECL(OP_UND_THUMB), /* 10 1100 1000 */ TABDECL(OP_UND_THUMB), /* 10 1100 1001 */ TABDECL(OP_UND_THUMB), /* 10 1100 1010 */ TABDECL(OP_UND_THUMB), /* 10 1100 1011 */ TABDECL(OP_UND_THUMB), /* 10 1100 1100 */ TABDECL(OP_UND_THUMB), /* 10 1100 1101 */ TABDECL(OP_UND_THUMB), /* 10 1100 1110 */ TABDECL(OP_UND_THUMB), /* 10 1100 1111 */ TABDECL(OP_UND_THUMB), /* 10 1101 0000 */ TABDECL(OP_PUSH), // OP_PUSH /* 10 1101 0001 */ TABDECL(OP_PUSH), // OP_PUSH /* 10 1101 0010 */ TABDECL(OP_PUSH), // OP_PUSH /* 10 1101 0011 */ TABDECL(OP_PUSH), // OP_PUSH /* 10 1101 0100 */ TABDECL(OP_PUSH_LR), // OP_PUSH_LR /* 10 1101 0101 */ TABDECL(OP_PUSH_LR), // OP_PUSH_LR /* 10 1101 0110 */ TABDECL(OP_PUSH_LR), // OP_PUSH_LR /* 10 1101 0111 */ TABDECL(OP_PUSH_LR), // OP_PUSH_LR /* 10 1101 1000 */ TABDECL(OP_UND_THUMB), /* 10 1101 1001 */ TABDECL(OP_UND_THUMB), /* 10 1101 1010 */ TABDECL(OP_UND_THUMB), /* 10 1101 1011 */ TABDECL(OP_UND_THUMB), /* 10 1101 1100 */ TABDECL(OP_UND_THUMB), /* 10 1101 1101 */ TABDECL(OP_UND_THUMB), /* 10 1101 1110 */ TABDECL(OP_UND_THUMB), /* 10 1101 1111 */ TABDECL(OP_UND_THUMB), /* 10 1110 0000 */ TABDECL(OP_UND_THUMB), /* 10 1110 0001 */ TABDECL(OP_UND_THUMB), /* 10 1110 0010 */ TABDECL(OP_UND_THUMB), /* 10 1110 0011 */ TABDECL(OP_UND_THUMB), /* 10 1110 0100 */ TABDECL(OP_UND_THUMB), /* 10 1110 0101 */ TABDECL(OP_UND_THUMB), /* 10 1110 0110 */ TABDECL(OP_UND_THUMB), /* 10 1110 0111 */ TABDECL(OP_UND_THUMB), /* 10 1110 1000 */ TABDECL(OP_UND_THUMB), /* 10 1110 1001 */ TABDECL(OP_UND_THUMB), /* 10 1110 1010 */ TABDECL(OP_UND_THUMB), /* 10 1110 1011 */ TABDECL(OP_UND_THUMB), /* 10 1110 1100 */ TABDECL(OP_UND_THUMB), /* 10 1110 1101 */ TABDECL(OP_UND_THUMB), /* 10 1110 1110 */ TABDECL(OP_UND_THUMB), /* 10 1110 1111 */ TABDECL(OP_UND_THUMB), /* 10 1111 0000 */ TABDECL(OP_POP), // OP_POP /* 10 1111 0001 */ TABDECL(OP_POP), // OP_POP /* 10 1111 0010 */ TABDECL(OP_POP), // OP_POP /* 10 1111 0011 */ TABDECL(OP_POP), // OP_POP /* 10 1111 0100 */ TABDECL(OP_POP_PC), // OP_POP_PC /* 10 1111 0101 */ TABDECL(OP_POP_PC), // OP_POP_PC /* 10 1111 0110 */ TABDECL(OP_POP_PC), // OP_POP_PC /* 10 1111 0111 */ TABDECL(OP_POP_PC), // OP_POP_PC /* 10 1111 1000 */ TABDECL(OP_BKPT_THUMB), // OP_BKPT_THUMB /* 10 1111 1001 */ TABDECL(OP_BKPT_THUMB), // OP_BKPT_THUMB /* 10 1111 1010 */ TABDECL(OP_BKPT_THUMB), // OP_BKPT_THUMB /* 10 1111 1011 */ TABDECL(OP_BKPT_THUMB), // OP_BKPT_THUMB /* 10 1111 1100 */ TABDECL(OP_UND_THUMB), /* 10 1111 1101 */ TABDECL(OP_UND_THUMB), /* 10 1111 1110 */ TABDECL(OP_UND_THUMB), /* 10 1111 1111 */ TABDECL(OP_UND_THUMB), /* 11 0000 0000 */ TABDECL(OP_STMIA_THUMB), // OP_STMIA_THUMB /* 11 0000 0001 */ TABDECL(OP_STMIA_THUMB), // OP_STMIA_THUMB /* 11 0000 0010 */ TABDECL(OP_STMIA_THUMB), // OP_STMIA_THUMB /* 11 0000 0011 */ TABDECL(OP_STMIA_THUMB), // OP_STMIA_THUMB /* 11 0000 0100 */ TABDECL(OP_STMIA_THUMB), // OP_STMIA_THUMB /* 11 0000 0101 */ TABDECL(OP_STMIA_THUMB), // OP_STMIA_THUMB /* 11 0000 0110 */ TABDECL(OP_STMIA_THUMB), // OP_STMIA_THUMB /* 11 0000 0111 */ TABDECL(OP_STMIA_THUMB), // OP_STMIA_THUMB /* 11 0000 1000 */ TABDECL(OP_STMIA_THUMB), // OP_STMIA_THUMB /* 11 0000 1001 */ TABDECL(OP_STMIA_THUMB), // OP_STMIA_THUMB /* 11 0000 1010 */ TABDECL(OP_STMIA_THUMB), // OP_STMIA_THUMB /* 11 0000 1011 */ TABDECL(OP_STMIA_THUMB), // OP_STMIA_THUMB /* 11 0000 1100 */ TABDECL(OP_STMIA_THUMB), // OP_STMIA_THUMB /* 11 0000 1101 */ TABDECL(OP_STMIA_THUMB), // OP_STMIA_THUMB /* 11 0000 1110 */ TABDECL(OP_STMIA_THUMB), // OP_STMIA_THUMB /* 11 0000 1111 */ TABDECL(OP_STMIA_THUMB), // OP_STMIA_THUMB /* 11 0001 0000 */ TABDECL(OP_STMIA_THUMB), // OP_STMIA_THUMB /* 11 0001 0001 */ TABDECL(OP_STMIA_THUMB), // OP_STMIA_THUMB /* 11 0001 0010 */ TABDECL(OP_STMIA_THUMB), // OP_STMIA_THUMB /* 11 0001 0011 */ TABDECL(OP_STMIA_THUMB), // OP_STMIA_THUMB /* 11 0001 0100 */ TABDECL(OP_STMIA_THUMB), // OP_STMIA_THUMB /* 11 0001 0101 */ TABDECL(OP_STMIA_THUMB), // OP_STMIA_THUMB /* 11 0001 0110 */ TABDECL(OP_STMIA_THUMB), // OP_STMIA_THUMB /* 11 0001 0111 */ TABDECL(OP_STMIA_THUMB), // OP_STMIA_THUMB /* 11 0001 1000 */ TABDECL(OP_STMIA_THUMB), // OP_STMIA_THUMB /* 11 0001 1001 */ TABDECL(OP_STMIA_THUMB), // OP_STMIA_THUMB /* 11 0001 1010 */ TABDECL(OP_STMIA_THUMB), // OP_STMIA_THUMB /* 11 0001 1011 */ TABDECL(OP_STMIA_THUMB), // OP_STMIA_THUMB /* 11 0001 1100 */ TABDECL(OP_STMIA_THUMB), // OP_STMIA_THUMB /* 11 0001 1101 */ TABDECL(OP_STMIA_THUMB), // OP_STMIA_THUMB /* 11 0001 1110 */ TABDECL(OP_STMIA_THUMB), // OP_STMIA_THUMB /* 11 0001 1111 */ TABDECL(OP_STMIA_THUMB), // OP_STMIA_THUMB /* 11 0010 0000 */ TABDECL(OP_LDMIA_THUMB), // OP_LDMIA_THUMB /* 11 0010 0001 */ TABDECL(OP_LDMIA_THUMB), // OP_LDMIA_THUMB /* 11 0010 0010 */ TABDECL(OP_LDMIA_THUMB), // OP_LDMIA_THUMB /* 11 0010 0011 */ TABDECL(OP_LDMIA_THUMB), // OP_LDMIA_THUMB /* 11 0010 0100 */ TABDECL(OP_LDMIA_THUMB), // OP_LDMIA_THUMB /* 11 0010 0101 */ TABDECL(OP_LDMIA_THUMB), // OP_LDMIA_THUMB /* 11 0010 0110 */ TABDECL(OP_LDMIA_THUMB), // OP_LDMIA_THUMB /* 11 0010 0111 */ TABDECL(OP_LDMIA_THUMB), // OP_LDMIA_THUMB /* 11 0010 1000 */ TABDECL(OP_LDMIA_THUMB), // OP_LDMIA_THUMB /* 11 0010 1001 */ TABDECL(OP_LDMIA_THUMB), // OP_LDMIA_THUMB /* 11 0010 1010 */ TABDECL(OP_LDMIA_THUMB), // OP_LDMIA_THUMB /* 11 0010 1011 */ TABDECL(OP_LDMIA_THUMB), // OP_LDMIA_THUMB /* 11 0010 1100 */ TABDECL(OP_LDMIA_THUMB), // OP_LDMIA_THUMB /* 11 0010 1101 */ TABDECL(OP_LDMIA_THUMB), // OP_LDMIA_THUMB /* 11 0010 1110 */ TABDECL(OP_LDMIA_THUMB), // OP_LDMIA_THUMB /* 11 0010 1111 */ TABDECL(OP_LDMIA_THUMB), // OP_LDMIA_THUMB /* 11 0011 0000 */ TABDECL(OP_LDMIA_THUMB), // OP_LDMIA_THUMB /* 11 0011 0001 */ TABDECL(OP_LDMIA_THUMB), // OP_LDMIA_THUMB /* 11 0011 0010 */ TABDECL(OP_LDMIA_THUMB), // OP_LDMIA_THUMB /* 11 0011 0011 */ TABDECL(OP_LDMIA_THUMB), // OP_LDMIA_THUMB /* 11 0011 0100 */ TABDECL(OP_LDMIA_THUMB), // OP_LDMIA_THUMB /* 11 0011 0101 */ TABDECL(OP_LDMIA_THUMB), // OP_LDMIA_THUMB /* 11 0011 0110 */ TABDECL(OP_LDMIA_THUMB), // OP_LDMIA_THUMB /* 11 0011 0111 */ TABDECL(OP_LDMIA_THUMB), // OP_LDMIA_THUMB /* 11 0011 1000 */ TABDECL(OP_LDMIA_THUMB), // OP_LDMIA_THUMB /* 11 0011 1001 */ TABDECL(OP_LDMIA_THUMB), // OP_LDMIA_THUMB /* 11 0011 1010 */ TABDECL(OP_LDMIA_THUMB), // OP_LDMIA_THUMB /* 11 0011 1011 */ TABDECL(OP_LDMIA_THUMB), // OP_LDMIA_THUMB /* 11 0011 1100 */ TABDECL(OP_LDMIA_THUMB), // OP_LDMIA_THUMB /* 11 0011 1101 */ TABDECL(OP_LDMIA_THUMB), // OP_LDMIA_THUMB /* 11 0011 1110 */ TABDECL(OP_LDMIA_THUMB), // OP_LDMIA_THUMB /* 11 0011 1111 */ TABDECL(OP_LDMIA_THUMB), // OP_LDMIA_THUMB /* 11 0100 0000 */ TABDECL(OP_B_COND), // OP_B_COND /* 11 0100 0001 */ TABDECL(OP_B_COND), // OP_B_COND /* 11 0100 0010 */ TABDECL(OP_B_COND), // OP_B_COND /* 11 0100 0011 */ TABDECL(OP_B_COND), // OP_B_COND /* 11 0100 0100 */ TABDECL(OP_B_COND), // OP_B_COND /* 11 0100 0101 */ TABDECL(OP_B_COND), // OP_B_COND /* 11 0100 0110 */ TABDECL(OP_B_COND), // OP_B_COND /* 11 0100 0111 */ TABDECL(OP_B_COND), // OP_B_COND /* 11 0100 1000 */ TABDECL(OP_B_COND), // OP_B_COND /* 11 0100 1001 */ TABDECL(OP_B_COND), // OP_B_COND /* 11 0100 1010 */ TABDECL(OP_B_COND), // OP_B_COND /* 11 0100 1011 */ TABDECL(OP_B_COND), // OP_B_COND /* 11 0100 1100 */ TABDECL(OP_B_COND), // OP_B_COND /* 11 0100 1101 */ TABDECL(OP_B_COND), // OP_B_COND /* 11 0100 1110 */ TABDECL(OP_B_COND), // OP_B_COND /* 11 0100 1111 */ TABDECL(OP_B_COND), // OP_B_COND /* 11 0101 0000 */ TABDECL(OP_B_COND), // OP_B_COND /* 11 0101 0001 */ TABDECL(OP_B_COND), // OP_B_COND /* 11 0101 0010 */ TABDECL(OP_B_COND), // OP_B_COND /* 11 0101 0011 */ TABDECL(OP_B_COND), // OP_B_COND /* 11 0101 0100 */ TABDECL(OP_B_COND), // OP_B_COND /* 11 0101 0101 */ TABDECL(OP_B_COND), // OP_B_COND /* 11 0101 0110 */ TABDECL(OP_B_COND), // OP_B_COND /* 11 0101 0111 */ TABDECL(OP_B_COND), // OP_B_COND /* 11 0101 1000 */ TABDECL(OP_B_COND), // OP_B_COND /* 11 0101 1001 */ TABDECL(OP_B_COND), // OP_B_COND /* 11 0101 1010 */ TABDECL(OP_B_COND), // OP_B_COND /* 11 0101 1011 */ TABDECL(OP_B_COND), // OP_B_COND /* 11 0101 1100 */ TABDECL(OP_B_COND), // OP_B_COND /* 11 0101 1101 */ TABDECL(OP_B_COND), // OP_B_COND /* 11 0101 1110 */ TABDECL(OP_B_COND), // OP_B_COND /* 11 0101 1111 */ TABDECL(OP_B_COND), // OP_B_COND /* 11 0110 0000 */ TABDECL(OP_B_COND), // OP_B_COND /* 11 0110 0001 */ TABDECL(OP_B_COND), // OP_B_COND /* 11 0110 0010 */ TABDECL(OP_B_COND), // OP_B_COND /* 11 0110 0011 */ TABDECL(OP_B_COND), // OP_B_COND /* 11 0110 0100 */ TABDECL(OP_B_COND), // OP_B_COND /* 11 0110 0101 */ TABDECL(OP_B_COND), // OP_B_COND /* 11 0110 0110 */ TABDECL(OP_B_COND), // OP_B_COND /* 11 0110 0111 */ TABDECL(OP_B_COND), // OP_B_COND /* 11 0110 1000 */ TABDECL(OP_B_COND), // OP_B_COND /* 11 0110 1001 */ TABDECL(OP_B_COND), // OP_B_COND /* 11 0110 1010 */ TABDECL(OP_B_COND), // OP_B_COND /* 11 0110 1011 */ TABDECL(OP_B_COND), // OP_B_COND /* 11 0110 1100 */ TABDECL(OP_B_COND), // OP_B_COND /* 11 0110 1101 */ TABDECL(OP_B_COND), // OP_B_COND /* 11 0110 1110 */ TABDECL(OP_B_COND), // OP_B_COND /* 11 0110 1111 */ TABDECL(OP_B_COND), // OP_B_COND /* 11 0111 0000 */ TABDECL(OP_B_COND), // OP_B_COND /* 11 0111 0001 */ TABDECL(OP_B_COND), // OP_B_COND /* 11 0111 0010 */ TABDECL(OP_B_COND), // OP_B_COND /* 11 0111 0011 */ TABDECL(OP_B_COND), // OP_B_COND /* 11 0111 0100 */ TABDECL(OP_B_COND), // OP_B_COND /* 11 0111 0101 */ TABDECL(OP_B_COND), // OP_B_COND /* 11 0111 0110 */ TABDECL(OP_B_COND), // OP_B_COND /* 11 0111 0111 */ TABDECL(OP_B_COND), // OP_B_COND /* 11 0111 1000 */ TABDECL(OP_B_COND), // OP_B_COND /* 11 0111 1001 */ TABDECL(OP_B_COND), // OP_B_COND /* 11 0111 1010 */ TABDECL(OP_B_COND), // OP_B_COND /* 11 0111 1011 */ TABDECL(OP_B_COND), // OP_B_COND /* 11 0111 1100 */ TABDECL(OP_SWI_THUMB), // OP_SWI_THUMB /* 11 0111 1101 */ TABDECL(OP_SWI_THUMB), // OP_SWI_THUMB /* 11 0111 1110 */ TABDECL(OP_SWI_THUMB), // OP_SWI_THUMB /* 11 0111 1111 */ TABDECL(OP_SWI_THUMB), // OP_SWI_THUMB /* 11 1000 0000 */ TABDECL(OP_B_UNCOND), // OP_B_UNCOND /* 11 1000 0001 */ TABDECL(OP_B_UNCOND), // OP_B_UNCOND /* 11 1000 0010 */ TABDECL(OP_B_UNCOND), // OP_B_UNCOND /* 11 1000 0011 */ TABDECL(OP_B_UNCOND), // OP_B_UNCOND /* 11 1000 0100 */ TABDECL(OP_B_UNCOND), // OP_B_UNCOND /* 11 1000 0101 */ TABDECL(OP_B_UNCOND), // OP_B_UNCOND /* 11 1000 0110 */ TABDECL(OP_B_UNCOND), // OP_B_UNCOND /* 11 1000 0111 */ TABDECL(OP_B_UNCOND), // OP_B_UNCOND /* 11 1000 1000 */ TABDECL(OP_B_UNCOND), // OP_B_UNCOND /* 11 1000 1001 */ TABDECL(OP_B_UNCOND), // OP_B_UNCOND /* 11 1000 1010 */ TABDECL(OP_B_UNCOND), // OP_B_UNCOND /* 11 1000 1011 */ TABDECL(OP_B_UNCOND), // OP_B_UNCOND /* 11 1000 1100 */ TABDECL(OP_B_UNCOND), // OP_B_UNCOND /* 11 1000 1101 */ TABDECL(OP_B_UNCOND), // OP_B_UNCOND /* 11 1000 1110 */ TABDECL(OP_B_UNCOND), // OP_B_UNCOND /* 11 1000 1111 */ TABDECL(OP_B_UNCOND), // OP_B_UNCOND /* 11 1001 0000 */ TABDECL(OP_B_UNCOND), // OP_B_UNCOND /* 11 1001 0001 */ TABDECL(OP_B_UNCOND), // OP_B_UNCOND /* 11 1001 0010 */ TABDECL(OP_B_UNCOND), // OP_B_UNCOND /* 11 1001 0011 */ TABDECL(OP_B_UNCOND), // OP_B_UNCOND /* 11 1001 0100 */ TABDECL(OP_B_UNCOND), // OP_B_UNCOND /* 11 1001 0101 */ TABDECL(OP_B_UNCOND), // OP_B_UNCOND /* 11 1001 0110 */ TABDECL(OP_B_UNCOND), // OP_B_UNCOND /* 11 1001 0111 */ TABDECL(OP_B_UNCOND), // OP_B_UNCOND /* 11 1001 1000 */ TABDECL(OP_B_UNCOND), // OP_B_UNCOND /* 11 1001 1001 */ TABDECL(OP_B_UNCOND), // OP_B_UNCOND /* 11 1001 1010 */ TABDECL(OP_B_UNCOND), // OP_B_UNCOND /* 11 1001 1011 */ TABDECL(OP_B_UNCOND), // OP_B_UNCOND /* 11 1001 1100 */ TABDECL(OP_B_UNCOND), // OP_B_UNCOND /* 11 1001 1101 */ TABDECL(OP_B_UNCOND), // OP_B_UNCOND /* 11 1001 1110 */ TABDECL(OP_B_UNCOND), // OP_B_UNCOND /* 11 1001 1111 */ TABDECL(OP_B_UNCOND), // OP_B_UNCOND /* 11 1010 0000 */ TABDECL(OP_BLX), // OP_BLX /* 11 1010 0001 */ TABDECL(OP_BLX), // OP_BLX /* 11 1010 0010 */ TABDECL(OP_BLX), // OP_BLX /* 11 1010 0011 */ TABDECL(OP_BLX), // OP_BLX /* 11 1010 0100 */ TABDECL(OP_BLX), // OP_BLX /* 11 1010 0101 */ TABDECL(OP_BLX), // OP_BLX /* 11 1010 0110 */ TABDECL(OP_BLX), // OP_BLX /* 11 1010 0111 */ TABDECL(OP_BLX), // OP_BLX /* 11 1010 1000 */ TABDECL(OP_BLX), // OP_BLX /* 11 1010 1001 */ TABDECL(OP_BLX), // OP_BLX /* 11 1010 1010 */ TABDECL(OP_BLX), // OP_BLX /* 11 1010 1011 */ TABDECL(OP_BLX), // OP_BLX /* 11 1010 1100 */ TABDECL(OP_BLX), // OP_BLX /* 11 1010 1101 */ TABDECL(OP_BLX), // OP_BLX /* 11 1010 1110 */ TABDECL(OP_BLX), // OP_BLX /* 11 1010 1111 */ TABDECL(OP_BLX), // OP_BLX /* 11 1011 0000 */ TABDECL(OP_BLX), // OP_BLX /* 11 1011 0001 */ TABDECL(OP_BLX), // OP_BLX /* 11 1011 0010 */ TABDECL(OP_BLX), // OP_BLX /* 11 1011 0011 */ TABDECL(OP_BLX), // OP_BLX /* 11 1011 0100 */ TABDECL(OP_BLX), // OP_BLX /* 11 1011 0101 */ TABDECL(OP_BLX), // OP_BLX /* 11 1011 0110 */ TABDECL(OP_BLX), // OP_BLX /* 11 1011 0111 */ TABDECL(OP_BLX), // OP_BLX /* 11 1011 1000 */ TABDECL(OP_BLX), // OP_BLX /* 11 1011 1001 */ TABDECL(OP_BLX), // OP_BLX /* 11 1011 1010 */ TABDECL(OP_BLX), // OP_BLX /* 11 1011 1011 */ TABDECL(OP_BLX), // OP_BLX /* 11 1011 1100 */ TABDECL(OP_BLX), // OP_BLX /* 11 1011 1101 */ TABDECL(OP_BLX), // OP_BLX /* 11 1011 1110 */ TABDECL(OP_BLX), // OP_BLX /* 11 1011 1111 */ TABDECL(OP_BLX), // OP_BLX /* 11 1100 0000 */ TABDECL(OP_BL_10), // OP_BL_10 /* 11 1100 0001 */ TABDECL(OP_BL_10), // OP_BL_10 /* 11 1100 0010 */ TABDECL(OP_BL_10), // OP_BL_10 /* 11 1100 0011 */ TABDECL(OP_BL_10), // OP_BL_10 /* 11 1100 0100 */ TABDECL(OP_BL_10), // OP_BL_10 /* 11 1100 0101 */ TABDECL(OP_BL_10), // OP_BL_10 /* 11 1100 0110 */ TABDECL(OP_BL_10), // OP_BL_10 /* 11 1100 0111 */ TABDECL(OP_BL_10), // OP_BL_10 /* 11 1100 1000 */ TABDECL(OP_BL_10), // OP_BL_10 /* 11 1100 1001 */ TABDECL(OP_BL_10), // OP_BL_10 /* 11 1100 1010 */ TABDECL(OP_BL_10), // OP_BL_10 /* 11 1100 1011 */ TABDECL(OP_BL_10), // OP_BL_10 /* 11 1100 1100 */ TABDECL(OP_BL_10), // OP_BL_10 /* 11 1100 1101 */ TABDECL(OP_BL_10), // OP_BL_10 /* 11 1100 1110 */ TABDECL(OP_BL_10), // OP_BL_10 /* 11 1100 1111 */ TABDECL(OP_BL_10), // OP_BL_10 /* 11 1101 0000 */ TABDECL(OP_BL_10), // OP_BL_10 /* 11 1101 0001 */ TABDECL(OP_BL_10), // OP_BL_10 /* 11 1101 0010 */ TABDECL(OP_BL_10), // OP_BL_10 /* 11 1101 0011 */ TABDECL(OP_BL_10), // OP_BL_10 /* 11 1101 0100 */ TABDECL(OP_BL_10), // OP_BL_10 /* 11 1101 0101 */ TABDECL(OP_BL_10), // OP_BL_10 /* 11 1101 0110 */ TABDECL(OP_BL_10), // OP_BL_10 /* 11 1101 0111 */ TABDECL(OP_BL_10), // OP_BL_10 /* 11 1101 1000 */ TABDECL(OP_BL_10), // OP_BL_10 /* 11 1101 1001 */ TABDECL(OP_BL_10), // OP_BL_10 /* 11 1101 1010 */ TABDECL(OP_BL_10), // OP_BL_10 /* 11 1101 1011 */ TABDECL(OP_BL_10), // OP_BL_10 /* 11 1101 1100 */ TABDECL(OP_BL_10), // OP_BL_10 /* 11 1101 1101 */ TABDECL(OP_BL_10), // OP_BL_10 /* 11 1101 1110 */ TABDECL(OP_BL_10), // OP_BL_10 /* 11 1101 1111 */ TABDECL(OP_BL_10), // OP_BL_10 /* 11 1110 0000 */ TABDECL(OP_BL_11), // OP_BL_11 /* 11 1110 0001 */ TABDECL(OP_BL_11), // OP_BL_11 /* 11 1110 0010 */ TABDECL(OP_BL_11), // OP_BL_11 /* 11 1110 0011 */ TABDECL(OP_BL_11), // OP_BL_11 /* 11 1110 0100 */ TABDECL(OP_BL_11), // OP_BL_11 /* 11 1110 0101 */ TABDECL(OP_BL_11), // OP_BL_11 /* 11 1110 0110 */ TABDECL(OP_BL_11), // OP_BL_11 /* 11 1110 0111 */ TABDECL(OP_BL_11), // OP_BL_11 /* 11 1110 1000 */ TABDECL(OP_BL_11), // OP_BL_11 /* 11 1110 1001 */ TABDECL(OP_BL_11), // OP_BL_11 /* 11 1110 1010 */ TABDECL(OP_BL_11), // OP_BL_11 /* 11 1110 1011 */ TABDECL(OP_BL_11), // OP_BL_11 /* 11 1110 1100 */ TABDECL(OP_BL_11), // OP_BL_11 /* 11 1110 1101 */ TABDECL(OP_BL_11), // OP_BL_11 /* 11 1110 1110 */ TABDECL(OP_BL_11), // OP_BL_11 /* 11 1110 1111 */ TABDECL(OP_BL_11), // OP_BL_11 /* 11 1111 0000 */ TABDECL(OP_BL_11), // OP_BL_11 /* 11 1111 0001 */ TABDECL(OP_BL_11), // OP_BL_11 /* 11 1111 0010 */ TABDECL(OP_BL_11), // OP_BL_11 /* 11 1111 0011 */ TABDECL(OP_BL_11), // OP_BL_11 /* 11 1111 0100 */ TABDECL(OP_BL_11), // OP_BL_11 /* 11 1111 0101 */ TABDECL(OP_BL_11), // OP_BL_11 /* 11 1111 0110 */ TABDECL(OP_BL_11), // OP_BL_11 /* 11 1111 0111 */ TABDECL(OP_BL_11), // OP_BL_11 /* 11 1111 1000 */ TABDECL(OP_BL_11), // OP_BL_11 /* 11 1111 1001 */ TABDECL(OP_BL_11), // OP_BL_11 /* 11 1111 1010 */ TABDECL(OP_BL_11), // OP_BL_11 /* 11 1111 1011 */ TABDECL(OP_BL_11), // OP_BL_11 /* 11 1111 1100 */ TABDECL(OP_BL_11), // OP_BL_11 /* 11 1111 1101 */ TABDECL(OP_BL_11), // OP_BL_11 /* 11 1111 1110 */ TABDECL(OP_BL_11), // OP_BL_11 /* 11 1111 1111 */ TABDECL(OP_BL_11), // OP_BL_11 desmume/src/libretro-common/formats/tga/rtga.c000664 001750 001750 00000032650 12755534123 022604 0ustar00sergiosergio000000 000000 #include #include #include #include /* ptrdiff_t on osx */ #include #include #include #include #include #include struct rtga { uint8_t *buff_data; uint32_t *output_image; void *empty; }; typedef struct { int (*read) (void *user,char *data,int size); /* fill 'data' with 'size' bytes. return number of bytes actually read */ void (*skip) (void *user,int n); /* skip the next 'n' bytes, or 'unget' the last -n bytes if negative */ int (*eof) (void *user); /* returns nonzero if we are at end of file/data */ } rtga_io_callbacks; typedef struct { uint32_t img_x, img_y; int img_n, img_out_n; rtga_io_callbacks io; void *io_user_data; int read_from_callbacks; int buflen; uint8_t buffer_start[128]; uint8_t *img_buffer, *img_buffer_end; uint8_t *img_buffer_original; } rtga__context; static void rtga__refill_buffer(rtga__context *s); static void rtga__start_mem(rtga__context *s, uint8_t const *buffer, int len) { s->io.read = NULL; s->read_from_callbacks = 0; s->img_buffer = s->img_buffer_original = (uint8_t *) buffer; s->img_buffer_end = (uint8_t *) buffer+len; } static uint8_t *rtga__tga_load(rtga__context *s, unsigned *x, unsigned *y, int *comp, int req_comp); #define rtga__err(x,y) 0 #define rtga__errpf(x,y) ((float *) (rtga__err(x,y)?NULL:NULL)) #define rtga__errpuc(x,y) ((unsigned char *) (rtga__err(x,y)?NULL:NULL)) static uint8_t *rtga_load_from_memory(uint8_t const *buffer, int len, unsigned *x, unsigned *y, int *comp, int req_comp) { rtga__context s; rtga__start_mem(&s,buffer,len); return rtga__tga_load(&s,x,y,comp,req_comp); } static void rtga__refill_buffer(rtga__context *s) { int n = (s->io.read)(s->io_user_data,(char*)s->buffer_start,s->buflen); if (n == 0) { /* at end of file, treat same as if from memory, but need to handle case * where s->img_buffer isn't pointing to safe memory, e.g. 0-byte file */ s->read_from_callbacks = 0; s->img_buffer = s->buffer_start; s->img_buffer_end = s->buffer_start+1; *s->img_buffer = 0; } else { s->img_buffer = s->buffer_start; s->img_buffer_end = s->buffer_start + n; } } static INLINE uint8_t rtga__get8(rtga__context *s) { if (s->img_buffer < s->img_buffer_end) return *s->img_buffer++; if (s->read_from_callbacks) { rtga__refill_buffer(s); return *s->img_buffer++; } return 0; } static void rtga__skip(rtga__context *s, int n) { if (n < 0) { s->img_buffer = s->img_buffer_end; return; } if (s->io.read) { int blen = (int) (s->img_buffer_end - s->img_buffer); if (blen < n) { s->img_buffer = s->img_buffer_end; (s->io.skip)(s->io_user_data, n - blen); return; } } s->img_buffer += n; } static int rtga__getn(rtga__context *s, uint8_t *buffer, int n) { if (s->io.read) { int blen = (int) (s->img_buffer_end - s->img_buffer); if (blen < n) { int res, count; memcpy(buffer, s->img_buffer, blen); count = (s->io.read)(s->io_user_data, (char*) buffer + blen, n - blen); res = (count == (n-blen)); s->img_buffer = s->img_buffer_end; return res; } } if (s->img_buffer+n <= s->img_buffer_end) { memcpy(buffer, s->img_buffer, n); s->img_buffer += n; return 1; } else return 0; } static int rtga__get16le(rtga__context *s) { int z = rtga__get8(s); return z + (rtga__get8(s) << 8); } static uint8_t rtga__compute_y(int r, int g, int b) { return (uint8_t) (((r*77) + (g*150) + (29*b)) >> 8); } static unsigned char *rtga__convert_format( unsigned char *data, int img_n, int req_comp, unsigned int x, unsigned int y) { int i,j; unsigned char *good; if (req_comp == img_n) return data; retro_assert(req_comp >= 1 && req_comp <= 4); good = (unsigned char *) malloc(req_comp * x * y); if (good == NULL) { free(data); return rtga__errpuc("outofmem", "Out of memory"); } for (j=0; j < (int) y; ++j) { unsigned char *src = data + j * x * img_n ; unsigned char *dest = good + j * x * req_comp; switch (((img_n)*8+(req_comp))) { case ((1)*8+(2)): for(i=x-1; i >= 0; --i, src += 1, dest += 2) dest[0]=src[0], dest[1]=255; break; case ((1)*8+(3)): for(i=x-1; i >= 0; --i, src += 1, dest += 3) dest[0]=dest[1]=dest[2]=src[0]; break; case ((1)*8+(4)): for(i=x-1; i >= 0; --i, src += 1, dest += 4) dest[0]=dest[1]=dest[2]=src[0], dest[3]=255; break; case ((2)*8+(1)): for(i=x-1; i >= 0; --i, src += 2, dest += 1) dest[0]=src[0]; break; case ((2)*8+(3)): for(i=x-1; i >= 0; --i, src += 2, dest += 3) dest[0]=dest[1]=dest[2]=src[0]; break; case ((2)*8+(4)): for(i=x-1; i >= 0; --i, src += 2, dest += 4) dest[0]=dest[1]=dest[2]=src[0], dest[3]=src[1]; break; case ((3)*8+(4)): for(i=x-1; i >= 0; --i, src += 3, dest += 4) dest[0]=src[0],dest[1]=src[1],dest[2]=src[2],dest[3]=255; break; case ((3)*8+(1)): for(i=x-1; i >= 0; --i, src += 3, dest += 1) dest[0]=rtga__compute_y(src[0],src[1],src[2]); break; case ((3)*8+(2)): for(i=x-1; i >= 0; --i, src += 3, dest += 2) dest[0]=rtga__compute_y(src[0],src[1],src[2]), dest[1] = 255; break; case ((4)*8+(1)): for(i=x-1; i >= 0; --i, src += 4, dest += 1) dest[0]=rtga__compute_y(src[0],src[1],src[2]); break; case ((4)*8+(2)): for(i=x-1; i >= 0; --i, src += 4, dest += 2) dest[0]=rtga__compute_y(src[0],src[1],src[2]), dest[1] = src[3]; break; case ((4)*8+(3)): for(i=x-1; i >= 0; --i, src += 4, dest += 3) dest[0]=src[0],dest[1]=src[1],dest[2]=src[2]; break; default: retro_assert(0); break; } } free(data); return good; } static uint8_t *rtga__tga_load(rtga__context *s, unsigned *x, unsigned *y, int *comp, int req_comp) { /* Read in the TGA header stuff */ int tga_offset = rtga__get8(s); int tga_indexed = rtga__get8(s); int tga_image_type = rtga__get8(s); int tga_is_RLE = 0; int tga_palette_start = rtga__get16le(s); int tga_palette_len = rtga__get16le(s); int tga_palette_bits = rtga__get8(s); int tga_x_origin = rtga__get16le(s); int tga_y_origin = rtga__get16le(s); int tga_width = rtga__get16le(s); int tga_height = rtga__get16le(s); int tga_bits_per_pixel = rtga__get8(s); int tga_comp = tga_bits_per_pixel / 8; int tga_inverted = rtga__get8(s); /* image data */ unsigned char *tga_data; unsigned char *tga_palette = NULL; int i, j; unsigned char raw_data[4] = {0}; int RLE_count = 0; int RLE_repeating = 0; int read_next_pixel = 1; (void)tga_palette_start; (void)tga_x_origin; (void)tga_y_origin; /* do a tiny bit of precessing */ if ( tga_image_type >= 8 ) { tga_image_type -= 8; tga_is_RLE = 1; } /* int tga_alpha_bits = tga_inverted & 15; */ tga_inverted = 1 - ((tga_inverted >> 5) & 1); /* error check */ if ( (tga_width < 1) || (tga_height < 1) || (tga_image_type < 1) || (tga_image_type > 3) || ((tga_bits_per_pixel != 8) && (tga_bits_per_pixel != 16) && (tga_bits_per_pixel != 24) && (tga_bits_per_pixel != 32)) ) return NULL; /* we don't report this as a bad TGA because we don't even know if it's TGA */ /* If paletted, then we will use the number of bits from the palette */ if ( tga_indexed ) tga_comp = tga_palette_bits / 8; /* TGA info */ *x = tga_width; *y = tga_height; if (comp) *comp = tga_comp; tga_data = (unsigned char*)malloc( (size_t)tga_width * tga_height * tga_comp ); if (!tga_data) return rtga__errpuc("outofmem", "Out of memory"); /* skip to the data's starting position (offset usually = 0) */ rtga__skip(s, tga_offset ); if ( !tga_indexed && !tga_is_RLE) { for (i=0; i < tga_height; ++i) { int y = tga_inverted ? tga_height -i - 1 : i; uint8_t *tga_row = tga_data + y*tga_width*tga_comp; rtga__getn(s, tga_row, tga_width * tga_comp); } } else { /* Do I need to load a palette? */ if ( tga_indexed) { /* any data to skip? (offset usually = 0) */ rtga__skip(s, tga_palette_start ); /* load the palette */ tga_palette = (unsigned char*)malloc( tga_palette_len * tga_palette_bits / 8 ); if (!tga_palette) { free(tga_data); return rtga__errpuc("outofmem", "Out of memory"); } if (!rtga__getn(s, tga_palette, tga_palette_len * tga_palette_bits / 8 )) { free(tga_data); free(tga_palette); return rtga__errpuc("bad palette", "Corrupt TGA"); } } /* load the data */ for (i=0; i < tga_width * tga_height; ++i) { /* if I'm in RLE mode, do I need to get a RLE rtga__pngchunk? */ if ( tga_is_RLE ) { if ( RLE_count == 0 ) { /* yep, get the next byte as a RLE command */ int RLE_cmd = rtga__get8(s); RLE_count = 1 + (RLE_cmd & 127); RLE_repeating = RLE_cmd >> 7; read_next_pixel = 1; } else if ( !RLE_repeating ) read_next_pixel = 1; } else read_next_pixel = 1; /* OK, if I need to read a pixel, do it now */ if ( read_next_pixel ) { /* load however much data we did have */ if ( tga_indexed ) { /* read in 1 byte, then perform the lookup */ int pal_idx = rtga__get8(s); if ( pal_idx >= tga_palette_len ) /* invalid index */ pal_idx = 0; pal_idx *= tga_bits_per_pixel / 8; for (j = 0; j*8 < tga_bits_per_pixel; ++j) raw_data[j] = tga_palette[pal_idx+j]; } else { /* read in the data raw */ for (j = 0; j*8 < tga_bits_per_pixel; ++j) raw_data[j] = rtga__get8(s); } /* clear the reading flag for the next pixel */ read_next_pixel = 0; } /* end of reading a pixel */ /* copy data */ for (j = 0; j < tga_comp; ++j) tga_data[i*tga_comp+j] = raw_data[j]; /* in case we're in RLE mode, keep counting down */ --RLE_count; } /* do I need to invert the image? */ if ( tga_inverted ) { for (j = 0; j*2 < tga_height; ++j) { int index1 = j * tga_width * tga_comp; int index2 = (tga_height - 1 - j) * tga_width * tga_comp; for (i = tga_width * tga_comp; i > 0; --i) { unsigned char temp = tga_data[index1]; tga_data[index1] = tga_data[index2]; tga_data[index2] = temp; ++index1; ++index2; } } } /* Clear my palette, if I had one */ if ( tga_palette != NULL ) free( tga_palette ); } /* swap RGB */ if (tga_comp >= 3) { unsigned char* tga_pixel = tga_data; for (i=0; i < tga_width * tga_height; ++i) { unsigned char temp = tga_pixel[0]; tga_pixel[0] = tga_pixel[2]; tga_pixel[2] = temp; tga_pixel += tga_comp; } } /* convert to target component count */ if (req_comp && req_comp != tga_comp) tga_data = rtga__convert_format(tga_data, tga_comp, req_comp, tga_width, tga_height); return tga_data; } int rtga_process_image(rtga_t *rtga, void **buf_data, size_t size, unsigned *width, unsigned *height) { int comp; unsigned size_tex = 0; if (!rtga) return IMAGE_PROCESS_ERROR; rtga->output_image = (uint32_t*)rtga_load_from_memory(rtga->buff_data, size, width, height, &comp, 4); *buf_data = rtga->output_image; size_tex = (*width) * (*height); /* Convert RGBA to ARGB */ while(size_tex--) { unsigned int texel = rtga->output_image[size_tex]; unsigned int A = texel & 0xFF000000; unsigned int B = texel & 0x00FF0000; unsigned int G = texel & 0x0000FF00; unsigned int R = texel & 0x000000FF; ((unsigned int*)rtga->output_image)[size_tex] = A | (R << 16) | G | (B >> 16); }; return IMAGE_PROCESS_END; } bool rtga_set_buf_ptr(rtga_t *rtga, void *data) { if (!rtga) return false; rtga->buff_data = (uint8_t*)data; return true; } void rtga_free(rtga_t *rtga) { if (!rtga) return; free(rtga); } rtga_t *rtga_alloc(void) { rtga_t *rtga = (rtga_t*)calloc(1, sizeof(*rtga)); if (!rtga) return NULL; return rtga; } desmume/src/libretro-common/include/glsm/000700 001750 001750 00000000000 12756420131 021612 5ustar00sergiosergio000000 000000 desmume/src/utils/libfat/directory.h000664 001750 001750 00000014214 12755534123 020717 0ustar00sergiosergio000000 000000 /* directory.h Reading, writing and manipulation of the directory structure on a FAT partition Copyright (c) 2006 Michael "Chishm" Chisholm Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. 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. 3. The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. */ #ifndef _DIRECTORY_H #define _DIRECTORY_H #include #include "common.h" #include "partition.h" #define DIR_ENTRY_DATA_SIZE 0x20 #define MAX_LFN_LENGTH 256 #define MAX_FILENAME_LENGTH 768 // 256 UCS-2 characters encoded into UTF-8 can use up to 768 UTF-8 chars #define MAX_ALIAS_LENGTH 13 #define LFN_ENTRY_LENGTH 13 #define ALIAS_ENTRY_LENGTH 11 #define MAX_ALIAS_EXT_LENGTH 3 #define MAX_ALIAS_PRI_LENGTH 8 #define MAX_NUMERIC_TAIL 999999 #define FAT16_ROOT_DIR_CLUSTER 0 #define DIR_SEPARATOR '/' // File attributes #define ATTRIB_ARCH 0x20 // Archive #define ATTRIB_DIR 0x10 // Directory #define ATTRIB_LFN 0x0F // Long file name #define ATTRIB_VOL 0x08 // Volume #define ATTRIB_SYS 0x04 // System #define ATTRIB_HID 0x02 // Hidden #define ATTRIB_RO 0x01 // Read only #ifdef __cplusplus extern "C" { #endif typedef enum {FT_DIRECTORY, FT_FILE} FILE_TYPE; typedef struct { uint32_t cluster; sec_t sector; int32_t offset; } DIR_ENTRY_POSITION; typedef struct { uint8_t entryData[DIR_ENTRY_DATA_SIZE]; DIR_ENTRY_POSITION dataStart; // Points to the start of the LFN entries of a file, or the alias for no LFN DIR_ENTRY_POSITION dataEnd; // Always points to the file/directory's alias entry char filename[MAX_FILENAME_LENGTH]; } DIR_ENTRY; // Directory entry offsets enum DIR_ENTRY_offset { DIR_ENTRY_name = 0x00, DIR_ENTRY_extension = 0x08, DIR_ENTRY_attributes = 0x0B, DIR_ENTRY_reserved = 0x0C, DIR_ENTRY_cTime_ms = 0x0D, DIR_ENTRY_cTime = 0x0E, DIR_ENTRY_cDate = 0x10, DIR_ENTRY_aDate = 0x12, DIR_ENTRY_clusterHigh = 0x14, DIR_ENTRY_mTime = 0x16, DIR_ENTRY_mDate = 0x18, DIR_ENTRY_cluster = 0x1A, DIR_ENTRY_fileSize = 0x1C }; /* Returns true if the file specified by entry is a directory */ static inline bool _FAT_directory_isDirectory (DIR_ENTRY* entry) { return ((entry->entryData[DIR_ENTRY_attributes] & ATTRIB_DIR) != 0); } static inline bool _FAT_directory_isWritable (DIR_ENTRY* entry) { return ((entry->entryData[DIR_ENTRY_attributes] & ATTRIB_RO) == 0); } static inline bool _FAT_directory_isDot (DIR_ENTRY* entry) { return ((entry->filename[0] == '.') && ((entry->filename[1] == '\0') || ((entry->filename[1] == '.') && entry->filename[2] == '\0'))); } /* Reads the first directory entry from the directory starting at dirCluster Places result in entry entry will be destroyed even if no directory entry is found Returns true on success, false on failure */ bool _FAT_directory_getFirstEntry (PARTITION* partition, DIR_ENTRY* entry, uint32_t dirCluster); /* Reads the next directory entry after the one already pointed to by entry Places result in entry entry will be destroyed even if no directory entry is found Returns true on success, false on failure */ bool _FAT_directory_getNextEntry (PARTITION* partition, DIR_ENTRY* entry); /* Gets the directory entry corrsponding to the supplied path entry will be destroyed even if no directory entry is found pathEnd specifies the end of the path string, for cutting strings short if needed specify NULL to use the full length of path pathEnd is only a suggestion, and the path string will be searched up until the next PATH_SEPARATOR after pathEND. Returns true on success, false on failure */ bool _FAT_directory_entryFromPath (PARTITION* partition, DIR_ENTRY* entry, const char* path, const char* pathEnd); /* Changes the current directory to the one specified by path Returns true on success, false on failure */ bool _FAT_directory_chdir (PARTITION* partition, const char* path); /* Removes the directory entry specified by entry Assumes that entry is valid Returns true on success, false on failure */ bool _FAT_directory_removeEntry (PARTITION* partition, DIR_ENTRY* entry); /* Add a directory entry to the directory specified by dirCluster The fileData, dataStart and dataEnd elements of the DIR_ENTRY struct are updated with the new directory entry position and alias. Returns true on success, false on failure */ bool _FAT_directory_addEntry (PARTITION* partition, DIR_ENTRY* entry, uint32_t dirCluster); /* Get the start cluster of a file from it's entry data */ uint32_t _FAT_directory_entryGetCluster (PARTITION* partition, const uint8_t* entryData); /* Fill in the file name and entry data of DIR_ENTRY* entry. Assumes that the entry's dataStart and dataEnd are correct Returns true on success, false on failure */ bool _FAT_directory_entryFromPosition (PARTITION* partition, DIR_ENTRY* entry); /* Fill in a stat struct based on a file entry */ void _FAT_directory_entryStat (PARTITION* partition, DIR_ENTRY* entry, struct stat *st); /* Get volume label */ bool _FAT_directory_getVolumeLabel (PARTITION* partition, char *label); #ifdef __cplusplus } #endif #endif // _DIRECTORY_H desmume/src/utils/AsmJit/core/memorymarker.h000664 001750 001750 00000002427 12755534123 022306 0ustar00sergiosergio000000 000000 // [AsmJit] // Complete JIT Assembler for C++ Language. // // [License] // Zlib - See COPYING file in this package. // [Guard] #ifndef _ASMJIT_CORE_MEMORYMARKER_H #define _ASMJIT_CORE_MEMORYMARKER_H // [Dependencies - AsmJit] #include "../core/build.h" #include "../core/defs.h" // [Api-Begin] #include "../core/apibegin.h" namespace AsmJit { //! @addtogroup AsmJit_MemoryManagement //! @{ // ============================================================================ // [AsmJit::MemoryMarker] // ============================================================================ //! @brief Virtual memory marker interface. struct MemoryMarker { ASMJIT_NO_COPY(MemoryMarker) // -------------------------------------------------------------------------- // [Construction / Destruction] // -------------------------------------------------------------------------- ASMJIT_API MemoryMarker(); ASMJIT_API virtual ~MemoryMarker(); // -------------------------------------------------------------------------- // [Interface] // -------------------------------------------------------------------------- virtual void mark(const void* ptr, size_t size) = 0; }; //! @} } // AsmJit namespace // [Api-End] #include "../core/apiend.h" // [Guard] #endif // _ASMJIT_CORE_MEMORYMARKER_H desmume/src/utils/libfat/directory.c000664 001750 001750 00000105546 12755534123 020723 0ustar00sergiosergio000000 000000 /* directory.c Reading, writing and manipulation of the directory structure on a FAT partition Copyright (c) 2006 Michael "Chishm" Chisholm Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. 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. 3. The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 #include #include "directory.h" #include "common.h" #include "partition.h" #include "file_allocation_table.h" #include "bit_ops.h" #include "filetime.h" #ifdef __APPLE__ #include #ifndef MAC_OS_X_VERSION_10_7 #define COMPILE_IN_STRNLEN #endif #endif // __APPLE__ #if defined(_WIN32) && !defined(_MSC_VER) && !defined(__MINGW64_VERSION_MAJOR) #define COMPILE_IN_STRNLEN #include #endif #ifdef COMPILE_IN_STRNLEN // In Mac OS X, strnlen() is unsupported prior to v10.7, so define it here. // mingw-w64 has it's own implementation of strnlen(), defined in in libw64crt. static size_t strnlen(const char *s, size_t n) { const char *p = (const char *)memchr(s, 0, n); return(p ? p-s : n); } #endif // Directory entry codes #define DIR_ENTRY_LAST 0x00 #define DIR_ENTRY_FREE 0xE5 #define LAST_LFN_POS (19*13) #define LAST_LFN_POS_CORRECTION (MAX_LFN_LENGTH-15) typedef unsigned short ucs2_t; // Long file name directory entry enum LFN_offset { LFN_offset_ordinal = 0x00, // Position within LFN LFN_offset_char0 = 0x01, LFN_offset_char1 = 0x03, LFN_offset_char2 = 0x05, LFN_offset_char3 = 0x07, LFN_offset_char4 = 0x09, LFN_offset_flag = 0x0B, // Should be equal to ATTRIB_LFN LFN_offset_reserved1 = 0x0C, // Always 0x00 LFN_offset_checkSum = 0x0D, // Checksum of short file name (alias) LFN_offset_char5 = 0x0E, LFN_offset_char6 = 0x10, LFN_offset_char7 = 0x12, LFN_offset_char8 = 0x14, LFN_offset_char9 = 0x16, LFN_offset_char10 = 0x18, LFN_offset_reserved2 = 0x1A, // Always 0x0000 LFN_offset_char11 = 0x1C, LFN_offset_char12 = 0x1E }; static const int LFN_offset_table[13]={0x01,0x03,0x05,0x07,0x09,0x0E,0x10,0x12,0x14,0x16,0x18,0x1C,0x1E}; #define LFN_END 0x40 #define LFN_DEL 0x80 static const char ILLEGAL_ALIAS_CHARACTERS[] = "\\/:;*?\"<>|&+,=[] "; static const char ILLEGAL_LFN_CHARACTERS[] = "\\/:*?\"<>|"; /* Returns number of UCS-2 characters needed to encode an LFN Returns -1 if it is an invalid LFN */ #define ABOVE_UCS_RANGE 0xF0 static int _FAT_directory_lfnLength (const char* name) { unsigned int i; size_t nameLength; int ucsLength; const char* tempName = name; nameLength = strnlen(name, MAX_FILENAME_LENGTH); // Make sure the name is short enough to be valid if ( nameLength >= MAX_FILENAME_LENGTH) { return -1; } // Make sure it doesn't contain any invalid characters if (strpbrk (name, ILLEGAL_LFN_CHARACTERS) != NULL) { return -1; } // Make sure the name doesn't contain any control codes or codes not representable in UCS-2 for (i = 0; i < nameLength; i++) { if (name[i] < 0x20 || name[i] >= ABOVE_UCS_RANGE) { return -1; } } // Convert to UCS-2 and get the resulting length ucsLength = mbsrtowcs(NULL, &tempName, MAX_LFN_LENGTH, NULL); if (ucsLength < 0 || ucsLength >= MAX_LFN_LENGTH) { return -1; } // Otherwise it is valid return ucsLength; } /* Convert a multibyte encoded string into a NUL-terminated UCS-2 string, storing at most len characters return number of characters stored */ static size_t _FAT_directory_mbstoucs2 (ucs2_t* dst, const char* src, size_t len) { mbstate_t ps = {0}; wchar_t tempChar; int bytes; size_t count = 0; while (count < len-1 && *src != '\0') { bytes = mbrtowc (&tempChar, src, MB_CUR_MAX, &ps); if (bytes > 0) { *dst = (ucs2_t)tempChar; src += bytes; dst++; count++; } else if (bytes == 0) { break; } else { return -1; } } *dst = '\0'; return count; } /* Convert a UCS-2 string into a NUL-terminated multibyte string, storing at most len chars return number of chars stored, or (size_t)-1 on error */ static size_t _FAT_directory_ucs2tombs (char* dst, const ucs2_t* src, size_t len) { mbstate_t ps = {0}; size_t count = 0; int bytes; char* buff = (char*)alloca(MB_CUR_MAX); int i; while (count < len - 1 && *src != '\0') { bytes = wcrtomb (buff, *src, &ps); if (bytes < 0) { return -1; } if (count + bytes < len && bytes > 0) { for (i = 0; i < bytes; i++) { *dst++ = buff[i]; } src++; count += bytes; } else { break; } } *dst = L'\0'; return count; } /* Case-independent comparison of two multibyte encoded strings */ static int _FAT_directory_mbsncasecmp (const char* s1, const char* s2, size_t len1) { wchar_t wc1, wc2; mbstate_t ps1 = {0}; mbstate_t ps2 = {0}; size_t b1 = 0; size_t b2 = 0; if (len1 == 0) { return 0; } do { s1 += b1; s2 += b2; b1 = mbrtowc(&wc1, s1, MB_CUR_MAX, &ps1); b2 = mbrtowc(&wc2, s2, MB_CUR_MAX, &ps2); if ((int)b1 < 0 || (int)b2 < 0) { break; } len1 -= b1; } while (len1 > 0 && towlower(wc1) == towlower(wc2) && wc1 != 0); return towlower(wc1) - towlower(wc2); } static bool _FAT_directory_entryGetAlias (const uint8_t * entryData, char* destName) { int i=0; int j=0; destName[0] = '\0'; if (entryData[0] != DIR_ENTRY_FREE) { if (entryData[0] == '.') { destName[0] = '.'; if (entryData[1] == '.') { destName[1] = '.'; destName[2] = '\0'; } else { destName[1] = '\0'; } } else { // Copy the filename from the dirEntry to the string for (i = 0; (i < 8) && (entryData[DIR_ENTRY_name + i] != ' '); i++) { destName[i] = entryData[DIR_ENTRY_name + i]; } // Copy the extension from the dirEntry to the string if (entryData[DIR_ENTRY_extension] != ' ') { destName[i++] = '.'; for ( j = 0; (j < 3) && (entryData[DIR_ENTRY_extension + j] != ' '); j++) { destName[i++] = entryData[DIR_ENTRY_extension + j]; } } destName[i] = '\0'; } } return (destName[0] != '\0'); } uint32_t _FAT_directory_entryGetCluster (PARTITION* partition, const uint8_t* entryData) { if (partition->filesysType == FS_FAT32) { // Only use high 16 bits of start cluster when we are certain they are correctly defined return u8array_to_u16(entryData,DIR_ENTRY_cluster) | (u8array_to_u16(entryData, DIR_ENTRY_clusterHigh) << 16); } else { return u8array_to_u16(entryData,DIR_ENTRY_cluster); } } static bool _FAT_directory_incrementDirEntryPosition (PARTITION* partition, DIR_ENTRY_POSITION* entryPosition, bool extendDirectory) { DIR_ENTRY_POSITION position = *entryPosition; uint32_t tempCluster; // Increment offset, wrapping at the end of a sector ++ position.offset; if (position.offset == BYTES_PER_READ / DIR_ENTRY_DATA_SIZE) { position.offset = 0; // Increment sector when wrapping ++ position.sector; // But wrap at the end of a cluster if ((position.sector == partition->sectorsPerCluster) && (position.cluster != FAT16_ROOT_DIR_CLUSTER)) { position.sector = 0; // Move onto the next cluster, making sure there is another cluster to go to tempCluster = _FAT_fat_nextCluster(partition, position.cluster); if (tempCluster == CLUSTER_EOF) { if (extendDirectory) { tempCluster = _FAT_fat_linkFreeClusterCleared (partition, position.cluster); if (!_FAT_fat_isValidCluster(partition, tempCluster)) { return false; // This will only happen if the disc is full } } else { return false; // Got to the end of the directory, not extending it } } position.cluster = tempCluster; } else if ((position.cluster == FAT16_ROOT_DIR_CLUSTER) && (position.sector == (partition->dataStart - partition->rootDirStart))) { return false; // Got to end of root directory, can't extend it } } *entryPosition = position; return true; } bool _FAT_directory_getNextEntry (PARTITION* partition, DIR_ENTRY* entry) { DIR_ENTRY_POSITION entryStart; DIR_ENTRY_POSITION entryEnd; uint8_t entryData[0x20]; ucs2_t lfn[MAX_LFN_LENGTH]; bool notFound, found; int lfnPos; uint8_t lfnChkSum, chkSum; bool lfnExists; int i; lfnChkSum = 0; entryStart = entry->dataEnd; // Make sure we are using the correct root directory, in case of FAT32 if (entryStart.cluster == FAT16_ROOT_DIR_CLUSTER) { entryStart.cluster = partition->rootDirCluster; } entryEnd = entryStart; lfnExists = false; found = false; notFound = false; while (!found && !notFound) { if (_FAT_directory_incrementDirEntryPosition (partition, &entryEnd, false) == false) { notFound = true; } _FAT_cache_readPartialSector (partition->cache, entryData, _FAT_fat_clusterToSector(partition, entryEnd.cluster) + entryEnd.sector, entryEnd.offset * DIR_ENTRY_DATA_SIZE, DIR_ENTRY_DATA_SIZE); if (entryData[DIR_ENTRY_attributes] == ATTRIB_LFN) { // It's an LFN if (entryData[LFN_offset_ordinal] & LFN_DEL) { lfnExists = false; } else if (entryData[LFN_offset_ordinal] & LFN_END) { // Last part of LFN, make sure it isn't deleted using previous if(Thanks MoonLight) entryStart = entryEnd; // This is the start of a directory entry lfnExists = true; lfnPos = (entryData[LFN_offset_ordinal] & ~LFN_END) * 13; if (lfnPos > MAX_LFN_LENGTH - 1) { lfnPos = MAX_LFN_LENGTH - 1; } lfn[lfnPos] = '\0'; // Set end of lfn to null character lfnChkSum = entryData[LFN_offset_checkSum]; } if (lfnChkSum != entryData[LFN_offset_checkSum]) { lfnExists = false; } if (lfnExists) { lfnPos = ((entryData[LFN_offset_ordinal] & ~LFN_END) - 1) * 13; if (lfnPos > LAST_LFN_POS) { // Force it within the buffer. Will corrupt the filename but prevent buffer overflows lfnPos = LAST_LFN_POS; } for (i = 0; i < 13; i++) { lfn[lfnPos + i] = entryData[LFN_offset_table[i]] | (entryData[LFN_offset_table[i]+1] << 8); } } } else if (entryData[DIR_ENTRY_attributes] & ATTRIB_VOL) { // This is a volume name, don't bother with it } else if (entryData[0] == DIR_ENTRY_LAST) { notFound = true; } else if ((entryData[0] != DIR_ENTRY_FREE) && (entryData[0] > 0x20) && !(entryData[DIR_ENTRY_attributes] & ATTRIB_VOL)) { if (lfnExists) { // Calculate file checksum chkSum = 0; for (i=0; i < 11; i++) { // NOTE: The operation is an unsigned char rotate right chkSum = ((chkSum & 1) ? 0x80 : 0) + (chkSum >> 1) + entryData[i]; } if (chkSum != lfnChkSum) { lfnExists = false; entry->filename[0] = '\0'; } } if (lfnExists) { if (_FAT_directory_ucs2tombs (entry->filename, lfn, MAX_FILENAME_LENGTH) == (size_t)-1) { // Failed to convert the file name to UTF-8. Maybe the wrong locale is set? return false; } } else { entryStart = entryEnd; _FAT_directory_entryGetAlias (entryData, entry->filename); } found = true; } } // If no file is found, return false if (notFound) { return false; } else { // Fill in the directory entry struct entry->dataStart = entryStart; entry->dataEnd = entryEnd; memcpy (entry->entryData, entryData, DIR_ENTRY_DATA_SIZE); return true; } } bool _FAT_directory_getFirstEntry (PARTITION* partition, DIR_ENTRY* entry, uint32_t dirCluster) { entry->dataStart.cluster = dirCluster; entry->dataStart.sector = 0; entry->dataStart.offset = -1; // Start before the beginning of the directory entry->dataEnd = entry->dataStart; return _FAT_directory_getNextEntry (partition, entry); } bool _FAT_directory_getRootEntry (PARTITION* partition, DIR_ENTRY* entry) { entry->dataStart.cluster = 0; entry->dataStart.sector = 0; entry->dataStart.offset = 0; entry->dataEnd = entry->dataStart; memset (entry->filename, '\0', MAX_FILENAME_LENGTH); entry->filename[0] = '.'; memset (entry->entryData, 0, DIR_ENTRY_DATA_SIZE); memset (entry->entryData, ' ', 11); entry->entryData[0] = '.'; entry->entryData[DIR_ENTRY_attributes] = ATTRIB_DIR; u16_to_u8array (entry->entryData, DIR_ENTRY_cluster, partition->rootDirCluster); u16_to_u8array (entry->entryData, DIR_ENTRY_clusterHigh, partition->rootDirCluster >> 16); return true; } bool _FAT_directory_getVolumeLabel (PARTITION* partition, char *label) { DIR_ENTRY entry; DIR_ENTRY_POSITION entryEnd; uint8_t entryData[DIR_ENTRY_DATA_SIZE]; int i; bool end; _FAT_directory_getRootEntry(partition, &entry); entryEnd = entry.dataEnd; // Make sure we are using the correct root directory, in case of FAT32 if (entryEnd.cluster == FAT16_ROOT_DIR_CLUSTER) { entryEnd.cluster = partition->rootDirCluster; } label[0]='\0'; label[11]='\0'; end = false; //this entry should be among the first 3 entries in the root directory table, if not, then system can have trouble displaying the right volume label while(!end) { if (_FAT_directory_incrementDirEntryPosition (partition, &entryEnd, false) == false) { end = true; } if(!_FAT_cache_readPartialSector (partition->cache, entryData, _FAT_fat_clusterToSector(partition, entryEnd.cluster) + entryEnd.sector, entryEnd.offset * DIR_ENTRY_DATA_SIZE, DIR_ENTRY_DATA_SIZE)) { //error reading return false; } if (entryData[DIR_ENTRY_attributes] == ATTRIB_VOL && entryData[0] != DIR_ENTRY_FREE) { for (i = 0; i < 11; i++) { label[i] = entryData[DIR_ENTRY_name + i]; } return true; } else if (entryData[0] == DIR_ENTRY_LAST) { end = true; } } return false; } bool _FAT_directory_entryFromPosition (PARTITION* partition, DIR_ENTRY* entry) { DIR_ENTRY_POSITION entryStart = entry->dataStart; DIR_ENTRY_POSITION entryEnd = entry->dataEnd; bool entryStillValid; bool finished; ucs2_t lfn[MAX_LFN_LENGTH]; int i; int lfnPos; uint8_t entryData[DIR_ENTRY_DATA_SIZE]; memset (entry->filename, '\0', MAX_FILENAME_LENGTH); // Create an empty directory entry to overwrite the old ones with for ( entryStillValid = true, finished = false; entryStillValid && !finished; entryStillValid = _FAT_directory_incrementDirEntryPosition (partition, &entryStart, false)) { _FAT_cache_readPartialSector (partition->cache, entryData, _FAT_fat_clusterToSector(partition, entryStart.cluster) + entryStart.sector, entryStart.offset * DIR_ENTRY_DATA_SIZE, DIR_ENTRY_DATA_SIZE); if ((entryStart.cluster == entryEnd.cluster) && (entryStart.sector == entryEnd.sector) && (entryStart.offset == entryEnd.offset)) { // Copy the entry data and stop, since this is the last section of the directory entry memcpy (entry->entryData, entryData, DIR_ENTRY_DATA_SIZE); finished = true; } else { // Copy the long file name data lfnPos = ((entryData[LFN_offset_ordinal] & ~LFN_END) - 1) * 13; if (lfnPos > LAST_LFN_POS) { lfnPos = LAST_LFN_POS_CORRECTION; } for (i = 0; i < 13; i++) { lfn[lfnPos + i] = entryData[LFN_offset_table[i]] | (entryData[LFN_offset_table[i]+1] << 8); } } } if (!entryStillValid) { return false; } if ((entryStart.cluster == entryEnd.cluster) && (entryStart.sector == entryEnd.sector) && (entryStart.offset == entryEnd.offset)) { // Since the entry doesn't have a long file name, extract the short filename if (!_FAT_directory_entryGetAlias (entry->entryData, entry->filename)) { return false; } } else { // Encode the long file name into a multibyte string if (_FAT_directory_ucs2tombs (entry->filename, lfn, MAX_FILENAME_LENGTH) == (size_t)-1) { return false; } } return true; } bool _FAT_directory_entryFromPath (PARTITION* partition, DIR_ENTRY* entry, const char* path, const char* pathEnd) { size_t dirnameLength; const char* pathPosition; const char* nextPathPosition; uint32_t dirCluster; bool foundFile; char alias[MAX_ALIAS_LENGTH]; bool found, notFound; pathPosition = path; found = false; notFound = false; if (pathEnd == NULL) { // Set pathEnd to the end of the path string pathEnd = strchr (path, '\0'); } if (pathPosition[0] == DIR_SEPARATOR) { // Start at root directory dirCluster = partition->rootDirCluster; // Consume separator(s) while (pathPosition[0] == DIR_SEPARATOR) { pathPosition++; } // If the path is only specifying a directory in the form of "/" return it if (pathPosition >= pathEnd) { _FAT_directory_getRootEntry (partition, entry); found = true; } } else { // Start in current working directory dirCluster = partition->cwdCluster; } // If the path is only specifying a directory in the form "." // and this is the root directory, return it if ((dirCluster == partition->rootDirCluster) && (strcmp(".", pathPosition) == 0)) { _FAT_directory_getRootEntry (partition, entry); found = true; } while (!found && !notFound) { // Get the name of the next required subdirectory within the path nextPathPosition = strchr (pathPosition, DIR_SEPARATOR); if (nextPathPosition != NULL) { dirnameLength = nextPathPosition - pathPosition; } else { dirnameLength = strlen(pathPosition); } if (dirnameLength > MAX_FILENAME_LENGTH) { // The path is too long to bother with return false; } // Look for the directory within the path foundFile = _FAT_directory_getFirstEntry (partition, entry, dirCluster); while (foundFile && !found && !notFound) { // It hasn't already found the file // Check if the filename matches if ((dirnameLength == strnlen(entry->filename, MAX_FILENAME_LENGTH)) && (_FAT_directory_mbsncasecmp(pathPosition, entry->filename, dirnameLength) == 0)) { found = true; } // Check if the alias matches _FAT_directory_entryGetAlias (entry->entryData, alias); if ((dirnameLength == strnlen(alias, MAX_ALIAS_LENGTH)) && (strncasecmp(pathPosition, alias, dirnameLength) == 0)) { found = true; } if (found && !(entry->entryData[DIR_ENTRY_attributes] & ATTRIB_DIR) && (nextPathPosition != NULL)) { // Make sure that we aren't trying to follow a file instead of a directory in the path found = false; } if (!found) { foundFile = _FAT_directory_getNextEntry (partition, entry); } } if (!foundFile) { // Check that the search didn't get to the end of the directory notFound = true; found = false; } else if ((nextPathPosition == NULL) || (nextPathPosition >= pathEnd)) { // Check that we reached the end of the path found = true; } else if (entry->entryData[DIR_ENTRY_attributes] & ATTRIB_DIR) { dirCluster = _FAT_directory_entryGetCluster (partition, entry->entryData); pathPosition = nextPathPosition; // Consume separator(s) while (pathPosition[0] == DIR_SEPARATOR) { pathPosition++; } // The requested directory was found if (pathPosition >= pathEnd) { found = true; } else { found = false; } } } if (found && !notFound) { if (partition->filesysType == FS_FAT32 && (entry->entryData[DIR_ENTRY_attributes] & ATTRIB_DIR) && _FAT_directory_entryGetCluster (partition, entry->entryData) == CLUSTER_ROOT) { // On FAT32 it should specify an actual cluster for the root entry, // not cluster 0 as on FAT16 _FAT_directory_getRootEntry (partition, entry); } return true; } else { return false; } } bool _FAT_directory_removeEntry (PARTITION* partition, DIR_ENTRY* entry) { DIR_ENTRY_POSITION entryStart = entry->dataStart; DIR_ENTRY_POSITION entryEnd = entry->dataEnd; bool entryStillValid; bool finished; uint8_t entryData[DIR_ENTRY_DATA_SIZE]; // Create an empty directory entry to overwrite the old ones with for ( entryStillValid = true, finished = false; entryStillValid && !finished; entryStillValid = _FAT_directory_incrementDirEntryPosition (partition, &entryStart, false)) { _FAT_cache_readPartialSector (partition->cache, entryData, _FAT_fat_clusterToSector(partition, entryStart.cluster) + entryStart.sector, entryStart.offset * DIR_ENTRY_DATA_SIZE, DIR_ENTRY_DATA_SIZE); entryData[0] = DIR_ENTRY_FREE; _FAT_cache_writePartialSector (partition->cache, entryData, _FAT_fat_clusterToSector(partition, entryStart.cluster) + entryStart.sector, entryStart.offset * DIR_ENTRY_DATA_SIZE, DIR_ENTRY_DATA_SIZE); if ((entryStart.cluster == entryEnd.cluster) && (entryStart.sector == entryEnd.sector) && (entryStart.offset == entryEnd.offset)) { finished = true; } } if (!entryStillValid) { return false; } return true; } static bool _FAT_directory_findEntryGap (PARTITION* partition, DIR_ENTRY* entry, uint32_t dirCluster, size_t size) { DIR_ENTRY_POSITION gapStart; DIR_ENTRY_POSITION gapEnd; uint8_t entryData[DIR_ENTRY_DATA_SIZE]; size_t dirEntryRemain; bool endOfDirectory, entryStillValid; // Scan Dir for free entry gapEnd.offset = 0; gapEnd.sector = 0; gapEnd.cluster = dirCluster; gapStart = gapEnd; entryStillValid = true; dirEntryRemain = size; endOfDirectory = false; while (entryStillValid && !endOfDirectory && (dirEntryRemain > 0)) { _FAT_cache_readPartialSector (partition->cache, entryData, _FAT_fat_clusterToSector(partition, gapEnd.cluster) + gapEnd.sector, gapEnd.offset * DIR_ENTRY_DATA_SIZE, DIR_ENTRY_DATA_SIZE); if (entryData[0] == DIR_ENTRY_LAST) { gapStart = gapEnd; -- dirEntryRemain; endOfDirectory = true; } else if (entryData[0] == DIR_ENTRY_FREE) { if (dirEntryRemain == size) { gapStart = gapEnd; } -- dirEntryRemain; } else { dirEntryRemain = size; } if (!endOfDirectory && (dirEntryRemain > 0)) { entryStillValid = _FAT_directory_incrementDirEntryPosition (partition, &gapEnd, true); } } // Make sure the scanning didn't fail if (!entryStillValid) { return false; } // Save the start entry, since we know it is valid entry->dataStart = gapStart; if (endOfDirectory) { memset (entryData, DIR_ENTRY_LAST, DIR_ENTRY_DATA_SIZE); dirEntryRemain += 1; // Increase by one to take account of End Of Directory Marker while ((dirEntryRemain > 0) && entryStillValid) { // Get the gapEnd before incrementing it, so the second to last one is saved entry->dataEnd = gapEnd; // Increment gapEnd, moving onto the next entry entryStillValid = _FAT_directory_incrementDirEntryPosition (partition, &gapEnd, true); -- dirEntryRemain; // Fill the entry with blanks _FAT_cache_writePartialSector (partition->cache, entryData, _FAT_fat_clusterToSector(partition, gapEnd.cluster) + gapEnd.sector, gapEnd.offset * DIR_ENTRY_DATA_SIZE, DIR_ENTRY_DATA_SIZE); } if (!entryStillValid) { return false; } } else { entry->dataEnd = gapEnd; } return true; } static bool _FAT_directory_entryExists (PARTITION* partition, const char* name, uint32_t dirCluster) { DIR_ENTRY tempEntry; bool foundFile; char alias[MAX_ALIAS_LENGTH]; size_t dirnameLength; dirnameLength = strnlen(name, MAX_FILENAME_LENGTH); if (dirnameLength >= MAX_FILENAME_LENGTH) { return false; } // Make sure the entry doesn't already exist foundFile = _FAT_directory_getFirstEntry (partition, &tempEntry, dirCluster); while (foundFile) { // It hasn't already found the file // Check if the filename matches if ((dirnameLength == strnlen(tempEntry.filename, MAX_FILENAME_LENGTH)) && (_FAT_directory_mbsncasecmp(name, tempEntry.filename, dirnameLength) == 0)) { return true; } // Check if the alias matches _FAT_directory_entryGetAlias (tempEntry.entryData, alias); if ((strncasecmp(name, alias, MAX_ALIAS_LENGTH) == 0)) { return true; } foundFile = _FAT_directory_getNextEntry (partition, &tempEntry); } return false; } /* Creates an alias for a long file name. If the alias is not an exact match for the filename, it returns the number of characters in the alias. If the two names match, it returns 0. If there was an error, it returns -1. */ static int _FAT_directory_createAlias (char* alias, const char* lfn) { bool lossyConversion = false; // Set when the alias had to be modified to be valid int lfnPos = 0; int aliasPos = 0; wchar_t lfnChar; int oemChar; mbstate_t ps = {0}; int bytesUsed = 0; const char* lfnExt; int aliasExtLen; // Strip leading periods while (lfn[lfnPos] == '.') { lfnPos ++; lossyConversion = true; } // Primary portion of alias while (aliasPos < 8 && lfn[lfnPos] != '.' && lfn[lfnPos] != '\0') { bytesUsed = mbrtowc(&lfnChar, lfn + lfnPos, MAX_FILENAME_LENGTH - lfnPos, &ps); if (bytesUsed < 0) { return -1; } oemChar = wctob(towupper((wint_t)lfnChar)); if (wctob((wint_t)lfnChar) != oemChar) { // Case of letter was changed lossyConversion = true; } if (oemChar == ' ') { // Skip spaces in filename lossyConversion = true; lfnPos += bytesUsed; continue; } if (oemChar == EOF) { oemChar = '_'; // Replace unconvertable characters with underscores lossyConversion = true; } if (strchr (ILLEGAL_ALIAS_CHARACTERS, oemChar) != NULL) { // Invalid Alias character oemChar = '_'; // Replace illegal characters with underscores lossyConversion = true; } alias[aliasPos] = (char)oemChar; aliasPos++; lfnPos += bytesUsed; } if (lfn[lfnPos] != '.' && lfn[lfnPos] != '\0') { // Name was more than 8 characters long lossyConversion = true; } // Alias extension lfnExt = strrchr (lfn, '.'); if (lfnExt != NULL && lfnExt != strchr (lfn, '.')) { // More than one period in name lossyConversion = true; } if (lfnExt != NULL && lfnExt[1] != '\0') { lfnExt++; alias[aliasPos] = '.'; aliasPos++; memset (&ps, 0, sizeof(ps)); for (aliasExtLen = 0; aliasExtLen < MAX_ALIAS_EXT_LENGTH && *lfnExt != '\0'; aliasExtLen++) { bytesUsed = mbrtowc(&lfnChar, lfnExt, MAX_FILENAME_LENGTH - lfnPos, &ps); if (bytesUsed < 0) { return -1; } oemChar = wctob(towupper((wint_t)lfnChar)); if (wctob((wint_t)lfnChar) != oemChar) { // Case of letter was changed lossyConversion = true; } if (oemChar == ' ') { // Skip spaces in alias lossyConversion = true; lfnExt += bytesUsed; continue; } if (oemChar == EOF) { oemChar = '_'; // Replace unconvertable characters with underscores lossyConversion = true; } if (strchr (ILLEGAL_ALIAS_CHARACTERS, oemChar) != NULL) { // Invalid Alias character oemChar = '_'; // Replace illegal characters with underscores lossyConversion = true; } alias[aliasPos] = (char)oemChar; aliasPos++; lfnExt += bytesUsed; } if (*lfnExt != '\0') { // Extension was more than 3 characters long lossyConversion = true; } } alias[aliasPos] = '\0'; if (lossyConversion) { return aliasPos; } else { return 0; } } bool _FAT_directory_addEntry (PARTITION* partition, DIR_ENTRY* entry, uint32_t dirCluster) { size_t entrySize; uint8_t lfnEntry[DIR_ENTRY_DATA_SIZE]; int i,j; // Must be signed for use when decrementing in for loop char *tmpCharPtr; DIR_ENTRY_POSITION curEntryPos; bool entryStillValid; uint8_t aliasCheckSum = 0; char alias [MAX_ALIAS_LENGTH]; int aliasLen; int lfnLen; // Make sure the filename is not 0 length if (strnlen (entry->filename, MAX_FILENAME_LENGTH) < 1) { return false; } // Make sure the filename is at least a valid LFN lfnLen = _FAT_directory_lfnLength (entry->filename); if (lfnLen < 0) { return false; } // Remove trailing spaces for (i = strlen (entry->filename) - 1; (i > 0) && (entry->filename[i] == ' '); --i) { entry->filename[i] = '\0'; } // Remove leading spaces for (i = 0; (i < (int)strlen (entry->filename)) && (entry->filename[i] == ' '); ++i) ; if (i > 0) { memmove (entry->filename, entry->filename + i, strlen (entry->filename + i)); } // Remove junk in filename i = strlen (entry->filename); memset (entry->filename + i, '\0', MAX_FILENAME_LENGTH - i); // Make sure the entry doesn't already exist if (_FAT_directory_entryExists (partition, entry->filename, dirCluster)) { return false; } // Clear out alias, so we can generate a new one memset (entry->entryData, ' ', 11); if ( strncmp(entry->filename, ".", MAX_FILENAME_LENGTH) == 0) { // "." entry entry->entryData[0] = '.'; entrySize = 1; } else if ( strncmp(entry->filename, "..", MAX_FILENAME_LENGTH) == 0) { // ".." entry entry->entryData[0] = '.'; entry->entryData[1] = '.'; entrySize = 1; } else { // Normal file name aliasLen = _FAT_directory_createAlias (alias, entry->filename); if (aliasLen < 0) { return false; } else if (aliasLen == 0) { // It's a normal short filename entrySize = 1; } else { // It's a long filename with an alias entrySize = ((lfnLen + LFN_ENTRY_LENGTH - 1) / LFN_ENTRY_LENGTH) + 1; // Generate full alias for all cases except when the alias is simply an upper case version of the LFN // and there isn't already a file with that name if (strncasecmp (alias, entry->filename, MAX_ALIAS_LENGTH) != 0 || _FAT_directory_entryExists (partition, alias, dirCluster)) { // expand primary part to 8 characters long by padding the end with underscores i = MAX_ALIAS_PRI_LENGTH - 1; // Move extension to last 3 characters while (alias[i] != '.' && i > 0) i--; if (i > 0) { j = MAX_ALIAS_LENGTH - MAX_ALIAS_EXT_LENGTH - 2; // 1 char for '.', one for NUL, 3 for extension memmove (alias + j, alias + i, strlen(alias) - i); // Pad primary component memset (alias + i, '_', j - i); alias[MAX_ALIAS_LENGTH-1]=0; } // Generate numeric tail for (i = 1; i <= MAX_NUMERIC_TAIL; i++) { j = i; tmpCharPtr = alias + MAX_ALIAS_PRI_LENGTH - 1; while (j > 0) { *tmpCharPtr = '0' + (j % 10); // ASCII numeric value tmpCharPtr--; j /= 10; } *tmpCharPtr = '~'; if (!_FAT_directory_entryExists (partition, alias, dirCluster)) { break; } } if (i > MAX_NUMERIC_TAIL) { // Couldn't get a valid alias return false; } } } // Copy alias or short file name into directory entry data for (i = 0, j = 0; (j < 8) && (alias[i] != '.') && (alias[i] != '\0'); i++, j++) { entry->entryData[j] = alias[i]; } while (j < 8) { entry->entryData[j] = ' '; ++ j; } if (alias[i] == '.') { // Copy extension ++ i; while ((alias[i] != '\0') && (j < 11)) { entry->entryData[j] = alias[i]; ++ i; ++ j; } } while (j < 11) { entry->entryData[j] = ' '; ++ j; } // Generate alias checksum for (i=0; i < ALIAS_ENTRY_LENGTH; i++) { // NOTE: The operation is an unsigned char rotate right aliasCheckSum = ((aliasCheckSum & 1) ? 0x80 : 0) + (aliasCheckSum >> 1) + entry->entryData[i]; } } // Find or create space for the entry if (_FAT_directory_findEntryGap (partition, entry, dirCluster, entrySize) == false) { return false; } // Write out directory entry curEntryPos = entry->dataStart; { // lfn is only pushed onto the stack here, reducing overall stack usage ucs2_t lfn[MAX_LFN_LENGTH] = {0}; _FAT_directory_mbstoucs2 (lfn, entry->filename, MAX_LFN_LENGTH); for (entryStillValid = true, i = entrySize; entryStillValid && i > 0; entryStillValid = _FAT_directory_incrementDirEntryPosition (partition, &curEntryPos, false), -- i ) { if (i > 1) { // Long filename entry lfnEntry[LFN_offset_ordinal] = (i - 1) | ((size_t)i == entrySize ? LFN_END : 0); for (j = 0; j < 13; j++) { if (lfn [(i - 2) * 13 + j] == '\0') { if ((j > 1) && (lfn [(i - 2) * 13 + (j-1)] == '\0')) { u16_to_u8array (lfnEntry, LFN_offset_table[j], 0xffff); // Padding } else { u16_to_u8array (lfnEntry, LFN_offset_table[j], 0x0000); // Terminating null character } } else { u16_to_u8array (lfnEntry, LFN_offset_table[j], lfn [(i - 2) * 13 + j]); } } lfnEntry[LFN_offset_checkSum] = aliasCheckSum; lfnEntry[LFN_offset_flag] = ATTRIB_LFN; lfnEntry[LFN_offset_reserved1] = 0; u16_to_u8array (lfnEntry, LFN_offset_reserved2, 0); _FAT_cache_writePartialSector (partition->cache, lfnEntry, _FAT_fat_clusterToSector(partition, curEntryPos.cluster) + curEntryPos.sector, curEntryPos.offset * DIR_ENTRY_DATA_SIZE, DIR_ENTRY_DATA_SIZE); } else { // Alias & file data _FAT_cache_writePartialSector (partition->cache, entry->entryData, _FAT_fat_clusterToSector(partition, curEntryPos.cluster) + curEntryPos.sector, curEntryPos.offset * DIR_ENTRY_DATA_SIZE, DIR_ENTRY_DATA_SIZE); } } } return true; } bool _FAT_directory_chdir (PARTITION* partition, const char* path) { DIR_ENTRY entry; if (!_FAT_directory_entryFromPath (partition, &entry, path, NULL)) { return false; } if (!(entry.entryData[DIR_ENTRY_attributes] & ATTRIB_DIR)) { return false; } partition->cwdCluster = _FAT_directory_entryGetCluster (partition, entry.entryData); return true; } #if defined(_WIN32) && !defined(_MSC_VER) #ifndef S_IRGRP #define S_IRGRP 0 #endif #ifndef S_IWGRP #define S_IWGRP 0 #endif #ifndef S_IROTH #define S_IROTH 0 #endif #ifndef S_IWOTH #define S_IWOTH 0 #endif #endif void _FAT_directory_entryStat (PARTITION* partition, DIR_ENTRY* entry, struct stat *st) { // Fill in the stat struct // Some of the values are faked for the sake of compatibility st->st_dev = _FAT_disc_hostType(partition->disc); // The device is the 32bit ioType value st->st_ino = (ino_t)(_FAT_directory_entryGetCluster(partition, entry->entryData)); // The file serial number is the start cluster st->st_mode = (_FAT_directory_isDirectory(entry) ? S_IFDIR : S_IFREG) | (S_IRUSR | S_IRGRP | S_IROTH) | (_FAT_directory_isWritable (entry) ? (S_IWUSR | S_IWGRP | S_IWOTH) : 0); // Mode bits based on dirEntry ATTRIB byte st->st_nlink = 1; // Always one hard link on a FAT file st->st_uid = 1; // Faked for FAT st->st_gid = 2; // Faked for FAT st->st_rdev = st->st_dev; st->st_size = u8array_to_u32 (entry->entryData, DIR_ENTRY_fileSize); // File size st->st_atime = _FAT_filetime_to_time_t ( 0, u8array_to_u16 (entry->entryData, DIR_ENTRY_aDate) ); #ifndef LIBFAT_PC st->st_spare1 = 0; #endif st->st_mtime = _FAT_filetime_to_time_t ( u8array_to_u16 (entry->entryData, DIR_ENTRY_mTime), u8array_to_u16 (entry->entryData, DIR_ENTRY_mDate) ); #ifndef LIBFAT_PC st->st_spare2 = 0; #endif st->st_ctime = _FAT_filetime_to_time_t ( u8array_to_u16 (entry->entryData, DIR_ENTRY_cTime), u8array_to_u16 (entry->entryData, DIR_ENTRY_cDate) ); #ifndef LIBFAT_PC st->st_spare3 = 0; st->st_blksize = BYTES_PER_READ; // Prefered file I/O block size st->st_blocks = (st->st_size + BYTES_PER_READ - 1) / BYTES_PER_READ; // File size in blocks st->st_spare4[0] = 0; st->st_spare4[1] = 0; #endif } desmume/src/utils/advanscene.cpp000664 001750 001750 00000016273 12755534123 020123 0ustar00sergiosergio000000 000000 /* Copyright (C) 2011-2015 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the this software. If not, see . */ #include #include #define TIXML_USE_STL #include "tinyxml/tinyxml.h" #include "advanscene.h" #include "../common.h" #include "../mc.h" #include "../emufile.h" ADVANsCEne advsc; #define _ADVANsCEne_BASE_ID "DeSmuME database (ADVANsCEne)\0x1A" #define _ADVANsCEne_BASE_VERSION_MAJOR 1 #define _ADVANsCEne_BASE_VERSION_MINOR 0 #define _ADVANsCEne_BASE_NAME "ADVANsCEne Nintendo DS Collection" u8 ADVANsCEne::checkDB(const char *ROMserial, u32 crc) { loaded = false; FILE *fp = fopen(database_path.c_str(), "rb"); if (fp) { char buf[64]; memset(buf, 0, sizeof(buf)); if (fread(buf, 1, strlen(_ADVANsCEne_BASE_ID), fp) == strlen(_ADVANsCEne_BASE_ID)) { //printf("ID: %s\n", buf); if (strcmp(buf, _ADVANsCEne_BASE_ID) == 0) { if (fread(&versionBase[0], 1, 2, fp) == 2) { //printf("Version base: %i.%i\n", versionBase[0], versionBase[1]); if (fread(&version[0], 1, 4, fp) == 4) { //printf("Version: %c%c%c%c\n", version[3], version[2], version[1], version[0]); if (fread(&createTime, 1, sizeof(time_t), fp) == sizeof(time_t)) { memset(buf, 0,sizeof(buf)); // serial(8) + crc32(4) + save_type(1) = 13 + reserved(8) = 21 while (true) { if (fread(buf, 1, 21, fp) != 21) break; bool serialFound = (memcmp(&buf[4], ROMserial, 4) == 0); u32 dbcrc = LE_TO_LOCAL_32(*(u32*)(buf+8)); bool crcFound = (crc == dbcrc); if(serialFound || crcFound) { foundAsCrc = crcFound; foundAsSerial = serialFound; memcpy(&crc32, &buf[8], 4); memcpy(&serial[0], &buf[4], 4); //printf("%s founded: crc32=%04X, save type %02X\n", ROMserial, crc32, buf[12]); saveType = buf[12]; fclose(fp); loaded = true; return true; } } } } } } } fclose(fp); } return false; } void ADVANsCEne::setDatabase(const char *path) { database_path = path; //i guess this means it needs (re)loading on account of the path having changed loaded = false; } bool ADVANsCEne::getXMLConfig(const char *in_filename) { TiXmlDocument *xml = NULL; TiXmlElement *el = NULL; TiXmlElement *el_configuration = NULL; TiXmlElement *el_newDat = NULL; xml = new TiXmlDocument(); if (!xml) return false; if (!xml->LoadFile(in_filename)) return false; el = xml->FirstChildElement("dat"); if (!el) return false; el_configuration = el->FirstChildElement("configuration"); if (!el_configuration) return false; el = el_configuration->FirstChildElement("datName"); if (el) { datName = el->GetText() ? el->GetText() : ""; } el = el_configuration->FirstChildElement("datVersion"); if (el) { datVersion = el->GetText() ? el->GetText() : ""; } el_newDat = el_configuration->FirstChildElement("newDat"); if (!el_newDat) return false; el = el_newDat->FirstChildElement("datVersionURL"); if (el) { urlVersion = el->GetText() ? el->GetText() : ""; } el = el_newDat->FirstChildElement("datURL"); if (el) { urlDat = el->GetText() ? el->GetText() : ""; } delete xml; return true; } u32 ADVANsCEne::convertDB(const char *in_filename, EMUFILE* output) { //these strings are contained in the xml file, verbatim, so they function as enum values //we leave the strings here rather than pooled elsewhere to remind us that theyre part of the advanscene format. const char *saveTypeNames[] = { "Eeprom - 4 kbit", // EEPROM 4kbit "Eeprom - 64 kbit", // EEPROM 64kbit "Eeprom - 512 kbit", // EEPROM 512kbit "Fram - 256 kbit", // FRAM 256kbit ! "Flash - 2 mbit", // FLASH 2Mbit "Flash - 4 mbit", // FLASH 4Mbit "Flash - 8 mbit", // FLASH 8Mbit "Flash - 16 mbit", // FLASH 16Mbit ! "Flash - 32 mbit", // FLASH 32Mbit ! "Flash - 64 mbit", // FLASH 64Mbit "Flash - 128 mbit", // FLASH 128Mbit ! "Flash - 256 mbit", // FLASH 256Mbit ! "Flash - 512 mbit" // FLASH 512Mbit ! }; TiXmlDocument *xml = NULL; TiXmlElement *el = NULL; TiXmlElement *el_serial = NULL; TiXmlElement *el_games = NULL; TiXmlElement *el_crc32 = NULL; TiXmlElement *el_saveType = NULL; u32 crc32 = 0; u32 reserved = 0; lastImportErrorMessage = ""; printf("Converting DB...\n"); if (getXMLConfig(in_filename)) { if (datName.size()==0) return 0; if (datName != _ADVANsCEne_BASE_NAME) return 0; } // Header output->fwrite(_ADVANsCEne_BASE_ID, strlen(_ADVANsCEne_BASE_ID)); output->fputc(_ADVANsCEne_BASE_VERSION_MAJOR); output->fputc(_ADVANsCEne_BASE_VERSION_MINOR); if (datVersion.size()) output->fwrite(&datVersion[0], datVersion.size()); else output->fputc(0); time_t __time = time(NULL); output->fwrite(&__time, sizeof(time_t)); xml = new TiXmlDocument(); if (!xml) return 0; if (!xml->LoadFile(in_filename)) return 0; el = xml->FirstChildElement("dat"); if (!el) return 0; el_games = el->FirstChildElement("games"); if (!el_games) return 0; el = el_games->FirstChildElement("game"); if (!el) return 0; u32 count = 0; while (el) { TiXmlElement* title = el->FirstChildElement("title"); if(title) { //just a little diagnostic //printf("Importing %s\n",title->GetText()); } else return 0; el_serial = el->FirstChildElement("serial"); if(!el_serial) { lastImportErrorMessage = "Missing element. Did you use the right xml file? We need the RtoolDS one."; return 0; } output->fwrite(el_serial->GetText(), 8); // CRC32 el_crc32 = el->FirstChildElement("files"); sscanf_s(el_crc32->FirstChildElement("romCRC")->GetText(), "%x", &crc32); output->fwrite(&crc32, sizeof(u32)); // Save type el_saveType = el->FirstChildElement("saveType"); u8 selectedSaveType = 0xFF; //unknown if (el_saveType) { const char *tmp = el_saveType->GetText(); if (tmp) { if (strcmp(tmp, "None") == 0) selectedSaveType = 0xFE; else { for (u8 i = 0; i < MAX_SAVE_TYPES; i++) { if (strcmp(saveTypeNames[i], "") == 0) continue; if (strcasecmp(tmp, saveTypeNames[i]) == 0) { selectedSaveType = i; break; } } } } } output->fputc(selectedSaveType); output->fwrite(&reserved, sizeof(u32)); output->fwrite(&reserved, sizeof(u32)); count++; el = el->NextSiblingElement("game"); } printf("\n"); delete xml; if (count > 0) printf("done\n"); else printf("error\n"); printf("ADVANsCEne converter: %i found\n", count); return count; } desmume/src/rtc.cpp000664 001750 001750 00000017417 12755534123 015445 0ustar00sergiosergio000000 000000 /* Copyright (C) 2006 yopyop Copyright (C) 2008 CrazyMax Copyright (C) 2008-2010 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the this software. If not, see . */ // TODO: interrupt handler #include "rtc.h" #include "common.h" #include "debug.h" #include "armcpu.h" #include #include "saves.h" #if defined(WIN32) && defined(_MSC_VER) #include "windows/main.h" #endif #include "movie.h" typedef struct { // RTC registers u8 regStatus1; u8 regStatus2; u8 regAdjustment; u8 regFree; // BUS u8 _prevSCK; u8 _prevCS; u8 _prevSIO; u8 _SCK; u8 _CS; u8 _SIO; u8 _DD; u16 _REG; // command & data u8 cmd; u8 cmdStat; u8 bitsCount; u8 data[8]; u8 cmdBitsSize[8]; } _RTC; _RTC rtc; SFORMAT SF_RTC[]={ { "R000", 1, 1, &rtc.regStatus1}, { "R010", 1, 1, &rtc.regStatus2}, { "R020", 1, 1, &rtc.regAdjustment}, { "R030", 1, 1, &rtc.regFree}, { "R040", 1, 1, &rtc._prevSCK}, { "R050", 1, 1, &rtc._prevCS}, { "R060", 1, 1, &rtc._prevSIO}, { "R070", 1, 1, &rtc._SCK}, { "R080", 1, 1, &rtc._CS}, { "R090", 1, 1, &rtc._SIO}, { "R100", 1, 1, &rtc._DD}, { "R110", 2, 1, &rtc._REG}, { "R120", 1, 1, &rtc.cmd}, { "R130", 1, 1, &rtc.cmdStat}, { "R140", 1, 1, &rtc.bitsCount}, { "R150", 1, 8, &rtc.data[0]}, { "R160", 1, 8, &rtc.cmdBitsSize[0]}, { 0 } }; static const u8 kDefaultCmdBitsSize[8] = {8, 8, 56, 24, 0, 24, 8, 8}; static inline u8 toBCD(u8 x) { return ((x / 10) << 4) | (x % 10); } DateTime rtcGetTime(void) { return DateTime::get_Now(); } static void rtcRecv() { //INFO("RTC Read command 0x%02X\n", (rtc.cmd >> 1)); memset(&rtc.data[0], 0, sizeof(rtc.data)); switch (rtc.cmd >> 1) { case 0: // status register 1 //INFO("RTC: read regstatus1 (0x%02X)\n", rtc.regStatus1); rtc.regStatus1 &= 0x0F; rtc.data[0] = rtc.regStatus1; //rtc.regStatus1 &= 0x7F; break; case 1: // status register 2 //INFO("RTC: read regstatus2 (0x%02X)\n", rtc.regStatus1); rtc.data[0] = rtc.regStatus2; break; case 2: // date & time { //INFO("RTC: read date & time\n"); DateTime tm = rtcGetTime(); rtc.data[0] = toBCD(tm.get_Year() % 100); rtc.data[1] = toBCD(tm.get_Month()); rtc.data[2] = toBCD(tm.get_Day()); //zero 24-apr-2010 - this is nonsense. //but it is so wrong, someone mustve thought they knew what they were doing, so i am leaving it... //rtc.data[3] = (tm.tm_wday + 6) & 7; //if (rtc.data[3] == 7) rtc.data[3] = 6; //do this instead (gbatek seems to say monday=0 but i don't think that is right) //0=sunday is necessary to make animal crossing behave //maybe it means "custom assignment" can be specified by the game rtc.data[3] = tm.get_DayOfWeek(); int hour = tm.get_Hour(); if (!(rtc.regStatus1 & 0x02)) hour %= 12; rtc.data[4] = ((hour < 12) ? 0x00 : 0x40) | toBCD(hour); rtc.data[5] = toBCD(tm.get_Minute()); rtc.data[6] = toBCD(tm.get_Second()); break; } case 3: // time { //INFO("RTC: read time\n"); DateTime tm = rtcGetTime(); int hour = tm.get_Hour(); if (!(rtc.regStatus1 & 0x02)) hour %= 12; rtc.data[0] = ((hour < 12) ? 0x00 : 0x40) | toBCD(hour); rtc.data[1] = toBCD(tm.get_Minute()); rtc.data[2] = toBCD(tm.get_Second()); break; } case 4: // freq/alarm 1 /*if (cmdBitsSize[0x04] == 8) INFO("RTC: read INT1 freq\n"); else INFO("RTC: read INT1 alarm1\n");*/ //NDS_makeARM7Int(7); break; case 5: // alarm 2 //INFO("RTC: read alarm 2\n"); break; case 6: // clock adjust //INFO("RTC: read clock adjust\n"); rtc.data[0] = rtc.regAdjustment; break; case 7: // free register //INFO("RTC: read free register\n"); rtc.data[0] = rtc.regFree; break; } } static void rtcSend() { //INFO("RTC write command 0x%02X\n", (rtc.cmd >> 1)); switch (rtc.cmd >> 1) { case 0: // status register 1 //INFO("RTC: write regstatus1 0x%02X\n", rtc.data[0]); // rtc.regStatus1 &= 0xF1; // rtc.regStatus1 |= (rtc.data[0] | 0x0E); rtc.regStatus1 = rtc.data[0]; break; case 1: // status register 2 //INFO("RTC: write regstatus2 0x%02X\n", rtc.data[0]); rtc.regStatus2 = rtc.data[0]; break; case 2: // date & time //INFO("RTC: write date & time : %02X %02X %02X %02X %02X %02X %02X\n", rtc.data[0], rtc.data[1], rtc.data[2], rtc.data[3], rtc.data[4], rtc.data[5], rtc.data[6]); break; case 3: // time //INFO("RTC: write time : %02X %02X %02X\n", rtc.data[0], rtc.data[1], rtc.data[2]); break; case 4: // freq/alarm 1 /*if (cmdBitsSize[0x04] == 8) INFO("RTC: write INT1 freq 0x%02X\n", rtc.data[0]); else INFO("RTC: write INT1 alarm1 0x%02X\n", rtc.data[0]);*/ break; case 5: // alarm 2 //INFO("RTC: write alarm 2\n"); break; case 6: // clock adjust //INFO("RTC: write clock adjust\n"); rtc.regAdjustment = rtc.data[0]; break; case 7: // free register //INFO("RTC: write free register\n"); rtc.regFree = rtc.data[0]; break; } } void rtcInit() { memset(&rtc, 0, sizeof(rtc)); memcpy(&rtc.cmdBitsSize[0],kDefaultCmdBitsSize,8); rtc.regStatus1 |= 0x02; } u16 rtcRead() { //INFO("MMU Read RTC 0x%02X (%03i)\n", rtc._REG, rtc.bitsCount); return (rtc._REG); } void rtcWrite(u16 val) { //INFO("MMU Write RTC 0x%02X (%03i)\n", val, rtc.bitsCount); rtc._DD = (val & 0x10) >> 4; rtc._SIO = rtc._DD?(val & 0x01):rtc._prevSIO; rtc._SCK = (val & 0x20)?((val & 0x02) >> 1):rtc._prevSCK; rtc._CS = (val & 0x40)?((val & 0x04) >> 2):rtc._prevCS; switch (rtc.cmdStat) { case 0: if ( (!rtc._prevCS) && (rtc._prevSCK) && (rtc._CS) && (rtc._SCK) ) { rtc.cmdStat = 1; rtc.bitsCount = 0; rtc.cmd = 0; } break; case 1: if (!rtc._CS) { rtc.cmdStat = 0; break; } if (rtc._SCK && rtc._DD) break; if (!rtc._SCK && !rtc._DD) break; rtc.cmd |= (rtc._SIO << rtc.bitsCount ); rtc.bitsCount ++; if (rtc.bitsCount == 8) { //INFO("RTC command 0x%02X\n", rtc.cmd); // Little-endian command if((rtc.cmd & 0x0F) == 0x06) { u8 tmp = rtc.cmd; rtc.cmd = ((tmp & 0x80) >> 7) | ((tmp & 0x40) >> 5) | ((tmp & 0x20) >> 3) | ((tmp & 0x10) >> 1); } // Big-endian command else { rtc.cmd &= 0x0F; } if((rtc._prevSCK) && (!rtc._SCK)) { rtc.bitsCount = 0; if ((rtc.cmd >> 1) == 0x04) { if ((rtc.regStatus2 & 0x0F) == 0x04) rtc.cmdBitsSize[rtc.cmd >> 1] = 24; else rtc.cmdBitsSize[rtc.cmd >> 1] = 8; } if (rtc.cmd & 0x01) { rtc.cmdStat = 4; rtcRecv(); } else { rtc.cmdStat = 3; } } } break; case 3: // write: if( (rtc._prevSCK) && (!rtc._SCK) ) { if(rtc._SIO) rtc.data[rtc.bitsCount >> 3] |= (1 << (rtc.bitsCount & 0x07)); rtc.bitsCount++; if (rtc.bitsCount == rtc.cmdBitsSize[rtc.cmd >> 1]) { rtcSend(); rtc.cmdStat = 0; } } break; case 4: // read: if( (rtc._prevSCK) && (!rtc._SCK) ) { rtc._REG = val; if((rtc.data[(rtc.bitsCount >> 3)] >> (rtc.bitsCount & 0x07)) & 0x01) rtc._REG |= 0x01; else rtc._REG &= ~0x01; rtc.bitsCount++; if (rtc.bitsCount == rtc.cmdBitsSize[rtc.cmd >> 1] || (!(val & 0x04))) rtc.cmdStat = 0; } break; } rtc._prevSIO = rtc._SIO; rtc._prevSCK = rtc._SCK; rtc._prevCS = rtc._CS; } desmume/src/libretro-common/compat/compat_fnmatch.c000664 001750 001750 00000013050 12755534123 023660 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2015 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (compat_fnmatch.c). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #if __TEST_FNMATCH__ #include #endif #include /* Implemnentation of fnmatch(3) so it can be * distributed to non *nix platforms. * * No flags are implemented ATM. * We don't use them. Add flags as needed. */ int rl_fnmatch(const char *pattern, const char *string, int flags) { const char *c; int charmatch = 0; int rv; for (c = pattern; *c != '\0'; c++) { /* String ended before pattern */ if ((*c != '*') && (*string == '\0')) return FNM_NOMATCH; switch (*c) { /* Match any number of unknown chars */ case '*': /* Find next node in the pattern * ignoring multiple asterixes */ do { c++; if (*c == '\0') return 0; } while (*c == '*'); /* Match the remaining pattern * ignoring more and more characters. */ do { /* We reached the end of the string without a * match. There is a way to optimize this by * calculating the minimum chars needed to * match the remaining pattern but I don't * think it is worth the work ATM. */ if (*string == '\0') return FNM_NOMATCH; rv = rl_fnmatch(c, string, flags); string++; } while (rv != 0); return 0; /* Match char from list */ case '[': charmatch = 0; for (c++; *c != ']'; c++) { /* Bad format */ if (*c == '\0') return FNM_NOMATCH; /* Match already found */ if (charmatch) continue; if (*c == *string) charmatch = 1; } /* No match in list */ if (!charmatch) return FNM_NOMATCH; string++; break; /* Has any character */ case '?': string++; break; /* Match following character verbatim */ case '\\': c++; /* Dangling escape at end of pattern. * FIXME: Was c == '\0' (makes no sense). * Not sure if c == NULL or *c == '\0' * is intended. Assuming *c due to c++ right before. */ if (*c == '\0') return FNM_NOMATCH; default: if (*c != *string) return FNM_NOMATCH; string++; } } /* End of string and end of pattend */ if (*string == '\0') return 0; return FNM_NOMATCH; } #if __TEST_FNMATCH__ int main(void) { assert(rl_fnmatch("TEST", "TEST", 0) == 0); assert(rl_fnmatch("TE?T", "TEST", 0) == 0); assert(rl_fnmatch("TE[Ssa]T", "TEST", 0) == 0); assert(rl_fnmatch("TE[Ssda]T", "TEsT", 0) == 0); assert(rl_fnmatch("TE[Ssda]T", "TEdT", 0) == 0); assert(rl_fnmatch("TE[Ssda]T", "TEaT", 0) == 0); assert(rl_fnmatch("TEST*", "TEST", 0) == 0); assert(rl_fnmatch("TEST**", "TEST", 0) == 0); assert(rl_fnmatch("TE*ST*", "TEST", 0) == 0); assert(rl_fnmatch("TE**ST*", "TEST", 0) == 0); assert(rl_fnmatch("TE**ST*", "TExST", 0) == 0); assert(rl_fnmatch("TE**ST", "TEST", 0) == 0); assert(rl_fnmatch("TE**ST", "TExST", 0) == 0); assert(rl_fnmatch("TE\\**ST", "TE*xST", 0) == 0); assert(rl_fnmatch("*.*", "test.jpg", 0) == 0); assert(rl_fnmatch("*.jpg", "test.jpg", 0) == 0); assert(rl_fnmatch("*.[Jj][Pp][Gg]", "test.jPg", 0) == 0); assert(rl_fnmatch("*.[Jj]*[Gg]", "test.jPg", 0) == 0); assert(rl_fnmatch("TEST?", "TEST", 0) == FNM_NOMATCH); assert(rl_fnmatch("TES[asd", "TEST", 0) == FNM_NOMATCH); assert(rl_fnmatch("TEST\\", "TEST", 0) == FNM_NOMATCH); assert(rl_fnmatch("TEST*S", "TEST", 0) == FNM_NOMATCH); assert(rl_fnmatch("TE**ST", "TExT", 0) == FNM_NOMATCH); assert(rl_fnmatch("TE\\*T", "TExT", 0) == FNM_NOMATCH); assert(rl_fnmatch("TES?", "TES", 0) == FNM_NOMATCH); assert(rl_fnmatch("TE", "TEST", 0) == FNM_NOMATCH); assert(rl_fnmatch("TEST!", "TEST", 0) == FNM_NOMATCH); assert(rl_fnmatch("DSAD", "TEST", 0) == FNM_NOMATCH); } #endif desmume/src/libretro-common/include/algorithms/000700 001750 001750 00000000000 12756420131 023021 5ustar00sergiosergio000000 000000 desmume/src/utils/AsmJit/core/logger.h000664 001750 001750 00000020553 12755534123 021053 0ustar00sergiosergio000000 000000 // [AsmJit] // Complete JIT Assembler for C++ Language. // // [License] // Zlib - See COPYING file in this package. // [Guard] #ifndef _ASMJIT_CORE_LOGGER_H #define _ASMJIT_CORE_LOGGER_H // [Dependencies - AsmJit] #include "../core/build.h" #include "../core/defs.h" #include "../core/stringbuilder.h" // [Dependencies - C] #include // [Api-Begin] #include "../core/apibegin.h" namespace AsmJit { //! @addtogroup AsmJit_Logging //! @{ // ============================================================================ // [AsmJit::Logger] // ============================================================================ //! @brief Abstract logging class. //! //! This class can be inherited and reimplemented to fit into your logging //! subsystem. When reimplementing use @c AsmJit::Logger::log() method to //! log into your stream. //! //! This class also contain @c _enabled member that can be used to enable //! or disable logging. struct Logger { ASMJIT_NO_COPY(Logger) // -------------------------------------------------------------------------- // [Construction / Destruction] // -------------------------------------------------------------------------- //! @brief Create logger. ASMJIT_API Logger(); //! @brief Destroy logger. ASMJIT_API virtual ~Logger(); // -------------------------------------------------------------------------- // [Logging] // -------------------------------------------------------------------------- //! @brief Abstract method to log output. //! //! Default implementation that is in @c AsmJit::Logger is to do nothing. //! It's virtual to fit to your logging system. virtual void logString(const char* buf, size_t len = kInvalidSize) = 0; //! @brief Log formatter message (like sprintf) sending output to @c logString() method. ASMJIT_API virtual void logFormat(const char* fmt, ...); // -------------------------------------------------------------------------- // [Flags] // -------------------------------------------------------------------------- //! @brief Get logger flags (used internally by Assembler/Compiler). inline uint32_t getFlags() const { return _flags; } // -------------------------------------------------------------------------- // [Enabled] // -------------------------------------------------------------------------- //! @brief Return @c true if logging is enabled. inline bool isEnabled() const { return (_flags & kLoggerIsEnabled) != 0; } //! @brief Set logging to enabled or disabled. ASMJIT_API virtual void setEnabled(bool enabled); // -------------------------------------------------------------------------- // [Used] // -------------------------------------------------------------------------- //! @brief Get whether the logger should be used. inline bool isUsed() const { return (_flags & kLoggerIsUsed) != 0; } // -------------------------------------------------------------------------- // [LogBinary] // -------------------------------------------------------------------------- //! @brief Get whether logging of binary output is enabled. inline bool getLogBinary() const { return (_flags & kLoggerOutputBinary) != 0; } //! @brief Enable or disable binary output logging. ASMJIT_API void setLogBinary(bool value); // -------------------------------------------------------------------------- // [HexImmediate] // -------------------------------------------------------------------------- inline bool getHexImmediate() const { return (_flags & kLoggerOutputHexImmediate) != 0; } ASMJIT_API void setHexImmediate(bool value); // -------------------------------------------------------------------------- // [HexDisplacement] // -------------------------------------------------------------------------- inline bool getHexDisplacement() const { return (_flags & kLoggerOutputHexDisplacement) != 0; } ASMJIT_API void setHexDisplacement(bool value); // -------------------------------------------------------------------------- // [InstructionPrefix] // -------------------------------------------------------------------------- //! @brief Get instruction prefix. inline const char* getInstructionPrefix() const { return _instructionPrefix; } //! @brief Set instruction prefix. ASMJIT_API void setInstructionPrefix(const char* prefix); //! @brief Reset instruction prefix. inline void resetInstructionPrefix() { setInstructionPrefix(NULL); } // -------------------------------------------------------------------------- // [Members] // -------------------------------------------------------------------------- //! @brief Flags, see @ref kLoggerFlag. uint32_t _flags; //! @brief Instrictions and macro-instructions prefix. char _instructionPrefix[12]; }; // ============================================================================ // [AsmJit::FileLogger] // ============================================================================ //! @brief Logger that can log to standard C @c FILE* stream. struct FileLogger : public Logger { ASMJIT_NO_COPY(FileLogger) // -------------------------------------------------------------------------- // [Construction / Destruction] // -------------------------------------------------------------------------- //! @brief Create a new @c FileLogger. //! @param stream FILE stream where logging will be sent (can be @c NULL //! to disable logging). ASMJIT_API FileLogger(FILE* stream = NULL); //! @brief Destroy the @ref FileLogger. ASMJIT_API virtual ~FileLogger(); // -------------------------------------------------------------------------- // [Accessors] // -------------------------------------------------------------------------- //! @brief Get @c FILE* stream. //! //! @note Return value can be @c NULL. inline FILE* getStream() const { return _stream; } //! @brief Set @c FILE* stream. //! //! @param stream @c FILE stream where to log output (can be @c NULL to //! disable logging). ASMJIT_API void setStream(FILE* stream); // -------------------------------------------------------------------------- // [Logging] // -------------------------------------------------------------------------- ASMJIT_API virtual void logString(const char* buf, size_t len = kInvalidSize); // -------------------------------------------------------------------------- // [Enabled] // -------------------------------------------------------------------------- ASMJIT_API virtual void setEnabled(bool enabled); // -------------------------------------------------------------------------- // [Members] // -------------------------------------------------------------------------- //! @brief C file stream. FILE* _stream; }; // ============================================================================ // [AsmJit::StringLogger] // ============================================================================ //! @brief String logger. struct StringLogger : public Logger { ASMJIT_NO_COPY(StringLogger) // -------------------------------------------------------------------------- // [Construction / Destruction] // -------------------------------------------------------------------------- //! @brief Create new @ref StringLogger. ASMJIT_API StringLogger(); //! @brief Destroy the @ref StringLogger. ASMJIT_API virtual ~StringLogger(); // -------------------------------------------------------------------------- // [Accessors] // -------------------------------------------------------------------------- //! @brief Get char* pointer which represents the serialized //! string. //! //! The pointer is owned by @ref StringLogger, it can't be modified or freed. inline const char* getString() const { return _stringBuilder.getData(); } //! @brief Clear the serialized string. inline void clearString() { _stringBuilder.clear(); } // -------------------------------------------------------------------------- // [Logging] // -------------------------------------------------------------------------- ASMJIT_API virtual void logString(const char* buf, size_t len = kInvalidSize); // -------------------------------------------------------------------------- // [Members] // -------------------------------------------------------------------------- //! @brief Output. StringBuilder _stringBuilder; }; //! @} } // AsmJit namespace // [Api-End] #include "../core/apiend.h" // [Guard] #endif // _ASMJIT_CORE_LOGGER_H desmume/src/utils/libfat/fat.h000664 001750 001750 00000007211 12755534123 017464 0ustar00sergiosergio000000 000000 /* fat.h Simple functionality for startup, mounting and unmounting of FAT-based devices. Copyright (c) 2006 - 2009 Michael "Chishm" Chisholm Dave "WinterMute" Murphy Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. 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. 3. The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. */ #ifndef _LIBFAT_H #define _LIBFAT_H #ifdef __cplusplus extern "C" { #endif // When compiling for NDS, make sure NDS is defined #ifndef NDS #if defined ARM9 || defined ARM7 #define NDS #endif #endif #ifndef _MSC_VER #include #endif #if defined(__gamecube__) || defined (__wii__) # include #else # ifdef NDS # include "nds/disc_io.h" # else # include "disc_io.h" # endif #endif /* Initialise any inserted block-devices. Add the fat device driver to the devoptab, making it available for standard file functions. cacheSize: The number of pages to allocate for each inserted block-device setAsDefaultDevice: if true, make this the default device driver for file operations */ extern bool fatInit (uint32_t cacheSize, bool setAsDefaultDevice); /* Calls fatInit with setAsDefaultDevice = true and cacheSize optimised for the host system. */ extern bool fatInitDefault (void); /* Mount the device pointed to by interface, and set up a devoptab entry for it as "name:". You can then access the filesystem using "name:/". This will mount the active partition or the first valid partition on the disc, and will use a cache size optimized for the host system. */ extern bool fatMountSimple (const char* name, const DISC_INTERFACE* interface); /* Mount the device pointed to by interface, and set up a devoptab entry for it as "name:". You can then access the filesystem using "name:/". If startSector = 0, it will mount the active partition of the first valid partition on the disc. Otherwise it will try to mount the partition starting at startSector. cacheSize specifies the number of pages to allocate for the cache. This will not startup the disc, so you need to call interface->startup(); first. */ extern bool fatMount (const char* name, const DISC_INTERFACE* interface, sec_t startSector, uint32_t cacheSize, uint32_t SectorsPerPage); /* Unmount the partition specified by name. If there are open files, it will attempt to synchronise them to disc. */ extern void fatUnmount (const char* name); /* Get Volume Label */ extern void fatGetVolumeLabel (const char* name, char *label); #ifdef __cplusplus } #endif #endif // _LIBFAT_H desmume/src/libretro-common/glsym/README.md000664 001750 001750 00000000414 12755534123 021660 0ustar00sergiosergio000000 000000 # Autogenerate GL extension loaders ## OpenGL desktop Use Khronos' recent [header](www.opengl.org/registry/api/glext.h). ./glgen.py /usr/include/GL/glext.h glsym_gl.h glsym_gl.c ## OpenGL ES ./glgen.py /usr/include/GLES2/gl2ext.h glsym_es2.h glsym_es2.c desmume/src/libretro-common/glsym/glsym_es3.c000664 001750 001750 00000014500 12755534123 022453 0ustar00sergiosergio000000 000000 #include "glsym/glsym.h" #include #define SYM(x) { "gl" #x, &(gl##x) } const struct rglgen_sym_map rglgen_symbol_map[] = { SYM(BlendBarrierKHR), SYM(DebugMessageControlKHR), SYM(DebugMessageInsertKHR), SYM(DebugMessageCallbackKHR), SYM(GetDebugMessageLogKHR), SYM(PushDebugGroupKHR), SYM(PopDebugGroupKHR), SYM(ObjectLabelKHR), SYM(GetObjectLabelKHR), SYM(ObjectPtrLabelKHR), SYM(GetObjectPtrLabelKHR), SYM(GetPointervKHR), SYM(GetGraphicsResetStatusKHR), SYM(ReadnPixelsKHR), SYM(GetnUniformfvKHR), SYM(GetnUniformivKHR), SYM(GetnUniformuivKHR), SYM(EGLImageTargetTexture2DOES), SYM(EGLImageTargetRenderbufferStorageOES), SYM(CopyImageSubDataOES), SYM(EnableiOES), SYM(DisableiOES), SYM(BlendEquationiOES), SYM(BlendEquationSeparateiOES), SYM(BlendFunciOES), SYM(BlendFuncSeparateiOES), SYM(ColorMaskiOES), SYM(IsEnablediOES), SYM(DrawElementsBaseVertexOES), SYM(DrawRangeElementsBaseVertexOES), SYM(DrawElementsInstancedBaseVertexOES), SYM(MultiDrawElementsBaseVertexOES), SYM(FramebufferTextureOES), SYM(GetProgramBinaryOES), SYM(ProgramBinaryOES), SYM(MapBufferOES), SYM(UnmapBufferOES), SYM(GetBufferPointervOES), SYM(PrimitiveBoundingBoxOES), SYM(MinSampleShadingOES), SYM(PatchParameteriOES), SYM(TexImage3DOES), SYM(TexSubImage3DOES), SYM(CopyTexSubImage3DOES), SYM(CompressedTexImage3DOES), SYM(CompressedTexSubImage3DOES), SYM(FramebufferTexture3DOES), SYM(TexParameterIivOES), SYM(TexParameterIuivOES), SYM(GetTexParameterIivOES), SYM(GetTexParameterIuivOES), SYM(SamplerParameterIivOES), SYM(SamplerParameterIuivOES), SYM(GetSamplerParameterIivOES), SYM(GetSamplerParameterIuivOES), SYM(TexBufferOES), SYM(TexBufferRangeOES), SYM(TexStorage3DMultisampleOES), SYM(TextureViewOES), SYM(BindVertexArrayOES), SYM(DeleteVertexArraysOES), SYM(GenVertexArraysOES), SYM(IsVertexArrayOES), SYM(FramebufferTextureMultiviewOVR), SYM(FramebufferTextureMultisampleMultiviewOVR), { NULL, NULL }, }; RGLSYMGLBLENDBARRIERKHRPROC __rglgen_glBlendBarrierKHR; RGLSYMGLDEBUGMESSAGECONTROLKHRPROC __rglgen_glDebugMessageControlKHR; RGLSYMGLDEBUGMESSAGEINSERTKHRPROC __rglgen_glDebugMessageInsertKHR; RGLSYMGLDEBUGMESSAGECALLBACKKHRPROC __rglgen_glDebugMessageCallbackKHR; RGLSYMGLGETDEBUGMESSAGELOGKHRPROC __rglgen_glGetDebugMessageLogKHR; RGLSYMGLPUSHDEBUGGROUPKHRPROC __rglgen_glPushDebugGroupKHR; RGLSYMGLPOPDEBUGGROUPKHRPROC __rglgen_glPopDebugGroupKHR; RGLSYMGLOBJECTLABELKHRPROC __rglgen_glObjectLabelKHR; RGLSYMGLGETOBJECTLABELKHRPROC __rglgen_glGetObjectLabelKHR; RGLSYMGLOBJECTPTRLABELKHRPROC __rglgen_glObjectPtrLabelKHR; RGLSYMGLGETOBJECTPTRLABELKHRPROC __rglgen_glGetObjectPtrLabelKHR; RGLSYMGLGETPOINTERVKHRPROC __rglgen_glGetPointervKHR; RGLSYMGLGETGRAPHICSRESETSTATUSKHRPROC __rglgen_glGetGraphicsResetStatusKHR; RGLSYMGLREADNPIXELSKHRPROC __rglgen_glReadnPixelsKHR; RGLSYMGLGETNUNIFORMFVKHRPROC __rglgen_glGetnUniformfvKHR; RGLSYMGLGETNUNIFORMIVKHRPROC __rglgen_glGetnUniformivKHR; RGLSYMGLGETNUNIFORMUIVKHRPROC __rglgen_glGetnUniformuivKHR; RGLSYMGLEGLIMAGETARGETTEXTURE2DOESPROC __rglgen_glEGLImageTargetTexture2DOES; RGLSYMGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC __rglgen_glEGLImageTargetRenderbufferStorageOES; RGLSYMGLCOPYIMAGESUBDATAOESPROC __rglgen_glCopyImageSubDataOES; RGLSYMGLENABLEIOESPROC __rglgen_glEnableiOES; RGLSYMGLDISABLEIOESPROC __rglgen_glDisableiOES; RGLSYMGLBLENDEQUATIONIOESPROC __rglgen_glBlendEquationiOES; RGLSYMGLBLENDEQUATIONSEPARATEIOESPROC __rglgen_glBlendEquationSeparateiOES; RGLSYMGLBLENDFUNCIOESPROC __rglgen_glBlendFunciOES; RGLSYMGLBLENDFUNCSEPARATEIOESPROC __rglgen_glBlendFuncSeparateiOES; RGLSYMGLCOLORMASKIOESPROC __rglgen_glColorMaskiOES; RGLSYMGLISENABLEDIOESPROC __rglgen_glIsEnablediOES; RGLSYMGLDRAWELEMENTSBASEVERTEXOESPROC __rglgen_glDrawElementsBaseVertexOES; RGLSYMGLDRAWRANGEELEMENTSBASEVERTEXOESPROC __rglgen_glDrawRangeElementsBaseVertexOES; RGLSYMGLDRAWELEMENTSINSTANCEDBASEVERTEXOESPROC __rglgen_glDrawElementsInstancedBaseVertexOES; RGLSYMGLMULTIDRAWELEMENTSBASEVERTEXOESPROC __rglgen_glMultiDrawElementsBaseVertexOES; RGLSYMGLFRAMEBUFFERTEXTUREOESPROC __rglgen_glFramebufferTextureOES; RGLSYMGLGETPROGRAMBINARYOESPROC __rglgen_glGetProgramBinaryOES; RGLSYMGLPROGRAMBINARYOESPROC __rglgen_glProgramBinaryOES; RGLSYMGLMAPBUFFEROESPROC __rglgen_glMapBufferOES; RGLSYMGLUNMAPBUFFEROESPROC __rglgen_glUnmapBufferOES; RGLSYMGLGETBUFFERPOINTERVOESPROC __rglgen_glGetBufferPointervOES; RGLSYMGLPRIMITIVEBOUNDINGBOXOESPROC __rglgen_glPrimitiveBoundingBoxOES; RGLSYMGLMINSAMPLESHADINGOESPROC __rglgen_glMinSampleShadingOES; RGLSYMGLPATCHPARAMETERIOESPROC __rglgen_glPatchParameteriOES; RGLSYMGLTEXIMAGE3DOESPROC __rglgen_glTexImage3DOES; RGLSYMGLTEXSUBIMAGE3DOESPROC __rglgen_glTexSubImage3DOES; RGLSYMGLCOPYTEXSUBIMAGE3DOESPROC __rglgen_glCopyTexSubImage3DOES; RGLSYMGLCOMPRESSEDTEXIMAGE3DOESPROC __rglgen_glCompressedTexImage3DOES; RGLSYMGLCOMPRESSEDTEXSUBIMAGE3DOESPROC __rglgen_glCompressedTexSubImage3DOES; RGLSYMGLFRAMEBUFFERTEXTURE3DOESPROC __rglgen_glFramebufferTexture3DOES; RGLSYMGLTEXPARAMETERIIVOESPROC __rglgen_glTexParameterIivOES; RGLSYMGLTEXPARAMETERIUIVOESPROC __rglgen_glTexParameterIuivOES; RGLSYMGLGETTEXPARAMETERIIVOESPROC __rglgen_glGetTexParameterIivOES; RGLSYMGLGETTEXPARAMETERIUIVOESPROC __rglgen_glGetTexParameterIuivOES; RGLSYMGLSAMPLERPARAMETERIIVOESPROC __rglgen_glSamplerParameterIivOES; RGLSYMGLSAMPLERPARAMETERIUIVOESPROC __rglgen_glSamplerParameterIuivOES; RGLSYMGLGETSAMPLERPARAMETERIIVOESPROC __rglgen_glGetSamplerParameterIivOES; RGLSYMGLGETSAMPLERPARAMETERIUIVOESPROC __rglgen_glGetSamplerParameterIuivOES; RGLSYMGLTEXBUFFEROESPROC __rglgen_glTexBufferOES; RGLSYMGLTEXBUFFERRANGEOESPROC __rglgen_glTexBufferRangeOES; RGLSYMGLTEXSTORAGE3DMULTISAMPLEOESPROC __rglgen_glTexStorage3DMultisampleOES; RGLSYMGLTEXTUREVIEWOESPROC __rglgen_glTextureViewOES; RGLSYMGLBINDVERTEXARRAYOESPROC __rglgen_glBindVertexArrayOES; RGLSYMGLDELETEVERTEXARRAYSOESPROC __rglgen_glDeleteVertexArraysOES; RGLSYMGLGENVERTEXARRAYSOESPROC __rglgen_glGenVertexArraysOES; RGLSYMGLISVERTEXARRAYOESPROC __rglgen_glIsVertexArrayOES; RGLSYMGLFRAMEBUFFERTEXTUREMULTIVIEWOVRPROC __rglgen_glFramebufferTextureMultiviewOVR; RGLSYMGLFRAMEBUFFERTEXTUREMULTISAMPLEMULTIVIEWOVRPROC __rglgen_glFramebufferTextureMultisampleMultiviewOVR; desmume/src/utils/AsmJit/core/apiend.h000664 001750 001750 00000000524 12755534123 021030 0ustar00sergiosergio000000 000000 // [AsmJit] // Complete JIT Assembler for C++ Language. // // [License] // Zlib - See COPYING file in this package. // [MSVC] #if defined(_MSC_VER) // Pop disabled warnings by ApiBegin.h #pragma warning(pop) // Rename symbols back. #undef vsnprintf #undef snprintf #endif // _MSC_VER // [GNUC] #if defined(__GNUC__) #endif // __GNUC__ desmume/src/libretro-common/include/memalign.h000664 001750 001750 00000003175 12755534123 022642 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2016 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (memalign.h). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef _LIBRETRO_MEMALIGN_H #define _LIBRETRO_MEMALIGN_H #include #include RETRO_BEGIN_DECLS void *memalign_alloc(size_t boundary, size_t size); void *memalign_alloc_aligned(size_t size); void memalign_free(void *ptr); RETRO_END_DECLS #endif desmume/src/libretro-common/file/nbio/test/Makefile000664 001750 001750 00000000532 12755534123 023534 0ustar00sergiosergio000000 000000 TARGET := nbio_test LIBRETRO_COMM_DIR := ../../.. SOURCES := \ nbio_test.c \ ../nbio_stdio.c OBJS := $(SOURCES:.c=.o) CFLAGS += -Wall -pedantic -std=gnu99 -g -I$(LIBRETRO_COMM_DIR)/include all: $(TARGET) %.o: %.c $(CC) -c -o $@ $< $(CFLAGS) $(TARGET): $(OBJS) $(CC) -o $@ $^ $(LDFLAGS) clean: rm -f $(TARGET) $(OBJS) .PHONY: clean desmume/src/mic_openal.cpp000664 001750 001750 00000006744 12755534123 016764 0ustar00sergiosergio000000 000000 /* Copyright (C) 2009-2010 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the this software. If not, see . */ #ifndef WIN32 #include #include #include "types.h" #include "mic.h" #include "readwrite.h" #include "emufile.h" #include "debug.h" #define MIC_BUFSIZE 512 BOOL Mic_Inited = FALSE; u8 Mic_Buffer[2][2*MIC_BUFSIZE]; u16 Mic_BufPos; u8 Mic_PlayBuf; u8 Mic_WriteBuf; int MicButtonPressed; ALCdevice *alDevice; ALCdevice *alCaptureDevice; ALCcontext *alContext; BOOL Mic_Init() { ALenum err; const char *szDefaultCaptureDevice; if (!(alDevice = alcOpenDevice(0))) { INFO("Failed to Initialize Open AL\n"); return FALSE; } if( !(alContext = alcCreateContext(alDevice, 0))) { INFO("Failed to create OpenAL context\n"); return FALSE; } if( !alcMakeContextCurrent(alContext)) { INFO("Failed to make OpenAL context current\n"); return FALSE; } alDistanceModel(AL_INVERSE_DISTANCE); szDefaultCaptureDevice = alcGetString(NULL, ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER); LOG("Default OpenAL Capture Device is '%s'\n\n", szDefaultCaptureDevice); alCaptureDevice = alcCaptureOpenDevice(szDefaultCaptureDevice, 16000, AL_FORMAT_STEREO8, MIC_BUFSIZE); err = alGetError(); if (err != AL_NO_ERROR) { INFO("Failed to alCaptureOpenDevice, ALenum %i\n", err); return 0; } alcCaptureStart(alCaptureDevice); Mic_Inited = TRUE; Mic_Reset(); return TRUE; } void Mic_Reset() { if (!Mic_Inited) return; memset(Mic_Buffer, 0, MIC_BUFSIZE*2*2); Mic_BufPos = 0; Mic_PlayBuf = 1; Mic_WriteBuf = 0; } void Mic_DeInit() { if (!Mic_Inited) return; Mic_Inited = FALSE; if (alDevice) { if (alCaptureDevice) { alcCaptureStop(alCaptureDevice); alcCaptureCloseDevice(alCaptureDevice); } if (alContext) { alcMakeContextCurrent(0); alcDestroyContext(alContext); } alcCloseDevice(alDevice); } } static void alReadSound() { ALenum err; int num; alcGetIntegerv(alCaptureDevice, ALC_CAPTURE_SAMPLES, 1, &num); if (num < MIC_BUFSIZE-1) { LOG("not enough microphone data waiting! (%i samples)\n", num); } else { LOG("%i samples waiting\n", num); } if (num > MIC_BUFSIZE) num = MIC_BUFSIZE; alcCaptureSamples(alCaptureDevice, Mic_Buffer[Mic_WriteBuf], num); err = alGetError(); if (err != AL_NO_ERROR) { INFO("Failed to alcCaptureSamples, ALenum %i\n", err); return; } } u8 Mic_ReadSample() { static u8 stats_max; static u8 stats_min; u8 ret; if (Mic_BufPos >= MIC_BUFSIZE) { alReadSound(); Mic_BufPos = 0; Mic_PlayBuf ^= 1; Mic_WriteBuf ^= 1; } ret = Mic_Buffer[Mic_PlayBuf][Mic_BufPos >> 1]; if (ret > stats_max) stats_max = ret; if (ret < stats_min) stats_min = ret; Mic_BufPos += 2; return ret; } void mic_savestate(EMUFILE* os) { write32le(-1,os); } bool mic_loadstate(EMUFILE* is, int size) { is->fseek(size, SEEK_CUR); return TRUE; } #endif desmume/src/instructions.h000664 001750 001750 00000002026 12755534123 017054 0ustar00sergiosergio000000 000000 /* Copyright (C) 2006 yopyop Copyright (C) 2012-2015 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the this software. If not, see . */ #ifndef _INSTRUCIONS_H_ #define _INSTRUCIONS_H_ #include "types.h" typedef u32 (FASTCALL* OpFunc)(const u32 i); extern const OpFunc arm_instructions_set[2][4096]; extern const char* arm_instruction_names[4096]; extern const OpFunc thumb_instructions_set[2][1024]; extern const char* thumb_instruction_names[1024]; #endif desmume/src/libretro-common/formats/png/rpng_encode.c000664 001750 001750 00000026234 12755534123 024144 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2016 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (rpng_encode.c). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include #include #include #include #include #include "rpng_internal.h" #undef GOTO_END_ERROR #define GOTO_END_ERROR() do { \ fprintf(stderr, "[RPNG]: Error in line %d.\n", __LINE__); \ ret = false; \ goto end; \ } while(0) static void dword_write_be(uint8_t *buf, uint32_t val) { *buf++ = (uint8_t)(val >> 24); *buf++ = (uint8_t)(val >> 16); *buf++ = (uint8_t)(val >> 8); *buf++ = (uint8_t)(val >> 0); } static bool png_write_crc(RFILE *file, const uint8_t *data, size_t size) { uint8_t crc_raw[4] = {0}; const struct file_archive_file_backend *stream_backend = file_archive_get_default_file_backend(); uint32_t crc = stream_backend->stream_crc_calculate(0, data, size); dword_write_be(crc_raw, crc); return filestream_write(file, crc_raw, sizeof(crc_raw)) == sizeof(crc_raw); } static bool png_write_ihdr(RFILE *file, const struct png_ihdr *ihdr) { uint8_t ihdr_raw[21]; ihdr_raw[0] = '0'; /* Size */ ihdr_raw[1] = '0'; ihdr_raw[2] = '0'; ihdr_raw[3] = '0'; ihdr_raw[4] = 'I'; ihdr_raw[5] = 'H'; ihdr_raw[6] = 'D'; ihdr_raw[7] = 'R'; ihdr_raw[8] = 0; /* Width */ ihdr_raw[9] = 0; ihdr_raw[10] = 0; ihdr_raw[11] = 0; ihdr_raw[12] = 0; /* Height */ ihdr_raw[13] = 0; ihdr_raw[14] = 0; ihdr_raw[15] = 0; ihdr_raw[16] = ihdr->depth; /* Depth */ ihdr_raw[17] = ihdr->color_type; ihdr_raw[18] = ihdr->compression; ihdr_raw[19] = ihdr->filter; ihdr_raw[20] = ihdr->interlace; dword_write_be(ihdr_raw + 0, sizeof(ihdr_raw) - 8); dword_write_be(ihdr_raw + 8, ihdr->width); dword_write_be(ihdr_raw + 12, ihdr->height); if (filestream_write(file, ihdr_raw, sizeof(ihdr_raw)) != sizeof(ihdr_raw)) return false; if (!png_write_crc(file, ihdr_raw + sizeof(uint32_t), sizeof(ihdr_raw) - sizeof(uint32_t))) return false; return true; } static bool png_write_idat(RFILE *file, const uint8_t *data, size_t size) { if (filestream_write(file, data, size) != (ssize_t)size) return false; if (!png_write_crc(file, data + sizeof(uint32_t), size - sizeof(uint32_t))) return false; return true; } static bool png_write_iend(RFILE *file) { const uint8_t data[] = { 0, 0, 0, 0, 'I', 'E', 'N', 'D', }; if (filestream_write(file, data, sizeof(data)) != sizeof(data)) return false; if (!png_write_crc(file, data + sizeof(uint32_t), sizeof(data) - sizeof(uint32_t))) return false; return true; } static void copy_argb_line(uint8_t *dst, const uint32_t *src, unsigned width) { unsigned i; for (i = 0; i < width; i++) { uint32_t col = src[i]; *dst++ = (uint8_t)(col >> 16); *dst++ = (uint8_t)(col >> 8); *dst++ = (uint8_t)(col >> 0); *dst++ = (uint8_t)(col >> 24); } } static void copy_bgr24_line(uint8_t *dst, const uint8_t *src, unsigned width) { unsigned i; for (i = 0; i < width; i++, dst += 3, src += 3) { dst[2] = src[0]; dst[1] = src[1]; dst[0] = src[2]; } } static unsigned count_sad(const uint8_t *data, size_t size) { size_t i; unsigned cnt = 0; for (i = 0; i < size; i++) cnt += abs((int8_t)data[i]); return cnt; } static unsigned filter_up(uint8_t *target, const uint8_t *line, const uint8_t *prev, unsigned width, unsigned bpp) { unsigned i; width *= bpp; for (i = 0; i < width; i++) target[i] = line[i] - prev[i]; return count_sad(target, width); } static unsigned filter_sub(uint8_t *target, const uint8_t *line, unsigned width, unsigned bpp) { unsigned i; width *= bpp; for (i = 0; i < bpp; i++) target[i] = line[i]; for (i = bpp; i < width; i++) target[i] = line[i] - line[i - bpp]; return count_sad(target, width); } static unsigned filter_avg(uint8_t *target, const uint8_t *line, const uint8_t *prev, unsigned width, unsigned bpp) { unsigned i; width *= bpp; for (i = 0; i < bpp; i++) target[i] = line[i] - (prev[i] >> 1); for (i = bpp; i < width; i++) target[i] = line[i] - ((line[i - bpp] + prev[i]) >> 1); return count_sad(target, width); } static unsigned filter_paeth(uint8_t *target, const uint8_t *line, const uint8_t *prev, unsigned width, unsigned bpp) { unsigned i; width *= bpp; for (i = 0; i < bpp; i++) target[i] = line[i] - paeth(0, prev[i], 0); for (i = bpp; i < width; i++) target[i] = line[i] - paeth(line[i - bpp], prev[i], prev[i - bpp]); return count_sad(target, width); } static bool rpng_save_image(const char *path, const uint8_t *data, unsigned width, unsigned height, unsigned pitch, unsigned bpp) { unsigned h; bool ret = true; struct png_ihdr ihdr = {0}; const struct file_archive_file_backend *stream_backend = NULL; size_t encode_buf_size = 0; uint8_t *encode_buf = NULL; uint8_t *deflate_buf = NULL; uint8_t *rgba_line = NULL; uint8_t *up_filtered = NULL; uint8_t *sub_filtered = NULL; uint8_t *avg_filtered = NULL; uint8_t *paeth_filtered = NULL; uint8_t *prev_encoded = NULL; uint8_t *encode_target = NULL; void *stream = NULL; RFILE *file = filestream_open(path, RFILE_MODE_WRITE, -1); if (!file) GOTO_END_ERROR(); stream_backend = file_archive_get_default_file_backend(); if (filestream_write(file, png_magic, sizeof(png_magic)) != sizeof(png_magic)) GOTO_END_ERROR(); ihdr.width = width; ihdr.height = height; ihdr.depth = 8; ihdr.color_type = bpp == sizeof(uint32_t) ? 6 : 2; /* RGBA or RGB */ if (!png_write_ihdr(file, &ihdr)) GOTO_END_ERROR(); encode_buf_size = (width * bpp + 1) * height; encode_buf = (uint8_t*)malloc(encode_buf_size); if (!encode_buf) GOTO_END_ERROR(); prev_encoded = (uint8_t*)calloc(1, width * bpp); if (!prev_encoded) GOTO_END_ERROR(); rgba_line = (uint8_t*)malloc(width * bpp); up_filtered = (uint8_t*)malloc(width * bpp); sub_filtered = (uint8_t*)malloc(width * bpp); avg_filtered = (uint8_t*)malloc(width * bpp); paeth_filtered = (uint8_t*)malloc(width * bpp); if (!rgba_line || !up_filtered || !sub_filtered || !avg_filtered || !paeth_filtered) GOTO_END_ERROR(); encode_target = encode_buf; for (h = 0; h < height; h++, encode_target += width * bpp, data += pitch) { if (bpp == sizeof(uint32_t)) copy_argb_line(rgba_line, (const uint32_t*)data, width); else copy_bgr24_line(rgba_line, data, width); /* Try every filtering method, and choose the method * which has most entries as zero. * * This is probably not very optimal, but it's very * simple to implement. */ { unsigned none_score = count_sad(rgba_line, width * bpp); unsigned up_score = filter_up(up_filtered, rgba_line, prev_encoded, width, bpp); unsigned sub_score = filter_sub(sub_filtered, rgba_line, width, bpp); unsigned avg_score = filter_avg(avg_filtered, rgba_line, prev_encoded, width, bpp); unsigned paeth_score = filter_paeth(paeth_filtered, rgba_line, prev_encoded, width, bpp); uint8_t filter = 0; unsigned min_sad = none_score; const uint8_t *chosen_filtered = rgba_line; if (sub_score < min_sad) { filter = 1; chosen_filtered = sub_filtered; min_sad = sub_score; } if (up_score < min_sad) { filter = 2; chosen_filtered = up_filtered; min_sad = up_score; } if (avg_score < min_sad) { filter = 3; chosen_filtered = avg_filtered; min_sad = avg_score; } if (paeth_score < min_sad) { filter = 4; chosen_filtered = paeth_filtered; min_sad = paeth_score; } *encode_target++ = filter; memcpy(encode_target, chosen_filtered, width * bpp); memcpy(prev_encoded, rgba_line, width * bpp); } } deflate_buf = (uint8_t*)malloc(encode_buf_size * 2); /* Just to be sure. */ if (!deflate_buf) GOTO_END_ERROR(); stream = stream_backend->stream_new(); if (!stream) GOTO_END_ERROR(); stream_backend->stream_set( stream, encode_buf_size, encode_buf_size * 2, encode_buf, deflate_buf + 8); stream_backend->stream_compress_init(stream, 9); if (stream_backend->stream_compress_data_to_file(stream) != 1) { stream_backend->stream_compress_free(stream); GOTO_END_ERROR(); } stream_backend->stream_compress_free(stream); memcpy(deflate_buf + 4, "IDAT", 4); dword_write_be(deflate_buf + 0, ((uint32_t)stream_backend->stream_get_total_out(stream))); if (!png_write_idat(file, deflate_buf, ((size_t)stream_backend->stream_get_total_out(stream) + 8))) GOTO_END_ERROR(); if (!png_write_iend(file)) GOTO_END_ERROR(); end: filestream_close(file); free(encode_buf); free(deflate_buf); free(rgba_line); free(prev_encoded); free(up_filtered); free(sub_filtered); free(avg_filtered); free(paeth_filtered); if (stream_backend) stream_backend->stream_free(stream); return ret; } bool rpng_save_image_argb(const char *path, const uint32_t *data, unsigned width, unsigned height, unsigned pitch) { return rpng_save_image(path, (const uint8_t*)data, width, height, pitch, sizeof(uint32_t)); } bool rpng_save_image_bgr24(const char *path, const uint8_t *data, unsigned width, unsigned height, unsigned pitch) { return rpng_save_image(path, (const uint8_t*)data, width, height, pitch, 3); } desmume/src/libretro-common/include/compat/msvc.h000664 001750 001750 00000006274 12755534123 023307 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2016 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (msvc_compat.h). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef __LIBRETRO_SDK_COMPAT_MSVC_H #define __LIBRETRO_SDK_COMPAT_MSVC_H #ifdef _MSC_VER #ifdef __cplusplus extern "C" { #endif /* Pre-MSVC 2015 compilers don't implement snprintf in a cross-platform manner. */ #if _MSC_VER < 1900 #include #ifndef snprintf #define snprintf c99_snprintf_retro__ #endif int c99_snprintf_retro__(char *outBuf, size_t size, const char *format, ...); #endif /* Pre-MSVC 2010 compilers don't implement vsnprintf in a cross-platform manner? Not sure about this one. */ #if _MSC_VER < 1600 #include #include #ifndef vsnprintf #define vsnprintf c99_vsnprintf_retro__ #endif int c99_vsnprintf_retro__(char *outBuf, size_t size, const char *format, va_list ap); #endif #ifdef __cplusplus } #endif #undef UNICODE /* Do not bother with UNICODE at this time. */ #include #include #include /* Python headers defines ssize_t and sets HAVE_SSIZE_T. * Cannot duplicate these efforts. */ #ifndef HAVE_SSIZE_T #if defined(_WIN64) typedef __int64 ssize_t; #elif defined(_WIN32) typedef int ssize_t; #endif #endif #define mkdir(dirname, unused) _mkdir(dirname) #define strtoull _strtoui64 #undef strcasecmp #define strcasecmp _stricmp #undef strncasecmp #define strncasecmp _strnicmp /* Disable some of the annoying warnings. */ #pragma warning(disable : 4800) #pragma warning(disable : 4805) #pragma warning(disable : 4244) #pragma warning(disable : 4305) #pragma warning(disable : 4146) #pragma warning(disable : 4267) #pragma warning(disable : 4723) #pragma warning(disable : 4996) /* roundf is available since MSVC 2013 */ #if _MSC_VER < 1800 #define roundf(in) (in >= 0.0f ? floorf(in + 0.5f) : ceilf(in - 0.5f)) #endif #ifndef PATH_MAX #define PATH_MAX _MAX_PATH #endif #ifndef SIZE_MAX #define SIZE_MAX _UI32_MAX #endif #endif #endif desmume/src/utils/AsmJit/core/compiler.h000664 001750 001750 00000027053 12755534123 021410 0ustar00sergiosergio000000 000000 // [AsmJit] // Complete JIT Assembler for C++ Language. // // [License] // Zlib - See COPYING file in this package. // [Guard] #ifndef _ASMJIT_CORE_COMPILER_H #define _ASMJIT_CORE_COMPILER_H // [Dependencies - AsmJit] #include "../core/assembler.h" #include "../core/context.h" #include "../core/func.h" #include "../core/operand.h" #include "../core/podvector.h" // [Api-Begin] #include "../core/apibegin.h" namespace AsmJit { // ============================================================================ // [Forward Declarations] // ============================================================================ struct Compiler; struct CompilerAlign; struct CompilerComment; struct CompilerContext; struct CompilerEmbed; struct CompilerFuncCall; struct CompilerFuncDecl; struct CompilerFuncEnd; struct CompilerInst; struct CompilerItem; struct CompilerMark; struct CompilerState; struct CompilerTarget; struct CompilerVar; // ============================================================================ // [AsmJit::CompilerState] // ============================================================================ //! @brief Compiler state base. struct CompilerState { }; // ============================================================================ // [AsmJit::CompilerVar] // ============================================================================ //! @brief Compiler variable base. struct CompilerVar { // -------------------------------------------------------------------------- // [Accessors] // -------------------------------------------------------------------------- //! @brief Get variable name. inline const char* getName() const { return _name; } //! @brief Get variable id. inline uint32_t getId() const { return _id; } //! @brief Get variable type. inline uint32_t getType() const { return _type; } //! @brief Get variable class. inline uint32_t getClass() const { return _class; } //! @brief Get variable priority. inline uint32_t getPriority() const { return _priority; } //! @brief Get variable size. inline uint32_t getSize() const { return _size; } //! @brief Get whether the variable is a function argument. inline bool isArgument() const { return static_cast(_isRegArgument | _isMemArgument); } //! @brief Get whether the variable is a function argument passed through register. inline bool isRegArgument() const { return static_cast(_isRegArgument); } //! @brief Get whether the variable is a function argument passed through memory. inline bool isMemArgument() const { return static_cast(_isMemArgument); } //! @brief Get variable content can be calculated by a simple instruction. inline bool isCalculated() const { return static_cast(_isCalculated); } // -------------------------------------------------------------------------- // [Members] // -------------------------------------------------------------------------- //! @brief Variable name. const char* _name; //! @brief Variable id. uint32_t _id; //! @brief Variable type. uint8_t _type; //! @brief Variable class. uint8_t _class; //! @brief Variable priority. uint8_t _priority; //! @brief Whether the variable is a function argument passed through register. uint8_t _isRegArgument : 1; //! @brief Whether the variable is a function argument passed through memory. uint8_t _isMemArgument : 1; //! @brief Whether variable content can be calculated by a simple instruction. //! //! This is used mainly by MMX and SSE2 code. This flag indicates that //! register allocator should never reserve memory for this variable, because //! the content can be generated by a single instruction (for example PXOR). uint8_t _isCalculated : 1; //! @internal. uint8_t _unused : 5; //! @brief Variable size. uint32_t _size; }; // ============================================================================ // [AsmJit::Compiler] // ============================================================================ //! @brief Compiler. //! //! @sa @ref Assembler. struct Compiler { // -------------------------------------------------------------------------- // [Construction / Destruction] // -------------------------------------------------------------------------- //! @brief Create a new @ref Compiler instance. ASMJIT_API Compiler(Context* context); //! @brief Destroy the @ref Compiler instance. ASMJIT_API virtual ~Compiler(); // -------------------------------------------------------------------------- // [Context] // -------------------------------------------------------------------------- //! @brief Get code generator. inline Context* getContext() const { return _context; } // -------------------------------------------------------------------------- // [Memory Management] // -------------------------------------------------------------------------- //! @brief Get zone memory manager. inline ZoneMemory& getZoneMemory() { return _zoneMemory; } //! @brief Get link memory manager. inline ZoneMemory& getLinkMemory() { return _linkMemory; } // -------------------------------------------------------------------------- // [Logging] // -------------------------------------------------------------------------- //! @brief Get logger. inline Logger* getLogger() const { return _logger; } //! @brief Set logger to @a logger. ASMJIT_API virtual void setLogger(Logger* logger); // -------------------------------------------------------------------------- // [Error Handling] // -------------------------------------------------------------------------- //! @brief Get error code. inline uint32_t getError() const { return _error; } //! @brief Set error code. //! //! This method is virtual, because higher classes can use it to catch all //! errors. ASMJIT_API virtual void setError(uint32_t error); // -------------------------------------------------------------------------- // [Properties] // -------------------------------------------------------------------------- //! @brief Get compiler property. ASMJIT_API virtual uint32_t getProperty(uint32_t propertyId); //! @brief Set compiler property. ASMJIT_API virtual void setProperty(uint32_t propertyId, uint32_t value); // -------------------------------------------------------------------------- // [Clear / Reset] // -------------------------------------------------------------------------- //! @brief Clear everything, but not deallocate buffers. //! //! @note This method will destroy your code. ASMJIT_API void clear(); //! @brief Free internal buffer, all emitters and NULL all pointers. //! //! @note This method will destroy your code. ASMJIT_API void reset(); //! @brief Called by clear() and reset() to clear all data related to derived //! class implementation. ASMJIT_API virtual void _purge(); // -------------------------------------------------------------------------- // [Item Management] // -------------------------------------------------------------------------- //! @brief Get first item. inline CompilerItem* getFirstItem() const { return _first; } //! @brief Get last item. inline CompilerItem* getLastItem() const { return _last; } //! @brief Get current item. //! //! @note If this method returns @c NULL it means that nothing has been //! emitted yet. inline CompilerItem* getCurrentItem() const { return _current; } //! @brief Get current function. inline CompilerFuncDecl* getFunc() const { return _func; } //! @brief Set current item to @a item and return the previous current one. ASMJIT_API CompilerItem* setCurrentItem(CompilerItem* item); //! @brief Add item after current item to @a item and set current item to //! @a item. ASMJIT_API void addItem(CompilerItem* item); //! @brief Add item after @a ref. ASMJIT_API void addItemAfter(CompilerItem* item, CompilerItem* ref); //! @brief Remove item @a item. ASMJIT_API void removeItem(CompilerItem* item); // -------------------------------------------------------------------------- // [Comment] // -------------------------------------------------------------------------- //! @brief Emit a single comment line. //! //! @note Comment is not directly sent to logger, but instead it's stored as //! @ref CompilerComment item emitted when @c serialize() method is called. ASMJIT_API void comment(const char* fmt, ...); // -------------------------------------------------------------------------- // [Embed] // -------------------------------------------------------------------------- //! @brief Embed data. ASMJIT_API void embed(const void* data, size_t len); // -------------------------------------------------------------------------- // [Members] // -------------------------------------------------------------------------- //! @brief ZoneMemory allocator, used to allocate compiler items. ZoneMemory _zoneMemory; //! @brief ZoneMemory allocator, used to alloc small data structures like //! linked lists. ZoneMemory _linkMemory; //! @brief Context. Context* _context; //! @brief Logger. Logger* _logger; //! @brief Error code. uint32_t _error; //! @brief Properties. uint32_t _properties; //! @brief Contains options for next emitted instruction, clear after each emit. uint32_t _emitOptions; //! @brief Whether compiler was finished the job (register allocator, etc...). uint32_t _finished; //! @brief First item. CompilerItem* _first; //! @brief Last item. CompilerItem* _last; //! @brief Current item. CompilerItem* _current; //! @brief Current function. CompilerFuncDecl* _func; //! @brief Targets. PodVector _targets; //! @brief Variables. PodVector _vars; //! @brief Compiler context instance, only available after prepare(). CompilerContext* _cc; //! @brief Variable name id (used to generate unique names per function). int _varNameId; }; // ============================================================================ // [AsmJit::Compiler - Helpers] // ============================================================================ template inline T* Compiler_newItem(Compiler* self) { void* addr = self->getZoneMemory().alloc(sizeof(T)); return new(addr) T(self); } template inline T* Compiler_newItem(Compiler* self, P1 p1) { void* addr = self->getZoneMemory().alloc(sizeof(T)); return new(addr) T(self, p1); } template inline T* Compiler_newItem(Compiler* self, P1 p1, P2 p2) { void* addr = self->getZoneMemory().alloc(sizeof(T)); return new(addr) T(self, p1, p2); } template inline T* Compiler_newItem(Compiler* self, P1 p1, P2 p2, P3 p3) { void* addr = self->getZoneMemory().alloc(sizeof(T)); return new(addr) T(self, p1, p2, p3); } template inline T* Compiler_newItem(Compiler* self, P1 p1, P2 p2, P3 p3, P4 p4) { void* addr = self->getZoneMemory().alloc(sizeof(T)); return new(addr) T(self, p1, p2, p3, p4); } template inline T* Compiler_newItem(Compiler* self, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) { void* addr = self->getZoneMemory().alloc(sizeof(T)); return new(addr) T(self, p1, p2, p3, p4, p5); } } // AsmJit namespace // [Api-End] #include "../core/apiend.h" // [Guard] #endif // _ASMJIT_CORE_COMPILER_H desmume/src/libretro-common/include/retro_stat.h000664 001750 001750 00000004120 12755534123 023226 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2016 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (retro_stat.h). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef __RETRO_STAT_H #define __RETRO_STAT_H #include #include #include #include RETRO_BEGIN_DECLS /** * path_is_directory: * @path : path * * Checks if path is a directory. * * Returns: true (1) if path is a directory, otherwise false (0). */ bool path_is_directory(const char *path); bool path_is_character_special(const char *path); bool path_is_valid(const char *path); int32_t path_get_size(const char *path); /** * path_mkdir_norecurse: * @dir : directory * * Create directory on filesystem. * * Returns: true (1) if directory could be created, otherwise false (0). **/ bool mkdir_norecurse(const char *dir); RETRO_END_DECLS #endif desmume/src/utils/AsmJit/core/compilercontext.cpp000664 001750 001750 00000001542 12755534123 023343 0ustar00sergiosergio000000 000000 // [AsmJit] // Complete JIT Assembler for C++ Language. // // [License] // Zlib - See COPYING file in this package. #define ASMJIT_EXPORTS // [Dependencies - AsmJit] #include "../core/compilercontext.h" // [Api-Begin] #include "../core/apibegin.h" namespace AsmJit { // ============================================================================ // [AsmJit::CompilerContext - Construction / Destruction] // ============================================================================ CompilerContext::CompilerContext(Compiler* compiler) : _zoneMemory(8192 - sizeof(ZoneChunk) - 32), _compiler(compiler), _func(NULL), _start(NULL), _stop(NULL), _extraBlock(NULL), _state(NULL), _active(NULL), _currentOffset(0), _isUnreachable(0) { } CompilerContext::~CompilerContext() { } } // AsmJit namespace // [Api-End] #include "../core/apiend.h" desmume/src/libretro-common/include/glsm/glsmsym.h000664 001750 001750 00000043335 12755534123 023510 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2016 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this libretro SDK code part (glsmsym.h). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef LIBRETRO_SDK_GLSM_SYM_H #define LIBRETRO_SDK_GLSM_SYM_H #include #include RETRO_BEGIN_DECLS /* deprecated old FF-style GL symbols */ #define glTexCoord2f rglTexCoord2f /* more forward-compatible GL subset symbols */ #define glBlitFramebuffer rglBlitFramebuffer #define glVertexAttrib4f rglVertexAttrib4f #define glVertexAttrib4fv rglVertexAttrib4fv #define glDrawArrays rglDrawArrays #define glDrawElements rglDrawElements #define glCompressedTexImage2D rglCompressedTexImage2D #define glBindTexture rglBindTexture #define glActiveTexture rglActiveTexture #define glFramebufferTexture rglFramebufferTexture #define glFramebufferTexture2D rglFramebufferTexture2D #define glFramebufferRenderbuffer rglFramebufferRenderbuffer #define glDeleteFramebuffers rglDeleteFramebuffers #define glDeleteTextures rglDeleteTextures #define glDeleteBuffers rglDeleteBuffers #define glRenderbufferStorage rglRenderbufferStorage #define glBindRenderbuffer rglBindRenderbuffer #define glDeleteRenderbuffers rglDeleteRenderbuffers #define glGenRenderbuffers rglGenRenderbuffers #define glGenFramebuffers rglGenFramebuffers #define glGenTextures rglGenTextures #define glBindFramebuffer rglBindFramebuffer #define glGenerateMipmap rglGenerateMipmap #define glCheckFramebufferStatus rglCheckFramebufferStatus #define glBindFragDataLocation rglBindFragDataLocation #define glBindAttribLocation rglBindAttribLocation #define glLinkProgram rglLinkProgram #define glGetProgramiv rglGetProgramiv #define glGetShaderiv rglGetShaderiv #define glAttachShader rglAttachShader #define glDetachShader rglDetachShader #define glShaderSource rglShaderSource #define glCompileShader rglCompileShader #define glCreateProgram rglCreateProgram #define glGetShaderInfoLog rglGetShaderInfoLog #define glGetProgramInfoLog rglGetProgramInfoLog #define glIsProgram rglIsProgram #define glEnableVertexAttribArray rglEnableVertexAttribArray #define glDisableVertexAttribArray rglDisableVertexAttribArray #define glVertexAttribPointer rglVertexAttribPointer #define glVertexAttribIPointer rglVertexAttribIPointer #define glVertexAttribLPointer rglVertexAttribLPointer #define glGetUniformLocation rglGetUniformLocation #define glGenBuffers rglGenBuffers #define glDisable(T) rglDisable(S##T) #define glEnable(T) rglEnable(S##T) #define glIsEnabled(T) rglIsEnabled(S##T) #define glUseProgram rglUseProgram #define glDepthMask rglDepthMask #define glStencilMask rglStencilMask #define glBufferData rglBufferData #define glBufferSubData rglBufferSubData #define glBindBuffer rglBindBuffer #define glCreateShader rglCreateShader #define glDeleteShader rglDeleteShader #define glDeleteProgram rglDeleteProgram #define glUniform1f rglUniform1f #define glUniform1i rglUniform1i #define glUniform2f rglUniform2f #define glUniform2i rglUniform2i #define glUniform2fv rglUniform2fv #define glUniform3f rglUniform3f #define glUniform3fv rglUniform3fv #define glUniform4i rglUniform4i #define glUniform4f rglUniform4f #define glUniform4fv rglUniform4fv #define glUniform1ui rglUniform1ui #define glUniform2ui rglUniform2ui #define glUniform3ui rglUniform3ui #define glUniform4ui rglUniform4ui #define glGetActiveUniform rglGetActiveUniform #define glBlendFunc rglBlendFunc #define glBlendFuncSeparate rglBlendFuncSeparate #define glDepthFunc rglDepthFunc #define glColorMask rglColorMask #define glClearColor rglClearColor #define glViewport rglViewport #define glScissor rglScissor #define glStencilFunc rglStencilFunc #define glCullFace rglCullFace #define glStencilOp rglStencilOp #define glFrontFace rglFrontFace #define glDepthRange rglDepthRange #define glClearDepth rglClearDepth #define glPolygonOffset rglPolygonOffset #define glPixelStorei rglPixelStorei #define glReadBuffer rglReadBuffer #define glUniformMatrix4fv rglUniformMatrix4fv #define glGetAttribLocation rglGetAttribLocation #define glTexStorage2D rglTexStorage2D #define glDrawBuffers rglDrawBuffers #define glGenVertexArrays rglGenVertexArrays #define glBindVertexArray rglBindVertexArray #define glBlendEquation rglBlendEquation #define glBlendColor rglBlendColor #define glBlendEquationSeparate rglBlendEquationSeparate #define glCopyImageSubData rglCopyImageSubData #define glMapBuffer rglMapBuffer #define glUnmapBuffer rglUnmapBuffer #define glMapBufferRange rglMapBufferRange #define glUniformBlockBinding rglUniformBlockBinding #define glGetUniformBlockIndex rglGetUniformBlockIndex #define glGetActiveUniformBlockiv rglGetActiveUniformBlockiv #define glBindBufferBase rglBindBufferBase #define glGetUniformIndices rglGetUniformIndices #define glGetActiveUniformsiv rglGetActiveUniformsiv #define glGetError rglGetError #define glClear rglClear #define glPolygonMode rglPolygonMode #define glLineWidth rglLineWidth #define glTexImage2DMultisample rglTexImage2DMultisample #define glTexStorage2DMultisample rglTexStorage2DMultisample #define glMemoryBarrier rglMemoryBarrier #define glBindImageTexture rglBindImageTexture #define glProgramBinary rglProgramBinary #define glGetProgramBinary rglGetProgramBinary #define glProgramParameteri rglProgramParameteri #define glTexSubImage2D rglTexSubImage2D #define glDeleteVertexArrays rglDeleteVertexArrays #define glRenderbufferStorageMultisample rglRenderbufferStorageMultisample #define glUniform1iv rglUniform1iv #define glUniform1fv rglUniform1fv #define glValidateProgram rglValidateProgram #define glGetStringi rglGetStringi #define glTexBuffer rglTexBuffer #define glClearBufferfv rglClearBufferfv #define glClearBufferfi rglClearBufferfi #define glWaitSync rglWaitSync #define glFenceSync rglFenceSync const GLubyte* rglGetStringi(GLenum name, GLuint index); void rglTexBuffer(GLenum target, GLenum internalFormat, GLuint buffer); void rglClearBufferfv( GLenum buffer, GLint drawBuffer, const GLfloat * value); void rglClearBufferfi( GLenum buffer, GLint drawBuffer, GLfloat depth, GLint stencil); void rglValidateProgram(GLuint program); void rglRenderbufferStorageMultisample( GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); void rglUniform1iv(GLint location, GLsizei count, const GLint *value); void rglUniform1fv(GLint location, GLsizei count, const GLfloat *value); void rglProgramParameteri( GLuint program, GLenum pname, GLint value); void rglGetProgramBinary( GLuint program, GLsizei bufsize, GLsizei *length, GLenum *binaryFormat, void *binary); void rglProgramBinary(GLuint program, GLenum binaryFormat, const void *binary, GLsizei length); void rglBindImageTexture( GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLenum format); void rglTexStorage2DMultisample(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations); void rglGetActiveUniformsiv( GLuint program, GLsizei uniformCount, const GLuint *uniformIndices, GLenum pname, GLint *params); void rglGetUniformIndices( GLuint program, GLsizei uniformCount, const GLchar **uniformNames, GLuint *uniformIndices); void rglBindBufferBase( GLenum target, GLuint index, GLuint buffer); void rglGetActiveUniformBlockiv( GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint *params); GLuint rglGetUniformBlockIndex( GLuint program, const GLchar *uniformBlockName); void * rglMapBuffer( GLenum target, GLenum access); void *rglMapBufferRange( GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access); GLboolean rglUnmapBuffer( GLenum target); void rglBlendColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); void rglBlendEquation(GLenum mode); void rglGenVertexArrays(GLsizei n, GLuint *arrays); void rglReadBuffer(GLenum mode); void rglPixelStorei(GLenum pname, GLint param); void rglTexCoord2f(GLfloat s, GLfloat t); void rglDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid * indices); void rglTexStorage2D(GLenum target, GLsizei levels, GLenum internalFormat, GLsizei width, GLsizei height); void rglCompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data); void glBindTexture(GLenum target, GLuint texture); void glActiveTexture(GLenum texture); void rglFramebufferTexture(GLenum target, GLenum attachment, GLuint texture, GLint level); void rglFramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); void rglFramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); void rglDeleteFramebuffers(GLsizei n, const GLuint *framebuffers); void rglRenderbufferStorage(GLenum target, GLenum internalFormat, GLsizei width, GLsizei height); void rglDeleteTextures(GLsizei n, const GLuint *textures); void rglBindRenderbuffer(GLenum target, GLuint renderbuffer); void rglDeleteRenderbuffers(GLsizei n, GLuint *renderbuffers); void rglGenRenderbuffers(GLsizei n, GLuint *renderbuffers); void rglGenFramebuffers(GLsizei n, GLuint *ids); void rglGenTextures(GLsizei n, GLuint *textures); void rglBindFramebuffer(GLenum target, GLuint framebuffer); void rglGenerateMipmap(GLenum target); GLenum rglCheckFramebufferStatus(GLenum target); void rglBindFragDataLocation(GLuint program, GLuint colorNumber, const char * name); void rglBindAttribLocation(GLuint program, GLuint index, const GLchar *name); void rglLinkProgram(GLuint program); void rglGetProgramiv(GLuint shader, GLenum pname, GLint *params); void rglGetShaderiv(GLuint shader, GLenum pname, GLint *params); void rglAttachShader(GLuint program, GLuint shader); void rglShaderSource(GLuint shader, GLsizei count, const GLchar **string, const GLint *length); void rglCompileShader(GLuint shader); GLuint rglCreateProgram(void); void rglGetShaderInfoLog(GLuint shader, GLsizei maxLength, GLsizei *length, GLchar *infoLog); void rglGetProgramInfoLog(GLuint shader, GLsizei maxLength, GLsizei *length, GLchar *infoLog); GLboolean rglIsProgram(GLuint program); void rglEnableVertexAttribArray(GLuint index); void rglDisableVertexAttribArray(GLuint index); void rglVertexAttribPointer(GLuint name, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* pointer); GLint rglGetUniformLocation(GLuint program, const GLchar *name); void rglGenBuffers(GLsizei n, GLuint *buffers); void rglDisable(GLenum cap); void rglEnable(GLenum cap); void rglUseProgram(GLuint program); void rglDepthMask(GLboolean flag); void rglStencilMask(GLenum mask); void rglBufferData(GLenum target, GLsizeiptr size, const GLvoid *data, GLenum usage); void rglBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid *data); void rglBindBuffer(GLenum target, GLuint buffer); GLuint rglCreateShader(GLenum shader); void rglDeleteShader(GLuint shader); void rglUniform1f(GLint location, GLfloat v0); void rglUniform1i(GLint location, GLint v0); void rglUniform2f(GLint location, GLfloat v0, GLfloat v1); void rglUniform2i(GLint location, GLint v0, GLint v1); void rglUniform2fv(GLint location, GLsizei count, const GLfloat *value); void rglUniform3f(GLint location, GLfloat v0, GLfloat v1, GLfloat v2); void rglUniform3fv(GLint location, GLsizei count, const GLfloat *value); void rglUniform4i(GLint location, GLint v0, GLint v1, GLint v2, GLint v3); void rglUniform4f(GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); void rglUniform4fv(GLint location, GLsizei count, const GLfloat *value); void rglBlendFunc(GLenum sfactor, GLenum dfactor); void rglBlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha); void rglDepthFunc(GLenum func); void rglColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha); void rglClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); void rglViewport(GLint x, GLint y, GLsizei width, GLsizei height); void rglScissor(GLint x, GLint y, GLsizei width, GLsizei height); GLboolean rglIsEnabled(GLenum cap); void rglStencilFunc(GLenum func, GLint ref, GLuint mask); void rglCullFace(GLenum mode); void rglStencilOp(GLenum sfail, GLenum dpfail, GLenum dppass); void rglFrontFace(GLenum mode); void rglDepthRange(GLclampd zNear, GLclampd zFar); void rglClearDepth(GLdouble depth); void rglPolygonOffset(GLfloat factor, GLfloat units); void rglDrawArrays(GLenum mode, GLint first, GLsizei count); void rglVertexAttrib4f(GLuint name, GLfloat x, GLfloat y, GLfloat z, GLfloat w); void rglVertexAttrib4fv(GLuint name, GLfloat* v); void rglDeleteProgram(GLuint program); void rglDeleteBuffers(GLsizei n, const GLuint *buffers); void rglBlitFramebuffer( GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); void rglDetachShader(GLuint program, GLuint shader); void rglUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); GLint rglGetAttribLocation(GLuint program, const GLchar *name); void rglDrawBuffers(GLsizei n, const GLenum *bufs); void rglBindVertexArray(GLuint array); void rglGetActiveUniform(GLuint program, GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name); void rglUniform1ui(GLint location, GLuint v); void rglUniform2ui(GLint location, GLuint v0, GLuint v1); void rglUniform3ui(GLint location, GLuint v0, GLuint v1, GLuint v2); void rglUniform4ui(GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3); void rglBlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha); void rglCopyImageSubData( GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth); void rglVertexAttribIPointer( GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid * pointer); void rglVertexAttribLPointer( GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid * pointer); void rglUniformBlockBinding( GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding); GLenum rglGetError(void); void rglClear(GLbitfield mask); void rglPolygonMode(GLenum face, GLenum mode); void rglLineWidth(GLfloat width); void rglTexImage2DMultisample( GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations); void rglMemoryBarrier( GLbitfield barriers); void rglTexSubImage2D( GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid * pixels); void rglDeleteVertexArrays(GLsizei n, const GLuint *arrays); void *rglFenceSync(GLenum condition, GLbitfield flags); void rglWaitSync(void *sync, GLbitfield flags, uint64_t timeout); RETRO_END_DECLS #endif desmume/src/libretro-common/glsm/glsm.c000664 001750 001750 00000122667 12755534123 021335 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2016 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this libretro SDK code part (glsm). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include #include #include #include struct gl_cached_state { struct { GLuint *ids; } bind_textures; #ifndef HAVE_OPENGLES GLenum colorlogicop; #endif struct { bool enabled[MAX_ATTRIB]; } vertex_attrib_pointer; struct { GLenum pname; GLint param; } pixelstore_i; struct { GLuint r; GLuint g; GLuint b; GLuint a; } clear_color; struct { bool used; GLint x; GLint y; GLsizei w; GLsizei h; } scissor; struct { GLint x; GLint y; GLsizei w; GLsizei h; } viewport; struct { bool used; GLenum sfactor; GLenum dfactor; } blendfunc; struct { bool used; GLenum srcRGB; GLenum dstRGB; GLenum srcAlpha; GLenum dstAlpha; } blendfunc_separate; struct { bool used; GLboolean red; GLboolean green; GLboolean blue; GLboolean alpha; } colormask; struct { bool used; GLdouble depth; } cleardepth; struct { bool used; GLenum func; } depthfunc; struct { bool used; GLclampd zNear; GLclampd zFar; } depthrange; struct { bool used; GLfloat factor; GLfloat units; } polygonoffset; struct { bool used; GLenum func; GLint ref; GLuint mask; } stencilfunc; struct { bool used; GLenum sfail; GLenum dpfail; GLenum dppass; } stencilop; struct { bool used; GLenum mode; } frontface; struct { bool used; GLenum mode; } cullface; struct { bool used; GLuint mask; } stencilmask; struct { bool used; GLboolean mask; } depthmask; struct { GLenum mode; } readbuffer; GLuint vao; GLuint framebuf; GLuint program; GLenum active_texture; int cap_state[SGL_CAP_MAX]; int cap_translate[SGL_CAP_MAX]; }; static GLint glsm_max_textures; static struct retro_hw_render_callback hw_render; static struct gl_cached_state gl_state; /* GL wrapper-side */ /* * * Core in: * OpenGL : 1.0 */ GLenum rglGetError(void) { return glGetError(); } /* * * Core in: * OpenGL : 1.0 */ void rglClear(GLbitfield mask) { glClear(mask); } /* * * Core in: * OpenGL : 2.0 */ void rglValidateProgram(GLuint program) { glValidateProgram(program); } /* * * Core in: * OpenGL : 1.0 * OpenGLES : N/A */ void rglPolygonMode(GLenum face, GLenum mode) { #ifndef HAVE_OPENGLES glPolygonMode(face, mode); #endif } void rglTexSubImage2D( GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid * pixels) { glTexSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels); } /* * * Core in: * OpenGL : 1.0 */ void rglLineWidth(GLfloat width) { glLineWidth(width); } /* * Category: FBO * * Core in: * OpenGL : 3.0 * OpenGLES : 3.0 */ void rglBlitFramebuffer( GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter) { #if defined(HAVE_OPENGL) || defined(HAVE_OPENGLES) && defined(HAVE_OPENGLES3) glBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter); #endif } /* * * Core in: * OpenGLES : 3.0 */ void rglReadBuffer(GLenum mode) { #if defined(HAVE_OPENGL) || defined(HAVE_OPENGLES) && defined(HAVE_OPENGLES3) glReadBuffer(mode); gl_state.readbuffer.mode = mode; #endif } /* * * Core in: * OpenGLES : 2.0 */ void rglClearDepth(GLdouble depth) { glsm_ctl(GLSM_CTL_IMM_VBO_DRAW, NULL); #ifdef HAVE_OPENGLES glClearDepthf(depth); #else glClearDepth(depth); #endif gl_state.cleardepth.used = true; gl_state.cleardepth.depth = depth; } /* * * Core in: * OpenGLES : 2.0 */ void rglPixelStorei(GLenum pname, GLint param) { glPixelStorei(pname, param); gl_state.pixelstore_i.pname = pname; gl_state.pixelstore_i.param = param; } /* * * Core in: * OpenGLES : 2.0 */ void rglDepthRange(GLclampd zNear, GLclampd zFar) { #ifdef HAVE_OPENGLES glDepthRangef(zNear, zFar); #else glDepthRange(zNear, zFar); #endif gl_state.depthrange.used = true; gl_state.depthrange.zNear = zNear; gl_state.depthrange.zFar = zFar; } /* * * Core in: * OpenGLES : 2.0 */ void rglFrontFace(GLenum mode) { glsm_ctl(GLSM_CTL_IMM_VBO_DRAW, NULL); glFrontFace(mode); gl_state.frontface.used = true; gl_state.frontface.mode = mode; } /* * * Core in: * OpenGLES : 2.0 */ void rglDepthFunc(GLenum func) { glsm_ctl(GLSM_CTL_IMM_VBO_DRAW, NULL); gl_state.depthfunc.used = true; gl_state.depthfunc.func = func; glDepthFunc(func); } /* * * Core in: * OpenGLES : 2.0 */ void rglColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) { glsm_ctl(GLSM_CTL_IMM_VBO_DRAW, NULL); glColorMask(red, green, blue, alpha); gl_state.colormask.red = red; gl_state.colormask.green = green; gl_state.colormask.blue = blue; gl_state.colormask.alpha = alpha; gl_state.colormask.used = true; } /* * * Core in: * OpenGLES : 2.0 */ void rglCullFace(GLenum mode) { glsm_ctl(GLSM_CTL_IMM_VBO_DRAW, NULL); glCullFace(mode); gl_state.cullface.used = true; gl_state.cullface.mode = mode; } /* * * Core in: * OpenGLES : 2.0 */ void rglStencilOp(GLenum sfail, GLenum dpfail, GLenum dppass) { glStencilOp(sfail, dpfail, dppass); gl_state.stencilop.used = true; gl_state.stencilop.sfail = sfail; gl_state.stencilop.dpfail = dpfail; gl_state.stencilop.dppass = dppass; } /* * * Core in: * OpenGLES : 2.0 */ void rglStencilFunc(GLenum func, GLint ref, GLuint mask) { glStencilFunc(func, ref, mask); gl_state.stencilfunc.used = true; gl_state.stencilfunc.func = func; gl_state.stencilfunc.ref = ref; gl_state.stencilfunc.mask = mask; } /* * * Core in: * OpenGL : 1.0 */ GLboolean rglIsEnabled(GLenum cap) { return gl_state.cap_state[cap] ? GL_TRUE : GL_FALSE; } /* * * Core in: * OpenGL : 1.0 */ void rglClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) { glsm_ctl(GLSM_CTL_IMM_VBO_DRAW, NULL); glClearColor(red, green, blue, alpha); gl_state.clear_color.r = red; gl_state.clear_color.g = green; gl_state.clear_color.b = blue; gl_state.clear_color.a = alpha; } /* * * Core in: * OpenGLES : 2.0 (maybe earlier?) */ void rglScissor(GLint x, GLint y, GLsizei width, GLsizei height) { glsm_ctl(GLSM_CTL_IMM_VBO_DRAW, NULL); glScissor(x, y, width, height); gl_state.scissor.used = true; gl_state.scissor.x = x; gl_state.scissor.y = y; gl_state.scissor.w = width; gl_state.scissor.h = height; } /* * * Core in: * OpenGL : 1.0 */ void rglViewport(GLint x, GLint y, GLsizei width, GLsizei height) { glsm_ctl(GLSM_CTL_IMM_VBO_DRAW, NULL); glViewport(x, y, width, height); gl_state.viewport.x = x; gl_state.viewport.y = y; gl_state.viewport.w = width; gl_state.viewport.h = height; } void rglBlendFunc(GLenum sfactor, GLenum dfactor) { glsm_ctl(GLSM_CTL_IMM_VBO_DRAW, NULL); gl_state.blendfunc.used = true; gl_state.blendfunc.sfactor = sfactor; gl_state.blendfunc.dfactor = dfactor; glBlendFunc(sfactor, dfactor); } /* * Category: Blending * * Core in: * OpenGL : 1.4 */ void rglBlendFuncSeparate(GLenum sfactor, GLenum dfactor) { glsm_ctl(GLSM_CTL_IMM_VBO_DRAW, NULL); gl_state.blendfunc_separate.used = true; gl_state.blendfunc_separate.srcRGB = sfactor; gl_state.blendfunc_separate.dstRGB = dfactor; gl_state.blendfunc_separate.srcAlpha = sfactor; gl_state.blendfunc_separate.dstAlpha = dfactor; glBlendFunc(sfactor, dfactor); } /* * Category: Textures * * Core in: * OpenGL : 1.3 */ void rglActiveTexture(GLenum texture) { glsm_ctl(GLSM_CTL_IMM_VBO_DRAW, NULL); glActiveTexture(texture); gl_state.active_texture = texture - GL_TEXTURE0; } /* * * Core in: * OpenGL : 1.1 */ void rglBindTexture(GLenum target, GLuint texture) { glsm_ctl(GLSM_CTL_IMM_VBO_DRAW, NULL); glBindTexture(target, texture); gl_state.bind_textures.ids[gl_state.active_texture] = texture; } /* * * Core in: * OpenGL : 1.0 */ void rglDisable(GLenum cap) { glsm_ctl(GLSM_CTL_IMM_VBO_DRAW, NULL); glDisable(gl_state.cap_translate[cap]); gl_state.cap_state[cap] = 0; } /* * * Core in: * OpenGL : 1.0 */ void rglEnable(GLenum cap) { glsm_ctl(GLSM_CTL_IMM_VBO_DRAW, NULL); glEnable(gl_state.cap_translate[cap]); gl_state.cap_state[cap] = 1; } /* * Category: Shaders * * Core in: * OpenGL : 2.0 */ void rglUseProgram(GLuint program) { glsm_ctl(GLSM_CTL_IMM_VBO_DRAW, NULL); gl_state.program = program; glUseProgram(program); } /* * * Core in: * OpenGL : 1.0 */ void rglDepthMask(GLboolean flag) { glsm_ctl(GLSM_CTL_IMM_VBO_DRAW, NULL); glDepthMask(flag); gl_state.depthmask.used = true; gl_state.depthmask.mask = flag; } /* * * Core in: * OpenGL : 1.0 */ void rglStencilMask(GLenum mask) { glStencilMask(mask); gl_state.stencilmask.used = true; gl_state.stencilmask.mask = mask; } /* * * Core in: * OpenGL : 1.5 */ void rglBufferData(GLenum target, GLsizeiptr size, const GLvoid *data, GLenum usage) { glBufferData(target, size, data, usage); } /* * * Core in: * OpenGL : 1.5 */ void rglBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid *data) { glBufferSubData(target, offset, size, data); } /* * * Core in: * OpenGL : 1.5 */ void rglBindBuffer(GLenum target, GLuint buffer) { glsm_ctl(GLSM_CTL_IMM_VBO_DRAW, NULL); glBindBuffer(target, buffer); } /* * Category: Shaders * * Core in: * OpenGL : 2.0 */ void rglLinkProgram(GLuint program) { glLinkProgram(program); } /* * Category: FBO * * Core in: * OpenGL : 3.0 * OpenGLES : 2.0 */ void rglFramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) { glFramebufferTexture2D(target, attachment, textarget, texture, level); } /* * Category: FBO * * Core in: * OpenGL : 3.0 * OpenGLES : 3.2 */ void rglFramebufferTexture(GLenum target, GLenum attachment, GLuint texture, GLint level) { #if defined(HAVE_OPENGL) || defined(HAVE_OPENGLES) && defined(HAVE_OPENGLES_3_2) glFramebufferTexture(target, attachment, texture, level); #endif } /* * * Core in: * OpenGL : 1.1 */ void rglDrawArrays(GLenum mode, GLint first, GLsizei count) { glDrawArrays(mode, first, count); } /* * * Core in: * OpenGL : 1.1 */ void rglDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid * indices) { glDrawElements(mode, count, type, indices); } void rglCompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data) { glCompressedTexImage2D(target, level, internalformat, width, height, border, imageSize, data); } void rglDeleteFramebuffers(GLsizei n, const GLuint *framebuffers) { glDeleteFramebuffers(n, framebuffers); } void rglDeleteTextures(GLsizei n, const GLuint *textures) { glDeleteTextures(n, textures); } /* * * Core in: * OpenGLES : 2.0 */ void rglRenderbufferStorage(GLenum target, GLenum internalFormat, GLsizei width, GLsizei height) { glRenderbufferStorage(target, internalFormat, width, height); } /* * * Core in: * * OpenGL : 3.0 * OpenGLES : 2.0 */ void rglBindRenderbuffer(GLenum target, GLuint renderbuffer) { glBindRenderbuffer(target, renderbuffer); } /* * * Core in: * * OpenGLES : 2.0 */ void rglDeleteRenderbuffers(GLsizei n, GLuint *renderbuffers) { glDeleteRenderbuffers(n, renderbuffers); } /* * * Core in: * * OpenGL : 3.0 * OpenGLES : 2.0 */ void rglGenRenderbuffers(GLsizei n, GLuint *renderbuffers) { glGenRenderbuffers(n, renderbuffers); } /* * * Core in: * * OpenGL : 3.0 * OpenGLES : 2.0 */ void rglGenerateMipmap(GLenum target) { glGenerateMipmap(target); } /* * Category: FBO * * Core in: * OpenGL : 3.0 */ GLenum rglCheckFramebufferStatus(GLenum target) { return glCheckFramebufferStatus(target); } /* * Category: FBO * * Core in: * OpenGL : 3.0 * OpenGLES : 2.0 */ void rglFramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer) { glFramebufferRenderbuffer(target, attachment, renderbuffertarget, renderbuffer); } /* * Category: Shaders * * Core in: * OpenGL : 3.0 */ void rglBindFragDataLocation(GLuint program, GLuint colorNumber, const char * name) { #if !defined(HAVE_OPENGLES2) glBindFragDataLocation(program, colorNumber, name); #endif } /* * Category: Shaders * * Core in: * OpenGL : 2.0 */ void rglGetProgramiv(GLuint shader, GLenum pname, GLint *params) { glGetProgramiv(shader, pname, params); } /* * Category: Shaders * * Core in: * OpenGL : 4.1 * OpenGLES : 3.0 */ void rglProgramParameteri( GLuint program, GLenum pname, GLint value) { #if !defined(HAVE_OPENGLES) || defined(HAVE_OPENGLES) && (defined(HAVE_OPENGLES3) || defined(HAVE_OPENGLES_3_1)) glProgramParameteri(program, pname, value); #else printf("WARNING! Not implemented.\n"); #endif } /* * * Core in: * OpenGL : 2.0 */ void rglGetActiveUniform(GLuint program, GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) { glGetActiveUniform(program, index, bufsize, length, size, type, name); } /* * Category: UBO * * Core in: * * OpenGL : 2.0 * OpenGLES : 3.0 */ void rglGetActiveUniformBlockiv(GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint *params) { #if defined(HAVE_OPENGL) || defined(HAVE_OPENGLES) && defined(HAVE_OPENGLES3) glGetActiveUniformBlockiv(program, uniformBlockIndex, pname, params); #else printf("WARNING! Not implemented.\n"); #endif } /* * * Core in: * * OpenGLES : 3.0 */ void rglGetActiveUniformsiv( GLuint program, GLsizei uniformCount, const GLuint *uniformIndices, GLenum pname, GLint *params) { #if defined(HAVE_OPENGL) || defined(HAVE_OPENGLES) && defined(HAVE_OPENGLES3) glGetActiveUniformsiv(program, uniformCount, uniformIndices, pname, params); #else printf("WARNING! Not implemented.\n"); #endif } /* * * Core in: * * OpenGLES : 3.0 */ void rglGetUniformIndices(GLuint program, GLsizei uniformCount, const GLchar **uniformNames, GLuint *uniformIndices) { #if defined(HAVE_OPENGL) || defined(HAVE_OPENGLES) && defined(HAVE_OPENGLES3) glGetUniformIndices(program, uniformCount, uniformNames, uniformIndices); #else printf("WARNING! Not implemented.\n"); #endif } /* * Category: UBO * * Core in: * * OpenGLES : 3.0 */ void rglBindBufferBase( GLenum target, GLuint index, GLuint buffer) { #if defined(HAVE_OPENGL) || defined(HAVE_OPENGLES) && defined(HAVE_OPENGLES3) glBindBufferBase(target, index, buffer); #else printf("WARNING! Not implemented.\n"); #endif } /* * * Category: UBO * * Core in: * * OpenGLES : 3.0 */ GLuint rglGetUniformBlockIndex( GLuint program, const GLchar *uniformBlockName) { #if defined(HAVE_OPENGL) || defined(HAVE_OPENGLES) && defined(HAVE_OPENGLES3) return glGetUniformBlockIndex(program, uniformBlockName); #else printf("WARNING! Not implemented.\n"); return 0; #endif } /* * Category: UBO * * Core in: * * OpenGLES : 3.0 */ void rglUniformBlockBinding( GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding) { #if defined(HAVE_OPENGL) || defined(HAVE_OPENGLES) && defined(HAVE_OPENGLES3) glUniformBlockBinding(program, uniformBlockIndex, uniformBlockBinding); #else printf("WARNING! Not implemented.\n"); #endif } /* * * Core in: * OpenGL : 2.0 * OpenGLES : 3.0 */ void rglUniform1ui(GLint location, GLuint v) { #if defined(HAVE_OPENGL) || defined(HAVE_OPENGLES) && defined(HAVE_OPENGLES3) glUniform1ui(location ,v); #endif } /* * * Core in: * OpenGL : 2.0 * OpenGLES : 3.0 */ void rglUniform2ui(GLint location, GLuint v0, GLuint v1) { #if defined(HAVE_OPENGL) || defined(HAVE_OPENGLES) && defined(HAVE_OPENGLES3) glUniform2ui(location, v0, v1); #endif } /* * * Core in: * OpenGL : 2.0 * OpenGLES : 3.0 */ void rglUniform3ui(GLint location, GLuint v0, GLuint v1, GLuint v2) { #if defined(HAVE_OPENGL) || defined(HAVE_OPENGLES) && defined(HAVE_OPENGLES3) glUniform3ui(location, v0, v1, v2); #endif } /* * * Core in: * OpenGL : 2.0 * OpenGLES : 3.0 */ void rglUniform4ui(GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3) { #if defined(HAVE_OPENGL) || defined(HAVE_OPENGLES) && defined(HAVE_OPENGLES3) glUniform4ui(location, v0, v1, v2, v3); #endif } /* * * Core in: * OpenGL : 2.0 */ void rglUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) { glUniformMatrix4fv(location, count, transpose, value); } /* * Category: Shaders * * Core in: * OpenGL : 2.0 */ void rglDetachShader(GLuint program, GLuint shader) { glDetachShader(program, shader); } /* * Category: Shaders * * Core in: * OpenGL : 2.0 */ void rglGetShaderiv(GLuint shader, GLenum pname, GLint *params) { glGetShaderiv(shader, pname, params); } /* * Category: Shaders * * Core in: * OpenGL : 2.0 */ void rglAttachShader(GLuint program, GLuint shader) { glAttachShader(program, shader); } /* * * Core in: * OpenGL : 2.0 */ GLint rglGetAttribLocation(GLuint program, const GLchar *name) { return glGetAttribLocation(program, name); } /* * Category: Shaders * * Core in: * OpenGL : 2.0 */ void rglShaderSource(GLuint shader, GLsizei count, const GLchar **string, const GLint *length) { return glShaderSource(shader, count, string, length); } /* * Category: Shaders * * Core in: * OpenGL : 2.0 */ void rglCompileShader(GLuint shader) { glCompileShader(shader); } /* * Category: Shaders * * Core in: * OpenGL : 2.0 */ GLuint rglCreateProgram(void) { return glCreateProgram(); } /* * * Core in: * OpenGL : 1.1 */ void rglGenTextures(GLsizei n, GLuint *textures) { glGenTextures(n, textures); } /* * * Core in: * OpenGL : 2.0 */ void rglGetShaderInfoLog(GLuint shader, GLsizei maxLength, GLsizei *length, GLchar *infoLog) { glGetShaderInfoLog(shader, maxLength, length, infoLog); } /* * * Core in: * OpenGL : 2.0 */ void rglGetProgramInfoLog(GLuint shader, GLsizei maxLength, GLsizei *length, GLchar *infoLog) { glGetProgramInfoLog(shader, maxLength, length, infoLog); } /* * * Core in: * OpenGL : 2.0 */ GLboolean rglIsProgram(GLuint program) { return glIsProgram(program); } void rglTexCoord2f(GLfloat s, GLfloat t) { #ifdef HAVE_LEGACY_GL glTexCoord2f(s, t); #endif } /* * Category: Generic vertex attributes * * Core in: * OpenGL : 2.0 * */ void rglDisableVertexAttribArray(GLuint index) { gl_state.vertex_attrib_pointer.enabled[index] = 0; glDisableVertexAttribArray(index); } /* * Category: Generic vertex attributes * * Core in: * OpenGL : 2.0 */ void rglEnableVertexAttribArray(GLuint index) { glsm_ctl(GLSM_CTL_IMM_VBO_DRAW, NULL); gl_state.vertex_attrib_pointer.enabled[index] = 1; glEnableVertexAttribArray(index); } /* * Category: Shaders * * Core in: * OpenGL : 2.0 */ void rglVertexAttribIPointer( GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid * pointer) { #if defined(HAVE_OPENGL) || defined(HAVE_OPENGLES) && defined(HAVE_OPENGLES3) glVertexAttribIPointer(index, size, type, stride, pointer); #endif } void rglVertexAttribLPointer( GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid * pointer) { #if defined(HAVE_OPENGL) glVertexAttribLPointer(index, size, type, stride, pointer); #endif } /* * Category: Generic vertex attributes * * Core in: * OpenGL : 2.0 */ void rglVertexAttribPointer(GLuint name, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* pointer) { glVertexAttribPointer(name, size, type, normalized, stride, pointer); } /* * Category: Generic vertex attributes * * Core in: * OpenGL : 2.0 */ void rglBindAttribLocation(GLuint program, GLuint index, const GLchar *name) { glBindAttribLocation(program, index, name); } /* * * Core in: * OpenGL : 2.0 */ void rglVertexAttrib4f(GLuint name, GLfloat x, GLfloat y, GLfloat z, GLfloat w) { glVertexAttrib4f(name, x, y, z, w); } /* * * Core in: * OpenGL : 2.0 */ void rglVertexAttrib4fv(GLuint name, GLfloat* v) { glVertexAttrib4fv(name, v); } /* * Category: Shaders * * Core in: * OpenGL : 2.0 */ GLuint rglCreateShader(GLenum shaderType) { return glCreateShader(shaderType); } /* * Category: Shaders * * Core in: * OpenGL : 2.0 */ void rglDeleteProgram(GLuint program) { glDeleteProgram(program); } /* * Category: Shaders * * Core in: * OpenGL : 2.0 */ void rglDeleteShader(GLuint shader) { glDeleteShader(shader); } /* * Category: Shaders * * Core in: * OpenGL : 2.0 */ GLint rglGetUniformLocation(GLuint program, const GLchar *name) { return glGetUniformLocation(program, name); } /* * Category: VBO and PBO * * Core in: * OpenGL : 1.5 */ void rglDeleteBuffers(GLsizei n, const GLuint *buffers) { glDeleteBuffers(n, buffers); } /* * Category: VBO and PBO * * Core in: * OpenGL : 1.5 */ void rglGenBuffers(GLsizei n, GLuint *buffers) { glGenBuffers(n, buffers); } /* * Category: Shaders * * Core in: * OpenGL : 2.0 */ void rglUniform1f(GLint location, GLfloat v0) { glUniform1f(location, v0); } /* * Category: Shaders * * Core in: * OpenGL : 2.0 */ void rglUniform1fv(GLint location, GLsizei count, const GLfloat *value) { glUniform1fv(location, count, value); } /* * Category: Shaders * * Core in: * OpenGL : 2.0 */ void rglUniform1iv(GLint location, GLsizei count, const GLint *value) { glUniform1iv(location, count, value); } void rglClearBufferfv( GLenum buffer, GLint drawBuffer, const GLfloat * value) { #if defined(HAVE_OPENGL) || defined(HAVE_OPENGLES) && defined(HAVE_OPENGLES_3) glClearBufferfv(buffer, drawBuffer, value); #endif } void rglTexBuffer(GLenum target, GLenum internalFormat, GLuint buffer) { #if defined(HAVE_OPENGL) || defined(HAVE_OPENGLES) && defined(HAVE_OPENGLES_3_2) glTexBuffer(target, internalFormat, buffer); #endif } /* * * Core in: * OpenGL : 2.0 * OpenGLES : 3.0 */ const GLubyte* rglGetStringi(GLenum name, GLuint index) { #if defined(HAVE_OPENGL) || defined(HAVE_OPENGLES) && defined(HAVE_OPENGLES_3) return glGetStringi(name, index); #else return NULL; #endif } void rglClearBufferfi( GLenum buffer, GLint drawBuffer, GLfloat depth, GLint stencil) { #if defined(HAVE_OPENGL) || defined(HAVE_OPENGLES) && defined(HAVE_OPENGLES_3) glClearBufferfi(buffer, drawBuffer, depth, stencil); #endif } /* * * Core in: * OpenGL : 3.0 * OpenGLES : 3.0 */ void rglRenderbufferStorageMultisample( GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height) { #if defined(HAVE_OPENGL) || defined(HAVE_OPENGLES) && defined(HAVE_OPENGLES_3) glRenderbufferStorageMultisample(target, samples, internalformat, width, height); #endif } /* * Category: Shaders * * Core in: * OpenGL : 2.0 */ void rglUniform1i(GLint location, GLint v0) { glUniform1i(location, v0); } /* * Category: Shaders * * Core in: * OpenGL : 2.0 */ void rglUniform2f(GLint location, GLfloat v0, GLfloat v1) { glUniform2f(location, v0, v1); } /* * Category: Shaders * * Core in: * OpenGL : 2.0 */ void rglUniform2i(GLint location, GLint v0, GLint v1) { glUniform2i(location, v0, v1); } /* * Category: Shaders * * Core in: * OpenGL : 2.0 */ void rglUniform2fv(GLint location, GLsizei count, const GLfloat *value) { glUniform2fv(location, count, value); } /* * Category: Shaders * * Core in: * OpenGL : 2.0 */ void rglUniform3f(GLint location, GLfloat v0, GLfloat v1, GLfloat v2) { glUniform3f(location, v0, v1, v2); } /* * Category: Shaders * * Core in: * OpenGL : 2.0 */ void rglUniform3fv(GLint location, GLsizei count, const GLfloat *value) { glUniform3fv(location, count, value); } /* * Category: Shaders * * Core in: * OpenGL : 2.0 */ void rglUniform4i(GLint location, GLint v0, GLint v1, GLint v2, GLint v3) { glUniform4i(location, v0, v1, v2, v3); } /* * Category: Shaders * * Core in: * OpenGL : 2.0 */ void rglUniform4f(GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) { glUniform4f(location, v0, v1, v2, v3); } /* * Category: Shaders * * Core in: * OpenGL : 2.0 */ void rglUniform4fv(GLint location, GLsizei count, const GLfloat *value) { glUniform4fv(location, count, value); } /* * * Core in: * OpenGL : 1.0 */ void rglPolygonOffset(GLfloat factor, GLfloat units) { glsm_ctl(GLSM_CTL_IMM_VBO_DRAW, NULL); glPolygonOffset(factor, units); gl_state.polygonoffset.used = true; gl_state.polygonoffset.factor = factor; gl_state.polygonoffset.units = units; } /* * Category: FBO * * Core in: * OpenGL : 3.0 */ void rglGenFramebuffers(GLsizei n, GLuint *ids) { glGenFramebuffers(n, ids); } /* * Category: FBO * * Core in: * OpenGL : 3.0 */ void rglBindFramebuffer(GLenum target, GLuint framebuffer) { glsm_ctl(GLSM_CTL_IMM_VBO_DRAW, NULL); glBindFramebuffer(target, framebuffer); gl_state.framebuf = framebuffer; } /* * Category: FBO * * Core in: * OpenGL : 2.0 * OpenGLES : 3.0 */ void rglDrawBuffers(GLsizei n, const GLenum *bufs) { #if defined(HAVE_OPENGL) || defined(HAVE_OPENGLES) && defined(HAVE_OPENGLES3) glDrawBuffers(n, bufs); #endif } /* * Category: FBO * * Core in: * OpenGL : 2.0 * OpenGLES : 3.0 */ void *rglMapBufferRange( GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access) { #if defined(HAVE_OPENGL) || defined(HAVE_OPENGLES) && defined(HAVE_OPENGLES3) return glMapBufferRange(target, offset, length, access); #else printf("WARNING! Not implemented.\n"); return NULL; #endif } /* * * Core in: * OpenGL : 4.3 * OpenGLES : 3.1 */ void rglTexStorage2DMultisample(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations) { #if defined(HAVE_OPENGLES) && defined(HAVE_OPENGLES_3_1) glTexStorage2DMultisample(target, samples, internalformat, width, height, fixedsamplelocations); #endif } /* * * Core in: * OpenGLES : 3.0 */ void rglTexStorage2D(GLenum target, GLsizei levels, GLenum internalFormat, GLsizei width, GLsizei height) { #if defined(HAVE_OPENGL) || defined(HAVE_OPENGLES) && defined(HAVE_OPENGLES3) glTexStorage2D(target, levels, internalFormat, width, height); #endif } /* * * Core in: * OpenGL : 4.2 * OpenGLES : 3.1 */ void rglMemoryBarrier( GLbitfield barriers) { #if !defined(HAVE_OPENGLES) || defined(HAVE_OPENGLES3) && defined(HAVE_OPENGLES_3_1) glMemoryBarrier(barriers); #else printf("WARNING! Not implemented.\n"); #endif } /* * * Core in: * OpenGL : 4.2 * OpenGLES : 3.1 */ void rglBindImageTexture( GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLenum format) { #if !defined(HAVE_OPENGLES) || defined(HAVE_OPENGLES3) && defined(HAVE_OPENGLES_3_1) glBindImageTexture(unit, texture, level, layered, layer, access, format); #else printf("WARNING! Not implemented.\n"); #endif } /* * * Core in: * OpenGL : 4.1 * OpenGLES : 3.1 */ void rglGetProgramBinary( GLuint program, GLsizei bufsize, GLsizei *length, GLenum *binaryFormat, void *binary) { #if !defined(HAVE_OPENGLES) || defined(HAVE_OPENGLES) && defined(HAVE_OPENGLES3) glGetProgramBinary(program, bufsize, length, binaryFormat, binary); #else printf("WARNING! Not implemented.\n"); #endif } /* * * Core in: * OpenGL : 4.1 * OpenGLES : 3.1 */ void rglProgramBinary(GLuint program, GLenum binaryFormat, const void *binary, GLsizei length) { #if !defined(HAVE_OPENGLES) || defined(HAVE_OPENGLES) && defined(HAVE_OPENGLES_3_1) glProgramBinary(program, binaryFormat, binary, length); #else printf("WARNING! Not implemented.\n"); #endif } void rglTexImage2DMultisample( GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations) { #ifndef HAVE_OPENGLES glTexImage2DMultisample(target, samples, internalformat, width, height, fixedsamplelocations); #endif } /* * * Core in: * OpenGL : 1.5 */ void * rglMapBuffer( GLenum target, GLenum access) { #if defined(HAVE_OPENGLES) return glMapBufferOES(target, access); #else return glMapBuffer(target, access); #endif } /* * * Core in: * OpenGL : 1.5 */ GLboolean rglUnmapBuffer( GLenum target) { #if defined(HAVE_OPENGLES) return glUnmapBufferOES(target); #else return glUnmapBuffer(target); #endif } void rglBlendEquation(GLenum mode) { glBlendEquation(mode); } void rglBlendColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) { glBlendColor(red, green, blue, alpha); } /* * Category: Blending * * Core in: * OpenGL : 2.0 */ void rglBlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha) { glBlendEquationSeparate(modeRGB, modeAlpha); } /* * * Core in: * OpenGL : 2.0 * OpenGLES : 3.2 */ void rglCopyImageSubData( GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth) { #if defined(HAVE_OPENGL) || defined(HAVE_OPENGLES) && defined(HAVE_OPENGLES_3_2) glCopyImageSubData(srcName, srcTarget, srcLevel, srcX, srcY, srcZ, dstName, dstTarget, dstLevel, dstX, dstY, dstZ, srcWidth, srcHeight, srcDepth); #endif } /* * Category: VAO * * Core in: * OpenGL : 3.0 * OpenGLES : 3.0 */ void rglBindVertexArray(GLuint array) { #if defined(HAVE_OPENGL) || defined(HAVE_OPENGLES) && defined(HAVE_OPENGLES3) glBindVertexArray(array); #endif } /* * Category: VAO * * Core in: * OpenGL : 3.0 * OpenGLES : 3.0 */ void rglGenVertexArrays(GLsizei n, GLuint *arrays) { #if defined(HAVE_OPENGL) || defined(HAVE_OPENGLES) && defined(HAVE_OPENGLES3) glGenVertexArrays(n, arrays); #endif } /* * Category: VAO * * Core in: * OpenGL : 3.0 * OpenGLES : 3.0 */ void rglDeleteVertexArrays(GLsizei n, const GLuint *arrays) { #if defined(HAVE_OPENGL) || defined(HAVE_OPENGLES) && defined(HAVE_OPENGLES3) glDeleteVertexArrays(n, arrays); #endif } /* * * Core in: * OpenGL : 3.2 * OpenGLES : 3.0 */ void *rglFenceSync(GLenum condition, GLbitfield flags) { #if defined(HAVE_OPENGL) || defined(HAVE_OPENGLES) && defined(HAVE_OPENGLES3) return (GLsync)glFenceSync(condition, flags); #endif } /* * * Core in: * OpenGL : 3.2 * OpenGLES : 3.0 */ void rglWaitSync(void *sync, GLbitfield flags, uint64_t timeout) { #if defined(HAVE_OPENGL) || defined(HAVE_OPENGLES) && defined(HAVE_OPENGLES3) glWaitSync((GLsync)sync, flags, (GLuint64)timeout); #endif } /* GLSM-side */ static void glsm_state_setup(void) { unsigned i; gl_state.cap_translate[SGL_DEPTH_TEST] = GL_DEPTH_TEST; gl_state.cap_translate[SGL_BLEND] = GL_BLEND; gl_state.cap_translate[SGL_POLYGON_OFFSET_FILL] = GL_POLYGON_OFFSET_FILL; gl_state.cap_translate[SGL_FOG] = GL_FOG; gl_state.cap_translate[SGL_CULL_FACE] = GL_CULL_FACE; gl_state.cap_translate[SGL_ALPHA_TEST] = GL_ALPHA_TEST; gl_state.cap_translate[SGL_SCISSOR_TEST] = GL_SCISSOR_TEST; gl_state.cap_translate[SGL_STENCIL_TEST] = GL_STENCIL_TEST; #ifndef HAVE_OPENGLES gl_state.cap_translate[SGL_COLOR_LOGIC_OP] = GL_COLOR_LOGIC_OP; gl_state.cap_translate[SGL_CLIP_DISTANCE0] = GL_CLIP_DISTANCE0; gl_state.cap_translate[SGL_DEPTH_CLAMP] = GL_DEPTH_CLAMP; #endif for (i = 0; i < MAX_ATTRIB; i++) gl_state.vertex_attrib_pointer.enabled[i] = 0; glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &glsm_max_textures); gl_state.bind_textures.ids = (GLuint*)calloc(glsm_max_textures, sizeof(GLuint)); gl_state.framebuf = hw_render.get_current_framebuffer(); gl_state.cullface.mode = GL_BACK; gl_state.frontface.mode = GL_CCW; gl_state.blendfunc_separate.used = false; gl_state.blendfunc_separate.srcRGB = GL_ONE; gl_state.blendfunc_separate.dstRGB = GL_ZERO; gl_state.blendfunc_separate.srcAlpha = GL_ONE; gl_state.blendfunc_separate.dstAlpha = GL_ZERO; gl_state.depthfunc.used = false; gl_state.colormask.used = false; gl_state.colormask.red = GL_TRUE; gl_state.colormask.green = GL_TRUE; gl_state.colormask.blue = GL_TRUE; gl_state.colormask.alpha = GL_TRUE; gl_state.polygonoffset.used = false; gl_state.depthfunc.func = GL_LESS; #ifndef HAVE_OPENGLES gl_state.colorlogicop = GL_COPY; #endif #ifdef CORE glGenVertexArrays(1, &gl_state.vao); #endif } static void glsm_state_bind(void) { unsigned i; for (i = 0; i < MAX_ATTRIB; i++) { if (gl_state.vertex_attrib_pointer.enabled[i]) glEnableVertexAttribArray(i); else glDisableVertexAttribArray(i); } glBindFramebuffer(RARCH_GL_FRAMEBUFFER, hw_render.get_current_framebuffer()); if (gl_state.blendfunc.used) glBlendFunc( gl_state.blendfunc.sfactor, gl_state.blendfunc.dfactor); if (gl_state.blendfunc_separate.used) glBlendFuncSeparate( gl_state.blendfunc_separate.srcRGB, gl_state.blendfunc_separate.dstRGB, gl_state.blendfunc_separate.srcAlpha, gl_state.blendfunc_separate.dstAlpha ); glClearColor( gl_state.clear_color.r, gl_state.clear_color.g, gl_state.clear_color.b, gl_state.clear_color.a); if (gl_state.depthfunc.used) glDepthFunc(gl_state.depthfunc.func); if (gl_state.colormask.used) glColorMask( gl_state.colormask.red, gl_state.colormask.green, gl_state.colormask.blue, gl_state.colormask.alpha); if (gl_state.cullface.used) glCullFace(gl_state.cullface.mode); if (gl_state.depthmask.used) glDepthMask(gl_state.depthmask.mask); if (gl_state.polygonoffset.used) glPolygonOffset( gl_state.polygonoffset.factor, gl_state.polygonoffset.units); if (gl_state.scissor.used) glScissor( gl_state.scissor.x, gl_state.scissor.y, gl_state.scissor.w, gl_state.scissor.h); glUseProgram(gl_state.program); glViewport( gl_state.viewport.x, gl_state.viewport.y, gl_state.viewport.w, gl_state.viewport.h); #ifdef CORE glBindVertexArray(gl_state.vao); #endif for(i = 0; i < SGL_CAP_MAX; i ++) { if (gl_state.cap_state[i]) glEnable(gl_state.cap_translate[i]); } if (gl_state.frontface.used) glFrontFace(gl_state.frontface.mode); if (gl_state.stencilmask.used) glStencilMask(gl_state.stencilmask.mask); if (gl_state.stencilop.used) glStencilOp(gl_state.stencilop.sfail, gl_state.stencilop.dpfail, gl_state.stencilop.dppass); if (gl_state.stencilfunc.used) glStencilFunc( gl_state.stencilfunc.func, gl_state.stencilfunc.ref, gl_state.stencilfunc.mask); for (i = 0; i < glsm_max_textures; i ++) { glActiveTexture(GL_TEXTURE0 + i); glBindTexture(GL_TEXTURE_2D, gl_state.bind_textures.ids[i]); } glActiveTexture(GL_TEXTURE0 + gl_state.active_texture); glBindBuffer(GL_ARRAY_BUFFER, 0); } static void glsm_state_unbind(void) { unsigned i; #ifdef CORE glBindVertexArray(0); #endif for (i = 0; i < SGL_CAP_MAX; i ++) { if (gl_state.cap_state[i]) glDisable(gl_state.cap_translate[i]); } glBlendFunc(GL_ONE, GL_ZERO); if (gl_state.colormask.used) glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); if (gl_state.blendfunc_separate.used) glBlendFuncSeparate(GL_ONE, GL_ZERO, GL_ONE, GL_ZERO); if (gl_state.cullface.used) glCullFace(GL_BACK); if (gl_state.depthmask.used) glDepthMask(GL_TRUE); if (gl_state.polygonoffset.used) glPolygonOffset(0, 0); glUseProgram(0); glClearColor(0,0,0,0.0f); if (gl_state.depthrange.used) rglDepthRange(0, 1); glStencilMask(1); glFrontFace(GL_CCW); if (gl_state.depthfunc.used) glDepthFunc(GL_LESS); if (gl_state.stencilop.used) glStencilOp(GL_KEEP,GL_KEEP, GL_KEEP); if (gl_state.stencilfunc.used) glStencilFunc(GL_ALWAYS,0,1); /* Clear textures */ for (i = 0; i < glsm_max_textures; i ++) { glActiveTexture(GL_TEXTURE0 + i); glBindTexture(GL_TEXTURE_2D, 0); } glActiveTexture(GL_TEXTURE0); for (i = 0; i < MAX_ATTRIB; i ++) glDisableVertexAttribArray(i); glBindFramebuffer(RARCH_GL_FRAMEBUFFER, 0); } static bool glsm_state_ctx_destroy(void *data) { if (gl_state.bind_textures.ids) free(gl_state.bind_textures.ids); gl_state.bind_textures.ids = NULL; } static bool glsm_state_ctx_init(void *data) { glsm_ctx_params_t *params = (glsm_ctx_params_t*)data; if (!params || !params->environ_cb) return false; #ifdef HAVE_OPENGLES #if defined(HAVE_OPENGLES_3_1) hw_render.context_type = RETRO_HW_CONTEXT_OPENGLES_VERSION; hw_render.version_major = 3; hw_render.version_minor = 1; #elif defined(HAVE_OPENGLES3) hw_render.context_type = RETRO_HW_CONTEXT_OPENGLES3; #else hw_render.context_type = RETRO_HW_CONTEXT_OPENGLES2; #endif #else #ifdef CORE hw_render.context_type = RETRO_HW_CONTEXT_OPENGL_CORE; hw_render.version_major = 3; hw_render.version_minor = 1; #else hw_render.context_type = RETRO_HW_CONTEXT_OPENGL; #endif #endif hw_render.context_reset = params->context_reset; hw_render.context_destroy = params->context_destroy; hw_render.stencil = params->stencil; hw_render.depth = true; hw_render.bottom_left_origin = true; hw_render.cache_context = true; if (!params->environ_cb(RETRO_ENVIRONMENT_SET_HW_RENDER, &hw_render)) return false; return true; } GLuint glsm_get_current_framebuffer(void) { return hw_render.get_current_framebuffer(); } bool glsm_ctl(enum glsm_state_ctl state, void *data) { switch (state) { case GLSM_CTL_IMM_VBO_DRAW: return false; case GLSM_CTL_IMM_VBO_DISABLE: return false; case GLSM_CTL_IS_IMM_VBO: return false; case GLSM_CTL_SET_IMM_VBO: break; case GLSM_CTL_UNSET_IMM_VBO: break; case GLSM_CTL_PROC_ADDRESS_GET: { glsm_ctx_proc_address_t *proc = (glsm_ctx_proc_address_t*)data; if (!hw_render.get_proc_address) return false; proc->addr = hw_render.get_proc_address; } break; case GLSM_CTL_STATE_CONTEXT_RESET: rglgen_resolve_symbols(hw_render.get_proc_address); break; case GLSM_CTL_STATE_CONTEXT_DESTROY: glsm_state_ctx_destroy(data); break; case GLSM_CTL_STATE_CONTEXT_INIT: return glsm_state_ctx_init(data); case GLSM_CTL_STATE_SETUP: glsm_state_setup(); break; case GLSM_CTL_STATE_UNBIND: glsm_state_unbind(); break; case GLSM_CTL_STATE_BIND: glsm_state_bind(); break; case GLSM_CTL_NONE: default: break; } return true; } desmume/src/addons/slot1comp_mc.cpp000664 001750 001750 00000002545 12755534123 020521 0ustar00sergiosergio000000 000000 /* Copyright (C) 2013-2015 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the this software. If not, see . */ //this file contains the components used for emulating standard gamecard "MC" devices (eeprom, fram, flash) //this is largely done by accessing the BackupDevice resources in the core emulator #include "slot1comp_mc.h" #include "../MMU.h" #include "../NDSSystem.h" Slot1Comp_MC g_Slot1Comp_MC; u8 Slot1Comp_MC::auxspi_transaction(int PROCNUM, u8 value) { return MMU_new.backupDevice.data_command(value, PROCNUM); } void Slot1Comp_MC::auxspi_reset(int PROCNUM) { MMU_new.backupDevice.reset_command(); } void Slot1Comp_MC::connect() { if(!memcmp(gameInfo.header.gameCode,"AXBJ", 4)) MMU_new.backupDevice.uninitializedValue = 0x00; // Daigassou! Band Brothers DX (JP) }desmume/src/libretro-common/file/nbio/nbio_stdio.c000664 001750 001750 00000010003 12755534123 023404 0ustar00sergiosergio000000 000000 #include #include #include struct nbio_t { FILE* f; void* data; size_t progress; size_t len; /* * possible values: * NBIO_READ, NBIO_WRITE - obvious * -1 - currently doing nothing * -2 - the pointer was reallocated since the last operation */ signed char op; signed char mode; }; static const char * modes[]={ "rb", "wb", "r+b", "rb", "wb", "r+b" }; struct nbio_t* nbio_open(const char * filename, unsigned mode) { struct nbio_t* handle = NULL; FILE* f = fopen(filename, modes[mode]); if (!f) return NULL; handle = (struct nbio_t*)malloc(sizeof(struct nbio_t)); if (!handle) goto error; handle->f = f; handle->len = 0; switch (mode) { case NBIO_WRITE: case BIO_WRITE: break; default: fseek(handle->f, 0, SEEK_END); handle->len = ftell(handle->f); break; } handle->mode = mode; handle->data = malloc(handle->len); if (handle->len && !handle->data) goto error; handle->progress = handle->len; handle->op = -2; return handle; error: if (handle) { if (handle->data) free(handle->data); handle->data = NULL; free(handle); } handle = NULL; fclose(f); return NULL; } void nbio_begin_read(struct nbio_t* handle) { if (!handle) return; if (handle->op >= 0) { puts("ERROR - attempted file read operation while busy"); abort(); } fseek(handle->f, 0, SEEK_SET); handle->op = NBIO_READ; handle->progress = 0; } void nbio_begin_write(struct nbio_t* handle) { if (!handle) return; if (handle->op >= 0) { puts("ERROR - attempted file write operation while busy"); abort(); } fseek(handle->f, 0, SEEK_SET); handle->op = NBIO_WRITE; handle->progress = 0; } bool nbio_iterate(struct nbio_t* handle) { size_t amount = 65536; if (!handle) return false; if (amount > handle->len - handle->progress) amount = handle->len - handle->progress; switch (handle->op) { case NBIO_READ: if (handle->mode == BIO_READ) { amount = handle->len; fread((char*)handle->data, 1, amount, handle->f); } else fread((char*)handle->data + handle->progress, 1, amount, handle->f); break; case NBIO_WRITE: if (handle->mode == BIO_WRITE) { size_t written = 0; amount = handle->len; written = fwrite((char*)handle->data, 1, amount, handle->f); if (written != amount) return false; } else fwrite((char*)handle->data + handle->progress, 1, amount, handle->f); break; } handle->progress += amount; if (handle->progress == handle->len) handle->op = -1; return (handle->op < 0); } void nbio_resize(struct nbio_t* handle, size_t len) { if (!handle) return; if (handle->op >= 0) { puts("ERROR - attempted file resize operation while busy"); abort(); } if (len < handle->len) { puts("ERROR - attempted file shrink operation, not implemented"); abort(); } handle->len = len; handle->data = realloc(handle->data, handle->len); handle->op = -1; handle->progress = handle->len; } void* nbio_get_ptr(struct nbio_t* handle, size_t* len) { if (!handle) return NULL; if (len) *len = handle->len; if (handle->op == -1) return handle->data; return NULL; } void nbio_cancel(struct nbio_t* handle) { if (!handle) return; handle->op = -1; handle->progress = handle->len; } void nbio_free(struct nbio_t* handle) { if (!handle) return; if (handle->op >= 0) { puts("ERROR - attempted free() while busy"); abort(); } fclose(handle->f); free(handle->data); handle->f = NULL; handle->data = NULL; free(handle); } desmume/src/libretro-common/include/algorithms/mismatch.h000664 001750 001750 00000003302 12755534123 025017 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2016 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (mismatch.h). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef __LIBRETRO_SDK_ALGORITHMS_MISMATCH_H__ #define __LIBRETRO_SDK_ALGORITHMS_MISMATCH_H__ #include #include #include #include RETRO_BEGIN_DECLS size_t find_change(const uint16_t *a, const uint16_t *b); size_t find_same(const uint16_t *a, const uint16_t *b); RETRO_END_DECLS #endif desmume/src/libretro-common/include/conversion/s16_to_float.h000664 001750 001750 00000007724 12755534123 025542 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2016 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (s16_to_float.h). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef __LIBRETRO_SDK_CONVERSION_S16_TO_FLOAT_H__ #define __LIBRETRO_SDK_CONVERSION_S16_TO_FLOAT_H__ #include #include #include RETRO_BEGIN_DECLS #if defined(__SSE2__) #define convert_s16_to_float convert_s16_to_float_SSE2 /** * convert_s16_to_float_SSE2: * @out : output buffer * @in : input buffer * @samples : size of samples to be converted * @gain : gain applied (.e.g. audio volume) * * Converts from signed integer 16-bit * to floating point. * * SSE2 implementation callback function. **/ void convert_s16_to_float_SSE2(float *out, const int16_t *in, size_t samples, float gain); #elif defined(__ALTIVEC__) #define convert_s16_to_float convert_s16_to_float_altivec /** * convert_s16_to_float_altivec: * @out : output buffer * @in : input buffer * @samples : size of samples to be converted * @gain : gain applied (.e.g. audio volume) * * Converts from signed integer 16-bit * to floating point. * * AltiVec implementation callback function. **/ void convert_s16_to_float_altivec(float *out, const int16_t *in, size_t samples, float gain); #elif defined(__ARM_NEON__) && !defined(VITA) #define convert_s16_to_float convert_s16_to_float_arm void (*convert_s16_to_float_arm)(float *out, const int16_t *in, size_t samples, float gain); #elif defined(_MIPS_ARCH_ALLEGREX) #define convert_s16_to_float convert_s16_to_float_ALLEGREX /** * convert_s16_to_float_ALLEGREX: * @out : output buffer * @in : input buffer * @samples : size of samples to be converted * @gain : gain applied (.e.g. audio volume) * * Converts from signed integer 16-bit * to floating point. * * MIPS ALLEGREX implementation callback function. **/ void convert_s16_to_float_ALLEGREX(float *out, const int16_t *in, size_t samples, float gain); #else #define convert_s16_to_float convert_s16_to_float_C #endif /** * convert_s16_to_float_C: * @out : output buffer * @in : input buffer * @samples : size of samples to be converted * @gain : gain applied (.e.g. audio volume) * * Converts from signed integer 16-bit * to floating point. * * C implementation callback function. **/ void convert_s16_to_float_C(float *out, const int16_t *in, size_t samples, float gain); /** * convert_s16_to_float_init_simd: * * Sets up function pointers for conversion * functions based on CPU features. **/ void convert_s16_to_float_init_simd(void); RETRO_END_DECLS #endif desmume/src/utils/AsmJit/core/logger.cpp000664 001750 001750 00000011742 12755534123 021406 0ustar00sergiosergio000000 000000 // [AsmJit] // Complete JIT Assembler for C++ Language. // // [License] // Zlib - See COPYING file in this package. #define ASMJIT_EXPORTS // [Dependencies - AsmJit] #include "../core/logger.h" // [Dependencies - C] #include // [Api-Begin] #include "../core/apibegin.h" namespace AsmJit { // ============================================================================ // [AsmJit::Logger - Construction / Destruction] // ============================================================================ Logger::Logger() : _flags(kLoggerIsEnabled | kLoggerIsUsed) { memset(_instructionPrefix, 0, ASMJIT_ARRAY_SIZE(_instructionPrefix)); } Logger::~Logger() { } // ============================================================================ // [AsmJit::Logger - Logging] // ============================================================================ void Logger::logFormat(const char* fmt, ...) { char buf[1024]; size_t len; va_list ap; va_start(ap, fmt); len = vsnprintf(buf, 1023, fmt, ap); va_end(ap); logString(buf, len); } // ============================================================================ // [AsmJit::Logger - Enabled] // ============================================================================ void Logger::setEnabled(bool enabled) { if (enabled) _flags |= kLoggerIsEnabled | kLoggerIsUsed; else _flags &= ~(kLoggerIsEnabled | kLoggerIsUsed); } // ============================================================================ // [AsmJit::Logger - LogBinary] // ============================================================================ void Logger::setLogBinary(bool value) { if (value) _flags |= kLoggerOutputBinary; else _flags &= ~kLoggerOutputBinary; } // ============================================================================ // [AsmJit::Logger - HexImmediate] // ============================================================================ void Logger::setHexImmediate(bool value) { if (value) _flags |= kLoggerOutputHexImmediate; else _flags &= ~kLoggerOutputHexImmediate; } // ============================================================================ // [AsmJit::Logger - HexDisplacement] // ============================================================================ void Logger::setHexDisplacement(bool value) { if (value) _flags |= kLoggerOutputHexDisplacement; else _flags &= ~kLoggerOutputHexDisplacement; } // ============================================================================ // [AsmJit::Logger - InstructionPrefix] // ============================================================================ void Logger::setInstructionPrefix(const char* prefix) { memset(_instructionPrefix, 0, ASMJIT_ARRAY_SIZE(_instructionPrefix)); if (!prefix) return; size_t length = strnlen(prefix, ASMJIT_ARRAY_SIZE(_instructionPrefix) - 1); memcpy(_instructionPrefix, prefix, length); } // ============================================================================ // [AsmJit::FileLogger - Construction / Destruction] // ============================================================================ FileLogger::FileLogger(FILE* stream) : _stream(NULL) { setStream(stream); } FileLogger::~FileLogger() { } // ============================================================================ // [AsmJit::FileLogger - Accessors] // ============================================================================ //! @brief Set file stream. void FileLogger::setStream(FILE* stream) { _stream = stream; if (isEnabled() && _stream != NULL) _flags |= kLoggerIsUsed; else _flags &= ~kLoggerIsUsed; } // ============================================================================ // [AsmJit::FileLogger - Logging] // ============================================================================ void FileLogger::logString(const char* buf, size_t len) { if (!isUsed()) return; if (len == kInvalidSize) len = strlen(buf); fwrite(buf, 1, len, _stream); } // ============================================================================ // [AsmJit::FileLogger - Enabled] // ============================================================================ void FileLogger::setEnabled(bool enabled) { if (enabled) _flags |= kLoggerIsEnabled | (_stream != NULL ? kLoggerIsUsed : 0); else _flags &= ~(kLoggerIsEnabled | kLoggerIsUsed); } // ============================================================================ // [AsmJit::StringLogger - Construction / Destruction] // ============================================================================ StringLogger::StringLogger() { } StringLogger::~StringLogger() { } // ============================================================================ // [AsmJit::StringLogger - Logging] // ============================================================================ void StringLogger::logString(const char* buf, size_t len) { if (!isUsed()) return; _stringBuilder.appendString(buf, len); } } // AsmJit namespace // [Api-End] #include "../core/apiend.h" desmume/src/libretro-common/include/net/000700 001750 001750 00000000000 12756420131 021436 5ustar00sergiosergio000000 000000 desmume/src/utils/AsmJit/x86/x86cpuinfo.cpp000664 001750 001750 00000023350 12755534123 021633 0ustar00sergiosergio000000 000000 // [AsmJit] // Complete JIT Assembler for C++ Language. // // [License] // Zlib - See COPYING file in this package. #define ASMJIT_EXPORTS // [Dependencies - AsmJit] #include "../x86/x86cpuinfo.h" #include "../x86/x86defs.h" // 2009-02-05: Thanks to Mike Tajmajer for VC7.1 compiler support. It shouldn't // affect x64 compilation, because x64 compiler starts with VS2005 (VC8.0). #if defined(_MSC_VER) # if _MSC_VER >= 1400 # include # endif // _MSC_VER >= 1400 (>= VS2005) #endif // _MSC_VER // [Api-Begin] #include "../core/apibegin.h" namespace AsmJit { // ============================================================================ // [AsmJit::X86CpuVendor] // ============================================================================ struct X86CpuVendor { uint32_t id; char text[12]; }; static const X86CpuVendor x86CpuVendor[] = { { kCpuIntel , { 'G', 'e', 'n', 'u', 'i', 'n', 'e', 'I', 'n', 't', 'e', 'l' } }, { kCpuAmd , { 'A', 'u', 't', 'h', 'e', 'n', 't', 'i', 'c', 'A', 'M', 'D' } }, { kCpuAmd , { 'A', 'M', 'D', 'i', 's', 'b', 'e', 't', 't', 'e', 'r', '!' } }, { kCpuNSM , { 'G', 'e', 'o', 'd', 'e', ' ', 'b', 'y', ' ', 'N', 'S', 'C' } }, { kCpuNSM , { 'C', 'y', 'r', 'i', 'x', 'I', 'n', 's', 't', 'e', 'a', 'd' } }, { kCpuTransmeta, { 'G', 'e', 'n', 'u', 'i', 'n', 'e', 'T', 'M', 'x', '8', '6' } }, { kCpuTransmeta, { 'T', 'r', 'a', 'n', 's', 'm', 'e', 't', 'a', 'C', 'P', 'U' } }, { kCpuVia , { 'V', 'I', 'A', 0 , 'V', 'I', 'A', 0 , 'V', 'I', 'A', 0 } }, { kCpuVia , { 'C', 'e', 'n', 't', 'a', 'u', 'r', 'H', 'a', 'u', 'l', 's' } } }; static inline bool x86CpuVendorEq(const X86CpuVendor& info, const char* vendorString) { const uint32_t* a = reinterpret_cast(info.text); const uint32_t* b = reinterpret_cast(vendorString); return (a[0] == b[0]) & (a[1] == b[1]) & (a[2] == b[2]) ; } // ============================================================================ // [AsmJit::x86CpuSimplifyBrandString] // ============================================================================ static inline void x86CpuSimplifyBrandString(char* s) { // Always clear the current character in the buffer. This ensures that there // is no garbage after the string NULL terminator. char* d = s; char prev = 0; char curr = s[0]; s[0] = '\0'; for (;;) { if (curr == 0) break; if (curr == ' ') { if (prev == '@') goto _Skip; if (s[1] == ' ' || s[1] == '@') goto _Skip; } d[0] = curr; d++; prev = curr; _Skip: curr = *++s; s[0] = '\0'; } d[0] = '\0'; } // ============================================================================ // [AsmJit::x86CpuId] // ============================================================================ // This is messy, I know. cpuid is implemented as intrinsic in VS2005, but // we should support other compilers as well. Main problem is that MS compilers // in 64-bit mode not allows to use inline assembler, so we need intrinsic and // we need also asm version. // x86CpuId() and detectCpuInfo() for x86 and x64 platforms begins here. #if defined(ASMJIT_X86) || defined(ASMJIT_X64) void x86CpuId(uint32_t in, X86CpuId* out) { #if defined(_MSC_VER) // 2009-02-05: Thanks to Mike Tajmajer for supporting VC7.1 compiler. // ASMJIT_X64 is here only for readibility, only VS2005 can compile 64-bit code. # if _MSC_VER >= 1400 || defined(ASMJIT_X64) // Done by intrinsics. __cpuid(reinterpret_cast(out->i), in); # else // _MSC_VER < 1400 uint32_t cpuid_in = in; uint32_t* cpuid_out = out->i; __asm { mov eax, cpuid_in mov edi, cpuid_out cpuid mov dword ptr[edi + 0], eax mov dword ptr[edi + 4], ebx mov dword ptr[edi + 8], ecx mov dword ptr[edi + 12], edx } # endif // _MSC_VER < 1400 #elif defined(__GNUC__) // Note, need to preserve ebx/rbx register! # if defined(ASMJIT_X86) # define __myCpuId(a, b, c, d, inp) \ asm ("mov %%ebx, %%edi\n" \ "cpuid\n" \ "xchg %%edi, %%ebx\n" \ : "=a" (a), "=D" (b), "=c" (c), "=d" (d) : "a" (inp)) # else # define __myCpuId(a, b, c, d, inp) \ asm ("mov %%rbx, %%rdi\n" \ "cpuid\n" \ "xchg %%rdi, %%rbx\n" \ : "=a" (a), "=D" (b), "=c" (c), "=d" (d) : "a" (inp)) # endif __myCpuId(out->eax, out->ebx, out->ecx, out->edx, in); #endif // Compiler #ifdef. } // ============================================================================ // [AsmJit::x86CpuDetect] // ============================================================================ void x86CpuDetect(X86CpuInfo* out) { uint32_t i; X86CpuId regs; // Clear everything except the '_size' member. memset(reinterpret_cast(out) + sizeof(uint32_t), 0, sizeof(CpuInfo) - sizeof(uint32_t)); // Fill safe defaults. memcpy(out->_vendorString, "Unknown", 8); out->_numberOfProcessors = CpuInfo::detectNumberOfProcessors(); // Get vendor string/id. x86CpuId(0, ®s); memcpy(out->_vendorString, ®s.ebx, 4); memcpy(out->_vendorString + 4, ®s.edx, 4); memcpy(out->_vendorString + 8, ®s.ecx, 4); for (i = 0; i < 3; i++) { if (x86CpuVendorEq(x86CpuVendor[i], out->_vendorString)) { out->_vendorId = x86CpuVendor[i].id; break; } } // Get feature flags in ecx/edx, and family/model in eax. x86CpuId(1, ®s); // Fill family and model fields. out->_family = (regs.eax >> 8) & 0x0F; out->_model = (regs.eax >> 4) & 0x0F; out->_stepping = (regs.eax ) & 0x0F; // Use extended family and model fields. if (out->_family == 0x0F) { out->_family += ((regs.eax >> 20) & 0xFF); out->_model += ((regs.eax >> 16) & 0x0F) << 4; } out->_processorType = ((regs.eax >> 12) & 0x03); out->_brandIndex = ((regs.ebx ) & 0xFF); out->_flushCacheLineSize = ((regs.ebx >> 8) & 0xFF) * 8; out->_maxLogicalProcessors = ((regs.ebx >> 16) & 0xFF); out->_apicPhysicalId = ((regs.ebx >> 24) & 0xFF); if (regs.ecx & 0x00000001U) out->_features |= kX86FeatureSse3; if (regs.ecx & 0x00000002U) out->_features |= kX86FeaturePclMulDQ; if (regs.ecx & 0x00000008U) out->_features |= kX86FeatureMonitorMWait; if (regs.ecx & 0x00000200U) out->_features |= kX86FeatureSsse3; if (regs.ecx & 0x00002000U) out->_features |= kX86FeatureCmpXchg16B; if (regs.ecx & 0x00080000U) out->_features |= kX86FeatureSse41; if (regs.ecx & 0x00100000U) out->_features |= kX86FeatureSse42; if (regs.ecx & 0x00400000U) out->_features |= kX86FeatureMovBE; if (regs.ecx & 0x00800000U) out->_features |= kX86FeaturePopCnt; if (regs.ecx & 0x10000000U) out->_features |= kX86FeatureAvx; if (regs.edx & 0x00000010U) out->_features |= kX86FeatureRdtsc; if (regs.edx & 0x00000100U) out->_features |= kX86FeatureCmpXchg8B; if (regs.edx & 0x00008000U) out->_features |= kX86FeatureCMov; if (regs.edx & 0x00800000U) out->_features |= kX86FeatureMmx; if (regs.edx & 0x01000000U) out->_features |= kX86FeatureFXSR; if (regs.edx & 0x02000000U) out->_features |= kX86FeatureSse | kX86FeatureMmxExt; if (regs.edx & 0x04000000U) out->_features |= kX86FeatureSse | kX86FeatureSse2; if (regs.edx & 0x10000000U) out->_features |= kX86FeatureMultiThreading; if (out->_vendorId == kCpuAmd && (regs.edx & 0x10000000U)) { // AMD sets Multithreading to ON if it has more cores. if (out->_numberOfProcessors == 1) out->_numberOfProcessors = 2; } // This comment comes from V8 and I think that its important: // // Opteron Rev E has i bug in which on very rare occasions i locked // instruction doesn't act as i read-acquire barrier if followed by i // non-locked read-modify-write instruction. Rev F has this bug in // pre-release versions, but not in versions released to customers, // so we test only for Rev E, which is family 15, model 32..63 inclusive. if (out->_vendorId == kCpuAmd && out->_family == 15 && out->_model >= 32 && out->_model <= 63) { out->_bugs |= kX86BugAmdLockMB; } // Calling cpuid with 0x80000000 as the in argument // gets the number of valid extended IDs. x86CpuId(0x80000000, ®s); uint32_t exIds = regs.eax; if (exIds > 0x80000004) exIds = 0x80000004; uint32_t* brand = reinterpret_cast(out->_brandString); for (i = 0x80000001; i <= exIds; i++) { x86CpuId(i, ®s); switch (i) { case 0x80000001: if (regs.ecx & 0x00000001U) out->_features |= kX86FeatureLahfSahf; if (regs.ecx & 0x00000020U) out->_features |= kX86FeatureLzCnt; if (regs.ecx & 0x00000040U) out->_features |= kX86FeatureSse4A; if (regs.ecx & 0x00000080U) out->_features |= kX86FeatureMSse; if (regs.ecx & 0x00000100U) out->_features |= kX86FeaturePrefetch; if (regs.edx & 0x00100000U) out->_features |= kX86FeatureExecuteDisableBit; if (regs.edx & 0x00200000U) out->_features |= kX86FeatureFFXSR; if (regs.edx & 0x00400000U) out->_features |= kX86FeatureMmxExt; if (regs.edx & 0x08000000U) out->_features |= kX86FeatureRdtscP; if (regs.edx & 0x20000000U) out->_features |= kX86Feature64Bit; if (regs.edx & 0x40000000U) out->_features |= kX86Feature3dNowExt | kX86FeatureMmxExt; if (regs.edx & 0x80000000U) out->_features |= kX86Feature3dNow; break; case 0x80000002: case 0x80000003: case 0x80000004: *brand++ = regs.eax; *brand++ = regs.ebx; *brand++ = regs.ecx; *brand++ = regs.edx; break; default: // Additional features can be detected in the future. break; } } // Simplify the brand string (remove unnecessary spaces to make it printable). x86CpuSimplifyBrandString(out->_brandString); } #endif } // AsmJit // [Api-End] #include "../core/apiend.h" desmume/src/libretro-common/include/compat/msvc/stdint.h000664 001750 001750 00000017143 12755534123 024611 0ustar00sergiosergio000000 000000 /* ISO C9x compliant stdint.h for Microsoft Visual Studio * Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 * * Copyright (c) 2006-2008 Alexander Chemeris * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. 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. * * 3. The name of the author may be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. */ #ifndef __RARCH_STDINT_H #define __RARCH_STDINT_H #if _MSC_VER && (_MSC_VER < 1600) /* Pre-MSVC 2010 needs an implementation of stdint.h. */ #if _MSC_VER > 1000 #pragma once #endif #include /* For Visual Studio 6 in C++ mode and for many Visual Studio versions when * compiling for ARM we should wrap include with 'extern "C++" {}' * or compiler give many errors like this: * * error C2733: second C linkage of overloaded function 'wmemchr' not allowed */ #ifdef __cplusplus extern "C" { #endif # include #ifdef __cplusplus } #endif /* Define _W64 macros to mark types changing their size, like intptr_t. */ #ifndef _W64 # if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300 # define _W64 __w64 # else # define _W64 # endif #endif /* 7.18.1 Integer types. */ /* 7.18.1.1 Exact-width integer types. */ /* Visual Studio 6 and Embedded Visual C++ 4 doesn't * realize that, e.g. char has the same size as __int8 * so we give up on __intX for them. */ #if (_MSC_VER < 1300) typedef signed char int8_t; typedef signed short int16_t; typedef signed int int32_t; typedef unsigned char uint8_t; typedef unsigned short uint16_t; typedef unsigned int uint32_t; #else typedef signed __int8 int8_t; typedef signed __int16 int16_t; typedef signed __int32 int32_t; typedef unsigned __int8 uint8_t; typedef unsigned __int16 uint16_t; typedef unsigned __int32 uint32_t; #endif typedef signed __int64 int64_t; typedef unsigned __int64 uint64_t; /* 7.18.1.2 Minimum-width integer types. */ typedef int8_t int_least8_t; typedef int16_t int_least16_t; typedef int32_t int_least32_t; typedef int64_t int_least64_t; typedef uint8_t uint_least8_t; typedef uint16_t uint_least16_t; typedef uint32_t uint_least32_t; typedef uint64_t uint_least64_t; /* 7.18.1.3 Fastest minimum-width integer types. */ typedef int8_t int_fast8_t; typedef int16_t int_fast16_t; typedef int32_t int_fast32_t; typedef int64_t int_fast64_t; typedef uint8_t uint_fast8_t; typedef uint16_t uint_fast16_t; typedef uint32_t uint_fast32_t; typedef uint64_t uint_fast64_t; /* 7.18.1.4 Integer types capable of holding object pointers. */ #ifdef _WIN64 /* [ */ typedef signed __int64 intptr_t; typedef unsigned __int64 uintptr_t; #else /* _WIN64 ][ */ typedef _W64 signed int intptr_t; typedef _W64 unsigned int uintptr_t; #endif /* _WIN64 ] */ /* 7.18.1.5 Greatest-width integer types. */ typedef int64_t intmax_t; typedef uint64_t uintmax_t; /* 7.18.2 Limits of specified-width integer types. */ #if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) /* [ See footnote 220 at page 257 and footnote 221 at page 259. */ /* 7.18.2.1 Limits of exact-width integer types. */ #define INT8_MIN ((int8_t)_I8_MIN) #define INT8_MAX _I8_MAX #define INT16_MIN ((int16_t)_I16_MIN) #define INT16_MAX _I16_MAX #define INT32_MIN ((int32_t)_I32_MIN) #define INT32_MAX _I32_MAX #define INT64_MIN ((int64_t)_I64_MIN) #define INT64_MAX _I64_MAX #define UINT8_MAX _UI8_MAX #define UINT16_MAX _UI16_MAX #define UINT32_MAX _UI32_MAX #define UINT64_MAX _UI64_MAX /* 7.18.2.2 Limits of minimum-width integer types. */ #define INT_LEAST8_MIN INT8_MIN #define INT_LEAST8_MAX INT8_MAX #define INT_LEAST16_MIN INT16_MIN #define INT_LEAST16_MAX INT16_MAX #define INT_LEAST32_MIN INT32_MIN #define INT_LEAST32_MAX INT32_MAX #define INT_LEAST64_MIN INT64_MIN #define INT_LEAST64_MAX INT64_MAX #define UINT_LEAST8_MAX UINT8_MAX #define UINT_LEAST16_MAX UINT16_MAX #define UINT_LEAST32_MAX UINT32_MAX #define UINT_LEAST64_MAX UINT64_MAX /* 7.18.2.3 Limits of fastest minimum-width integer types. */ #define INT_FAST8_MIN INT8_MIN #define INT_FAST8_MAX INT8_MAX #define INT_FAST16_MIN INT16_MIN #define INT_FAST16_MAX INT16_MAX #define INT_FAST32_MIN INT32_MIN #define INT_FAST32_MAX INT32_MAX #define INT_FAST64_MIN INT64_MIN #define INT_FAST64_MAX INT64_MAX #define UINT_FAST8_MAX UINT8_MAX #define UINT_FAST16_MAX UINT16_MAX #define UINT_FAST32_MAX UINT32_MAX #define UINT_FAST64_MAX UINT64_MAX /* 7.18.2.4 Limits of integer types capable of holding object pointers. */ #ifdef _WIN64 /* [ */ # define INTPTR_MIN INT64_MIN # define INTPTR_MAX INT64_MAX # define UINTPTR_MAX UINT64_MAX #else /* _WIN64 ][ */ # define INTPTR_MIN INT32_MIN # define INTPTR_MAX INT32_MAX # define UINTPTR_MAX UINT32_MAX #endif /* _WIN64 ] */ /* 7.18.2.5 Limits of greatest-width integer types */ #define INTMAX_MIN INT64_MIN #define INTMAX_MAX INT64_MAX #define UINTMAX_MAX UINT64_MAX /* 7.18.3 Limits of other integer types */ #ifdef _WIN64 /* [ */ # define PTRDIFF_MIN _I64_MIN # define PTRDIFF_MAX _I64_MAX #else /* _WIN64 ][ */ # define PTRDIFF_MIN _I32_MIN # define PTRDIFF_MAX _I32_MAX #endif /* _WIN64 ] */ #define SIG_ATOMIC_MIN INT_MIN #define SIG_ATOMIC_MAX INT_MAX #ifndef SIZE_MAX /* [ */ # ifdef _WIN64 /* [ */ # define SIZE_MAX _UI64_MAX # else /* _WIN64 ][ */ # define SIZE_MAX _UI32_MAX # endif /* _WIN64 ] */ #endif /* SIZE_MAX ] */ /* WCHAR_MIN and WCHAR_MAX are also defined in */ #ifndef WCHAR_MIN /* [ */ # define WCHAR_MIN 0 #endif /* WCHAR_MIN ] */ #ifndef WCHAR_MAX // [ # define WCHAR_MAX _UI16_MAX #endif /* WCHAR_MAX ] */ #define WINT_MIN 0 #define WINT_MAX _UI16_MAX #endif /* __STDC_LIMIT_MACROS ] */ /* 7.18.4 Limits of other integer types */ #if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) /* [ See footnote 224 at page 260 */ /* 7.18.4.1 Macros for minimum-width integer constants */ #define INT8_C(val) val##i8 #define INT16_C(val) val##i16 #define INT32_C(val) val##i32 #define INT64_C(val) val##i64 #define UINT8_C(val) val##ui8 #define UINT16_C(val) val##ui16 #define UINT32_C(val) val##ui32 #define UINT64_C(val) val##ui64 /* 7.18.4.2 Macros for greatest-width integer constants */ #define INTMAX_C INT64_C #define UINTMAX_C UINT64_C #endif /* __STDC_CONSTANT_MACROS ] */ #else /* Sanity for everything else. */ #include #endif #endif desmume/src/libretro-common/gfx/math/matrix_4x4.c000664 001750 001750 00000012501 12755534123 023132 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2016 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (matrix.c). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include #include #include void matrix_4x4_copy(math_matrix_4x4 *dst, const math_matrix_4x4 *src) { unsigned i, j; for (i = 0; i < 4; i++) for (j = 0; j < 4; j++) MAT_ELEM_4X4(*dst, i, j) = MAT_ELEM_4X4(*src, i, j); } /* * Sets mat to an identity matrix */ void matrix_4x4_identity(math_matrix_4x4 *mat) { unsigned i; memset(mat, 0, sizeof(*mat)); for (i = 0; i < 4; i++) MAT_ELEM_4X4(*mat, i, i) = 1.0f; } /* * Sets out to the transposed matrix of in */ void matrix_4x4_transpose(math_matrix_4x4 *out, const math_matrix_4x4 *in) { unsigned i, j; math_matrix_4x4 mat; for (i = 0; i < 4; i++) for (j = 0; j < 4; j++) MAT_ELEM_4X4(mat, j, i) = MAT_ELEM_4X4(*in, i, j); *out = mat; } /* * Builds an X-axis rotation matrix */ void matrix_4x4_rotate_x(math_matrix_4x4 *mat, float rad) { float cosine = cosf(rad); float sine = sinf(rad); matrix_4x4_identity(mat); MAT_ELEM_4X4(*mat, 1, 1) = cosine; MAT_ELEM_4X4(*mat, 2, 2) = cosine; MAT_ELEM_4X4(*mat, 1, 2) = -sine; MAT_ELEM_4X4(*mat, 2, 1) = sine; } /* * Builds a rotation matrix using the * rotation around the Y-axis. */ void matrix_4x4_rotate_y(math_matrix_4x4 *mat, float rad) { float cosine = cosf(rad); float sine = sinf(rad); matrix_4x4_identity(mat); MAT_ELEM_4X4(*mat, 0, 0) = cosine; MAT_ELEM_4X4(*mat, 2, 2) = cosine; MAT_ELEM_4X4(*mat, 0, 2) = -sine; MAT_ELEM_4X4(*mat, 2, 0) = sine; } /* * Builds a rotation matrix using the * rotation around the Z-axis. */ void matrix_4x4_rotate_z(math_matrix_4x4 *mat, float rad) { float cosine = cosf(rad); float sine = sinf(rad); matrix_4x4_identity(mat); MAT_ELEM_4X4(*mat, 0, 0) = cosine; MAT_ELEM_4X4(*mat, 1, 1) = cosine; MAT_ELEM_4X4(*mat, 0, 1) = -sine; MAT_ELEM_4X4(*mat, 1, 0) = sine; } /* * Creates an orthographic projection matrix. */ void matrix_4x4_ortho(math_matrix_4x4 *mat, float left, float right, float bottom, float top, float znear, float zfar) { float tx, ty, tz; matrix_4x4_identity(mat); tx = -(right + left) / (right - left); ty = -(top + bottom) / (top - bottom); tz = -(zfar + znear) / (zfar - znear); MAT_ELEM_4X4(*mat, 0, 0) = 2.0f / (right - left); MAT_ELEM_4X4(*mat, 1, 1) = 2.0f / (top - bottom); MAT_ELEM_4X4(*mat, 2, 2) = -2.0f / (zfar - znear); MAT_ELEM_4X4(*mat, 0, 3) = tx; MAT_ELEM_4X4(*mat, 1, 3) = ty; MAT_ELEM_4X4(*mat, 2, 3) = tz; } void matrix_4x4_scale(math_matrix_4x4 *out, float x, float y, float z) { memset(out, 0, sizeof(*out)); MAT_ELEM_4X4(*out, 0, 0) = x; MAT_ELEM_4X4(*out, 1, 1) = y; MAT_ELEM_4X4(*out, 2, 2) = z; MAT_ELEM_4X4(*out, 3, 3) = 1.0f; } /* * Builds a translation matrix. All other elements in * the matrix will be set to zero except for the * diagonal which is set to 1.0 */ void matrix_4x4_translate(math_matrix_4x4 *out, float x, float y, float z) { matrix_4x4_identity(out); MAT_ELEM_4X4(*out, 0, 3) = x; MAT_ELEM_4X4(*out, 1, 3) = y; MAT_ELEM_4X4(*out, 2, 3) = z; } /* * Creates a perspective projection matrix. */ void matrix_4x4_projection(math_matrix_4x4 *out, float znear, float zfar) { float delta_z = zfar - znear; memset(out, 0, sizeof(*out)); MAT_ELEM_4X4(*out, 0, 0) = znear; MAT_ELEM_4X4(*out, 1, 1) = zfar; MAT_ELEM_4X4(*out, 2, 2) = (zfar + znear) / delta_z; MAT_ELEM_4X4(*out, 2, 3) = -2.0f * zfar * znear / delta_z; MAT_ELEM_4X4(*out, 3, 2) = -1.0f; } /* * Multiplies a with b, stores the result in out */ void matrix_4x4_multiply( math_matrix_4x4 *out, const math_matrix_4x4 *a, const math_matrix_4x4 *b) { unsigned r, c, k; math_matrix_4x4 mat; for (r = 0; r < 4; r++) { for (c = 0; c < 4; c++) { float dot = 0.0f; for (k = 0; k < 4; k++) dot += MAT_ELEM_4X4(*a, r, k) * MAT_ELEM_4X4(*b, k, c); MAT_ELEM_4X4(mat, r, c) = dot; } } *out = mat; } desmume/src/utils/vfat.cpp000664 001750 001750 00000014152 12755534123 016746 0ustar00sergiosergio000000 000000 /* Copyright (C) 2006 yopyop Copyright (C) 2006 Mic Copyright (C) 2010-2016 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the this software. If not, see . */ #include #include #include #include #include #include #include "../types.h" #include "../debug.h" #include "../emufile.h" #include "emufat.h" #include "vfat.h" #include "libfat/libfat_public_api.h" #include #include #include static char retro_dir[PATH_MAX_LENGTH]; enum EListCallbackArg { EListCallbackArg_Item, EListCallbackArg_Pop }; typedef void (*ListCallback)(RDIR *rdir, EListCallbackArg); // List all files and subdirectories recursively static void list_files(const char *filepath, ListCallback list_callback) { void * hFind; char *fname; u32 dwError; RDIR *rdir = retro_opendir(filepath); if (!rdir) return; strcpy(retro_dir, filepath); if (retro_dirent_error(rdir)) goto end; for (;;) { const char *name = NULL; if (!retro_readdir(rdir)) break; const char *fname = retro_dirent_get_name(rdir); list_callback(rdir,EListCallbackArg_Item); if (retro_dirent_is_dir(rdir, filepath) && (strcmp(fname, ".")) && strcmp(fname, "..")) { std::string subdir = (std::string)filepath + path_default_slash() + fname; list_files(subdir.c_str(), list_callback); list_callback(rdir, EListCallbackArg_Pop); } } end: retro_closedir(rdir); } static unsigned long dataSectors = 0; void count_ListCallback(RDIR *rdir, EListCallbackArg arg) { if(arg == EListCallbackArg_Pop) return; u32 sectors = 1; if (!retro_dirent_is_dir(rdir, retro_dir)) { const char *path = retro_dirent_get_name(rdir); /* allocate sectors for file */ int32_t fileSize = path_get_size(path); sectors += (fileSize+511)/512 + 1; } dataSectors += sectors; } static std::string currPath; static std::stack pathStack; static std::stack virtPathStack; static std::string currVirtPath; void build_ListCallback(RDIR *rdir, EListCallbackArg arg) { const char *fname = retro_dirent_get_name(rdir); if(arg == EListCallbackArg_Pop) { currPath = pathStack.top(); pathStack.pop(); currVirtPath = virtPathStack.top(); virtPathStack.pop(); return; } if (retro_dirent_is_dir(rdir, retro_dir)) { if(!strcmp(fname,".")) return; if(!strcmp(fname,"..")) return; pathStack.push(currPath); virtPathStack.push(currVirtPath); currVirtPath = currVirtPath + "/" + fname; bool ok = LIBFAT_MkDir(currVirtPath.c_str()); if(!ok) printf("ERROR adding dir %s via libfat\n",currVirtPath.c_str()); currPath = currPath + path_default_slash() + fname; return; } else { std::string path = currPath + path_default_slash() + fname; FILE* inf = fopen(path.c_str(),"rb"); if(inf) { u8 * buf; size_t elements_read; long len; fseek(inf, 0, SEEK_END); len = ftell(inf); fseek(inf, 0, SEEK_SET); buf = new u8[len]; elements_read = fread(buf, 1, len, inf); if (elements_read != len) printf( "libfat: %lu bytes read instead of %l.\n", elements_read, len ); fclose(inf); std::string path = currVirtPath + "/" + fname; printf("FAT + (%10.2f KB) %s \n",len/1024.f,path.c_str()); bool ok = LIBFAT_WriteFile(path.c_str(),buf,len); if(!ok) printf("ERROR adding file to fat\n"); delete[] buf; } else printf("ERROR opening file for fat\n"); } } bool VFAT::build(const char* path, int extra_MB) { dataSectors = 0; currVirtPath = ""; currPath = path; list_files(path, count_ListCallback); dataSectors += 8; //a few for reserved sectors, etc. dataSectors += extra_MB*1024*1024/512; //add extra write space //dataSectors += 16*1024*1024/512; //add 16MB worth of write space. this is probably enough for anyone, but maybe it should be configurable. //we could always suggest to users to add a big file to their directory to overwrite (that would cause the image to get padded) //this seems to be the minimum size that will turn into a solid fat32 if(dataSectors<36*1024*1024/512) dataSectors = 36*1024*1024/512; if(dataSectors>=(0x80000000>>9)) { printf( "error allocating memory for fat (%lu KBytes)\n", (dataSectors*512) / 1024 ); printf("total fat sizes > 2GB are never going to work\n"); } delete file; try { file = new EMUFILE_MEMORY(dataSectors*512); } catch(std::bad_alloc) { printf( "error allocating memory for fat (%lu KBytes)\n", (dataSectors*512) / 1024 ); printf("(out of memory)\n"); return false; } //debug.. //file = new EMUFILE_FILE("c:\\temp.ima","rb+"); //format the disk { EmuFat fat(file); EmuFatVolume vol; u8 ok = vol.init(&fat); vol.formatNew(dataSectors); //ensure we are working in memory, just in case we were testing with a disk file. //libfat will need to go straight to memory (for now; we could easily change it to work with the disk) file = file->memwrap(); } EMUFILE_MEMORY* memf = (EMUFILE_MEMORY*)file; //setup libfat and write all the files through it LIBFAT_Init(memf->buf(),memf->size()); list_files(path, build_ListCallback); LIBFAT_Shutdown(); return true; } VFAT::VFAT() : file(NULL) { } VFAT::~VFAT() { delete file; } EMUFILE* VFAT::detach() { EMUFILE* ret = file; file = NULL; return ret; } desmume/src/libretro-common/net/test/Makefile000664 001750 001750 00000001544 12755534123 022460 0ustar00sergiosergio000000 000000 TARGETS = http_test net_ifinfo LIBRETRO_COMM_DIR := ../.. INCFLAGS = -I$(LIBRETRO_COMM_DIR)/include ifeq ($(DEBUG),1) CFLAGS += -O0 -g else CFLAGS += -O2 endif CFLAGS += -Wall -pedantic -std=gnu99 HTTP_TEST_C = \ $(LIBRETRO_COMM_DIR)/net/net_http.c \ net_http_test.c \ $(LIBRETRO_COMM_DIR)/net/net_compat.c \ $(LIBRETRO_COMM_DIR)/compat/compat_strl.c HTTP_TEST_OBJS := $(HTTP_TEST_C:.c=.o) NET_IFINFO_C = \ $(LIBRETRO_COMM_DIR)/net/net_ifinfo.c \ net_ifinfo_test.c NET_IFINFO_OBJS := $(NET_IFINFO_C:.c=.o) .PHONY: all clean all: $(TARGETS) %.o: %.c $(CC) $(INCFLAGS) $< -c $(CFLAGS) -o $@ http_test: $(HTTP_TEST_OBJS) $(CC) $(INCFLAGS) $(HTTP_TEST_OBJS) $(CFLAGS) -o $@ net_ifinfo: $(NET_IFINFO_OBJS) $(CC) $(INCFLAGS) $(NET_IFINFO_OBJS) $(CFLAGS) -o $@ clean: rm -rf $(TARGETS) $(HTTP_TEST_OBJS) $(NET_IFINFO_OBJS) desmume/src/libretro-common/dynamic/000700 001750 001750 00000000000 12756420131 020651 5ustar00sergiosergio000000 000000 desmume/src/utils/AsmJit/x86/x86compilerfunc.h000664 001750 001750 00000034072 12755534123 022326 0ustar00sergiosergio000000 000000 // [AsmJit] // Complete JIT Assembler for C++ Language. // // [License] // Zlib - See COPYING file in this package. // [Guard] #ifndef _ASMJIT_X86_X86COMPILERFUNC_H #define _ASMJIT_X86_X86COMPILERFUNC_H // [Dependencies - AsmJit] #include "../x86/x86assembler.h" #include "../x86/x86compiler.h" #include "../x86/x86compileritem.h" // [Api-Begin] #include "../core/apibegin.h" namespace AsmJit { //! @addtogroup AsmJit_X86 //! @{ // ============================================================================ // [AsmJit::X86CompilerFuncDecl] // ============================================================================ //! @brief @ref X86Compiler specific function declaration item. struct X86CompilerFuncDecl : public CompilerFuncDecl { ASMJIT_NO_COPY(X86CompilerFuncDecl) // -------------------------------------------------------------------------- // [Construction / Destruction] // -------------------------------------------------------------------------- //! @brief Create a new @ref X86CompilerFuncDecl instance. ASMJIT_API X86CompilerFuncDecl(X86Compiler* x86Compiler); //! @brief Destroy the @ref X86CompilerFuncDecl instance. ASMJIT_API virtual ~X86CompilerFuncDecl(); // -------------------------------------------------------------------------- // [Accessors] // -------------------------------------------------------------------------- //! @brief Get compiler as @ref X86Compiler. inline X86Compiler* getCompiler() const { return reinterpret_cast(_compiler); } //! @brief Get function end item as @ref X86CompilerFuncEnd. inline X86CompilerFuncEnd* getEnd() const { return reinterpret_cast(_end); } //! @brief Get function declaration as @ref X86FuncDecl. inline X86FuncDecl* getDecl() const { return reinterpret_cast(_decl); } //! @brief Get function arguments as variables as @ref X86CompilerVar. inline X86CompilerVar** getVars() const { return reinterpret_cast(_vars); } //! @brief Get function argument at @a index. inline X86CompilerVar* getVar(uint32_t index) const { ASMJIT_ASSERT(index < _x86Decl.getArgumentsCount()); return reinterpret_cast(_vars)[index]; } //! @brief Get whether it's assumed that stack is aligned to 16 bytes. inline bool isAssumed16ByteAlignment() const { return hasFuncFlag(kX86FuncFlagAssume16ByteAlignment); } //! @brief Get whether it's required to align stack to 16 bytes by function. inline bool isPerformed16ByteAlignment() const { return hasFuncFlag(kX86FuncFlagPerform16ByteAlignment); } //! @brief Get whether the ESP is adjusted. inline bool isEspAdjusted() const { return hasFuncFlag(kX86FuncFlagIsEspAdjusted); } // -------------------------------------------------------------------------- // [Interface] // -------------------------------------------------------------------------- ASMJIT_API virtual void prepare(CompilerContext& cc); ASMJIT_API virtual CompilerItem* translate(CompilerContext& cc); // -------------------------------------------------------------------------- // [Misc] // -------------------------------------------------------------------------- ASMJIT_API virtual int getMaxSize() const; // -------------------------------------------------------------------------- // [Prototype] // -------------------------------------------------------------------------- ASMJIT_API virtual void setPrototype( uint32_t convention, uint32_t returnType, const uint32_t* arguments, uint32_t argumentsCount); // -------------------------------------------------------------------------- // [Helpers] // -------------------------------------------------------------------------- //! @internal //! //! @brief Get required stack offset needed to subtract/add Esp/Rsp in //! prolog/epilog. inline int32_t _getRequiredStackOffset() const { return _funcCallStackSize + _memStackSize16 + _peMovStackSize + _peAdjustStackSize; } //! @brief Create variables from FunctionPrototype declaration. This is just //! parsing what FunctionPrototype generated for current function calling //! convention and arguments. ASMJIT_API void _createVariables(); //! @brief Prepare variables (ids, names, scope, registers). ASMJIT_API void _prepareVariables(CompilerItem* first); //! @brief Allocate variables (setting correct state, changing masks, etc). ASMJIT_API void _allocVariables(CompilerContext& cc); ASMJIT_API void _preparePrologEpilog(CompilerContext& cc); ASMJIT_API void _dumpFunction(CompilerContext& cc); ASMJIT_API void _emitProlog(CompilerContext& cc); ASMJIT_API void _emitEpilog(CompilerContext& cc); // -------------------------------------------------------------------------- // [Function-Call] // -------------------------------------------------------------------------- //! @brief Reserve stack for calling other function and mark function as //! callee. ASMJIT_API void reserveStackForFunctionCall(int32_t size); // -------------------------------------------------------------------------- // [Members] // -------------------------------------------------------------------------- //! @brief X86 function decl. X86FuncDecl _x86Decl; //! @brief Modified and preserved GP registers mask. uint32_t _gpModifiedAndPreserved; //! @brief Modified and preserved MM registers mask. uint32_t _mmModifiedAndPreserved; //! @brief Modified and preserved XMM registers mask. uint32_t _xmmModifiedAndPreserved; //! @brief Id of MovDQWord instruction (@c kX86InstMovDQA or @c kX86InstMovDQU). //! //! The value is based on stack alignment. If it's guaranteed that stack //! is aligned to 16-bytes then @c kX86InstMovDQA instruction is used, otherwise //! the @c kX86InstMovDQU instruction is used for 16-byte mov. uint32_t _movDqInstCode; //! @brief Prolog / epilog stack size for PUSH/POP sequences. int32_t _pePushPopStackSize; //! @brief Prolog / epilog stack size for MOV sequences. int32_t _peMovStackSize; //! @brief Prolog / epilog stack adjust size (to make it 16-byte aligned). int32_t _peAdjustStackSize; //! @brief Memory stack size (for all variables and temporary memory). int32_t _memStackSize; //! @brief Like @c _memStackSize, but aligned to 16-bytes. int32_t _memStackSize16; }; // ============================================================================ // [AsmJit::X86CompilerFuncEnd] // ============================================================================ //! @brief @ref X86Compiler function end item. struct X86CompilerFuncEnd : public CompilerFuncEnd { ASMJIT_NO_COPY(X86CompilerFuncEnd) // -------------------------------------------------------------------------- // [Construction / Destruction] // -------------------------------------------------------------------------- //! @brief Create a new @ref X86CompilerFuncEnd instance. ASMJIT_API X86CompilerFuncEnd(X86Compiler* x86Compiler, X86CompilerFuncDecl* func); //! @brief Destroy the @ref X86CompilerFuncEnd instance. ASMJIT_API virtual ~X86CompilerFuncEnd(); // -------------------------------------------------------------------------- // [Accessors] // -------------------------------------------------------------------------- //! @brief Get compiler as @ref X86Compiler. inline X86Compiler* getCompiler() const { return reinterpret_cast(_compiler); } //! @brief Get related function as @ref X86CompilerFuncDecl. inline X86CompilerFuncDecl* getFunc() const { return reinterpret_cast(_func); } // -------------------------------------------------------------------------- // [Interface] // -------------------------------------------------------------------------- ASMJIT_API virtual void prepare(CompilerContext& cc); ASMJIT_API virtual CompilerItem* translate(CompilerContext& cc); }; // ============================================================================ // [AsmJit::X86CompilerFuncRet] // ============================================================================ //! @brief Function return. struct X86CompilerFuncRet : public CompilerFuncRet { ASMJIT_NO_COPY(X86CompilerFuncRet) // -------------------------------------------------------------------------- // [Construction / Destruction] // -------------------------------------------------------------------------- //! @brief Create a new @ref X86CompilerFuncRet instance. ASMJIT_API X86CompilerFuncRet(X86Compiler* c, X86CompilerFuncDecl* func, const Operand* first, const Operand* second); //! @brief Destroy the @ref X86CompilerFuncRet instance. ASMJIT_API virtual ~X86CompilerFuncRet(); // -------------------------------------------------------------------------- // [Accessors] // -------------------------------------------------------------------------- //! @brief Get compiler as @ref X86Compiler. inline X86Compiler* getCompiler() const { return reinterpret_cast(_compiler); } //! @Brief Get related function as @ref X86CompilerFuncDecl. inline X86CompilerFuncDecl* getFunc() const { return reinterpret_cast(_func); } // -------------------------------------------------------------------------- // [Interface] // -------------------------------------------------------------------------- ASMJIT_API virtual void prepare(CompilerContext& cc); ASMJIT_API virtual CompilerItem* translate(CompilerContext& cc); ASMJIT_API virtual void emit(Assembler& a); // -------------------------------------------------------------------------- // [Misc] // -------------------------------------------------------------------------- ASMJIT_API virtual int getMaxSize() const; }; // ============================================================================ // [AsmJit::X86CompilerFuncCall] // ============================================================================ //! @brief Compiler function call item. struct X86CompilerFuncCall : public CompilerFuncCall { ASMJIT_NO_COPY(X86CompilerFuncCall) // -------------------------------------------------------------------------- // [Construction / Destruction] // -------------------------------------------------------------------------- //! @brief Create a new @ref X86CompilerFuncCall instance. ASMJIT_API X86CompilerFuncCall(X86Compiler* x86Compiler, X86CompilerFuncDecl* caller, const Operand* target); //! @brief Destroy the @ref X86CompilerFuncCall instance. ASMJIT_API virtual ~X86CompilerFuncCall(); // -------------------------------------------------------------------------- // [Accessors] // -------------------------------------------------------------------------- //! @brief Get compiler as @ref X86Compiler. inline X86Compiler* getCompiler() const { return reinterpret_cast(_compiler); } //! @brief Get caller as @ref X86CompilerFuncDecl. inline X86CompilerFuncDecl* getCaller() const { return reinterpret_cast(_caller); } //! @brief Get function prototype. inline const X86FuncDecl* getDecl() const { return reinterpret_cast(_decl); } // -------------------------------------------------------------------------- // [Interface] // -------------------------------------------------------------------------- ASMJIT_API virtual void prepare(CompilerContext& cc); ASMJIT_API virtual CompilerItem* translate(CompilerContext& cc); // -------------------------------------------------------------------------- // [Misc] // -------------------------------------------------------------------------- ASMJIT_API virtual int getMaxSize() const; ASMJIT_API virtual bool _tryUnuseVar(CompilerVar* v); // -------------------------------------------------------------------------- // [Prototype] // -------------------------------------------------------------------------- ASMJIT_API virtual void setPrototype(uint32_t convention, uint32_t returnType, const uint32_t* arguments, uint32_t argumentsCount); //! @brief Set function prototype. inline void setPrototype(uint32_t convention, const FuncPrototype& func) { setPrototype(convention, func.getReturnType(), func.getArguments(), func.getArgumentsCount()); } //! @brief Set return value. ASMJIT_API bool setReturn(const Operand& first, const Operand& second = Operand()); //! @brief Set function argument @a i to @a var. ASMJIT_API bool setArgument(uint32_t i, const Var& var); //! @brief Set function argument @a i to @a imm. ASMJIT_API bool setArgument(uint32_t i, const Imm& imm); // -------------------------------------------------------------------------- // [Internal] // -------------------------------------------------------------------------- ASMJIT_API uint32_t _findTemporaryGpRegister(CompilerContext& cc); ASMJIT_API uint32_t _findTemporaryXmmRegister(CompilerContext& cc); ASMJIT_API X86CompilerVar* _getOverlappingVariable(CompilerContext& cc, const FuncArg& argType) const; ASMJIT_API void _moveAllocatedVariableToStack(CompilerContext& cc, X86CompilerVar* vdata, const FuncArg& argType); ASMJIT_API void _moveSpilledVariableToStack(CompilerContext& cc, X86CompilerVar* vdata, const FuncArg& argType, uint32_t temporaryGpReg, uint32_t temporaryXmmReg); ASMJIT_API void _moveSrcVariableToRegister(CompilerContext& cc, X86CompilerVar* vdata, const FuncArg& argType); // -------------------------------------------------------------------------- // [Members] // -------------------------------------------------------------------------- //! @brief X86 declaration. X86FuncDecl _x86Decl; //! @brief Mask of GP registers used as function arguments. uint32_t _gpParams; //! @brief Mask of MM registers used as function arguments. uint32_t _mmParams; //! @brief Mask of XMM registers used as function arguments. uint32_t _xmmParams; //! @brief Variables count. uint32_t _variablesCount; //! @brief Variables (extracted from operands). VarCallRecord* _variables; //! @brief Argument index to @c VarCallRecord. VarCallRecord* _argumentToVarRecord[kFuncArgsMax]; }; //! @} } // AsmJit namespace // [Api-End] #include "../core/apiend.h" // [Guard] #endif // _ASMJIT_X86_X86COMPILERFUNC_H desmume/src/libretro-common/memmap/000700 001750 001750 00000000000 12756420131 020501 5ustar00sergiosergio000000 000000 desmume/src/Disassembler.cpp000664 001750 001750 00000331732 12755534123 017271 0ustar00sergiosergio000000 000000 /* Copyright (C) 2006 yopyop Copyright (C) 2006-2012 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the this software. If not, see . */ #include #include #include "Disassembler.h" #include "utils/bits.h" #include "armcpu.h" #define ROR(i, j) ((((u32)(i))>>(j)) | (((u32)(i))<<(32-(j)))) const char Condition[16][3] = { "EQ", "NE", "CS", "CC", "MI", "PL", "VS", "VC", "HI", "LS", "GE", "LT", "GT", "LE", "", "" }; const char Registre[16][4] = { "R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7", "R8", "R9", "R10", "R11", "R12", "SP", "LR", "PC", }; const char MSR_FIELD[16][5] = { "", "c", "x", "xc", "s", "sc", "sx", "sxc", "f", "fc", "fx", "fxc", "fs", "fsc", "fsx", "fsxc" }; #define DATAPROC_LSL_IMM(nom, s) char tmp[10] = "";\ if(((i>>7)&0x1F)!=0)\ sprintf(tmp, ", LSL #%X", (int)((i>>7)&0x1F));\ sprintf(txt, "%s%s%s %s, %s, %s%s",\ #nom,\ Condition[CONDITION(i)],\ s,\ Registre[REG_POS(i,12)],\ Registre[REG_POS(i,16)],\ Registre[REG_POS(i,0)],\ tmp); #define DATAPROC_ROR_IMM(nom, s) char tmp[10] = "";\ if(((i>>7)&0x1F)!=0)\ sprintf(tmp, ", RRX");\ sprintf(txt, "%s%s%s %s, %s, %s%s",\ #nom,\ Condition[CONDITION(i)],\ s,\ Registre[REG_POS(i,12)],\ Registre[REG_POS(i,16)],\ Registre[REG_POS(i,0)],\ tmp\ ); #define DATAPROC_REG_SHIFT(nom, shift,s) sprintf(txt, "%s%s%s %s, %s, %s, %s %s",\ #nom,\ Condition[CONDITION(i)],\ s,\ Registre[REG_POS(i,12)],\ Registre[REG_POS(i,16)],\ Registre[REG_POS(i,0)],\ #shift,\ Registre[REG_POS(i,8)]\ ); #define DATAPROC_IMM_SHIFT(nom, shift, s) sprintf(txt, "%s%s%s %s, %s, %s, %s #%X",\ #nom,\ Condition[CONDITION(i)],\ s,\ Registre[REG_POS(i,12)],\ Registre[REG_POS(i,16)],\ Registre[REG_POS(i,0)],\ #shift,\ (int)((i>>7)&0x1F)\ ); #define DATAPROC_IMM_VALUE(nom,s) u32 shift_op = ROR((i&0xFF), (i>>7)&0x1E);\ sprintf(txt, "%s%s%s %s, %s, #%X",\ #nom,\ Condition[CONDITION(i)],\ s,\ Registre[REG_POS(i,12)],\ Registre[REG_POS(i,16)],\ (int)shift_op\ ); #define DATAPROC_ONE_OP_LSL_IMM(nom, s, v) char tmp[10] = "";\ if(((i>>7)&0x1F)!=0)\ sprintf(tmp, ", LSL #%X", (int)((i>>7)&0x1F));\ sprintf(txt, "%s%s%s %s, %s%s",\ #nom,\ Condition[CONDITION(i)],\ s,\ Registre[REG_POS(i,v)],\ Registre[REG_POS(i,0)],\ tmp); #define DATAPROC_ONE_OP_ROR_IMM(nom, s, v) char tmp[10] = "";\ if(((i>>7)&0x1F)==0)\ sprintf(tmp, ", RRX");\ else\ sprintf(tmp, ", ROR %d", (int)((i>>7)&0x1F));\ sprintf(txt, "%s%s%s %s, %s%s",\ #nom,\ Condition[CONDITION(i)],\ s,\ Registre[REG_POS(i,v)],\ Registre[REG_POS(i,0)],\ tmp\ ); #define DATAPROC_ONE_OP_REG_SHIFT(nom, shift,s, v) sprintf(txt, "%s%s%s %s, %s, %s %s",\ #nom,\ Condition[CONDITION(i)],\ s,\ Registre[REG_POS(i,v)],\ Registre[REG_POS(i,0)],\ #shift,\ Registre[REG_POS(i,8)]\ ); #define DATAPROC_ONE_OP_IMM_SHIFT(nom, shift, s, v) sprintf(txt, "%s%s%s %s, %s, %s #%X",\ #nom,\ Condition[CONDITION(i)],\ s,\ Registre[REG_POS(i,v)],\ Registre[REG_POS(i,0)],\ #shift,\ (int)((i>>7)&0x1F)\ ); #define DATAPROC_ONE_OP_IMM_VALUE(nom, s, v)\ u32 shift_op = ROR((i&0xFF), (i>>7)&0x1E);\ sprintf(txt, "%s%s%s %s, #%X",\ #nom,\ Condition[CONDITION(i)],\ s,\ Registre[REG_POS(i,v)],\ (int)shift_op\ ); #define SIGNEXTEND_24(i) (((i)&0xFFFFFF)|(0xFF000000*BIT23(i))) #define LDRSTR_LSL_IMM(nom, op, op2, op3) char tmp[10] = "";\ if(((i>>7)&0x1F)!=0)\ sprintf(tmp, ", LSL #%X", (int)((i>>7)&0x1F));\ sprintf(txt, "%s%s %s, [%s%s, %s%s%s%s",\ #nom,\ Condition[CONDITION(i)],\ Registre[REG_POS(i,12)],\ Registre[REG_POS(i,16)],\ op2,\ op,\ Registre[REG_POS(i,0)],\ tmp,\ op3); #define LDRSTR_ROR_IMM(nom, op, op2, op3) char tmp[10] = "";\ if(((i>>7)&0x1F)!=0)\ sprintf(tmp, ", RRX");\ sprintf(txt, "%s%s %s, [%s%s, %s%s%s%s",\ #nom,\ Condition[CONDITION(i)],\ Registre[REG_POS(i,12)],\ Registre[REG_POS(i,16)],\ op2,\ op,\ Registre[REG_POS(i,0)],\ tmp,\ op3\ ); #define LDRSTR_IMM_SHIFT(nom, shift, op, op2, op3)\ sprintf(txt, "%s%s %s, [%s%s, %s%s, %s #%X%s",\ #nom,\ Condition[CONDITION(i)],\ Registre[REG_POS(i,12)],\ Registre[REG_POS(i,16)],\ op2,\ op,\ Registre[REG_POS(i,0)],\ #shift,\ (int)((i>>7)&0x1F),\ op3\ ); #define RegList(nb) char lreg[100] = "";\ int prec = 0;\ int j;\ for(j = 0; j < nb; j++)\ {\ if(prec)\ {\ if((!BIT_N(i, j+1))||(j==nb-1))\ {\ sprintf(lreg + strlen(lreg), "%s,", Registre[j]);\ prec = 0;\ }\ }\ else\ {\ if(BIT_N(i, j))\ {\ if((BIT_N(i, j+1))&&(j!=nb-1))\ {\ sprintf(lreg + strlen(lreg), "%s-", Registre[j]);\ prec = 1;\ }\ else\ sprintf(lreg + strlen(lreg), "%s,", Registre[j]);\ }\ }\ }\ if(*lreg) lreg[strlen(lreg)-1]='\0'; static char * OP_UND(u32 adr, u32 i, char * txt) { sprintf(txt, "----"); return txt; } //-----------------------AND------------------------------------ static char * OP_AND_LSL_IMM(u32 adr, u32 i, char * txt) { DATAPROC_LSL_IMM(AND, ""); return txt; } static char * OP_AND_LSL_REG(u32 adr, u32 i, char * txt) { DATAPROC_REG_SHIFT(AND, LSL, ""); return txt; } static char * OP_AND_LSR_IMM(u32 adr, u32 i, char * txt) { DATAPROC_IMM_SHIFT(AND, LSR, ""); return txt; } static char * OP_AND_LSR_REG(u32 adr, u32 i, char * txt) { DATAPROC_REG_SHIFT(AND, LSR, ""); return txt; } static char * OP_AND_ASR_IMM(u32 adr, u32 i, char * txt) { DATAPROC_IMM_SHIFT(AND, ASR, ""); return txt; } static char * OP_AND_ASR_REG(u32 adr, u32 i, char * txt) { DATAPROC_REG_SHIFT(AND, ASR, ""); return txt; } static char * OP_AND_ROR_IMM(u32 adr, u32 i, char * txt) { DATAPROC_ROR_IMM(AND, ""); return txt; } static char * OP_AND_ROR_REG(u32 adr, u32 i, char * txt) { DATAPROC_REG_SHIFT(AND, ROR, ""); return txt; } static char * OP_AND_IMM_VAL(u32 adr, u32 i, char * txt) { DATAPROC_IMM_VALUE(AND, ""); return txt; } static char * OP_AND_S_LSL_IMM(u32 adr, u32 i, char * txt) { DATAPROC_LSL_IMM(AND, "S"); return txt; } static char * OP_AND_S_LSL_REG(u32 adr, u32 i, char * txt) { DATAPROC_REG_SHIFT(AND, LSL, "S"); return txt; } static char * OP_AND_S_LSR_IMM(u32 adr, u32 i, char * txt) { DATAPROC_IMM_SHIFT(AND, LSR, "S"); return txt; } static char * OP_AND_S_LSR_REG(u32 adr, u32 i, char * txt) { DATAPROC_REG_SHIFT(AND, LSR, "S"); return txt; } static char * OP_AND_S_ASR_IMM(u32 adr, u32 i, char * txt) { DATAPROC_IMM_SHIFT(AND, ASR, "S"); return txt; } static char * OP_AND_S_ASR_REG(u32 adr, u32 i, char * txt) { DATAPROC_REG_SHIFT(AND, ASR, "S"); return txt; } static char * OP_AND_S_ROR_IMM(u32 adr, u32 i, char * txt) { DATAPROC_ROR_IMM(AND, "S"); return txt; } static char * OP_AND_S_ROR_REG(u32 adr, u32 i, char * txt) { DATAPROC_REG_SHIFT(AND, ROR, "S"); return txt; } static char * OP_AND_S_IMM_VAL(u32 adr, u32 i, char * txt) { DATAPROC_IMM_VALUE(AND, "S"); return txt; } //--------------EOR------------------------------ static char * OP_EOR_LSL_IMM(u32 adr, u32 i, char * txt) { DATAPROC_LSL_IMM(EOR, ""); return txt; } static char * OP_EOR_LSL_REG(u32 adr, u32 i, char * txt) { DATAPROC_REG_SHIFT(EOR, LSL, ""); return txt; } static char * OP_EOR_LSR_IMM(u32 adr, u32 i, char * txt) { DATAPROC_IMM_SHIFT(EOR, LSR, ""); return txt; } static char * OP_EOR_LSR_REG(u32 adr, u32 i, char * txt) { DATAPROC_REG_SHIFT(EOR, LSR, ""); return txt; } static char * OP_EOR_ASR_IMM(u32 adr, u32 i, char * txt) { DATAPROC_IMM_SHIFT(EOR, ASR, ""); return txt; } static char * OP_EOR_ASR_REG(u32 adr, u32 i, char * txt) { DATAPROC_REG_SHIFT(EOR, ASR, ""); return txt; } static char * OP_EOR_ROR_IMM(u32 adr, u32 i, char * txt) { DATAPROC_ROR_IMM(EOR, ""); return txt; } static char * OP_EOR_ROR_REG(u32 adr, u32 i, char * txt) { DATAPROC_REG_SHIFT(EOR, ROR, ""); return txt; } static char * OP_EOR_IMM_VAL(u32 adr, u32 i, char * txt) { DATAPROC_IMM_VALUE(EOR, ""); return txt; } static char * OP_EOR_S_LSL_IMM(u32 adr, u32 i, char * txt) { DATAPROC_LSL_IMM(EOR, "S"); return txt; } static char * OP_EOR_S_LSL_REG(u32 adr, u32 i, char * txt) { DATAPROC_REG_SHIFT(EOR, LSL, "S"); return txt; } static char * OP_EOR_S_LSR_IMM(u32 adr, u32 i, char * txt) { DATAPROC_IMM_SHIFT(EOR, LSR, "S"); return txt; } static char * OP_EOR_S_LSR_REG(u32 adr, u32 i, char * txt) { DATAPROC_REG_SHIFT(EOR, LSR, "S"); return txt; } static char * OP_EOR_S_ASR_IMM(u32 adr, u32 i, char * txt) { DATAPROC_IMM_SHIFT(EOR, ASR, "S"); return txt; } static char * OP_EOR_S_ASR_REG(u32 adr, u32 i, char * txt) { DATAPROC_REG_SHIFT(EOR, ASR, "S"); return txt; } static char * OP_EOR_S_ROR_IMM(u32 adr, u32 i, char * txt) { DATAPROC_ROR_IMM(EOR, "S"); return txt; } static char * OP_EOR_S_ROR_REG(u32 adr, u32 i, char * txt) { DATAPROC_REG_SHIFT(EOR, ROR, "S"); return txt; } static char * OP_EOR_S_IMM_VAL(u32 adr, u32 i, char * txt) { DATAPROC_IMM_VALUE(EOR, "S"); return txt; } //-------------SUB------------------------------------- static char * OP_SUB_LSL_IMM(u32 adr, u32 i, char * txt) { DATAPROC_LSL_IMM(SUB, ""); return txt; } static char * OP_SUB_LSL_REG(u32 adr, u32 i, char * txt) { DATAPROC_REG_SHIFT(SUB, LSL, ""); return txt; } static char * OP_SUB_LSR_IMM(u32 adr, u32 i, char * txt) { DATAPROC_IMM_SHIFT(SUB, LSR, ""); return txt; } static char * OP_SUB_LSR_REG(u32 adr, u32 i, char * txt) { DATAPROC_REG_SHIFT(SUB, LSR, ""); return txt; } static char * OP_SUB_ASR_IMM(u32 adr, u32 i, char * txt) { DATAPROC_IMM_SHIFT(SUB, ASR, ""); return txt; } static char * OP_SUB_ASR_REG(u32 adr, u32 i, char * txt) { DATAPROC_REG_SHIFT(SUB, ASR, ""); return txt;} static char * OP_SUB_ROR_IMM(u32 adr, u32 i, char * txt) { DATAPROC_ROR_IMM(SUB, ""); return txt;} static char * OP_SUB_ROR_REG(u32 adr, u32 i, char * txt) { DATAPROC_REG_SHIFT(SUB, ROR, ""); return txt;} static char * OP_SUB_IMM_VAL(u32 adr, u32 i, char * txt) { DATAPROC_IMM_VALUE(SUB, ""); return txt;} static char * OP_SUB_S_LSL_IMM(u32 adr, u32 i, char * txt) { DATAPROC_LSL_IMM(SUB, "S"); return txt;} static char * OP_SUB_S_LSL_REG(u32 adr, u32 i, char * txt) { DATAPROC_REG_SHIFT(SUB, LSL, "S"); return txt;} static char * OP_SUB_S_LSR_IMM(u32 adr, u32 i, char * txt) { DATAPROC_IMM_SHIFT(SUB, LSR, "S"); return txt;} static char * OP_SUB_S_LSR_REG(u32 adr, u32 i, char * txt) { DATAPROC_REG_SHIFT(SUB, LSR, "S"); return txt;} static char * OP_SUB_S_ASR_IMM(u32 adr, u32 i, char * txt) { DATAPROC_IMM_SHIFT(SUB, ASR, "S"); return txt;} static char * OP_SUB_S_ASR_REG(u32 adr, u32 i, char * txt) { DATAPROC_REG_SHIFT(SUB, ASR, "S"); return txt;} static char * OP_SUB_S_ROR_IMM(u32 adr, u32 i, char * txt) { DATAPROC_ROR_IMM(SUB, "S"); return txt;} static char * OP_SUB_S_ROR_REG(u32 adr, u32 i, char * txt) { DATAPROC_REG_SHIFT(SUB, ROR, "S"); return txt;} static char * OP_SUB_S_IMM_VAL(u32 adr, u32 i, char * txt) { DATAPROC_IMM_VALUE(SUB, "S"); return txt;} //------------------RSB------------------------ static char * OP_RSB_LSL_IMM(u32 adr, u32 i, char * txt) { DATAPROC_LSL_IMM(RSB, ""); return txt;} static char * OP_RSB_LSL_REG(u32 adr, u32 i, char * txt) { DATAPROC_REG_SHIFT(RSB, LSL, ""); return txt;} static char * OP_RSB_LSR_IMM(u32 adr, u32 i, char * txt) { DATAPROC_IMM_SHIFT(RSB, LSR, ""); return txt;} static char * OP_RSB_LSR_REG(u32 adr, u32 i, char * txt) { DATAPROC_REG_SHIFT(RSB, LSR, ""); return txt;} static char * OP_RSB_ASR_IMM(u32 adr, u32 i, char * txt) { DATAPROC_IMM_SHIFT(RSB, ASR, ""); return txt;} static char * OP_RSB_ASR_REG(u32 adr, u32 i, char * txt) { DATAPROC_REG_SHIFT(RSB, ASR, ""); return txt;} static char * OP_RSB_ROR_IMM(u32 adr, u32 i, char * txt) { DATAPROC_ROR_IMM(RSB, ""); return txt;} static char * OP_RSB_ROR_REG(u32 adr, u32 i, char * txt) { DATAPROC_REG_SHIFT(RSB, ROR, ""); return txt;} static char * OP_RSB_IMM_VAL(u32 adr, u32 i, char * txt) { DATAPROC_IMM_VALUE(RSB, ""); return txt;} static char * OP_RSB_S_LSL_IMM(u32 adr, u32 i, char * txt) { DATAPROC_LSL_IMM(RSB, "S"); return txt;} static char * OP_RSB_S_LSL_REG(u32 adr, u32 i, char * txt) { DATAPROC_REG_SHIFT(RSB, LSL, "S"); return txt;} static char * OP_RSB_S_LSR_IMM(u32 adr, u32 i, char * txt) { DATAPROC_IMM_SHIFT(RSB, LSR, "S"); return txt;} static char * OP_RSB_S_LSR_REG(u32 adr, u32 i, char * txt) { DATAPROC_REG_SHIFT(RSB, LSR, "S"); return txt;} static char * OP_RSB_S_ASR_IMM(u32 adr, u32 i, char * txt) { DATAPROC_IMM_SHIFT(RSB, ASR, "S"); return txt;} static char * OP_RSB_S_ASR_REG(u32 adr, u32 i, char * txt) { DATAPROC_REG_SHIFT(RSB, ASR, "S"); return txt;} static char * OP_RSB_S_ROR_IMM(u32 adr, u32 i, char * txt) { DATAPROC_ROR_IMM(RSB, "S"); return txt;} static char * OP_RSB_S_ROR_REG(u32 adr, u32 i, char * txt) { DATAPROC_REG_SHIFT(RSB, ROR, "S"); return txt;} static char * OP_RSB_S_IMM_VAL(u32 adr, u32 i, char * txt) { DATAPROC_IMM_VALUE(RSB, "S"); return txt;} //------------------ADD----------------------------------- static char * OP_ADD_LSL_IMM(u32 adr, u32 i, char * txt) { DATAPROC_LSL_IMM(ADD, ""); return txt;} static char * OP_ADD_LSL_REG(u32 adr, u32 i, char * txt) { DATAPROC_REG_SHIFT(ADD, LSL, ""); return txt;} static char * OP_ADD_LSR_IMM(u32 adr, u32 i, char * txt) { DATAPROC_IMM_SHIFT(ADD, LSR, ""); return txt;} static char * OP_ADD_LSR_REG(u32 adr, u32 i, char * txt) { DATAPROC_REG_SHIFT(ADD, LSR, ""); return txt;} static char * OP_ADD_ASR_IMM(u32 adr, u32 i, char * txt) { DATAPROC_IMM_SHIFT(ADD, ASR, ""); return txt;} static char * OP_ADD_ASR_REG(u32 adr, u32 i, char * txt) { DATAPROC_REG_SHIFT(ADD, ASR, ""); return txt;} static char * OP_ADD_ROR_IMM(u32 adr, u32 i, char * txt) { DATAPROC_ROR_IMM(ADD, ""); return txt;} static char * OP_ADD_ROR_REG(u32 adr, u32 i, char * txt) { DATAPROC_REG_SHIFT(ADD, ROR, ""); return txt;} static char * OP_ADD_IMM_VAL(u32 adr, u32 i, char * txt) { DATAPROC_IMM_VALUE(ADD, ""); return txt;} static char * OP_ADD_S_LSL_IMM(u32 adr, u32 i, char * txt) { DATAPROC_LSL_IMM(ADD, "S"); return txt;} static char * OP_ADD_S_LSL_REG(u32 adr, u32 i, char * txt) { DATAPROC_REG_SHIFT(ADD, LSL, "S"); return txt;} static char * OP_ADD_S_LSR_IMM(u32 adr, u32 i, char * txt) { DATAPROC_IMM_SHIFT(ADD, LSR, "S"); return txt;} static char * OP_ADD_S_LSR_REG(u32 adr, u32 i, char * txt) { DATAPROC_REG_SHIFT(ADD, LSR, "S"); return txt;} static char * OP_ADD_S_ASR_IMM(u32 adr, u32 i, char * txt) { DATAPROC_IMM_SHIFT(ADD, ASR, "S"); return txt;} static char * OP_ADD_S_ASR_REG(u32 adr, u32 i, char * txt) { DATAPROC_REG_SHIFT(ADD, ASR, "S"); return txt;} static char * OP_ADD_S_ROR_IMM(u32 adr, u32 i, char * txt) { DATAPROC_ROR_IMM(ADD, "S"); return txt;} static char * OP_ADD_S_ROR_REG(u32 adr, u32 i, char * txt) { DATAPROC_REG_SHIFT(ADD, ROR, "S"); return txt;} static char * OP_ADD_S_IMM_VAL(u32 adr, u32 i, char * txt) { DATAPROC_IMM_VALUE(ADD, "S"); return txt;} //------------------ADC----------------------------------- static char * OP_ADC_LSL_IMM(u32 adr, u32 i, char * txt) { DATAPROC_LSL_IMM(ADC, ""); return txt;} static char * OP_ADC_LSL_REG(u32 adr, u32 i, char * txt) { DATAPROC_REG_SHIFT(ADC, LSL, ""); return txt;} static char * OP_ADC_LSR_IMM(u32 adr, u32 i, char * txt) { DATAPROC_IMM_SHIFT(ADC, LSR, ""); return txt;} static char * OP_ADC_LSR_REG(u32 adr, u32 i, char * txt) { DATAPROC_REG_SHIFT(ADC, LSR, ""); return txt;} static char * OP_ADC_ASR_IMM(u32 adr, u32 i, char * txt) { DATAPROC_IMM_SHIFT(ADC, ASR, ""); return txt;} static char * OP_ADC_ASR_REG(u32 adr, u32 i, char * txt) { DATAPROC_REG_SHIFT(ADC, ASR, ""); return txt;} static char * OP_ADC_ROR_IMM(u32 adr, u32 i, char * txt) { DATAPROC_ROR_IMM(ADC, ""); return txt;} static char * OP_ADC_ROR_REG(u32 adr, u32 i, char * txt) { DATAPROC_REG_SHIFT(ADC, ROR, ""); return txt;} static char * OP_ADC_IMM_VAL(u32 adr, u32 i, char * txt) { DATAPROC_IMM_VALUE(ADC, ""); return txt;} static char * OP_ADC_S_LSL_IMM(u32 adr, u32 i, char * txt) { DATAPROC_LSL_IMM(ADC, "S"); return txt;} static char * OP_ADC_S_LSL_REG(u32 adr, u32 i, char * txt) { DATAPROC_REG_SHIFT(ADC, LSL, "S"); return txt;} static char * OP_ADC_S_LSR_IMM(u32 adr, u32 i, char * txt) { DATAPROC_IMM_SHIFT(ADC, LSR, "S"); return txt;} static char * OP_ADC_S_LSR_REG(u32 adr, u32 i, char * txt) { DATAPROC_REG_SHIFT(ADC, LSR, "S"); return txt;} static char * OP_ADC_S_ASR_IMM(u32 adr, u32 i, char * txt) { DATAPROC_IMM_SHIFT(ADC, ASR, "S"); return txt;} static char * OP_ADC_S_ASR_REG(u32 adr, u32 i, char * txt) { DATAPROC_REG_SHIFT(ADC, ASR, "S"); return txt;} static char * OP_ADC_S_ROR_IMM(u32 adr, u32 i, char * txt) { DATAPROC_ROR_IMM(ADC, "S"); return txt;} static char * OP_ADC_S_ROR_REG(u32 adr, u32 i, char * txt) { DATAPROC_REG_SHIFT(ADC, ROR, "S"); return txt;} static char * OP_ADC_S_IMM_VAL(u32 adr, u32 i, char * txt) { DATAPROC_IMM_VALUE(ADC, "S"); return txt;} //-------------SBC------------------------------------- static char * OP_SBC_LSL_IMM(u32 adr, u32 i, char * txt) { DATAPROC_LSL_IMM(SBC, ""); return txt;} static char * OP_SBC_LSL_REG(u32 adr, u32 i, char * txt) { DATAPROC_REG_SHIFT(SBC, LSL, ""); return txt;} static char * OP_SBC_LSR_IMM(u32 adr, u32 i, char * txt) { DATAPROC_IMM_SHIFT(SBC, LSR, ""); return txt;} static char * OP_SBC_LSR_REG(u32 adr, u32 i, char * txt) { DATAPROC_REG_SHIFT(SBC, LSR, ""); return txt;} static char * OP_SBC_ASR_IMM(u32 adr, u32 i, char * txt) { DATAPROC_IMM_SHIFT(SBC, ASR, ""); return txt;} static char * OP_SBC_ASR_REG(u32 adr, u32 i, char * txt) { DATAPROC_REG_SHIFT(SBC, ASR, ""); return txt;} static char * OP_SBC_ROR_IMM(u32 adr, u32 i, char * txt) { DATAPROC_ROR_IMM(SBC, ""); return txt;} static char * OP_SBC_ROR_REG(u32 adr, u32 i, char * txt) { DATAPROC_REG_SHIFT(SBC, ROR, ""); return txt;} static char * OP_SBC_IMM_VAL(u32 adr, u32 i, char * txt) { DATAPROC_IMM_VALUE(SBC, ""); return txt;} static char * OP_SBC_S_LSL_IMM(u32 adr, u32 i, char * txt) { DATAPROC_LSL_IMM(SBC, "S"); return txt;} static char * OP_SBC_S_LSL_REG(u32 adr, u32 i, char * txt) { DATAPROC_REG_SHIFT(SBC, LSL, "S"); return txt;} static char * OP_SBC_S_LSR_IMM(u32 adr, u32 i, char * txt) { DATAPROC_IMM_SHIFT(SBC, LSR, "S"); return txt;} static char * OP_SBC_S_LSR_REG(u32 adr, u32 i, char * txt) { DATAPROC_REG_SHIFT(SBC, LSR, "S"); return txt;} static char * OP_SBC_S_ASR_IMM(u32 adr, u32 i, char * txt) { DATAPROC_IMM_SHIFT(SBC, ASR, "S"); return txt;} static char * OP_SBC_S_ASR_REG(u32 adr, u32 i, char * txt) { DATAPROC_REG_SHIFT(SBC, ASR, "S"); return txt;} static char * OP_SBC_S_ROR_IMM(u32 adr, u32 i, char * txt) { DATAPROC_ROR_IMM(SBC, "S"); return txt;} static char * OP_SBC_S_ROR_REG(u32 adr, u32 i, char * txt) { DATAPROC_REG_SHIFT(SBC, ROR, "S"); return txt;} static char * OP_SBC_S_IMM_VAL(u32 adr, u32 i, char * txt) { DATAPROC_IMM_VALUE(SBC, "S"); return txt;} //---------------RSC---------------------------------- static char * OP_RSC_LSL_IMM(u32 adr, u32 i, char * txt) { DATAPROC_LSL_IMM(RSC, ""); return txt;} static char * OP_RSC_LSL_REG(u32 adr, u32 i, char * txt) { DATAPROC_REG_SHIFT(RSC, LSL, ""); return txt;} static char * OP_RSC_LSR_IMM(u32 adr, u32 i, char * txt) { DATAPROC_IMM_SHIFT(RSC, LSR, ""); return txt;} static char * OP_RSC_LSR_REG(u32 adr, u32 i, char * txt) { DATAPROC_REG_SHIFT(RSC, LSR, ""); return txt;} static char * OP_RSC_ASR_IMM(u32 adr, u32 i, char * txt) { DATAPROC_IMM_SHIFT(RSC, ASR, ""); return txt;} static char * OP_RSC_ASR_REG(u32 adr, u32 i, char * txt) { DATAPROC_REG_SHIFT(RSC, ASR, ""); return txt;} static char * OP_RSC_ROR_IMM(u32 adr, u32 i, char * txt) { DATAPROC_ROR_IMM(RSC, ""); return txt;} static char * OP_RSC_ROR_REG(u32 adr, u32 i, char * txt) { DATAPROC_REG_SHIFT(RSC, ROR, ""); return txt;} static char * OP_RSC_IMM_VAL(u32 adr, u32 i, char * txt) { DATAPROC_IMM_VALUE(RSC, ""); return txt;} static char * OP_RSC_S_LSL_IMM(u32 adr, u32 i, char * txt) { DATAPROC_LSL_IMM(RSC, "S"); return txt;} static char * OP_RSC_S_LSL_REG(u32 adr, u32 i, char * txt) { DATAPROC_REG_SHIFT(RSC, LSL, "S"); return txt;} static char * OP_RSC_S_LSR_IMM(u32 adr, u32 i, char * txt) { DATAPROC_IMM_SHIFT(RSC, LSR, "S"); return txt;} static char * OP_RSC_S_LSR_REG(u32 adr, u32 i, char * txt) { DATAPROC_REG_SHIFT(RSC, LSR, "S"); return txt;} static char * OP_RSC_S_ASR_IMM(u32 adr, u32 i, char * txt) { DATAPROC_IMM_SHIFT(RSC, ASR, "S"); return txt;} static char * OP_RSC_S_ASR_REG(u32 adr, u32 i, char * txt) { DATAPROC_REG_SHIFT(RSC, ASR, "S"); return txt;} static char * OP_RSC_S_ROR_IMM(u32 adr, u32 i, char * txt) { DATAPROC_ROR_IMM(RSC, "S"); return txt;} static char * OP_RSC_S_ROR_REG(u32 adr, u32 i, char * txt) { DATAPROC_REG_SHIFT(RSC, ROR, "S"); return txt;} static char * OP_RSC_S_IMM_VAL(u32 adr, u32 i, char * txt) { DATAPROC_IMM_VALUE(RSC, "S"); return txt;} //-------------------TST---------------------------- static char * OP_TST_LSL_IMM(u32 adr, u32 i, char * txt) { DATAPROC_ONE_OP_LSL_IMM(TST, "", 16); return txt;} static char * OP_TST_LSL_REG(u32 adr, u32 i, char * txt) { DATAPROC_ONE_OP_REG_SHIFT(TST, LSL, "", 16); return txt;} static char * OP_TST_LSR_IMM(u32 adr, u32 i, char * txt) { DATAPROC_ONE_OP_IMM_SHIFT(TST, LSR, "", 16); return txt;} static char * OP_TST_LSR_REG(u32 adr, u32 i, char * txt) { DATAPROC_ONE_OP_REG_SHIFT(TST, LSR, "", 16); return txt;} static char * OP_TST_ASR_IMM(u32 adr, u32 i, char * txt) { DATAPROC_ONE_OP_IMM_SHIFT(TST, ASR, "", 16); return txt;} static char * OP_TST_ASR_REG(u32 adr, u32 i, char * txt) { DATAPROC_ONE_OP_REG_SHIFT(TST, ASR, "", 16); return txt;} static char * OP_TST_ROR_IMM(u32 adr, u32 i, char * txt) { DATAPROC_ONE_OP_ROR_IMM(TST, "", 16); return txt;} static char * OP_TST_ROR_REG(u32 adr, u32 i, char * txt) { DATAPROC_ONE_OP_REG_SHIFT(TST, ROR, "", 16); return txt;} static char * OP_TST_IMM_VAL(u32 adr, u32 i, char * txt) { DATAPROC_ONE_OP_IMM_VALUE(TST, "", 16); return txt;} //-------------------TEQ---------------------------- static char * OP_TEQ_LSL_IMM(u32 adr, u32 i, char * txt) { DATAPROC_ONE_OP_LSL_IMM(TEQ, "", 16); return txt;} static char * OP_TEQ_LSL_REG(u32 adr, u32 i, char * txt) { DATAPROC_ONE_OP_REG_SHIFT(TEQ, LSL, "", 16); return txt;} static char * OP_TEQ_LSR_IMM(u32 adr, u32 i, char * txt) { DATAPROC_ONE_OP_IMM_SHIFT(TEQ, LSR, "", 16); return txt;} static char * OP_TEQ_LSR_REG(u32 adr, u32 i, char * txt) { DATAPROC_ONE_OP_REG_SHIFT(TEQ, LSR, "", 16); return txt;} static char * OP_TEQ_ASR_IMM(u32 adr, u32 i, char * txt) { DATAPROC_ONE_OP_IMM_SHIFT(TEQ, ASR, "", 16); return txt;} static char * OP_TEQ_ASR_REG(u32 adr, u32 i, char * txt) { DATAPROC_ONE_OP_REG_SHIFT(TEQ, ASR, "", 16); return txt;} static char * OP_TEQ_ROR_IMM(u32 adr, u32 i, char * txt) { DATAPROC_ONE_OP_ROR_IMM(TEQ, "", 16); return txt;} static char * OP_TEQ_ROR_REG(u32 adr, u32 i, char * txt) { DATAPROC_ONE_OP_REG_SHIFT(TEQ, ROR, "", 16); return txt;} static char * OP_TEQ_IMM_VAL(u32 adr, u32 i, char * txt) { DATAPROC_ONE_OP_IMM_VALUE(TEQ, "", 16); return txt;} //-------------CMP------------------------------------- static char * OP_CMP_LSL_IMM(u32 adr, u32 i, char * txt) { DATAPROC_ONE_OP_LSL_IMM(CMP, "", 16); return txt;} static char * OP_CMP_LSL_REG(u32 adr, u32 i, char * txt) { DATAPROC_ONE_OP_REG_SHIFT(CMP, LSL, "", 16); return txt;} static char * OP_CMP_LSR_IMM(u32 adr, u32 i, char * txt) { DATAPROC_ONE_OP_IMM_SHIFT(CMP, LSR, "", 16); return txt;} static char * OP_CMP_LSR_REG(u32 adr, u32 i, char * txt) { DATAPROC_ONE_OP_REG_SHIFT(CMP, LSR, "", 16); return txt;} static char * OP_CMP_ASR_IMM(u32 adr, u32 i, char * txt) { DATAPROC_ONE_OP_IMM_SHIFT(CMP, ASR, "", 16); return txt;} static char * OP_CMP_ASR_REG(u32 adr, u32 i, char * txt) { DATAPROC_ONE_OP_REG_SHIFT(CMP, ASR, "", 16); return txt;} static char * OP_CMP_ROR_IMM(u32 adr, u32 i, char * txt) { DATAPROC_ONE_OP_ROR_IMM(CMP, "", 16); return txt;} static char * OP_CMP_ROR_REG(u32 adr, u32 i, char * txt) { DATAPROC_ONE_OP_REG_SHIFT(CMP, ROR, "", 16); return txt;} static char * OP_CMP_IMM_VAL(u32 adr, u32 i, char * txt) { DATAPROC_ONE_OP_IMM_VALUE(CMP, "", 16); return txt;} //---------------CMN--------------------------- static char * OP_CMN_LSL_IMM(u32 adr, u32 i, char * txt) { DATAPROC_ONE_OP_LSL_IMM(CMN, "", 16); return txt;} static char * OP_CMN_LSL_REG(u32 adr, u32 i, char * txt) { DATAPROC_ONE_OP_REG_SHIFT(CMN, LSL, "", 16); return txt;} static char * OP_CMN_LSR_IMM(u32 adr, u32 i, char * txt) { DATAPROC_ONE_OP_IMM_SHIFT(CMP, ASR, "", 16); return txt;} static char * OP_CMN_LSR_REG(u32 adr, u32 i, char * txt) { DATAPROC_ONE_OP_REG_SHIFT(CMN, LSR, "", 16); return txt;} static char * OP_CMN_ASR_IMM(u32 adr, u32 i, char * txt) { DATAPROC_ONE_OP_IMM_SHIFT(CMN, ASR, "", 16); return txt;} static char * OP_CMN_ASR_REG(u32 adr, u32 i, char * txt) { DATAPROC_ONE_OP_REG_SHIFT(CMN, ASR, "", 16); return txt;} static char * OP_CMN_ROR_IMM(u32 adr, u32 i, char * txt) { DATAPROC_ONE_OP_ROR_IMM(CMN, "", 16); return txt;} static char * OP_CMN_ROR_REG(u32 adr, u32 i, char * txt) { DATAPROC_ONE_OP_REG_SHIFT(CMN, ROR, "", 16); return txt;} static char * OP_CMN_IMM_VAL(u32 adr, u32 i, char * txt) { DATAPROC_ONE_OP_IMM_VALUE(CMN, "", 16); return txt;} //------------------ORR------------------- static char * OP_ORR_LSL_IMM(u32 adr, u32 i, char * txt) { DATAPROC_LSL_IMM(ORR, ""); return txt;} static char * OP_ORR_LSL_REG(u32 adr, u32 i, char * txt) { DATAPROC_REG_SHIFT(ORR, LSL, ""); return txt;} static char * OP_ORR_LSR_IMM(u32 adr, u32 i, char * txt) { DATAPROC_IMM_SHIFT(ORR, LSR, ""); return txt;} static char * OP_ORR_LSR_REG(u32 adr, u32 i, char * txt) { DATAPROC_REG_SHIFT(ORR, LSR, ""); return txt;} static char * OP_ORR_ASR_IMM(u32 adr, u32 i, char * txt) { DATAPROC_IMM_SHIFT(ORR, ASR, ""); return txt;} static char * OP_ORR_ASR_REG(u32 adr, u32 i, char * txt) { DATAPROC_REG_SHIFT(ORR, ASR, ""); return txt;} static char * OP_ORR_ROR_IMM(u32 adr, u32 i, char * txt) { DATAPROC_ROR_IMM(ORR, ""); return txt;} static char * OP_ORR_ROR_REG(u32 adr, u32 i, char * txt) { DATAPROC_REG_SHIFT(ORR, ROR, ""); return txt;} static char * OP_ORR_IMM_VAL(u32 adr, u32 i, char * txt) { DATAPROC_IMM_VALUE(ORR, ""); return txt;} static char * OP_ORR_S_LSL_IMM(u32 adr, u32 i, char * txt) { DATAPROC_LSL_IMM(ORR, "S"); return txt;} static char * OP_ORR_S_LSL_REG(u32 adr, u32 i, char * txt) { DATAPROC_REG_SHIFT(ORR, LSL, "S"); return txt;} static char * OP_ORR_S_LSR_IMM(u32 adr, u32 i, char * txt) { DATAPROC_IMM_SHIFT(ORR, LSR, "S"); return txt;} static char * OP_ORR_S_LSR_REG(u32 adr, u32 i, char * txt) { DATAPROC_REG_SHIFT(ORR, LSR, "S"); return txt;} static char * OP_ORR_S_ASR_IMM(u32 adr, u32 i, char * txt) { DATAPROC_IMM_SHIFT(ORR, ASR, "S"); return txt;} static char * OP_ORR_S_ASR_REG(u32 adr, u32 i, char * txt) { DATAPROC_REG_SHIFT(ORR, ASR, "S"); return txt;} static char * OP_ORR_S_ROR_IMM(u32 adr, u32 i, char * txt) { DATAPROC_ROR_IMM(ORR, "S"); return txt;} static char * OP_ORR_S_ROR_REG(u32 adr, u32 i, char * txt) { DATAPROC_REG_SHIFT(ORR, ROR, "S"); return txt;} static char * OP_ORR_S_IMM_VAL(u32 adr, u32 i, char * txt) { DATAPROC_IMM_VALUE(ORR, "S"); return txt;} //------------------MOV------------------- static char * OP_MOV_LSL_IMM(u32 adr, u32 i, char * txt) { DATAPROC_ONE_OP_LSL_IMM(MOV, "", 12); return txt;} static char * OP_MOV_LSL_REG(u32 adr, u32 i, char * txt) { DATAPROC_ONE_OP_REG_SHIFT(MOV, LSL, "", 12); return txt;} static char * OP_MOV_LSR_IMM(u32 adr, u32 i, char * txt) { DATAPROC_ONE_OP_IMM_SHIFT(MOV, LSR, "", 12); return txt;} static char * OP_MOV_LSR_REG(u32 adr, u32 i, char * txt) { DATAPROC_ONE_OP_REG_SHIFT(MOV, LSR, "", 12); return txt;} static char * OP_MOV_ASR_IMM(u32 adr, u32 i, char * txt) { DATAPROC_ONE_OP_IMM_SHIFT(MOV, ASR, "", 12); return txt;} static char * OP_MOV_ASR_REG(u32 adr, u32 i, char * txt) { DATAPROC_ONE_OP_REG_SHIFT(MOV, ASR, "", 12); return txt;} static char * OP_MOV_ROR_IMM(u32 adr, u32 i, char * txt) { DATAPROC_ONE_OP_ROR_IMM(MOV, "", 12); return txt;} static char * OP_MOV_ROR_REG(u32 adr, u32 i, char * txt) { DATAPROC_ONE_OP_REG_SHIFT(MOV, ROR, "", 12); return txt;} static char * OP_MOV_IMM_VAL(u32 adr, u32 i, char * txt) { DATAPROC_ONE_OP_IMM_VALUE(MOV, "", 12); return txt;} static char * OP_MOV_S_LSL_IMM(u32 adr, u32 i, char * txt) { DATAPROC_ONE_OP_LSL_IMM(MOV, "S", 12); return txt;} static char * OP_MOV_S_LSL_REG(u32 adr, u32 i, char * txt) { DATAPROC_ONE_OP_REG_SHIFT(MOV, LSL, "S", 12); return txt;} static char * OP_MOV_S_LSR_IMM(u32 adr, u32 i, char * txt) { DATAPROC_ONE_OP_IMM_SHIFT(MOV, LSR, "S", 12); return txt;} static char * OP_MOV_S_LSR_REG(u32 adr, u32 i, char * txt) { DATAPROC_ONE_OP_REG_SHIFT(MOV, LSR, "S", 12); return txt;} static char * OP_MOV_S_ASR_IMM(u32 adr, u32 i, char * txt) { DATAPROC_ONE_OP_IMM_SHIFT(MOV, ASR, "S", 12); return txt;} static char * OP_MOV_S_ASR_REG(u32 adr, u32 i, char * txt) { DATAPROC_ONE_OP_REG_SHIFT(MOV, ASR, "S", 12); return txt;} static char * OP_MOV_S_ROR_IMM(u32 adr, u32 i, char * txt) { DATAPROC_ONE_OP_ROR_IMM(MOV, "S", 12); return txt;} static char * OP_MOV_S_ROR_REG(u32 adr, u32 i, char * txt) { DATAPROC_ONE_OP_REG_SHIFT(MOV, ROR, "S", 12); return txt;} static char * OP_MOV_S_IMM_VAL(u32 adr, u32 i, char * txt) { DATAPROC_ONE_OP_IMM_VALUE(MOV, "S", 12); return txt;} //------------------BIC------------------- static char * OP_BIC_LSL_IMM(u32 adr, u32 i, char * txt) { DATAPROC_LSL_IMM(BIC, ""); return txt;} static char * OP_BIC_LSL_REG(u32 adr, u32 i, char * txt) { DATAPROC_REG_SHIFT(BIC, LSL, ""); return txt;} static char * OP_BIC_LSR_IMM(u32 adr, u32 i, char * txt) { DATAPROC_IMM_SHIFT(BIC, LSR, ""); return txt;} static char * OP_BIC_LSR_REG(u32 adr, u32 i, char * txt) { DATAPROC_REG_SHIFT(BIC, LSR, ""); return txt;} static char * OP_BIC_ASR_IMM(u32 adr, u32 i, char * txt) { DATAPROC_IMM_SHIFT(BIC, ASR, ""); return txt;} static char * OP_BIC_ASR_REG(u32 adr, u32 i, char * txt) { DATAPROC_REG_SHIFT(BIC, ASR, ""); return txt;} static char * OP_BIC_ROR_IMM(u32 adr, u32 i, char * txt) { DATAPROC_ROR_IMM(BIC, ""); return txt;} static char * OP_BIC_ROR_REG(u32 adr, u32 i, char * txt) { DATAPROC_REG_SHIFT(BIC, ROR, ""); return txt;} static char * OP_BIC_IMM_VAL(u32 adr, u32 i, char * txt) { DATAPROC_IMM_VALUE(BIC, ""); return txt;} static char * OP_BIC_S_LSL_IMM(u32 adr, u32 i, char * txt) { DATAPROC_LSL_IMM(BIC, "S"); return txt;} static char * OP_BIC_S_LSL_REG(u32 adr, u32 i, char * txt) { DATAPROC_REG_SHIFT(BIC, LSL, "S"); return txt;} static char * OP_BIC_S_LSR_IMM(u32 adr, u32 i, char * txt) { DATAPROC_IMM_SHIFT(BIC, LSR, "S"); return txt;} static char * OP_BIC_S_LSR_REG(u32 adr, u32 i, char * txt) { DATAPROC_REG_SHIFT(BIC, LSR, "S"); return txt;} static char * OP_BIC_S_ASR_IMM(u32 adr, u32 i, char * txt) { DATAPROC_IMM_SHIFT(BIC, ASR, "S"); return txt;} static char * OP_BIC_S_ASR_REG(u32 adr, u32 i, char * txt) { DATAPROC_REG_SHIFT(BIC, ASR, "S"); return txt;} static char * OP_BIC_S_ROR_IMM(u32 adr, u32 i, char * txt) { DATAPROC_ROR_IMM(BIC, "S"); return txt;} static char * OP_BIC_S_ROR_REG(u32 adr, u32 i, char * txt) { DATAPROC_REG_SHIFT(BIC, ROR, "S"); return txt;} static char * OP_BIC_S_IMM_VAL(u32 adr, u32 i, char * txt) { DATAPROC_IMM_VALUE(BIC, "S"); return txt;} //------------------MVN------------------- static char * OP_MVN_LSL_IMM(u32 adr, u32 i, char * txt) { DATAPROC_ONE_OP_LSL_IMM(MVN, "", 12); return txt;} static char * OP_MVN_LSL_REG(u32 adr, u32 i, char * txt) { DATAPROC_ONE_OP_REG_SHIFT(MVN, LSL, "", 12); return txt;} static char * OP_MVN_LSR_IMM(u32 adr, u32 i, char * txt) { DATAPROC_ONE_OP_IMM_SHIFT(MVN, LSR, "", 12); return txt;} static char * OP_MVN_LSR_REG(u32 adr, u32 i, char * txt) { DATAPROC_ONE_OP_REG_SHIFT(MVN, LSR, "", 12); return txt;} static char * OP_MVN_ASR_IMM(u32 adr, u32 i, char * txt) { DATAPROC_ONE_OP_IMM_SHIFT(MVN, ASR, "", 12); return txt;} static char * OP_MVN_ASR_REG(u32 adr, u32 i, char * txt) { DATAPROC_ONE_OP_REG_SHIFT(MVN, ASR, "", 12); return txt;} static char * OP_MVN_ROR_IMM(u32 adr, u32 i, char * txt) { DATAPROC_ONE_OP_ROR_IMM(MVN, "", 12); return txt;} static char * OP_MVN_ROR_REG(u32 adr, u32 i, char * txt) { DATAPROC_ONE_OP_REG_SHIFT(MVN, ROR, "", 12); return txt;} static char * OP_MVN_IMM_VAL(u32 adr, u32 i, char * txt) { DATAPROC_ONE_OP_IMM_VALUE(MVN, "", 12); return txt;} static char * OP_MVN_S_LSL_IMM(u32 adr, u32 i, char * txt) { DATAPROC_ONE_OP_LSL_IMM(MVN, "S", 12); return txt;} static char * OP_MVN_S_LSL_REG(u32 adr, u32 i, char * txt) { DATAPROC_ONE_OP_REG_SHIFT(MVN, LSL, "S", 12); return txt;} static char * OP_MVN_S_LSR_IMM(u32 adr, u32 i, char * txt) { DATAPROC_ONE_OP_IMM_SHIFT(MVN, LSR, "S", 12); return txt;} static char * OP_MVN_S_LSR_REG(u32 adr, u32 i, char * txt) { DATAPROC_ONE_OP_REG_SHIFT(MVN, LSR, "S", 12); return txt;} static char * OP_MVN_S_ASR_IMM(u32 adr, u32 i, char * txt) { DATAPROC_ONE_OP_IMM_SHIFT(MOV, ASR, "S", 12); return txt;} static char * OP_MVN_S_ASR_REG(u32 adr, u32 i, char * txt) { DATAPROC_ONE_OP_REG_SHIFT(MVN, ASR, "S", 12); return txt;} static char * OP_MVN_S_ROR_IMM(u32 adr, u32 i, char * txt) { DATAPROC_ONE_OP_ROR_IMM(MVN, "S", 12); return txt;} static char * OP_MVN_S_ROR_REG(u32 adr, u32 i, char * txt) { DATAPROC_ONE_OP_REG_SHIFT(MVN, ROR, "S", 12); return txt;} static char * OP_MVN_S_IMM_VAL(u32 adr, u32 i, char * txt) { DATAPROC_ONE_OP_IMM_VALUE(MVN, "S", 12); return txt;} //-------------MUL------------------------ static char * OP_MUL(u32 adr, u32 i, char * txt) { sprintf(txt, "MUL%s %s, %s, %s", Condition[CONDITION(i)], Registre[REG_POS(i,16)], Registre[REG_POS(i,0)], Registre[REG_POS(i,8)]); return txt;} static char * OP_MLA(u32 adr, u32 i, char * txt) { sprintf(txt, "MLA%s %s, %s, %s, %s", Condition[CONDITION(i)], Registre[REG_POS(i,16)], Registre[REG_POS(i,0)], Registre[REG_POS(i,8)], Registre[REG_POS(i,12)]); return txt;} static char * OP_MUL_S(u32 adr, u32 i, char * txt) { sprintf(txt, "MUL%sS %s, %s, %s", Condition[CONDITION(i)], Registre[REG_POS(i,16)], Registre[REG_POS(i,0)], Registre[REG_POS(i,8)]); return txt;} static char * OP_MLA_S(u32 adr, u32 i, char * txt) { sprintf(txt, "MLA%sS %s, %s, %s, %s", Condition[CONDITION(i)], Registre[REG_POS(i,16)], Registre[REG_POS(i,0)], Registre[REG_POS(i,8)], Registre[REG_POS(i,12)]); return txt;} //----------UMUL-------------------------- static char * OP_UMULL(u32 adr, u32 i, char * txt) { sprintf(txt, "UMULL%s %s, %s, %s, %s", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], Registre[REG_POS(i,0)], Registre[REG_POS(i,8)]); return txt;} static char * OP_UMLAL(u32 adr, u32 i, char * txt) { sprintf(txt, "UMLAL%s %s, %s, %s, %s", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], Registre[REG_POS(i,0)], Registre[REG_POS(i,8)]); return txt;} static char * OP_UMULL_S(u32 adr, u32 i, char * txt) { sprintf(txt, "UMULL%sS %s, %s, %s, %s", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], Registre[REG_POS(i,0)], Registre[REG_POS(i,8)]); return txt;} static char * OP_UMLAL_S(u32 adr, u32 i, char * txt) { sprintf(txt, "UMLAL%sS %s, %s, %s, %s", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], Registre[REG_POS(i,0)], Registre[REG_POS(i,8)]); return txt;} //----------SMUL-------------------------- static char * OP_SMULL(u32 adr, u32 i, char * txt) { sprintf(txt, "SMULL%s %s, %s, %s, %s", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], Registre[REG_POS(i,0)], Registre[REG_POS(i,8)]); return txt;} static char * OP_SMLAL(u32 adr, u32 i, char * txt) { sprintf(txt, "SMLAL%s %s, %s, %s, %s", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], Registre[REG_POS(i,0)], Registre[REG_POS(i,8)]); return txt;} static char * OP_SMULL_S(u32 adr, u32 i, char * txt) { sprintf(txt, "SMULL%sS %s, %s, %s, %s", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], Registre[REG_POS(i,0)], Registre[REG_POS(i,8)]); return txt;} static char * OP_SMLAL_S(u32 adr, u32 i, char * txt) { sprintf(txt, "SMLAL%sS %s, %s, %s, %s", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], Registre[REG_POS(i,0)], Registre[REG_POS(i,8)]); return txt;} //---------------SWP------------------------------ static char * OP_SWP(u32 adr, u32 i, char * txt) { sprintf(txt, "SWP%s %s, %s, [%s]", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,0)], Registre[REG_POS(i,16)]); return txt;} static char * OP_SWPB(u32 adr, u32 i, char * txt) { sprintf(txt, "SWPB%s %s, %s, [%s]", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,0)], Registre[REG_POS(i,16)]); return txt;} //------------LDRH----------------------------- static char * OP_LDRH_P_IMM_OFF(u32 adr, u32 i, char * txt) { sprintf(txt, "LDRH%s %s, [%s, #%X]", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], (int)(((i>>4)&0xF0)|(i&0xF))); return txt;} static char * OP_LDRH_M_IMM_OFF(u32 adr, u32 i, char * txt) { sprintf(txt, "LDRH%s %s, [%s, -#%X]", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], (int)(((i>>4)&0xF0)|(i&0xF))); return txt;} static char * OP_LDRH_P_REG_OFF(u32 adr, u32 i, char * txt) { sprintf(txt, "LDRH%s %s, [%s, %s]", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], Registre[REG_POS(i,0)]); return txt;} static char * OP_LDRH_M_REG_OFF(u32 adr, u32 i, char * txt) { sprintf(txt, "LDRH%s %s, [%s, -%s]", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], Registre[REG_POS(i,0)]); return txt;} static char * OP_LDRH_PRE_INDE_P_IMM_OFF(u32 adr, u32 i, char * txt) { sprintf(txt, "LDRH%s %s, [%s, #%X]!", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], (int)(((i>>4)&0xF0)|(i&0xF))); return txt;} static char * OP_LDRH_PRE_INDE_M_IMM_OFF(u32 adr, u32 i, char * txt) { sprintf(txt, "LDRH%s %s, [%s, -#%X]!", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], (int)(((i>>4)&0xF0)|(i&0xF))); return txt;} static char * OP_LDRH_PRE_INDE_P_REG_OFF(u32 adr, u32 i, char * txt) { sprintf(txt, "LDRH%s %s, [%s, %s]!", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], Registre[REG_POS(i,0)]); return txt;} static char * OP_LDRH_PRE_INDE_M_REG_OFF(u32 adr, u32 i, char * txt) { sprintf(txt, "LDRH%s %s, [%s, -%s]!", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], Registre[REG_POS(i,0)]); return txt;} static char * OP_LDRH_POS_INDE_P_IMM_OFF(u32 adr, u32 i, char * txt) { sprintf(txt, "LDRH%s %s, [%s], #%X", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], (int)(((i>>4)&0xF0)|(i&0xF))); return txt;} static char * OP_LDRH_POS_INDE_M_IMM_OFF(u32 adr, u32 i, char * txt) { sprintf(txt, "LDRH%s %s, [%s], -#%X", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], (int)(((i>>4)&0xF0)|(i&0xF))); return txt;} static char * OP_LDRH_POS_INDE_P_REG_OFF(u32 adr, u32 i, char * txt) { sprintf(txt, "LDRH%s %s, [%s], %s", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], Registre[REG_POS(i,0)]); return txt;} static char * OP_LDRH_POS_INDE_M_REG_OFF(u32 adr, u32 i, char * txt) { sprintf(txt, "LDRH%s %s, [%s], -%s", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], Registre[REG_POS(i,0)]); return txt;} //------------STRH----------------------------- static char * OP_STRH_P_IMM_OFF(u32 adr, u32 i, char * txt) { sprintf(txt, "STRH%s %s, [%s, #%X]", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], (int)(((i>>4)&0xF0)|(i&0xF))); return txt;} static char * OP_STRH_M_IMM_OFF(u32 adr, u32 i, char * txt) { sprintf(txt, "STRH%s %s, [%s, -#%X]", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], (int)(((i>>4)&0xF0)|(i&0xF))); return txt;} static char * OP_STRH_P_REG_OFF(u32 adr, u32 i, char * txt) { sprintf(txt, "STRH%s %s, [%s, %s]", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], Registre[REG_POS(i,0)]); return txt;} static char * OP_STRH_M_REG_OFF(u32 adr, u32 i, char * txt) { sprintf(txt, "STRH%s %s, [%s, -%s]", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], Registre[REG_POS(i,0)]); return txt;} static char * OP_STRH_PRE_INDE_P_IMM_OFF(u32 adr, u32 i, char * txt) { sprintf(txt, "STRH%s %s, [%s, #%X]!", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], (int)(((i>>4)&0xF0)|(i&0xF))); return txt;} static char * OP_STRH_PRE_INDE_M_IMM_OFF(u32 adr, u32 i, char * txt) { sprintf(txt, "STRH%s %s, [%s, -#%X]!", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], (int)(((i>>4)&0xF0)|(i&0xF))); return txt;} static char * OP_STRH_PRE_INDE_P_REG_OFF(u32 adr, u32 i, char * txt) { sprintf(txt, "STRH%s %s, [%s, %s]!", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], Registre[REG_POS(i,0)]); return txt;} static char * OP_STRH_PRE_INDE_M_REG_OFF(u32 adr, u32 i, char * txt) { sprintf(txt, "STRH%s %s, [%s, -%s]!", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], Registre[REG_POS(i,0)]); return txt;} static char * OP_STRH_POS_INDE_P_IMM_OFF(u32 adr, u32 i, char * txt) { sprintf(txt, "STRH%s %s, [%s], #%X", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], (int)(((i>>4)&0xF0)|(i&0xF))); return txt;} static char * OP_STRH_POS_INDE_M_IMM_OFF(u32 adr, u32 i, char * txt) { sprintf(txt, "STRH%s %s, [%s], -#%X", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], (int)(((i>>4)&0xF0)|(i&0xF))); return txt;} static char * OP_STRH_POS_INDE_P_REG_OFF(u32 adr, u32 i, char * txt) { sprintf(txt, "STRH%s %s, [%s], %s", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], Registre[REG_POS(i,0)]); return txt;} static char * OP_STRH_POS_INDE_M_REG_OFF(u32 adr, u32 i, char * txt) { sprintf(txt, "STRH%s %s, [%s], -%s", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], Registre[REG_POS(i,0)]); return txt;} //----------------LDRSH-------------------------- static char * OP_LDRSH_P_IMM_OFF(u32 adr, u32 i, char * txt) { sprintf(txt, "LDRSH%s %s, [%s, #%X]", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], (int)(((i>>4)&0xF0)|(i&0xF))); return txt;} static char * OP_LDRSH_M_IMM_OFF(u32 adr, u32 i, char * txt) { sprintf(txt, "LDRSH%s %s, [%s, -#%X]", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], (int)(((i>>4)&0xF0)|(i&0xF))); return txt;} static char * OP_LDRSH_P_REG_OFF(u32 adr, u32 i, char * txt) { sprintf(txt, "LDRSH%s %s, [%s, %s]", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], Registre[REG_POS(i,0)]); return txt;} static char * OP_LDRSH_M_REG_OFF(u32 adr, u32 i, char * txt) { sprintf(txt, "LDRSH%s %s, [%s, -%s]", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], Registre[REG_POS(i,0)]); return txt;} static char * OP_LDRSH_PRE_INDE_P_IMM_OFF(u32 adr, u32 i, char * txt) { sprintf(txt, "LDRSH%s %s, [%s, #%X]!", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], (int)(((i>>4)&0xF0)|(i&0xF))); return txt;} static char * OP_LDRSH_PRE_INDE_M_IMM_OFF(u32 adr, u32 i, char * txt) { sprintf(txt, "LDRSH%s %s, [%s, -#%X]!", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], (int)(((i>>4)&0xF0)|(i&0xF))); return txt;} static char * OP_LDRSH_PRE_INDE_P_REG_OFF(u32 adr, u32 i, char * txt) { sprintf(txt, "LDRSH%s %s, [%s, %s]!", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], Registre[REG_POS(i,0)]); return txt;} static char * OP_LDRSH_PRE_INDE_M_REG_OFF(u32 adr, u32 i, char * txt) { sprintf(txt, "LDRSH%s %s, [%s, -%s]!", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], Registre[REG_POS(i,0)]); return txt;} static char * OP_LDRSH_POS_INDE_P_IMM_OFF(u32 adr, u32 i, char * txt) { sprintf(txt, "LDRSH%s %s, [%s], #%X", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], (int)(((i>>4)&0xF0)|(i&0xF))); return txt;} static char * OP_LDRSH_POS_INDE_M_IMM_OFF(u32 adr, u32 i, char * txt) { sprintf(txt, "LDRSH%s %s, [%s], -#%X", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], (int)(((i>>4)&0xF0)|(i&0xF))); return txt;} static char * OP_LDRSH_POS_INDE_P_REG_OFF(u32 adr, u32 i, char * txt) { sprintf(txt, "LDRSH%s %s, [%s], %s", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], Registre[REG_POS(i,0)]); return txt;} static char * OP_LDRSH_POS_INDE_M_REG_OFF(u32 adr, u32 i, char * txt) { sprintf(txt, "LDRSH%s %s, [%s], -%s", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], Registre[REG_POS(i,0)]); return txt;} //----------------------LDRSB---------------------- static char * OP_LDRSB_P_IMM_OFF(u32 adr, u32 i, char * txt) { sprintf(txt, "LDRSB%s %s, [%s, #%X]", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], (int)(((i>>4)&0xF0)|(i&0xF))); return txt;} static char * OP_LDRSB_M_IMM_OFF(u32 adr, u32 i, char * txt) { sprintf(txt, "LDRSB%s %s, [%s, -#%X]", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], (int)(((i>>4)&0xF0)|(i&0xF))); return txt;} static char * OP_LDRSB_P_REG_OFF(u32 adr, u32 i, char * txt) { sprintf(txt, "LDRSB%s %s, [%s, %s]", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], Registre[REG_POS(i,0)]); return txt;} static char * OP_LDRSB_M_REG_OFF(u32 adr, u32 i, char * txt) { sprintf(txt, "LDRSB%s %s, [%s, -%s]", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], Registre[REG_POS(i,0)]); return txt;} static char * OP_LDRSB_PRE_INDE_P_IMM_OFF(u32 adr, u32 i, char * txt) { sprintf(txt, "LDRSB%s %s, [%s, #%X]!", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], (int)(((i>>4)&0xF0)|(i&0xF))); return txt;} static char * OP_LDRSB_PRE_INDE_M_IMM_OFF(u32 adr, u32 i, char * txt) { sprintf(txt, "LDRSB%s %s, [%s, -#%X]!", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], (int)(((i>>4)&0xF0)|(i&0xF))); return txt;} static char * OP_LDRSB_PRE_INDE_P_REG_OFF(u32 adr, u32 i, char * txt) { sprintf(txt, "LDRSB%s %s, [%s, %s]!", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], Registre[REG_POS(i,0)]); return txt;} static char * OP_LDRSB_PRE_INDE_M_REG_OFF(u32 adr, u32 i, char * txt) { sprintf(txt, "LDRSB%s %s, [%s, -%s]!", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], Registre[REG_POS(i,0)]); return txt;} static char * OP_LDRSB_POS_INDE_P_IMM_OFF(u32 adr, u32 i, char * txt) { sprintf(txt, "LDRSB%s %s, [%s], #%X", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], (int)(((i>>4)&0xF0)|(i&0xF))); return txt;} static char * OP_LDRSB_POS_INDE_M_IMM_OFF(u32 adr, u32 i, char * txt) { sprintf(txt, "LDRSB%s %s, [%s], -#%X", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], (int)(((i>>4)&0xF0)|(i&0xF))); return txt;} static char * OP_LDRSB_POS_INDE_P_REG_OFF(u32 adr, u32 i, char * txt) { sprintf(txt, "LDRSB%s %s, [%s], %s", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], Registre[REG_POS(i,0)]); return txt;} static char * OP_LDRSB_POS_INDE_M_REG_OFF(u32 adr, u32 i, char * txt) { sprintf(txt, "LDRSB%s %s, [%s], -%s", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], Registre[REG_POS(i,0)]); return txt;} //--------------MRS-------------------------------- static char * OP_MRS_CPSR(u32 adr, u32 i, char * txt) { sprintf(txt, "MRS%s %s, CPSR", Condition[CONDITION(i)], Registre[REG_POS(i,12)]); return txt;} static char * OP_MRS_SPSR(u32 adr, u32 i, char * txt) { sprintf(txt, "MRS%s %s, SPSR", Condition[CONDITION(i)], Registre[REG_POS(i,12)]); return txt;} //--------------MSR-------------------------------- static char * OP_MSR_CPSR(u32 adr, u32 i, char * txt) { sprintf(txt, "MSR%s CPSR_%s, %s", Condition[CONDITION(i)], MSR_FIELD[REG_POS(i,16)], Registre[REG_POS(i,0)]); return txt;} static char * OP_MSR_SPSR(u32 adr, u32 i, char * txt) { sprintf(txt, "MSR%s SPSR_%s, %s", Condition[CONDITION(i)], MSR_FIELD[REG_POS(i,16)], Registre[REG_POS(i,0)]); return txt;} static char * OP_MSR_CPSR_IMM_VAL(u32 adr, u32 i, char * txt) { sprintf(txt, "MSR%s CPSR_%s, #%X", Condition[CONDITION(i)], MSR_FIELD[REG_POS(i,16)], (int)ROR((i&0xFF), ((i>>7)&0x1E))); return txt;} static char * OP_MSR_SPSR_IMM_VAL(u32 adr, u32 i, char * txt) { sprintf(txt, "MSR%s SPSR_%s, #%X", Condition[CONDITION(i)], MSR_FIELD[REG_POS(i,16)], (int)ROR((i&0xFF), (i>>7)&0x1E)); return txt;} //-----------------BRANCH-------------------------- static char * OP_BX(u32 adr, u32 i, char * txt) { sprintf(txt, "BX%s %s", Condition[CONDITION(i)], Registre[REG_POS(i,0)]); return txt;} static char * OP_BLX_REG(u32 adr, u32 i, char * txt) { sprintf(txt, "BLX%s %s", Condition[CONDITION(i)], Registre[REG_POS(i,0)]); return txt;} static char * OP_B(u32 adr, u32 i, char * txt) { if(CONDITION(i)==0xF) { sprintf(txt, "BLX%s %08X", Condition[CONDITION(i)], (int)(adr+(SIGNEXTEND_24(i)<<2)+8)); return txt;} sprintf(txt, "B%s %08X", Condition[CONDITION(i)], (int)(adr+(SIGNEXTEND_24(i)<<2)+8)); return txt;} static char * OP_BL(u32 adr, u32 i, char * txt) { if(CONDITION(i)==0xF) { sprintf(txt, "BLX%s %08X", Condition[CONDITION(i)], (int)(adr+(SIGNEXTEND_24(i)<<2)+10)); return txt;} sprintf(txt, "BL%s %08X", Condition[CONDITION(i)], (int)(adr+(SIGNEXTEND_24(i)<<2)+8)); return txt;} //----------------CLZ------------------------------- static char * OP_CLZ(u32 adr, u32 i, char * txt) { sprintf(txt, "CLZ%s %s, %s", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,0)]); return txt;} //--------------------QADD--QSUB------------------------------ static char * OP_QADD(u32 adr, u32 i, char * txt) { sprintf(txt, "QADD%s %s, %s, %s", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,0)], Registre[REG_POS(i,16)]); return txt;} static char * OP_QSUB(u32 adr, u32 i, char * txt) { sprintf(txt, "QSUB%s %s, %s, %s", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,0)], Registre[REG_POS(i,16)]); return txt;} static char * OP_QDADD(u32 adr, u32 i, char * txt) { sprintf(txt, "QDADD%s %s, %s, %s", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,0)], Registre[REG_POS(i,16)]); return txt;} static char * OP_QDSUB(u32 adr, u32 i, char * txt) { sprintf(txt, "QDSUB%s %s, %s, %s", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,0)], Registre[REG_POS(i,16)]); return txt;} //-----------------SMUL------------------------------- static char * OP_SMUL_B_B(u32 adr, u32 i, char * txt) { sprintf(txt, "SMULBB%s %s, %s, %s", Condition[CONDITION(i)], Registre[REG_POS(i,16)], Registre[REG_POS(i,0)], Registre[REG_POS(i,8)]); return txt;} static char * OP_SMUL_B_T(u32 adr, u32 i, char * txt) { sprintf(txt, "SMULBT%s %s, %s, %s", Condition[CONDITION(i)], Registre[REG_POS(i,16)], Registre[REG_POS(i,0)], Registre[REG_POS(i,8)]); return txt;} static char * OP_SMUL_T_B(u32 adr, u32 i, char * txt) { sprintf(txt, "SMULTB%s %s, %s, %s", Condition[CONDITION(i)], Registre[REG_POS(i,16)], Registre[REG_POS(i,0)], Registre[REG_POS(i,8)]); return txt;} static char * OP_SMUL_T_T(u32 adr, u32 i, char * txt) { sprintf(txt, "SMULTT%s %s, %s, %s", Condition[CONDITION(i)], Registre[REG_POS(i,16)], Registre[REG_POS(i,0)], Registre[REG_POS(i,8)]); return txt;} //-----------SMLA---------------------------- static char * OP_SMLA_B_B(u32 adr, u32 i, char * txt) { sprintf(txt, "SMLABB%s %s, %s, %s, %s", Condition[CONDITION(i)], Registre[REG_POS(i,16)], Registre[REG_POS(i,0)], Registre[REG_POS(i,8)], Registre[REG_POS(i,12)]); return txt;} static char * OP_SMLA_B_T(u32 adr, u32 i, char * txt) { sprintf(txt, "SMLABT%s %s, %s, %s, %s", Condition[CONDITION(i)], Registre[REG_POS(i,16)], Registre[REG_POS(i,0)], Registre[REG_POS(i,8)], Registre[REG_POS(i,12)]); return txt;} static char * OP_SMLA_T_B(u32 adr, u32 i, char * txt) { sprintf(txt, "SMLATB%s %s, %s, %s, %s", Condition[CONDITION(i)], Registre[REG_POS(i,16)], Registre[REG_POS(i,0)], Registre[REG_POS(i,8)], Registre[REG_POS(i,12)]); return txt;} static char * OP_SMLA_T_T(u32 adr, u32 i, char * txt) { sprintf(txt, "SMLATT%s %s, %s, %s, %s", Condition[CONDITION(i)], Registre[REG_POS(i,16)], Registre[REG_POS(i,0)], Registre[REG_POS(i,8)], Registre[REG_POS(i,12)]); return txt;} //--------------SMLAL--------------------------------------- static char * OP_SMLAL_B_B(u32 adr, u32 i, char * txt) { sprintf(txt, "SMLABB%s %s, %s, %s, %s", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], Registre[REG_POS(i,0)], Registre[REG_POS(i,8)]); return txt;} static char * OP_SMLAL_B_T(u32 adr, u32 i, char * txt) { sprintf(txt, "SMLABT%s %s, %s, %s, %s", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], Registre[REG_POS(i,0)], Registre[REG_POS(i,8)]); return txt;} static char * OP_SMLAL_T_B(u32 adr, u32 i, char * txt) { sprintf(txt, "SMLATB%s %s, %s, %s, %s", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], Registre[REG_POS(i,0)], Registre[REG_POS(i,8)]); return txt;} static char * OP_SMLAL_T_T(u32 adr, u32 i, char * txt) { sprintf(txt, "SMLATT%s %s, %s, %s, %s", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], Registre[REG_POS(i,0)], Registre[REG_POS(i,8)]); return txt;} //--------------SMULW-------------------- static char * OP_SMULW_B(u32 adr, u32 i, char * txt) { sprintf(txt, "SMULWB%s %s, %s, %s", Condition[CONDITION(i)], Registre[REG_POS(i,16)], Registre[REG_POS(i,0)], Registre[REG_POS(i,8)]); return txt;} static char * OP_SMULW_T(u32 adr, u32 i, char * txt) { sprintf(txt, "SMULWT%s %s, %s, %s", Condition[CONDITION(i)], Registre[REG_POS(i,16)], Registre[REG_POS(i,0)], Registre[REG_POS(i,8)]); return txt;} //--------------SMLAW------------------- static char * OP_SMLAW_B(u32 adr, u32 i, char * txt) { sprintf(txt, "SMLAWB%s %s, %s, %s, %s", Condition[CONDITION(i)], Registre[REG_POS(i,16)], Registre[REG_POS(i,0)], Registre[REG_POS(i,8)], Registre[REG_POS(i,12)]); return txt;} static char * OP_SMLAW_T(u32 adr, u32 i, char * txt) { sprintf(txt, "SMLAWT%s %s, %s, %s, %s", Condition[CONDITION(i)], Registre[REG_POS(i,16)], Registre[REG_POS(i,0)], Registre[REG_POS(i,8)], Registre[REG_POS(i,12)]); return txt;} //------------LDR--------------------------- static char * OP_LDR_P_IMM_OFF(u32 adr, u32 i, char * txt) { if(REG_POS(i,16) == 15) sprintf(txt, "LDR%s %s, [%08X]", Condition[CONDITION(i)], Registre[REG_POS(i,12)], (adr + 8 + (int)(i&0x7FF))); else sprintf(txt, "LDR%s %s, [%s, #%X]", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], (int)(i&0x7FF)); return txt;} static char * OP_LDR_M_IMM_OFF(u32 adr, u32 i, char * txt) { if(REG_POS(i,16) == 15) sprintf(txt, "LDR%s %s, [%08X]", Condition[CONDITION(i)], Registre[REG_POS(i,12)], (adr + 8 - (int)(i&0x7FF))); else sprintf(txt, "LDR%s %s, [%s, -#%X]", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], (int)(i&0x7FF)); return txt;} static char * OP_LDREX(u32 adr, u32 i, char * txt) { sprintf(txt, "LDREX%s %s, [%s]", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)]); return txt;} static char * OP_LDR_P_LSL_IMM_OFF(u32 adr, u32 i, char * txt) { LDRSTR_LSL_IMM(LDR, "", "", "]"); return txt;} static char * OP_LDR_M_LSL_IMM_OFF(u32 adr, u32 i, char * txt) { LDRSTR_LSL_IMM(LDR, "-", "", "]"); return txt;} static char * OP_LDR_P_LSR_IMM_OFF(u32 adr, u32 i, char * txt) { LDRSTR_IMM_SHIFT(LDR, LSR, "", "", "]"); return txt;} static char * OP_LDR_M_LSR_IMM_OFF(u32 adr, u32 i, char * txt) { LDRSTR_IMM_SHIFT(LDR, LSR, "M", "", "]"); return txt;} static char * OP_LDR_P_ASR_IMM_OFF(u32 adr, u32 i, char * txt) { LDRSTR_IMM_SHIFT(LDR, ASR, "", "", "]"); return txt;} static char * OP_LDR_M_ASR_IMM_OFF(u32 adr, u32 i, char * txt) { LDRSTR_IMM_SHIFT(LDR, ASR, "-", "", "]"); return txt;} static char * OP_LDR_P_ROR_IMM_OFF(u32 adr, u32 i, char * txt) { LDRSTR_ROR_IMM(LDR, "", "", "]"); return txt;} static char * OP_LDR_M_ROR_IMM_OFF(u32 adr, u32 i, char * txt) { LDRSTR_ROR_IMM(LDR, "-", "", "]"); return txt;} static char * OP_LDR_P_IMM_OFF_PREIND(u32 adr, u32 i, char * txt) { sprintf(txt, "LDR%s %s, [%s, #%X]!", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], (int)(i&0x7FF)); return txt;} static char * OP_LDR_M_IMM_OFF_PREIND(u32 adr, u32 i, char * txt) { sprintf(txt, "LDR%s %s, [%s, -#%X]!", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], (int)(i&0x7FF)); return txt;} static char * OP_LDR_P_LSL_IMM_OFF_PREIND(u32 adr, u32 i, char * txt) { LDRSTR_LSL_IMM(LDR, "", "", "]!"); return txt;} static char * OP_LDR_M_LSL_IMM_OFF_PREIND(u32 adr, u32 i, char * txt) { LDRSTR_LSL_IMM(LDR, "-", "", "]!"); return txt;} static char * OP_LDR_P_LSR_IMM_OFF_PREIND(u32 adr, u32 i, char * txt) { LDRSTR_IMM_SHIFT(LDR, LSR, "", "", "]!"); return txt;} static char * OP_LDR_M_LSR_IMM_OFF_PREIND(u32 adr, u32 i, char * txt) { LDRSTR_IMM_SHIFT(LDR, LSR, "-", "", "]!"); return txt;} static char * OP_LDR_P_ASR_IMM_OFF_PREIND(u32 adr, u32 i, char * txt) { LDRSTR_IMM_SHIFT(LDR, ASR, "", "", "]!"); return txt;} static char * OP_LDR_M_ASR_IMM_OFF_PREIND(u32 adr, u32 i, char * txt) { LDRSTR_IMM_SHIFT(LDR, ASR, "-", "", "]!"); return txt;} static char * OP_LDR_P_ROR_IMM_OFF_PREIND(u32 adr, u32 i, char * txt) { LDRSTR_ROR_IMM(LDR, "", "", "]!"); return txt;} static char * OP_LDR_M_ROR_IMM_OFF_PREIND(u32 adr, u32 i, char * txt) { LDRSTR_ROR_IMM(LDR, "-", "", "]!"); return txt;} static char * OP_LDR_P_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) { sprintf(txt, "LDR%s %s, [%s], #%X!", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], (int)(i&0x7FF)); return txt;} static char * OP_LDR_P_IMM_OFF_POSTIND2(u32 adr, u32 i, char * txt) { sprintf(txt, "LDR%s %s, [%s], #%X!", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], (int)(i&0x7FF)); return txt;} static char * OP_LDR_M_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) { sprintf(txt, "LDR%s %s, [%s], -#%X!", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], (int)(i&0x7FF)); return txt;} static char * OP_LDR_P_LSL_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) { LDRSTR_LSL_IMM(LDR, "", "]", ""); return txt;} static char * OP_LDR_M_LSL_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) { LDRSTR_LSL_IMM(LDR, "-", "]", ""); return txt;} static char * OP_LDR_P_LSR_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) { LDRSTR_IMM_SHIFT(LDR, LSR, "", "]", ""); return txt;} static char * OP_LDR_M_LSR_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) { LDRSTR_IMM_SHIFT(LDR, LSR, "-", "]", ""); return txt;} static char * OP_LDR_P_ASR_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) { LDRSTR_IMM_SHIFT(LDR, ASR, "", "]", ""); return txt;} static char * OP_LDR_M_ASR_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) { LDRSTR_IMM_SHIFT(LDR, ASR, "-", "]", ""); return txt;} static char * OP_LDR_P_ROR_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) { LDRSTR_ROR_IMM(LDR, "", "]", ""); return txt;} static char * OP_LDR_M_ROR_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) { LDRSTR_ROR_IMM(LDR, "-", "]", ""); return txt;} //-----------------LDRB------------------------------------------- static char * OP_LDRB_P_IMM_OFF(u32 adr, u32 i, char * txt) { sprintf(txt, "LDRB%s %s, [%s, #%X]", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], (int)(i&0x7FF)); return txt;} static char * OP_LDRB_M_IMM_OFF(u32 adr, u32 i, char * txt) { sprintf(txt, "LDRB%s %s, [%s, -#%X]", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], (int)(i&0x7FF)); return txt;} static char * OP_LDRB_P_LSL_IMM_OFF(u32 adr, u32 i, char * txt) { LDRSTR_LSL_IMM(LDRB, "", "", "]"); return txt;} static char * OP_LDRB_M_LSL_IMM_OFF(u32 adr, u32 i, char * txt) { LDRSTR_LSL_IMM(LDRB, "-", "", "]"); return txt;} static char * OP_LDRB_P_LSR_IMM_OFF(u32 adr, u32 i, char * txt) { LDRSTR_IMM_SHIFT(LDRB, LSR, "", "", "]"); return txt;} static char * OP_LDRB_M_LSR_IMM_OFF(u32 adr, u32 i, char * txt) { LDRSTR_IMM_SHIFT(LDRB, LSR, "M", "", "]"); return txt;} static char * OP_LDRB_P_ASR_IMM_OFF(u32 adr, u32 i, char * txt) { LDRSTR_IMM_SHIFT(LDRB, ASR, "", "", "]"); return txt;} static char * OP_LDRB_M_ASR_IMM_OFF(u32 adr, u32 i, char * txt) { LDRSTR_IMM_SHIFT(LDRB, ASR, "-", "", "]"); return txt;} static char * OP_LDRB_P_ROR_IMM_OFF(u32 adr, u32 i, char * txt) { LDRSTR_ROR_IMM(LDRB, "", "", "]"); return txt;} static char * OP_LDRB_M_ROR_IMM_OFF(u32 adr, u32 i, char * txt) { LDRSTR_ROR_IMM(LDRB, "-", "", "]"); return txt;} static char * OP_LDRB_P_IMM_OFF_PREIND(u32 adr, u32 i, char * txt) { sprintf(txt, "LDRB%s %s, [%s, #%X]!", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], (int)(i&0x7FF)); return txt;} static char * OP_LDRB_M_IMM_OFF_PREIND(u32 adr, u32 i, char * txt) { sprintf(txt, "LDRB%s %s, [%s, -#%X]!", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], (int)(i&0x7FF)); return txt;} static char * OP_LDRB_P_LSL_IMM_OFF_PREIND(u32 adr, u32 i, char * txt) { LDRSTR_LSL_IMM(LDRB, "", "", "]!"); return txt;} static char * OP_LDRB_M_LSL_IMM_OFF_PREIND(u32 adr, u32 i, char * txt) { LDRSTR_LSL_IMM(LDRB, "-", "", "]!"); return txt;} static char * OP_LDRB_P_LSR_IMM_OFF_PREIND(u32 adr, u32 i, char * txt) { LDRSTR_IMM_SHIFT(LDRB, LSR, "", "", "]!"); return txt;} static char * OP_LDRB_M_LSR_IMM_OFF_PREIND(u32 adr, u32 i, char * txt) { LDRSTR_IMM_SHIFT(LDRB, LSR, "-", "", "]!"); return txt;} static char * OP_LDRB_P_ASR_IMM_OFF_PREIND(u32 adr, u32 i, char * txt) { LDRSTR_IMM_SHIFT(LDRB, ASR, "", "", "]!"); return txt;} static char * OP_LDRB_M_ASR_IMM_OFF_PREIND(u32 adr, u32 i, char * txt) { LDRSTR_IMM_SHIFT(LDRB, ASR, "-", "", "]!"); return txt;} static char * OP_LDRB_P_ROR_IMM_OFF_PREIND(u32 adr, u32 i, char * txt) { LDRSTR_ROR_IMM(LDRB, "", "", "]!"); return txt;} static char * OP_LDRB_M_ROR_IMM_OFF_PREIND(u32 adr, u32 i, char * txt) { LDRSTR_ROR_IMM(LDRB, "-", "", "]!"); return txt;} static char * OP_LDRB_P_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) { sprintf(txt, "LDRB%s %s, [%s], #%X!", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], (int)(i&0x7FF)); return txt;} static char * OP_LDRB_M_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) { sprintf(txt, "LDRB%s %s, [%s], -#%X!", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], (int)(i&0x7FF)); return txt;} static char * OP_LDRB_P_LSL_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) { LDRSTR_LSL_IMM(LDRB, "", "]", ""); return txt;} static char * OP_LDRB_M_LSL_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) { LDRSTR_LSL_IMM(LDRB, "-", "]", ""); return txt;} static char * OP_LDRB_P_LSR_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) { LDRSTR_IMM_SHIFT(LDRB, LSR, "", "]", ""); return txt;} static char * OP_LDRB_M_LSR_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) { LDRSTR_IMM_SHIFT(LDRB, LSR, "-", "]", ""); return txt;} static char * OP_LDRB_P_ASR_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) { LDRSTR_IMM_SHIFT(LDRB, ASR, "", "]", ""); return txt;} static char * OP_LDRB_M_ASR_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) { LDRSTR_IMM_SHIFT(LDRB, ASR, "-", "]", ""); return txt;} static char * OP_LDRB_P_ROR_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) { LDRSTR_ROR_IMM(LDRB, "", "]", ""); return txt;} static char * OP_LDRB_M_ROR_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) { LDRSTR_ROR_IMM(LDRB, "-", "]", ""); return txt;} //----------------------STR-------------------------------- static char * OP_STR_P_IMM_OFF(u32 adr, u32 i, char * txt) { sprintf(txt, "STR%s %s, [%s, #%X]", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], (int)(i&0x7FF)); return txt;} static char * OP_STR_M_IMM_OFF(u32 adr, u32 i, char * txt) { sprintf(txt, "STR%s %s, [%s, -#%X]", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], (int)(i&0x7FF)); return txt;} static char * OP_STREX(u32 adr, u32 i, char * txt) { sprintf(txt, "STREX%s %s, %s, [%s]", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,0)], Registre[REG_POS(i,16)]); return txt;} static char * OP_STR_P_LSL_IMM_OFF(u32 adr, u32 i, char * txt) { LDRSTR_LSL_IMM(STR, "", "", "]"); return txt;} static char * OP_STR_M_LSL_IMM_OFF(u32 adr, u32 i, char * txt) { LDRSTR_LSL_IMM(STR, "-", "", "]"); return txt;} static char * OP_STR_P_LSR_IMM_OFF(u32 adr, u32 i, char * txt) { LDRSTR_IMM_SHIFT(STR, LSR, "", "", "]"); return txt;} static char * OP_STR_M_LSR_IMM_OFF(u32 adr, u32 i, char * txt) { LDRSTR_IMM_SHIFT(STR, LSR, "M", "", "]"); return txt;} static char * OP_STR_P_ASR_IMM_OFF(u32 adr, u32 i, char * txt) { LDRSTR_IMM_SHIFT(STR, ASR, "", "", "]"); return txt;} static char * OP_STR_M_ASR_IMM_OFF(u32 adr, u32 i, char * txt) { LDRSTR_IMM_SHIFT(STR, ASR, "-", "", "]"); return txt;} static char * OP_STR_P_ROR_IMM_OFF(u32 adr, u32 i, char * txt) { LDRSTR_ROR_IMM(STR, "", "", "]"); return txt;} static char * OP_STR_M_ROR_IMM_OFF(u32 adr, u32 i, char * txt) { LDRSTR_ROR_IMM(STR, "-", "", "]"); return txt;} static char * OP_STR_P_IMM_OFF_PREIND(u32 adr, u32 i, char * txt) { sprintf(txt, "STR%s %s, [%s, #%X]!", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], (int)(i&0x7FF)); return txt;} static char * OP_STR_M_IMM_OFF_PREIND(u32 adr, u32 i, char * txt) { sprintf(txt, "STR%s %s, [%s, -#%X]!", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], (int)(i&0x7FF)); return txt;} static char * OP_STR_P_LSL_IMM_OFF_PREIND(u32 adr, u32 i, char * txt) { LDRSTR_LSL_IMM(STR, "", "", "]!"); return txt;} static char * OP_STR_M_LSL_IMM_OFF_PREIND(u32 adr, u32 i, char * txt) { LDRSTR_LSL_IMM(STR, "-", "", "]!"); return txt;} static char * OP_STR_P_LSR_IMM_OFF_PREIND(u32 adr, u32 i, char * txt) { LDRSTR_IMM_SHIFT(STR, LSR, "", "", "]!"); return txt;} static char * OP_STR_M_LSR_IMM_OFF_PREIND(u32 adr, u32 i, char * txt) { LDRSTR_IMM_SHIFT(STR, LSR, "-", "", "]!"); return txt;} static char * OP_STR_P_ASR_IMM_OFF_PREIND(u32 adr, u32 i, char * txt) { LDRSTR_IMM_SHIFT(STR, ASR, "", "", "]!"); return txt;} static char * OP_STR_M_ASR_IMM_OFF_PREIND(u32 adr, u32 i, char * txt) { LDRSTR_IMM_SHIFT(STR, ASR, "-", "", "]!"); return txt;} static char * OP_STR_P_ROR_IMM_OFF_PREIND(u32 adr, u32 i, char * txt) { LDRSTR_ROR_IMM(STR, "", "", "]!"); return txt;} static char * OP_STR_M_ROR_IMM_OFF_PREIND(u32 adr, u32 i, char * txt) { LDRSTR_ROR_IMM(STR, "-", "", "]!"); return txt;} static char * OP_STR_P_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) { sprintf(txt, "STR%s %s, [%s], #%X!", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], (int)(i&0x7FF)); return txt;} static char * OP_STR_M_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) { sprintf(txt, "STR%s %s, [%s], -#%X!", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], (int)(i&0x7FF)); return txt;} static char * OP_STR_P_LSL_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) { LDRSTR_LSL_IMM(STR, "", "]", ""); return txt;} static char * OP_STR_M_LSL_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) { LDRSTR_LSL_IMM(STR, "-", "]", ""); return txt;} static char * OP_STR_P_LSR_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) { LDRSTR_IMM_SHIFT(STR, LSR, "", "]", ""); return txt;} static char * OP_STR_M_LSR_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) { LDRSTR_IMM_SHIFT(STR, LSR, "-", "]", ""); return txt;} static char * OP_STR_P_ASR_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) { LDRSTR_IMM_SHIFT(STR, ASR, "", "]", ""); return txt;} static char * OP_STR_M_ASR_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) { LDRSTR_IMM_SHIFT(STR, ASR, "-", "]", ""); return txt;} static char * OP_STR_P_ROR_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) { LDRSTR_ROR_IMM(STR, "", "]", ""); return txt;} static char * OP_STR_M_ROR_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) { LDRSTR_ROR_IMM(STR, "-", "]", ""); return txt;} //-----------------------STRB------------------------------------- static char * OP_STRB_P_IMM_OFF(u32 adr, u32 i, char * txt) { sprintf(txt, "STRB%s %s, [%s, #%X]", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], (int)(i&0x7FF)); return txt;} static char * OP_STRB_M_IMM_OFF(u32 adr, u32 i, char * txt) { sprintf(txt, "STRB%s %s, [%s, -#%X]", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], (int)(i&0x7FF)); return txt;} static char * OP_STRB_P_LSL_IMM_OFF(u32 adr, u32 i, char * txt) { LDRSTR_LSL_IMM(STRB, "", "", "]"); return txt;} static char * OP_STRB_M_LSL_IMM_OFF(u32 adr, u32 i, char * txt) { LDRSTR_LSL_IMM(STRB, "-", "", "]"); return txt;} static char * OP_STRB_P_LSR_IMM_OFF(u32 adr, u32 i, char * txt) { LDRSTR_IMM_SHIFT(STRB, LSR, "", "", "]"); return txt;} static char * OP_STRB_M_LSR_IMM_OFF(u32 adr, u32 i, char * txt) { LDRSTR_IMM_SHIFT(STRB, LSR, "M", "", "]"); return txt;} static char * OP_STRB_P_ASR_IMM_OFF(u32 adr, u32 i, char * txt) { LDRSTR_IMM_SHIFT(STRB, ASR, "", "", "]"); return txt;} static char * OP_STRB_M_ASR_IMM_OFF(u32 adr, u32 i, char * txt) { LDRSTR_IMM_SHIFT(STRB, ASR, "-", "", "]"); return txt;} static char * OP_STRB_P_ROR_IMM_OFF(u32 adr, u32 i, char * txt) { LDRSTR_ROR_IMM(STRB, "", "", "]"); return txt;} static char * OP_STRB_M_ROR_IMM_OFF(u32 adr, u32 i, char * txt) { LDRSTR_ROR_IMM(STRB, "-", "", "]"); return txt;} static char * OP_STRB_P_IMM_OFF_PREIND(u32 adr, u32 i, char * txt) { sprintf(txt, "STRB%s %s, [%s, #%X]!", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], (int)(i&0x7FF)); return txt;} static char * OP_STRB_M_IMM_OFF_PREIND(u32 adr, u32 i, char * txt) { sprintf(txt, "STRB%s %s, [%s, -#%X]!", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], (int)(i&0x7FF)); return txt;} static char * OP_STRB_P_LSL_IMM_OFF_PREIND(u32 adr, u32 i, char * txt) { LDRSTR_LSL_IMM(STRB, "", "", "]!"); return txt;} static char * OP_STRB_M_LSL_IMM_OFF_PREIND(u32 adr, u32 i, char * txt) { LDRSTR_LSL_IMM(STRB, "-", "", "]!"); return txt;} static char * OP_STRB_P_LSR_IMM_OFF_PREIND(u32 adr, u32 i, char * txt) { LDRSTR_IMM_SHIFT(STRB, LSR, "", "", "]!"); return txt;} static char * OP_STRB_M_LSR_IMM_OFF_PREIND(u32 adr, u32 i, char * txt) { LDRSTR_IMM_SHIFT(STRB, LSR, "-", "", "]!"); return txt;} static char * OP_STRB_P_ASR_IMM_OFF_PREIND(u32 adr, u32 i, char * txt) { LDRSTR_IMM_SHIFT(STRB, ASR, "", "", "]!"); return txt;} static char * OP_STRB_M_ASR_IMM_OFF_PREIND(u32 adr, u32 i, char * txt) { LDRSTR_IMM_SHIFT(STRB, ASR, "-", "", "]!"); return txt;} static char * OP_STRB_P_ROR_IMM_OFF_PREIND(u32 adr, u32 i, char * txt) { LDRSTR_ROR_IMM(STRB, "", "", "]!"); return txt;} static char * OP_STRB_M_ROR_IMM_OFF_PREIND(u32 adr, u32 i, char * txt) { LDRSTR_ROR_IMM(STRB, "-", "", "]!"); return txt;} static char * OP_STRB_P_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) { sprintf(txt, "STRB%s %s, [%s], #%X!", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], (int)(i&0x7FF)); return txt;} static char * OP_STRB_M_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) { sprintf(txt, "STRB%s %s, [%s], -#%X!", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], (int)(i&0x7FF)); return txt;} static char * OP_STRB_P_LSL_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) { LDRSTR_LSL_IMM(STRB, "", "]", ""); return txt;} static char * OP_STRB_M_LSL_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) { LDRSTR_LSL_IMM(STRB, "-", "]", ""); return txt;} static char * OP_STRB_P_LSR_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) { LDRSTR_IMM_SHIFT(STRB, LSR, "", "]", ""); return txt;} static char * OP_STRB_M_LSR_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) { LDRSTR_IMM_SHIFT(STRB, LSR, "-", "]", ""); return txt;} static char * OP_STRB_P_ASR_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) { LDRSTR_IMM_SHIFT(STRB, ASR, "", "]", ""); return txt;} static char * OP_STRB_M_ASR_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) { LDRSTR_IMM_SHIFT(STRB, ASR, "-", "]", ""); return txt;} static char * OP_STRB_P_ROR_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) { LDRSTR_ROR_IMM(STRB, "", "]", ""); return txt;} static char * OP_STRB_M_ROR_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) { LDRSTR_ROR_IMM(STRB, "-", "]", ""); return txt;} //-----------------------LDRBT------------------------------------- #if 0 static char * OP_LDRBT_P_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) { sprintf(txt, "LDRBT%s %s, [%s], #%X!", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], (int)(i&0x7FF)); return txt;} static char * OP_LDRBT_M_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) { sprintf(txt, "LDRBT%s %s, [%s], -#%X!", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], (int)(i&0x7FF)); return txt;} static char * OP_LDRBT_P_LSL_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) { LDRSTR_LSL_IMM(LDRBT, "", "]", ""); return txt;} static char * OP_LDRBT_M_LSL_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) { LDRSTR_LSL_IMM(LDRBT, "-", "]", ""); return txt;} static char * OP_LDRBT_P_LSR_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) { LDRSTR_IMM_SHIFT(LDRBT, LSR, "", "]", ""); return txt;} static char * OP_LDRBT_M_LSR_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) { LDRSTR_IMM_SHIFT(LDRBT, LSR, "-", "]", ""); return txt;} static char * OP_LDRBT_P_ASR_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) { LDRSTR_IMM_SHIFT(LDRBT, ASR, "", "]", ""); return txt;} static char * OP_LDRBT_M_ASR_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) { LDRSTR_IMM_SHIFT(LDRBT, ASR, "-", "]", ""); return txt;} static char * OP_LDRBT_P_ROR_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) { LDRSTR_ROR_IMM(LDRBT, "", "]", ""); return txt;} static char * OP_LDRBT_M_ROR_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) { LDRSTR_ROR_IMM(LDRBT, "-", "]", ""); return txt;} //----------------------STRBT---------------------------- static char * OP_STRBT_P_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) { sprintf(txt, "STRBT%s %s, [%s], #%X!", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], (int)(i&0x7FF)); return txt;} static char * OP_STRBT_M_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) { sprintf(txt, "STRBT%s %s, [%s], -#%X!", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], (int)(i&0x7FF)); return txt;} static char * OP_STRBT_P_LSL_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) { LDRSTR_LSL_IMM(STRBT, "", "]", ""); return txt;} static char * OP_STRBT_M_LSL_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) { LDRSTR_LSL_IMM(STRBT, "-", "]", ""); return txt;} static char * OP_STRBT_P_LSR_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) { LDRSTR_IMM_SHIFT(STRBT, LSR, "", "]", ""); return txt;} static char * OP_STRBT_M_LSR_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) { LDRSTR_IMM_SHIFT(STRBT, LSR, "-", "]", ""); return txt;} static char * OP_STRBT_P_ASR_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) { LDRSTR_IMM_SHIFT(STRBT, ASR, "", "]", ""); return txt;} static char * OP_STRBT_M_ASR_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) { LDRSTR_IMM_SHIFT(STRBT, ASR, "-", "]", ""); return txt;} static char * OP_STRBT_P_ROR_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) { LDRSTR_ROR_IMM(STRBT, "", "]", ""); return txt;} static char * OP_STRBT_M_ROR_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) { LDRSTR_ROR_IMM(STRBT, "-", "]", ""); return txt;} #endif //---------------------LDM----------------------------- static char * OP_LDMIA(u32 adr, u32 i, char * txt) { RegList(16); sprintf(txt, "LDMIA%s %s, {%s}", Condition[CONDITION(i)], Registre[REG_POS(i,16)], lreg); return txt;} static char * OP_LDMIB(u32 adr, u32 i, char * txt) { RegList(16); sprintf(txt, "LDMIB%s %s, {%s}", Condition[CONDITION(i)], Registre[REG_POS(i,16)], lreg); return txt;} static char * OP_LDMDA(u32 adr, u32 i, char * txt) { RegList(16); sprintf(txt, "LDMDA%s %s, {%s}", Condition[CONDITION(i)], Registre[REG_POS(i,16)], lreg); return txt;} static char * OP_LDMDB(u32 adr, u32 i, char * txt) { RegList(16); sprintf(txt, "LDMDB%s %s, {%s}", Condition[CONDITION(i)], Registre[REG_POS(i,16)], lreg); return txt;} static char * OP_LDMIA_W(u32 adr, u32 i, char * txt) { RegList(16); sprintf(txt, "LDMIA%s %s!, {%s}", Condition[CONDITION(i)], Registre[REG_POS(i,16)], lreg); return txt;} static char * OP_LDMIB_W(u32 adr, u32 i, char * txt) { RegList(16); sprintf(txt, "LDMIB%s %s!, {%s}", Condition[CONDITION(i)], Registre[REG_POS(i,16)], lreg); return txt;} static char * OP_LDMDA_W(u32 adr, u32 i, char * txt) { RegList(16); sprintf(txt, "LDMDA%s %s!, {%s}", Condition[CONDITION(i)], Registre[REG_POS(i,16)], lreg); return txt;} static char * OP_LDMDB_W(u32 adr, u32 i, char * txt) { RegList(16); sprintf(txt, "LDMDB%s %s!, {%s}", Condition[CONDITION(i)], Registre[REG_POS(i,16)], lreg); return txt;} static char * OP_LDMIA2(u32 adr, u32 i, char * txt) { RegList(16); sprintf(txt, "LDMIA%s %s, {%s}^", Condition[CONDITION(i)], Registre[REG_POS(i,16)], lreg); return txt;} static char * OP_LDMIB2(u32 adr, u32 i, char * txt) { RegList(16); sprintf(txt, "LDMIB%s %s, {%s}^", Condition[CONDITION(i)], Registre[REG_POS(i,16)], lreg); return txt;} static char * OP_LDMDA2(u32 adr, u32 i, char * txt) { RegList(16); sprintf(txt, "LDMDA%s %s, {%s}^", Condition[CONDITION(i)], Registre[REG_POS(i,16)], lreg); return txt;} static char * OP_LDMDB2(u32 adr, u32 i, char * txt) { RegList(16); sprintf(txt, "LDMDB%s %s, {%s}^", Condition[CONDITION(i)], Registre[REG_POS(i,16)], lreg); return txt;} static char * OP_LDMIA2_W(u32 adr, u32 i, char * txt) { RegList(16); sprintf(txt, "LDMIA%s %s!, {%s}^", Condition[CONDITION(i)], Registre[REG_POS(i,16)], lreg); if(BIT15(i)==0) sprintf(txt, "%s ?????", txt); return txt;} static char * OP_LDMIB2_W(u32 adr, u32 i, char * txt) { RegList(16); sprintf(txt, "LDMIB%s %s!, {%s}^", Condition[CONDITION(i)], Registre[REG_POS(i,16)], lreg); if(BIT15(i)==0) sprintf(txt, "%s ?????", txt); return txt;} static char * OP_LDMDA2_W(u32 adr, u32 i, char * txt) { RegList(16); sprintf(txt, "LDMDA%s %s!, {%s}^", Condition[CONDITION(i)], Registre[REG_POS(i,16)], lreg); if(BIT15(i)==0) sprintf(txt, "%s ?????", txt); return txt;} static char * OP_LDMDB2_W(u32 adr, u32 i, char * txt) { RegList(16); sprintf(txt, "LDMDB%s %s!, {%s}^", Condition[CONDITION(i)], Registre[REG_POS(i,16)], lreg); if(BIT15(i)==0) sprintf(txt, "%s ?????", txt); return txt;} //------------------------------STM---------------------------------- static char * OP_STMIA(u32 adr, u32 i, char * txt) { RegList(16); sprintf(txt, "STMIA%s %s, {%s}", Condition[CONDITION(i)], Registre[REG_POS(i,16)], lreg); return txt;} static char * OP_STMIB(u32 adr, u32 i, char * txt) { RegList(16); sprintf(txt, "STMIB%s %s, {%s}", Condition[CONDITION(i)], Registre[REG_POS(i,16)], lreg); return txt;} static char * OP_STMDA(u32 adr, u32 i, char * txt) { RegList(16); sprintf(txt, "STMDA%s %s, {%s}", Condition[CONDITION(i)], Registre[REG_POS(i,16)], lreg); return txt;} static char * OP_STMDB(u32 adr, u32 i, char * txt) { RegList(16); sprintf(txt, "STMDB%s %s, {%s}", Condition[CONDITION(i)], Registre[REG_POS(i,16)], lreg); return txt;} static char * OP_STMIA_W(u32 adr, u32 i, char * txt) { RegList(16); sprintf(txt, "STMIA%s %s!, {%s}", Condition[CONDITION(i)], Registre[REG_POS(i,16)], lreg); return txt;} static char * OP_STMIB_W(u32 adr, u32 i, char * txt) { RegList(16); sprintf(txt, "STMIB%s %s!, {%s}", Condition[CONDITION(i)], Registre[REG_POS(i,16)], lreg); return txt;} static char * OP_STMDA_W(u32 adr, u32 i, char * txt) { RegList(16); sprintf(txt, "STMDA%s %s!, {%s}", Condition[CONDITION(i)], Registre[REG_POS(i,16)], lreg); return txt;} static char * OP_STMDB_W(u32 adr, u32 i, char * txt) { RegList(16); sprintf(txt, "STMDB%s %s!, {%s}", Condition[CONDITION(i)], Registre[REG_POS(i,16)], lreg); return txt;} static char * OP_STMIA2(u32 adr, u32 i, char * txt) { RegList(16); sprintf(txt, "STMIA%s %s, {%s}^", Condition[CONDITION(i)], Registre[REG_POS(i,16)], lreg); return txt;} static char * OP_STMIB2(u32 adr, u32 i, char * txt) { RegList(16); sprintf(txt, "STMIB%s %s, {%s}^", Condition[CONDITION(i)], Registre[REG_POS(i,16)], lreg); return txt;} static char * OP_STMDA2(u32 adr, u32 i, char * txt) { RegList(16); sprintf(txt, "STMDA%s %s, {%s}^", Condition[CONDITION(i)], Registre[REG_POS(i,16)], lreg); return txt;} static char * OP_STMDB2(u32 adr, u32 i, char * txt) { RegList(16); sprintf(txt, "STMDB%s %s, {%s}^", Condition[CONDITION(i)], Registre[REG_POS(i,16)], lreg); return txt;} static char * OP_STMIA2_W(u32 adr, u32 i, char * txt) { RegList(16); sprintf(txt, "STMIA%s %s!, {%s}^ ?????", Condition[CONDITION(i)], Registre[REG_POS(i,16)], lreg); return txt;} static char * OP_STMIB2_W(u32 adr, u32 i, char * txt) { RegList(16); sprintf(txt, "STMIB%s %s!, {%s}^ ?????", Condition[CONDITION(i)], Registre[REG_POS(i,16)], lreg); return txt;} static char * OP_STMDA2_W(u32 adr, u32 i, char * txt) { RegList(16); sprintf(txt, "STMDA%s %s!, {%s}^ ?????", Condition[CONDITION(i)], Registre[REG_POS(i,16)], lreg); return txt; } static char * OP_STMDB2_W(u32 adr, u32 i, char * txt) { RegList(16); sprintf(txt, "STMDB%s %s!, {%s}^ ?????", Condition[CONDITION(i)], Registre[REG_POS(i,16)], lreg); return txt; } //---------------------STC---------------------------------- static char * OP_STC_P_IMM_OFF(u32 adr, u32 i, char * txt) { if(CONDITION(i)==0xF) { sprintf(txt, "STC2 CP%X, CR%X, [%s, #%X]", (int)REG_POS(i, 8),(int)REG_POS(i, 12), Registre[REG_POS(i, 16)],(int)((i&0xFF)<<2)); return txt; } sprintf(txt, "STC%s %X, CP%X, [%s, #%X]",Condition[CONDITION(i)], (int)REG_POS(i, 8),(int)REG_POS(i, 12), Registre[REG_POS(i, 16)],(int)((i&0xFF)<<2)); return txt; } static char * OP_STC_M_IMM_OFF(u32 adr, u32 i, char * txt) { if(CONDITION(i)==0xF) { sprintf(txt, "STC2 CP%X, CR%X, [%s, #-%X]",(int)REG_POS(i, 8),(int)REG_POS(i, 12), Registre[REG_POS(i, 16)],(int)((i&0xFF)<<2)); return txt; } sprintf(txt, "STC%s CP%X, CR%X, [%s, #-%X]",Condition[CONDITION(i)], (int)REG_POS(i, 8),(int)REG_POS(i, 12), Registre[REG_POS(i, 16)], (int)((i&0xFF)<<2)); return txt; } static char * OP_STC_P_PREIND(u32 adr, u32 i, char * txt) { if(CONDITION(i)==0xF) { sprintf(txt, "STC2 CP%X, CR%X, [%s, #%X]!",(int)REG_POS(i, 8),(int)REG_POS(i, 12), Registre[REG_POS(i, 16)], (int)((i&0xFF)<<2)); return txt; } sprintf(txt, "STC%s CP%X, CR%X, [%s, #%X]!",Condition[CONDITION(i)], (int)REG_POS(i, 8),(int)REG_POS(i, 12), Registre[REG_POS(i, 16)], (int)((i&0xFF)<<2)); return txt; } static char * OP_STC_M_PREIND(u32 adr, u32 i, char * txt) { if(CONDITION(i)==0xF) { sprintf(txt, "STC2 CP%X, CR%X, [%s, #-%X]!",(int)REG_POS(i, 8),(int)REG_POS(i, 12), Registre[REG_POS(i, 16)], (int)((i&0xFF)<<2)); return txt; } sprintf(txt, "STC%s CP%X, CR%X, [%s, #-%X]!",Condition[CONDITION(i)], (int)REG_POS(i, 8),(int)REG_POS(i, 12), Registre[REG_POS(i, 16)], (int)((i&0xFF)<<2)); return txt; } static char * OP_STC_P_POSTIND(u32 adr, u32 i, char * txt) { if(CONDITION(i)==0xF) { sprintf(txt, "STC2 CP%X, CR%X, [%s], #%X",(int)REG_POS(i, 8),(int)REG_POS(i, 12), Registre[REG_POS(i, 16)], (int)((i&0xFF)<<2)); return txt; } sprintf(txt, "STC%s CP%X, CR%X, [%s], #%X",Condition[CONDITION(i)], (int)REG_POS(i, 8),(int)REG_POS(i, 12), Registre[REG_POS(i, 16)], (int)((i&0xFF)<<2)); return txt; } static char * OP_STC_M_POSTIND(u32 adr, u32 i, char * txt) { if(CONDITION(i)==0xF) { sprintf(txt, "STC2 CP%X, CR%X, [%s], #-%X",(int)REG_POS(i, 8),(int)REG_POS(i, 12), Registre[REG_POS(i, 16)], (int)((i&0xFF)<<2)); return txt; } sprintf(txt, "STC%s CP%X, CR%X, [%s], #-%X",Condition[CONDITION(i)], (int)REG_POS(i, 8),(int)REG_POS(i, 12), Registre[REG_POS(i, 16)], (int)((i&0xFF)<<2)); return txt; } static char * OP_STC_OPTION(u32 adr, u32 i, char * txt) { if(CONDITION(i)==0xF) { sprintf(txt, "STC2 CP%X, CR%X, [%s], {%X}",(int)REG_POS(i, 8),(int)REG_POS(i, 12), Registre[REG_POS(i, 16)], (int)(i&0xFF)); return txt; } sprintf(txt, "STC%s CP%X, CR%X, [%s], {%X}",Condition[CONDITION(i)], (int)REG_POS(i, 8),(int)REG_POS(i, 12), Registre[REG_POS(i, 16)], (int)(i&0xFF)); return txt; } //---------------------LDC---------------------------------- static char * OP_LDC_P_IMM_OFF(u32 adr, u32 i, char * txt) { if(CONDITION(i)==0xF) { sprintf(txt, "LDC2 CP%X, CR%X, [%s, #%X]",(int)REG_POS(i, 8),(int)REG_POS(i, 12), Registre[REG_POS(i, 16)], (int)((i&0xFF)<<2)); return txt; } sprintf(txt, "LDC%s CP%X, CR%X, [%s, #%X]",Condition[CONDITION(i)], (int)REG_POS(i, 8),(int)REG_POS(i, 12), Registre[REG_POS(i, 16)], (int)((i&0xFF)<<2)); return txt; } static char * OP_LDC_M_IMM_OFF(u32 adr, u32 i, char * txt) { if(CONDITION(i)==0xF) { sprintf(txt, "LDC2 CP%X, CR%X, [%s, #-%X]",(int)REG_POS(i, 8),(int)REG_POS(i, 12), Registre[REG_POS(i, 16)], (int)((i&0xFF)<<2)); return txt; } sprintf(txt, "LDC%s CP%X, CR%X, [%s, #-%X]",Condition[CONDITION(i)], (int)REG_POS(i, 8),(int)REG_POS(i, 12), Registre[REG_POS(i, 16)], (int)((i&0xFF)<<2)); return txt; } static char * OP_LDC_P_PREIND(u32 adr, u32 i, char * txt) { if(CONDITION(i)==0xF) { sprintf(txt, "LDC2 CP%X, CR%X, [%s, #%X]!",(int)REG_POS(i, 8),(int)REG_POS(i, 12), Registre[REG_POS(i, 16)], (int)((i&0xFF)<<2)); return txt; } sprintf(txt, "LDC%s CP%X, CR%X, [%s, #%X]!",Condition[CONDITION(i)], (int)REG_POS(i, 8),(int)REG_POS(i, 12), Registre[REG_POS(i, 16)], (int)((i&0xFF)<<2)); return txt; } static char * OP_LDC_M_PREIND(u32 adr, u32 i, char * txt) { if(CONDITION(i)==0xF) { sprintf(txt, "LDC2 CP%X, CR%X, [%s, #-%X]!",(int)REG_POS(i, 8),(int)REG_POS(i, 12), Registre[REG_POS(i, 16)], (int)((i&0xFF)<<2)); return txt; } sprintf(txt, "LDC%s CP%X, CR%X, [%s, #-%X]!",Condition[CONDITION(i)], (int)REG_POS(i, 8),(int)REG_POS(i, 12), Registre[REG_POS(i, 16)], (int)((i&0xFF)<<2)); return txt; } static char * OP_LDC_P_POSTIND(u32 adr, u32 i, char * txt) { if(CONDITION(i)==0xF) { sprintf(txt, "LDC2 CP%X, CR%X, [%s], #%X",(int)REG_POS(i, 8),(int)REG_POS(i, 12), Registre[REG_POS(i, 16)], (int)((i&0xFF)<<2)); return txt; } sprintf(txt, "LDC%s CP%X, CR%X, [%s], #%X",Condition[CONDITION(i)], (int)REG_POS(i, 8),(int)REG_POS(i, 12), Registre[REG_POS(i, 16)], (int)((i&0xFF)<<2)); return txt; } static char * OP_LDC_M_POSTIND(u32 adr, u32 i, char * txt) { if(CONDITION(i)==0xF) { sprintf(txt, "LDC2 CP%X, CR%X, [%s], #-%X", (int)REG_POS(i, 8), (int)REG_POS(i, 12), Registre[REG_POS(i, 16)], (int)((i&0xFF)<<2)); return txt; } sprintf(txt, "LDC%s CP%X, CR%X, [%s], #-%X",Condition[CONDITION(i)], (int)REG_POS(i, 8),(int)REG_POS(i, 12), Registre[REG_POS(i, 16)], (int)((i&0xFF)<<2)); return txt; } static char * OP_LDC_OPTION(u32 adr, u32 i, char * txt) { if(CONDITION(i)==0xF) { sprintf(txt, "LDC2 CP%X, CR%X, [%s], {%X}", (int)REG_POS(i, 8), (int)REG_POS(i, 12), Registre[REG_POS(i, 16)], (int)(i&0xFF)); return txt; } sprintf(txt, "LDC%s CP%X, CR%X, [%s], {%X}",Condition[CONDITION(i)], (int)REG_POS(i, 8), (int)REG_POS(i, 12), Registre[REG_POS(i, 16)], (int)(i&0xFF)); return txt; } /* * * The Enhanced DSP Extension LDRD and STRD instructions. * */ static char * OP_LDRD_STRD_POST_INDEX(u32 adr, u32 i, char * txt) { const char *direction = BIT5(i) ? "STR" : "LDR"; /* U bit - set = add, clear = sub */ char sign = BIT23(i) ? '+' : '-'; int txt_index = 0; txt_index += sprintf( &txt[txt_index], "%s%sD R%d, [R%d], ", direction, Condition[CONDITION(i)], (int)REG_POS(i, 12), (int)REG_POS(i, 16)); /* I bit - set = immediate, clear = reg */ if ( BIT22(i)) { sprintf( &txt[txt_index], "#%c%d", sign, (int)(((i>>4) & 0xF0) | (i&0xF)) ); } else { sprintf( &txt[txt_index], "%cR%d", sign, (int)REG_POS(i, 0)); } return txt; } static char * OP_LDRD_STRD_OFFSET_PRE_INDEX(u32 adr, u32 i, char * txt) { const char *direction = BIT5(i) ? "STR" : "LDR"; /* U bit - set = add, clear = sub */ char sign = BIT23(i) ? '+' : '-'; int txt_index = 0; txt_index += sprintf( &txt[txt_index], "%s%sD R%d, [R%d, ", direction, Condition[CONDITION(i)], (int)REG_POS(i, 12), (int)REG_POS(i, 16)); /* I bit - set = immediate, clear = reg */ if ( BIT22(i)) { if ( BIT21(i)) { /* pre-index */ sprintf( &txt[txt_index], "#%c%d]!", sign, (int)(((i>>4)&0xF0)|(i&0xF))); } else { /* offset */ sprintf( &txt[txt_index], "#%c%d]", sign, (int)(((i>>4)&0xF0)|(i&0xF))); } } else { if ( BIT21(i)) { /* pre-index */ sprintf( &txt[txt_index], "%c%d]!", sign, (int)REG_POS(i, 0)); } else { /* offset */ sprintf( &txt[txt_index], "%c%d]", sign, (int)REG_POS(i, 0)); } } return txt; } //----------------MCR----------------------- static char * OP_MCR(u32 adr, u32 i, char * txt) { if(CONDITION(i)==0xF) { sprintf(txt, "MCR2 CP%d, %X, %s, CR%d, CR%d, %X",(int)REG_POS(i, 8), (int)((i>>21)&7), Registre[REG_POS(i, 12)], (int)REG_POS(i, 16), (int)REG_POS(i, 0), (int)((i>>5)&0x7)); return txt; } sprintf(txt, "MCR%s CP%d, %X, %s, CR%d, CR%d, %X",Condition[CONDITION(i)], (int)REG_POS(i, 8), (int)((i>>21)&7), Registre[REG_POS(i, 12)], (int)REG_POS(i, 16), (int)REG_POS(i, 0), (int)((i>>5)&0x7)); return txt; } //----------------MRC----------------------- static char * OP_MRC(u32 adr, u32 i, char * txt) { if(CONDITION(i)==0xF) { sprintf(txt, "MRC2 CP%d, %X, %s, CR%d, CR%d, %X",(int)REG_POS(i, 8), (int)((i>>21)&7), Registre[REG_POS(i, 12)], (int)REG_POS(i, 16), (int)REG_POS(i, 0), (int)((i>>5)&0x7)); return txt; } sprintf(txt, "MRC%s CP%d, %X, %s, CR%d, CR%d, %X",Condition[CONDITION(i)], (int)REG_POS(i, 8), (int)((i>>21)&7), Registre[REG_POS(i, 12)], (int)REG_POS(i, 16), (int)REG_POS(i, 0), (int)((i>>5)&0x7)); return txt; } //--------------SWI-------------------------- static char * OP_SWI(u32 adr, u32 i, char * txt) { sprintf(txt, "SWI%s %X",Condition[CONDITION(i)], (int)((i&0xFFFFFF)>>16)); return txt; } //----------------BKPT------------------------- static char * OP_BKPT(u32 adr, u32 i, char * txt) { sprintf(txt, "BKPT #%X",(int)(((i>>4)&0xFFF)|(i&0xF))); return txt; } //----------------CDP----------------------- static char * OP_CDP(u32 adr, u32 i, char * txt) { sprintf(txt, "CDP-------------------------------"); return txt; } //------------------------------------------------------------ // THUMB //------------------------------------------------------------ #define REG_NUM(i, n) (((i)>>n)&0x7) static char * OP_UND_THUMB(u32 adr, u32 i, char * txt) { sprintf(txt, "----"); return txt; } static char * OP_LSL_0(u32 adr, u32 i, char * txt) { sprintf(txt, "LSL %s, %s, #0", Registre[REG_NUM(i, 0)], Registre[REG_NUM(i, 3)]); return txt; } static char * OP_LSL(u32 adr, u32 i, char * txt) { sprintf(txt, "LSL %s, %s, #%X", Registre[REG_NUM(i, 0)], Registre[REG_NUM(i, 3)], (int)((i>>6) & 0x1F)); return txt; } static char * OP_LSR_0(u32 adr, u32 i, char * txt) { sprintf(txt, "LSR %s, %s, #0", Registre[REG_NUM(i, 0)], Registre[REG_NUM(i, 3)]); return txt; } static char * OP_LSR(u32 adr, u32 i, char * txt) { sprintf(txt, "LSR %s, %s, #%X", Registre[REG_NUM(i, 0)], Registre[REG_NUM(i, 3)], (int)((i>>6) & 0x1F)); return txt; } static char * OP_ASR_0(u32 adr, u32 i, char * txt) { sprintf(txt, "ASR %s, %s, #0", Registre[REG_NUM(i, 0)], Registre[REG_NUM(i, 3)]); return txt; } static char * OP_ASR(u32 adr, u32 i, char * txt) { sprintf(txt, "ASR %s, %s, #%X", Registre[REG_NUM(i, 0)], Registre[REG_NUM(i, 3)], (int)((i>>6) & 0x1F)); return txt; } static char * OP_ADD_REG(u32 adr, u32 i, char * txt) { sprintf(txt, "ADD %s, %s, %s", Registre[REG_NUM(i, 0)], Registre[REG_NUM(i, 3)], Registre[REG_NUM(i, 6)]); return txt; } static char * OP_SUB_REG(u32 adr, u32 i, char * txt) { sprintf(txt, "SUB %s, %s, %s", Registre[REG_NUM(i, 0)], Registre[REG_NUM(i, 3)], Registre[REG_NUM(i, 6)]); return txt; } static char * OP_ADD_IMM3(u32 adr, u32 i, char * txt) { sprintf(txt, "ADD %s, %s, #%X", Registre[REG_NUM(i, 0)], Registre[REG_NUM(i, 3)], (int)REG_NUM(i, 6)); return txt; } static char * OP_SUB_IMM3(u32 adr, u32 i, char * txt) { sprintf(txt, "SUB %s, %s, #%X", Registre[REG_NUM(i, 0)], Registre[REG_NUM(i, 3)], (int)REG_NUM(i, 6)); return txt; } static char * OP_MOV_IMM8(u32 adr, u32 i, char * txt) { sprintf(txt, "MOV %s, #%X", Registre[REG_NUM(i, 8)], (int)(i&0xFF)); return txt; } static char * OP_CMP_IMM8(u32 adr, u32 i, char * txt) { sprintf(txt, "CMP %s, #%X", Registre[REG_NUM(i, 8)], (int)(i&0xFF)); return txt; } static char * OP_ADD_IMM8(u32 adr, u32 i, char * txt) { sprintf(txt, "ADD %s, #%X", Registre[REG_NUM(i, 8)], (int)(i&0xFF)); return txt; } static char * OP_SUB_IMM8(u32 adr, u32 i, char * txt) { sprintf(txt, "SUB %s, #%X", Registre[REG_NUM(i, 8)], (int)(i&0xFF)); return txt; } static char * OP_AND(u32 adr, u32 i, char * txt) { sprintf(txt, "AND %s, %s", Registre[REG_NUM(i, 0)], Registre[REG_NUM(i, 3)]); return txt; } static char * OP_EOR(u32 adr, u32 i, char * txt) { sprintf(txt, "EOR %s, %s", Registre[REG_NUM(i, 0)], Registre[REG_NUM(i, 3)]); return txt; } static char * OP_LSL_REG(u32 adr, u32 i, char * txt) { sprintf(txt, "LSL %s, %s", Registre[REG_NUM(i, 0)], Registre[REG_NUM(i, 3)]); return txt; } static char * OP_LSR_REG(u32 adr, u32 i, char * txt) { sprintf(txt, "LSR %s, %s", Registre[REG_NUM(i, 0)], Registre[REG_NUM(i, 3)]); return txt; } static char * OP_ASR_REG(u32 adr, u32 i, char * txt) { sprintf(txt, "ASR %s, %s", Registre[REG_NUM(i, 0)], Registre[REG_NUM(i, 3)]); return txt; } static char * OP_ADC_REG(u32 adr, u32 i, char * txt) { sprintf(txt, "ADC %s, %s", Registre[REG_NUM(i, 0)], Registre[REG_NUM(i, 3)]); return txt; } static char * OP_SBC_REG(u32 adr, u32 i, char * txt) { sprintf(txt, "SBC %s, %s", Registre[REG_NUM(i, 0)], Registre[REG_NUM(i, 3)]); return txt; } static char * OP_ROR_REG(u32 adr, u32 i, char * txt) { sprintf(txt, "ROR %s, %s", Registre[REG_NUM(i, 0)], Registre[REG_NUM(i, 3)]); return txt; } static char * OP_TST(u32 adr, u32 i, char * txt) { sprintf(txt, "TST %s, %s", Registre[REG_NUM(i, 0)], Registre[REG_NUM(i, 3)]); return txt; } static char * OP_NEG(u32 adr, u32 i, char * txt) { sprintf(txt, "NEG %s, %s", Registre[REG_NUM(i, 0)], Registre[REG_NUM(i, 3)]); return txt; } static char * OP_CMP(u32 adr, u32 i, char * txt) { sprintf(txt, "CMP %s, %s", Registre[REG_NUM(i, 0)], Registre[REG_NUM(i, 3)]); return txt; } static char * OP_CMN(u32 adr, u32 i, char * txt) { sprintf(txt, "CMN %s, %s", Registre[REG_NUM(i, 0)], Registre[REG_NUM(i, 3)]); return txt; } static char * OP_ORR(u32 adr, u32 i, char * txt) { sprintf(txt, "ORR %s, %s", Registre[REG_NUM(i, 0)], Registre[REG_NUM(i, 3)]); return txt; } static char * OP_MUL_REG(u32 adr, u32 i, char * txt) { sprintf(txt, "MUL %s, %s", Registre[REG_NUM(i, 0)], Registre[REG_NUM(i, 3)]); return txt; } static char * OP_BIC(u32 adr, u32 i, char * txt) { sprintf(txt, "BIC %s, %s", Registre[REG_NUM(i, 0)], Registre[REG_NUM(i, 3)]); return txt; } static char * OP_MVN(u32 adr, u32 i, char * txt) { sprintf(txt, "MVN %s, %s", Registre[REG_NUM(i, 0)], Registre[REG_NUM(i, 3)]); return txt; } static char * OP_ADD_SPE(u32 adr, u32 i, char * txt) { u8 Rd = (i&7) | ((i>>4)&8); sprintf(txt, "ADD %s, %s", Registre[Rd], Registre[REG_POS(i, 3)]); return txt; } static char * OP_CMP_SPE(u32 adr, u32 i, char * txt) { u8 Rd = (i&7) | ((i>>4)&8); sprintf(txt, "CMP %s, %s", Registre[Rd], Registre[REG_POS(i, 3)]); return txt; } static char * OP_MOV_SPE(u32 adr, u32 i, char * txt) { u8 Rd = (i&7) | ((i>>4)&8); sprintf(txt, "MOV %s, %s", Registre[Rd], Registre[REG_POS(i, 3)]); return txt; } static char * OP_BX_THUMB(u32 adr, u32 i, char * txt) { sprintf(txt, "BX %s", Registre[REG_POS(i, 3)]); return txt; } static char * OP_BLX_THUMB(u32 adr, u32 i, char * txt) { sprintf(txt, "BLX %s", Registre[REG_POS(i, 3)]); return txt; } static char * OP_LDR_PCREL(u32 adr, u32 i, char * txt) { sprintf(txt, "LDR %s, [PC, #%X]", Registre[REG_NUM(i, 8)], (int)((i&0xFF)<<2)); return txt; } static char * OP_STR_REG_OFF(u32 adr, u32 i, char * txt) { sprintf(txt, "STR %s, [%s, %s]", Registre[REG_NUM(i, 0)], Registre[REG_NUM(i, 3)], Registre[REG_NUM(i, 6)]); return txt; } static char * OP_STRH_REG_OFF(u32 adr, u32 i, char * txt) { sprintf(txt, "STRH %s, [%s, %s]", Registre[REG_NUM(i, 0)], Registre[REG_NUM(i, 3)], Registre[REG_NUM(i, 6)]); return txt; } static char * OP_STRB_REG_OFF(u32 adr, u32 i, char * txt) { sprintf(txt, "STRB %s, [%s, %s]", Registre[REG_NUM(i, 0)], Registre[REG_NUM(i, 3)], Registre[REG_NUM(i, 6)]); return txt; } static char * OP_LDRSB_REG_OFF(u32 adr, u32 i, char * txt) { sprintf(txt, "LDRSB %s, [%s, %s]", Registre[REG_NUM(i, 0)], Registre[REG_NUM(i, 3)], Registre[REG_NUM(i, 6)]); return txt; } static char * OP_LDR_REG_OFF(u32 adr, u32 i, char * txt) { sprintf(txt, "LDR %s, [%s, %s]", Registre[REG_NUM(i, 0)], Registre[REG_NUM(i, 3)], Registre[REG_NUM(i, 6)]); return txt; } static char * OP_LDRH_REG_OFF(u32 adr, u32 i, char * txt) { sprintf(txt, "LDRH %s, [%s, %s]", Registre[REG_NUM(i, 0)], Registre[REG_NUM(i, 3)], Registre[REG_NUM(i, 6)]); return txt; } static char * OP_LDRB_REG_OFF(u32 adr, u32 i, char * txt) { sprintf(txt, "LDRB %s, [%s, %s]", Registre[REG_NUM(i, 0)], Registre[REG_NUM(i, 3)], Registre[REG_NUM(i, 6)]); return txt; } static char * OP_LDRSH_REG_OFF(u32 adr, u32 i, char * txt) { sprintf(txt, "LDRSH %s, [%s, %s]", Registre[REG_NUM(i, 0)], Registre[REG_NUM(i, 3)], Registre[REG_NUM(i, 6)]); return txt; } static char * OP_STR_IMM_OFF(u32 adr, u32 i, char * txt) { sprintf(txt, "STR %s, [%s, #%X]", Registre[REG_NUM(i, 0)], Registre[REG_NUM(i, 3)], (int)((i>>4)&0x7C)); return txt; } static char * OP_LDR_IMM_OFF(u32 adr, u32 i, char * txt) { sprintf(txt, "LDR %s, [%s, #%X]", Registre[REG_NUM(i, 0)], Registre[REG_NUM(i, 3)], (int)((i>>4)&0x7C)); return txt; } static char * OP_STRB_IMM_OFF(u32 adr, u32 i, char * txt) { sprintf(txt, "STRB %s, [%s, #%X]", Registre[REG_NUM(i, 0)], Registre[REG_NUM(i, 3)], (int)((i>>6)&0x1F)); return txt; } static char * OP_LDRB_IMM_OFF(u32 adr, u32 i, char * txt) { sprintf(txt, "LDRB %s, [%s, #%X]", Registre[REG_NUM(i, 0)], Registre[REG_NUM(i, 3)], (int)((i>>6)&0x1F)); return txt; } static char * OP_STRH_IMM_OFF(u32 adr, u32 i, char * txt) { sprintf(txt, "STRH %s, [%s, #%X]", Registre[REG_NUM(i, 0)], Registre[REG_NUM(i, 3)], (int)((i>>5)&0x3E)); return txt; } static char * OP_LDRH_IMM_OFF(u32 adr, u32 i, char * txt) { sprintf(txt, "LDRH %s, [%s, #%X]", Registre[REG_NUM(i, 0)], Registre[REG_NUM(i, 3)], (int)((i>>5)&0x3E)); return txt; } static char * OP_STR_SPREL(u32 adr, u32 i, char * txt) { sprintf(txt, "STR %s, [SP, #%X]", Registre[REG_NUM(i, 8)], (int)((i&0xFF)<<2)); return txt; } static char * OP_LDR_SPREL(u32 adr, u32 i, char * txt) { sprintf(txt, "LDR %s, [SP, #%X]", Registre[REG_NUM(i, 8)], (int)((i&0xFF)<<2)); return txt; } static char * OP_ADD_2PC(u32 adr, u32 i, char * txt) { sprintf(txt, "ADD %s, PC, #%X", Registre[REG_NUM(i, 8)], (int)((i&0xFF)<<2)); return txt; } static char * OP_ADD_2SP(u32 adr, u32 i, char * txt) { sprintf(txt, "ADD %s, SP, #%X", Registre[REG_NUM(i, 8)], (int)((i&0xFF)<<2)); return txt; } static char * OP_ADJUST_P_SP(u32 adr, u32 i, char * txt) { sprintf(txt, "ADD SP, #%X", (int)((i&0x7F)<<2)); return txt; } static char * OP_ADJUST_M_SP(u32 adr, u32 i, char * txt) { sprintf(txt, "SUB SP, #%X", (int)((i&0x7F)<<2)); return txt; } static char * OP_PUSH(u32 adr, u32 i, char * txt) { RegList(8); sprintf(txt, "PUSH {%s}", lreg); return txt; } static char * OP_PUSH_LR(u32 adr, u32 i, char * txt) { RegList(8); sprintf(txt, "PUSH {%s, LR}", lreg); return txt; } static char * OP_POP(u32 adr, u32 i, char * txt) { RegList(8); sprintf(txt, "POP {%s}", lreg); return txt; } static char * OP_POP_PC(u32 adr, u32 i, char * txt) { RegList(8); sprintf(txt, "POP {%s, PC}", lreg); return txt; } static char * OP_BKPT_THUMB(u32 adr, u32 i, char * txt) { sprintf(txt, "BKPT"); return txt; } static char * OP_STMIA_THUMB(u32 adr, u32 i, char * txt) { RegList(8); sprintf(txt, "STMIA %s!, {%s}", Registre[REG_NUM(i, 8)], lreg); return txt; } static char * OP_LDMIA_THUMB(u32 adr, u32 i, char * txt) { RegList(8); sprintf(txt, "LDMIA %s!, {%s}", Registre[REG_NUM(i, 8)], lreg); return txt; } static char * OP_B_COND(u32 adr, u32 i, char * txt) { sprintf(txt, "B%s #%X", Condition[(i>>8)&0xF], (int)(adr+(((s32)((signed char)(i&0xFF)))<<1)+4)); return txt; } static char * OP_SWI_THUMB(u32 adr, u32 i, char * txt) { sprintf(txt, "SWI #%X", (int)(i & 0xFF)); return txt; } #define SIGNEEXT_IMM11(i) (((i)&0x7FF) | (BIT10(i) * 0xFFFFF800)) static char * OP_B_UNCOND(u32 adr, u32 i, char * txt) { sprintf(txt, "B #%X", (int)(adr+(SIGNEEXT_IMM11(i)<<1)+4)); return txt; } u32 part = 0; static char * OP_BLX(u32 adr, u32 i, char * txt) { sprintf(txt, "BLX #%X", (int)(part + ((i&0x7FF)<<1))&0xFFFFFFFC); return txt; } static char * OP_BL_10(u32 adr, u32 i, char * txt) { part = adr+4 + (SIGNEEXT_IMM11(i)<<12); sprintf(txt, "calculating high part of the address"); return txt; } static char * OP_BL_11(u32 adr, u32 i, char * txt) { sprintf(txt, "BL #%X", (int)(part + ((i&0x7FF)<<1))&0xFFFFFFFC); return txt; } #define TABDECL(x) x const DisasmOpFunc des_arm_instructions_set[4096] = { #include "instruction_tabdef.inc" }; const DisasmOpFunc des_thumb_instructions_set[1024] = { #include "thumb_tabdef.inc" }; desmume/src/mem.h000664 001750 001750 00000010177 12755534123 015074 0ustar00sergiosergio000000 000000 /* Copyright (C) 2005 Theo Berkau Copyright (C) 2005-2006 Guillaume Duhamel Copyright (C) 2008-2010 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the this software. If not, see . */ #ifndef MEM_H #define MEM_H #include #include #include "types.h" //this was originally declared in MMU.h but we suffered some organizational problems and had to remove it enum MMU_ACCESS_TYPE { MMU_AT_CODE, //used for cpu prefetches MMU_AT_DATA, //used for cpu read/write MMU_AT_GPU, //used for gpu read/write MMU_AT_DMA, //used for dma read/write (blocks access to TCM) MMU_AT_DEBUG, //used for emulator debugging functions (bypasses some debug handling) }; static INLINE u8 T1ReadByte(u8* const mem, const u32 addr) { return mem[addr]; } static INLINE u16 T1ReadWord_guaranteedAligned(void* const mem, const u32 addr) { assert((addr&1)==0); #ifdef MSB_FIRST return (((u8*)mem)[addr + 1] << 8) | ((u8*)mem)[addr]; #else return *(u16*)((u8*)mem + addr); #endif } static INLINE u16 T1ReadWord(void* const mem, const u32 addr) { #ifdef MSB_FIRST return (((u8*)mem)[addr + 1] << 8) | ((u8*)mem)[addr]; #else return *((u16 *) ((u8*)mem + addr)); #endif } static INLINE u32 T1ReadLong_guaranteedAligned(u8* const mem, const u32 addr) { assert((addr&3)==0); #ifdef MSB_FIRST return (mem[addr + 3] << 24 | mem[addr + 2] << 16 | mem[addr + 1] << 8 | mem[addr]); #else return *(u32*)(mem + addr); #endif } static INLINE u32 T1ReadLong(u8* const mem, u32 addr) { addr &= ~3; #ifdef MSB_FIRST return (mem[addr + 3] << 24 | mem[addr + 2] << 16 | mem[addr + 1] << 8 | mem[addr]); #else return *(u32*)(mem + addr); #endif } static INLINE u64 T1ReadQuad(u8* const mem, const u32 addr) { #ifdef MSB_FIRST return (u64(mem[addr + 7]) << 56 | u64(mem[addr + 6]) << 48 | u64(mem[addr + 5]) << 40 | u64(mem[addr + 4]) << 32 | u64(mem[addr + 3]) << 24 | u64(mem[addr + 2]) << 16 | u64(mem[addr + 1]) << 8 | u64(mem[addr ])); #else return *((u64 *) (mem + addr)); #endif } static INLINE void T1WriteByte(u8* const mem, const u32 addr, const u8 val) { mem[addr] = val; } static INLINE void T1WriteWord(u8* const mem, const u32 addr, const u16 val) { #ifdef MSB_FIRST mem[addr + 1] = val >> 8; mem[addr] = val & 0xFF; #else *((u16 *) (mem + addr)) = val; #endif } static INLINE void T1WriteLong(u8* const mem, const u32 addr, const u32 val) { #ifdef MSB_FIRST 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 } static INLINE void T1WriteQuad(u8* const mem, const u32 addr, const u64 val) { #ifdef MSB_FIRST mem[addr + 7] = (val >> 56); mem[addr + 6] = (val >> 48) & 0xFF; mem[addr + 5] = (val >> 40) & 0xFF; mem[addr + 4] = (val >> 32) & 0xFF; mem[addr + 3] = (val >> 24) & 0xFF; mem[addr + 2] = (val >> 16) & 0xFF; mem[addr + 1] = (val >> 8) & 0xFF; mem[addr] = val & 0xFF; #else *((u64 *) (mem + addr)) = val; #endif } static INLINE u16 HostReadWord(u8* const mem, const u32 addr) { return *((u16 *) (mem + addr)); } static INLINE void HostWriteWord(u8* const mem, const u32 addr, const u16 val) { *((u16 *) (mem + addr)) = val; } static INLINE void HostWriteLong(u8* const mem, const u32 addr, const u32 val) { *((u32 *) (mem + addr)) = val; } static INLINE void HostWriteTwoWords(u8* const mem, const u32 addr, const u32 val) { #ifdef MSB_FIRST *((u16 *) (mem + addr + 2)) = val >> 16; *((u16 *) (mem + addr)) = val & 0xFFFF; #else *((u32 *) (mem + addr)) = val; #endif } #endif desmume/src/libretro-common/net/test/http_test000755 001750 001750 00000037030 12755534123 022761 0ustar00sergiosergio000000 000000 ELF> @@X6@8@@@@@@ÀÀ@@@@$!$! (!(!`(!`àè @!@!`@!`ÐÐ@@DDPåtd@@üüQåtd/lib64/ld-linux-x86-64.so.2GNU GNUtñ*ÀïüvˆÅ¸¯÷,‡h1ª„×n]{®ELÐΛ0¼>Ü 7!†(´sQ¡ libc.so.6socketconnectsignalselectreallocmemchrstrtolcallocstrlensendgetaddrinfo__errno_locationrecvstrtoulsetsockoptmalloc__ctype_b_locclosefreeaddrinfofcntlmemmove__libc_start_mainsnprintffree__gmon_start__GLIBC_2.3GLIBC_2.2.5ii ëui õ#`0#`8#`@#`H#`P#`X#``#`h#`p#` x#` €#` ˆ#` #` ˜#` #`¨#`°#`¸#`À#`È#`Ð#`Ø#`à#`è#`ð#`HƒìH‹% H…Àtè«HƒÄÃÿ5 ÿ% @ÿ% héàÿÿÿÿ% héÐÿÿÿÿ%  héÀÿÿÿÿ% hé°ÿÿÿÿ%ú hé ÿÿÿÿ%ò héÿÿÿÿ%ê hé€ÿÿÿÿ%â hépÿÿÿÿ%Ú hé`ÿÿÿÿ%Ò h éPÿÿÿÿ%Ê h é@ÿÿÿÿ% h é0ÿÿÿÿ%º h é ÿÿÿÿ%² h éÿÿÿÿ%ª héÿÿÿÿ%¢ héðþÿÿÿ%š héàþÿÿÿ%’ héÐþÿÿÿ%Š héÀþÿÿÿ%‚ hé°þÿÿÿ%z hé þÿÿÿ%r héþÿÿÿ%j hé€þÿÿÿ%b hépþÿÿÿ%Z hé`þÿÿÿ%j fUSHƒì(HÇD$HÇD$è“ ƒÊÿ„À„¢¿x@è>H‰Åëf„H‹T$H‹t$¿Ð@1ÀèzþÿÿHT$Ht$H‰ïè(„ÀtÔ¿ç@èúH‰Ã€1Ò1öH‰ßè„ÀtðHt$1ÒH‰ßèa ¾H‰Â¿@1ÀèþÿÿH‰ïè• H‰ßè è( 1ÒHƒÄ(‰Ð[]Ãf.„1íI‰Ñ^H‰âHƒäðPTIÇÀð@HÇÁ€@HÇǰ @èþÿÿôfD¸$`UH-$`HƒøH‰åv¸H…Àt]¿$`ÿàf„]Ã@f.„¾$`UHî$`HÁþH‰åH‰ðHÁè?HÆHÑþt¸H…Àt ]¿$`ÿà]ÃfD€=Á uUH‰åènÿÿÿ]Æ® óÃ@¿8!`Hƒ?u듸H…ÀtñUH‰åÿÐ]ézÿÿÿf.„€>uEAUATI‰õUSA‰üH‰ÕH‰ËHƒìH…Ét ¹@H‰ÚH‰îD‰çè­üÿÿH…À~HÅH)ÃuàHƒÄ[]A\A]óÃ@…ÀyÌèGüÿÿƒ8 uÂAÆEëÛf.„€>u;H‰ÐSH‰ÊH‰ó1ÉH‰ÆèüÿÿHƒø~ [Àt…Àx"ÆHÇÀÿÿÿÿ[ÃfDHÇÀÿÿÿÿÄèÛûÿÿƒ8 uÔ1À[ÃfATUI‰üS¾(¿èZüÿÿH…Àt}L‰çH‰ÃèÚûÿÿHhH‰ïè~üÿÿH…ÀH‰CtKL‰æH‰ÇH‰êè ¿@¹L‰æó¦uH‹CHƒÀH‰CH‰H‰Ø[]A\ÀH‹{H…ÿtè*ûÿÿH‰ßè"ûÿÿ[1À]A\Ã1ÀëÐ@H…ÿt;H‹W¶ €ù:wH¾€¸H£Îs óÄHƒÂ1ÀH‰WÃD1ÀÃf.„H…ÿt;H‹G€8t2USH‰ûHƒìÆH‹oÇG P€}:tHƒÅ¸H‰kHƒÄ[]Ã1ÀÃDèÓûÿÿH¾UH‹öDPu 1ÀHƒÄ[]ÃH}Hsº èvûÿÿH‹k‰C €}/t¤1ÀëÓDH…ÿtSH‰ûH‹H…ÿtèúÿÿH‰ß[éúÿÿóÃ@f.„H‹GÃf.„H…ÿ„AUATUSH‰ýHƒìhD‹g H‹HÇD$HÇD$ HÇD$(è „À„CD‰áH|$ Ld$0º&@¾1Àè úÿÿ1À¹L‰çóH«Ht$ HL$L‰âH‰ßÇD$8装ÀˆóH‹D$H…À„å‹P ‹p‹xè¿úÿÿHL$A¸º¾‰Ç‰ÃHÇD$HÇD$è?ùÿÿH‹D$‰ß‹PH‹pè<úÿÿ…ÀH‹|$…wè:‰ßèC„À„áƒûÿ„jHt$ ¹º @‰ßÆD$ è7üÿÿL‹mL‰ïèûøÿÿHt$ H‰ÁL‰ê‰ßèüÿÿHt$ ¹ º@‰ßèüÿÿHt$ ¹º@‰ßèíûÿÿL‹mL‰ïè±øÿÿHt$ H‰ÁL‰ê‰ßèÏûÿÿ‹M ƒùPtoº%@¾L‰ç1ÀHÇD$0HÇD$8è¡øÿÿL‰á‹HƒÁ‚ÿþþþ÷Ò!Ð%€€€€té‰ÂHt$ ‰ßÁê©€€DÂHQHDʉÂÂL‰âHƒÙL)áèXûÿÿHt$ ¹º@‰ßèBûÿÿHt$ ¹º)@‰ßè,ûÿÿHt$ ¹º@‰ßèûÿÿ€|$ t?‰ßèHƒÄh1À[]A\A]ÃèÉßèü@1ÀHƒÄh[]A\A]Ã1ÀÃD¿0èFøÿÿ¿‰Ç@ÿÿÿÿÆ@Æ@ H‰ÅÆ@ HÇ@HÇ@HÇ@ è øÿÿH…ÀH‰E(„pÿÿÿH‰è딉ßèƒë‰H…ÿt ‹Ã„1ÀÃf.„H…ÿ„·AWAVAUATI‰ôUSH‰ÕH‰ûHƒì€ uo¶G<Ž®ƒè<†CM…ätH‹CI‰$H…ít€{ t{HÇE€{”ÀHƒÄ[]A\A]A^A_ÃDL‰þHsH‹CH9ÆH‰s„ªH9ðs¨ÆC ÆC¸ÇCÿÿÿÿHƒÄ[]A\A]A^A_ĸÃf.„H‹CH‰EëƒfDH‹WH‹O HG H‰ÆH‰D$H)ÑHW(‹?è¾ùÿÿH…ÀI‰Çx‹I‰ÆH‹C LsHPÀI9ÖƒÎD¶kL‰sA€ý~hé f.„¿=@¹H‰Æó¦…@ÿÿÿHx º 1öè›öÿÿ‰CH‹C(ÆCIvL‹4$H‰ÇI)öL‰òèjöÿÿD¶kL‰sA€ý½H‹{(L‰ò¾ J7H‰$è¾õÿÿH…ÀI‰Æ„£ÆH‹C(I9ÆtA€~ÿ tW€{„eÿÿÿ¿E@¹H‰Æó¦tL¿V@¹H‰Æó¦uÆC €8…fÿÿÿ€{ ÆC…XÿÿÿÆCéOÿÿÿ€AÆFÿH‹C(ëžDHxÆC º 1öèdõÿÿH‰CH‹C(ë–M‰÷HÇCAƒíA€ý‡ÎýÿÿM…ÿ„„¶C <…ìýÿÿ¶C<t3<…¡ýÿÿH‹CL9ø‡7H‰ÂI)ÇÆC¶CHS<H‰SH‰SuÍM‰øLCL‹sL‰ÂL‰CL)òHƒú†WýÿÿL‹k(Hƒê¾ KDK|5H‰$èjôÿÿH…ÀI‰Ç„+ýÿÿK|51öºèÝôÿÿH‹{IwL‹<$I‰ÆH‰{H{(I)÷L‰úè«ôÿÿM…öL‰sÆC…*ÿÿÿH‹sH‹{(ÆCH‰sèuôÿÿH‰C(¶C é ÿÿÿ„HG H‰D$H‹SH‹K H‹t$‹;H)ÑHS(è÷ÿÿH…ÀI‰ÇxeH‹S HCHJÀH9È‚¿þÿÿH4H‹{(H‰s èôÿÿH‰C(é¥þÿÿDL)øL{H‰CéMüÿÿH4H‹{(M‰þH‰s èÜóÿÿLsH‰C(éýÿÿ€{ …züÿÿH‹sH‹{(E1ÿÆCè±óÿÿH‰C(1ÀérÿÿÿH‹{(ÆCè™óÿÿH‹sH‰C(H‹Cé8üÿÿ„H…ÿt‹GøÿÿÿÿÃH…ÿtC„ÒtH…ötH‹GH‰H‹G(ÃfD€ u ‹G-ȃøcvÖH…ötHÇ1ÀÃfD1ÀÃDH…ÿtSH‰û‹?ƒÿÿtè‹H‰ß[éòñÿÿfóÃ@f.„¶G „Àu‹G-ȃøc—ÀóÄé óÿÿf.„éóÿÿf.„S¾1À‰ûèÑñÿÿ€Ì‰ß¾‰Â1Àè¾ñÿÿ…À”À[Àéûñÿÿf.„éKòÿÿf.„H…ÒtEATA‰üUH‰õSH‰Óë @HÅH)Ãt 1ÉH‰ÚH‰îD‰çè€ñÿÿH…Àã[1À]A\Ã@[¸]A\øÃH…ÒtEATA‰üUH‰õSH‰Óë @HÅH)Ãt 1ÉH‰ÚH‰îD‰çèàðÿÿH…Àã[1À]A\Ã@[¸]A\øÀ=¢ t¸ÃHƒì¾¿ è]ñÿÿÆ ¸HƒÄÃff.„óÃf.„@H…ÒtSHƒêtw¶HOLF„ÀˆtpHúë€IƒÀA¶pÿHƒÁ@„ö@ˆqÿtBH‰ÈH)øH9Êu߯L‰Æë €1À€>tH)ÆfDHƒÀ€<uöóÃóÃf.„óÃI‰ðH‰ú1Àë½1ÀÃATUH‰ÕSH‰ûI‰ôèðÿÿI‰ÁH<H‰èL)ȺI9éHFÐL‰æè=ÿÿÿ[LÈ]A\ÃDAWAVA‰ÿAUATL%– UH-– SI‰öI‰ÕL)åHƒìHÁýè/ïÿÿH…ít 1Û„L‰êL‰öD‰ÿAÿÜHƒÃH9ëuêHƒÄ[]A\A]A^A_Ãf.„óÃHƒìHƒÄÃhttp://GET / HTTP/1.1 Host: :%iConnection: close HTTP/1.Content-Length: Transfer-Encoding: chunkedhttp://buildbot.libretro.com/nightly/win-x86/latest/mednafen_psx_libretro.dll.zip%.9lu / %.9lu http://www.wikipedia.org/%.*s ;üøíÿÿH¨ïÿÿˆðÿÿˆñÿÿpøñÿÿ¸Xòÿÿèøòÿÿ(Hóÿÿ@Øóÿÿ€ôÿÿ ôÿÿ¸÷ÿÿ8÷ÿÿ0˜ûÿÿ°¨ûÿÿÈøûÿÿà(üÿÿHüÿÿ@XüÿÿXhüÿÿp˜üÿÿ¨üÿÿ¨¸üÿÿÀýÿÿXýÿÿ@˜ýÿÿX¨ýÿÿp8þÿÿˆxþÿÿ¸èþÿÿzRx hïÿÿ*zRx $¨ìÿÿ FJ w€?;*3$"DDðÿÿeGBŒD †A(ƒM0i(Aà AÆBÌBÍF0ƒ†Œ,Œ8ðÿÿ^IƒW ÃH QÃWƒMÃ<¼hðÿÿœBŒA†D ƒf ABH W CBD üÈðÿÿC<ñÿÿ‹O†AƒG eAÃAÆJ ƒ†Z AÃAÆD TPñÿÿ"FƒUÃt`ñÿÿ\ŒXñÿÿÿKBŒA †A(ƒGV (Cà AÆBÌBÍD V(Aà AÆBÌBÍLƒ†Œìøóÿÿ|ôÿÿXKBŽB B(ŒD0†A8ƒJPH 8AÃ0AÆ(BÌ BÍBÎBÏF u8AÃ0AÆ(BÌ BÍBÎBÏYPƒ†ŒŽ„à÷ÿÿœØ÷ÿÿK´øÿÿ"FƒSÃÔ øÿÿ$ìˆëÿÿÓA†AƒD@ÈCAøÿÿ,ø÷ÿÿDð÷ÿÿ)Aƒgdøÿÿ|ø÷ÿÿ<”ð÷ÿÿPGŒD†D ƒg ÃCÆBÌE AÃFÆBÌ<ÔøÿÿPGŒD†D ƒg ÃCÆBÌE AÃFÆBÌøÿÿ4T_,8øÿÿD0øÿÿ,\¨øÿÿ;BŒA†D ƒmDBDŒ¸øÿÿeBBŽE B(ŒH0†H8ƒM@r8A0A(B BBBÔàøÿÿ` @@ @ à@ ô@(!`0!`õþÿo`@@€@  #`Xˆ@p@ þÿÿo@@ÿÿÿoðÿÿo @@!` @& @6 @F @V @f @v @† @– @¦ @¶ @Æ @Ö @æ @ö @ @ @& @6 @F @V @f @v @† @– @GCC: (GNU) 5.3.0@@<@`@€@@ @@@ p@ ˆ@ à@ @   @° @ô@@@@(!`0!`8!`@!`#`#`ø#`$`ñÿñÿ8!` À @" @5@ @K$`Z0!`` @(!`¬ñÿ· @eÅ @^Óñÿãñÿð $`üñÿñÿ  !@8!`ñÿ$0!`5@!`>(!`Q@d#`z`@ð@¯Áß H ø#`û @ "5$`—ô@<Pdbx@P”à@"­ÀP@Ò@@;â@"ò @2Fø#`Sg vŠ$`—@¦º€@eÊÞ@@XîP@‹0$`L @*°@*$`6°@KD@C`° @Óe`@4rp@)‚À@P›° @ÿ½0@Ì àõ @ @&$`2@J d}` @œl à@•°@¥¾Øinit.ccrtstuff.c__JCR_LIST__deregister_tm_clones__do_global_dtors_auxcompleted.6945__do_global_dtors_aux_fini_array_entryframe_dummy__frame_dummy_init_array_entrynet_http.cnet_http_sendnet_http_recvnet_http_test.cnet_compat.cinited.4693compat_strl.c__FRAME_END____JCR_END____init_array_end_DYNAMIC__init_array_start__GNU_EH_FRAME_HDR_GLOBAL_OFFSET_TABLE_freeaddrinfo_retro__libc_csu_finifree@@GLIBC_2.2.5recv@@GLIBC_2.2.5__errno_location@@GLIBC_2.2.5_ITM_deregisterTMCloneTablenetwork_deinitsetsockopt@@GLIBC_2.2.5fcntl@@GLIBC_2.2.5_edatastrlen@@GLIBC_2.2.5send@@GLIBC_2.2.5snprintf@@GLIBC_2.2.5socket_receive_all_blockingnet_http_connection_freeclose@@GLIBC_2.2.5getaddrinfo_retrostrlcat_retro__net_http_deletememchr@@GLIBC_2.2.5socket_close__libc_start_main@@GLIBC_2.2.5calloc@@GLIBC_2.2.5__data_startsignal@@GLIBC_2.2.5__gmon_start__strtol@@GLIBC_2.2.5__dso_handle_IO_stdin_usedselect@@GLIBC_2.2.5__libc_csu_initmalloc@@GLIBC_2.2.5net_http_updatenet_http_connection_donesocket_selectrealloc@@GLIBC_2.2.5__bss_startnet_http_datanet_http_connection_iteratemainnetwork_initsocket_nonblocksocket_send_all_blockingmemmove@@GLIBC_2.2.5net_http_newnet_http_error_Jv_RegisterClassesstrtoul@@GLIBC_2.2.5net_http_fdnet_http_statusconnect@@GLIBC_2.2.5__TMC_END__net_http_connection_url_ITM_registerTMCloneTablegetaddrinfo@@GLIBC_2.2.5net_http_connection_newstrlcpy_retro____ctype_b_loc@@GLIBC_2.3freeaddrinfo@@GLIBC_2.2.5socket@@GLIBC_2.2.5.symtab.strtab.shstrtab.interp.note.ABI-tag.note.gnu.build-id.gnu.hash.dynsym.dynstr.gnu.version.gnu.version_r.rela.dyn.rela.plt.init.plt.got.text.fini.rodata.eh_frame_hdr.eh_frame.init_array.fini_array.jcr.dynamic.got.plt.data.bss.comment@#@ 1<@<$Döÿÿo`@`N €@€ˆV@^ÿÿÿo @ 6kþÿÿo@@@0zp@p„Bˆ@ˆXŽà@à‰ @  ”  @  ° @° B£ô@ô ©@±@ü¿@É(!`(!Õ0!`0!á8!`8!æ@!`@!И#`#ï#`#àøø#`ø#þ$`$0$L5  $@ 6 `/ìdesmume/src/libretro-common/glsym/glsym_es2.c000664 001750 001750 00000044173 12755534123 022463 0ustar00sergiosergio000000 000000 #include "glsym/glsym.h" #include #define SYM(x) { "gl" #x, &(gl##x) } const struct rglgen_sym_map rglgen_symbol_map[] = { SYM(BlendBarrierKHR), SYM(DebugMessageControlKHR), SYM(DebugMessageInsertKHR), SYM(DebugMessageCallbackKHR), SYM(GetDebugMessageLogKHR), SYM(PushDebugGroupKHR), SYM(PopDebugGroupKHR), SYM(ObjectLabelKHR), SYM(GetObjectLabelKHR), SYM(ObjectPtrLabelKHR), SYM(GetObjectPtrLabelKHR), SYM(GetPointervKHR), SYM(GetGraphicsResetStatusKHR), SYM(ReadnPixelsKHR), SYM(GetnUniformfvKHR), SYM(GetnUniformivKHR), SYM(GetnUniformuivKHR), SYM(EGLImageTargetTexture2DOES), SYM(EGLImageTargetRenderbufferStorageOES), SYM(CopyImageSubDataOES), SYM(EnableiOES), SYM(DisableiOES), SYM(BlendEquationiOES), SYM(BlendEquationSeparateiOES), SYM(BlendFunciOES), SYM(BlendFuncSeparateiOES), SYM(ColorMaskiOES), SYM(IsEnablediOES), SYM(DrawElementsBaseVertexOES), SYM(DrawRangeElementsBaseVertexOES), SYM(DrawElementsInstancedBaseVertexOES), SYM(MultiDrawElementsBaseVertexOES), SYM(FramebufferTextureOES), SYM(GetProgramBinaryOES), SYM(ProgramBinaryOES), SYM(MapBufferOES), SYM(UnmapBufferOES), SYM(GetBufferPointervOES), SYM(PrimitiveBoundingBoxOES), SYM(MinSampleShadingOES), SYM(PatchParameteriOES), SYM(TexImage3DOES), SYM(TexSubImage3DOES), SYM(CopyTexSubImage3DOES), SYM(CompressedTexImage3DOES), SYM(CompressedTexSubImage3DOES), SYM(FramebufferTexture3DOES), SYM(TexParameterIivOES), SYM(TexParameterIuivOES), SYM(GetTexParameterIivOES), SYM(GetTexParameterIuivOES), SYM(SamplerParameterIivOES), SYM(SamplerParameterIuivOES), SYM(GetSamplerParameterIivOES), SYM(GetSamplerParameterIuivOES), SYM(TexBufferOES), SYM(TexBufferRangeOES), SYM(TexStorage3DMultisampleOES), SYM(TextureViewOES), SYM(BindVertexArrayOES), SYM(DeleteVertexArraysOES), SYM(GenVertexArraysOES), SYM(IsVertexArrayOES), SYM(DrawArraysInstancedBaseInstanceEXT), SYM(DrawElementsInstancedBaseInstanceEXT), SYM(DrawElementsInstancedBaseVertexBaseInstanceEXT), SYM(BindFragDataLocationIndexedEXT), SYM(BindFragDataLocationEXT), SYM(GetProgramResourceLocationIndexEXT), SYM(GetFragDataIndexEXT), SYM(BufferStorageEXT), SYM(CopyImageSubDataEXT), SYM(LabelObjectEXT), SYM(GetObjectLabelEXT), SYM(InsertEventMarkerEXT), SYM(PushGroupMarkerEXT), SYM(PopGroupMarkerEXT), SYM(DiscardFramebufferEXT), SYM(GenQueriesEXT), SYM(DeleteQueriesEXT), SYM(IsQueryEXT), SYM(BeginQueryEXT), SYM(EndQueryEXT), SYM(QueryCounterEXT), SYM(GetQueryivEXT), SYM(GetQueryObjectivEXT), SYM(GetQueryObjectuivEXT), SYM(DrawBuffersEXT), SYM(EnableiEXT), SYM(DisableiEXT), SYM(BlendEquationiEXT), SYM(BlendEquationSeparateiEXT), SYM(BlendFunciEXT), SYM(BlendFuncSeparateiEXT), SYM(ColorMaskiEXT), SYM(IsEnablediEXT), SYM(DrawElementsBaseVertexEXT), SYM(DrawRangeElementsBaseVertexEXT), SYM(DrawElementsInstancedBaseVertexEXT), SYM(MultiDrawElementsBaseVertexEXT), SYM(DrawArraysInstancedEXT), SYM(DrawElementsInstancedEXT), SYM(FramebufferTextureEXT), SYM(VertexAttribDivisorEXT), SYM(MapBufferRangeEXT), SYM(FlushMappedBufferRangeEXT), SYM(MultiDrawArraysEXT), SYM(MultiDrawElementsEXT), SYM(MultiDrawArraysIndirectEXT), SYM(MultiDrawElementsIndirectEXT), SYM(RenderbufferStorageMultisampleEXT), SYM(FramebufferTexture2DMultisampleEXT), SYM(ReadBufferIndexedEXT), SYM(DrawBuffersIndexedEXT), SYM(GetIntegeri_vEXT), SYM(PrimitiveBoundingBoxEXT), SYM(RasterSamplesEXT), SYM(GetGraphicsResetStatusEXT), SYM(ReadnPixelsEXT), SYM(GetnUniformfvEXT), SYM(GetnUniformivEXT), SYM(ActiveShaderProgramEXT), SYM(BindProgramPipelineEXT), SYM(CreateShaderProgramvEXT), SYM(DeleteProgramPipelinesEXT), SYM(GenProgramPipelinesEXT), SYM(GetProgramPipelineInfoLogEXT), SYM(GetProgramPipelineivEXT), SYM(IsProgramPipelineEXT), SYM(ProgramParameteriEXT), SYM(ProgramUniform1fEXT), SYM(ProgramUniform1fvEXT), SYM(ProgramUniform1iEXT), SYM(ProgramUniform1ivEXT), SYM(ProgramUniform2fEXT), SYM(ProgramUniform2fvEXT), SYM(ProgramUniform2iEXT), SYM(ProgramUniform2ivEXT), SYM(ProgramUniform3fEXT), SYM(ProgramUniform3fvEXT), SYM(ProgramUniform3iEXT), SYM(ProgramUniform3ivEXT), SYM(ProgramUniform4fEXT), SYM(ProgramUniform4fvEXT), SYM(ProgramUniform4iEXT), SYM(ProgramUniform4ivEXT), SYM(ProgramUniformMatrix2fvEXT), SYM(ProgramUniformMatrix3fvEXT), SYM(ProgramUniformMatrix4fvEXT), SYM(UseProgramStagesEXT), SYM(ValidateProgramPipelineEXT), SYM(ProgramUniform1uiEXT), SYM(ProgramUniform2uiEXT), SYM(ProgramUniform3uiEXT), SYM(ProgramUniform4uiEXT), SYM(ProgramUniform1uivEXT), SYM(ProgramUniform2uivEXT), SYM(ProgramUniform3uivEXT), SYM(ProgramUniform4uivEXT), SYM(ProgramUniformMatrix2x3fvEXT), SYM(ProgramUniformMatrix3x2fvEXT), SYM(ProgramUniformMatrix2x4fvEXT), SYM(ProgramUniformMatrix4x2fvEXT), SYM(ProgramUniformMatrix3x4fvEXT), SYM(ProgramUniformMatrix4x3fvEXT), SYM(TexPageCommitmentEXT), SYM(PatchParameteriEXT), SYM(TexParameterIivEXT), SYM(TexParameterIuivEXT), SYM(GetTexParameterIivEXT), SYM(GetTexParameterIuivEXT), SYM(SamplerParameterIivEXT), SYM(SamplerParameterIuivEXT), SYM(GetSamplerParameterIivEXT), SYM(GetSamplerParameterIuivEXT), SYM(TexBufferEXT), SYM(TexBufferRangeEXT), SYM(TexStorage1DEXT), SYM(TexStorage2DEXT), SYM(TexStorage3DEXT), SYM(TextureStorage1DEXT), SYM(TextureStorage2DEXT), SYM(TextureStorage3DEXT), SYM(TextureViewEXT), SYM(FramebufferTextureMultiviewOVR), SYM(FramebufferTextureMultisampleMultiviewOVR), { NULL, NULL }, }; RGLSYMGLBLENDBARRIERKHRPROC __rglgen_glBlendBarrierKHR; RGLSYMGLDEBUGMESSAGECONTROLKHRPROC __rglgen_glDebugMessageControlKHR; RGLSYMGLDEBUGMESSAGEINSERTKHRPROC __rglgen_glDebugMessageInsertKHR; RGLSYMGLDEBUGMESSAGECALLBACKKHRPROC __rglgen_glDebugMessageCallbackKHR; RGLSYMGLGETDEBUGMESSAGELOGKHRPROC __rglgen_glGetDebugMessageLogKHR; RGLSYMGLPUSHDEBUGGROUPKHRPROC __rglgen_glPushDebugGroupKHR; RGLSYMGLPOPDEBUGGROUPKHRPROC __rglgen_glPopDebugGroupKHR; RGLSYMGLOBJECTLABELKHRPROC __rglgen_glObjectLabelKHR; RGLSYMGLGETOBJECTLABELKHRPROC __rglgen_glGetObjectLabelKHR; RGLSYMGLOBJECTPTRLABELKHRPROC __rglgen_glObjectPtrLabelKHR; RGLSYMGLGETOBJECTPTRLABELKHRPROC __rglgen_glGetObjectPtrLabelKHR; RGLSYMGLGETPOINTERVKHRPROC __rglgen_glGetPointervKHR; RGLSYMGLGETGRAPHICSRESETSTATUSKHRPROC __rglgen_glGetGraphicsResetStatusKHR; RGLSYMGLREADNPIXELSKHRPROC __rglgen_glReadnPixelsKHR; RGLSYMGLGETNUNIFORMFVKHRPROC __rglgen_glGetnUniformfvKHR; RGLSYMGLGETNUNIFORMIVKHRPROC __rglgen_glGetnUniformivKHR; RGLSYMGLGETNUNIFORMUIVKHRPROC __rglgen_glGetnUniformuivKHR; RGLSYMGLEGLIMAGETARGETTEXTURE2DOESPROC __rglgen_glEGLImageTargetTexture2DOES; RGLSYMGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC __rglgen_glEGLImageTargetRenderbufferStorageOES; RGLSYMGLCOPYIMAGESUBDATAOESPROC __rglgen_glCopyImageSubDataOES; RGLSYMGLENABLEIOESPROC __rglgen_glEnableiOES; RGLSYMGLDISABLEIOESPROC __rglgen_glDisableiOES; RGLSYMGLBLENDEQUATIONIOESPROC __rglgen_glBlendEquationiOES; RGLSYMGLBLENDEQUATIONSEPARATEIOESPROC __rglgen_glBlendEquationSeparateiOES; RGLSYMGLBLENDFUNCIOESPROC __rglgen_glBlendFunciOES; RGLSYMGLBLENDFUNCSEPARATEIOESPROC __rglgen_glBlendFuncSeparateiOES; RGLSYMGLCOLORMASKIOESPROC __rglgen_glColorMaskiOES; RGLSYMGLISENABLEDIOESPROC __rglgen_glIsEnablediOES; RGLSYMGLDRAWELEMENTSBASEVERTEXOESPROC __rglgen_glDrawElementsBaseVertexOES; RGLSYMGLDRAWRANGEELEMENTSBASEVERTEXOESPROC __rglgen_glDrawRangeElementsBaseVertexOES; RGLSYMGLDRAWELEMENTSINSTANCEDBASEVERTEXOESPROC __rglgen_glDrawElementsInstancedBaseVertexOES; RGLSYMGLMULTIDRAWELEMENTSBASEVERTEXOESPROC __rglgen_glMultiDrawElementsBaseVertexOES; RGLSYMGLFRAMEBUFFERTEXTUREOESPROC __rglgen_glFramebufferTextureOES; RGLSYMGLGETPROGRAMBINARYOESPROC __rglgen_glGetProgramBinaryOES; RGLSYMGLPROGRAMBINARYOESPROC __rglgen_glProgramBinaryOES; RGLSYMGLMAPBUFFEROESPROC __rglgen_glMapBufferOES; RGLSYMGLUNMAPBUFFEROESPROC __rglgen_glUnmapBufferOES; RGLSYMGLGETBUFFERPOINTERVOESPROC __rglgen_glGetBufferPointervOES; RGLSYMGLPRIMITIVEBOUNDINGBOXOESPROC __rglgen_glPrimitiveBoundingBoxOES; RGLSYMGLMINSAMPLESHADINGOESPROC __rglgen_glMinSampleShadingOES; RGLSYMGLPATCHPARAMETERIOESPROC __rglgen_glPatchParameteriOES; RGLSYMGLTEXIMAGE3DOESPROC __rglgen_glTexImage3DOES; RGLSYMGLTEXSUBIMAGE3DOESPROC __rglgen_glTexSubImage3DOES; RGLSYMGLCOPYTEXSUBIMAGE3DOESPROC __rglgen_glCopyTexSubImage3DOES; RGLSYMGLCOMPRESSEDTEXIMAGE3DOESPROC __rglgen_glCompressedTexImage3DOES; RGLSYMGLCOMPRESSEDTEXSUBIMAGE3DOESPROC __rglgen_glCompressedTexSubImage3DOES; RGLSYMGLFRAMEBUFFERTEXTURE3DOESPROC __rglgen_glFramebufferTexture3DOES; RGLSYMGLTEXPARAMETERIIVOESPROC __rglgen_glTexParameterIivOES; RGLSYMGLTEXPARAMETERIUIVOESPROC __rglgen_glTexParameterIuivOES; RGLSYMGLGETTEXPARAMETERIIVOESPROC __rglgen_glGetTexParameterIivOES; RGLSYMGLGETTEXPARAMETERIUIVOESPROC __rglgen_glGetTexParameterIuivOES; RGLSYMGLSAMPLERPARAMETERIIVOESPROC __rglgen_glSamplerParameterIivOES; RGLSYMGLSAMPLERPARAMETERIUIVOESPROC __rglgen_glSamplerParameterIuivOES; RGLSYMGLGETSAMPLERPARAMETERIIVOESPROC __rglgen_glGetSamplerParameterIivOES; RGLSYMGLGETSAMPLERPARAMETERIUIVOESPROC __rglgen_glGetSamplerParameterIuivOES; RGLSYMGLTEXBUFFEROESPROC __rglgen_glTexBufferOES; RGLSYMGLTEXBUFFERRANGEOESPROC __rglgen_glTexBufferRangeOES; RGLSYMGLTEXSTORAGE3DMULTISAMPLEOESPROC __rglgen_glTexStorage3DMultisampleOES; RGLSYMGLTEXTUREVIEWOESPROC __rglgen_glTextureViewOES; RGLSYMGLBINDVERTEXARRAYOESPROC __rglgen_glBindVertexArrayOES; RGLSYMGLDELETEVERTEXARRAYSOESPROC __rglgen_glDeleteVertexArraysOES; RGLSYMGLGENVERTEXARRAYSOESPROC __rglgen_glGenVertexArraysOES; RGLSYMGLISVERTEXARRAYOESPROC __rglgen_glIsVertexArrayOES; RGLSYMGLDRAWARRAYSINSTANCEDBASEINSTANCEEXTPROC __rglgen_glDrawArraysInstancedBaseInstanceEXT; RGLSYMGLDRAWELEMENTSINSTANCEDBASEINSTANCEEXTPROC __rglgen_glDrawElementsInstancedBaseInstanceEXT; RGLSYMGLDRAWELEMENTSINSTANCEDBASEVERTEXBASEINSTANCEEXTPROC __rglgen_glDrawElementsInstancedBaseVertexBaseInstanceEXT; RGLSYMGLBINDFRAGDATALOCATIONINDEXEDEXTPROC __rglgen_glBindFragDataLocationIndexedEXT; RGLSYMGLBINDFRAGDATALOCATIONEXTPROC __rglgen_glBindFragDataLocationEXT; RGLSYMGLGETPROGRAMRESOURCELOCATIONINDEXEXTPROC __rglgen_glGetProgramResourceLocationIndexEXT; RGLSYMGLGETFRAGDATAINDEXEXTPROC __rglgen_glGetFragDataIndexEXT; RGLSYMGLBUFFERSTORAGEEXTPROC __rglgen_glBufferStorageEXT; RGLSYMGLCOPYIMAGESUBDATAEXTPROC __rglgen_glCopyImageSubDataEXT; RGLSYMGLLABELOBJECTEXTPROC __rglgen_glLabelObjectEXT; RGLSYMGLGETOBJECTLABELEXTPROC __rglgen_glGetObjectLabelEXT; RGLSYMGLINSERTEVENTMARKEREXTPROC __rglgen_glInsertEventMarkerEXT; RGLSYMGLPUSHGROUPMARKEREXTPROC __rglgen_glPushGroupMarkerEXT; RGLSYMGLPOPGROUPMARKEREXTPROC __rglgen_glPopGroupMarkerEXT; RGLSYMGLDISCARDFRAMEBUFFEREXTPROC __rglgen_glDiscardFramebufferEXT; RGLSYMGLGENQUERIESEXTPROC __rglgen_glGenQueriesEXT; RGLSYMGLDELETEQUERIESEXTPROC __rglgen_glDeleteQueriesEXT; RGLSYMGLISQUERYEXTPROC __rglgen_glIsQueryEXT; RGLSYMGLBEGINQUERYEXTPROC __rglgen_glBeginQueryEXT; RGLSYMGLENDQUERYEXTPROC __rglgen_glEndQueryEXT; RGLSYMGLQUERYCOUNTEREXTPROC __rglgen_glQueryCounterEXT; RGLSYMGLGETQUERYIVEXTPROC __rglgen_glGetQueryivEXT; RGLSYMGLGETQUERYOBJECTIVEXTPROC __rglgen_glGetQueryObjectivEXT; RGLSYMGLGETQUERYOBJECTUIVEXTPROC __rglgen_glGetQueryObjectuivEXT; RGLSYMGLDRAWBUFFERSEXTPROC __rglgen_glDrawBuffersEXT; RGLSYMGLENABLEIEXTPROC __rglgen_glEnableiEXT; RGLSYMGLDISABLEIEXTPROC __rglgen_glDisableiEXT; RGLSYMGLBLENDEQUATIONIEXTPROC __rglgen_glBlendEquationiEXT; RGLSYMGLBLENDEQUATIONSEPARATEIEXTPROC __rglgen_glBlendEquationSeparateiEXT; RGLSYMGLBLENDFUNCIEXTPROC __rglgen_glBlendFunciEXT; RGLSYMGLBLENDFUNCSEPARATEIEXTPROC __rglgen_glBlendFuncSeparateiEXT; RGLSYMGLCOLORMASKIEXTPROC __rglgen_glColorMaskiEXT; RGLSYMGLISENABLEDIEXTPROC __rglgen_glIsEnablediEXT; RGLSYMGLDRAWELEMENTSBASEVERTEXEXTPROC __rglgen_glDrawElementsBaseVertexEXT; RGLSYMGLDRAWRANGEELEMENTSBASEVERTEXEXTPROC __rglgen_glDrawRangeElementsBaseVertexEXT; RGLSYMGLDRAWELEMENTSINSTANCEDBASEVERTEXEXTPROC __rglgen_glDrawElementsInstancedBaseVertexEXT; RGLSYMGLMULTIDRAWELEMENTSBASEVERTEXEXTPROC __rglgen_glMultiDrawElementsBaseVertexEXT; RGLSYMGLDRAWARRAYSINSTANCEDEXTPROC __rglgen_glDrawArraysInstancedEXT; RGLSYMGLDRAWELEMENTSINSTANCEDEXTPROC __rglgen_glDrawElementsInstancedEXT; RGLSYMGLFRAMEBUFFERTEXTUREEXTPROC __rglgen_glFramebufferTextureEXT; RGLSYMGLVERTEXATTRIBDIVISOREXTPROC __rglgen_glVertexAttribDivisorEXT; RGLSYMGLMAPBUFFERRANGEEXTPROC __rglgen_glMapBufferRangeEXT; RGLSYMGLFLUSHMAPPEDBUFFERRANGEEXTPROC __rglgen_glFlushMappedBufferRangeEXT; RGLSYMGLMULTIDRAWARRAYSEXTPROC __rglgen_glMultiDrawArraysEXT; RGLSYMGLMULTIDRAWELEMENTSEXTPROC __rglgen_glMultiDrawElementsEXT; RGLSYMGLMULTIDRAWARRAYSINDIRECTEXTPROC __rglgen_glMultiDrawArraysIndirectEXT; RGLSYMGLMULTIDRAWELEMENTSINDIRECTEXTPROC __rglgen_glMultiDrawElementsIndirectEXT; RGLSYMGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC __rglgen_glRenderbufferStorageMultisampleEXT; RGLSYMGLFRAMEBUFFERTEXTURE2DMULTISAMPLEEXTPROC __rglgen_glFramebufferTexture2DMultisampleEXT; RGLSYMGLREADBUFFERINDEXEDEXTPROC __rglgen_glReadBufferIndexedEXT; RGLSYMGLDRAWBUFFERSINDEXEDEXTPROC __rglgen_glDrawBuffersIndexedEXT; RGLSYMGLGETINTEGERI_VEXTPROC __rglgen_glGetIntegeri_vEXT; RGLSYMGLPRIMITIVEBOUNDINGBOXEXTPROC __rglgen_glPrimitiveBoundingBoxEXT; RGLSYMGLRASTERSAMPLESEXTPROC __rglgen_glRasterSamplesEXT; RGLSYMGLGETGRAPHICSRESETSTATUSEXTPROC __rglgen_glGetGraphicsResetStatusEXT; RGLSYMGLREADNPIXELSEXTPROC __rglgen_glReadnPixelsEXT; RGLSYMGLGETNUNIFORMFVEXTPROC __rglgen_glGetnUniformfvEXT; RGLSYMGLGETNUNIFORMIVEXTPROC __rglgen_glGetnUniformivEXT; RGLSYMGLACTIVESHADERPROGRAMEXTPROC __rglgen_glActiveShaderProgramEXT; RGLSYMGLBINDPROGRAMPIPELINEEXTPROC __rglgen_glBindProgramPipelineEXT; RGLSYMGLCREATESHADERPROGRAMVEXTPROC __rglgen_glCreateShaderProgramvEXT; RGLSYMGLDELETEPROGRAMPIPELINESEXTPROC __rglgen_glDeleteProgramPipelinesEXT; RGLSYMGLGENPROGRAMPIPELINESEXTPROC __rglgen_glGenProgramPipelinesEXT; RGLSYMGLGETPROGRAMPIPELINEINFOLOGEXTPROC __rglgen_glGetProgramPipelineInfoLogEXT; RGLSYMGLGETPROGRAMPIPELINEIVEXTPROC __rglgen_glGetProgramPipelineivEXT; RGLSYMGLISPROGRAMPIPELINEEXTPROC __rglgen_glIsProgramPipelineEXT; RGLSYMGLPROGRAMPARAMETERIEXTPROC __rglgen_glProgramParameteriEXT; RGLSYMGLPROGRAMUNIFORM1FEXTPROC __rglgen_glProgramUniform1fEXT; RGLSYMGLPROGRAMUNIFORM1FVEXTPROC __rglgen_glProgramUniform1fvEXT; RGLSYMGLPROGRAMUNIFORM1IEXTPROC __rglgen_glProgramUniform1iEXT; RGLSYMGLPROGRAMUNIFORM1IVEXTPROC __rglgen_glProgramUniform1ivEXT; RGLSYMGLPROGRAMUNIFORM2FEXTPROC __rglgen_glProgramUniform2fEXT; RGLSYMGLPROGRAMUNIFORM2FVEXTPROC __rglgen_glProgramUniform2fvEXT; RGLSYMGLPROGRAMUNIFORM2IEXTPROC __rglgen_glProgramUniform2iEXT; RGLSYMGLPROGRAMUNIFORM2IVEXTPROC __rglgen_glProgramUniform2ivEXT; RGLSYMGLPROGRAMUNIFORM3FEXTPROC __rglgen_glProgramUniform3fEXT; RGLSYMGLPROGRAMUNIFORM3FVEXTPROC __rglgen_glProgramUniform3fvEXT; RGLSYMGLPROGRAMUNIFORM3IEXTPROC __rglgen_glProgramUniform3iEXT; RGLSYMGLPROGRAMUNIFORM3IVEXTPROC __rglgen_glProgramUniform3ivEXT; RGLSYMGLPROGRAMUNIFORM4FEXTPROC __rglgen_glProgramUniform4fEXT; RGLSYMGLPROGRAMUNIFORM4FVEXTPROC __rglgen_glProgramUniform4fvEXT; RGLSYMGLPROGRAMUNIFORM4IEXTPROC __rglgen_glProgramUniform4iEXT; RGLSYMGLPROGRAMUNIFORM4IVEXTPROC __rglgen_glProgramUniform4ivEXT; RGLSYMGLPROGRAMUNIFORMMATRIX2FVEXTPROC __rglgen_glProgramUniformMatrix2fvEXT; RGLSYMGLPROGRAMUNIFORMMATRIX3FVEXTPROC __rglgen_glProgramUniformMatrix3fvEXT; RGLSYMGLPROGRAMUNIFORMMATRIX4FVEXTPROC __rglgen_glProgramUniformMatrix4fvEXT; RGLSYMGLUSEPROGRAMSTAGESEXTPROC __rglgen_glUseProgramStagesEXT; RGLSYMGLVALIDATEPROGRAMPIPELINEEXTPROC __rglgen_glValidateProgramPipelineEXT; RGLSYMGLPROGRAMUNIFORM1UIEXTPROC __rglgen_glProgramUniform1uiEXT; RGLSYMGLPROGRAMUNIFORM2UIEXTPROC __rglgen_glProgramUniform2uiEXT; RGLSYMGLPROGRAMUNIFORM3UIEXTPROC __rglgen_glProgramUniform3uiEXT; RGLSYMGLPROGRAMUNIFORM4UIEXTPROC __rglgen_glProgramUniform4uiEXT; RGLSYMGLPROGRAMUNIFORM1UIVEXTPROC __rglgen_glProgramUniform1uivEXT; RGLSYMGLPROGRAMUNIFORM2UIVEXTPROC __rglgen_glProgramUniform2uivEXT; RGLSYMGLPROGRAMUNIFORM3UIVEXTPROC __rglgen_glProgramUniform3uivEXT; RGLSYMGLPROGRAMUNIFORM4UIVEXTPROC __rglgen_glProgramUniform4uivEXT; RGLSYMGLPROGRAMUNIFORMMATRIX2X3FVEXTPROC __rglgen_glProgramUniformMatrix2x3fvEXT; RGLSYMGLPROGRAMUNIFORMMATRIX3X2FVEXTPROC __rglgen_glProgramUniformMatrix3x2fvEXT; RGLSYMGLPROGRAMUNIFORMMATRIX2X4FVEXTPROC __rglgen_glProgramUniformMatrix2x4fvEXT; RGLSYMGLPROGRAMUNIFORMMATRIX4X2FVEXTPROC __rglgen_glProgramUniformMatrix4x2fvEXT; RGLSYMGLPROGRAMUNIFORMMATRIX3X4FVEXTPROC __rglgen_glProgramUniformMatrix3x4fvEXT; RGLSYMGLPROGRAMUNIFORMMATRIX4X3FVEXTPROC __rglgen_glProgramUniformMatrix4x3fvEXT; RGLSYMGLTEXPAGECOMMITMENTEXTPROC __rglgen_glTexPageCommitmentEXT; RGLSYMGLPATCHPARAMETERIEXTPROC __rglgen_glPatchParameteriEXT; RGLSYMGLTEXPARAMETERIIVEXTPROC __rglgen_glTexParameterIivEXT; RGLSYMGLTEXPARAMETERIUIVEXTPROC __rglgen_glTexParameterIuivEXT; RGLSYMGLGETTEXPARAMETERIIVEXTPROC __rglgen_glGetTexParameterIivEXT; RGLSYMGLGETTEXPARAMETERIUIVEXTPROC __rglgen_glGetTexParameterIuivEXT; RGLSYMGLSAMPLERPARAMETERIIVEXTPROC __rglgen_glSamplerParameterIivEXT; RGLSYMGLSAMPLERPARAMETERIUIVEXTPROC __rglgen_glSamplerParameterIuivEXT; RGLSYMGLGETSAMPLERPARAMETERIIVEXTPROC __rglgen_glGetSamplerParameterIivEXT; RGLSYMGLGETSAMPLERPARAMETERIUIVEXTPROC __rglgen_glGetSamplerParameterIuivEXT; RGLSYMGLTEXBUFFEREXTPROC __rglgen_glTexBufferEXT; RGLSYMGLTEXBUFFERRANGEEXTPROC __rglgen_glTexBufferRangeEXT; RGLSYMGLTEXSTORAGE1DEXTPROC __rglgen_glTexStorage1DEXT; RGLSYMGLTEXSTORAGE2DEXTPROC __rglgen_glTexStorage2DEXT; RGLSYMGLTEXSTORAGE3DEXTPROC __rglgen_glTexStorage3DEXT; RGLSYMGLTEXTURESTORAGE1DEXTPROC __rglgen_glTextureStorage1DEXT; RGLSYMGLTEXTURESTORAGE2DEXTPROC __rglgen_glTextureStorage2DEXT; RGLSYMGLTEXTURESTORAGE3DEXTPROC __rglgen_glTextureStorage3DEXT; RGLSYMGLTEXTUREVIEWEXTPROC __rglgen_glTextureViewEXT; RGLSYMGLFRAMEBUFFERTEXTUREMULTIVIEWOVRPROC __rglgen_glFramebufferTextureMultiviewOVR; RGLSYMGLFRAMEBUFFERTEXTUREMULTISAMPLEMULTIVIEWOVRPROC __rglgen_glFramebufferTextureMultisampleMultiviewOVR; desmume/src/utils/AsmJit/x86/x86assembler.cpp000664 001750 001750 00000251104 12755534123 022145 0ustar00sergiosergio000000 000000 // [AsmJit] // Complete JIT Assembler for C++ Language. // // [License] // Zlib - See COPYING file in this package. #define ASMJIT_EXPORTS // [Dependencies - AsmJit] #include "../core/assembler.h" #include "../core/context.h" #include "../core/cpuinfo.h" #include "../core/defs.h" #include "../core/intutil.h" #include "../core/logger.h" #include "../core/memorymanager.h" #include "../core/memorymarker.h" #include "../core/stringutil.h" #include "../x86/x86assembler.h" #include "../x86/x86cpuinfo.h" #include "../x86/x86defs.h" #include "../x86/x86operand.h" #include "../x86/x86util.h" // [Api-Begin] #include "../core/apibegin.h" namespace AsmJit { // ============================================================================ // [Constants] // ============================================================================ enum { kMaxCommentLength = 80 }; // ============================================================================ // [AsmJit::X64TrampolineWriter] // ============================================================================ #if defined(ASMJIT_X64) //! @brief Class used to determine size of trampoline and as trampoline writer. struct X64TrampolineWriter { // Size of trampoline enum { kSizeJmp = 6, kSizeAddr = 8, kSizeTotal = kSizeJmp + kSizeAddr }; // Write trampoline into code at address @a code that will jump to @a target. static void writeTrampoline(uint8_t* code, uint64_t target) { code[0] = 0xFF; // Jmp OpCode. code[1] = 0x25; // ModM (RIP addressing). ((uint32_t*)(code + 2))[0] = 0; // Offset (zero). ((uint64_t*)(code + kSizeJmp))[0] = (uint64_t)target; // Absolute address. } }; #endif // ASMJIT_X64 // ============================================================================ // [AsmJit::X86Assembler - Construction / Destruction] // ============================================================================ X86Assembler::X86Assembler(Context* context) : Assembler(context) { _properties = IntUtil::maskFromIndex(kX86PropertyOptimizedAlign); } X86Assembler::~X86Assembler() { } // ============================================================================ // [AsmJit::X86Assembler - Buffer - Setters (X86-Extensions)] // ============================================================================ void X86Assembler::setVarAt(size_t pos, sysint_t i, uint8_t isUnsigned, uint32_t size) { if (size == 1 && !isUnsigned) setByteAt (pos, (int8_t )i); else if (size == 1 && isUnsigned) setByteAt (pos, (uint8_t )i); else if (size == 2 && !isUnsigned) setWordAt (pos, (int16_t )i); else if (size == 2 && isUnsigned) setWordAt (pos, (uint16_t)i); else if (size == 4 && !isUnsigned) setDWordAt(pos, (int32_t )i); else if (size == 4 && isUnsigned) setDWordAt(pos, (uint32_t)i); #if defined(ASMJIT_X64) else if (size == 8 && !isUnsigned) setQWordAt(pos, (int64_t )i); else if (size == 8 && isUnsigned) setQWordAt(pos, (uint64_t)i); #endif // ASMJIT_X64 else ASMJIT_ASSERT(0); } // ============================================================================ // [AsmJit::X86Assembler - Emit] // ============================================================================ void X86Assembler::_emitModM( uint8_t opReg, const Mem& mem, sysint_t immSize) { ASMJIT_ASSERT(mem.getType() == kOperandMem); uint8_t baseReg = mem.getBase() & 0x7; uint8_t indexReg = mem.getIndex() & 0x7; sysint_t disp = mem.getDisplacement(); uint32_t shift = mem.getShift(); if (mem.getMemType() == kOperandMemNative) { // [base + displacemnt] if (!mem.hasIndex()) { // ESP/RSP/R12 == 4 if (baseReg == 4) { uint8_t mod = 0; if (disp) mod = IntUtil::isInt8(disp) ? 1 : 2; _emitMod(mod, opReg, 4); _emitSib(0, 4, 4); if (disp) { if (IntUtil::isInt8(disp)) _emitByte((int8_t)disp); else _emitInt32((int32_t)disp); } } // EBP/RBP/R13 == 5 else if (baseReg != 5 && disp == 0) { _emitMod(0, opReg, baseReg); } else if (IntUtil::isInt8(disp)) { _emitMod(1, opReg, baseReg); _emitByte((int8_t)disp); } else { _emitMod(2, opReg, baseReg); _emitInt32((int32_t)disp); } } // [base + index * scale + displacemnt] else { // ASMJIT_ASSERT(indexReg != RID_ESP); // EBP/RBP/R13 == 5 if (baseReg != 5 && disp == 0) { _emitMod(0, opReg, 4); _emitSib(shift, indexReg, baseReg); } else if (IntUtil::isInt8(disp)) { _emitMod(1, opReg, 4); _emitSib(shift, indexReg, baseReg); _emitByte((int8_t)disp); } else { _emitMod(2, opReg, 4); _emitSib(shift, indexReg, baseReg); _emitInt32((int32_t)disp); } } } // Address | 32-bit mode | 64-bit mode // ------------------------------+-------------+--------------- // [displacement] | ABSOLUTE | RELATIVE (RIP) // [index * scale + displacemnt] | ABSOLUTE | ABSOLUTE (ZERO EXTENDED) else { // - In 32-bit mode the absolute addressing model is used. // - In 64-bit mode the relative addressing model is used together with // the absolute addressing. Main problem is that if instruction // contains SIB then relative addressing (RIP) is not possible. #if defined(ASMJIT_X86) if (mem.hasIndex()) { // ASMJIT_ASSERT(mem.getMemIndex() != 4); // ESP/RSP == 4 _emitMod(0, opReg, 4); _emitSib(shift, indexReg, 5); } else { _emitMod(0, opReg, 5); } // X86 uses absolute addressing model, all relative addresses will be // relocated to absolute ones. if (mem.getMemType() == kOperandMemLabel) { LabelData& l_data = _labels[mem._mem.base & kOperandIdValueMask]; RelocData r_data; uint32_t relocId = _relocData.getLength(); // Relative addressing will be relocated to absolute address. r_data.type = kRelocRelToAbs; r_data.size = 4; r_data.offset = getOffset(); r_data.destination = disp; if (l_data.offset != -1) { // Bound label. r_data.destination += l_data.offset; // Add a dummy DWORD. _emitInt32(0); } else { // Non-bound label. _emitDisplacement(l_data, -4 - immSize, 4)->relocId = relocId; } _relocData.append(r_data); } else { // Absolute address _emitInt32( (int32_t)((uint8_t*)mem._mem.target + disp) ); } #else // X64 uses relative addressing model if (mem.getMemType() == kOperandMemLabel) { LabelData& l_data = _labels[mem._mem.base & kOperandIdValueMask]; if (mem.hasIndex()) { // Indexing is not possible. setError(kErrorIllegalAddressing); return; } // Relative address (RIP +/- displacement). _emitMod(0, opReg, 5); disp -= (4 + immSize); if (l_data.offset != -1) { // Bound label. disp += getOffset() - l_data.offset; // Displacement is known. _emitInt32((int32_t)disp); } else { // Non-bound label. _emitDisplacement(l_data, disp, 4); } } else { // Absolute address (truncated to 32-bits), this kind of address requires // SIB byte (4). _emitMod(0, opReg, 4); if (mem.hasIndex()) { // ASMJIT_ASSERT(mem.getMemIndex() != 4); // ESP/RSP == 4 _emitSib(shift, indexReg, 5); } else { _emitSib(0, 4, 5); } // Truncate to 32-bits. sysuint_t target = (sysuint_t)((uint8_t*)mem._mem.target + disp); if (target > (sysuint_t)0xFFFFFFFF) { if (_logger) { _logger->logString("*** ASSEMBER WARNING - Absolute address truncated to 32-bits.\n"); } target &= 0xFFFFFFFF; } _emitInt32( (int32_t)((uint32_t)target) ); } #endif // ASMJIT_X64 } } void X86Assembler::_emitModRM( uint8_t opReg, const Operand& op, sysint_t immSize) { ASMJIT_ASSERT(op.getType() == kOperandReg || op.getType() == kOperandMem); if (op.getType() == kOperandReg) _emitModR(opReg, reinterpret_cast(op).getRegCode()); else _emitModM(opReg, reinterpret_cast(op), immSize); } void X86Assembler::_emitSegmentPrefix(const Operand& rm) { static const uint8_t segmentCode[6] = { 0x26, // ES 0x2E, // SS 0x36, // SS 0x3E, // DS 0x64, // FS 0x65 // GS }; if (!rm.isMem()) return; uint32_t seg = reinterpret_cast(rm).getSegment(); if (seg >= kX86RegNumSeg) return; _emitByte(segmentCode[seg]); } void X86Assembler::_emitX86Inl( uint32_t opCode, uint8_t i16bit, uint8_t rexw, uint8_t reg, bool forceRexPrefix) { // 16-bit prefix. if (i16bit) _emitByte(0x66); // Instruction prefix. if (opCode & 0xFF000000) _emitByte((uint8_t)((opCode & 0xFF000000) >> 24)); // REX prefix. #if defined(ASMJIT_X64) _emitRexR(rexw, 0, reg, forceRexPrefix); #endif // ASMJIT_X64 // Instruction opcodes. if (opCode & 0x00FF0000) _emitByte((uint8_t)((opCode & 0x00FF0000) >> 16)); if (opCode & 0x0000FF00) _emitByte((uint8_t)((opCode & 0x0000FF00) >> 8)); _emitByte((uint8_t)(opCode & 0x000000FF) + (reg & 0x7)); } void X86Assembler::_emitX86RM( uint32_t opCode, uint8_t i16bit, uint8_t rexw, uint8_t o, const Operand& op, sysint_t immSize, bool forceRexPrefix) { // 16-bit prefix. if (i16bit) _emitByte(0x66); // Segment prefix. _emitSegmentPrefix(op); // Instruction prefix. if (opCode & 0xFF000000) _emitByte((uint8_t)((opCode & 0xFF000000) >> 24)); // REX prefix. #if defined(ASMJIT_X64) _emitRexRM(rexw, o, op, forceRexPrefix); #endif // ASMJIT_X64 // Instruction opcodes. if (opCode & 0x00FF0000) _emitByte((uint8_t)((opCode & 0x00FF0000) >> 16)); if (opCode & 0x0000FF00) _emitByte((uint8_t)((opCode & 0x0000FF00) >> 8)); _emitByte((uint8_t)(opCode & 0x000000FF)); // Mod R/M. _emitModRM(o, op, immSize); } void X86Assembler::_emitFpu(uint32_t opCode) { _emitOpCode(opCode); } void X86Assembler::_emitFpuSTI(uint32_t opCode, uint32_t sti) { // Illegal stack offset. ASMJIT_ASSERT(0 <= sti && sti < 8); _emitOpCode(opCode + sti); } void X86Assembler::_emitFpuMEM(uint32_t opCode, uint8_t opReg, const Mem& mem) { // Segment prefix. _emitSegmentPrefix(mem); // Instruction prefix. if (opCode & 0xFF000000) _emitByte((uint8_t)((opCode & 0xFF000000) >> 24)); // REX prefix. #if defined(ASMJIT_X64) _emitRexRM(0, opReg, mem, false); #endif // ASMJIT_X64 // Instruction opcodes. if (opCode & 0x00FF0000) _emitByte((uint8_t)((opCode & 0x00FF0000) >> 16)); if (opCode & 0x0000FF00) _emitByte((uint8_t)((opCode & 0x0000FF00) >> 8)); _emitByte((uint8_t)((opCode & 0x000000FF))); _emitModM(opReg, mem, 0); } void X86Assembler::_emitMmu(uint32_t opCode, uint8_t rexw, uint8_t opReg, const Operand& src, sysint_t immSize) { // Segment prefix. _emitSegmentPrefix(src); // Instruction prefix. if (opCode & 0xFF000000) _emitByte((uint8_t)((opCode & 0xFF000000) >> 24)); // REX prefix. #if defined(ASMJIT_X64) _emitRexRM(rexw, opReg, src, false); #endif // ASMJIT_X64 // Instruction opcodes. if (opCode & 0x00FF0000) _emitByte((uint8_t)((opCode & 0x00FF0000) >> 16)); // No checking, MMX/SSE instructions have always two opcodes or more. _emitByte((uint8_t)((opCode & 0x0000FF00) >> 8)); _emitByte((uint8_t)((opCode & 0x000000FF))); if (src.isReg()) _emitModR(opReg, reinterpret_cast(src).getRegCode()); else _emitModM(opReg, reinterpret_cast(src), immSize); } X86Assembler::LabelLink* X86Assembler::_emitDisplacement( LabelData& l_data, sysint_t inlinedDisplacement, int size) { ASMJIT_ASSERT(l_data.offset == -1); ASMJIT_ASSERT(size == 1 || size == 4); // Chain with label. LabelLink* link = _newLabelLink(); link->prev = l_data.links; link->offset = getOffset(); link->displacement = inlinedDisplacement; l_data.links = link; // Emit label size as dummy data. if (size == 1) _emitByte(0x01); else // if (size == 4) _emitDWord(0x04040404); return link; } void X86Assembler::_emitJmpOrCallReloc(uint32_t instruction, void* target) { RelocData rd; rd.type = kRelocTrampoline; #if defined(ASMJIT_X64) // If we are compiling in 64-bit mode, we can use trampoline if relative jump // is not possible. _trampolineSize += X64TrampolineWriter::kSizeTotal; #endif // ARCHITECTURE_SPECIFIC rd.size = 4; rd.offset = getOffset(); rd.address = target; _relocData.append(rd); // Emit dummy 32-bit integer (will be overwritten by relocCode()). _emitInt32(0); } //! @internal //! //! @brief Get whether the extended register (additional eight registers //! introduced by 64-bit mode) is used. static inline bool X86Assembler_isExtRegisterUsed(const Operand& op) { // Hacky, but correct. // - If operand type is register then extended register is register with // index 8 and greater (8 to 15 inclusive). // - If operand type is memory operand then we need to take care about // label (in _mem.base) and kInvalidValue, we just decrement the value // by 8 and check if it's at interval 0 to 7 inclusive (if it's there // then it's extended register. return (op.isReg() && (op._reg.code & kRegIndexMask) >= 8U) || (op.isMem() && ((((uint32_t)op._mem.base - 8U) < 8U) || (((uint32_t)op._mem.index - 8U) < 8U) )); } // Logging helpers. static const char* AssemblerX86_operandSize[] = { NULL, "byte ptr ", "word ptr ", NULL, "dword ptr ", NULL, NULL, NULL, "qword ptr ", NULL, "tword ptr ", NULL, NULL, NULL, NULL, NULL, "dqword ptr " }; static const char X86Assembler_segmentName[] = "es:\0" "cs:\0" "ss:\0" "ds:\0" "fs:\0" "gs:\0" "\0\0\0\0"; static char* X86Assembler_dumpInstructionName(char* buf, uint32_t code) { ASMJIT_ASSERT(code < _kX86InstCount); return StringUtil::copy(buf, x86InstInfo[code].getName()); } char* X86Assembler_dumpRegister(char* buf, uint32_t type, uint32_t index) { // NE == Not-Encodable. const char reg8l[] = "al\0\0" "cl\0\0" "dl\0\0" "bl\0\0" "spl\0" "bpl\0" "sil\0" "dil\0" ; const char reg8h[] = "ah\0\0" "ch\0\0" "dh\0\0" "bh\0\0" "NE\0\0" "NE\0\0" "NE\0\0" "NE\0\0"; const char reg16[] = "ax\0\0" "cx\0\0" "dx\0\0" "bx\0\0" "sp\0\0" "bp\0\0" "si\0\0" "di\0\0"; switch (type) { case kX86RegTypeGpbLo: if (index < 8) return StringUtil::copy(buf, ®8l[index*4]); *buf++ = 'r'; goto _EmitID; case kX86RegTypeGpbHi: if (index < 4) return StringUtil::copy(buf, ®8h[index*4]); _EmitNE: return StringUtil::copy(buf, "NE"); case kX86RegTypeGpw: if (index < 8) return StringUtil::copy(buf, ®16[index*4]); *buf++ = 'r'; buf = StringUtil::utoa(buf, index); *buf++ = 'w'; return buf; case kX86RegTypeGpd: if (index < 8) { *buf++ = 'e'; return StringUtil::copy(buf, ®16[index*4]); } *buf++ = 'r'; buf = StringUtil::utoa(buf, index); *buf++ = 'd'; return buf; case kX86RegTypeGpq: *buf++ = 'r'; if (index < 8) return StringUtil::copy(buf, ®16[index*4]); _EmitID: return StringUtil::utoa(buf, index); case kX86RegTypeX87: *buf++ = 's'; *buf++ = 't'; goto _EmitID; case kX86RegTypeMm: *buf++ = 'm'; *buf++ = 'm'; goto _EmitID; case kX86RegTypeXmm: *buf++ = 'x'; *buf++ = 'm'; *buf++ = 'm'; goto _EmitID; case kX86RegTypeYmm: *buf++ = 'y'; *buf++ = 'm'; *buf++ = 'm'; goto _EmitID; case kX86RegTypeSeg: if (index < kX86RegNumSeg) return StringUtil::copy(buf, &X86Assembler_segmentName[index*4], 2); goto _EmitNE; default: return buf; } } char* X86Assembler_dumpOperand(char* buf, const Operand* op, uint32_t memRegType, uint32_t loggerFlags) { if (op->isReg()) { const Reg& reg = reinterpret_cast(*op); return X86Assembler_dumpRegister(buf, reg.getRegType(), reg.getRegIndex()); } else if (op->isMem()) { const Mem& mem = reinterpret_cast(*op); uint32_t seg = mem.getSegment(); bool isAbsolute = false; if (op->getSize() <= 16) buf = StringUtil::copy(buf, AssemblerX86_operandSize[op->getSize()]); if (seg < kX86RegNumSeg) buf = StringUtil::copy(buf, &X86Assembler_segmentName[seg * 4]); *buf++ = '['; switch (mem.getMemType()) { case kOperandMemNative: { // [base + index << shift + displacement] buf = X86Assembler_dumpRegister(buf, memRegType, mem.getBase()); break; } case kOperandMemLabel: { // [label + index << shift + displacement] buf += sprintf(buf, "L.%u", mem.getBase() & kOperandIdValueMask); break; } case kOperandMemAbsolute: { // [absolute] isAbsolute = true; buf = StringUtil::utoa(buf, (sysuint_t)mem.getTarget() + mem.getDisplacement(), 16); break; } } if (mem.hasIndex()) { buf = StringUtil::copy(buf, " + "); buf = X86Assembler_dumpRegister(buf, memRegType, mem.getIndex()); if (mem.getShift()) { buf = StringUtil::copy(buf, " * "); *buf++ = "1248"[mem.getShift() & 3]; } } if (mem.getDisplacement() && !isAbsolute) { sysint_t d = mem.getDisplacement(); uint32_t base = 10; char sign = '+'; if (d < 0) { d = -d; sign = '-'; } buf[0] = ' '; buf[1] = sign; buf[2] = ' '; buf += 3; if ((loggerFlags & kLoggerOutputHexDisplacement) != 0 && d > 9) { buf[0] = '0'; buf[1] = 'x'; buf += 2; base = 16; } buf = StringUtil::utoa(buf, static_cast(d), base); } *buf++ = ']'; return buf; } else if (op->isImm()) { const Imm& i = reinterpret_cast(*op); sysuint_t value = i.getUValue(); uint32_t base = 10; if ((loggerFlags & kLoggerOutputHexImmediate) && value > 9) base = 16; if (i.isUnsigned() || base == 16) { return StringUtil::utoa(buf, value, base); } else { return StringUtil::itoa(buf, static_cast(value), base); } } else if (op->isLabel()) { return buf + sprintf(buf, "L.%u", op->getId() & kOperandIdValueMask); } else { return StringUtil::copy(buf, "None"); } } static char* X86Assembler_dumpInstruction(char* buf, uint32_t code, uint32_t emitOptions, const Operand* o0, const Operand* o1, const Operand* o2, uint32_t memRegType, uint32_t loggerFlags) { // Rex, lock, and short prefix. if (emitOptions & kX86EmitOptionRex) buf = StringUtil::copy(buf, "rex ", 4); if (emitOptions & kX86EmitOptionLock) buf = StringUtil::copy(buf, "lock ", 5); if (emitOptions & kX86EmitOptionShortJump) buf = StringUtil::copy(buf, "short ", 6); // Dump instruction name. buf = X86Assembler_dumpInstructionName(buf, code); // Dump operands. if (!o0->isNone()) { *buf++ = ' '; buf = X86Assembler_dumpOperand(buf, o0, memRegType, loggerFlags); } if (!o1->isNone()) { *buf++ = ','; *buf++ = ' '; buf = X86Assembler_dumpOperand(buf, o1, memRegType, loggerFlags); } if (!o2->isNone()) { *buf++ = ','; *buf++ = ' '; buf = X86Assembler_dumpOperand(buf, o2, memRegType, loggerFlags); } return buf; } static char* X86Assembler_dumpComment(char* buf, size_t len, const uint8_t* binaryData, size_t binaryLen, const char* comment) { size_t currentLength = len; size_t commentLength = comment ? strnlen(comment, kMaxCommentLength) : 0; if (binaryLen || commentLength) { size_t align = 32; char sep = ';'; for (size_t i = (binaryLen == 0); i < 2; i++) { char* bufBegin = buf; // Append align. if (currentLength < align) { buf = StringUtil::fill(buf, ' ', align - currentLength); } // Append separator. if (sep) { *buf++ = sep; *buf++ = ' '; } // Append binary data or comment. if (i == 0) { buf = StringUtil::hex(buf, binaryData, binaryLen); if (commentLength == 0) break; } else { buf = StringUtil::copy(buf, comment, commentLength); } currentLength += (size_t)(buf - bufBegin); align += 18; sep = '|'; } } *buf++ = '\n'; return buf; } static const _OpReg _patchedHiRegs[4] = { // Operand |Size|Reserved0|Reserved1| OperandId | RegisterCode | // ----------+----+---------+---------+--------------+-----------------------+ { kOperandReg, 1, {0 ,0 }, kInvalidValue, kX86RegTypeGpbLo | 4 }, { kOperandReg, 1, {0 ,0 }, kInvalidValue, kX86RegTypeGpbLo | 5 }, { kOperandReg, 1, {0 ,0 }, kInvalidValue, kX86RegTypeGpbLo | 6 }, { kOperandReg, 1, {0 ,0 }, kInvalidValue, kX86RegTypeGpbLo | 7 } }; void X86Assembler::_emitInstruction(uint32_t code) { _emitInstruction(code, &noOperand, &noOperand, &noOperand); } void X86Assembler::_emitInstruction(uint32_t code, const Operand* o0) { _emitInstruction(code, o0, &noOperand, &noOperand); } void X86Assembler::_emitInstruction(uint32_t code, const Operand* o0, const Operand* o1) { _emitInstruction(code, o0, o1, &noOperand); } void X86Assembler::_emitInstruction(uint32_t code, const Operand* o0, const Operand* o1, const Operand* o2) { ASMJIT_ASSERT(o0 != NULL); ASMJIT_ASSERT(o1 != NULL); ASMJIT_ASSERT(o2 != NULL); const Operand* _loggerOperands[3]; uint32_t bLoHiUsed = 0; #if defined(ASMJIT_X86) uint32_t forceRexPrefix = false; #else uint32_t forceRexPrefix = _emitOptions & kX86EmitOptionRex; #endif uint32_t memRegType = kX86RegTypeGpz; #if defined(ASMJIT_DEBUG) bool assertIllegal = false; #endif // ASMJIT_DEBUG const Imm* immOperand = NULL; uint32_t immSize; #define _FINISHED() \ goto _End #define _FINISHED_IMMEDIATE(_Operand_, _Size_) \ do { \ immOperand = reinterpret_cast(_Operand_); \ immSize = (_Size_); \ goto _EmitImmediate; \ } while (0) // Convert operands to kOperandNone if needed. if (o0->isReg()) bLoHiUsed |= o0->_reg.code & (kX86RegTypeGpbLo | kX86RegTypeGpbHi); if (o1->isReg()) bLoHiUsed |= o1->_reg.code & (kX86RegTypeGpbLo | kX86RegTypeGpbHi); if (o2->isReg()) bLoHiUsed |= o2->_reg.code & (kX86RegTypeGpbLo | kX86RegTypeGpbHi); size_t beginOffset = getOffset(); const X86InstInfo* id = &x86InstInfo[code]; if (code >= _kX86InstCount) { setError(kErrorUnknownInstruction); goto _Cleanup; } // Check if register operand is BPL, SPL, SIL, DIL and do action that depends // to current mode: // - 64-bit: - Force REX prefix. // // Check if register operand is AH, BH, CH or DH and do action that depends // to current mode: // - 32-bit: - Patch operand index (index += 4), because we are using // different index what is used in opcode. // - 64-bit: - Check whether there is REX prefix and raise error if it is. // - Do the same as in 32-bit mode - patch register index. // // NOTE: This is a hit hacky, but I added this to older code-base and I have // no energy to rewrite it. Maybe in future all of this can be cleaned up! if (bLoHiUsed | forceRexPrefix) { _loggerOperands[0] = o0; _loggerOperands[1] = o1; _loggerOperands[2] = o2; #if defined(ASMJIT_X64) // Check if there is register that makes this instruction un-encodable. forceRexPrefix |= (uint32_t)X86Assembler_isExtRegisterUsed(*o0); forceRexPrefix |= (uint32_t)X86Assembler_isExtRegisterUsed(*o1); forceRexPrefix |= (uint32_t)X86Assembler_isExtRegisterUsed(*o2); if (o0->isRegType(kX86RegTypeGpbLo) && (o0->_reg.code & kRegIndexMask) >= 4) forceRexPrefix = true; else if (o1->isRegType(kX86RegTypeGpbLo) && (o1->_reg.code & kRegIndexMask) >= 4) forceRexPrefix = true; else if (o2->isRegType(kX86RegTypeGpbLo) && (o2->_reg.code & kRegIndexMask) >= 4) forceRexPrefix = true; if ((bLoHiUsed & kX86RegTypeGpbHi) != 0 && forceRexPrefix) { goto _IllegalInstruction; } #endif // ASMJIT_X64 // Patch GPB.HI operand index. if ((bLoHiUsed & kX86RegTypeGpbHi) != 0) { if (o0->isRegType(kX86RegTypeGpbHi)) o0 = reinterpret_cast(&_patchedHiRegs[o0->_reg.code & kRegIndexMask]); if (o1->isRegType(kX86RegTypeGpbHi)) o1 = reinterpret_cast(&_patchedHiRegs[o1->_reg.code & kRegIndexMask]); if (o2->isRegType(kX86RegTypeGpbHi)) o2 = reinterpret_cast(&_patchedHiRegs[o2->_reg.code & kRegIndexMask]); } } // Check for buffer space (and grow if needed). if (!canEmit()) goto _Cleanup; if (_emitOptions & kX86EmitOptionLock) { if (!id->isLockable()) goto _IllegalInstruction; _emitByte(0xF0); } switch (id->getGroup()) { case kX86InstGroupNone: { _FINISHED(); } case kX86InstGroupEmit: { _emitOpCode(id->_opCode[0]); _FINISHED(); } case kX86InstGroupArith: { uint32_t opCode = id->_opCode[0]; uint8_t opReg = (uint8_t)id->_opCodeR; // Mem <- Reg if (o0->isMem() && o1->isReg()) { _emitX86RM(opCode + (o1->getSize() != 1), o1->getSize() == 2, o1->getSize() == 8, reinterpret_cast(*o1).getRegCode(), reinterpret_cast(*o0), 0, forceRexPrefix); _FINISHED(); } // Reg <- Reg|Mem if (o0->isReg() && o1->isRegMem()) { _emitX86RM(opCode + 2 + (o0->getSize() != 1), o0->getSize() == 2, o0->getSize() == 8, reinterpret_cast(*o0).getRegCode(), reinterpret_cast(*o1), 0, forceRexPrefix); _FINISHED(); } // Alternate Form - AL, AX, EAX, RAX. if (o0->isRegIndex(0) && o1->isImm()) { if (o0->getSize() == 1 || !IntUtil::isInt8(static_cast(o1)->getValue())) { if (o0->getSize() == 2) _emitByte(0x66); // 16-bit. else if (o0->getSize() == 8) _emitByte(0x48); // REX.W. _emitByte((opReg << 3) | (0x04 + (o0->getSize() != 1))); _FINISHED_IMMEDIATE(o1, IntUtil::_min(o0->getSize(), 4)); } } if (o0->isRegMem() && o1->isImm()) { const Imm& imm = reinterpret_cast(*o1); immSize = IntUtil::isInt8(imm.getValue()) ? 1 : IntUtil::_min(o0->getSize(), 4); _emitX86RM(id->_opCode[1] + (o0->getSize() != 1 ? (immSize != 1 ? 1 : 3) : 0), o0->getSize() == 2, o0->getSize() == 8, opReg, reinterpret_cast(*o0), immSize, forceRexPrefix); _FINISHED_IMMEDIATE(&imm, immSize); } break; } case kX86InstGroupBSwap: { if (o0->isReg()) { const GpReg& dst = reinterpret_cast(*o0); #if defined(ASMJIT_X64) _emitRexR(dst.getRegType() == kX86RegTypeGpq, 1, dst.getRegCode(), forceRexPrefix); #endif // ASMJIT_X64 _emitByte(0x0F); _emitModR(1, dst.getRegCode()); _FINISHED(); } break; } case kX86InstGroupBTest: { if (o0->isRegMem() && o1->isReg()) { const Operand& dst = reinterpret_cast(*o0); const GpReg& src = reinterpret_cast(*o1); _emitX86RM(id->_opCode[0], src.isRegType(kX86RegTypeGpw), src.isRegType(kX86RegTypeGpq), src.getRegCode(), dst, 0, forceRexPrefix); _FINISHED(); } if (o0->isRegMem() && o1->isImm()) { const Operand& dst = reinterpret_cast(*o0); const Imm& src = reinterpret_cast(*o1); _emitX86RM(id->_opCode[1], dst.getSize() == 2, dst.getSize() == 8, (uint8_t)id->_opCodeR, dst, 1, forceRexPrefix); _FINISHED_IMMEDIATE(o1, 1); } break; } case kX86InstGroupCall: { if (o0->isRegTypeMem(kX86RegTypeGpz)) { const Operand& dst = reinterpret_cast(*o0); _emitX86RM(0xFF, 0, 0, 2, dst, 0, forceRexPrefix); _FINISHED(); } if (o0->isImm()) { const Imm& imm = reinterpret_cast(*o0); _emitByte(0xE8); _emitJmpOrCallReloc(kX86InstGroupCall, (void*)imm.getValue()); _FINISHED(); } if (o0->isLabel()) { LabelData& l_data = _labels[reinterpret_cast(o0)->getId() & kOperandIdValueMask]; if (l_data.offset != -1) { // Bound label. static const sysint_t rel32_size = 5; sysint_t offs = l_data.offset - getOffset(); ASMJIT_ASSERT(offs <= 0); _emitByte(0xE8); _emitInt32((int32_t)(offs - rel32_size)); } else { // Non-bound label. _emitByte(0xE8); _emitDisplacement(l_data, -4, 4); } _FINISHED(); } break; } case kX86InstGroupCrc32: { if (o0->isReg() && o1->isRegMem()) { const GpReg& dst = reinterpret_cast(*o0); const Operand& src = reinterpret_cast(*o1); ASMJIT_ASSERT(dst.getRegType() == kX86RegTypeGpd || dst.getRegType() == kX86RegTypeGpq); _emitX86RM(id->_opCode[0] + (src.getSize() != 1), src.getSize() == 2, dst.getRegType() == 8, dst.getRegCode(), src, 0, forceRexPrefix); _FINISHED(); } break; } case kX86InstGroupEnter: { if (o0->isImm() && o1->isImm()) { _emitByte(0xC8); _emitWord((uint16_t)(uintptr_t)reinterpret_cast(*o2).getValue()); _emitByte((uint8_t )(uintptr_t)reinterpret_cast(*o1).getValue()); _FINISHED(); } break; } case kX86InstGroupIMul: { // 1 operand if (o0->isRegMem() && o1->isNone() && o2->isNone()) { const Operand& src = reinterpret_cast(*o0); _emitX86RM(0xF6 + (src.getSize() != 1), src.getSize() == 2, src.getSize() == 8, 5, src, 0, forceRexPrefix); _FINISHED(); } // 2 operands else if (o0->isReg() && !o1->isNone() && o2->isNone()) { const GpReg& dst = reinterpret_cast(*o0); ASMJIT_ASSERT(!dst.isRegType(kX86RegTypeGpw)); if (o1->isRegMem()) { const Operand& src = reinterpret_cast(*o1); _emitX86RM(0x0FAF, dst.isRegType(kX86RegTypeGpw), dst.isRegType(kX86RegTypeGpq), dst.getRegCode(), src, 0, forceRexPrefix); _FINISHED(); } else if (o1->isImm()) { const Imm& imm = reinterpret_cast(*o1); if (IntUtil::isInt8(imm.getValue())) { _emitX86RM(0x6B, dst.isRegType(kX86RegTypeGpw), dst.isRegType(kX86RegTypeGpq), dst.getRegCode(), dst, 1, forceRexPrefix); _FINISHED_IMMEDIATE(&imm, 1); } else { immSize = dst.isRegType(kX86RegTypeGpw) ? 2 : 4; _emitX86RM(0x69, dst.isRegType(kX86RegTypeGpw), dst.isRegType(kX86RegTypeGpq), dst.getRegCode(), dst, immSize, forceRexPrefix); _FINISHED_IMMEDIATE(&imm, immSize); } } } // 3 operands else if (o0->isReg() && o1->isRegMem() && o2->isImm()) { const GpReg& dst = reinterpret_cast(*o0); const Operand& src = reinterpret_cast(*o1); const Imm& imm = reinterpret_cast(*o2); if (IntUtil::isInt8(imm.getValue())) { _emitX86RM(0x6B, dst.isRegType(kX86RegTypeGpw), dst.isRegType(kX86RegTypeGpq), dst.getRegCode(), src, 1, forceRexPrefix); _FINISHED_IMMEDIATE(&imm, 1); } else { immSize = dst.isRegType(kX86RegTypeGpw) ? 2 : 4; _emitX86RM(0x69, dst.isRegType(kX86RegTypeGpw), dst.isRegType(kX86RegTypeGpq), dst.getRegCode(), src, immSize, forceRexPrefix); _FINISHED_IMMEDIATE(&imm, immSize); } } break; } case kX86InstGroupIncDec: { if (o0->isRegMem()) { const Operand& dst = reinterpret_cast(*o0); // INC [r16|r32] in 64-bit mode is not encodable. #if defined(ASMJIT_X86) if ((dst.isReg()) && (dst.isRegType(kX86RegTypeGpw) || dst.isRegType(kX86RegTypeGpd))) { _emitX86Inl(id->_opCode[0], dst.isRegType(kX86RegTypeGpw), 0, reinterpret_cast(dst).getRegCode(), false); _FINISHED(); } #endif // ASMJIT_X86 _emitX86RM(id->_opCode[1] + (dst.getSize() != 1), dst.getSize() == 2, dst.getSize() == 8, (uint8_t)id->_opCodeR, dst, 0, forceRexPrefix); _FINISHED(); } break; } case kX86InstGroupJcc: { if (o0->isLabel()) { LabelData& l_data = _labels[reinterpret_cast(o0)->getId() & kOperandIdValueMask]; uint32_t hint = (uint32_t)(o1->isImm() ? reinterpret_cast(*o1).getValue() : 0); bool isShortJump = (_emitOptions & kX86EmitOptionShortJump) != 0; // Emit jump hint if configured for that. if ((hint & (kCondHintLikely | kCondHintUnlikely)) && (_properties & (1 << kX86PropertyJumpHints))) { if (hint & kCondHintLikely) _emitByte(kX86CondPrefixLikely); else if (hint & kCondHintUnlikely) _emitByte(kX86CondPrefixUnlikely); } if (l_data.offset != -1) { // Bound label. static const sysint_t rel8_size = 2; static const sysint_t rel32_size = 6; sysint_t offs = l_data.offset - getOffset(); ASMJIT_ASSERT(offs <= 0); if (IntUtil::isInt8(offs - rel8_size)) { _emitByte(0x70 | (uint8_t)id->_opCode[0]); _emitByte((uint8_t)(int8_t)(offs - rel8_size)); // Change the emit options so logger can log instruction correctly. _emitOptions |= kX86EmitOptionShortJump; } else { if (isShortJump && _logger) { _logger->logString("*** ASSEMBLER WARNING: Emitting long conditional jump, but short jump instruction forced!\n"); _emitOptions &= ~kX86EmitOptionShortJump; } _emitByte(0x0F); _emitByte(0x80 | (uint8_t)id->_opCode[0]); _emitInt32((int32_t)(offs - rel32_size)); } } else { // Non-bound label. if (isShortJump) { _emitByte(0x70 | (uint8_t)id->_opCode[0]); _emitDisplacement(l_data, -1, 1); } else { _emitByte(0x0F); _emitByte(0x80 | (uint8_t)id->_opCode[0]); _emitDisplacement(l_data, -4, 4); } } _FINISHED(); } break; } case kX86InstGroupJmp: { if (o0->isRegMem()) { const Operand& dst = reinterpret_cast(*o0); _emitX86RM(0xFF, 0, 0, 4, dst, 0, forceRexPrefix); _FINISHED(); } if (o0->isImm()) { const Imm& imm = reinterpret_cast(*o0); _emitByte(0xE9); _emitJmpOrCallReloc(kX86InstGroupJmp, (void*)imm.getValue()); _FINISHED(); } if (o0->isLabel()) { LabelData& l_data = _labels[reinterpret_cast(o0)->getId() & kOperandIdValueMask]; bool isShortJump = (_emitOptions & kX86EmitOptionShortJump) != 0; if (l_data.offset != -1) { // Bound label. const sysint_t rel8_size = 2; const sysint_t rel32_size = 5; sysint_t offs = l_data.offset - getOffset(); if (IntUtil::isInt8(offs - rel8_size)) { _emitByte(0xEB); _emitByte((uint8_t)(int8_t)(offs - rel8_size)); // Change the emit options so logger can log instruction correctly. _emitOptions |= kX86EmitOptionShortJump; } else { if (isShortJump) { if (_logger) { _logger->logString("*** ASSEMBLER WARNING: Emitting long jump, but short jump instruction forced!\n"); _emitOptions &= ~kX86EmitOptionShortJump; } } _emitByte(0xE9); _emitInt32((int32_t)(offs - rel32_size)); } } else { // Non-bound label. if (isShortJump) { _emitByte(0xEB); _emitDisplacement(l_data, -1, 1); } else { _emitByte(0xE9); _emitDisplacement(l_data, -4, 4); } } _FINISHED(); } break; } case kX86InstGroupLea: { if (o0->isReg() && o1->isMem()) { const GpReg& dst = reinterpret_cast(*o0); const Mem& src = reinterpret_cast(*o1); // Size override prefix support. if (src.getSizePrefix()) { _emitByte(0x67); #if defined(ASMJIT_X86) memRegType = kX86RegTypeGpw; #else memRegType = kX86RegTypeGpd; #endif } _emitX86RM(0x8D, dst.isRegType(kX86RegTypeGpw), dst.isRegType(kX86RegTypeGpq), dst.getRegCode(), src, 0, forceRexPrefix); _FINISHED(); } break; } case kX86InstGroupMem: { if (o0->isMem()) { _emitX86RM(id->_opCode[0], 0, (uint8_t)id->_opCode[1], (uint8_t)id->_opCodeR, reinterpret_cast(*o0), 0, forceRexPrefix); _FINISHED(); } break; } case kX86InstGroupMov: { const Operand& dst = *o0; const Operand& src = *o1; switch (dst.getType() << 4 | src.getType()) { // Reg <- Reg/Mem case (kOperandReg << 4) | kOperandReg: { // Reg <- Sreg if (src.isRegType(kX86RegTypeSeg)) { ASMJIT_ASSERT(dst.isRegType(kX86RegTypeGpw) || dst.isRegType(kX86RegTypeGpd) || dst.isRegType(kX86RegTypeGpq) ); _emitX86RM(0x8C, dst.getSize() == 2, dst.getSize() == 8, reinterpret_cast(src).getRegCode(), reinterpret_cast(dst), 0, forceRexPrefix); _FINISHED(); } // Sreg <- Reg/Mem if (dst.isRegType(kX86RegTypeSeg)) { ASMJIT_ASSERT(src.isRegType(kX86RegTypeGpw ) || src.isRegType(kX86RegTypeGpd ) || src.isRegType(kX86RegTypeGpq ) ); _Emit_Mov_Sreg_RM: _emitX86RM(0x8E, src.getSize() == 2, src.getSize() == 8, reinterpret_cast(dst).getRegCode(), reinterpret_cast(src), 0, forceRexPrefix); _FINISHED(); } ASMJIT_ASSERT(src.isRegType(kX86RegTypeGpbLo) || src.isRegType(kX86RegTypeGpbHi) || src.isRegType(kX86RegTypeGpw ) || src.isRegType(kX86RegTypeGpd ) || src.isRegType(kX86RegTypeGpq ) ); // ... fall through ... } case (kOperandReg << 4) | kOperandMem: { // Sreg <- Mem if (dst.isRegType(kX86RegTypeSeg)) { goto _Emit_Mov_Sreg_RM; } ASMJIT_ASSERT(dst.isRegType(kX86RegTypeGpbLo) || dst.isRegType(kX86RegTypeGpbHi) || dst.isRegType(kX86RegTypeGpw ) || dst.isRegType(kX86RegTypeGpd ) || dst.isRegType(kX86RegTypeGpq ) ); _emitX86RM(0x0000008A + (dst.getSize() != 1), dst.isRegType(kX86RegTypeGpw), dst.isRegType(kX86RegTypeGpq), reinterpret_cast(dst).getRegCode(), reinterpret_cast(src), 0, forceRexPrefix); _FINISHED(); } // Reg <- Imm case (kOperandReg << 4) | kOperandImm: { const GpReg& dst = reinterpret_cast(*o0); const Imm& src = reinterpret_cast(*o1); // In 64-bit mode the immediate can be 64-bits long if the // destination operand type is register (otherwise 32-bits). immSize = dst.getSize(); #if defined(ASMJIT_X64) // Optimize instruction size by using 32-bit immediate if value can // fit into it. if (immSize == 8 && IntUtil::isInt32(src.getValue())) { _emitX86RM(0xC7, 0, // 16BIT 1, // REX.W 0, // O dst, 0, forceRexPrefix); immSize = 4; } else { #endif // ASMJIT_X64 _emitX86Inl((dst.getSize() == 1 ? 0xB0 : 0xB8), dst.isRegType(kX86RegTypeGpw), dst.isRegType(kX86RegTypeGpq), dst.getRegCode(), forceRexPrefix); #if defined(ASMJIT_X64) } #endif // ASMJIT_X64 _FINISHED_IMMEDIATE(&src, immSize); } // Mem <- Reg/Sreg case (kOperandMem << 4) | kOperandReg: { if (src.isRegType(kX86RegTypeSeg)) { // Mem <- Sreg _emitX86RM(0x8C, dst.getSize() == 2, dst.getSize() == 8, reinterpret_cast(src).getRegCode(), reinterpret_cast(dst), 0, forceRexPrefix); _FINISHED(); } else { // Mem <- Reg ASMJIT_ASSERT(src.isRegType(kX86RegTypeGpbLo) || src.isRegType(kX86RegTypeGpbHi) || src.isRegType(kX86RegTypeGpw ) || src.isRegType(kX86RegTypeGpd ) || src.isRegType(kX86RegTypeGpq ) ); _emitX86RM(0x88 + (src.getSize() != 1), src.isRegType(kX86RegTypeGpw), src.isRegType(kX86RegTypeGpq), reinterpret_cast(src).getRegCode(), reinterpret_cast(dst), 0, forceRexPrefix); _FINISHED(); } } // Mem <- Imm case (kOperandMem << 4) | kOperandImm: { immSize = IntUtil::_min(dst.getSize(), 4); _emitX86RM(0xC6 + (dst.getSize() != 1), dst.getSize() == 2, dst.getSize() == 8, 0, reinterpret_cast(dst), immSize, forceRexPrefix); _FINISHED_IMMEDIATE(&src, immSize); } } break; } case kX86InstGroupMovPtr: { if ((o0->isReg() && o1->isImm()) || (o0->isImm() && o1->isReg())) { bool reverse = o1->getType() == kOperandReg; uint8_t opCode = !reverse ? 0xA0 : 0xA2; const GpReg& reg = reinterpret_cast(!reverse ? *o0 : *o1); const Imm& imm = reinterpret_cast(!reverse ? *o1 : *o0); if (reg.getRegIndex() != 0) goto _IllegalInstruction; if (reg.isRegType(kX86RegTypeGpw)) _emitByte(0x66); #if defined(ASMJIT_X64) _emitRexR(reg.getSize() == 8, 0, 0, forceRexPrefix); #endif // ASMJIT_X64 _emitByte(opCode + (reg.getSize() != 1)); _FINISHED_IMMEDIATE(&imm, sizeof(sysint_t)); } break; } case kX86InstGroupMovSxMovZx: { if (o0->isReg() && o1->isRegMem()) { const GpReg& dst = reinterpret_cast(*o0); const Operand& src = reinterpret_cast(*o1); if (dst.getSize() == 1) goto _IllegalInstruction; if (src.getSize() != 1 && src.getSize() != 2) goto _IllegalInstruction; if (src.getSize() == 2 && dst.getSize() == 2) goto _IllegalInstruction; _emitX86RM(id->_opCode[0] + (src.getSize() != 1), dst.isRegType(kX86RegTypeGpw), dst.isRegType(kX86RegTypeGpq), dst.getRegCode(), src, 0, forceRexPrefix); _FINISHED(); } break; } #if defined(ASMJIT_X64) case kX86InstGroupMovSxD: { if (o0->isReg() && o1->isRegMem()) { const GpReg& dst = reinterpret_cast(*o0); const Operand& src = reinterpret_cast(*o1); _emitX86RM(0x00000063, 0, 1, dst.getRegCode(), src, 0, forceRexPrefix); _FINISHED(); } break; } #endif // ASMJIT_X64 case kX86InstGroupPush: { if (o0->isRegType(kX86RegTypeSeg)) { static const uint32_t opcodeList[] = { 0x06, // ES. 0x0E, // CS. 0x16, // SS. 0x1E, // DS. 0x0FA0, // FS. 0x0FA8 // GS. }; unsigned int segment = reinterpret_cast(o0)->getRegIndex(); ASMJIT_ASSERT(segment < kX86SegCount); unsigned int opcode = opcodeList[segment]; if (opcode > 0xFF) _emitByte(opcode >> 8); _emitByte(opcode & 0xFF); _FINISHED(); } // This section is only for immediates, memory/register operands are handled in kX86InstGroupPop. if (o0->isImm()) { const Imm& imm = reinterpret_cast(*o0); if (IntUtil::isInt8(imm.getValue())) { _emitByte(0x6A); _FINISHED_IMMEDIATE(&imm, 1); } else { _emitByte(0x68); _FINISHED_IMMEDIATE(&imm, 4); } } // ... goto kX86InstGroupPop ... } case kX86InstGroupPop: { if (o0->isRegType(kX86RegTypeSeg)) { static const uint32_t opcodeList[] = { 0x07, // ES. 0, // CS. 0x17, // SS. 0x1F, // DS. 0x0FA1, // FS. 0x0FA9 // GS. }; unsigned int segment = reinterpret_cast(o0)->getRegIndex(); ASMJIT_ASSERT(segment < kX86SegCount); unsigned int opcode = opcodeList[segment]; ASMJIT_ASSERT(opcode != 0); if (opcode > 0xFF) _emitByte(opcode >> 8); _emitByte(opcode & 0xFF); _FINISHED(); } if (o0->isReg()) { ASMJIT_ASSERT(o0->isRegType(kX86RegTypeGpw) || o0->isRegType(kX86RegTypeGpz)); _emitX86Inl(id->_opCode[0], o0->isRegType(kX86RegTypeGpw), 0, reinterpret_cast(*o0).getRegCode(), forceRexPrefix); _FINISHED(); } if (o0->isMem()) { _emitX86RM(id->_opCode[1], o0->getSize() == 2, 0, (uint8_t)id->_opCodeR, reinterpret_cast(*o0), 0, forceRexPrefix); _FINISHED(); } break; } case kX86InstGroupRegRm: { if (o0->isReg() && o1->isRegMem()) { const GpReg& dst = reinterpret_cast(*o0); const Operand& src = reinterpret_cast(*o1); ASMJIT_ASSERT(dst.getSize() != 1); _emitX86RM(id->_opCode[0], dst.getRegType() == kX86RegTypeGpw, dst.getRegType() == kX86RegTypeGpq, dst.getRegCode(), src, 0, forceRexPrefix); _FINISHED(); } break; } case kX86InstGroupRm: { if (o0->isRegMem()) { const Operand& op = reinterpret_cast(*o0); _emitX86RM(id->_opCode[0] + (op.getSize() != 1), op.getSize() == 2, op.getSize() == 8, (uint8_t)id->_opCodeR, op, 0, forceRexPrefix); _FINISHED(); } break; } case kX86InstGroupRmByte: { if (o0->isRegMem()) { const Operand& op = reinterpret_cast(*o0); // Only BYTE register or BYTE/TYPELESS memory location can be used. ASMJIT_ASSERT(op.getSize() <= 1); _emitX86RM(id->_opCode[0], false, false, 0, op, 0, forceRexPrefix); _FINISHED(); } break; } case kX86InstGroupRmReg: { if (o0->isRegMem() && o1->isReg()) { const Operand& dst = reinterpret_cast(*o0); const GpReg& src = reinterpret_cast(*o1); _emitX86RM(id->_opCode[0] + (src.getSize() != 1), src.getRegType() == kX86RegTypeGpw, src.getRegType() == kX86RegTypeGpq, src.getRegCode(), dst, 0, forceRexPrefix); _FINISHED(); } break; } case kX86InstGroupRep: { uint32_t opCode = id->_opCode[0]; uint32_t opSize = id->_opCode[1]; // Emit REP prefix (1 BYTE). _emitByte(opCode >> 24); if (opSize != 1) opCode++; // D, Q and W form. if (opSize == 2) _emitByte(0x66); // 16-bit prefix. #if defined(ASMJIT_X64) else if (opSize == 8) _emitByte(0x48); // REX.W prefix. #endif // ASMJIT_X64 // Emit opcode (1 BYTE). _emitByte(opCode & 0xFF); _FINISHED(); } case kX86InstGroupRet: { if (o0->isNone()) { _emitByte(0xC3); _FINISHED(); } else if (o0->isImm()) { const Imm& imm = reinterpret_cast(*o0); ASMJIT_ASSERT(IntUtil::isUInt16(imm.getValue())); if (imm.getValue() == 0) { _emitByte(0xC3); _FINISHED(); } else { _emitByte(0xC2); _FINISHED_IMMEDIATE(&imm, 2); } } break; } case kX86InstGroupRot: { if (o0->isRegMem() && (o1->isRegCode(kX86RegCl) || o1->isImm())) { // generate opcode. For these operations is base 0xC0 or 0xD0. bool useImm8 = o1->isImm() && reinterpret_cast(*o1).getValue() != 1; uint32_t opCode = useImm8 ? 0xC0 : 0xD0; // size and operand type modifies the opcode if (o0->getSize() != 1) opCode |= 0x01; if (o1->getType() == kOperandReg) opCode |= 0x02; _emitX86RM(opCode, o0->getSize() == 2, o0->getSize() == 8, (uint8_t)id->_opCodeR, reinterpret_cast(*o0), useImm8 ? 1 : 0, forceRexPrefix); if (useImm8) _FINISHED_IMMEDIATE(o1, 1); else _FINISHED(); } break; } case kX86InstGroupShldShrd: { if (o0->isRegMem() && o1->isReg() && (o2->isImm() || (o2->isReg() && o2->isRegCode(kX86RegCl)))) { const Operand& dst = reinterpret_cast(*o0); const GpReg& src1 = reinterpret_cast(*o1); const Operand& src2 = reinterpret_cast(*o2); ASMJIT_ASSERT(dst.getSize() == src1.getSize()); _emitX86RM(id->_opCode[0] + src2.isReg(), src1.isRegType(kX86RegTypeGpw), src1.isRegType(kX86RegTypeGpq), src1.getRegCode(), dst, src2.isImm() ? 1 : 0, forceRexPrefix); if (src2.isImm()) _FINISHED_IMMEDIATE(&src2, 1); else _FINISHED(); } break; } case kX86InstGroupTest: { if (o0->isRegMem() && o1->isReg()) { ASMJIT_ASSERT(o0->getSize() == o1->getSize()); _emitX86RM(0x84 + (o1->getSize() != 1), o1->getSize() == 2, o1->getSize() == 8, reinterpret_cast(*o1).getRegCode(), reinterpret_cast(*o0), 0, forceRexPrefix); _FINISHED(); } // Alternate Form - AL, AX, EAX, RAX. if (o0->isRegIndex(0) && o1->isImm()) { immSize = IntUtil::_min(o0->getSize(), 4); if (o0->getSize() == 2) _emitByte(0x66); // 16-bit. #if defined(ASMJIT_X64) _emitRexRM(o0->getSize() == 8, 0, reinterpret_cast(*o0), forceRexPrefix); #endif // ASMJIT_X64 _emitByte(0xA8 + (o0->getSize() != 1)); _FINISHED_IMMEDIATE(o1, immSize); } if (o0->isRegMem() && o1->isImm()) { immSize = IntUtil::_min(o0->getSize(), 4); if (o0->getSize() == 2) _emitByte(0x66); // 16-bit. _emitSegmentPrefix(reinterpret_cast(*o0)); // Segment prefix. #if defined(ASMJIT_X64) _emitRexRM(o0->getSize() == 8, 0, reinterpret_cast(*o0), forceRexPrefix); #endif // ASMJIT_X64 _emitByte(0xF6 + (o0->getSize() != 1)); _emitModRM(0, reinterpret_cast(*o0), immSize); _FINISHED_IMMEDIATE(o1, immSize); } break; } case kX86InstGroupXchg: { if (o0->isRegMem() && o1->isReg()) { const Operand& dst = reinterpret_cast(*o0); const GpReg& src = reinterpret_cast(*o1); if (src.isRegType(kX86RegTypeGpw)) _emitByte(0x66); // 16-bit. _emitSegmentPrefix(dst); // segment prefix #if defined(ASMJIT_X64) _emitRexRM(src.isRegType(kX86RegTypeGpq), src.getRegCode(), dst, forceRexPrefix); #endif // ASMJIT_X64 // Special opcode for index 0 registers (AX, EAX, RAX vs register). if ((dst.getType() == kOperandReg && dst.getSize() > 1) && (reinterpret_cast(dst).getRegCode() == 0 || reinterpret_cast(src).getRegCode() == 0 )) { uint8_t index = reinterpret_cast(dst).getRegCode() | src.getRegCode(); _emitByte(0x90 + index); _FINISHED(); } _emitByte(0x86 + (src.getSize() != 1)); _emitModRM(src.getRegCode(), dst, 0); _FINISHED(); } break; } case kX86InstGroupMovBE: { if (o0->isReg() && o1->isMem()) { _emitX86RM(0x000F38F0, o0->isRegType(kX86RegTypeGpw), o0->isRegType(kX86RegTypeGpq), reinterpret_cast(*o0).getRegCode(), reinterpret_cast(*o1), 0, forceRexPrefix); _FINISHED(); } if (o0->isMem() && o1->isReg()) { _emitX86RM(0x000F38F1, o1->isRegType(kX86RegTypeGpw), o1->isRegType(kX86RegTypeGpq), reinterpret_cast(*o1).getRegCode(), reinterpret_cast(*o0), 0, forceRexPrefix); _FINISHED(); } break; } case kX86InstGroupX87StM: { if (o0->isRegType(kX86RegTypeX87)) { uint8_t i1 = reinterpret_cast(*o0).getRegIndex(); uint8_t i2 = 0; if (code != kX86InstFCom && code != kX86InstFComP) { if (!o1->isRegType(kX86RegTypeX87)) goto _IllegalInstruction; i2 = reinterpret_cast(*o1).getRegIndex(); } else if (i1 != 0 && i2 != 0) { goto _IllegalInstruction; } _emitByte(i1 == 0 ? ((id->_opCode[0] & 0xFF000000) >> 24) : ((id->_opCode[0] & 0x00FF0000) >> 16)); _emitByte(i1 == 0 ? ((id->_opCode[0] & 0x0000FF00) >> 8) + i2 : ((id->_opCode[0] & 0x000000FF) ) + i1); _FINISHED(); } if (o0->isMem() && (o0->getSize() == 4 || o0->getSize() == 8) && o1->isNone()) { const Mem& m = reinterpret_cast(*o0); // Segment prefix. _emitSegmentPrefix(m); _emitByte(o0->getSize() == 4 ? ((id->_opCode[0] & 0xFF000000) >> 24) : ((id->_opCode[0] & 0x00FF0000) >> 16)); _emitModM((uint8_t)id->_opCodeR, m, 0); _FINISHED(); } break; } case kX86InstGroupX87StI: { if (o0->isRegType(kX86RegTypeX87)) { uint8_t i = reinterpret_cast(*o0).getRegIndex(); _emitByte((uint8_t)((id->_opCode[0] & 0x0000FF00) >> 8)); _emitByte((uint8_t)((id->_opCode[0] & 0x000000FF) + i)); _FINISHED(); } break; } case kX86InstGroupX87Status: { if (o0->isReg() && reinterpret_cast(*o0).getRegType() <= kX86RegTypeGpq && reinterpret_cast(*o0).getRegIndex() == 0) { _emitOpCode(id->_opCode[1]); _FINISHED(); } if (o0->isMem()) { _emitX86RM(id->_opCode[0], 0, 0, (uint8_t)id->_opCodeR, reinterpret_cast(*o0), 0, forceRexPrefix); _FINISHED(); } break; } case kX86InstGroupX87FldFst: { if (o0->isRegType(kX86RegTypeX87)) { _emitByte((uint8_t)((id->_opCode[1] & 0xFF000000) >> 24)); _emitByte((uint8_t)((id->_opCode[1] & 0x00FF0000) >> 16) + reinterpret_cast(*o0).getRegIndex()); _FINISHED(); } // ... fall through to kX86InstGroupX87Mem ... } case kX86InstGroupX87Mem: { if (!o0->isMem()) goto _IllegalInstruction; const Mem& m = reinterpret_cast(*o0); uint8_t opCode = 0x00, mod = 0; if (o0->getSize() == 2 && (id->_opFlags[0] & kX86InstOpStM2)) { opCode = (uint8_t)((id->_opCode[0] & 0xFF000000) >> 24); mod = (uint8_t)id->_opCodeR; } if (o0->getSize() == 4 && (id->_opFlags[0] & kX86InstOpStM4)) { opCode = (uint8_t)((id->_opCode[0] & 0x00FF0000) >> 16); mod = (uint8_t)id->_opCodeR; } if (o0->getSize() == 8 && (id->_opFlags[0] & kX86InstOpStM8)) { opCode = (uint8_t)((id->_opCode[0] & 0x0000FF00) >> 8); mod = (uint8_t)((id->_opCode[0] & 0x000000FF) ); } if (opCode) { _emitSegmentPrefix(m); _emitByte(opCode); _emitModM(mod, m, 0); _FINISHED(); } break; } case kX86InstGroupMmuMov: { ASMJIT_ASSERT(id->_opFlags[0] != 0); ASMJIT_ASSERT(id->_opFlags[1] != 0); // Check parameters (X)MM|GP32_64 <- (X)MM|GP32_64|Mem|Imm if ((o0->isMem() && (id->_opFlags[0] & kX86InstOpMem) == 0) || (o0->isRegType(kX86RegTypeMm ) && (id->_opFlags[0] & kX86InstOpMm ) == 0) || (o0->isRegType(kX86RegTypeXmm) && (id->_opFlags[0] & kX86InstOpXmm) == 0) || (o0->isRegType(kX86RegTypeGpd) && (id->_opFlags[0] & kX86InstOpGd ) == 0) || (o0->isRegType(kX86RegTypeGpq) && (id->_opFlags[0] & kX86InstOpGq ) == 0) || (o1->isRegType(kX86RegTypeMm ) && (id->_opFlags[1] & kX86InstOpMm ) == 0) || (o1->isRegType(kX86RegTypeXmm) && (id->_opFlags[1] & kX86InstOpXmm) == 0) || (o1->isRegType(kX86RegTypeGpd) && (id->_opFlags[1] & kX86InstOpGd ) == 0) || (o1->isRegType(kX86RegTypeGpq) && (id->_opFlags[1] & kX86InstOpGq ) == 0) || (o1->isMem() && (id->_opFlags[1] & kX86InstOpMem) == 0) ) { goto _IllegalInstruction; } // Illegal. if (o0->isMem() && o1->isMem()) goto _IllegalInstruction; uint8_t rexw = ((id->_opFlags[0] | id->_opFlags[1]) & kX86InstOpNoRex) ? 0 : o0->isRegType(kX86RegTypeGpq) | o1->isRegType(kX86RegTypeGpq); // (X)MM|Reg <- (X)MM|Reg if (o0->isReg() && o1->isReg()) { _emitMmu(id->_opCode[0], rexw, reinterpret_cast(*o0).getRegCode(), reinterpret_cast(*o1), 0); _FINISHED(); } // (X)MM|Reg <- Mem if (o0->isReg() && o1->isMem()) { _emitMmu(id->_opCode[0], rexw, reinterpret_cast(*o0).getRegCode(), reinterpret_cast(*o1), 0); _FINISHED(); } // Mem <- (X)MM|Reg if (o0->isMem() && o1->isReg()) { _emitMmu(id->_opCode[1], rexw, reinterpret_cast(*o1).getRegCode(), reinterpret_cast(*o0), 0); _FINISHED(); } break; } case kX86InstGroupMmuMovD: { if ((o0->isRegType(kX86RegTypeMm) || o0->isRegType(kX86RegTypeXmm)) && (o1->isRegType(kX86RegTypeGpd) || o1->isMem())) { _emitMmu(o0->isRegType(kX86RegTypeXmm) ? 0x66000F6E : 0x00000F6E, 0, reinterpret_cast(*o0).getRegCode(), reinterpret_cast(*o1), 0); _FINISHED(); } if ((o0->isRegType(kX86RegTypeGpd) || o0->isMem()) && (o1->isRegType(kX86RegTypeMm) || o1->isRegType(kX86RegTypeXmm))) { _emitMmu(o1->isRegType(kX86RegTypeXmm) ? 0x66000F7E : 0x00000F7E, 0, reinterpret_cast(*o1).getRegCode(), reinterpret_cast(*o0), 0); _FINISHED(); } break; } case kX86InstGroupMmuMovQ: { if (o0->isRegType(kX86RegTypeMm) && o1->isRegType(kX86RegTypeMm)) { _emitMmu(0x00000F6F, 0, reinterpret_cast(*o0).getRegCode(), reinterpret_cast(*o1), 0); _FINISHED(); } if (o0->isRegType(kX86RegTypeXmm) && o1->isRegType(kX86RegTypeXmm)) { _emitMmu(0xF3000F7E, 0, reinterpret_cast(*o0).getRegCode(), reinterpret_cast(*o1), 0); _FINISHED(); } // Convenience - movdq2q if (o0->isRegType(kX86RegTypeMm) && o1->isRegType(kX86RegTypeXmm)) { _emitMmu(0xF2000FD6, 0, reinterpret_cast(*o0).getRegCode(), reinterpret_cast(*o1), 0); _FINISHED(); } // Convenience - movq2dq if (o0->isRegType(kX86RegTypeXmm) && o1->isRegType(kX86RegTypeMm)) { _emitMmu(0xF3000FD6, 0, reinterpret_cast(*o0).getRegCode(), reinterpret_cast(*o1), 0); _FINISHED(); } if (o0->isRegType(kX86RegTypeMm) && o1->isMem()) { _emitMmu(0x00000F6F, 0, reinterpret_cast(*o0).getRegCode(), reinterpret_cast(*o1), 0); _FINISHED(); } if (o0->isRegType(kX86RegTypeXmm) && o1->isMem()) { _emitMmu(0xF3000F7E, 0, reinterpret_cast(*o0).getRegCode(), reinterpret_cast(*o1), 0); _FINISHED(); } if (o0->isMem() && o1->isRegType(kX86RegTypeMm)) { _emitMmu(0x00000F7F, 0, reinterpret_cast(*o1).getRegCode(), reinterpret_cast(*o0), 0); _FINISHED(); } if (o0->isMem() && o1->isRegType(kX86RegTypeXmm)) { _emitMmu(0x66000FD6, 0, reinterpret_cast(*o1).getRegCode(), reinterpret_cast(*o0), 0); _FINISHED(); } #if defined(ASMJIT_X64) if ((o0->isRegType(kX86RegTypeMm) || o0->isRegType(kX86RegTypeXmm)) && (o1->isRegType(kX86RegTypeGpq) || o1->isMem())) { _emitMmu(o0->isRegType(kX86RegTypeXmm) ? 0x66000F6E : 0x00000F6E, 1, reinterpret_cast(*o0).getRegCode(), reinterpret_cast(*o1), 0); _FINISHED(); } if ((o0->isRegType(kX86RegTypeGpq) || o0->isMem()) && (o1->isRegType(kX86RegTypeMm) || o1->isRegType(kX86RegTypeXmm))) { _emitMmu(o1->isRegType(kX86RegTypeXmm) ? 0x66000F7E : 0x00000F7E, 1, reinterpret_cast(*o1).getRegCode(), reinterpret_cast(*o0), 0); _FINISHED(); } #endif // ASMJIT_X64 break; } case kX86InstGroupMmuExtract: { if (!(o0->isRegMem() && (o1->isRegType(kX86RegTypeXmm) || (code == kX86InstPExtrW && o1->isRegType(kX86RegTypeMm))) && o2->isImm())) { goto _IllegalInstruction; } uint32_t opCode = id->_opCode[0]; uint8_t isGpdGpq = o0->isRegType(kX86RegTypeGpd) | o0->isRegType(kX86RegTypeGpq); if (code == kX86InstPExtrB && (o0->getSize() != 0 && o0->getSize() != 1) && !isGpdGpq) goto _IllegalInstruction; if (code == kX86InstPExtrW && (o0->getSize() != 0 && o0->getSize() != 2) && !isGpdGpq) goto _IllegalInstruction; if (code == kX86InstPExtrD && (o0->getSize() != 0 && o0->getSize() != 4) && !isGpdGpq) goto _IllegalInstruction; if (code == kX86InstPExtrQ && (o0->getSize() != 0 && o0->getSize() != 8) && !isGpdGpq) goto _IllegalInstruction; if (o1->isRegType(kX86RegTypeXmm)) opCode |= 0x66000000; if (o0->isReg()) { _emitMmu(opCode, id->_opCodeR | (uint8_t)o0->isRegType(kX86RegTypeGpq), reinterpret_cast(*o1).getRegCode(), reinterpret_cast(*o0), 1); _FINISHED_IMMEDIATE(o2, 1); } if (o0->isMem()) { _emitMmu(opCode, (uint8_t)id->_opCodeR, reinterpret_cast(*o1).getRegCode(), reinterpret_cast(*o0), 1); _FINISHED_IMMEDIATE(o2, 1); } break; } case kX86InstGroupMmuPrefetch: { if (o0->isMem() && o1->isImm()) { const Mem& mem = reinterpret_cast(*o0); const Imm& hint = reinterpret_cast(*o1); _emitMmu(0x00000F18, 0, (uint8_t)hint.getValue(), mem, 0); _FINISHED(); } break; } case kX86InstGroupMmuRmI: { ASMJIT_ASSERT(id->_opFlags[0] != 0); ASMJIT_ASSERT(id->_opFlags[1] != 0); // Check parameters (X)MM|GP32_64 <- (X)MM|GP32_64|Mem|Imm if (!o0->isReg() || (o0->isRegType(kX86RegTypeMm ) && (id->_opFlags[0] & kX86InstOpMm ) == 0) || (o0->isRegType(kX86RegTypeXmm) && (id->_opFlags[0] & kX86InstOpXmm) == 0) || (o0->isRegType(kX86RegTypeGpd) && (id->_opFlags[0] & kX86InstOpGd ) == 0) || (o0->isRegType(kX86RegTypeGpq) && (id->_opFlags[0] & kX86InstOpGq ) == 0) || (o1->isRegType(kX86RegTypeMm ) && (id->_opFlags[1] & kX86InstOpMm ) == 0) || (o1->isRegType(kX86RegTypeXmm) && (id->_opFlags[1] & kX86InstOpXmm) == 0) || (o1->isRegType(kX86RegTypeGpd) && (id->_opFlags[1] & kX86InstOpGd ) == 0) || (o1->isRegType(kX86RegTypeGpq) && (id->_opFlags[1] & kX86InstOpGq ) == 0) || (o1->isMem() && (id->_opFlags[1] & kX86InstOpMem) == 0) || (o1->isImm() && (id->_opFlags[1] & kX86InstOpImm) == 0)) { goto _IllegalInstruction; } uint32_t prefix = ((id->_opFlags[0] & kX86InstOpMmXmm) == kX86InstOpMmXmm && o0->isRegType(kX86RegTypeXmm)) || ((id->_opFlags[1] & kX86InstOpMmXmm) == kX86InstOpMmXmm && o1->isRegType(kX86RegTypeXmm)) ? 0x66000000 : 0x00000000; uint8_t rexw = ((id->_opFlags[0] | id->_opFlags[1]) & kX86InstOpNoRex) ? 0 : o0->isRegType(kX86RegTypeGpq) | o1->isRegType(kX86RegTypeGpq); // (X)MM <- (X)MM (opcode0) if (o1->isReg()) { if ((id->_opFlags[1] & (kX86InstOpMmXmm | kX86InstOpGqd)) == 0) goto _IllegalInstruction; _emitMmu(id->_opCode[0] | prefix, rexw, reinterpret_cast(*o0).getRegCode(), reinterpret_cast(*o1), 0); _FINISHED(); } // (X)MM <- Mem (opcode0) if (o1->isMem()) { if ((id->_opFlags[1] & kX86InstOpMem) == 0) goto _IllegalInstruction; _emitMmu(id->_opCode[0] | prefix, rexw, reinterpret_cast(*o0).getRegCode(), reinterpret_cast(*o1), 0); _FINISHED(); } // (X)MM <- Imm (opcode1+opcodeR) if (o1->isImm()) { if ((id->_opFlags[1] & kX86InstOpImm) == 0) goto _IllegalInstruction; _emitMmu(id->_opCode[1] | prefix, rexw, (uint8_t)id->_opCodeR, reinterpret_cast(*o0), 1); _FINISHED_IMMEDIATE(o1, 1); } break; } case kX86InstGroupMmuRmImm8: { ASMJIT_ASSERT(id->_opFlags[0] != 0); ASMJIT_ASSERT(id->_opFlags[1] != 0); // Check parameters (X)MM|GP32_64 <- (X)MM|GP32_64|Mem|Imm if (!o0->isReg() || (o0->isRegType(kX86RegTypeMm ) && (id->_opFlags[0] & kX86InstOpMm ) == 0) || (o0->isRegType(kX86RegTypeXmm) && (id->_opFlags[0] & kX86InstOpXmm) == 0) || (o0->isRegType(kX86RegTypeGpd) && (id->_opFlags[0] & kX86InstOpGd ) == 0) || (o0->isRegType(kX86RegTypeGpq) && (id->_opFlags[0] & kX86InstOpGq ) == 0) || (o1->isRegType(kX86RegTypeMm ) && (id->_opFlags[1] & kX86InstOpMm ) == 0) || (o1->isRegType(kX86RegTypeXmm) && (id->_opFlags[1] & kX86InstOpXmm) == 0) || (o1->isRegType(kX86RegTypeGpd) && (id->_opFlags[1] & kX86InstOpGd ) == 0) || (o1->isRegType(kX86RegTypeGpq) && (id->_opFlags[1] & kX86InstOpGq ) == 0) || (o1->isMem() && (id->_opFlags[1] & kX86InstOpMem) == 0) || !o2->isImm()) { goto _IllegalInstruction; } uint32_t prefix = ((id->_opFlags[0] & kX86InstOpMmXmm) == kX86InstOpMmXmm && o0->isRegType(kX86RegTypeXmm)) || ((id->_opFlags[1] & kX86InstOpMmXmm) == kX86InstOpMmXmm && o1->isRegType(kX86RegTypeXmm)) ? 0x66000000 : 0x00000000; uint8_t rexw = ((id->_opFlags[0]|id->_opFlags[1]) & kX86InstOpNoRex) ? 0 : o0->isRegType(kX86RegTypeGpq) | o1->isRegType(kX86RegTypeGpq); // (X)MM <- (X)MM (opcode0) if (o1->isReg()) { if ((id->_opFlags[1] & (kX86InstOpMmXmm | kX86InstOpGqd)) == 0) goto _IllegalInstruction; _emitMmu(id->_opCode[0] | prefix, rexw, reinterpret_cast(*o0).getRegCode(), reinterpret_cast(*o1), 1); _FINISHED_IMMEDIATE(o2, 1); } // (X)MM <- Mem (opcode0) if (o1->isMem()) { if ((id->_opFlags[1] & kX86InstOpMem) == 0) goto _IllegalInstruction; _emitMmu(id->_opCode[0] | prefix, rexw, reinterpret_cast(*o0).getRegCode(), reinterpret_cast(*o1), 1); _FINISHED_IMMEDIATE(o2, 1); } break; } case kX86InstGroupMmuRm3dNow: { if (o0->isRegType(kX86RegTypeMm) && (o1->isRegType(kX86RegTypeMm) || o1->isMem())) { _emitMmu(id->_opCode[0], 0, reinterpret_cast(*o0).getRegCode(), reinterpret_cast(*o1), 1); _emitByte((uint8_t)id->_opCode[1]); _FINISHED(); } break; } } _IllegalInstruction: // Set an error. If we run in release mode assertion will be not used, so we // must inform about invalid state. setError(kErrorIllegalInstruction); #if defined(ASMJIT_DEBUG) assertIllegal = true; #endif // ASMJIT_DEBUG goto _End; _EmitImmediate: { sysint_t value = immOperand->getValue(); switch (immSize) { case 1: _emitByte ((uint8_t )(sysuint_t)value); break; case 2: _emitWord ((uint16_t)(sysuint_t)value); break; case 4: _emitDWord((uint32_t)(sysuint_t)value); break; #if defined(ASMJIT_X64) case 8: _emitQWord((uint64_t)(sysuint_t)value); break; #endif // ASMJIT_X64 default: ASMJIT_ASSERT(0); } } _End: if (_logger #if defined(ASMJIT_DEBUG) || assertIllegal #endif // ASMJIT_DEBUG ) { char bufStorage[512]; char* buf = bufStorage; // Detect truncated operand. Imm immTemporary(0); uint32_t loggerFlags = 0; // Use the original operands, because BYTE some of them were replaced. if (bLoHiUsed) { o0 = _loggerOperands[0]; o1 = _loggerOperands[1]; o2 = _loggerOperands[2]; } if (immOperand) { sysint_t value = immOperand->getValue(); bool isUnsigned = immOperand->isUnsigned(); switch (immSize) { case 1: if ( isUnsigned && !IntUtil::isUInt8 (value)) { immTemporary.setValue((uint8_t)(sysuint_t)value, true ); break; } if (!isUnsigned && !IntUtil::isInt8 (value)) { immTemporary.setValue((uint8_t)(sysuint_t)value, false); break; } break; case 2: if ( isUnsigned && !IntUtil::isUInt16(value)) { immTemporary.setValue((uint16_t)(sysuint_t)value, true ); break; } if (!isUnsigned && !IntUtil::isInt16 (value)) { immTemporary.setValue((uint16_t)(sysuint_t)value, false); break; } break; case 4: if ( isUnsigned && !IntUtil::isUInt32(value)) { immTemporary.setValue((uint32_t)(sysuint_t)value, true ); break; } if (!isUnsigned && !IntUtil::isInt32 (value)) { immTemporary.setValue((uint32_t)(sysuint_t)value, false); break; } break; } if (immTemporary.getValue() != 0) { if (o0 == immOperand) o0 = &immTemporary; if (o1 == immOperand) o1 = &immTemporary; if (o2 == immOperand) o2 = &immTemporary; } } if (_logger) { buf = StringUtil::copy(buf, _logger->getInstructionPrefix()); loggerFlags = _logger->getFlags(); } buf = X86Assembler_dumpInstruction(buf, code, _emitOptions, o0, o1, o2, memRegType, loggerFlags); if ((loggerFlags & kLoggerOutputBinary) != 0) buf = X86Assembler_dumpComment(buf, (size_t)(buf - bufStorage), getCode() + beginOffset, getOffset() - beginOffset, _inlineComment); else buf = X86Assembler_dumpComment(buf, (size_t)(buf - bufStorage), NULL, 0, _inlineComment); // We don't need to NULL terminate the resulting string. #if defined(ASMJIT_DEBUG) if (_logger) #endif // ASMJIT_DEBUG _logger->logString(bufStorage, (size_t)(buf - bufStorage)); #if defined(ASMJIT_DEBUG) if (assertIllegal) { // Here we need to NULL terminate. buf[0] = '\0'; // Raise an assertion failure, because this situation shouldn't happen. assertionFailure(__FILE__, __LINE__, bufStorage); } #endif // ASMJIT_DEBUG } _Cleanup: _inlineComment = NULL; _emitOptions = 0; } void X86Assembler::_emitJcc(uint32_t code, const Label* label, uint32_t hint) { if (hint == kCondHintNone) { _emitInstruction(code, label); } else { Imm imm(hint); _emitInstruction(code, label, &imm); } } // ============================================================================ // [AsmJit::Assembler - Relocation helpers] // ============================================================================ size_t X86Assembler::relocCode(void* _dst, sysuint_t addressBase) const { // Copy code to virtual memory (this is a given _dst pointer). uint8_t* dst = reinterpret_cast(_dst); size_t coff = _buffer.getOffset(); size_t csize = getCodeSize(); // We are copying the exact size of the generated code. Extra code for trampolines // is generated on-the-fly by relocator (this code doesn't exist at the moment). memcpy(dst, _buffer.getData(), coff); #if defined(ASMJIT_X64) // Trampoline pointer. uint8_t* tramp = dst + coff; #endif // ASMJIT_X64 // Relocate all recorded locations. size_t i; size_t len = _relocData.getLength(); for (i = 0; i < len; i++) { const RelocData& r = _relocData[i]; sysint_t val; #if defined(ASMJIT_X64) // Whether to use trampoline, can be only used if relocation type is // kRelocAbsToRel. bool useTrampoline = false; #endif // ASMJIT_X64 // Be sure that reloc data structure is correct. ASMJIT_ASSERT((size_t)(r.offset + r.size) <= csize); switch (r.type) { case kRelocAbsToAbs: val = (sysint_t)(r.address); break; case kRelocRelToAbs: val = (sysint_t)(addressBase + r.destination); break; case kRelocAbsToRel: case kRelocTrampoline: val = (sysint_t)( (sysuint_t)r.address - (addressBase + (sysuint_t)r.offset + 4) ); #if defined(ASMJIT_X64) if (r.type == kRelocTrampoline && !IntUtil::isInt32(val)) { val = (sysint_t)( (sysuint_t)tramp - ((sysuint_t)_dst + (sysuint_t)r.offset + 4) ); useTrampoline = true; } #endif // ASMJIT_X64 break; default: ASMJIT_ASSERT(0); } switch (r.size) { case 4: *reinterpret_cast(dst + r.offset) = static_cast(val); break; case 8: *reinterpret_cast(dst + r.offset) = static_cast(val); break; default: ASMJIT_ASSERT(0); } #if defined(ASMJIT_X64) if (useTrampoline) { if (getLogger()) { getLogger()->logFormat("; Trampoline from %p -> %p\n", (int8_t*)addressBase + r.offset, r.address); } X64TrampolineWriter::writeTrampoline(tramp, (uint64_t)r.address); tramp += X64TrampolineWriter::kSizeTotal; } #endif // ASMJIT_X64 } #if defined(ASMJIT_X64) return (size_t)(tramp - dst); #else return (size_t)(coff); #endif // ASMJIT_X64 } // ============================================================================ // [AsmJit::Assembler - EmbedLabel] // ============================================================================ void X86Assembler::embedLabel(const Label& label) { ASMJIT_ASSERT(label.getId() != kInvalidValue); if (!canEmit()) return; LabelData& l_data = _labels[label.getId() & kOperandIdValueMask]; RelocData r_data; if (_logger) { _logger->logFormat(sizeof(sysint_t) == 4 ? ".dd L.%u\n" : ".dq L.%u\n", (uint32_t)label.getId() & kOperandIdValueMask); } r_data.type = kRelocRelToAbs; r_data.size = sizeof(sysint_t); r_data.offset = getOffset(); r_data.destination = 0; if (l_data.offset != -1) { // Bound label. r_data.destination = l_data.offset; } else { // Non-bound label. Need to chain. LabelLink* link = _newLabelLink(); link->prev = (LabelLink*)l_data.links; link->offset = getOffset(); link->displacement = 0; link->relocId = _relocData.getLength(); l_data.links = link; } _relocData.append(r_data); // Emit dummy intptr_t (4 or 8 bytes that depends on address size). _emitIntPtrT(0); } // ============================================================================ // [AsmJit::Assembler - Align] // ============================================================================ void X86Assembler::align(uint32_t m) { if (!canEmit()) return; if (_logger) _logger->logFormat("%s.align %u\n", _logger->getInstructionPrefix(), (uint)m); if (!m) return; if (m > 64) { ASMJIT_ASSERT(0); return; } sysint_t i = m - (getOffset() % m); if (i == m) return; if (_properties & (1 << kX86PropertyOptimizedAlign)) { const X86CpuInfo* ci = X86CpuInfo::getGlobal(); // NOPs optimized for Intel: // Intel 64 and IA-32 Architectures Software Developer's Manual // - Volume 2B // - Instruction Set Reference N-Z // - NOP // NOPs optimized for AMD: // Software Optimization Guide for AMD Family 10h Processors (Quad-Core) // - 4.13 - Code Padding with Operand-Size Override and Multibyte NOP // Intel and AMD. static const uint8_t nop1[] = { 0x90 }; static const uint8_t nop2[] = { 0x66, 0x90 }; static const uint8_t nop3[] = { 0x0F, 0x1F, 0x00 }; static const uint8_t nop4[] = { 0x0F, 0x1F, 0x40, 0x00 }; static const uint8_t nop5[] = { 0x0F, 0x1F, 0x44, 0x00, 0x00 }; static const uint8_t nop6[] = { 0x66, 0x0F, 0x1F, 0x44, 0x00, 0x00 }; static const uint8_t nop7[] = { 0x0F, 0x1F, 0x80, 0x00, 0x00, 0x00, 0x00 }; static const uint8_t nop8[] = { 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00 }; static const uint8_t nop9[] = { 0x66, 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00 }; // AMD. static const uint8_t nop10[] = { 0x66, 0x66, 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00 }; static const uint8_t nop11[] = { 0x66, 0x66, 0x66, 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00 }; const uint8_t* p; sysint_t n; if (ci->getVendorId() == kCpuIntel && ((ci->getFamily() & 0x0F) == 6 || (ci->getFamily() & 0x0F) == 15)) { do { switch (i) { case 1: p = nop1; n = 1; break; case 2: p = nop2; n = 2; break; case 3: p = nop3; n = 3; break; case 4: p = nop4; n = 4; break; case 5: p = nop5; n = 5; break; case 6: p = nop6; n = 6; break; case 7: p = nop7; n = 7; break; case 8: p = nop8; n = 8; break; default: p = nop9; n = 9; break; } i -= n; do { _emitByte(*p++); } while(--n); } while (i); return; } if (ci->getVendorId() == kCpuAmd && ci->getFamily() >= 0x0F) { do { switch (i) { case 1: p = nop1 ; n = 1; break; case 2: p = nop2 ; n = 2; break; case 3: p = nop3 ; n = 3; break; case 4: p = nop4 ; n = 4; break; case 5: p = nop5 ; n = 5; break; case 6: p = nop6 ; n = 6; break; case 7: p = nop7 ; n = 7; break; case 8: p = nop8 ; n = 8; break; case 9: p = nop9 ; n = 9; break; case 10: p = nop10; n = 10; break; default: p = nop11; n = 11; break; } i -= n; do { _emitByte(*p++); } while(--n); } while (i); return; } #if defined(ASMJIT_X86) // Legacy NOPs, 0x90 with 0x66 prefix. do { switch (i) { default: _emitByte(0x66); i--; case 3: _emitByte(0x66); i--; case 2: _emitByte(0x66); i--; case 1: _emitByte(0x90); i--; } } while(i); #endif } // Legacy NOPs, only 0x90. In 64-bit mode, we can't use 0x66 prefix. do { _emitByte(0x90); } while(--i); } // ============================================================================ // [AsmJit::Assembler - Label] // ============================================================================ Label X86Assembler::newLabel() { Label label; label._base.id = (uint32_t)_labels.getLength() | kOperandIdTypeLabel; LabelData l_data; l_data.offset = -1; l_data.links = NULL; _labels.append(l_data); return label; } void X86Assembler::registerLabels(size_t count) { // Duplicated newLabel() code, but we are not creating Label instances. LabelData l_data; l_data.offset = -1; l_data.links = NULL; for (size_t i = 0; i < count; i++) _labels.append(l_data); } void X86Assembler::bind(const Label& label) { // Only labels created by newLabel() can be used by Assembler. ASMJIT_ASSERT(label.getId() != kInvalidValue); // Never go out of bounds. ASMJIT_ASSERT((label.getId() & kOperandIdValueMask) < _labels.getLength()); // Get label data based on label id. LabelData& l_data = _labels[label.getId() & kOperandIdValueMask]; // Label can be bound only once. ASMJIT_ASSERT(l_data.offset == -1); // Log. if (_logger) _logger->logFormat("L.%u:\n", (uint32_t)label.getId() & kOperandIdValueMask); sysint_t pos = getOffset(); LabelLink* link = l_data.links; LabelLink* prev = NULL; while (link) { sysint_t offset = link->offset; if (link->relocId != -1) { // If linked label points to RelocData then instead of writing relative // displacement to assembler stream, we will write it to RelocData. _relocData[link->relocId].destination += pos; } else { // Not using relocId, this means that we overwriting real displacement // in assembler stream. int32_t patchedValue = (int32_t)(pos - offset + link->displacement); uint32_t size = getByteAt(offset); // Only these size specifiers are allowed. ASMJIT_ASSERT(size == 1 || size == 4); if (size == 4) { setInt32At(offset, patchedValue); } else // if (size == 1) { if (IntUtil::isInt8(patchedValue)) { setByteAt(offset, (uint8_t)(int8_t)patchedValue); } else { // Fatal error. setError(kErrorIllegalShortJump); } } } prev = link->prev; link = prev; } // Chain unused links. link = l_data.links; if (link) { if (prev == NULL) prev = link; prev->prev = _unusedLinks; _unusedLinks = link; } // Unlink label if it was linked. l_data.offset = pos; l_data.links = NULL; } // ============================================================================ // [AsmJit::Assembler - Make] // ============================================================================ void* X86Assembler::make() { // Do nothing on error state or when no instruction was emitted. if (_error || getCodeSize() == 0) return NULL; void* p; _error = _context->generate(&p, this); return p; } } // AsmJit namespace // [Api-End] #include "../core/apiend.h" desmume/src/utils/AsmJit/x86/x86cpuinfo.h000664 001750 001750 00000007677 12755534123 021316 0ustar00sergiosergio000000 000000 // [AsmJit] // Complete JIT Assembler for C++ Language. // // [License] // Zlib - See COPYING file in this package. // [Guard] #ifndef _ASMJIT_X86_X86CPUINFO_H #define _ASMJIT_X86_X86CPUINFO_H // [Dependencies - AsmJit] #include "../core/cpuinfo.h" #include "../core/defs.h" // [Api-Begin] #include "../core/apibegin.h" namespace AsmJit { //! @addtogroup AsmJit_X86 //! @{ // ============================================================================ // [AsmJit::X86CpuId] // ============================================================================ //! @brief X86 CpuId output. union X86CpuId { //! @brief EAX/EBX/ECX/EDX output. uint32_t i[4]; struct { //! @brief EAX output. uint32_t eax; //! @brief EBX output. uint32_t ebx; //! @brief ECX output. uint32_t ecx; //! @brief EDX output. uint32_t edx; }; }; // ============================================================================ // [AsmJit::X86CpuInfo] // ============================================================================ struct X86CpuInfo : public CpuInfo { // -------------------------------------------------------------------------- // [Construction / Destruction] // -------------------------------------------------------------------------- inline X86CpuInfo(uint32_t size = sizeof(X86CpuInfo)) : CpuInfo(size) { } // -------------------------------------------------------------------------- // [Accessors] // -------------------------------------------------------------------------- //! @brief Get processor type. inline uint32_t getProcessorType() const { return _processorType; } //! @brief Get brand index. inline uint32_t getBrandIndex() const { return _brandIndex; } //! @brief Get flush cache line size. inline uint32_t getFlushCacheLineSize() const { return _flushCacheLineSize; } //! @brief Get maximum logical processors count. inline uint32_t getMaxLogicalProcessors() const { return _maxLogicalProcessors; } //! @brief Get APIC physical ID. inline uint32_t getApicPhysicalId() const { return _apicPhysicalId; } // -------------------------------------------------------------------------- // [Statics] // -------------------------------------------------------------------------- //! @brief Get global instance of @ref X86CpuInfo. static inline const X86CpuInfo* getGlobal() { return static_cast(CpuInfo::getGlobal()); } // -------------------------------------------------------------------------- // [Members] // -------------------------------------------------------------------------- //! @brief Processor type. uint32_t _processorType; //! @brief Brand index. uint32_t _brandIndex; //! @brief Flush cache line size in bytes. uint32_t _flushCacheLineSize; //! @brief Maximum number of addressable IDs for logical processors. uint32_t _maxLogicalProcessors; //! @brief Initial APIC ID. uint32_t _apicPhysicalId; }; // ============================================================================ // [AsmJit::x86CpuId] // ============================================================================ #if defined(ASMJIT_X86) || defined(ASMJIT_X64) //! @brief Calls CPUID instruction with eax == @a in and stores output to @a out. //! //! @c cpuid() function has one input parameter that is passed to cpuid through //! eax register and results in four output values representing result of cpuid //! instruction (eax, ebx, ecx and edx registers). ASMJIT_API void x86CpuId(uint32_t in, X86CpuId* out); // ============================================================================ // [AsmJit::x86CpuDetect] // ============================================================================ //! @brief Detect CPU features to CpuInfo structure @a out. //! //! @sa @c CpuInfo. ASMJIT_API void x86CpuDetect(X86CpuInfo* out); #endif // ASMJIT_X86 || ASMJIT_X64 //! @} } // AsmJit namespace // [Api-End] #include "../core/apiend.h" // [Guard] #endif // _ASMJIT_X86_X86CPUINFO_H desmume/src/utils/libfat/mem_allocate.h000664 001750 001750 00000003631 12755534123 021336 0ustar00sergiosergio000000 000000 /* mem_allocate.h Memory allocation and destruction calls Replace these calls with custom allocators if malloc is unavailable Copyright (c) 2006 Michael "Chishm" Chisholm Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. 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. 3. The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. */ #ifndef _MEM_ALLOCATE_H #define _MEM_ALLOCATE_H #include #include static INLINE void* _FAT_mem_allocate (size_t size) { return malloc (size); } static INLINE void* _FAT_mem_align (size_t size) { #ifdef __wii__ return memalign (32, size); #else return malloc (size); #endif } static inline void _FAT_mem_free (void* mem) { free (mem); } #endif // _MEM_ALLOCATE_H desmume/src/libretro-common/formats/image_transfer.c000664 001750 001750 00000013772 12755534123 024066 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2016 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (image_transfer.c). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include #include #include #ifdef HAVE_RPNG #include #endif #ifdef HAVE_RJPEG #include #endif #ifdef HAVE_RTGA #include #endif #ifdef HAVE_RBMP #include #endif #include void image_transfer_free(void *data, enum image_type_enum type) { switch (type) { case IMAGE_TYPE_TGA: #ifdef HAVE_RTGA rtga_free((rtga_t*)data); #endif break; case IMAGE_TYPE_PNG: #ifdef HAVE_RPNG rpng_free((rpng_t*)data); #endif break; case IMAGE_TYPE_JPEG: #ifdef HAVE_RJPEG rjpeg_free((rjpeg_t*)data); #endif break; case IMAGE_TYPE_BMP: #ifdef HAVE_RBMP rbmp_free((rbmp_t*)data); #endif break; case IMAGE_TYPE_NONE: break; } } void *image_transfer_new(enum image_type_enum type) { switch (type) { case IMAGE_TYPE_PNG: #ifdef HAVE_RPNG return rpng_alloc(); #else break; #endif case IMAGE_TYPE_JPEG: #ifdef HAVE_RJPEG return rjpeg_alloc(); #else break; #endif case IMAGE_TYPE_TGA: #ifdef HAVE_RTGA return rtga_alloc(); #else break; #endif case IMAGE_TYPE_BMP: #ifdef HAVE_RBMP return rbmp_alloc(); #else break; #endif default: break; } return NULL; } bool image_transfer_start(void *data, enum image_type_enum type) { switch (type) { case IMAGE_TYPE_PNG: #ifdef HAVE_RPNG if (!rpng_start((rpng_t*)data)) break; return true; #else break; #endif case IMAGE_TYPE_JPEG: #ifdef HAVE_RJPEG return true; #else break; #endif case IMAGE_TYPE_TGA: #ifdef HAVE_RTGA return true; #else break; #endif case IMAGE_TYPE_BMP: return true; case IMAGE_TYPE_NONE: break; } return false; } bool image_transfer_is_valid( void *data, enum image_type_enum type) { switch (type) { case IMAGE_TYPE_PNG: #ifdef HAVE_RPNG return rpng_is_valid((rpng_t*)data); #else break; #endif case IMAGE_TYPE_JPEG: #ifdef HAVE_RJPEG return true; #else break; #endif case IMAGE_TYPE_TGA: #ifdef HAVE_RTGA return true; #else break; #endif case IMAGE_TYPE_BMP: return true; case IMAGE_TYPE_NONE: break; } return false; } void image_transfer_set_buffer_ptr( void *data, enum image_type_enum type, void *ptr) { switch (type) { case IMAGE_TYPE_PNG: #ifdef HAVE_RPNG rpng_set_buf_ptr((rpng_t*)data, (uint8_t*)ptr); #endif break; case IMAGE_TYPE_JPEG: #ifdef HAVE_RJPEG rjpeg_set_buf_ptr((rjpeg_t*)data, (uint8_t*)ptr); #endif break; case IMAGE_TYPE_TGA: #ifdef HAVE_RTGA rtga_set_buf_ptr((rtga_t*)data, (uint8_t*)ptr); #endif break; case IMAGE_TYPE_BMP: #ifdef HAVE_RBMP rbmp_set_buf_ptr((rbmp_t*)data, (uint8_t*)ptr); #endif break; case IMAGE_TYPE_NONE: break; } } int image_transfer_process( void *data, enum image_type_enum type, uint32_t **buf, size_t len, unsigned *width, unsigned *height) { switch (type) { case IMAGE_TYPE_PNG: #ifdef HAVE_RPNG if (!rpng_is_valid((rpng_t*)data)) return IMAGE_PROCESS_ERROR; return rpng_process_image( (rpng_t*)data, (void**)buf, len, width, height); #else break; #endif case IMAGE_TYPE_JPEG: #ifdef HAVE_RJPEG return rjpeg_process_image((rjpeg_t*)data, (void**)buf, len, width, height); #else break; #endif case IMAGE_TYPE_TGA: #ifdef HAVE_RTGA return rtga_process_image((rtga_t*)data, (void**)buf, len, width, height); #else break; #endif case IMAGE_TYPE_BMP: #ifdef HAVE_RBMP return rbmp_process_image((rbmp_t*)data, (void**)buf, len, width, height); #else break; #endif case IMAGE_TYPE_NONE: break; } return 0; } bool image_transfer_iterate(void *data, enum image_type_enum type) { switch (type) { case IMAGE_TYPE_PNG: #ifdef HAVE_RPNG if (!rpng_iterate_image((rpng_t*)data)) return false; #endif break; case IMAGE_TYPE_JPEG: #ifdef HAVE_RJPEG return false; #else break; #endif case IMAGE_TYPE_TGA: #ifdef HAVE_RTGA return false; #else break; #endif case IMAGE_TYPE_BMP: return false; case IMAGE_TYPE_NONE: return false; } return true; } desmume/src/libretro-common/formats/xml/test/rxml_test.c000664 001750 001750 00000004614 12755534123 024673 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2016 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (rxml_test.c). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include #include static void print_siblings(struct rxml_node *node, unsigned level) { fprintf(stderr, "\n%*sName: %s\n", level * 4, "", node->name); if (node->data) fprintf(stderr, "%*sData: %s\n", level * 4, "", node->data); for (const struct rxml_attrib_node *attrib = node->attrib; attrib; attrib = attrib->next) fprintf(stderr, "%*s Attrib: %s = %s\n", level * 4, "", attrib->attrib, attrib->value); if (node->children) print_siblings(node->children, level + 1); if (node->next) print_siblings(node->next, level); } static void rxml_log_document(const char *path) { rxml_document_t *doc = rxml_load_document(path); if (!doc) { fprintf(stderr, "rxml: Failed to load document: %s\n", path); return; } print_siblings(rxml_root_node(doc), 0); rxml_free_document(doc); } int main(int argc, char *argv[]) { if (argc != 2) { fprintf(stderr, "Usage: %s \n", argv[0]); return 1; } rxml_log_document(argv[1]); } desmume/src/libretro-common/rthreads/xenon_sdl_threads.c000664 001750 001750 00000004064 12755534123 024736 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2016 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (xenon_sdl_threads.c). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ // libSDLxenon doesn't implement this yet :[. Implement it very stupidly for now. ;) #include "SDL_thread.h" #include "SDL_mutex.h" #include #include SDL_cond *SDL_CreateCond(void) { bool *sleeping = calloc(1, sizeof(*sleeping)); return (SDL_cond*)sleeping; } void SDL_DestroyCond(SDL_cond *sleeping) { free(sleeping); } int SDL_CondWait(SDL_cond *cond, SDL_mutex *lock) { (void)lock; volatile bool *sleeping = (volatile bool*)cond; SDL_mutexV(lock); *sleeping = true; while (*sleeping); /* Yeah, we all love busyloops don't we? ._. */ SDL_mutexP(lock); return 0; } int SDL_CondSignal(SDL_cond *cond) { *(volatile bool*)cond = false; return 0; } desmume/Makefile.libretro000664 001750 001750 00000015242 12755534123 016635 0ustar00sergiosergio000000 000000 DEBUG=0 X432R_CUSTOMRENDERER_ENABLED=0 ifeq ($(platform),) platform = unix ifeq ($(shell uname -a),) platform = win else ifneq ($(findstring MINGW,$(shell uname -a)),) platform = win else ifneq ($(findstring Darwin,$(shell uname -a)),) platform = osx else ifneq ($(findstring win,$(shell uname -a)),) platform = win endif endif TARGET_NAME := desmume CORE_DIR := src # Unix ifeq ($(platform), unix) TARGET := $(TARGET_NAME)_libretro.so fpic := -fPIC SHARED := -shared -Wl,--no-undefined -Wl,--version-script=$(CORE_DIR)/libretro/link.T LIBS := -lpthread DESMUME_JIT = 1 # OS X else ifeq ($(platform), osx) TARGET := $(TARGET_NAME)_libretro.dylib fpic := -fPIC SHARED := -dynamiclib DESMUME_JIT = 1 fpic += -mmacosx-version-min=10.2 ifndef ($(NOUNIVERSAL)) CFLAGS += $(ARCHFLAGS) CXXFLAGS += $(ARCHFLAGS) LDFLAGS += $(ARCHFLAGS) endif # iOS else ifneq (,$(findstring ios,$(platform))) TARGET := $(TARGET_NAME)_libretro_ios.dylib ifeq ($(IOSSDK),) IOSSDK := $(shell xcodebuild -version -sdk iphoneos Path) endif CC = clang -arch armv7 -isysroot $(IOSSDK) CXX = clang++ -arch armv7 -isysroot $(IOSSDK) CXXFLAGS = -DUSE_POSIX_MEMALIGN -D__RETRO_ARM__ fpic := -fPIC SHARED := -dynamiclib DESMUME_JIT_ARM = 1 ifeq ($(platform),ios9) CC += -miphoneos-version-min=8.0 CXX += -miphoneos-version-min=8.0 CFLAGS += -miphoneos-version-min=8.0 CXXFLAGS += -miphoneos-version-min=8.0 else CC += -miphoneos-version-min=5.0 CXX += -miphoneos-version-min=5.0 CFLAGS += -miphoneos-version-min=5.0 CXXFLAGS += -miphoneos-version-min=5.0 endif # Theos iOS else ifeq ($(platform), theos_ios) DEPLOYMENT_IOSVERSION = 5.0 TARGET = iphone:latest:$(DEPLOYMENT_IOSVERSION) ARCHS = armv7 armv7s TARGET_IPHONEOS_DEPLOYMENT_VERSION=$(DEPLOYMENT_IOSVERSION) THEOS_BUILD_DIR := objs include $(THEOS)/makefiles/common.mk LIBRARY_NAME = $(TARGET_NAME)_libretro_ios DESMUME_JIT_ARM = 1 COMMON_DEFINES = -DUSE_POSIX_MEMALIGN -D__RETRO_ARM__ # QNX else ifneq (,$(findstring qnx,$(platform))) TARGET := $(TARGET_NAME)_libretro_qnx.so fpic := -fPIC SHARED := -shared -Wl,--version-script=$(CORE_DIR)/libretro/link.T CC = qcc -Vgcc_ntoarmv7le CXX = QCC -Vgcc_ntoarmv7le_cpp AR = QCC -Vgcc_ntoarmv7le # PS3 else ifeq ($(platform), ps3) TARGET := $(TARGET_NAME)_libretro_ps3.a CC = $(CELL_SDK)/host-win32/ppu/bin/ppu-lv2-gcc.exe CXX = $(CELL_SDK)/host-win32/ppu/bin/ppu-lv2-g++.exe AR = $(CELL_SDK)/host-win32/ppu/bin/ppu-lv2-ar.exe CXXFLAGS += -D__ppc__ -D__CELLOS_LV2__ STATIC_LINKING = 1 # sncps3 else ifeq ($(platform), sncps3) TARGET := $(TARGET_NAME)_libretro_ps3.a CC = $(CELL_SDK)/host-win32/sn/bin/ps3ppusnc.exe CXX = $(CELL_SDK)/host-win32/sn/bin/ps3ppusnc.exe AR = $(CELL_SDK)/host-win32/sn/bin/ps3snarl.exe CXXFLAGS += -D__ppc__-D__CELLOS_LV2__ STATIC_LINKING = 1 # Lightweight PS3 Homebrew SDK else ifeq ($(platform), psl1ght) TARGET := $(TARGET_NAME)_libretro_psl1ght.a CC = $(PS3DEV)/ppu/bin/ppu-gcc$(EXE_EXT) CXX = $(PS3DEV)/ppu/bin/ppu-g++$(EXE_EXT) AR = $(PS3DEV)/ppu/bin/ppu-ar$(EXE_EXT) CXXFLAGS += -D__ppc__ -D__CELLOS_LV2__ STATIC_LINKING = 1 # PSP else ifeq ($(platform), psp1) TARGET := $(TARGET_NAME)_libretro_psp1.a CC = psp-gcc$(EXE_EXT) CXX = psp-g++$(EXE_EXT) AR = psp-ar$(EXE_EXT) CXXFLAGS += -DPSP -G0 STATIC_LINKING = 1 # Vita else ifeq ($(platform), vita) TARGET := $(TARGET_NAME)_libretro_vita.a CC = arm-vita-eabi-gcc$(EXE_EXT) CXX = arm-vita-eabi-g++$(EXE_EXT) AR = arm-vita-eabi-ar$(EXE_EXT) CXXFLAGS += -DVITA CFLAGS += -DVITA DESMUME_JIT_ARM = 1 STATIC_LINKING = 1 # Xbox 360 else ifeq ($(platform), xenon) TARGET := $(TARGET_NAME)_libretro_xenon360.a CC = xenon-gcc$(EXE_EXT) CXX = xenon-g++$(EXE_EXT) AR = xenon-ar$(EXE_EXT) CXXFLAGS += -D__LIBXENON__ -m32 -D__ppc__ STATIC_LINKING = 1 # Nintendo Wii else ifeq ($(platform), wii) TARGET := $(TARGET_NAME)_libretro_wii.a CC = $(DEVKITPPC)/bin/powerpc-eabi-gcc$(EXE_EXT) CXX = $(DEVKITPPC)/bin/powerpc-eabi-g++$(EXE_EXT) AR = $(DEVKITPPC)/bin/powerpc-eabi-ar$(EXE_EXT) CFLAGS += -DGEKKO -mrvl -mcpu=750 -meabi -mhard-float -D__ppc__ STATIC_LINKING = 1 # Android else ifeq ($(platform), android) TARGET := $(TARGET_NAME)_libretro_$(TARGET_NAME).so CC = arm-linux-androideabi-gcc$(EXE_EXT) CXX = arm-linux-androideabi-g++$(EXE_EXT) CXXFLAGS += -D__RETRO_ARM__ fpic := -fPIC SHARED := -shared -Wl,--version-script=$(CORE_DIR)/libretro/link.T DESMUME_JIT_ARM = 1 ifeq ($(RETRO_PROFILE),1) LDFLAGS += -llog endif # ARM else ifneq (,$(findstring armv,$(platform))) DESMUME_JIT_ARM = 1 CXXFLAGS += -DUSE_POSIX_MEMALIGN -D__RETRO_ARM__ TARGET := $(TARGET_NAME)_libretro.so SHARED := -shared -Wl,--no-undefined -Wl,--version-script=$(CORE_DIR)/libretro/link.T LIBS := -lpthread fpic := -fPIC ifneq (,$(findstring clang,$(platform))) CC = clang CXX = clang++ AR = clang endif ifneq (,$(findstring cortexa5,$(platform))) CXXFLAGS += -marm -mcpu=cortex-a5 else ifneq (,$(findstring cortexa8,$(platform))) CXXFLAGS += -marm -mcpu=cortex-a8 else ifneq (,$(findstring cortexa9,$(platform))) CXXFLAGS += -marm -mcpu=cortex-a9 else ifneq (,$(findstring cortexa15a7,$(platform))) CXXFLAGS += -marm -mcpu=cortex-a15.cortex-a7 else CXXFLAGS += -marm endif ifneq (,$(findstring softfloat,$(platform))) CXXFLAGS += -mfloat-abi=softfp else ifneq (,$(findstring hardfloat,$(platform))) CXXFLAGS += -mfloat-abi=hard endif CXXFLAGS += -DARM # Windows else TARGET := $(TARGET_NAME)_libretro.dll CC = gcc CXX = g++ SHARED := -shared -static-libgcc -static-libstdc++ -Wl,--version-script=$(CORE_DIR)/libretro/link.T ifeq ($(DEBUG), 0) SHARED += -s endif DESMUME_JIT = 1 HAVE_DIRENT_WIN = 1 endif ifeq ($(DESMUME_JIT_ARM),1) CXXFLAGS += -DHAVE_JIT endif ifeq ($(DESMUME_JIT),1) CXXFLAGS += -DHAVE_JIT endif include Makefile.common ifeq ($(DEBUG), 1) CXXFLAGS += -g -O0 else CXXFLAGS += -DNDEBUG -O3 endif ifeq ($(RETRO_PROFILE),1) CXXFLAGS += -DRETRO_PROFILE=1 endif ifeq ($(X432R_CUSTOMRENDERER_ENABLED),1) CXXFLAGS += -DX432R_CUSTOMRENDERER_ENABLED endif OBJECTS = $(SOURCES_CXX:.cpp=.o) $(SOURCES_C:.c=.o) CXXFLAGS += -D__LIBRETRO__ -fpermissive $(fpic) $(INCDIR) CFLAGS += -std=gnu99 -D__LIBRETRO__ $(fpic) $(INCDIR) ifeq ($(platform), theos_ios) COMMON_FLAGS := -DIOS -DARM $(COMMON_DEFINES) $(INCFLAGS) -I$(THEOS_INCLUDE_PATH) -Wno-error $(LIBRARY_NAME)_CFLAGS += $(CFLAGS) $(COMMON_FLAGS) $(LIBRARY_NAME)_CXXFLAGS += $(CXXFLAGS) $(COMMON_FLAGS) ${LIBRARY_NAME}_FILES = $(SOURCES_CXX) $(SOURCES_C) include $(THEOS_MAKE_PATH)/library.mk else all: $(TARGET) $(TARGET): $(OBJECTS) ifeq ($(STATIC_LINKING), 1) $(AR) rcs $@ $(OBJECTS) else $(CXX) $(LDFLAGS) $(fpic) $(SHARED) -o $@ $(OBJECTS) $(LIBS) endif clean: rm -f $(OBJECTS) $(TARGET) .PHONY: clean endif desmume/src/libretro-common/include/gfx/scaler/pixconv.h000664 001750 001750 00000006676 12755534123 024605 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2016 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (pixconv.h). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef __LIBRETRO_SDK_SCALER_PIXCONV_H__ #define __LIBRETRO_SDK_SCALER_PIXCONV_H__ #include void conv_0rgb1555_argb8888(void *output, const void *input, int width, int height, int out_stride, int in_stride); void conv_0rgb1555_rgb565(void *output, const void *input, int width, int height, int out_stride, int in_stride); void conv_rgb565_0rgb1555(void *output, const void *input, int width, int height, int out_stride, int in_stride); void conv_rgb565_argb8888(void *output, const void *input, int width, int height, int out_stride, int in_stride); void conv_rgba4444_argb8888(void *output, const void *input, int width, int height, int out_stride, int in_stride); void conv_rgba4444_rgb565(void *output, const void *input, int width, int height, int out_stride, int in_stride); void conv_bgr24_argb8888(void *output, const void *input, int width, int height, int out_stride, int in_stride); void conv_argb8888_0rgb1555(void *output, const void *input, int width, int height, int out_stride, int in_stride); void conv_argb8888_rgba4444(void *output_, const void *input_, int width, int height, int out_stride, int in_stride); void conv_argb8888_rgb565(void *output, const void *input, int width, int height, int out_stride, int in_stride); void conv_argb8888_bgr24(void *output, const void *input, int width, int height, int out_stride, int in_stride); void conv_argb8888_abgr8888(void *output, const void *input, int width, int height, int out_stride, int in_stride); void conv_0rgb1555_bgr24(void *output, const void *input, int width, int height, int out_stride, int in_stride); void conv_rgb565_bgr24(void *output, const void *input, int width, int height, int out_stride, int in_stride); void conv_yuyv_argb8888(void *output, const void *input, int width, int height, int out_stride, int in_stride); void conv_copy(void *output, const void *input, int width, int height, int out_stride, int in_stride); #endif desmume/src/texcache.cpp000664 001750 001750 00000054723 12755534123 016442 0ustar00sergiosergio000000 000000 /* Copyright (C) 2006 yopyop Copyright (C) 2006-2007 shash Copyright (C) 2008-2015 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the this software. If not, see . */ #include #include #include #include #include "texcache.h" #include "common.h" #include "debug.h" #include "gfx3d.h" #include "MMU.h" #include "NDSSystem.h" using std::min; using std::max; //only dump this from ogl renderer. for now, softrasterizer creates things in an incompatible pixel format //#define DEBUG_DUMP_TEXTURE #define CONVERT(color,alpha) ((TEXFORMAT == TexFormat_32bpp)?(RGB15TO32(color,alpha)):RGB15TO6665(color,alpha)) //This class represents a number of regions of memory which should be viewed as contiguous class MemSpan { public: static const int MAXSIZE = 17; //max size for textures: 1024*1024*2 bytes / 128*1024 banks + 1 for wraparound MemSpan() : numItems(0), size(0) {} int numItems; struct Item { u32 start; u32 len; u8* ptr; u32 ofs; //offset within the memspan } items[MAXSIZE]; int size; //this MemSpan shall be considered the first argument to a standard memcmp //the length shall be as specified in this MemSpan, unless you specify otherwise int memcmp(void* buf2, int size=-1) { if(size==-1) size = this->size; size = min(this->size,size); for(int i=0;isize; size = min(this->size,size); u8* bufptr = (u8*)buf; int done = 0; for(int i=0;isize; size = min(this->size,size); u16* bufptr = (u16*)buf; int done = 0; for(int i=0;i>17)&3; //slots will wrap around curr.len = min(len,0x20000-curr.start); curr.ofs = currofs; len -= curr.len; ofs += curr.len; currofs += curr.len; u8* ptr = MMU.texInfo.textureSlotAddr[slot]; //TODO - dont alert if the masterbrightnesses are max or min if(ptr == MMU.blank_memory) { PROGINFO("Tried to reference unmapped texture memory: slot %d\n",slot); } curr.ptr = ptr + curr.start; } return ret; } //creates a MemSpan in texture palette memory static MemSpan MemSpan_TexPalette(u32 ofs, u32 len, bool silent) { MemSpan ret; ret.size = len; u32 currofs = 0; while(len) { MemSpan::Item &curr = ret.items[ret.numItems++]; curr.start = ofs&0x3FFF; u32 slot = (ofs>>14)&7; //this masks to 8 slots, but there are really only 6 if(slot>5 && !silent) { PROGINFO("Texture palette overruns texture memory. Wrapping at palette slot 0.\n"); slot -= 5; } curr.len = min(len,0x4000-curr.start); curr.ofs = currofs; len -= curr.len; ofs += curr.len; //if(len != 0) //here is an actual test case of bank spanning currofs += curr.len; u8* ptr = MMU.texInfo.texPalSlot[slot]; //TODO - dont alert if the masterbrightnesses are max or min if(ptr == MMU.blank_memory && !silent) { PROGINFO("Tried to reference unmapped texture palette memory: 16k slot #%d\n",slot); } curr.ptr = ptr + curr.start; } return ret; } #if defined (DEBUG_DUMP_TEXTURE) && defined (WIN32) #define DO_DEBUG_DUMP_TEXTURE static void DebugDumpTexture(TexCacheItem* item) { static int ctr=0; char fname[100]; sprintf(fname,"c:\\dump\\%d.bmp", ctr); ctr++; NDS_WriteBMP_32bppBuffer(item->sizeX,item->sizeY,item->decoded,fname); } #endif class TexCache { public: TexCache() : cache_size(0) { memset(paletteDump,0,sizeof(paletteDump)); } TTexCacheItemMultimap index; //this ought to be enough for anyone //static const u32 kMaxCacheSize = 64*1024*1024; //changed by zeromus on 15-dec. I couldnt find any games that were getting anywhere NEAR 64 static const u32 kMaxCacheSize = 16*1024*1024; //metal slug burns through sprites so fast, it can test it pretty quickly though //this is not really precise, it is off by a constant factor u32 cache_size; void list_remove(TexCacheItem* item) { index.erase(item->iterator); cache_size -= item->decode_len; } void list_push_front(TexCacheItem* item) { item->iterator = index.insert(std::make_pair(item->texformat,item)); cache_size += item->decode_len; } template TexCacheItem* scan(u32 format, u32 texpal) { //for each texformat, number of palette entries static const int palSizes[] = {0, 32, 4, 16, 256, 0, 8, 0}; //for each texformat, multiplier from numtexels to numbytes (fixed point 30.2) static const int texSizes[] = {0, 4, 1, 2, 4, 1, 4, 8}; //used to hold a copy of the palette specified for this texture u16 pal[256]; u32 textureMode = (unsigned short)((format>>26)&0x07); u32 sizeX=(8 << ((format>>20)&0x07)); u32 sizeY=(8 << ((format>>23)&0x07)); u32 imageSize = sizeX*sizeY; u8 *adr; u32 paletteAddress; switch (textureMode) { case TEXMODE_I2: paletteAddress = texpal<<3; break; case TEXMODE_A3I5: //a3i5 case TEXMODE_I4: //i4 case TEXMODE_I8: //i8 case TEXMODE_A5I3: //a5i3 case TEXMODE_16BPP: //16bpp case TEXMODE_4X4: //4x4 default: paletteAddress = texpal<<4; break; } //analyze the texture memory mapping and the specifications of this texture int palSize = palSizes[textureMode]; int texSize = (imageSize*texSizes[textureMode])>>2; //shifted because the texSizes multiplier is fixed point MemSpan ms = MemSpan_TexMem((format&0xFFFF)<<3,texSize); MemSpan mspal = MemSpan_TexPalette(paletteAddress,palSize*2,false); //determine the location for 4x4 index data u32 indexBase; if((format & 0xc000) == 0x8000) indexBase = 0x30000; else indexBase = 0x20000; u32 indexOffset = (format&0x3FFF)<<2; int indexSize = 0; MemSpan msIndex; if(textureMode == TEXMODE_4X4) { indexSize = imageSize>>3; msIndex = MemSpan_TexMem(indexOffset+indexBase,indexSize); } //dump the palette to a temp buffer, so that we don't have to worry about memory mapping. //this isnt such a problem with texture memory, because we read sequentially from it. //however, we read randomly from palette memory, so the mapping is more costly. #ifdef MSB_FIRST mspal.dump16(pal); #else mspal.dump(pal); #endif //TODO - as a special optimization, keep the last item returned and check it first for(std::pair iters = index.equal_range(format); iters.first != iters.second; ++iters.first) { TexCacheItem* curr = iters.first->second; //conditions where we reject matches: //when the teximage or texpal params dont match //(this is our key for identifying textures in the cache) //NEW: due to using format as a key we dont need to check this anymore //if(curr->texformat != format) continue; if(curr->texpal != texpal) continue; //we're being asked for a different format than what we had cached. //TODO - this could be done at the entire cache level instead of checking repeatedly if(curr->cacheFormat != TEXFORMAT) goto REJECT; //if the texture is assumed invalid, reject it if(curr->assumedInvalid) goto REJECT; //the texture matches params, but isnt suspected invalid. accept it. if(!curr->suspectedInvalid) return curr; //we suspect the texture may be invalid. we need to do a byte-for-byte comparison to re-establish that it is valid: //when the palettes dont match: //note that we are considering 4x4 textures to have a palette size of 0. //they really have a potentially HUGE palette, too big for us to handle like a normal palette, //so they go through a different system if(mspal.size != 0 && memcmp(curr->dump.palette,pal,mspal.size)) goto REJECT; //when the texture data doesn't match if(ms.memcmp(&curr->dump.texture[0],curr->dump.textureSize)) goto REJECT; //if the texture is 4x4 then the index data must match if(textureMode == TEXMODE_4X4) { if(msIndex.memcmp(curr->dump.texture + curr->dump.textureSize,curr->dump.indexSize)) goto REJECT; } //we found a match. just return it //REMINDER to make it primary/newest when we have smarter code //list_remove(curr); //list_push_front(curr); curr->suspectedInvalid = false; return curr; REJECT: //we found a cached item for the current address, but the data is stale. //for a variety of complicated reasons, we need to throw it out right this instant. list_remove(curr); delete curr; break; } //item was not found. recruit an existing one (the oldest), or create a new one //evict(); //reduce the size of the cache if necessary //TODO - as a peculiarity of the texcache, eviction must happen after the entire 3d frame runs //to support separate cache and read passes TexCacheItem* newitem = new TexCacheItem(); newitem->suspectedInvalid = false; newitem->texformat = format; newitem->cacheFormat = TEXFORMAT; newitem->texpal = texpal; newitem->sizeX=sizeX; newitem->sizeY=sizeY; newitem->invSizeX=1.0f/((float)(sizeX)); newitem->invSizeY=1.0f/((float)(sizeY)); newitem->decode_len = sizeX*sizeY*4; newitem->mode = textureMode; newitem->decoded = new u8[newitem->decode_len]; list_push_front(newitem); //printf("allocating: up to %d with %d items\n",cache_size,index.size()); u32 *dwdst = (u32*)newitem->decoded; //dump palette data for cache keying if(palSize) memcpy(newitem->dump.palette, pal, palSize*2); //dump texture and 4x4 index data for cache keying const int texsize = newitem->dump.textureSize = ms.size; const int indexsize = newitem->dump.indexSize = msIndex.size; newitem->dump.texture = new u8[texsize+indexsize]; ms.dump(&newitem->dump.texture[0],newitem->dump.maxTextureSize); //dump texture if(textureMode == TEXMODE_4X4) msIndex.dump(newitem->dump.texture+newitem->dump.textureSize,newitem->dump.indexSize); //dump 4x4 //============================================================================ //Texture conversion //============================================================================ const u8 opaqueColor = (TEXFORMAT == TexFormat_32bpp) ? 0xFF : 0x1F; const u8 palZeroTransparent = ( 1 - ((format>>29) & 1) ) * opaqueColor; switch (newitem->mode) { case TEXMODE_A3I5: { int j; for(j=0;j>5; if(TEXFORMAT == TexFormat_15bpp) *dwdst++ = RGB15TO6665(c,material_3bit_to_5bit[alpha]); else *dwdst++ = RGB15TO32(c,material_3bit_to_8bit[alpha]); adr++; } } break; } case TEXMODE_I2: { int j; for(j=0;j>2)&0x3; c = pal[bits]; *dwdst++ = CONVERT(c,(bits == 0) ? palZeroTransparent : opaqueColor); bits = ((*adr)>>4)&0x3; c = pal[bits]; *dwdst++ = CONVERT(c,(bits == 0) ? palZeroTransparent : opaqueColor); bits = ((*adr)>>6)&0x3; c = pal[bits]; *dwdst++ = CONVERT(c,(bits == 0) ? palZeroTransparent : opaqueColor); adr++; } } break; } case TEXMODE_I4: { for(int j=0;j>4); c = pal[bits]; *dwdst++ = CONVERT(c,(bits == 0) ? palZeroTransparent : opaqueColor); adr++; } } break; } case TEXMODE_I8: { for(int j=0;j>14)&0x7] + ((paletteAddress + (offset)*2)&0x3FFF) ) ) u16* slot1; u32* map = (u32*)ms.items[0].ptr; u32 limit = ms.items[0].len<<2; u32 d = 0; if ( (format & 0xc000) == 0x8000) // texel are in slot 2 slot1=(u16*)&MMU.texInfo.textureSlotAddr[1][((format & 0x3FFF)<<2)+0x010000]; else slot1=(u16*)&MMU.texInfo.textureSlotAddr[1][(format & 0x3FFF)<<2]; u16 yTmpSize = (sizeY>>2); u16 xTmpSize = (sizeX>>2); //this is flagged whenever a 4x4 overruns its slot. //i am guessing we just generate black in that case bool dead = false; for (int y = 0; y < yTmpSize; y ++) { u32 tmpPos[4]={(y<<2)*sizeX,((y<<2)+1)*sizeX, ((y<<2)+2)*sizeX,((y<<2)+3)*sizeX}; for (int x = 0; x < xTmpSize; x ++, d++) { if(d >= limit) dead = true; if(dead) { for (int sy = 0; sy < 4; sy++) { u32 currentPos = (x<<2) + tmpPos[sy]; dwdst[currentPos] = dwdst[currentPos+1] = dwdst[currentPos+2] = dwdst[currentPos+3] = 0; } continue; } u32 currBlock = map[d]; u16 pal1 = slot1[d]; u16 pal1offset = (pal1 & 0x3FFF)<<1; u8 mode = pal1>>14; u32 tmp_col[4]; tmp_col[0] = RGB15TO32( PAL4X4(pal1offset), 0xFF ); tmp_col[1] = RGB15TO32( PAL4X4(pal1offset+1), 0xFF ); switch (mode) { case 0: tmp_col[2] = RGB15TO32( PAL4X4(pal1offset+2), 0xFF ); tmp_col[3] = RGB15TO32(0x7FFF, 0x00); break; case 1: #ifdef MSB_FIRST tmp_col[2] = ( (((tmp_col[0] & 0xFF000000) >> 1)+((tmp_col[1] & 0xFF000000) >> 1)) & 0xFF000000 ) | ( (((tmp_col[0] & 0x00FF0000) + (tmp_col[1] & 0x00FF0000)) >> 1) & 0x00FF0000 ) | ( (((tmp_col[0] & 0x0000FF00) + (tmp_col[1] & 0x0000FF00)) >> 1) & 0x0000FF00 ) | 0x000000FF; tmp_col[3] = 0xFFFFFF00; #else tmp_col[2] = ( (((tmp_col[0] & 0x00FF00FF) + (tmp_col[1] & 0x00FF00FF)) >> 1) & 0x00FF00FF ) | ( (((tmp_col[0] & 0x0000FF00) + (tmp_col[1] & 0x0000FF00)) >> 1) & 0x0000FF00 ) | 0xFF000000; tmp_col[3] = 0x00FFFFFF; #endif break; case 2: tmp_col[2] = RGB15TO32( PAL4X4(pal1offset+2), 0xFF ); tmp_col[3] = RGB15TO32( PAL4X4(pal1offset+3), 0xFF ); break; case 3: { #ifdef MSB_FIRST const u32 r0 = (tmp_col[0]>>24) & 0x000000FF; const u32 r1 = (tmp_col[1]>>24) & 0x000000FF; const u32 g0 = (tmp_col[0]>>16) & 0x000000FF; const u32 g1 = (tmp_col[1]>>16) & 0x000000FF; const u32 b0 = (tmp_col[0]>> 8) & 0x000000FF; const u32 b1 = (tmp_col[1]>> 8) & 0x000000FF; #else const u32 r0 = tmp_col[0] & 0x000000FF; const u32 r1 = tmp_col[1] & 0x000000FF; const u32 g0 = (tmp_col[0]>> 8) & 0x000000FF; const u32 g1 = (tmp_col[1]>> 8) & 0x000000FF; const u32 b0 = (tmp_col[0]>>16) & 0x000000FF; const u32 b1 = (tmp_col[1]>>16) & 0x000000FF; #endif const u16 tmp1 = ( (r0*5 + r1*3)>>6) | ( ((g0*5 + g1*3)>>6) << 5 ) | ( ((b0*5 + b1*3)>>6) << 10 ); const u16 tmp2 = ( (r0*3 + r1*5)>>6) | ( ((g0*3 + g1*5)>>6) << 5 ) | ( ((b0*3 + b1*5)>>6) << 10 ); tmp_col[2] = RGB15TO32(tmp1, 0xFF); tmp_col[3] = RGB15TO32(tmp2, 0xFF); break; } } if(TEXFORMAT==TexFormat_15bpp) { size_t i; for(i = 0; i < 4; i++) { #ifdef MSB_FIRST const u32 a = (tmp_col[i] >> 3) & 0x0000001F; tmp_col[i] >>= 2; tmp_col[i] &= 0x3F3F3F00; tmp_col[i] |= a; #else const u32 a = (tmp_col[i] >> 3) & 0x1F000000; tmp_col[i] >>= 2; tmp_col[i] &= 0x003F3F3F; tmp_col[i] |= a; #endif } } //TODO - this could be more precise for 32bpp mode (run it through the color separation table) //set all 16 texels for (size_t sy = 0; sy < 4; sy++) { // Texture offset u32 currentPos = (x<<2) + tmpPos[sy]; u8 currRow = (u8)((currBlock>>(sy<<3))&0xFF); dwdst[currentPos] = tmp_col[currRow&3]; dwdst[currentPos+1] = tmp_col[(currRow>>2)&3]; dwdst[currentPos+2] = tmp_col[(currRow>>4)&3]; dwdst[currentPos+3] = tmp_col[(currRow>>6)&3]; } } } break; } case TEXMODE_A5I3: { for(int j=0;j>3); if(TEXFORMAT == TexFormat_15bpp) *dwdst++ = RGB15TO6665(c,alpha); else *dwdst++ = RGB15TO32(c,material_5bit_to_8bit[alpha]); adr++; } } break; } case TEXMODE_16BPP: { for(int j=0;j>1; for(int x = 0; x < len; ++x) { u16 c = map[x]; int alpha = ((c&0x8000)?opaqueColor:0); *dwdst++ = CONVERT(c&0x7FFF,alpha); } } break; } } //switch(texture format) #ifdef DO_DEBUG_DUMP_TEXTURE DebugDumpTexture(newitem); #endif return newitem; } //scan() static const int PALETTE_DUMP_SIZE = (64+16+16)*1024; u8 paletteDump[PALETTE_DUMP_SIZE]; void invalidate() { //check whether the palette memory changed //TODO - we should handle this instead by setting dirty flags in the vram memory mapping and noting whether palette memory was dirty. //but this will work for now MemSpan mspal = MemSpan_TexPalette(0,PALETTE_DUMP_SIZE,true); bool paletteDirty = mspal.memcmp(paletteDump); if(paletteDirty) { mspal.dump(paletteDump); } for(TTexCacheItemMultimap::iterator it(index.begin()); it != index.end(); ++it) { it->second->suspectedInvalid = true; //when the palette changes, we assume all 4x4 textures are dirty. //this is because each 4x4 item doesnt carry along with it a copy of the entire palette, for verification //instead, we just use the one paletteDump for verifying of all 4x4 textures; and if paletteDirty is set, verification has failed if(it->second->getTextureMode() == TEXMODE_4X4 && paletteDirty) it->second->assumedInvalid = true; } } void evict(u32 target = kMaxCacheSize) { //debug print //printf("%d %d/%d\n",index.size(),cache_size/1024,target/1024); //dont do anything unless we're over the target if(cache_size target) { if(index.size()==0) break; //just in case.. doesnt seem possible, cache_size wouldve been 0 TexCacheItem* item = index.begin()->second; list_remove(item); //printf("evicting! totalsize:%d\n",cache_size); delete item; } } } texCache; void TexCache_Reset() { texCache.evict(0); } void TexCache_Invalidate() { //note that this gets called whether texdata or texpalette gets reconfigured. texCache.invalidate(); } TexCacheItem* TexCache_SetTexture(TexCache_TexFormat TEXFORMAT, u32 format, u32 texpal) { switch(TEXFORMAT) { case TexFormat_32bpp: return texCache.scan(format,texpal); case TexFormat_15bpp: return texCache.scan(format,texpal); default: break; } return NULL; } //call this periodically to keep the tex cache clean void TexCache_EvictFrame() { texCache.evict(); } desmume/Makefile.common000664 001750 001750 00000012103 12755534123 016274 0ustar00sergiosergio000000 000000 INCDIR := -I$(CORE_DIR)/libretro-common/include SOURCES_CXX := \ $(CORE_DIR)/armcpu.cpp \ $(CORE_DIR)/arm_instructions.cpp \ $(CORE_DIR)/bios.cpp \ $(CORE_DIR)/cp15.cpp \ $(CORE_DIR)/emufile.cpp \ $(CORE_DIR)/encrypt.cpp \ $(CORE_DIR)/FIFO.cpp \ $(CORE_DIR)/firmware.cpp \ $(CORE_DIR)/GPU.cpp \ $(CORE_DIR)/mc.cpp \ $(CORE_DIR)/path.cpp \ $(CORE_DIR)/readwrite.cpp \ $(CORE_DIR)/wifi.cpp \ $(CORE_DIR)/MMU.cpp \ $(CORE_DIR)/NDSSystem.cpp \ $(CORE_DIR)/render3D.cpp \ $(CORE_DIR)/rtc.cpp \ $(CORE_DIR)/saves.cpp \ $(CORE_DIR)/slot1.cpp \ $(CORE_DIR)/slot2.cpp \ $(CORE_DIR)/SPU.cpp \ $(CORE_DIR)/matrix.cpp \ $(CORE_DIR)/gfx3d.cpp \ $(CORE_DIR)/thumb_instructions.cpp \ $(CORE_DIR)/utils/advanscene.cpp \ $(CORE_DIR)/utils/datetime.cpp \ $(CORE_DIR)/utils/emufat.cpp \ $(CORE_DIR)/utils/xstring.cpp \ $(CORE_DIR)/utils/decrypt/crc.cpp \ $(CORE_DIR)/utils/decrypt/decrypt.cpp \ $(CORE_DIR)/utils/decrypt/header.cpp \ $(CORE_DIR)/utils/vfat.cpp \ $(CORE_DIR)/utils/tinyxml/tinystr.cpp \ $(CORE_DIR)/utils/tinyxml/tinyxml.cpp \ $(CORE_DIR)/utils/tinyxml/tinyxmlerror.cpp \ $(CORE_DIR)/utils/tinyxml/tinyxmlparser.cpp \ $(CORE_DIR)/addons/slot2_auto.cpp \ $(CORE_DIR)/addons/slot2_mpcf.cpp \ $(CORE_DIR)/addons/slot2_paddle.cpp \ $(CORE_DIR)/addons/slot2_gbagame.cpp \ $(CORE_DIR)/addons/slot2_none.cpp \ $(CORE_DIR)/addons/slot2_rumblepak.cpp \ $(CORE_DIR)/addons/slot2_guitarGrip.cpp \ $(CORE_DIR)/addons/slot2_expMemory.cpp \ $(CORE_DIR)/addons/slot2_piano.cpp \ $(CORE_DIR)/addons/slot2_passme.cpp \ $(CORE_DIR)/addons/slot1_none.cpp \ $(CORE_DIR)/addons/slot1_r4.cpp \ $(CORE_DIR)/addons/slot1comp_mc.cpp \ $(CORE_DIR)/addons/slot1comp_rom.cpp \ $(CORE_DIR)/addons/slot1comp_protocol.cpp \ $(CORE_DIR)/addons/slot1_retail_mcrom.cpp \ $(CORE_DIR)/addons/slot1_retail_nand.cpp \ $(CORE_DIR)/addons/slot1_retail_auto.cpp \ $(CORE_DIR)/cheatSystem.cpp \ $(CORE_DIR)/texcache.cpp \ $(CORE_DIR)/rasterize.cpp \ $(CORE_DIR)/mic.cpp \ $(CORE_DIR)/driver.cpp \ $(CORE_DIR)/libretro/libretro.cpp \ $(CORE_DIR)/libretro/scrc32.cpp SOURCES_C := \ $(CORE_DIR)/utils/libfat/partition.c \ $(CORE_DIR)/utils/libfat/cache.c \ $(CORE_DIR)/utils/libfat/directory.c \ $(CORE_DIR)/utils/libfat/disc.c \ $(CORE_DIR)/utils/libfat/fatdir.c \ $(CORE_DIR)/utils/libfat/fatfile.c \ $(CORE_DIR)/utils/libfat/filetime.c \ $(CORE_DIR)/utils/libfat/file_allocation_table.c \ $(CORE_DIR)/utils/libfat/libfat.c \ $(CORE_DIR)/utils/libfat/libfat_public_api.c \ $(CORE_DIR)/utils/libfat/lock.c ifeq ($(platform), vita) SOURCES_CXX += $(CORE_DIR)/utils/task_vita.cpp else # We can only stop excluding this for Vita once we have more # filesystem functions implemented SOURCES_CXX += $(CORE_DIR)/addons/slot1_retail_mcrom_debug.cpp \ $(CORE_DIR)/utils/fsnitro.cpp SOURCES_CXX += $(CORE_DIR)/utils/task.cpp SOURCES_C += $(CORE_DIR)/libretro-common/rthreads/rthreads.c endif SOURCES_C += $(CORE_DIR)/common.c \ $(CORE_DIR)/utils/dlditool.c \ $(CORE_DIR)/libretro-common/memmap/memalign.c \ $(CORE_DIR)/libretro-common/streams/file_stream.c \ $(CORE_DIR)/libretro-common/features/features_cpu.c \ $(CORE_DIR)/libretro-common/compat/compat_strl.c \ $(CORE_DIR)/libretro-common/file/retro_dirent.c \ $(CORE_DIR)/libretro-common/file/retro_stat.c \ $(CORE_DIR)/libretro-common/file/file_path.c \ $(CORE_DIR)/libretro-common/string/stdstring.c \ $(CORE_DIR)/version.c ifeq ($(DESMUME_JIT_ARM),1) SOURCES_CXX += \ $(CORE_DIR)/utils/arm_arm/arm_gen.cpp \ $(CORE_DIR)/utils/arm_arm/arm_jit.cpp endif ifeq ($(DEBUG),1) SOURCES_CXX += $(CORE_DIR)/debug.cpp \ $(CORE_DIR)/Disassembler.cpp endif ifeq ($(DESMUME_JIT),1) SOURCES_CXX += \ $(CORE_DIR)/arm_jit.cpp \ $(CORE_DIR)/utils/AsmJit/core/assembler.cpp \ $(CORE_DIR)/utils/AsmJit/core/assert.cpp \ $(CORE_DIR)/utils/AsmJit/core/buffer.cpp \ $(CORE_DIR)/utils/AsmJit/core/compiler.cpp \ $(CORE_DIR)/utils/AsmJit/core/compilercontext.cpp \ $(CORE_DIR)/utils/AsmJit/core/compilerfunc.cpp \ $(CORE_DIR)/utils/AsmJit/core/compileritem.cpp \ $(CORE_DIR)/utils/AsmJit/core/context.cpp \ $(CORE_DIR)/utils/AsmJit/core/cpuinfo.cpp \ $(CORE_DIR)/utils/AsmJit/core/defs.cpp \ $(CORE_DIR)/utils/AsmJit/core/func.cpp \ $(CORE_DIR)/utils/AsmJit/core/logger.cpp \ $(CORE_DIR)/utils/AsmJit/core/memorymanager.cpp \ $(CORE_DIR)/utils/AsmJit/core/memorymarker.cpp \ $(CORE_DIR)/utils/AsmJit/core/operand.cpp \ $(CORE_DIR)/utils/AsmJit/core/stringbuilder.cpp \ $(CORE_DIR)/utils/AsmJit/core/stringutil.cpp \ $(CORE_DIR)/utils/AsmJit/core/virtualmemory.cpp \ $(CORE_DIR)/utils/AsmJit/core/zonememory.cpp \ $(CORE_DIR)/utils/AsmJit/x86/x86assembler.cpp \ $(CORE_DIR)/utils/AsmJit/x86/x86compiler.cpp \ $(CORE_DIR)/utils/AsmJit/x86/x86compilercontext.cpp \ $(CORE_DIR)/utils/AsmJit/x86/x86compilerfunc.cpp \ $(CORE_DIR)/utils/AsmJit/x86/x86compileritem.cpp \ $(CORE_DIR)/utils/AsmJit/x86/x86cpuinfo.cpp \ $(CORE_DIR)/utils/AsmJit/x86/x86defs.cpp \ $(CORE_DIR)/utils/AsmJit/x86/x86func.cpp \ $(CORE_DIR)/utils/AsmJit/x86/x86operand.cpp \ $(CORE_DIR)/utils/AsmJit/x86/x86util.cpp endif INCDIR += -I$(CORE_DIR) -I$(CORE_DIR)/libretro desmume/src/addons/000700 001750 001750 00000000000 12756420130 015364 5ustar00sergiosergio000000 000000 desmume/src/libretro-common/include/queues/task_queue.h000664 001750 001750 00000012637 12755534123 024531 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2016 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (task_queue.h). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef __LIBRETRO_SDK_TASK_QUEUE_H__ #define __LIBRETRO_SDK_TASK_QUEUE_H__ #include #include #include #include #include RETRO_BEGIN_DECLS enum task_queue_ctl_state { TASK_QUEUE_CTL_NONE = 0, /* Deinitializes the task system. * This deinitializes the task system. * The tasks that are running at * the moment will stay on hold * until TASK_QUEUE_CTL_INIT is called again. */ TASK_QUEUE_CTL_DEINIT, /* Initializes the task system. * This initializes the task system * and chooses an appropriate * implementation according to the settings. * * This must only be called from the main thread. */ TASK_QUEUE_CTL_INIT, /** * Calls func for every running task * until it returns true. * Returns a task or NULL if not found. */ TASK_QUEUE_CTL_FIND, /** * Calls func for every running task when handler * parameter matches task handler, allowing the * list parameter to be filled with user-defined * data. */ TASK_QUEUE_CTL_RETRIEVE, /* Blocks until all tasks have finished. * This must only be called from the main thread. */ TASK_QUEUE_CTL_WAIT, /* Checks for finished tasks * Takes the finished tasks, if any, * and runs their callbacks. * This must only be called from the main thread. */ TASK_QUEUE_CTL_CHECK, /* Pushes a task * The task will start as soon as possible. */ TASK_QUEUE_CTL_PUSH, /* Sends a signal to terminate all the tasks. * * This won't terminate the tasks immediately. * They will finish as soon as possible. * * This must only be called from the main thread. */ TASK_QUEUE_CTL_RESET, TASK_QUEUE_CTL_SET_THREADED, TASK_QUEUE_CTL_UNSET_THREADED, TASK_QUEUE_CTL_IS_THREADED, /** * Signals a task to end without waiting for * it to complete. */ TASK_QUEUE_CTL_CANCEL }; typedef struct retro_task retro_task_t; typedef void (*retro_task_callback_t)(void *task_data, void *user_data, const char *error); typedef void (*retro_task_handler_t)(retro_task_t *task); typedef bool (*retro_task_finder_t)(retro_task_t *task, void *userdata); typedef bool (*retro_task_retriever_t)(retro_task_t *task, void *data); typedef struct { char *source_file; } decompress_task_data_t; struct retro_task { retro_task_handler_t handler; /* always called from the main loop */ retro_task_callback_t callback; /* task cleanup handler to free allocated resources, will * be called immediately after running the main callback */ retro_task_handler_t cleanup; /* set to true by the handler to signal * the task has finished executing. */ bool finished; /* set to true by the task system * to signal the task *must* end. */ bool cancelled; /* if true no OSD messages will be displayed. */ bool mute; /* created by the handler, destroyed by the user */ void *task_data; /* owned by the user */ void *user_data; /* created and destroyed by the code related to the handler */ void *state; /* created by task handler; destroyed by main loop * (after calling the callback) */ char *error; /* -1 = unmettered, 0-100 progress value */ int8_t progress; /* handler can modify but will be * free()d automatically if non-NULL. */ char *title; /* don't touch this. */ retro_task_t *next; }; typedef struct task_finder_data { retro_task_finder_t func; void *userdata; } task_finder_data_t; typedef struct task_retriever_info { struct task_retriever_info *next; void *data; } task_retriever_info_t; typedef struct task_retriever_data { retro_task_handler_t handler; size_t element_size; retro_task_retriever_t func; task_retriever_info_t *list; } task_retriever_data_t; bool task_queue_ctl(enum task_queue_ctl_state state, void *data); void *task_queue_retriever_info_next(task_retriever_info_t **link); void task_queue_retriever_info_free(task_retriever_info_t *list); void task_queue_cancel_task(void *task); RETRO_END_DECLS #endif desmume/src/libretro-common/compat/000700 001750 001750 00000000000 12756420130 020507 5ustar00sergiosergio000000 000000 desmume/src/libretro/scrc32.cpp000664 001750 001750 00000007716 12755534123 017577 0ustar00sergiosergio000000 000000 #ifndef _S_CRC32_H #define _S_CRC32_H static const unsigned long crc_table[256] = { 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L, 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L, 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL, 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L, 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L, 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL, 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L, 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL, 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L, 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L, 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL, 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L, 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL, 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L, 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L, 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL, 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L, 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L, 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL, 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L, 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L, 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L, 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L, 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L, 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL, 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L, 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L, 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL, 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL, 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L, 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL, 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L, 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L, 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL, 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L, 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL, 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L, 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L, 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L, 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L, 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L, 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, 0x2d02ef8dL }; #define DO1_CRC32(buf) crc = crc_table[((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8); #define DO2_CRC32(buf) DO1_CRC32(buf); DO1_CRC32(buf); #define DO4_CRC32(buf) DO2_CRC32(buf); DO2_CRC32(buf); #define DO8_CRC32(buf) DO4_CRC32(buf); DO4_CRC32(buf); unsigned long crc32(unsigned long crc, const unsigned char *buf, unsigned int len) { if (buf == 0) return 0L; crc = crc ^ 0xffffffffL; while (len >= 8) { DO8_CRC32(buf); len -= 8; } if (len) do { DO1_CRC32(buf); } while (--len); return crc ^ 0xffffffffL; } #endif desmume/src/addons/slot1_none.cpp000664 001750 001750 00000002204 12755534123 020172 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2015 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the this software. If not, see . */ #include "../slot1.h" class Slot1_None : public ISlot1Interface { public: virtual Slot1Info const* info() { static Slot1InfoSimple info("None","Slot1 no-card emulation", 0xFF); return &info; } //pretty much every access to the card should just be ignored and reading HIGH-Z off the GC bus. //so, nothing really to do here //(notably, it results in a 0xFFFFFFFF card ID) }; ISlot1Interface* construct_Slot1_None() { return new Slot1_None(); }desmume/src/rtc.h000664 001750 001750 00000001654 12755534123 015106 0ustar00sergiosergio000000 000000 /* Copyright 2006 yopyop Copyright 2008 CrazyMax Copyright 2008-2010 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the this software. If not, see . */ #ifndef _RTC_H_ #define _RTC_H_ #include #include #include "types.h" #include "utils/datetime.h" DateTime rtcGetTime(void); extern void rtcInit(); extern u16 rtcRead(); extern void rtcWrite(u16 val); #endif desmume/src/libretro-common/include/encodings/utf.h000664 001750 001750 00000003512 12755534123 023613 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2016 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (utf.h). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef _LIBRETRO_ENCODINGS_UTF_H #define _LIBRETRO_ENCODINGS_UTF_H #include #include #include size_t utf8_conv_utf32(uint32_t *out, size_t out_chars, const char *in, size_t in_size); bool utf16_conv_utf8(uint8_t *out, size_t *out_chars, const uint16_t *in, size_t in_size); size_t utf8len(const char *string); size_t utf8cpy(char *d, size_t d_len, const char *s, size_t chars); const char *utf8skip(const char *str, size_t chars); #endif desmume/src/types.h000664 001750 001750 00000022175 12755534123 015463 0ustar00sergiosergio000000 000000 /* Copyright (C) 2005 Guillaume Duhamel Copyright (C) 2008-2015 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the this software. If not, see . */ #ifndef TYPES_HPP #define TYPES_HPP //analyze microsoft compilers #ifdef _MSC_VER #define HOST_WINDOWS #endif //_MSC_VER // Determine CPU architecture for platforms that don't use the autoconf script #if defined(__x86_64__) || defined(__LP64) || defined(__IA64__) || defined(_M_X64) || defined(_WIN64) #define HOST_64 #else #define HOST_32 #endif #ifdef DEVELOPER #define IF_DEVELOPER(X) X #else #define IF_DEVELOPER(X) #endif #ifdef HOST_WINDOWS #define ENABLE_SSE #define ENABLE_SSE2 #define HAVE_JIT #endif #ifdef __GNUC__ #ifdef __SSE__ #define ENABLE_SSE #endif #ifdef __SSE2__ #define ENABLE_SSE2 #endif #ifdef __SSE3__ #define ENABLE_SSE3 #endif #ifdef __SSSE3__ #define ENABLE_SSSE3 #endif #endif #ifdef _MSC_VER #define strcasecmp(x,y) _stricmp(x,y) #define strncasecmp(x, y, l) strnicmp(x, y, l) #define snprintf _snprintf #else #ifndef _WIN32 #define WINAPI #endif #endif #include //------------alignment macros------------- //dont apply these to types without further testing. it only works portably here on declarations of variables //cant we find a pattern other people use more successfully? #if defined(_MSC_VER) || defined(__INTEL_COMPILER) #define DS_ALIGN(X) __declspec(align(X)) #elif defined(__GNUC__) #define DS_ALIGN(X) __attribute__ ((aligned (X))) #else #define DS_ALIGN(X) #endif #ifdef HOST_64 #define CACHE_ALIGN DS_ALIGN(64) #else #define CACHE_ALIGN DS_ALIGN(32) #endif //use this for example when you want a byte value to be better-aligned #define FAST_ALIGN DS_ALIGN(4) //--------------------------------------------- #ifdef __MINGW32__ #define FASTCALL __attribute__((fastcall)) #define ASMJIT_CALL_CONV kX86FuncConvCompatFastCall #elif defined (__i386__) && !defined(__clang__) #define FASTCALL __attribute__((regparm(3))) #define ASMJIT_CALL_CONV kX86FuncConvGccRegParm3 #elif defined(_MSC_VER) || defined(__INTEL_COMPILER) #define FASTCALL #define ASMJIT_CALL_CONV kX86FuncConvDefault #else #define FASTCALL #define ASMJIT_CALL_CONV kX86FuncConvDefault #endif #ifdef _MSC_VER #define _CDECL_ __cdecl #else #define _CDECL_ #endif #ifndef FORCEINLINE #if defined(_MSC_VER) || defined(__INTEL_COMPILER) #define FORCEINLINE __forceinline #define MSC_FORCEINLINE __forceinline #else #define FORCEINLINE inline __attribute__((always_inline)) #define MSC_FORCEINLINE #endif #endif #ifndef NOINLINE #ifdef __GNUC__ #define NOINLINE __attribute__((noinline)) #else #define NOINLINE #endif #endif #if defined(__LP64__) typedef unsigned char u8; typedef unsigned short u16; typedef unsigned int u32; typedef unsigned long long u64; typedef signed char s8; typedef signed short s16; typedef signed int s32; typedef signed long long s64; #else typedef unsigned char u8; typedef unsigned short u16; typedef unsigned int u32; #if defined(_MSC_VER) || defined(__INTEL_COMPILER) typedef unsigned __int64 u64; #else typedef unsigned long long u64; #endif typedef signed char s8; typedef signed short s16; typedef signed int s32; #if defined(_MSC_VER) || defined(__INTEL_COMPILER) 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 /* little endian (ds' endianess) to local endianess convert macros */ #ifdef MSB_FIRST /* 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 LE_TO_LOCAL_64(x) ((((x)&0xff)<<56)|(((x)&0xff00)<<40)|(((x)&0xff0000)<<24)|(((x)&0xff000000)<<8)|(((x)>>8)&0xff000000)|(((x)>>24)&0xff0000)|(((x)>>40)&0xff00)|(((x)>>56)&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)) # define LOCAL_TO_LE_64(x) ((((x)&0xff)<<56)|(((x)&0xff00)<<40)|(((x)&0xff0000)<<24)|(((x)&0xff000000)<<8)|(((x)>>8)&0xff000000)|(((x)>>24)&0xff0000)|(((x)>>40)&0xff00)|(((x)>>56)&0xff)) #else /* local arch is little endian */ # define LE_TO_LOCAL_16(x) (x) # define LE_TO_LOCAL_32(x) (x) # define LE_TO_LOCAL_64(x) (x) # define LOCAL_TO_LE_16(x) (x) # define LOCAL_TO_LE_32(x) (x) # define LOCAL_TO_LE_64(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; static INLINE u64 double_to_u64(double d) { union { u64 a; double b; } fuxor; fuxor.b = d; return fuxor.a; } static INLINE double u64_to_double(u64 u) { union { u64 a; double b; } fuxor; fuxor.a = u; return fuxor.b; } //fairly standard for loop macros #define MACRODO1(TRICK,TODO) { const size_t X = TRICK; TODO; } #define MACRODO2(X,TODO) { MACRODO1((X),TODO) MACRODO1(((X)+1),TODO) } #define MACRODO4(X,TODO) { MACRODO2((X),TODO) MACRODO2(((X)+2),TODO) } #define MACRODO8(X,TODO) { MACRODO4((X),TODO) MACRODO4(((X)+4),TODO) } #define MACRODO16(X,TODO) { MACRODO8((X),TODO) MACRODO8(((X)+8),TODO) } #define MACRODO32(X,TODO) { MACRODO16((X),TODO) MACRODO16(((X)+16),TODO) } #define MACRODO64(X,TODO) { MACRODO32((X),TODO) MACRODO32(((X)+32),TODO) } #define MACRODO128(X,TODO) { MACRODO64((X),TODO) MACRODO64(((X)+64),TODO) } #define MACRODO256(X,TODO) { MACRODO128((X),TODO) MACRODO128(((X)+128),TODO) } //this one lets you loop any number of times (as long as N<256) #define MACRODO_N(N,TODO) {\ if((N)&0x100) MACRODO256(0,TODO); \ if((N)&0x080) MACRODO128((N)&(0x100),TODO); \ if((N)&0x040) MACRODO64((N)&(0x100|0x080),TODO); \ if((N)&0x020) MACRODO32((N)&(0x100|0x080|0x040),TODO); \ if((N)&0x010) MACRODO16((N)&(0x100|0x080|0x040|0x020),TODO); \ if((N)&0x008) MACRODO8((N)&(0x100|0x080|0x040|0x020|0x010),TODO); \ if((N)&0x004) MACRODO4((N)&(0x100|0x080|0x040|0x020|0x010|0x008),TODO); \ if((N)&0x002) MACRODO2((N)&(0x100|0x080|0x040|0x020|0x010|0x008|0x004),TODO); \ if((N)&0x001) MACRODO1((N)&(0x100|0x080|0x040|0x020|0x010|0x008|0x004|0x002),TODO); \ } //--------------------------- //Binary constant generator macro By Tom Torfs - donated to the public domain //turn a numeric literal into a hex constant //(avoids problems with leading zeroes) //8-bit constants max value 0x11111111, always fits in unsigned long #define HEX__(n) 0x##n##LU //8-bit conversion function #define B8__(x) ((x&0x0000000FLU)?1:0) \ +((x&0x000000F0LU)?2:0) \ +((x&0x00000F00LU)?4:0) \ +((x&0x0000F000LU)?8:0) \ +((x&0x000F0000LU)?16:0) \ +((x&0x00F00000LU)?32:0) \ +((x&0x0F000000LU)?64:0) \ +((x&0xF0000000LU)?128:0) //for upto 8-bit binary constants #define B8(d) ((unsigned char)B8__(HEX__(d))) // for upto 16-bit binary constants, MSB first #define B16(dmsb,dlsb) (((unsigned short)B8(dmsb)<<8) \ + B8(dlsb)) // for upto 32-bit binary constants, MSB first */ #define B32(dmsb,db2,db3,dlsb) (((unsigned long)B8(dmsb)<<24) \ + ((unsigned long)B8(db2)<<16) \ + ((unsigned long)B8(db3)<<8) \ + B8(dlsb)) //Sample usage: //B8(01010101) = 85 //B16(10101010,01010101) = 43605 //B32(10000000,11111111,10101010,01010101) = 2164238933 //--------------------------- static const char hexValid[23] = {"0123456789ABCDEFabcdef"}; template inline void reconstruct(T* t) { t->~T(); new(t) T(); } #endif desmume/src/libretro-common/queues/fifo_queue.c000664 001750 001750 00000006474 12755534123 023064 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2016 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (fifo_queue.c). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include #include #include struct fifo_buffer { uint8_t *buffer; size_t size; size_t first; size_t end; }; fifo_buffer_t *fifo_new(size_t size) { fifo_buffer_t *buf = (fifo_buffer_t*)calloc(1, sizeof(*buf)); if (!buf) return NULL; buf->buffer = (uint8_t*)calloc(1, size + 1); if (!buf->buffer) { free(buf); return NULL; } buf->size = size + 1; return buf; } void fifo_clear(fifo_buffer_t *buffer) { buffer->first = 0; buffer->end = 0; } void fifo_free(fifo_buffer_t *buffer) { if (!buffer) return; free(buffer->buffer); free(buffer); } size_t fifo_read_avail(fifo_buffer_t *buffer) { size_t first = buffer->first; size_t end = buffer->end; if (end < first) end += buffer->size; return end - first; } size_t fifo_write_avail(fifo_buffer_t *buffer) { size_t first = buffer->first; size_t end = buffer->end; if (end < first) end += buffer->size; return (buffer->size - 1) - (end - first); } void fifo_write(fifo_buffer_t *buffer, const void *in_buf, size_t size) { size_t first_write = size; size_t rest_write = 0; if (buffer->end + size > buffer->size) { first_write = buffer->size - buffer->end; rest_write = size - first_write; } memcpy(buffer->buffer + buffer->end, in_buf, first_write); memcpy(buffer->buffer, (const uint8_t*)in_buf + first_write, rest_write); buffer->end = (buffer->end + size) % buffer->size; } void fifo_read(fifo_buffer_t *buffer, void *in_buf, size_t size) { size_t first_read = size; size_t rest_read = 0; if (buffer->first + size > buffer->size) { first_read = buffer->size - buffer->first; rest_read = size - first_read; } memcpy(in_buf, (const uint8_t*)buffer->buffer + buffer->first, first_read); memcpy((uint8_t*)in_buf + first_read, buffer->buffer, rest_read); buffer->first = (buffer->first + size) % buffer->size; } desmume/src/utils/000700 001750 001750 00000000000 12756420413 015260 5ustar00sergiosergio000000 000000 desmume/src/libretro-common/file/retro_dirent.c000664 001750 001750 00000013302 12755534123 023031 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2016 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (retro_dirent.c). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include #include #include #if defined(_WIN32) # ifdef _MSC_VER # define setmode _setmode # endif # ifdef _XBOX # include # define INVALID_FILE_ATTRIBUTES -1 # else # include # include # include # include # endif #elif defined(VITA) # include # include #else # if defined(PSP) # include # endif # include # include # include # include #endif #ifdef __CELLOS_LV2__ #include #endif #include #include #include struct RDIR { #if defined(_WIN32) WIN32_FIND_DATA entry; HANDLE directory; bool next; #elif defined(VITA) || defined(PSP) SceUID directory; SceIoDirent entry; #elif defined(__CELLOS_LV2__) CellFsErrno error; int directory; CellFsDirent entry; #else DIR *directory; const struct dirent *entry; #endif }; struct RDIR *retro_opendir(const char *name) { #if defined(_WIN32) char path_buf[1024]; #endif struct RDIR *rdir = (struct RDIR*)calloc(1, sizeof(*rdir)); if (!rdir) return NULL; #if defined(_WIN32) snprintf(path_buf, sizeof(path_buf), "%s\\*", name); rdir->directory = FindFirstFile(path_buf, &rdir->entry); #elif defined(VITA) || defined(PSP) rdir->directory = sceIoDopen(name); #elif defined(__CELLOS_LV2__) rdir->error = cellFsOpendir(name, &rdir->directory); #else rdir->directory = opendir(name); rdir->entry = NULL; #endif return rdir; } bool retro_dirent_error(struct RDIR *rdir) { #if defined(_WIN32) return (rdir->directory == INVALID_HANDLE_VALUE); #elif defined(VITA) || defined(PSP) return (rdir->directory < 0); #elif defined(__CELLOS_LV2__) return (rdir->error != CELL_FS_SUCCEEDED); #else return !(rdir->directory); #endif } int retro_readdir(struct RDIR *rdir) { #if defined(_WIN32) if(rdir->next) return (FindNextFile(rdir->directory, &rdir->entry) != 0); else { rdir->next = true; return (rdir->directory != INVALID_HANDLE_VALUE); } #elif defined(VITA) || defined(PSP) return (sceIoDread(rdir->directory, &rdir->entry) > 0); #elif defined(__CELLOS_LV2__) uint64_t nread; rdir->error = cellFsReaddir(rdir->directory, &rdir->entry, &nread); return (nread != 0); #else return ((rdir->entry = readdir(rdir->directory)) != NULL); #endif } const char *retro_dirent_get_name(struct RDIR *rdir) { #if defined(_WIN32) return rdir->entry.cFileName; #elif defined(VITA) || defined(PSP) || defined(__CELLOS_LV2__) return rdir->entry.d_name; #else return rdir->entry->d_name; #endif } /** * * retro_dirent_is_dir: * @rdir : pointer to the directory entry. * @path : path to the directory entry. * * Is the directory listing entry a directory? * * Returns: true if directory listing entry is * a directory, false if not. */ bool retro_dirent_is_dir(struct RDIR *rdir, const char *path) { #if defined(_WIN32) const WIN32_FIND_DATA *entry = (const WIN32_FIND_DATA*)&rdir->entry; return entry->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY; #elif defined(PSP) || defined(VITA) const SceIoDirent *entry = (const SceIoDirent*)&rdir->entry; #if defined(PSP) return (entry->d_stat.st_attr & FIO_SO_IFDIR) == FIO_SO_IFDIR; #elif defined(VITA) return SCE_S_ISDIR(entry->d_stat.st_mode); #endif #elif defined(__CELLOS_LV2__) CellFsDirent *entry = (CellFsDirent*)&rdir->entry; return (entry->d_type == CELL_FS_TYPE_DIRECTORY); #elif defined(DT_DIR) const struct dirent *entry = (const struct dirent*)rdir->entry; if (entry->d_type == DT_DIR) return true; /* This can happen on certain file systems. */ if (entry->d_type == DT_UNKNOWN || entry->d_type == DT_LNK) return path_is_directory(path); return false; #else /* dirent struct doesn't have d_type, do it the slow way ... */ return path_is_directory(path); #endif } void retro_closedir(struct RDIR *rdir) { if (!rdir) return; #if defined(_WIN32) if (rdir->directory != INVALID_HANDLE_VALUE) FindClose(rdir->directory); #elif defined(VITA) || defined(PSP) sceIoDclose(rdir->directory); #elif defined(__CELLOS_LV2__) rdir->error = cellFsClosedir(rdir->directory); #else if (rdir->directory) closedir(rdir->directory); #endif free(rdir); } desmume/src/utils/AsmJit/x86/x86assembler.h000664 001750 001750 00000736462 12755534123 021631 0ustar00sergiosergio000000 000000 // [AsmJit] // Complete JIT Assembler for C++ Language. // // [License] // Zlib - See COPYING file in this package. // [Guard] #ifndef _ASMJIT_X86_X86ASSEMBLER_H #define _ASMJIT_X86_X86ASSEMBLER_H // [Dependencies - AsmJit] #include "../core/assembler.h" #include "../x86/x86defs.h" #include "../x86/x86operand.h" #include "../x86/x86util.h" // [Api-Begin] #include "../core/apibegin.h" namespace AsmJit { //! @addtogroup AsmJit_X86 //! @{ // ============================================================================ // [AsmJit::X86Assembler] // ============================================================================ //! @brief X86Assembler - low level x86/x64 code generation. //! //! @ref X86Assembler is the main class in AsmJit for generating low level //! x86/x64 binary stream. It creates internal buffer where opcodes are stored //! and contains methods that mimics x86/x64 assembler instructions. Code //! generation should be safe, because basic type-checks are done by the C++ //! compiler. It's nearly impossible to create invalid instruction (for example //! mov [eax], [eax] that will not be detected at compile time by //! C++ compiler. //! //! Each call to assembler intrinsics directly emits instruction to internal //! binary stream. Instruction emitting also contains runtime checks so it //! should be impossible to create an instruction that is not valid (except //! there is bug in AsmJit). //! //! @ref X86Assembler contains internal buffer where all emitted instructions //! are stored. Look at @ref Buffer for an implementation. To generate and //! allocate memory for function use @ref X86Assembler::make() method that will //! allocate memory using the provided memory manager (see @ref MemoryManager) //! and relocates the output code to the provided address. If you want to create //! your function manually, you should look at @ref VirtualMemory interface and //! use @ref X86Assembler::relocCode() method to relocate emitted code into //! provided memory location. You can also take the emitted buffer by @ref //! X86Assembler::take() to do something else with it. If you take buffer, you //! must free it manually by using @ref ASMJIT_FREE() macro. //! //! @section AsmJit_Assembler_CodeGeneration Code Generation //! //! To generate code is only needed to create instance of @c AsmJit::Assembler //! and to use intrinsics. See example how to do that: //! //! @code //! // Use AsmJit namespace. //! using namespace AsmJit; //! //! // Create Assembler instance. //! Assembler a; //! //! // Prolog. //! a.push(ebp); //! a.mov(ebp, esp); //! //! // Mov 1024 to EAX, EAX is also return value. //! a.mov(eax, imm(1024)); //! //! // Epilog. //! a.mov(esp, ebp); //! a.pop(ebp); //! //! // Return. //! a.ret(); //! @endcode //! //! You can see that syntax is very close to Intel one. Only difference is that //! you are calling functions that emits the binary code for you. All registers //! are in @c AsmJit namespace, so it's very comfortable to use it (look at //! first line). There is also used method @c AsmJit::imm() to create an //! immediate value. Use @c AsmJit::uimm() to create unsigned immediate value. //! //! There is also possibility to use memory addresses and immediates. To build //! memory address use @c ptr(), @c byte_ptr(), @c word_ptr(), @c dword_ptr() //! or other friend methods. In most cases you needs only @c ptr() method, but //! there are instructions where you must specify address size, //! //! for example (a is @c AsmJit::Assembler instance): //! //! @code //! a.mov(ptr(eax), imm(0)); // mov ptr [eax], 0 //! a.mov(ptr(eax), edx); // mov ptr [eax], edx //! @endcode //! //! But it's also possible to create complex addresses: //! //! @code //! // eax + ecx*x addresses //! a.mov(ptr(eax, ecx, kScaleNone), imm(0)); // mov ptr [eax + ecx], 0 //! a.mov(ptr(eax, ecx, kScale2Times), imm(0)); // mov ptr [eax + ecx * 2], 0 //! a.mov(ptr(eax, ecx, kScale4Times), imm(0)); // mov ptr [eax + ecx * 4], 0 //! a.mov(ptr(eax, ecx, kScale8Times), imm(0)); // mov ptr [eax + ecx * 8], 0 //! // eax + ecx*x + disp addresses //! a.mov(ptr(eax, ecx, kScaleNone, 4), imm(0)); // mov ptr [eax + ecx + 4], 0 //! a.mov(ptr(eax, ecx, kScale2Times, 8), imm(0)); // mov ptr [eax + ecx * 2 + 8], 0 //! a.mov(ptr(eax, ecx, kScale4Times, 12), imm(0)); // mov ptr [eax + ecx * 4 + 12], 0 //! a.mov(ptr(eax, ecx, kScale8Times, 16), imm(0)); // mov ptr [eax + ecx * 8 + 16], 0 //! @endcode //! //! All addresses shown are using @c AsmJit::ptr() to make memory operand. //! Some assembler instructions (single operand ones) needs to specify memory //! operand size. For example calling a.inc(ptr(eax)) can't be //! used. @c AsmJit::Assembler::inc(), @c AsmJit::Assembler::dec() and similar //! instructions can't be serialized without specifying how bytes they are //! operating on. See next code how assembler works: //! //! @code //! // [byte] address //! a.inc(byte_ptr(eax)); // inc byte ptr [eax] //! a.dec(byte_ptr(eax)); // dec byte ptr [eax] //! // [word] address //! a.inc(word_ptr(eax)); // inc word ptr [eax] //! a.dec(word_ptr(eax)); // dec word ptr [eax] //! // [dword] address //! a.inc(dword_ptr(eax)); // inc dword ptr [eax] //! a.dec(dword_ptr(eax)); // dec dword ptr [eax] //! @endcode //! //! @section AsmJit_Assembler_CallingJitCode Calling JIT Code //! //! While you are over from emitting instructions, you can make your function //! using @c AsmJit::Assembler::make() method. This method will use memory //! manager to allocate virtual memory and relocates generated code to it. For //! memory allocation is used global memory manager by default and memory is //! freeable, but of course this default behavior can be overridden specifying //! your memory manager and allocation type. If you want to do with code //! something else you can always override make() method and do what you want. //! //! You can get size of generated code by @c getCodeSize() or @c getOffset() //! methods. These methods returns you code size (or more precisely current code //! offset) in bytes. Use takeCode() to take internal buffer (all pointers in //! @c AsmJit::Assembler instance will be zeroed and current buffer returned) //! to use it. If you don't take it, @c AsmJit::Assembler destructor will //! free it automatically. To alloc and run code manually don't use //! @c malloc()'ed memory, but instead use @c AsmJit::VirtualMemory::alloc() //! to get memory for executing (specify @c canExecute to @c true) or //! @c AsmJit::MemoryManager that provides more effective and comfortable way //! to allocate virtual memory. //! //! See next example how to allocate memory where you can execute code created //! by @c AsmJit::Assembler: //! //! @code //! using namespace AsmJit; //! //! Assembler a; //! //! // ... your code generation //! //! // your function prototype //! typedef void (*MyFn)(); //! //! // make your function //! MyFn fn = asmjit_cast(a.make()); //! //! // call your function //! fn(); //! //! // If you don't need your function again, free it. //! MemoryManager::getGlobal()->free(fn); //! @endcode //! //! There is also low level alternative how to allocate virtual memory and //! relocate code to it: //! //! @code //! using namespace AsmJit; //! //! Assembler a; //! // Your code generation ... //! //! // Your function prototype. //! typedef void (*MyFn)(); //! //! // Alloc memory for your function. //! MyFn fn = asmjit_cast( //! MemoryManager::getGlobal()->alloc(a.getCodeSize()); //! //! // Relocate the code (will make the function). //! a.relocCode(fn); //! //! // Call the generated function. //! fn(); //! //! // If you don't need your function anymore, it should be freed. //! MemoryManager::getGlobal()->free(fn); //! @endcode //! //! @c note This was very primitive example how to call generated code. //! In real production code you will never alloc and free code for one run, //! you will usually use generated code many times. //! //! @section AsmJit_Assembler_Labels Labels //! //! While generating assembler code, you will usually need to create complex //! code with labels. Labels are fully supported and you can call @c jmp or //! @c je (and similar) instructions to initialized or yet uninitialized label. //! Each label expects to be bound into offset. To bind label to specific //! offset, use @c bind() method. //! //! See next example that contains complete code that creates simple memory //! copy function (in DWORD entities). //! //! @code //! // Example: Usage of Label (32-bit code). //! // //! // Create simple DWORD memory copy function: //! // ASMJIT_STDCALL void copy32(uint32_t* dst, const uint32_t* src, size_t count); //! using namespace AsmJit; //! //! // Assembler instance. //! Assembler a; //! //! // Constants. //! const int arg_offset = 8; // Arguments offset (STDCALL EBP). //! const int arg_size = 12; // Arguments size. //! //! // Labels. //! Label L_Loop = a.newLabel(); //! //! // Prolog. //! a.push(ebp); //! a.mov(ebp, esp); //! a.push(esi); //! a.push(edi); //! //! // Fetch arguments //! a.mov(esi, dword_ptr(ebp, arg_offset + 0)); // Get dst. //! a.mov(edi, dword_ptr(ebp, arg_offset + 4)); // Get src. //! a.mov(ecx, dword_ptr(ebp, arg_offset + 8)); // Get count. //! //! // Bind L_Loop label to here. //! a.bind(L_Loop); //! //! Copy 4 bytes. //! a.mov(eax, dword_ptr(esi)); //! a.mov(dword_ptr(edi), eax); //! //! // Increment pointers. //! a.add(esi, 4); //! a.add(edi, 4); //! //! // Repeat loop until (--ecx != 0). //! a.dec(ecx); //! a.jz(L_Loop); //! //! // Epilog. //! a.pop(edi); //! a.pop(esi); //! a.mov(esp, ebp); //! a.pop(ebp); //! //! // Return: STDCALL convention is to pop stack in called function. //! a.ret(arg_size); //! @endcode //! //! If you need more abstraction for generating assembler code and you want //! to hide calling conventions between 32-bit and 64-bit operating systems, //! look at @c Compiler class that is designed for higher level code //! generation. //! //! @section AsmJit_Assembler_AdvancedCodeGeneration Advanced Code Generation //! //! This section describes some advanced generation features of @c Assembler //! class which can be simply overlooked. The first thing that is very likely //! needed is generic register support. In previous example the named registers //! were used. AsmJit contains functions which can convert register index into //! operand and back. //! //! Let's define function which can be used to generate some abstract code: //! //! @code //! // Simple function that generates dword copy. //! void genCopyDWord( //! Assembler& a, //! const GpReg& dst, const GpReg& src, const GpReg& tmp) //! { //! a.mov(tmp, dword_ptr(src)); //! a.mov(dword_ptr(dst), tmp); //! } //! @endcode //! //! This function can be called like genCopyDWord(a, edi, esi, ebx) //! or by using existing @ref GpReg instances. This abstraction allows to join //! more code sections together without rewriting each to use specific registers. //! You need to take care only about implicit registers which may be used by //! several instructions (like mul, imul, div, idiv, shifting, etc...). //! //! Next, more advanced, but often needed technique is that you can build your //! own registers allocator. X86 architecture contains 8 general purpose registers, //! 8 MMX (MM) registers and 8 SSE (XMM) registers. The X64 (AMD64) architecture //! extends count of general purpose registers and SSE2 registers to 16. Use the //! @c kX86RegNumBase constant to get count of GP or XMM registers or @c kX86RegNumGp, //! @c kX86RegNumMm and @c kX86RegNumXmm constants individually. //! //! To build register from index (value from 0 inclusive to kRegNumXXX //! exclusive) use @ref gpd(), @ref gpq() or @ref gpz() functions. To create //! a 8 or 16-bit register use @ref gpw(), @ref gpb_lo() or @ref gpb_hi(). //! To create other registers there are similar methods like @ref mm(), @ref xmm() //! and @ref st(). //! //! So our function call to genCopyDWord can be also used like this: //! //! @code //! genCopyDWord(a, gpd(kX86RegIndexEdi), gpd(kX86RegIndexEsi), gpd(kX86RegIndexEbx)); //! @endcode //! //! kX86RegIndexXXX are constants defined by @ref kX86RegIndex enum. You can use your //! own register allocator (or register slot manager) to alloc / free registers //! so kX86RegIndexXXX values can be replaced by your variables (0 to kRegNumXXX-1). //! //! @sa @ref X86Compiler. struct X86Assembler : public Assembler { // -------------------------------------------------------------------------- // [Construction / Destruction] // -------------------------------------------------------------------------- ASMJIT_API X86Assembler(Context* context = JitContext::getGlobal()); ASMJIT_API virtual ~X86Assembler(); // -------------------------------------------------------------------------- // [Buffer - Setters (X86-Extensions)] // -------------------------------------------------------------------------- //! @brief Set custom variable @a i at position @a pos. //! //! @note This function is used to patch existing code. ASMJIT_API void setVarAt(size_t pos, sysint_t i, uint8_t isUnsigned, uint32_t size); // -------------------------------------------------------------------------- // [Emit] // // These functions are not protected against buffer overrun. Each place of // code which calls these functions ensures that there is some space using // canEmit() method. Emitters are internally protected in AsmJit::Buffer, // but only in debug builds. // -------------------------------------------------------------------------- //! @brief Emit single @a opCode without operands. inline void _emitOpCode(uint32_t opCode) { // Instruction prefix. if (opCode & 0xFF000000) _emitByte(static_cast((opCode >> 24) & 0xFF)); // Instruction opcodes. if (opCode & 0x00FF0000) _emitByte(static_cast((opCode >> 16) & 0xFF)); if (opCode & 0x0000FF00) _emitByte(static_cast((opCode >> 8) & 0xFF)); // Last opcode is always emitted (can be also 0x00). _emitByte(static_cast(opCode & 0xFF)); } //! @brief Emit MODR/M byte. inline void _emitMod(uint8_t m, uint8_t o, uint8_t r) { _emitByte(((m & 0x03) << 6) | ((o & 0x07) << 3) | (r & 0x07)); } //! @brief Emit SIB byte. inline void _emitSib(uint8_t s, uint8_t i, uint8_t b) { _emitByte(((s & 0x03) << 6) | ((i & 0x07) << 3) | (b & 0x07)); } //! @brief Emit REX prefix (64-bit mode only). inline void _emitRexR(uint8_t w, uint8_t opReg, uint8_t regCode, bool forceRexPrefix) { #if defined(ASMJIT_X64) uint32_t rex; // w - Default operand size(0=Default, 1=64-bit). // r - Register field (1=high bit extension of the ModR/M REG field). // x - Index field not used in RexR // b - Base field (1=high bit extension of the ModR/M or SIB Base field). rex = (static_cast(forceRexPrefix != 0)) << 6; // Rex prefix code. rex += (static_cast(w ) ) << 3; // Rex.W (w << 3). rex += (static_cast(opReg ) & 0x08 ) >> 1; // Rex.R (r << 2). rex += (static_cast(regCode) & 0x08 ) >> 3; // Rex.B (b << 0). if (rex) _emitByte(static_cast(rex | 0x40)); #else ASMJIT_UNUSED(w); ASMJIT_UNUSED(opReg); ASMJIT_UNUSED(regCode); ASMJIT_UNUSED(forceRexPrefix); #endif // ASMJIT_X64 } //! @brief Emit REX prefix (64-bit mode only). inline void _emitRexRM(uint8_t w, uint8_t opReg, const Operand& rm, bool forceRexPrefix) { #if defined(ASMJIT_X64) uint32_t rex; // w - Default operand size(0=Default, 1=64-bit). // r - Register field (1=high bit extension of the ModR/M REG field). // x - Index field (1=high bit extension of the SIB Index field). // b - Base field (1=high bit extension of the ModR/M or SIB Base field). rex = (static_cast(forceRexPrefix != 0)) << 6; // Rex prefix code. rex += (static_cast(w ) ) << 3; // Rex.W (w << 3). rex += (static_cast(opReg ) & 0x08 ) >> 1; // Rex.R (r << 2). uint32_t b = 0; uint32_t x = 0; if (rm.isReg()) { b = (static_cast(rm).getRegCode() & 0x08) != 0; } else if (rm.isMem()) { b = ((static_cast(rm).getBase() & 0x8) != 0) & (static_cast(rm).getBase() != kInvalidValue); x = ((static_cast(rm).getIndex() & 0x8) != 0) & (static_cast(rm).getIndex() != kInvalidValue); } rex += static_cast(x) << 1; // Rex.R (x << 1). rex += static_cast(b) ; // Rex.B (b << 0). if (rex) _emitByte(static_cast(rex | 0x40)); #else ASMJIT_UNUSED(w); ASMJIT_UNUSED(opReg); ASMJIT_UNUSED(rm); #endif // ASMJIT_X64 } //! @brief Emit Register / Register - calls _emitMod(3, opReg, r) inline void _emitModR(uint8_t opReg, uint8_t r) { _emitMod(3, opReg, r); } //! @brief Emit Register / Register - calls _emitMod(3, opReg, r.code()) inline void _emitModR(uint8_t opReg, const Reg& r) { _emitMod(3, opReg, r.getRegCode()); } //! @brief Emit register / memory address combination to buffer. //! //! This method can hangle addresses from simple to complex ones with //! index and displacement. ASMJIT_API void _emitModM(uint8_t opReg, const Mem& mem, sysint_t immSize); //! @brief Emit Reg<-Reg or Reg<-Reg|Mem ModRM (can be followed by SIB //! and displacement) to buffer. //! //! This function internally calls @c _emitModM() or _emitModR() that depends //! to @a op type. //! //! @note @a opReg is usually real register ID (see @c R) but some instructions //! have specific format and in that cases @a opReg is part of opcode. ASMJIT_API void _emitModRM(uint8_t opReg, const Operand& op, sysint_t immSize); //! @brief Emit CS (code segmend) prefix. //! //! Behavior of this function is to emit code prefix only if memory operand //! address uses code segment. Code segment is used through memory operand //! with attached @c AsmJit::Label. ASMJIT_API void _emitSegmentPrefix(const Operand& rm); //! @brief Emit instruction where register is inlined to opcode. ASMJIT_API void _emitX86Inl(uint32_t opCode, uint8_t i16bit, uint8_t rexw, uint8_t reg, bool forceRexPrefix); //! @brief Emit instruction with reg/memory operand. ASMJIT_API void _emitX86RM(uint32_t opCode, uint8_t i16bit, uint8_t rexw, uint8_t o, const Operand& op, sysint_t immSize, bool forceRexPrefix); //! @brief Emit FPU instruction with no operands. ASMJIT_API void _emitFpu(uint32_t opCode); //! @brief Emit FPU instruction with one operand @a sti (index of FPU register). ASMJIT_API void _emitFpuSTI(uint32_t opCode, uint32_t sti); //! @brief Emit FPU instruction with one operand @a opReg and memory operand @a mem. ASMJIT_API void _emitFpuMEM(uint32_t opCode, uint8_t opReg, const Mem& mem); //! @brief Emit MMX/SSE instruction. ASMJIT_API void _emitMmu(uint32_t opCode, uint8_t rexw, uint8_t opReg, const Operand& src, sysint_t immSize); //! @brief Emit displacement. ASMJIT_API LabelLink* _emitDisplacement(LabelData& l_data, sysint_t inlinedDisplacement, int size); //! @brief Emit relative relocation to absolute pointer @a target. It's needed //! to add what instruction is emitting this, because in x64 mode the relative //! displacement can be impossible to calculate and in this case the trampoline //! is used. ASMJIT_API void _emitJmpOrCallReloc(uint32_t instruction, void* target); // Helpers to decrease binary code size. These four emit methods are just // helpers thats used by assembler. They call emitX86() adding NULLs // to first, second and third operand, if needed. //! @brief Emit X86/FPU or MM/XMM instruction. ASMJIT_API void _emitInstruction(uint32_t code); //! @brief Emit X86/FPU or MM/XMM instruction. ASMJIT_API void _emitInstruction(uint32_t code, const Operand* o0); //! @brief Emit X86/FPU or MM/XMM instruction. ASMJIT_API void _emitInstruction(uint32_t code, const Operand* o0, const Operand* o1); //! @brief Emit X86/FPU or MM/XMM instruction. //! //! Operands @a o1, @a o2 or @a o3 can be @c NULL if they are not used. //! //! Hint: Use @c emitX86() helpers to emit instructions. ASMJIT_API void _emitInstruction(uint32_t code, const Operand* o0, const Operand* o1, const Operand* o2); //! @brief Private method for emitting jcc. ASMJIT_API void _emitJcc(uint32_t code, const Label* label, uint32_t hint); //! @brief Private method for emitting short jcc. inline void _emitShortJcc(uint32_t code, const Label* label, uint32_t hint) { _emitOptions |= kX86EmitOptionShortJump; _emitJcc(code, label, hint); } // -------------------------------------------------------------------------- // [EmbedLabel] // -------------------------------------------------------------------------- //! @brief Embed absolute label pointer (4 or 8 bytes). ASMJIT_API void embedLabel(const Label& label); // -------------------------------------------------------------------------- // [Align] // -------------------------------------------------------------------------- //! @brief Align target buffer to @a m bytes. //! //! Typical usage of this is to align labels at start of the inner loops. //! //! Inserts @c nop() instructions or CPU optimized NOPs. ASMJIT_API void align(uint32_t m); // -------------------------------------------------------------------------- // [Label] // -------------------------------------------------------------------------- //! @brief Create and return new label. ASMJIT_API Label newLabel(); //! @brief Register labels (used by @c Compiler). ASMJIT_API void registerLabels(size_t count); //! @brief Bind label to the current offset. //! //! @note Label can be bound only once! ASMJIT_API void bind(const Label& label); // -------------------------------------------------------------------------- // [Reloc] // -------------------------------------------------------------------------- ASMJIT_API virtual size_t relocCode(void* dst, sysuint_t addressBase) const; // -------------------------------------------------------------------------- // [Make] // -------------------------------------------------------------------------- ASMJIT_API virtual void* make(); // -------------------------------------------------------------------------- // [Embed] // -------------------------------------------------------------------------- //! @brief Add 8-bit integer data to the instuction stream. inline void db(uint8_t x) { embed(&x, 1); } //! @brief Add 16-bit integer data to the instuction stream. inline void dw(uint16_t x) { embed(&x, 2); } //! @brief Add 32-bit integer data to the instuction stream. inline void dd(uint32_t x) { embed(&x, 4); } //! @brief Add 64-bit integer data to the instuction stream. inline void dq(uint64_t x) { embed(&x, 8); } //! @brief Add 8-bit integer data to the instuction stream. inline void dint8(int8_t x) { embed(&x, sizeof(int8_t)); } //! @brief Add 8-bit integer data to the instuction stream. inline void duint8(uint8_t x) { embed(&x, sizeof(uint8_t)); } //! @brief Add 16-bit integer data to the instuction stream. inline void dint16(int16_t x) { embed(&x, sizeof(int16_t)); } //! @brief Add 16-bit integer data to the instuction stream. inline void duint16(uint16_t x) { embed(&x, sizeof(uint16_t)); } //! @brief Add 32-bit integer data to the instuction stream. inline void dint32(int32_t x) { embed(&x, sizeof(int32_t)); } //! @brief Add 32-bit integer data to the instuction stream. inline void duint32(uint32_t x) { embed(&x, sizeof(uint32_t)); } //! @brief Add 64-bit integer data to the instuction stream. inline void dint64(int64_t x) { embed(&x, sizeof(int64_t)); } //! @brief Add 64-bit integer data to the instuction stream. inline void duint64(uint64_t x) { embed(&x, sizeof(uint64_t)); } //! @brief Add system-integer data to the instuction stream. inline void dintptr(intptr_t x) { embed(&x, sizeof(intptr_t)); } //! @brief Add system-integer data to the instuction stream. inline void duintptr(uintptr_t x) { embed(&x, sizeof(uintptr_t)); } //! @brief Add float data to the instuction stream. inline void dfloat(float x) { embed(&x, sizeof(float)); } //! @brief Add double data to the instuction stream. inline void ddouble(double x) { embed(&x, sizeof(double)); } //! @brief Add pointer data to the instuction stream. inline void dptr(void* x) { embed(&x, sizeof(void*)); } //! @brief Add MM data to the instuction stream. inline void dmm(const MmData& x) { embed(&x, sizeof(MmData)); } //! @brief Add XMM data to the instuction stream. inline void dxmm(const XmmData& x) { embed(&x, sizeof(XmmData)); } //! @brief Add data to the instuction stream. inline void data(const void* data, size_t size) { embed(data, size); } //! @brief Add data in a given structure instance to the instuction stream. template inline void dstruct(const T& x) { embed(&x, sizeof(T)); } // -------------------------------------------------------------------------- // [X86 Instructions] // -------------------------------------------------------------------------- //! @brief Add with Carry. inline void adc(const GpReg& dst, const GpReg& src) { _emitInstruction(kX86InstAdc, &dst, &src); } //! @brief Add with Carry. inline void adc(const GpReg& dst, const Mem& src) { _emitInstruction(kX86InstAdc, &dst, &src); } //! @brief Add with Carry. inline void adc(const GpReg& dst, const Imm& src) { _emitInstruction(kX86InstAdc, &dst, &src); } //! @brief Add with Carry. inline void adc(const Mem& dst, const GpReg& src) { _emitInstruction(kX86InstAdc, &dst, &src); } //! @brief Add with Carry. inline void adc(const Mem& dst, const Imm& src) { _emitInstruction(kX86InstAdc, &dst, &src); } //! @brief Add. inline void add(const GpReg& dst, const GpReg& src) { _emitInstruction(kX86InstAdd, &dst, &src); } //! @brief Add. inline void add(const GpReg& dst, const Mem& src) { _emitInstruction(kX86InstAdd, &dst, &src); } //! @brief Add. inline void add(const GpReg& dst, const Imm& src) { _emitInstruction(kX86InstAdd, &dst, &src); } //! @brief Add. inline void add(const Mem& dst, const GpReg& src) { _emitInstruction(kX86InstAdd, &dst, &src); } //! @brief Add. inline void add(const Mem& dst, const Imm& src) { _emitInstruction(kX86InstAdd, &dst, &src); } //! @brief Logical And. inline void and_(const GpReg& dst, const GpReg& src) { _emitInstruction(kX86InstAnd, &dst, &src); } //! @brief Logical And. inline void and_(const GpReg& dst, const Mem& src) { _emitInstruction(kX86InstAnd, &dst, &src); } //! @brief Logical And. inline void and_(const GpReg& dst, const Imm& src) { _emitInstruction(kX86InstAnd, &dst, &src); } //! @brief Logical And. inline void and_(const Mem& dst, const GpReg& src) { _emitInstruction(kX86InstAnd, &dst, &src); } //! @brief Logical And. inline void and_(const Mem& dst, const Imm& src) { _emitInstruction(kX86InstAnd, &dst, &src); } //! @brief Bit Scan Forward. inline void bsf(const GpReg& dst, const GpReg& src) { ASMJIT_ASSERT(!dst.isGpb()); _emitInstruction(kX86InstBsf, &dst, &src); } //! @brief Bit Scan Forward. inline void bsf(const GpReg& dst, const Mem& src) { ASMJIT_ASSERT(!dst.isGpb()); _emitInstruction(kX86InstBsf, &dst, &src); } //! @brief Bit Scan Reverse. inline void bsr(const GpReg& dst, const GpReg& src) { ASMJIT_ASSERT(!dst.isGpb()); _emitInstruction(kX86InstBsr, &dst, &src); } //! @brief Bit Scan Reverse. inline void bsr(const GpReg& dst, const Mem& src) { ASMJIT_ASSERT(!dst.isGpb()); _emitInstruction(kX86InstBsr, &dst, &src); } //! @brief Byte swap (32-bit or 64-bit registers only) (i486). inline void bswap(const GpReg& dst) { ASMJIT_ASSERT(dst.getRegType() == kX86RegTypeGpd || dst.getRegType() == kX86RegTypeGpq); _emitInstruction(kX86InstBSwap, &dst); } //! @brief Bit test. inline void bt(const GpReg& dst, const GpReg& src) { _emitInstruction(kX86InstBt, &dst, &src); } //! @brief Bit test. inline void bt(const GpReg& dst, const Imm& src) { _emitInstruction(kX86InstBt, &dst, &src); } //! @brief Bit test. inline void bt(const Mem& dst, const GpReg& src) { _emitInstruction(kX86InstBt, &dst, &src); } //! @brief Bit test. inline void bt(const Mem& dst, const Imm& src) { _emitInstruction(kX86InstBt, &dst, &src); } //! @brief Bit test and complement. inline void btc(const GpReg& dst, const GpReg& src) { _emitInstruction(kX86InstBtc, &dst, &src); } //! @brief Bit test and complement. inline void btc(const GpReg& dst, const Imm& src) { _emitInstruction(kX86InstBtc, &dst, &src); } //! @brief Bit test and complement. inline void btc(const Mem& dst, const GpReg& src) { _emitInstruction(kX86InstBtc, &dst, &src); } //! @brief Bit test and complement. inline void btc(const Mem& dst, const Imm& src) { _emitInstruction(kX86InstBtc, &dst, &src); } //! @brief Bit test and reset. inline void btr(const GpReg& dst, const GpReg& src) { _emitInstruction(kX86InstBtr, &dst, &src); } //! @brief Bit test and reset. inline void btr(const GpReg& dst, const Imm& src) { _emitInstruction(kX86InstBtr, &dst, &src); } //! @brief Bit test and reset. inline void btr(const Mem& dst, const GpReg& src) { _emitInstruction(kX86InstBtr, &dst, &src); } //! @brief Bit test and reset. inline void btr(const Mem& dst, const Imm& src) { _emitInstruction(kX86InstBtr, &dst, &src); } //! @brief Bit test and set. inline void bts(const GpReg& dst, const GpReg& src) { _emitInstruction(kX86InstBts, &dst, &src); } //! @brief Bit test and set. inline void bts(const GpReg& dst, const Imm& src) { _emitInstruction(kX86InstBts, &dst, &src); } //! @brief Bit test and set. inline void bts(const Mem& dst, const GpReg& src) { _emitInstruction(kX86InstBts, &dst, &src); } //! @brief Bit test and set. inline void bts(const Mem& dst, const Imm& src) { _emitInstruction(kX86InstBts, &dst, &src); } //! @brief Call Procedure. inline void call(const GpReg& dst) { ASMJIT_ASSERT(dst.isRegType(kX86RegTypeGpz)); _emitInstruction(kX86InstCall, &dst); } //! @brief Call Procedure. inline void call(const Mem& dst) { _emitInstruction(kX86InstCall, &dst); } //! @brief Call Procedure. inline void call(const Imm& dst) { _emitInstruction(kX86InstCall, &dst); } //! @brief Call Procedure. //! @overload inline void call(void* dst) { Imm imm((sysint_t)dst); _emitInstruction(kX86InstCall, &imm); } //! @brief Call Procedure. inline void call(const Label& label) { _emitInstruction(kX86InstCall, &label); } //! @brief Convert Byte to Word (Sign Extend). //! //! AX <- Sign Extend AL inline void cbw() { _emitInstruction(kX86InstCbw); } //! @brief Convert Word to DWord (Sign Extend). //! //! DX:AX <- Sign Extend AX inline void cwd() { _emitInstruction(kX86InstCwd); } //! @brief Convert Word to DWord (Sign Extend). //! //! EAX <- Sign Extend AX inline void cwde() { _emitInstruction(kX86InstCwde); } //! @brief Convert DWord to QWord (Sign Extend). //! //! EDX:EAX <- Sign Extend EAX inline void cdq() { _emitInstruction(kX86InstCdq); } #if defined(ASMJIT_X64) //! @brief Convert DWord to QWord (Sign Extend). //! //! RAX <- Sign Extend EAX inline void cdqe() { _emitInstruction(kX86InstCdqe); } #endif // ASMJIT_X64 //! @brief Clear Carry flag //! //! This instruction clears the CF flag in the EFLAGS register. inline void clc() { _emitInstruction(kX86InstClc); } //! @brief Clear Direction flag //! //! This instruction clears the DF flag in the EFLAGS register. inline void cld() { _emitInstruction(kX86InstCld); } //! @brief Complement Carry Flag. //! //! This instruction complements the CF flag in the EFLAGS register. //! (CF = NOT CF) inline void cmc() { _emitInstruction(kX86InstCmc); } //! @brief Conditional Move. inline void cmov(kX86Cond cc, const GpReg& dst, const GpReg& src) { _emitInstruction(X86Util::getCMovccInstFromCond(cc), &dst, &src); } //! @brief Conditional Move. inline void cmov(kX86Cond cc, const GpReg& dst, const Mem& src) { _emitInstruction(X86Util::getCMovccInstFromCond(cc), &dst, &src); } //! @brief Conditional Move. inline void cmova (const GpReg& dst, const GpReg& src) { _emitInstruction(kX86InstCMovA , &dst, &src); } //! @brief Conditional Move. inline void cmova (const GpReg& dst, const Mem& src) { _emitInstruction(kX86InstCMovA , &dst, &src); } //! @brief Conditional Move. inline void cmovae (const GpReg& dst, const GpReg& src) { _emitInstruction(kX86InstCMovAE , &dst, &src); } //! @brief Conditional Move. inline void cmovae (const GpReg& dst, const Mem& src) { _emitInstruction(kX86InstCMovAE , &dst, &src); } //! @brief Conditional Move. inline void cmovb (const GpReg& dst, const GpReg& src) { _emitInstruction(kX86InstCMovB , &dst, &src); } //! @brief Conditional Move. inline void cmovb (const GpReg& dst, const Mem& src) { _emitInstruction(kX86InstCMovB , &dst, &src); } //! @brief Conditional Move. inline void cmovbe (const GpReg& dst, const GpReg& src) { _emitInstruction(kX86InstCMovBE , &dst, &src); } //! @brief Conditional Move. inline void cmovbe (const GpReg& dst, const Mem& src) { _emitInstruction(kX86InstCMovBE , &dst, &src); } //! @brief Conditional Move. inline void cmovc (const GpReg& dst, const GpReg& src) { _emitInstruction(kX86InstCMovC , &dst, &src); } //! @brief Conditional Move. inline void cmovc (const GpReg& dst, const Mem& src) { _emitInstruction(kX86InstCMovC , &dst, &src); } //! @brief Conditional Move. inline void cmove (const GpReg& dst, const GpReg& src) { _emitInstruction(kX86InstCMovE , &dst, &src); } //! @brief Conditional Move. inline void cmove (const GpReg& dst, const Mem& src) { _emitInstruction(kX86InstCMovE , &dst, &src); } //! @brief Conditional Move. inline void cmovg (const GpReg& dst, const GpReg& src) { _emitInstruction(kX86InstCMovG , &dst, &src); } //! @brief Conditional Move. inline void cmovg (const GpReg& dst, const Mem& src) { _emitInstruction(kX86InstCMovG , &dst, &src); } //! @brief Conditional Move. inline void cmovge (const GpReg& dst, const GpReg& src) { _emitInstruction(kX86InstCMovGE , &dst, &src); } //! @brief Conditional Move. inline void cmovge (const GpReg& dst, const Mem& src) { _emitInstruction(kX86InstCMovGE , &dst, &src); } //! @brief Conditional Move. inline void cmovl (const GpReg& dst, const GpReg& src) { _emitInstruction(kX86InstCMovL , &dst, &src); } //! @brief Conditional Move. inline void cmovl (const GpReg& dst, const Mem& src) { _emitInstruction(kX86InstCMovL , &dst, &src); } //! @brief Conditional Move. inline void cmovle (const GpReg& dst, const GpReg& src) { _emitInstruction(kX86InstCMovLE , &dst, &src); } //! @brief Conditional Move. inline void cmovle (const GpReg& dst, const Mem& src) { _emitInstruction(kX86InstCMovLE , &dst, &src); } //! @brief Conditional Move. inline void cmovna (const GpReg& dst, const GpReg& src) { _emitInstruction(kX86InstCMovNA , &dst, &src); } //! @brief Conditional Move. inline void cmovna (const GpReg& dst, const Mem& src) { _emitInstruction(kX86InstCMovNA , &dst, &src); } //! @brief Conditional Move. inline void cmovnae(const GpReg& dst, const GpReg& src) { _emitInstruction(kX86InstCMovNAE, &dst, &src); } //! @brief Conditional Move. inline void cmovnae(const GpReg& dst, const Mem& src) { _emitInstruction(kX86InstCMovNAE, &dst, &src); } //! @brief Conditional Move. inline void cmovnb (const GpReg& dst, const GpReg& src) { _emitInstruction(kX86InstCMovNB , &dst, &src); } //! @brief Conditional Move. inline void cmovnb (const GpReg& dst, const Mem& src) { _emitInstruction(kX86InstCMovNB , &dst, &src); } //! @brief Conditional Move. inline void cmovnbe(const GpReg& dst, const GpReg& src) { _emitInstruction(kX86InstCMovNBE, &dst, &src); } //! @brief Conditional Move. inline void cmovnbe(const GpReg& dst, const Mem& src) { _emitInstruction(kX86InstCMovNBE, &dst, &src); } //! @brief Conditional Move. inline void cmovnc (const GpReg& dst, const GpReg& src) { _emitInstruction(kX86InstCMovNC , &dst, &src); } //! @brief Conditional Move. inline void cmovnc (const GpReg& dst, const Mem& src) { _emitInstruction(kX86InstCMovNC , &dst, &src); } //! @brief Conditional Move. inline void cmovne (const GpReg& dst, const GpReg& src) { _emitInstruction(kX86InstCMovNE , &dst, &src); } //! @brief Conditional Move. inline void cmovne (const GpReg& dst, const Mem& src) { _emitInstruction(kX86InstCMovNE , &dst, &src); } //! @brief Conditional Move. inline void cmovng (const GpReg& dst, const GpReg& src) { _emitInstruction(kX86InstCMovNG , &dst, &src); } //! @brief Conditional Move. inline void cmovng (const GpReg& dst, const Mem& src) { _emitInstruction(kX86InstCMovNG , &dst, &src); } //! @brief Conditional Move. inline void cmovnge(const GpReg& dst, const GpReg& src) { _emitInstruction(kX86InstCMovNGE, &dst, &src); } //! @brief Conditional Move. inline void cmovnge(const GpReg& dst, const Mem& src) { _emitInstruction(kX86InstCMovNGE, &dst, &src); } //! @brief Conditional Move. inline void cmovnl (const GpReg& dst, const GpReg& src) { _emitInstruction(kX86InstCMovNL , &dst, &src); } //! @brief Conditional Move. inline void cmovnl (const GpReg& dst, const Mem& src) { _emitInstruction(kX86InstCMovNL , &dst, &src); } //! @brief Conditional Move. inline void cmovnle(const GpReg& dst, const GpReg& src) { _emitInstruction(kX86InstCMovNLE, &dst, &src); } //! @brief Conditional Move. inline void cmovnle(const GpReg& dst, const Mem& src) { _emitInstruction(kX86InstCMovNLE, &dst, &src); } //! @brief Conditional Move. inline void cmovno (const GpReg& dst, const GpReg& src) { _emitInstruction(kX86InstCMovNO , &dst, &src); } //! @brief Conditional Move. inline void cmovno (const GpReg& dst, const Mem& src) { _emitInstruction(kX86InstCMovNO , &dst, &src); } //! @brief Conditional Move. inline void cmovnp (const GpReg& dst, const GpReg& src) { _emitInstruction(kX86InstCMovNP , &dst, &src); } //! @brief Conditional Move. inline void cmovnp (const GpReg& dst, const Mem& src) { _emitInstruction(kX86InstCMovNP , &dst, &src); } //! @brief Conditional Move. inline void cmovns (const GpReg& dst, const GpReg& src) { _emitInstruction(kX86InstCMovNS , &dst, &src); } //! @brief Conditional Move. inline void cmovns (const GpReg& dst, const Mem& src) { _emitInstruction(kX86InstCMovNS , &dst, &src); } //! @brief Conditional Move. inline void cmovnz (const GpReg& dst, const GpReg& src) { _emitInstruction(kX86InstCMovNZ , &dst, &src); } //! @brief Conditional Move. inline void cmovnz (const GpReg& dst, const Mem& src) { _emitInstruction(kX86InstCMovNZ , &dst, &src); } //! @brief Conditional Move. inline void cmovo (const GpReg& dst, const GpReg& src) { _emitInstruction(kX86InstCMovO , &dst, &src); } //! @brief Conditional Move. inline void cmovo (const GpReg& dst, const Mem& src) { _emitInstruction(kX86InstCMovO , &dst, &src); } //! @brief Conditional Move. inline void cmovp (const GpReg& dst, const GpReg& src) { _emitInstruction(kX86InstCMovP , &dst, &src); } //! @brief Conditional Move. inline void cmovp (const GpReg& dst, const Mem& src) { _emitInstruction(kX86InstCMovP , &dst, &src); } //! @brief Conditional Move. inline void cmovpe (const GpReg& dst, const GpReg& src) { _emitInstruction(kX86InstCMovPE , &dst, &src); } //! @brief Conditional Move. inline void cmovpe (const GpReg& dst, const Mem& src) { _emitInstruction(kX86InstCMovPE , &dst, &src); } //! @brief Conditional Move. inline void cmovpo (const GpReg& dst, const GpReg& src) { _emitInstruction(kX86InstCMovPO , &dst, &src); } //! @brief Conditional Move. inline void cmovpo (const GpReg& dst, const Mem& src) { _emitInstruction(kX86InstCMovPO , &dst, &src); } //! @brief Conditional Move. inline void cmovs (const GpReg& dst, const GpReg& src) { _emitInstruction(kX86InstCMovS , &dst, &src); } //! @brief Conditional Move. inline void cmovs (const GpReg& dst, const Mem& src) { _emitInstruction(kX86InstCMovS , &dst, &src); } //! @brief Conditional Move. inline void cmovz (const GpReg& dst, const GpReg& src) { _emitInstruction(kX86InstCMovZ , &dst, &src); } //! @brief Conditional Move. inline void cmovz (const GpReg& dst, const Mem& src) { _emitInstruction(kX86InstCMovZ , &dst, &src); } //! @brief Compare Two Operands. inline void cmp(const GpReg& dst, const GpReg& src) { _emitInstruction(kX86InstCmp, &dst, &src); } //! @brief Compare Two Operands. inline void cmp(const GpReg& dst, const Mem& src) { _emitInstruction(kX86InstCmp, &dst, &src); } //! @brief Compare Two Operands. inline void cmp(const GpReg& dst, const Imm& src) { _emitInstruction(kX86InstCmp, &dst, &src); } //! @brief Compare Two Operands. inline void cmp(const Mem& dst, const GpReg& src) { _emitInstruction(kX86InstCmp, &dst, &src); } //! @brief Compare Two Operands. inline void cmp(const Mem& dst, const Imm& src) { _emitInstruction(kX86InstCmp, &dst, &src); } //! @brief Compare and Exchange (i486). inline void cmpxchg(const GpReg& dst, const GpReg& src) { _emitInstruction(kX86InstCmpXCHG, &dst, &src); } //! @brief Compare and Exchange (i486). inline void cmpxchg(const Mem& dst, const GpReg& src) { _emitInstruction(kX86InstCmpXCHG, &dst, &src); } //! @brief Compares the 64-bit value in EDX:EAX with the memory operand (Pentium). //! //! If the values are equal, then this instruction stores the 64-bit value //! in ECX:EBX into the memory operand and sets the zero flag. Otherwise, //! this instruction copies the 64-bit memory operand into the EDX:EAX //! registers and clears the zero flag. inline void cmpxchg8b(const Mem& dst) { _emitInstruction(kX86InstCmpXCHG8B, &dst); } #if defined(ASMJIT_X64) //! @brief Compares the 128-bit value in RDX:RAX with the memory operand (X64). //! //! If the values are equal, then this instruction stores the 128-bit value //! in RCX:RBX into the memory operand and sets the zero flag. Otherwise, //! this instruction copies the 128-bit memory operand into the RDX:RAX //! registers and clears the zero flag. inline void cmpxchg16b(const Mem& dst) { _emitInstruction(kX86InstCmpXCHG16B, &dst); } #endif // ASMJIT_X64 //! @brief CPU Identification (i486). inline void cpuid() { _emitInstruction(kX86InstCpuId); } #if defined(ASMJIT_X64) //! @brief Convert QWord to DQWord (Sign Extend). //! //! RDX:RAX <- Sign Extend RAX inline void cqo() { _emitInstruction(kX86InstCqo); } #endif // ASMJIT_X64 #if defined(ASMJIT_X86) //! @brief Decimal adjust AL after addition //! //! This instruction adjusts the sum of two packed BCD values to create //! a packed BCD result. //! //! @note This instruction is only available in 32-bit mode. inline void daa() { _emitInstruction(kX86InstDaa); } #endif // ASMJIT_X86 #if defined(ASMJIT_X86) //! @brief Decimal adjust AL after subtraction //! //! This instruction adjusts the result of the subtraction of two packed //! BCD values to create a packed BCD result. //! //! @note This instruction is only available in 32-bit mode. inline void das() { _emitInstruction(kX86InstDas); } #endif // ASMJIT_X86 //! @brief Decrement by 1. //! @note This instruction can be slower than sub(dst, 1) inline void dec(const GpReg& dst) { _emitInstruction(kX86InstDec, &dst); } //! @brief Decrement by 1. //! @note This instruction can be slower than sub(dst, 1) inline void dec(const Mem& dst) { _emitInstruction(kX86InstDec, &dst); } //! @brief Unsigned divide. //! //! This instruction divides (unsigned) the value in the AL, AX, or EAX //! register by the source operand and stores the result in the AX, //! DX:AX, or EDX:EAX registers. inline void div(const GpReg& src) { _emitInstruction(kX86InstDiv, &src); } //! @brief Unsigned divide. //! @overload inline void div(const Mem& src) { _emitInstruction(kX86InstDiv, &src); } //! @brief Make Stack Frame for Procedure Parameters. inline void enter(const Imm& imm16, const Imm& imm8) { _emitInstruction(kX86InstEnter, &imm16, &imm8); } //! @brief Signed divide. //! //! This instruction divides (signed) the value in the AL, AX, or EAX //! register by the source operand and stores the result in the AX, //! DX:AX, or EDX:EAX registers. inline void idiv(const GpReg& src) { _emitInstruction(kX86InstIDiv, &src); } //! @brief Signed divide. //! @overload inline void idiv(const Mem& src) { _emitInstruction(kX86InstIDiv, &src); } //! @brief Signed multiply. //! //! Source operand (in a general-purpose register or memory location) //! is multiplied by the value in the AL, AX, or EAX register (depending //! on the operand size) and the product is stored in the AX, DX:AX, or //! EDX:EAX registers, respectively. inline void imul(const GpReg& src) { _emitInstruction(kX86InstIMul, &src); } //! @overload inline void imul(const Mem& src) { _emitInstruction(kX86InstIMul, &src); } //! @brief Signed multiply. //! //! Destination operand (the first operand) is multiplied by the source //! operand (second operand). The destination operand is a general-purpose //! register and the source operand is an immediate value, a general-purpose //! register, or a memory location. The product is then stored in the //! destination operand location. inline void imul(const GpReg& dst, const GpReg& src) { _emitInstruction(kX86InstIMul, &dst, &src); } //! @brief Signed multiply. //! @overload inline void imul(const GpReg& dst, const Mem& src) { _emitInstruction(kX86InstIMul, &dst, &src); } //! @brief Signed multiply. //! @overload inline void imul(const GpReg& dst, const Imm& src) { _emitInstruction(kX86InstIMul, &dst, &src); } //! @brief Signed multiply. //! //! source operand (which can be a general-purpose register or a memory //! location) is multiplied by the second source operand (an immediate //! value). The product is then stored in the destination operand //! (a general-purpose register). inline void imul(const GpReg& dst, const GpReg& src, const Imm& imm) { _emitInstruction(kX86InstIMul, &dst, &src, &imm); } //! @overload inline void imul(const GpReg& dst, const Mem& src, const Imm& imm) { _emitInstruction(kX86InstIMul, &dst, &src, &imm); } //! @brief Increment by 1. //! @note This instruction can be slower than add(dst, 1) inline void inc(const GpReg& dst) { _emitInstruction(kX86InstInc, &dst); } //! @brief Increment by 1. //! @note This instruction can be slower than add(dst, 1) inline void inc(const Mem& dst) { _emitInstruction(kX86InstInc, &dst); } //! @brief Interrupt 3 - trap to debugger. inline void int3() { _emitInstruction(kX86InstInt3); } //! @brief Jump to label @a label if condition @a cc is met. //! //! This instruction checks the state of one or more of the status flags in //! the EFLAGS register (CF, OF, PF, SF, and ZF) and, if the flags are in the //! specified state (condition), performs a jump to the target instruction //! specified by the destination operand. A condition code (cc) is associated //! with each instruction to indicate the condition being tested for. If the //! condition is not satisfied, the jump is not performed and execution //! continues with the instruction following the Jcc instruction. inline void j(kX86Cond cc, const Label& label, uint32_t hint = kCondHintNone) { _emitJcc(X86Util::getJccInstFromCond(cc), &label, hint); } //! @brief Jump to label @a label if condition is met. inline void ja (const Label& label, uint32_t hint = kCondHintNone) { _emitJcc(kX86InstJA , &label, hint); } //! @brief Jump to label @a label if condition is met. inline void jae (const Label& label, uint32_t hint = kCondHintNone) { _emitJcc(kX86InstJAE , &label, hint); } //! @brief Jump to label @a label if condition is met. inline void jb (const Label& label, uint32_t hint = kCondHintNone) { _emitJcc(kX86InstJB , &label, hint); } //! @brief Jump to label @a label if condition is met. inline void jbe (const Label& label, uint32_t hint = kCondHintNone) { _emitJcc(kX86InstJBE , &label, hint); } //! @brief Jump to label @a label if condition is met. inline void jc (const Label& label, uint32_t hint = kCondHintNone) { _emitJcc(kX86InstJC , &label, hint); } //! @brief Jump to label @a label if condition is met. inline void je (const Label& label, uint32_t hint = kCondHintNone) { _emitJcc(kX86InstJE , &label, hint); } //! @brief Jump to label @a label if condition is met. inline void jg (const Label& label, uint32_t hint = kCondHintNone) { _emitJcc(kX86InstJG , &label, hint); } //! @brief Jump to label @a label if condition is met. inline void jge (const Label& label, uint32_t hint = kCondHintNone) { _emitJcc(kX86InstJGE , &label, hint); } //! @brief Jump to label @a label if condition is met. inline void jl (const Label& label, uint32_t hint = kCondHintNone) { _emitJcc(kX86InstJL , &label, hint); } //! @brief Jump to label @a label if condition is met. inline void jle (const Label& label, uint32_t hint = kCondHintNone) { _emitJcc(kX86InstJLE , &label, hint); } //! @brief Jump to label @a label if condition is met. inline void jna (const Label& label, uint32_t hint = kCondHintNone) { _emitJcc(kX86InstJNA , &label, hint); } //! @brief Jump to label @a label if condition is met. inline void jnae(const Label& label, uint32_t hint = kCondHintNone) { _emitJcc(kX86InstJNAE, &label, hint); } //! @brief Jump to label @a label if condition is met. inline void jnb (const Label& label, uint32_t hint = kCondHintNone) { _emitJcc(kX86InstJNB , &label, hint); } //! @brief Jump to label @a label if condition is met. inline void jnbe(const Label& label, uint32_t hint = kCondHintNone) { _emitJcc(kX86InstJNBE, &label, hint); } //! @brief Jump to label @a label if condition is met. inline void jnc (const Label& label, uint32_t hint = kCondHintNone) { _emitJcc(kX86InstJNC , &label, hint); } //! @brief Jump to label @a label if condition is met. inline void jne (const Label& label, uint32_t hint = kCondHintNone) { _emitJcc(kX86InstJNE , &label, hint); } //! @brief Jump to label @a label if condition is met. inline void jng (const Label& label, uint32_t hint = kCondHintNone) { _emitJcc(kX86InstJNG , &label, hint); } //! @brief Jump to label @a label if condition is met. inline void jnge(const Label& label, uint32_t hint = kCondHintNone) { _emitJcc(kX86InstJNGE, &label, hint); } //! @brief Jump to label @a label if condition is met. inline void jnl (const Label& label, uint32_t hint = kCondHintNone) { _emitJcc(kX86InstJNL , &label, hint); } //! @brief Jump to label @a label if condition is met. inline void jnle(const Label& label, uint32_t hint = kCondHintNone) { _emitJcc(kX86InstJNLE, &label, hint); } //! @brief Jump to label @a label if condition is met. inline void jno (const Label& label, uint32_t hint = kCondHintNone) { _emitJcc(kX86InstJNO , &label, hint); } //! @brief Jump to label @a label if condition is met. inline void jnp (const Label& label, uint32_t hint = kCondHintNone) { _emitJcc(kX86InstJNP , &label, hint); } //! @brief Jump to label @a label if condition is met. inline void jns (const Label& label, uint32_t hint = kCondHintNone) { _emitJcc(kX86InstJNS , &label, hint); } //! @brief Jump to label @a label if condition is met. inline void jnz (const Label& label, uint32_t hint = kCondHintNone) { _emitJcc(kX86InstJNZ , &label, hint); } //! @brief Jump to label @a label if condition is met. inline void jo (const Label& label, uint32_t hint = kCondHintNone) { _emitJcc(kX86InstJO , &label, hint); } //! @brief Jump to label @a label if condition is met. inline void jp (const Label& label, uint32_t hint = kCondHintNone) { _emitJcc(kX86InstJP , &label, hint); } //! @brief Jump to label @a label if condition is met. inline void jpe (const Label& label, uint32_t hint = kCondHintNone) { _emitJcc(kX86InstJPE , &label, hint); } //! @brief Jump to label @a label if condition is met. inline void jpo (const Label& label, uint32_t hint = kCondHintNone) { _emitJcc(kX86InstJPO , &label, hint); } //! @brief Jump to label @a label if condition is met. inline void js (const Label& label, uint32_t hint = kCondHintNone) { _emitJcc(kX86InstJS , &label, hint); } //! @brief Jump to label @a label if condition is met. inline void jz (const Label& label, uint32_t hint = kCondHintNone) { _emitJcc(kX86InstJZ , &label, hint); } //! @brief Short jump to label @a label if condition @a cc is met. //! @sa j() inline void short_j(kX86Cond cc, const Label& label, uint32_t hint = kCondHintNone) { _emitOptions |= kX86EmitOptionShortJump; j(cc, label, hint); } //! @brief Short jump to label @a label if condition is met. inline void short_ja (const Label& label, uint32_t hint = kCondHintNone) { _emitShortJcc(kX86InstJA , &label, hint); } //! @brief Short jump to label @a label if condition is met. inline void short_jae (const Label& label, uint32_t hint = kCondHintNone) { _emitShortJcc(kX86InstJAE , &label, hint); } //! @brief Short jump to label @a label if condition is met. inline void short_jb (const Label& label, uint32_t hint = kCondHintNone) { _emitShortJcc(kX86InstJB , &label, hint); } //! @brief Short jump to label @a label if condition is met. inline void short_jbe (const Label& label, uint32_t hint = kCondHintNone) { _emitShortJcc(kX86InstJBE , &label, hint); } //! @brief Short jump to label @a label if condition is met. inline void short_jc (const Label& label, uint32_t hint = kCondHintNone) { _emitShortJcc(kX86InstJC , &label, hint); } //! @brief Short jump to label @a label if condition is met. inline void short_je (const Label& label, uint32_t hint = kCondHintNone) { _emitShortJcc(kX86InstJE , &label, hint); } //! @brief Short jump to label @a label if condition is met. inline void short_jg (const Label& label, uint32_t hint = kCondHintNone) { _emitShortJcc(kX86InstJG , &label, hint); } //! @brief Short jump to label @a label if condition is met. inline void short_jge (const Label& label, uint32_t hint = kCondHintNone) { _emitShortJcc(kX86InstJGE , &label, hint); } //! @brief Short jump to label @a label if condition is met. inline void short_jl (const Label& label, uint32_t hint = kCondHintNone) { _emitShortJcc(kX86InstJL , &label, hint); } //! @brief Short jump to label @a label if condition is met. inline void short_jle (const Label& label, uint32_t hint = kCondHintNone) { _emitShortJcc(kX86InstJLE , &label, hint); } //! @brief Short jump to label @a label if condition is met. inline void short_jna (const Label& label, uint32_t hint = kCondHintNone) { _emitShortJcc(kX86InstJNA , &label, hint); } //! @brief Short jump to label @a label if condition is met. inline void short_jnae(const Label& label, uint32_t hint = kCondHintNone) { _emitShortJcc(kX86InstJNAE, &label, hint); } //! @brief Short jump to label @a label if condition is met. inline void short_jnb (const Label& label, uint32_t hint = kCondHintNone) { _emitShortJcc(kX86InstJNB , &label, hint); } //! @brief Short jump to label @a label if condition is met. inline void short_jnbe(const Label& label, uint32_t hint = kCondHintNone) { _emitShortJcc(kX86InstJNBE, &label, hint); } //! @brief Short jump to label @a label if condition is met. inline void short_jnc (const Label& label, uint32_t hint = kCondHintNone) { _emitShortJcc(kX86InstJNC , &label, hint); } //! @brief Short jump to label @a label if condition is met. inline void short_jne (const Label& label, uint32_t hint = kCondHintNone) { _emitShortJcc(kX86InstJNE , &label, hint); } //! @brief Short jump to label @a label if condition is met. inline void short_jng (const Label& label, uint32_t hint = kCondHintNone) { _emitShortJcc(kX86InstJNG , &label, hint); } //! @brief Short jump to label @a label if condition is met. inline void short_jnge(const Label& label, uint32_t hint = kCondHintNone) { _emitShortJcc(kX86InstJNGE, &label, hint); } //! @brief Short jump to label @a label if condition is met. inline void short_jnl (const Label& label, uint32_t hint = kCondHintNone) { _emitShortJcc(kX86InstJNL , &label, hint); } //! @brief Short jump to label @a label if condition is met. inline void short_jnle(const Label& label, uint32_t hint = kCondHintNone) { _emitShortJcc(kX86InstJNLE, &label, hint); } //! @brief Short jump to label @a label if condition is met. inline void short_jno (const Label& label, uint32_t hint = kCondHintNone) { _emitShortJcc(kX86InstJNO , &label, hint); } //! @brief Short jump to label @a label if condition is met. inline void short_jnp (const Label& label, uint32_t hint = kCondHintNone) { _emitShortJcc(kX86InstJNP , &label, hint); } //! @brief Short jump to label @a label if condition is met. inline void short_jns (const Label& label, uint32_t hint = kCondHintNone) { _emitShortJcc(kX86InstJNS , &label, hint); } //! @brief Short jump to label @a label if condition is met. inline void short_jnz (const Label& label, uint32_t hint = kCondHintNone) { _emitShortJcc(kX86InstJNZ , &label, hint); } //! @brief Short jump to label @a label if condition is met. inline void short_jo (const Label& label, uint32_t hint = kCondHintNone) { _emitShortJcc(kX86InstJO , &label, hint); } //! @brief Short jump to label @a label if condition is met. inline void short_jp (const Label& label, uint32_t hint = kCondHintNone) { _emitShortJcc(kX86InstJP , &label, hint); } //! @brief Short jump to label @a label if condition is met. inline void short_jpe (const Label& label, uint32_t hint = kCondHintNone) { _emitShortJcc(kX86InstJPE , &label, hint); } //! @brief Short jump to label @a label if condition is met. inline void short_jpo (const Label& label, uint32_t hint = kCondHintNone) { _emitShortJcc(kX86InstJPO , &label, hint); } //! @brief Short jump to label @a label if condition is met. inline void short_js (const Label& label, uint32_t hint = kCondHintNone) { _emitShortJcc(kX86InstJS , &label, hint); } //! @brief Short jump to label @a label if condition is met. inline void short_jz (const Label& label, uint32_t hint = kCondHintNone) { _emitShortJcc(kX86InstJZ , &label, hint); } //! @brief Jump. //! @overload inline void jmp(const GpReg& dst) { _emitInstruction(kX86InstJmp, &dst); } //! @brief Jump. //! @overload inline void jmp(const Mem& dst) { _emitInstruction(kX86InstJmp, &dst); } //! @brief Jump. //! @overload inline void jmp(const Imm& dst) { _emitInstruction(kX86InstJmp, &dst); } //! @brief Jump. //! @overload inline void jmp(void* dst) { Imm imm((sysint_t)dst); _emitInstruction(kX86InstJmp, &imm); } //! @brief Jump. //! //! This instruction transfers program control to a different point //! in the instruction stream without recording return information. //! The destination (target) operand specifies the label of the //! instruction being jumped to. inline void jmp(const Label& label) { _emitInstruction(kX86InstJmp, &label); } //! @brief Short jump. //! @sa jmp() inline void short_jmp(const Label& label) { _emitOptions |= kX86EmitOptionShortJump; _emitInstruction(kX86InstJmp, &label); } //! @brief Load Effective Address //! //! This instruction computes the effective address of the second //! operand (the source operand) and stores it in the first operand //! (destination operand). The source operand is a memory address //! (offset part) specified with one of the processors addressing modes. //! The destination operand is a general-purpose register. inline void lea(const GpReg& dst, const Mem& src) { _emitInstruction(kX86InstLea, &dst, &src); } //! @brief High Level Procedure Exit. inline void leave() { _emitInstruction(kX86InstLeave); } //! @brief Move. //! //! This instruction copies the second operand (source operand) to the first //! operand (destination operand). The source operand can be an immediate //! value, general-purpose register, segment register, or memory location. //! The destination register can be a general-purpose register, segment //! register, or memory location. Both operands must be the same size, which //! can be a byte, a word, or a DWORD. //! //! @note To move MMX or SSE registers to/from GP registers or memory, use //! corresponding functions: @c movd(), @c movq(), etc. Passing MMX or SSE //! registers to @c mov() is illegal. inline void mov(const GpReg& dst, const GpReg& src) { _emitInstruction(kX86InstMov, &dst, &src); } //! @brief Move. //! @overload inline void mov(const GpReg& dst, const Mem& src) { _emitInstruction(kX86InstMov, &dst, &src); } //! @brief Move. //! @overload inline void mov(const GpReg& dst, const Imm& src) { _emitInstruction(kX86InstMov, &dst, &src); } //! @brief Move. //! @overload inline void mov(const Mem& dst, const GpReg& src) { _emitInstruction(kX86InstMov, &dst, &src); } //! @brief Move. //! @overload inline void mov(const Mem& dst, const Imm& src) { _emitInstruction(kX86InstMov, &dst, &src); } //! @brief Move from segment register. //! @overload. inline void mov(const GpReg& dst, const SegmentReg& src) { _emitInstruction(kX86InstMov, &dst, &src); } //! @brief Move from segment register. //! @overload. inline void mov(const Mem& dst, const SegmentReg& src) { _emitInstruction(kX86InstMov, &dst, &src); } //! @brief Move to segment register. //! @overload. inline void mov(const SegmentReg& dst, const GpReg& src) { _emitInstruction(kX86InstMov, &dst, &src); } //! @brief Move to segment register. //! @overload. inline void mov(const SegmentReg& dst, const Mem& src) { _emitInstruction(kX86InstMov, &dst, &src); } //! @brief Move byte, word, dword or qword from absolute address @a src to //! AL, AX, EAX or RAX register. inline void mov_ptr(const GpReg& dst, void* src) { ASMJIT_ASSERT(dst.getRegIndex() == 0); Imm imm((sysint_t)src); _emitInstruction(kX86InstMovPtr, &dst, &imm); } //! @brief Move byte, word, dword or qword from AL, AX, EAX or RAX register //! to absolute address @a dst. inline void mov_ptr(void* dst, const GpReg& src) { ASMJIT_ASSERT(src.getRegIndex() == 0); Imm imm((sysint_t)dst); _emitInstruction(kX86InstMovPtr, &imm, &src); } //! @brief Move with Sign-Extension. //! //! This instruction copies the contents of the source operand (register //! or memory location) to the destination operand (register) and sign //! extends the value to 16, 32 or 64-bits. //! //! @sa movsxd(). void movsx(const GpReg& dst, const GpReg& src) { _emitInstruction(kX86InstMovSX, &dst, &src); } //! @brief Move with Sign-Extension. //! @overload void movsx(const GpReg& dst, const Mem& src) { _emitInstruction(kX86InstMovSX, &dst, &src); } #if defined(ASMJIT_X64) //! @brief Move DWord to QWord with sign-extension. inline void movsxd(const GpReg& dst, const GpReg& src) { _emitInstruction(kX86InstMovSXD, &dst, &src); } //! @brief Move DWord to QWord with sign-extension. //! @overload inline void movsxd(const GpReg& dst, const Mem& src) { _emitInstruction(kX86InstMovSXD, &dst, &src); } #endif // ASMJIT_X64 //! @brief Move with Zero-Extend. //! //! This instruction copies the contents of the source operand (register //! or memory location) to the destination operand (register) and zero //! extends the value to 16 or 32-bits. The size of the converted value //! depends on the operand-size attribute. inline void movzx(const GpReg& dst, const GpReg& src) { _emitInstruction(kX86InstMovZX, &dst, &src); } //! @brief Move with Zero-Extend. //! @brief Overload inline void movzx(const GpReg& dst, const Mem& src) { _emitInstruction(kX86InstMovZX, &dst, &src); } //! @brief Unsigned multiply. //! //! Source operand (in a general-purpose register or memory location) //! is multiplied by the value in the AL, AX, or EAX register (depending //! on the operand size) and the product is stored in the AX, DX:AX, or //! EDX:EAX registers, respectively. inline void mul(const GpReg& src) { _emitInstruction(kX86InstMul, &src); } //! @brief Unsigned multiply. //! @overload inline void mul(const Mem& src) { _emitInstruction(kX86InstMul, &src); } //! @brief Two's Complement Negation. inline void neg(const GpReg& dst) { _emitInstruction(kX86InstNeg, &dst); } //! @brief Two's Complement Negation. inline void neg(const Mem& dst) { _emitInstruction(kX86InstNeg, &dst); } //! @brief No Operation. //! //! This instruction performs no operation. This instruction is a one-byte //! instruction that takes up space in the instruction stream but does not //! affect the machine context, except the EIP register. The NOP instruction //! is an alias mnemonic for the XCHG (E)AX, (E)AX instruction. inline void nop() { _emitInstruction(kX86InstNop); } //! @brief One's Complement Negation. inline void not_(const GpReg& dst) { _emitInstruction(kX86InstNot, &dst); } //! @brief One's Complement Negation. inline void not_(const Mem& dst) { _emitInstruction(kX86InstNot, &dst); } //! @brief Logical Inclusive OR. inline void or_(const GpReg& dst, const GpReg& src) { _emitInstruction(kX86InstOr, &dst, &src); } //! @brief Logical Inclusive OR. inline void or_(const GpReg& dst, const Mem& src) { _emitInstruction(kX86InstOr, &dst, &src); } //! @brief Logical Inclusive OR. inline void or_(const GpReg& dst, const Imm& src) { _emitInstruction(kX86InstOr, &dst, &src); } //! @brief Logical Inclusive OR. inline void or_(const Mem& dst, const GpReg& src) { _emitInstruction(kX86InstOr, &dst, &src); } //! @brief Logical Inclusive OR. inline void or_(const Mem& dst, const Imm& src) { _emitInstruction(kX86InstOr, &dst, &src); } //! @brief Pop a Value from the Stack. //! //! This instruction loads the value from the top of the stack to the location //! specified with the destination operand and then increments the stack pointer. //! The destination operand can be a general purpose register, memory location, //! or segment register. inline void pop(const GpReg& dst) { ASMJIT_ASSERT(dst.isRegType(kX86RegTypeGpw) || dst.isRegType(kX86RegTypeGpz)); _emitInstruction(kX86InstPop, &dst); } //! @brief Pop a Segment Register from the Stack. //! //! @note There is no instruction to pop a cs segment register. inline void pop(const SegmentReg& dst) { ASMJIT_ASSERT(dst.getRegIndex() != kX86SegCs); _emitInstruction(kX86InstPop, &dst); } inline void pop(const Mem& dst) { ASMJIT_ASSERT(dst.getSize() == 2 || dst.getSize() == sizeof(sysint_t)); _emitInstruction(kX86InstPop, &dst); } #if defined(ASMJIT_X86) //! @brief Pop All General-Purpose Registers. //! //! Pop EDI, ESI, EBP, EBX, EDX, ECX, and EAX. inline void popad() { _emitInstruction(kX86InstPopAD); } #endif // ASMJIT_X86 //! @brief Pop Stack into EFLAGS Register (32-bit or 64-bit). inline void popf() { #if defined(ASMJIT_X86) popfd(); #else popfq(); #endif } #if defined(ASMJIT_X86) //! @brief Pop Stack into EFLAGS Register (32-bit). inline void popfd() { _emitInstruction(kX86InstPopFD); } #else //! @brief Pop Stack into EFLAGS Register (64-bit). inline void popfq() { _emitInstruction(kX86InstPopFQ); } #endif //! @brief Push WORD/DWORD/QWORD Onto the Stack. //! //! @note 32-bit architecture pushed DWORD while 64-bit //! pushes QWORD. 64-bit mode not provides instruction to //! push 32-bit register/memory. inline void push(const GpReg& src) { ASMJIT_ASSERT(src.isRegType(kX86RegTypeGpw) || src.isRegType(kX86RegTypeGpz)); _emitInstruction(kX86InstPush, &src); } //! @brief Push Segment Register Onto the Stack. inline void push(const SegmentReg& src) { _emitInstruction(kX86InstPush, &src); } //! @brief Push WORD/DWORD/QWORD Onto the Stack. inline void push(const Mem& src) { ASMJIT_ASSERT(src.getSize() == 2 || src.getSize() == sizeof(sysint_t)); _emitInstruction(kX86InstPush, &src); } //! @brief Push WORD/DWORD/QWORD Onto the Stack. inline void push(const Imm& src) { _emitInstruction(kX86InstPush, &src); } #if defined(ASMJIT_X86) //! @brief Push All General-Purpose Registers. //! //! Push EAX, ECX, EDX, EBX, original ESP, EBP, ESI, and EDI. inline void pushad() { _emitInstruction(kX86InstPushAD); } #endif // ASMJIT_X86 //! @brief Push EFLAGS Register (32-bit or 64-bit) onto the Stack. inline void pushf() { #if defined(ASMJIT_X86) pushfd(); #else pushfq(); #endif } #if defined(ASMJIT_X86) //! @brief Push EFLAGS Register (32-bit) onto the Stack. inline void pushfd() { _emitInstruction(kX86InstPushFD); } #else //! @brief Push EFLAGS Register (64-bit) onto the Stack. inline void pushfq() { _emitInstruction(kX86InstPushFQ); } #endif // ASMJIT_X86 //! @brief Rotate Bits Left. //! @note @a src register can be only @c cl. inline void rcl(const GpReg& dst, const GpReg& src) { _emitInstruction(kX86InstRcl, &dst, &src); } //! @brief Rotate Bits Left. inline void rcl(const GpReg& dst, const Imm& src) { _emitInstruction(kX86InstRcl, &dst, &src); } //! @brief Rotate Bits Left. //! @note @a src register can be only @c cl. inline void rcl(const Mem& dst, const GpReg& src) { _emitInstruction(kX86InstRcl, &dst, &src); } //! @brief Rotate Bits Left. inline void rcl(const Mem& dst, const Imm& src) { _emitInstruction(kX86InstRcl, &dst, &src); } //! @brief Rotate Bits Right. //! @note @a src register can be only @c cl. inline void rcr(const GpReg& dst, const GpReg& src) { _emitInstruction(kX86InstRcr, &dst, &src); } //! @brief Rotate Bits Right. inline void rcr(const GpReg& dst, const Imm& src) { _emitInstruction(kX86InstRcr, &dst, &src); } //! @brief Rotate Bits Right. //! @note @a src register can be only @c cl. inline void rcr(const Mem& dst, const GpReg& src) { _emitInstruction(kX86InstRcr, &dst, &src); } //! @brief Rotate Bits Right. inline void rcr(const Mem& dst, const Imm& src) { _emitInstruction(kX86InstRcr, &dst, &src); } //! @brief Read Time-Stamp Counter (Pentium). inline void rdtsc() { _emitInstruction(kX86InstRdtsc); } //! @brief Read Time-Stamp Counter and Processor ID (New). inline void rdtscp() { _emitInstruction(kX86InstRdtscP); } //! @brief Load ECX/RCX BYTEs from DS:[ESI/RSI] to AL. inline void rep_lodsb() { _emitInstruction(kX86InstRepLodSB); } //! @brief Load ECX/RCX DWORDs from DS:[ESI/RSI] to EAX. inline void rep_lodsd() { _emitInstruction(kX86InstRepLodSD); } #if defined(ASMJIT_X64) //! @brief Load ECX/RCX QWORDs from DS:[ESI/RSI] to RAX. inline void rep_lodsq() { _emitInstruction(kX86InstRepLodSQ); } #endif // ASMJIT_X64 //! @brief Load ECX/RCX WORDs from DS:[ESI/RSI] to AX. inline void rep_lodsw() { _emitInstruction(kX86InstRepLodSW); } //! @brief Move ECX/RCX BYTEs from DS:[ESI/RSI] to ES:[EDI/RDI]. inline void rep_movsb() { _emitInstruction(kX86InstRepMovSB); } //! @brief Move ECX/RCX DWORDs from DS:[ESI/RSI] to ES:[EDI/RDI]. inline void rep_movsd() { _emitInstruction(kX86InstRepMovSD); } #if defined(ASMJIT_X64) //! @brief Move ECX/RCX QWORDs from DS:[ESI/RSI] to ES:[EDI/RDI]. inline void rep_movsq() { _emitInstruction(kX86InstRepMovSQ); } #endif // ASMJIT_X64 //! @brief Move ECX/RCX WORDs from DS:[ESI/RSI] to ES:[EDI/RDI]. inline void rep_movsw() { _emitInstruction(kX86InstRepMovSW); } //! @brief Fill ECX/RCX BYTEs at ES:[EDI/RDI] with AL. inline void rep_stosb() { _emitInstruction(kX86InstRepStoSB); } //! @brief Fill ECX/RCX DWORDs at ES:[EDI/RDI] with EAX. inline void rep_stosd() { _emitInstruction(kX86InstRepStoSD); } #if defined(ASMJIT_X64) //! @brief Fill ECX/RCX QWORDs at ES:[EDI/RDI] with RAX. inline void rep_stosq() { _emitInstruction(kX86InstRepStoSQ); } #endif // ASMJIT_X64 //! @brief Fill ECX/RCX WORDs at ES:[EDI/RDI] with AX. inline void rep_stosw() { _emitInstruction(kX86InstRepStoSW); } //! @brief Repeated find nonmatching BYTEs in ES:[EDI/RDI] and DS:[ESI/RDI]. inline void repe_cmpsb() { _emitInstruction(kX86InstRepECmpSB); } //! @brief Repeated find nonmatching DWORDs in ES:[EDI/RDI] and DS:[ESI/RDI]. inline void repe_cmpsd() { _emitInstruction(kX86InstRepECmpSD); } #if defined(ASMJIT_X64) //! @brief Repeated find nonmatching QWORDs in ES:[EDI/RDI] and DS:[ESI/RDI]. inline void repe_cmpsq() { _emitInstruction(kX86InstRepECmpSQ); } #endif // ASMJIT_X64 //! @brief Repeated find nonmatching WORDs in ES:[EDI/RDI] and DS:[ESI/RDI]. inline void repe_cmpsw() { _emitInstruction(kX86InstRepECmpSW); } //! @brief Find non-AL BYTE starting at ES:[EDI/RDI]. inline void repe_scasb() { _emitInstruction(kX86InstRepEScaSB); } //! @brief Find non-EAX DWORD starting at ES:[EDI/RDI]. inline void repe_scasd() { _emitInstruction(kX86InstRepEScaSD); } #if defined(ASMJIT_X64) //! @brief Find non-RAX QWORD starting at ES:[EDI/RDI]. inline void repe_scasq() { _emitInstruction(kX86InstRepEScaSQ); } #endif // ASMJIT_X64 //! @brief Find non-AX WORD starting at ES:[EDI/RDI]. inline void repe_scasw() { _emitInstruction(kX86InstRepEScaSW); } //! @brief Repeated find nonmatching BYTEs in ES:[EDI/RDI] and DS:[ESI/RDI]. inline void repne_cmpsb() { _emitInstruction(kX86InstRepNECmpSB); } //! @brief Repeated find nonmatching DWORDs in ES:[EDI/RDI] and DS:[ESI/RDI]. inline void repne_cmpsd() { _emitInstruction(kX86InstRepNECmpSD); } #if defined(ASMJIT_X64) //! @brief Repeated find nonmatching QWORDs in ES:[EDI/RDI] and DS:[ESI/RDI]. inline void repne_cmpsq() { _emitInstruction(kX86InstRepNECmpSQ); } #endif // ASMJIT_X64 //! @brief Repeated find nonmatching WORDs in ES:[EDI/RDI] and DS:[ESI/RDI]. inline void repne_cmpsw() { _emitInstruction(kX86InstRepNECmpSW); } //! @brief Find AL, starting at ES:[EDI/RDI]. inline void repne_scasb() { _emitInstruction(kX86InstRepNEScaSB); } //! @brief Find EAX, starting at ES:[EDI/RDI]. inline void repne_scasd() { _emitInstruction(kX86InstRepNEScaSD); } #if defined(ASMJIT_X64) //! @brief Find RAX, starting at ES:[EDI/RDI]. inline void repne_scasq() { _emitInstruction(kX86InstRepNEScaSQ); } #endif // ASMJIT_X64 //! @brief Find AX, starting at ES:[EDI/RDI]. inline void repne_scasw() { _emitInstruction(kX86InstRepNEScaSW); } //! @brief Return from Procedure. inline void ret() { _emitInstruction(kX86InstRet); } //! @brief Return from Procedure. inline void ret(const Imm& imm16) { _emitInstruction(kX86InstRet, &imm16); } //! @brief Rotate Bits Left. //! @note @a src register can be only @c cl. inline void rol(const GpReg& dst, const GpReg& src) { _emitInstruction(kX86InstRol, &dst, &src); } //! @brief Rotate Bits Left. inline void rol(const GpReg& dst, const Imm& src) { _emitInstruction(kX86InstRol, &dst, &src); } //! @brief Rotate Bits Left. //! @note @a src register can be only @c cl. inline void rol(const Mem& dst, const GpReg& src) { _emitInstruction(kX86InstRol, &dst, &src); } //! @brief Rotate Bits Left. inline void rol(const Mem& dst, const Imm& src) { _emitInstruction(kX86InstRol, &dst, &src); } //! @brief Rotate Bits Right. //! @note @a src register can be only @c cl. inline void ror(const GpReg& dst, const GpReg& src) { _emitInstruction(kX86InstRor, &dst, &src); } //! @brief Rotate Bits Right. inline void ror(const GpReg& dst, const Imm& src) { _emitInstruction(kX86InstRor, &dst, &src); } //! @brief Rotate Bits Right. //! @note @a src register can be only @c cl. inline void ror(const Mem& dst, const GpReg& src) { _emitInstruction(kX86InstRor, &dst, &src); } //! @brief Rotate Bits Right. inline void ror(const Mem& dst, const Imm& src) { _emitInstruction(kX86InstRor, &dst, &src); } #if defined(ASMJIT_X86) //! @brief Store AH into Flags. inline void sahf() { _emitInstruction(kX86InstSahf); } #endif // ASMJIT_X86 //! @brief Integer subtraction with borrow. inline void sbb(const GpReg& dst, const GpReg& src) { _emitInstruction(kX86InstSbb, &dst, &src); } //! @brief Integer subtraction with borrow. inline void sbb(const GpReg& dst, const Mem& src) { _emitInstruction(kX86InstSbb, &dst, &src); } //! @brief Integer subtraction with borrow. inline void sbb(const GpReg& dst, const Imm& src) { _emitInstruction(kX86InstSbb, &dst, &src); } //! @brief Integer subtraction with borrow. inline void sbb(const Mem& dst, const GpReg& src) { _emitInstruction(kX86InstSbb, &dst, &src); } //! @brief Integer subtraction with borrow. inline void sbb(const Mem& dst, const Imm& src) { _emitInstruction(kX86InstSbb, &dst, &src); } //! @brief Shift Bits Left. //! @note @a src register can be only @c cl. inline void sal(const GpReg& dst, const GpReg& src) { _emitInstruction(kX86InstSal, &dst, &src); } //! @brief Shift Bits Left. inline void sal(const GpReg& dst, const Imm& src) { _emitInstruction(kX86InstSal, &dst, &src); } //! @brief Shift Bits Left. //! @note @a src register can be only @c cl. inline void sal(const Mem& dst, const GpReg& src) { _emitInstruction(kX86InstSal, &dst, &src); } //! @brief Shift Bits Left. inline void sal(const Mem& dst, const Imm& src) { _emitInstruction(kX86InstSal, &dst, &src); } //! @brief Shift Bits Right. //! @note @a src register can be only @c cl. inline void sar(const GpReg& dst, const GpReg& src) { _emitInstruction(kX86InstSar, &dst, &src); } //! @brief Shift Bits Right. inline void sar(const GpReg& dst, const Imm& src) { _emitInstruction(kX86InstSar, &dst, &src); } //! @brief Shift Bits Right. //! @note @a src register can be only @c cl. inline void sar(const Mem& dst, const GpReg& src) { _emitInstruction(kX86InstSar, &dst, &src); } //! @brief Shift Bits Right. inline void sar(const Mem& dst, const Imm& src) { _emitInstruction(kX86InstSar, &dst, &src); } //! @brief Set Byte on Condition. inline void set(kX86Cond cc, const GpReg& dst) { ASMJIT_ASSERT(dst.getSize() == 1); _emitInstruction(X86Util::getSetccInstFromCond(cc), &dst); } //! @brief Set Byte on Condition. inline void set(kX86Cond cc, const Mem& dst) { ASMJIT_ASSERT(dst.getSize() <= 1); _emitInstruction(X86Util::getSetccInstFromCond(cc), &dst); } //! @brief Set Byte on Condition. inline void seta (const GpReg& dst) { ASMJIT_ASSERT(dst.getSize() == 1); _emitInstruction(kX86InstSetA , &dst); } //! @brief Set Byte on Condition. inline void seta (const Mem& dst) { ASMJIT_ASSERT(dst.getSize() <= 1); _emitInstruction(kX86InstSetA , &dst); } //! @brief Set Byte on Condition. inline void setae (const GpReg& dst) { ASMJIT_ASSERT(dst.getSize() == 1); _emitInstruction(kX86InstSetAE , &dst); } //! @brief Set Byte on Condition. inline void setae (const Mem& dst) { ASMJIT_ASSERT(dst.getSize() <= 1); _emitInstruction(kX86InstSetAE , &dst); } //! @brief Set Byte on Condition. inline void setb (const GpReg& dst) { ASMJIT_ASSERT(dst.getSize() == 1); _emitInstruction(kX86InstSetB , &dst); } //! @brief Set Byte on Condition. inline void setb (const Mem& dst) { ASMJIT_ASSERT(dst.getSize() <= 1); _emitInstruction(kX86InstSetB , &dst); } //! @brief Set Byte on Condition. inline void setbe (const GpReg& dst) { ASMJIT_ASSERT(dst.getSize() == 1); _emitInstruction(kX86InstSetBE , &dst); } //! @brief Set Byte on Condition. inline void setbe (const Mem& dst) { ASMJIT_ASSERT(dst.getSize() <= 1); _emitInstruction(kX86InstSetBE , &dst); } //! @brief Set Byte on Condition. inline void setc (const GpReg& dst) { ASMJIT_ASSERT(dst.getSize() == 1); _emitInstruction(kX86InstSetC , &dst); } //! @brief Set Byte on Condition. inline void setc (const Mem& dst) { ASMJIT_ASSERT(dst.getSize() <= 1); _emitInstruction(kX86InstSetC , &dst); } //! @brief Set Byte on Condition. inline void sete (const GpReg& dst) { ASMJIT_ASSERT(dst.getSize() == 1); _emitInstruction(kX86InstSetE , &dst); } //! @brief Set Byte on Condition. inline void sete (const Mem& dst) { ASMJIT_ASSERT(dst.getSize() <= 1); _emitInstruction(kX86InstSetE , &dst); } //! @brief Set Byte on Condition. inline void setg (const GpReg& dst) { ASMJIT_ASSERT(dst.getSize() == 1); _emitInstruction(kX86InstSetG , &dst); } //! @brief Set Byte on Condition. inline void setg (const Mem& dst) { ASMJIT_ASSERT(dst.getSize() <= 1); _emitInstruction(kX86InstSetG , &dst); } //! @brief Set Byte on Condition. inline void setge (const GpReg& dst) { ASMJIT_ASSERT(dst.getSize() == 1); _emitInstruction(kX86InstSetGE , &dst); } //! @brief Set Byte on Condition. inline void setge (const Mem& dst) { ASMJIT_ASSERT(dst.getSize() <= 1); _emitInstruction(kX86InstSetGE , &dst); } //! @brief Set Byte on Condition. inline void setl (const GpReg& dst) { ASMJIT_ASSERT(dst.getSize() == 1); _emitInstruction(kX86InstSetL , &dst); } //! @brief Set Byte on Condition. inline void setl (const Mem& dst) { ASMJIT_ASSERT(dst.getSize() <= 1); _emitInstruction(kX86InstSetL , &dst); } //! @brief Set Byte on Condition. inline void setle (const GpReg& dst) { ASMJIT_ASSERT(dst.getSize() == 1); _emitInstruction(kX86InstSetLE , &dst); } //! @brief Set Byte on Condition. inline void setle (const Mem& dst) { ASMJIT_ASSERT(dst.getSize() <= 1); _emitInstruction(kX86InstSetLE , &dst); } //! @brief Set Byte on Condition. inline void setna (const GpReg& dst) { ASMJIT_ASSERT(dst.getSize() == 1); _emitInstruction(kX86InstSetNA , &dst); } //! @brief Set Byte on Condition. inline void setna (const Mem& dst) { ASMJIT_ASSERT(dst.getSize() <= 1); _emitInstruction(kX86InstSetNA , &dst); } //! @brief Set Byte on Condition. inline void setnae(const GpReg& dst) { ASMJIT_ASSERT(dst.getSize() == 1); _emitInstruction(kX86InstSetNAE, &dst); } //! @brief Set Byte on Condition. inline void setnae(const Mem& dst) { ASMJIT_ASSERT(dst.getSize() <= 1); _emitInstruction(kX86InstSetNAE, &dst); } //! @brief Set Byte on Condition. inline void setnb (const GpReg& dst) { ASMJIT_ASSERT(dst.getSize() == 1); _emitInstruction(kX86InstSetNB , &dst); } //! @brief Set Byte on Condition. inline void setnb (const Mem& dst) { ASMJIT_ASSERT(dst.getSize() <= 1); _emitInstruction(kX86InstSetNB , &dst); } //! @brief Set Byte on Condition. inline void setnbe(const GpReg& dst) { ASMJIT_ASSERT(dst.getSize() == 1); _emitInstruction(kX86InstSetNBE, &dst); } //! @brief Set Byte on Condition. inline void setnbe(const Mem& dst) { ASMJIT_ASSERT(dst.getSize() <= 1); _emitInstruction(kX86InstSetNBE, &dst); } //! @brief Set Byte on Condition. inline void setnc (const GpReg& dst) { ASMJIT_ASSERT(dst.getSize() == 1); _emitInstruction(kX86InstSetNC , &dst); } //! @brief Set Byte on Condition. inline void setnc (const Mem& dst) { ASMJIT_ASSERT(dst.getSize() <= 1); _emitInstruction(kX86InstSetNC , &dst); } //! @brief Set Byte on Condition. inline void setne (const GpReg& dst) { ASMJIT_ASSERT(dst.getSize() == 1); _emitInstruction(kX86InstSetNE , &dst); } //! @brief Set Byte on Condition. inline void setne (const Mem& dst) { ASMJIT_ASSERT(dst.getSize() <= 1); _emitInstruction(kX86InstSetNE , &dst); } //! @brief Set Byte on Condition. inline void setng (const GpReg& dst) { ASMJIT_ASSERT(dst.getSize() == 1); _emitInstruction(kX86InstSetNG , &dst); } //! @brief Set Byte on Condition. inline void setng (const Mem& dst) { ASMJIT_ASSERT(dst.getSize() <= 1); _emitInstruction(kX86InstSetNG , &dst); } //! @brief Set Byte on Condition. inline void setnge(const GpReg& dst) { ASMJIT_ASSERT(dst.getSize() == 1); _emitInstruction(kX86InstSetNGE, &dst); } //! @brief Set Byte on Condition. inline void setnge(const Mem& dst) { ASMJIT_ASSERT(dst.getSize() <= 1); _emitInstruction(kX86InstSetNGE, &dst); } //! @brief Set Byte on Condition. inline void setnl (const GpReg& dst) { ASMJIT_ASSERT(dst.getSize() == 1); _emitInstruction(kX86InstSetNL , &dst); } //! @brief Set Byte on Condition. inline void setnl (const Mem& dst) { ASMJIT_ASSERT(dst.getSize() <= 1); _emitInstruction(kX86InstSetNL , &dst); } //! @brief Set Byte on Condition. inline void setnle(const GpReg& dst) { ASMJIT_ASSERT(dst.getSize() == 1); _emitInstruction(kX86InstSetNLE, &dst); } //! @brief Set Byte on Condition. inline void setnle(const Mem& dst) { ASMJIT_ASSERT(dst.getSize() <= 1); _emitInstruction(kX86InstSetNLE, &dst); } //! @brief Set Byte on Condition. inline void setno (const GpReg& dst) { ASMJIT_ASSERT(dst.getSize() == 1); _emitInstruction(kX86InstSetNO , &dst); } //! @brief Set Byte on Condition. inline void setno (const Mem& dst) { ASMJIT_ASSERT(dst.getSize() <= 1); _emitInstruction(kX86InstSetNO , &dst); } //! @brief Set Byte on Condition. inline void setnp (const GpReg& dst) { ASMJIT_ASSERT(dst.getSize() == 1); _emitInstruction(kX86InstSetNP , &dst); } //! @brief Set Byte on Condition. inline void setnp (const Mem& dst) { ASMJIT_ASSERT(dst.getSize() <= 1); _emitInstruction(kX86InstSetNP , &dst); } //! @brief Set Byte on Condition. inline void setns (const GpReg& dst) { ASMJIT_ASSERT(dst.getSize() == 1); _emitInstruction(kX86InstSetNS , &dst); } //! @brief Set Byte on Condition. inline void setns (const Mem& dst) { ASMJIT_ASSERT(dst.getSize() <= 1); _emitInstruction(kX86InstSetNS , &dst); } //! @brief Set Byte on Condition. inline void setnz (const GpReg& dst) { ASMJIT_ASSERT(dst.getSize() == 1); _emitInstruction(kX86InstSetNZ , &dst); } //! @brief Set Byte on Condition. inline void setnz (const Mem& dst) { ASMJIT_ASSERT(dst.getSize() <= 1); _emitInstruction(kX86InstSetNZ , &dst); } //! @brief Set Byte on Condition. inline void seto (const GpReg& dst) { ASMJIT_ASSERT(dst.getSize() == 1); _emitInstruction(kX86InstSetO , &dst); } //! @brief Set Byte on Condition. inline void seto (const Mem& dst) { ASMJIT_ASSERT(dst.getSize() <= 1); _emitInstruction(kX86InstSetO , &dst); } //! @brief Set Byte on Condition. inline void setp (const GpReg& dst) { ASMJIT_ASSERT(dst.getSize() == 1); _emitInstruction(kX86InstSetP , &dst); } //! @brief Set Byte on Condition. inline void setp (const Mem& dst) { ASMJIT_ASSERT(dst.getSize() <= 1); _emitInstruction(kX86InstSetP , &dst); } //! @brief Set Byte on Condition. inline void setpe (const GpReg& dst) { ASMJIT_ASSERT(dst.getSize() == 1); _emitInstruction(kX86InstSetPE , &dst); } //! @brief Set Byte on Condition. inline void setpe (const Mem& dst) { ASMJIT_ASSERT(dst.getSize() <= 1); _emitInstruction(kX86InstSetPE , &dst); } //! @brief Set Byte on Condition. inline void setpo (const GpReg& dst) { ASMJIT_ASSERT(dst.getSize() == 1); _emitInstruction(kX86InstSetPO , &dst); } //! @brief Set Byte on Condition. inline void setpo (const Mem& dst) { ASMJIT_ASSERT(dst.getSize() <= 1); _emitInstruction(kX86InstSetPO , &dst); } //! @brief Set Byte on Condition. inline void sets (const GpReg& dst) { ASMJIT_ASSERT(dst.getSize() == 1); _emitInstruction(kX86InstSetS , &dst); } //! @brief Set Byte on Condition. inline void sets (const Mem& dst) { ASMJIT_ASSERT(dst.getSize() <= 1); _emitInstruction(kX86InstSetS , &dst); } //! @brief Set Byte on Condition. inline void setz (const GpReg& dst) { ASMJIT_ASSERT(dst.getSize() == 1); _emitInstruction(kX86InstSetZ , &dst); } //! @brief Set Byte on Condition. inline void setz (const Mem& dst) { ASMJIT_ASSERT(dst.getSize() <= 1); _emitInstruction(kX86InstSetZ , &dst); } //! @brief Shift Bits Left. //! @note @a src register can be only @c cl. inline void shl(const GpReg& dst, const GpReg& src) { _emitInstruction(kX86InstShl, &dst, &src); } //! @brief Shift Bits Left. inline void shl(const GpReg& dst, const Imm& src) { _emitInstruction(kX86InstShl, &dst, &src); } //! @brief Shift Bits Left. //! @note @a src register can be only @c cl. inline void shl(const Mem& dst, const GpReg& src) { _emitInstruction(kX86InstShl, &dst, &src); } //! @brief Shift Bits Left. inline void shl(const Mem& dst, const Imm& src) { _emitInstruction(kX86InstShl, &dst, &src); } //! @brief Shift Bits Right. //! @note @a src register can be only @c cl. inline void shr(const GpReg& dst, const GpReg& src) { _emitInstruction(kX86InstShr, &dst, &src); } //! @brief Shift Bits Right. inline void shr(const GpReg& dst, const Imm& src) { _emitInstruction(kX86InstShr, &dst, &src); } //! @brief Shift Bits Right. //! @note @a src register can be only @c cl. inline void shr(const Mem& dst, const GpReg& src) { _emitInstruction(kX86InstShr, &dst, &src); } //! @brief Shift Bits Right. inline void shr(const Mem& dst, const Imm& src) { _emitInstruction(kX86InstShr, &dst, &src); } //! @brief Double Precision Shift Left. //! @note src2 register can be only @c cl register. inline void shld(const GpReg& dst, const GpReg& src1, const GpReg& src2) { _emitInstruction(kX86InstShld, &dst, &src1, &src2); } //! @brief Double Precision Shift Left. inline void shld(const GpReg& dst, const GpReg& src1, const Imm& src2) { _emitInstruction(kX86InstShld, &dst, &src1, &src2); } //! @brief Double Precision Shift Left. //! @note src2 register can be only @c cl register. inline void shld(const Mem& dst, const GpReg& src1, const GpReg& src2) { _emitInstruction(kX86InstShld, &dst, &src1, &src2); } //! @brief Double Precision Shift Left. inline void shld(const Mem& dst, const GpReg& src1, const Imm& src2) { _emitInstruction(kX86InstShld, &dst, &src1, &src2); } //! @brief Double Precision Shift Right. //! @note src2 register can be only @c cl register. inline void shrd(const GpReg& dst, const GpReg& src1, const GpReg& src2) { _emitInstruction(kX86InstShrd, &dst, &src1, &src2); } //! @brief Double Precision Shift Right. inline void shrd(const GpReg& dst, const GpReg& src1, const Imm& src2) { _emitInstruction(kX86InstShrd, &dst, &src1, &src2); } //! @brief Double Precision Shift Right. //! @note src2 register can be only @c cl register. inline void shrd(const Mem& dst, const GpReg& src1, const GpReg& src2) { _emitInstruction(kX86InstShrd, &dst, &src1, &src2); } //! @brief Double Precision Shift Right. inline void shrd(const Mem& dst, const GpReg& src1, const Imm& src2) { _emitInstruction(kX86InstShrd, &dst, &src1, &src2); } //! @brief Set Carry Flag to 1. inline void stc() { _emitInstruction(kX86InstStc); } //! @brief Set Direction Flag to 1. inline void std() { _emitInstruction(kX86InstStd); } //! @brief Subtract. inline void sub(const GpReg& dst, const GpReg& src) { _emitInstruction(kX86InstSub, &dst, &src); } //! @brief Subtract. inline void sub(const GpReg& dst, const Mem& src) { _emitInstruction(kX86InstSub, &dst, &src); } //! @brief Subtract. inline void sub(const GpReg& dst, const Imm& src) { _emitInstruction(kX86InstSub, &dst, &src); } //! @brief Subtract. inline void sub(const Mem& dst, const GpReg& src) { _emitInstruction(kX86InstSub, &dst, &src); } //! @brief Subtract. inline void sub(const Mem& dst, const Imm& src) { _emitInstruction(kX86InstSub, &dst, &src); } //! @brief Logical Compare. inline void test(const GpReg& op1, const GpReg& op2) { _emitInstruction(kX86InstTest, &op1, &op2); } //! @brief Logical Compare. inline void test(const GpReg& op1, const Imm& op2) { _emitInstruction(kX86InstTest, &op1, &op2); } //! @brief Logical Compare. inline void test(const Mem& op1, const GpReg& op2) { _emitInstruction(kX86InstTest, &op1, &op2); } //! @brief Logical Compare. inline void test(const Mem& op1, const Imm& op2) { _emitInstruction(kX86InstTest, &op1, &op2); } //! @brief Undefined instruction - Raise invalid opcode exception. inline void ud2() { _emitInstruction(kX86InstUd2); } //! @brief Exchange and Add. inline void xadd(const GpReg& dst, const GpReg& src) { _emitInstruction(kX86InstXadd, &dst, &src); } //! @brief Exchange and Add. inline void xadd(const Mem& dst, const GpReg& src) { _emitInstruction(kX86InstXadd, &dst, &src); } //! @brief Exchange Register/Memory with Register. inline void xchg(const GpReg& dst, const GpReg& src) { _emitInstruction(kX86InstXchg, &dst, &src); } //! @brief Exchange Register/Memory with Register. inline void xchg(const Mem& dst, const GpReg& src) { _emitInstruction(kX86InstXchg, &dst, &src); } //! @brief Exchange Register/Memory with Register. inline void xchg(const GpReg& dst, const Mem& src) { _emitInstruction(kX86InstXchg, &src, &dst); } //! @brief Exchange Register/Memory with Register. inline void xor_(const GpReg& dst, const GpReg& src) { _emitInstruction(kX86InstXor, &dst, &src); } //! @brief Exchange Register/Memory with Register. inline void xor_(const GpReg& dst, const Mem& src) { _emitInstruction(kX86InstXor, &dst, &src); } //! @brief Exchange Register/Memory with Register. inline void xor_(const GpReg& dst, const Imm& src) { _emitInstruction(kX86InstXor, &dst, &src); } //! @brief Exchange Register/Memory with Register. inline void xor_(const Mem& dst, const GpReg& src) { _emitInstruction(kX86InstXor, &dst, &src); } //! @brief Exchange Register/Memory with Register. inline void xor_(const Mem& dst, const Imm& src) { _emitInstruction(kX86InstXor, &dst, &src); } // -------------------------------------------------------------------------- // [X87 Instructions (FPU)] // -------------------------------------------------------------------------- //! @brief Compute 2^x - 1 (FPU). inline void f2xm1() { _emitInstruction(kX86InstF2XM1); } //! @brief Absolute Value of st(0) (FPU). inline void fabs() { _emitInstruction(kX86InstFAbs); } //! @brief Add @a src to @a dst and store result in @a dst (FPU). //! //! @note One of dst or src must be st(0). inline void fadd(const X87Reg& dst, const X87Reg& src) { ASMJIT_ASSERT(dst.getRegIndex() == 0 || src.getRegIndex() == 0); _emitInstruction(kX86InstFAdd, &dst, &src); } //! @brief Add @a src to st(0) and store result in st(0) (FPU). //! //! @note SP-FP or DP-FP determined by @a adr size. inline void fadd(const Mem& src) { _emitInstruction(kX86InstFAdd, &src); } //! @brief Add st(0) to @a dst and POP register stack (FPU). inline void faddp(const X87Reg& dst = st(1)) { _emitInstruction(kX86InstFAddP, &dst); } //! @brief Load Binary Coded Decimal (FPU). inline void fbld(const Mem& src) { _emitInstruction(kX86InstFBLd, &src); } //! @brief Store BCD Integer and Pop (FPU). inline void fbstp(const Mem& dst) { _emitInstruction(kX86InstFBStP, &dst); } //! @brief Change st(0) Sign (FPU). inline void fchs() { _emitInstruction(kX86InstFCHS); } //! @brief Clear Exceptions (FPU). //! //! Clear floating-point exception flags after checking for pending unmasked //! floating-point exceptions. //! //! Clears the floating-point exception flags (PE, UE, OE, ZE, DE, and IE), //! the exception summary status flag (ES), the stack fault flag (SF), and //! the busy flag (B) in the FPU status word. The FCLEX instruction checks //! for and handles any pending unmasked floating-point exceptions before //! clearing the exception flags. inline void fclex() { _emitInstruction(kX86InstFClex); } //! @brief FP Conditional Move (FPU). inline void fcmovb(const X87Reg& src) { _emitInstruction(kX86InstFCMovB, &src); } //! @brief FP Conditional Move (FPU). inline void fcmovbe(const X87Reg& src) { _emitInstruction(kX86InstFCMovBE, &src); } //! @brief FP Conditional Move (FPU). inline void fcmove(const X87Reg& src) { _emitInstruction(kX86InstFCMovE, &src); } //! @brief FP Conditional Move (FPU). inline void fcmovnb(const X87Reg& src) { _emitInstruction(kX86InstFCMovNB, &src); } //! @brief FP Conditional Move (FPU). inline void fcmovnbe(const X87Reg& src) { _emitInstruction(kX86InstFCMovNBE, &src); } //! @brief FP Conditional Move (FPU). inline void fcmovne(const X87Reg& src) { _emitInstruction(kX86InstFCMovNE, &src); } //! @brief FP Conditional Move (FPU). inline void fcmovnu(const X87Reg& src) { _emitInstruction(kX86InstFCMovNU, &src); } //! @brief FP Conditional Move (FPU). inline void fcmovu(const X87Reg& src) { _emitInstruction(kX86InstFCMovU, &src); } //! @brief Compare st(0) with @a reg (FPU). inline void fcom(const X87Reg& reg = st(1)) { _emitInstruction(kX86InstFCom, ®); } //! @brief Compare st(0) with 4-byte or 8-byte FP at @a src (FPU). inline void fcom(const Mem& src) { _emitInstruction(kX86InstFCom, &src); } //! @brief Compare st(0) with @a reg and pop the stack (FPU). inline void fcomp(const X87Reg& reg = st(1)) { _emitInstruction(kX86InstFComP, ®); } //! @brief Compare st(0) with 4-byte or 8-byte FP at @a adr and pop the //! stack (FPU). inline void fcomp(const Mem& mem) { _emitInstruction(kX86InstFComP, &mem); } //! @brief Compare st(0) with st(1) and pop register stack twice (FPU). inline void fcompp() { _emitInstruction(kX86InstFComPP); } //! @brief Compare st(0) and @a reg and Set EFLAGS (FPU). inline void fcomi(const X87Reg& reg) { _emitInstruction(kX86InstFComI, ®); } //! @brief Compare st(0) and @a reg and Set EFLAGS and pop the stack (FPU). inline void fcomip(const X87Reg& reg) { _emitInstruction(kX86InstFComIP, ®); } //! @brief Cosine (FPU). //! //! This instruction calculates the cosine of the source operand in //! register st(0) and stores the result in st(0). inline void fcos() { _emitInstruction(kX86InstFCos); } //! @brief Decrement Stack-Top Pointer (FPU). //! //! Subtracts one from the TOP field of the FPU status word (decrements //! the top-ofstack pointer). If the TOP field contains a 0, it is set //! to 7. The effect of this instruction is to rotate the stack by one //! position. The contents of the FPU data registers and tag register //! are not affected. inline void fdecstp() { _emitInstruction(kX86InstFDecStP); } //! @brief Divide @a dst by @a src (FPU). //! //! @note One of @a dst or @a src register must be st(0). inline void fdiv(const X87Reg& dst, const X87Reg& src) { ASMJIT_ASSERT(dst.getRegIndex() == 0 || src.getRegIndex() == 0); _emitInstruction(kX86InstFDiv, &dst, &src); } //! @brief Divide st(0) by 32-bit or 64-bit FP value (FPU). inline void fdiv(const Mem& src) { _emitInstruction(kX86InstFDiv, &src); } //! @brief Divide @a reg by st(0) (FPU). inline void fdivp(const X87Reg& reg = st(1)) { _emitInstruction(kX86InstFDivP, ®); } //! @brief Reverse Divide @a dst by @a src (FPU). //! //! @note One of @a dst or @a src register must be st(0). inline void fdivr(const X87Reg& dst, const X87Reg& src) { ASMJIT_ASSERT(dst.getRegIndex() == 0 || src.getRegIndex() == 0); _emitInstruction(kX86InstFDivR, &dst, &src); } //! @brief Reverse Divide st(0) by 32-bit or 64-bit FP value (FPU). inline void fdivr(const Mem& src) { _emitInstruction(kX86InstFDivR, &src); } //! @brief Reverse Divide @a reg by st(0) (FPU). inline void fdivrp(const X87Reg& reg = st(1)) { _emitInstruction(kX86InstFDivRP, ®); } //! @brief Free Floating-Point Register (FPU). //! //! Sets the tag in the FPU tag register associated with register @a reg //! to empty (11B). The contents of @a reg and the FPU stack-top pointer //! (TOP) are not affected. inline void ffree(const X87Reg& reg) { _emitInstruction(kX86InstFFree, ®); } //! @brief Add 16-bit or 32-bit integer to st(0) (FPU). inline void fiadd(const Mem& src) { ASMJIT_ASSERT(src.getSize() == 2 || src.getSize() == 4); _emitInstruction(kX86InstFIAdd, &src); } //! @brief Compare st(0) with 16-bit or 32-bit Integer (FPU). inline void ficom(const Mem& src) { ASMJIT_ASSERT(src.getSize() == 2 || src.getSize() == 4); _emitInstruction(kX86InstFICom, &src); } //! @brief Compare st(0) with 16-bit or 32-bit Integer and pop the stack (FPU). inline void ficomp(const Mem& src) { ASMJIT_ASSERT(src.getSize() == 2 || src.getSize() == 4); _emitInstruction(kX86InstFIComP, &src); } //! @brief Divide st(0) by 32-bit or 16-bit integer (@a src) (FPU). inline void fidiv(const Mem& src) { ASMJIT_ASSERT(src.getSize() == 2 || src.getSize() == 4); _emitInstruction(kX86InstFIDiv, &src); } //! @brief Reverse Divide st(0) by 32-bit or 16-bit integer (@a src) (FPU). inline void fidivr(const Mem& src) { ASMJIT_ASSERT(src.getSize() == 2 || src.getSize() == 4); _emitInstruction(kX86InstFIDivR, &src); } //! @brief Load 16-bit, 32-bit or 64-bit Integer and push it to the stack (FPU). //! //! Converts the signed-integer source operand into double extended-precision //! floating point format and pushes the value onto the FPU register stack. //! The source operand can be a word, doubleword, or quadword integer. It is //! loaded without rounding errors. The sign of the source operand is //! preserved. inline void fild(const Mem& src) { ASMJIT_ASSERT(src.getSize() == 2 || src.getSize() == 4 || src.getSize() == 8); _emitInstruction(kX86InstFILd, &src); } //! @brief Multiply st(0) by 16-bit or 32-bit integer and store it //! to st(0) (FPU). inline void fimul(const Mem& src) { ASMJIT_ASSERT(src.getSize() == 2 || src.getSize() == 4); _emitInstruction(kX86InstFIMul, &src); } //! @brief Increment Stack-Top Pointer (FPU). //! //! Adds one to the TOP field of the FPU status word (increments the //! top-of-stack pointer). If the TOP field contains a 7, it is set to 0. //! The effect of this instruction is to rotate the stack by one position. //! The contents of the FPU data registers and tag register are not affected. //! This operation is not equivalent to popping the stack, because the tag //! for the previous top-of-stack register is not marked empty. inline void fincstp() { _emitInstruction(kX86InstFIncStP); } //! @brief Initialize Floating-Point Unit (FPU). //! //! Initialize FPU after checking for pending unmasked floating-point //! exceptions. inline void finit() { _emitInstruction(kX86InstFInit); } //! @brief Subtract 16-bit or 32-bit integer from st(0) and store result to //! st(0) (FPU). inline void fisub(const Mem& src) { ASMJIT_ASSERT(src.getSize() == 2 || src.getSize() == 4); _emitInstruction(kX86InstFISub, &src); } //! @brief Reverse Subtract 16-bit or 32-bit integer from st(0) and //! store result to st(0) (FPU). inline void fisubr(const Mem& src) { ASMJIT_ASSERT(src.getSize() == 2 || src.getSize() == 4); _emitInstruction(kX86InstFISubR, &src); } //! @brief Initialize Floating-Point Unit (FPU). //! //! Initialize FPU without checking for pending unmasked floating-point //! exceptions. inline void fninit() { _emitInstruction(kX86InstFNInit); } //! @brief Store st(0) as 16-bit or 32-bit Integer to @a dst (FPU). inline void fist(const Mem& dst) { ASMJIT_ASSERT(dst.getSize() == 2 || dst.getSize() == 4); _emitInstruction(kX86InstFISt, &dst); } //! @brief Store st(0) as 16-bit, 32-bit or 64-bit Integer to @a dst and pop //! stack (FPU). inline void fistp(const Mem& dst) { ASMJIT_ASSERT(dst.getSize() == 2 || dst.getSize() == 4 || dst.getSize() == 8); _emitInstruction(kX86InstFIStP, &dst); } //! @brief Push 32-bit, 64-bit or 80-bit Floating Point Value onto the FPU //! register stack (FPU). inline void fld(const Mem& src) { ASMJIT_ASSERT(src.getSize() == 4 || src.getSize() == 8 || src.getSize() == 10); _emitInstruction(kX86InstFLd, &src); } //! @brief Push @a reg onto the FPU register stack (FPU). inline void fld(const X87Reg& reg) { _emitInstruction(kX86InstFLd, ®); } //! @brief Push +1.0 onto the FPU register stack (FPU). inline void fld1() { _emitInstruction(kX86InstFLd1); } //! @brief Push log2(10) onto the FPU register stack (FPU). inline void fldl2t() { _emitInstruction(kX86InstFLdL2T); } //! @brief Push log2(e) onto the FPU register stack (FPU). inline void fldl2e() { _emitInstruction(kX86InstFLdL2E); } //! @brief Push pi onto the FPU register stack (FPU). inline void fldpi() { _emitInstruction(kX86InstFLdPi); } //! @brief Push log10(2) onto the FPU register stack (FPU). inline void fldlg2() { _emitInstruction(kX86InstFLdLg2); } //! @brief Push ln(2) onto the FPU register stack (FPU). inline void fldln2() { _emitInstruction(kX86InstFLdLn2); } //! @brief Push +0.0 onto the FPU register stack (FPU). inline void fldz() { _emitInstruction(kX86InstFLdZ); } //! @brief Load x87 FPU Control Word (2 bytes) (FPU). inline void fldcw(const Mem& src) { _emitInstruction(kX86InstFLdCw, &src); } //! @brief Load x87 FPU Environment (14 or 28 bytes) (FPU). inline void fldenv(const Mem& src) { _emitInstruction(kX86InstFLdEnv, &src); } //! @brief Multiply @a dst by @a src and store result in @a dst (FPU). //! //! @note One of dst or src must be st(0). inline void fmul(const X87Reg& dst, const X87Reg& src) { ASMJIT_ASSERT(dst.getRegIndex() == 0 || src.getRegIndex() == 0); _emitInstruction(kX86InstFMul, &dst, &src); } //! @brief Multiply st(0) by @a src and store result in st(0) (FPU). //! //! @note SP-FP or DP-FP determined by @a adr size. inline void fmul(const Mem& src) { _emitInstruction(kX86InstFMul, &src); } //! @brief Multiply st(0) by @a dst and POP register stack (FPU). inline void fmulp(const X87Reg& dst = st(1)) { _emitInstruction(kX86InstFMulP, &dst); } //! @brief Clear Exceptions (FPU). //! //! Clear floating-point exception flags without checking for pending //! unmasked floating-point exceptions. //! //! Clears the floating-point exception flags (PE, UE, OE, ZE, DE, and IE), //! the exception summary status flag (ES), the stack fault flag (SF), and //! the busy flag (B) in the FPU status word. The FCLEX instruction does //! not checks for and handles any pending unmasked floating-point exceptions //! before clearing the exception flags. inline void fnclex() { _emitInstruction(kX86InstFNClex); } //! @brief No Operation (FPU). inline void fnop() { _emitInstruction(kX86InstFNop); } //! @brief Save FPU State (FPU). //! //! Store FPU environment to m94byte or m108byte without //! checking for pending unmasked FP exceptions. //! Then re-initialize the FPU. inline void fnsave(const Mem& dst) { _emitInstruction(kX86InstFNSave, &dst); } //! @brief Store x87 FPU Environment (FPU). //! //! Store FPU environment to @a dst (14 or 28 Bytes) without checking for //! pending unmasked floating-point exceptions. Then mask all floating //! point exceptions. inline void fnstenv(const Mem& dst) { _emitInstruction(kX86InstFNStEnv, &dst); } //! @brief Store x87 FPU Control Word (FPU). //! //! Store FPU control word to @a dst (2 Bytes) without checking for pending //! unmasked floating-point exceptions. inline void fnstcw(const Mem& dst) { _emitInstruction(kX86InstFNStCw, &dst); } //! @brief Store x87 FPU Status Word (2 Bytes) (FPU). inline void fnstsw(const GpReg& dst) { ASMJIT_ASSERT(dst.isRegCode(kX86RegAx)); _emitInstruction(kX86InstFNStSw, &dst); } //! @brief Store x87 FPU Status Word (2 Bytes) (FPU). inline void fnstsw(const Mem& dst) { _emitInstruction(kX86InstFNStSw, &dst); } //! @brief Partial Arctangent (FPU). //! //! Replace st(1) with arctan(st(1)/st(0)) and pop the register stack. inline void fpatan() { _emitInstruction(kX86InstFPAtan); } //! @brief Partial Remainder (FPU). //! //! Replace st(0) with the remainder obtained from dividing st(0) by st(1). inline void fprem() { _emitInstruction(kX86InstFPRem); } //! @brief Partial Remainder (FPU). //! //! Replace st(0) with the IEEE remainder obtained from dividing st(0) by //! st(1). inline void fprem1() { _emitInstruction(kX86InstFPRem1); } //! @brief Partial Tangent (FPU). //! //! Replace st(0) with its tangent and push 1 onto the FPU stack. inline void fptan() { _emitInstruction(kX86InstFPTan); } //! @brief Round to Integer (FPU). //! //! Rount st(0) to an Integer. inline void frndint() { _emitInstruction(kX86InstFRndInt); } //! @brief Restore FPU State (FPU). //! //! Load FPU state from src (94 or 108 bytes). inline void frstor(const Mem& src) { _emitInstruction(kX86InstFRstor, &src); } //! @brief Save FPU State (FPU). //! //! Store FPU state to 94 or 108-bytes after checking for //! pending unmasked FP exceptions. Then reinitialize //! the FPU. inline void fsave(const Mem& dst) { _emitInstruction(kX86InstFSave, &dst); } //! @brief Scale (FPU). //! //! Scale st(0) by st(1). inline void fscale() { _emitInstruction(kX86InstFScale); } //! @brief Sine (FPU). //! //! This instruction calculates the sine of the source operand in //! register st(0) and stores the result in st(0). inline void fsin() { _emitInstruction(kX86InstFSin); } //! @brief Sine and Cosine (FPU). //! //! Compute the sine and cosine of st(0); replace st(0) with //! the sine, and push the cosine onto the register stack. inline void fsincos() { _emitInstruction(kX86InstFSinCos); } //! @brief Square Root (FPU). //! //! Calculates square root of st(0) and stores the result in st(0). inline void fsqrt() { _emitInstruction(kX86InstFSqrt); } //! @brief Store Floating Point Value (FPU). //! //! Store st(0) as 32-bit or 64-bit floating point value to @a dst. inline void fst(const Mem& dst) { ASMJIT_ASSERT(dst.getSize() == 4 || dst.getSize() == 8); _emitInstruction(kX86InstFSt, &dst); } //! @brief Store Floating Point Value (FPU). //! //! Store st(0) to @a reg. inline void fst(const X87Reg& reg) { _emitInstruction(kX86InstFSt, ®); } //! @brief Store Floating Point Value and Pop Register Stack (FPU). //! //! Store st(0) as 32-bit or 64-bit floating point value to @a dst //! and pop register stack. inline void fstp(const Mem& dst) { ASMJIT_ASSERT(dst.getSize() == 4 || dst.getSize() == 8 || dst.getSize() == 10); _emitInstruction(kX86InstFStP, &dst); } //! @brief Store Floating Point Value and Pop Register Stack (FPU). //! //! Store st(0) to @a reg and pop register stack. inline void fstp(const X87Reg& reg) { _emitInstruction(kX86InstFStP, ®); } //! @brief Store x87 FPU Control Word (FPU). //! //! Store FPU control word to @a dst (2 Bytes) after checking for pending //! unmasked floating-point exceptions. inline void fstcw(const Mem& dst) { _emitInstruction(kX86InstFStCw, &dst); } //! @brief Store x87 FPU Environment (FPU). //! //! Store FPU environment to @a dst (14 or 28 Bytes) after checking for //! pending unmasked floating-point exceptions. Then mask all floating //! point exceptions. inline void fstenv(const Mem& dst) { _emitInstruction(kX86InstFStEnv, &dst); } //! @brief Store x87 FPU Status Word (2 Bytes) (FPU). inline void fstsw(const GpReg& dst) { ASMJIT_ASSERT(dst.isRegCode(kX86RegAx)); _emitInstruction(kX86InstFStSw, &dst); } //! @brief Store x87 FPU Status Word (2 Bytes) (FPU). inline void fstsw(const Mem& dst) { _emitInstruction(kX86InstFStSw, &dst); } //! @brief Subtract @a src from @a dst and store result in @a dst (FPU). //! //! @note One of dst or src must be st(0). inline void fsub(const X87Reg& dst, const X87Reg& src) { ASMJIT_ASSERT(dst.getRegIndex() == 0 || src.getRegIndex() == 0); _emitInstruction(kX86InstFSub, &dst, &src); } //! @brief Subtract @a src from st(0) and store result in st(0) (FPU). //! //! @note SP-FP or DP-FP determined by @a adr size. inline void fsub(const Mem& src) { ASMJIT_ASSERT(src.getSize() == 4 || src.getSize() == 8); _emitInstruction(kX86InstFSub, &src); } //! @brief Subtract st(0) from @a dst and POP register stack (FPU). inline void fsubp(const X87Reg& dst = st(1)) { _emitInstruction(kX86InstFSubP, &dst); } //! @brief Reverse Subtract @a src from @a dst and store result in @a dst (FPU). //! //! @note One of dst or src must be st(0). inline void fsubr(const X87Reg& dst, const X87Reg& src) { ASMJIT_ASSERT(dst.getRegIndex() == 0 || src.getRegIndex() == 0); _emitInstruction(kX86InstFSubR, &dst, &src); } //! @brief Reverse Subtract @a src from st(0) and store result in st(0) (FPU). //! //! @note SP-FP or DP-FP determined by @a adr size. inline void fsubr(const Mem& src) { ASMJIT_ASSERT(src.getSize() == 4 || src.getSize() == 8); _emitInstruction(kX86InstFSubR, &src); } //! @brief Reverse Subtract st(0) from @a dst and POP register stack (FPU). inline void fsubrp(const X87Reg& dst = st(1)) { _emitInstruction(kX86InstFSubRP, &dst); } //! @brief Floating point test - Compare st(0) with 0.0. (FPU). inline void ftst() { _emitInstruction(kX86InstFTst); } //! @brief Unordered Compare st(0) with @a reg (FPU). inline void fucom(const X87Reg& reg = st(1)) { _emitInstruction(kX86InstFUCom, ®); } //! @brief Unordered Compare st(0) and @a reg, check for ordered values //! and Set EFLAGS (FPU). inline void fucomi(const X87Reg& reg) { _emitInstruction(kX86InstFUComI, ®); } //! @brief UnorderedCompare st(0) and @a reg, Check for ordered values //! and Set EFLAGS and pop the stack (FPU). inline void fucomip(const X87Reg& reg = st(1)) { _emitInstruction(kX86InstFUComIP, ®); } //! @brief Unordered Compare st(0) with @a reg and pop register stack (FPU). inline void fucomp(const X87Reg& reg = st(1)) { _emitInstruction(kX86InstFUComP, ®); } //! @brief Unordered compare st(0) with st(1) and pop register stack twice //! (FPU). inline void fucompp() { _emitInstruction(kX86InstFUComPP); } inline void fwait() { _emitInstruction(kX86InstFWait); } //! @brief Examine st(0) (FPU). //! //! Examines the contents of the ST(0) register and sets the condition code //! flags C0, C2, and C3 in the FPU status word to indicate the class of //! value or number in the register. inline void fxam() { _emitInstruction(kX86InstFXam); } //! @brief Exchange Register Contents (FPU). //! //! Exchange content of st(0) with @a reg. inline void fxch(const X87Reg& reg = st(1)) { _emitInstruction(kX86InstFXch, ®); } //! @brief Restore FP And MMX(tm) State And Streaming SIMD Extension State //! (FPU, MMX, SSE). //! //! Load FP and MMX(tm) technology and Streaming SIMD Extension state from //! src (512 bytes). inline void fxrstor(const Mem& src) { _emitInstruction(kX86InstFXRstor, &src); } //! @brief Store FP and MMX(tm) State and Streaming SIMD Extension State //! (FPU, MMX, SSE). //! //! Store FP and MMX(tm) technology state and Streaming SIMD Extension state //! to dst (512 bytes). inline void fxsave(const Mem& dst) { _emitInstruction(kX86InstFXSave, &dst); } //! @brief Extract Exponent and Significand (FPU). //! //! Separate value in st(0) into exponent and significand, store exponent //! in st(0), and push the significand onto the register stack. inline void fxtract() { _emitInstruction(kX86InstFXtract); } //! @brief Compute y * log2(x). //! //! Replace st(1) with (st(1) * log2st(0)) and pop the register stack. inline void fyl2x() { _emitInstruction(kX86InstFYL2X); } //! @brief Compute y * log_2(x+1). //! //! Replace st(1) with (st(1) * (log2st(0) + 1.0)) and pop the register stack. inline void fyl2xp1() { _emitInstruction(kX86InstFYL2XP1); } // -------------------------------------------------------------------------- // [MMX] // -------------------------------------------------------------------------- //! @brief Empty MMX state. inline void emms() { _emitInstruction(kX86InstEmms); } //! @brief Move DWord (MMX). inline void movd(const Mem& dst, const MmReg& src) { _emitInstruction(kX86InstMovD, &dst, &src); } //! @brief Move DWord (MMX). inline void movd(const GpReg& dst, const MmReg& src) { _emitInstruction(kX86InstMovD, &dst, &src); } //! @brief Move DWord (MMX). inline void movd(const MmReg& dst, const Mem& src) { _emitInstruction(kX86InstMovD, &dst, &src); } //! @brief Move DWord (MMX). inline void movd(const MmReg& dst, const GpReg& src) { _emitInstruction(kX86InstMovD, &dst, &src); } //! @brief Move QWord (MMX). inline void movq(const MmReg& dst, const MmReg& src) { _emitInstruction(kX86InstMovQ, &dst, &src); } //! @brief Move QWord (MMX). inline void movq(const Mem& dst, const MmReg& src) { _emitInstruction(kX86InstMovQ, &dst, &src); } #if defined(ASMJIT_X64) //! @brief Move QWord (MMX). inline void movq(const GpReg& dst, const MmReg& src) { _emitInstruction(kX86InstMovQ, &dst, &src); } #endif //! @brief Move QWord (MMX). inline void movq(const MmReg& dst, const Mem& src) { _emitInstruction(kX86InstMovQ, &dst, &src); } #if defined(ASMJIT_X64) //! @brief Move QWord (MMX). inline void movq(const MmReg& dst, const GpReg& src) { _emitInstruction(kX86InstMovQ, &dst, &src); } #endif //! @brief Pack with Signed Saturation (MMX). inline void packsswb(const MmReg& dst, const MmReg& src) { _emitInstruction(kX86InstPackSSWB, &dst, &src); } //! @brief Pack with Signed Saturation (MMX). inline void packsswb(const MmReg& dst, const Mem& src) { _emitInstruction(kX86InstPackSSWB, &dst, &src); } //! @brief Pack with Signed Saturation (MMX). inline void packssdw(const MmReg& dst, const MmReg& src) { _emitInstruction(kX86InstPackSSDW, &dst, &src); } //! @brief Pack with Signed Saturation (MMX). inline void packssdw(const MmReg& dst, const Mem& src) { _emitInstruction(kX86InstPackSSDW, &dst, &src); } //! @brief Pack with Unsigned Saturation (MMX). inline void packuswb(const MmReg& dst, const MmReg& src) { _emitInstruction(kX86InstPackUSWB, &dst, &src); } //! @brief Pack with Unsigned Saturation (MMX). inline void packuswb(const MmReg& dst, const Mem& src) { _emitInstruction(kX86InstPackUSWB, &dst, &src); } //! @brief Packed BYTE Add (MMX). inline void paddb(const MmReg& dst, const MmReg& src) { _emitInstruction(kX86InstPAddB, &dst, &src); } //! @brief Packed BYTE Add (MMX). inline void paddb(const MmReg& dst, const Mem& src) { _emitInstruction(kX86InstPAddB, &dst, &src); } //! @brief Packed WORD Add (MMX). inline void paddw(const MmReg& dst, const MmReg& src) { _emitInstruction(kX86InstPAddW, &dst, &src); } //! @brief Packed WORD Add (MMX). inline void paddw(const MmReg& dst, const Mem& src) { _emitInstruction(kX86InstPAddW, &dst, &src); } //! @brief Packed DWORD Add (MMX). inline void paddd(const MmReg& dst, const MmReg& src) { _emitInstruction(kX86InstPAddD, &dst, &src); } //! @brief Packed DWORD Add (MMX). inline void paddd(const MmReg& dst, const Mem& src) { _emitInstruction(kX86InstPAddD, &dst, &src); } //! @brief Packed Add with Saturation (MMX). inline void paddsb(const MmReg& dst, const MmReg& src) { _emitInstruction(kX86InstPAddSB, &dst, &src); } //! @brief Packed Add with Saturation (MMX). inline void paddsb(const MmReg& dst, const Mem& src) { _emitInstruction(kX86InstPAddSB, &dst, &src); } //! @brief Packed Add with Saturation (MMX). inline void paddsw(const MmReg& dst, const MmReg& src) { _emitInstruction(kX86InstPAddSW, &dst, &src); } //! @brief Packed Add with Saturation (MMX). inline void paddsw(const MmReg& dst, const Mem& src) { _emitInstruction(kX86InstPAddSW, &dst, &src); } //! @brief Packed Add Unsigned with Saturation (MMX). inline void paddusb(const MmReg& dst, const MmReg& src) { _emitInstruction(kX86InstPAddUSB, &dst, &src); } //! @brief Packed Add Unsigned with Saturation (MMX). inline void paddusb(const MmReg& dst, const Mem& src) { _emitInstruction(kX86InstPAddUSB, &dst, &src); } //! @brief Packed Add Unsigned with Saturation (MMX). inline void paddusw(const MmReg& dst, const MmReg& src) { _emitInstruction(kX86InstPAddUSW, &dst, &src); } //! @brief Packed Add Unsigned with Saturation (MMX). inline void paddusw(const MmReg& dst, const Mem& src) { _emitInstruction(kX86InstPAddUSW, &dst, &src); } //! @brief Logical AND (MMX). inline void pand(const MmReg& dst, const MmReg& src) { _emitInstruction(kX86InstPAnd, &dst, &src); } //! @brief Logical AND (MMX). inline void pand(const MmReg& dst, const Mem& src) { _emitInstruction(kX86InstPAnd, &dst, &src); } //! @brief Logical AND Not (MMX). inline void pandn(const MmReg& dst, const MmReg& src) { _emitInstruction(kX86InstPAndN, &dst, &src); } //! @brief Logical AND Not (MMX). inline void pandn(const MmReg& dst, const Mem& src) { _emitInstruction(kX86InstPAndN, &dst, &src); } //! @brief Packed Compare for Equal (BYTES) (MMX). inline void pcmpeqb(const MmReg& dst, const MmReg& src) { _emitInstruction(kX86InstPCmpEqB, &dst, &src); } //! @brief Packed Compare for Equal (BYTES) (MMX). inline void pcmpeqb(const MmReg& dst, const Mem& src) { _emitInstruction(kX86InstPCmpEqB, &dst, &src); } //! @brief Packed Compare for Equal (WORDS) (MMX). inline void pcmpeqw(const MmReg& dst, const MmReg& src) { _emitInstruction(kX86InstPCmpEqW, &dst, &src); } //! @brief Packed Compare for Equal (WORDS) (MMX). inline void pcmpeqw(const MmReg& dst, const Mem& src) { _emitInstruction(kX86InstPCmpEqW, &dst, &src); } //! @brief Packed Compare for Equal (DWORDS) (MMX). inline void pcmpeqd(const MmReg& dst, const MmReg& src) { _emitInstruction(kX86InstPCmpEqD, &dst, &src); } //! @brief Packed Compare for Equal (DWORDS) (MMX). inline void pcmpeqd(const MmReg& dst, const Mem& src) { _emitInstruction(kX86InstPCmpEqD, &dst, &src); } //! @brief Packed Compare for Greater Than (BYTES) (MMX). inline void pcmpgtb(const MmReg& dst, const MmReg& src) { _emitInstruction(kX86InstPCmpGtB, &dst, &src); } //! @brief Packed Compare for Greater Than (BYTES) (MMX). inline void pcmpgtb(const MmReg& dst, const Mem& src) { _emitInstruction(kX86InstPCmpGtB, &dst, &src); } //! @brief Packed Compare for Greater Than (WORDS) (MMX). inline void pcmpgtw(const MmReg& dst, const MmReg& src) { _emitInstruction(kX86InstPCmpGtW, &dst, &src); } //! @brief Packed Compare for Greater Than (WORDS) (MMX). inline void pcmpgtw(const MmReg& dst, const Mem& src) { _emitInstruction(kX86InstPCmpGtW, &dst, &src); } //! @brief Packed Compare for Greater Than (DWORDS) (MMX). inline void pcmpgtd(const MmReg& dst, const MmReg& src) { _emitInstruction(kX86InstPCmpGtD, &dst, &src); } //! @brief Packed Compare for Greater Than (DWORDS) (MMX). inline void pcmpgtd(const MmReg& dst, const Mem& src) { _emitInstruction(kX86InstPCmpGtD, &dst, &src); } //! @brief Packed Multiply High (MMX). inline void pmulhw(const MmReg& dst, const MmReg& src) { _emitInstruction(kX86InstPMulHW, &dst, &src); } //! @brief Packed Multiply High (MMX). inline void pmulhw(const MmReg& dst, const Mem& src) { _emitInstruction(kX86InstPMulHW, &dst, &src); } //! @brief Packed Multiply Low (MMX). inline void pmullw(const MmReg& dst, const MmReg& src) { _emitInstruction(kX86InstPMulLW, &dst, &src); } //! @brief Packed Multiply Low (MMX). inline void pmullw(const MmReg& dst, const Mem& src) { _emitInstruction(kX86InstPMulLW, &dst, &src); } //! @brief Bitwise Logical OR (MMX). inline void por(const MmReg& dst, const MmReg& src) { _emitInstruction(kX86InstPOr, &dst, &src); } //! @brief Bitwise Logical OR (MMX). inline void por(const MmReg& dst, const Mem& src) { _emitInstruction(kX86InstPOr, &dst, &src); } //! @brief Packed Multiply and Add (MMX). inline void pmaddwd(const MmReg& dst, const MmReg& src) { _emitInstruction(kX86InstPMAddWD, &dst, &src); } //! @brief Packed Multiply and Add (MMX). inline void pmaddwd(const MmReg& dst, const Mem& src) { _emitInstruction(kX86InstPMAddWD, &dst, &src); } //! @brief Packed Shift Left Logical (MMX). inline void pslld(const MmReg& dst, const MmReg& src) { _emitInstruction(kX86InstPSllD, &dst, &src); } //! @brief Packed Shift Left Logical (MMX). inline void pslld(const MmReg& dst, const Mem& src) { _emitInstruction(kX86InstPSllD, &dst, &src); } //! @brief Packed Shift Left Logical (MMX). inline void pslld(const MmReg& dst, const Imm& src) { _emitInstruction(kX86InstPSllD, &dst, &src); } //! @brief Packed Shift Left Logical (MMX). inline void psllq(const MmReg& dst, const MmReg& src) { _emitInstruction(kX86InstPSllQ, &dst, &src); } //! @brief Packed Shift Left Logical (MMX). inline void psllq(const MmReg& dst, const Mem& src) { _emitInstruction(kX86InstPSllQ, &dst, &src); } //! @brief Packed Shift Left Logical (MMX). inline void psllq(const MmReg& dst, const Imm& src) { _emitInstruction(kX86InstPSllQ, &dst, &src); } //! @brief Packed Shift Left Logical (MMX). inline void psllw(const MmReg& dst, const MmReg& src) { _emitInstruction(kX86InstPSllW, &dst, &src); } //! @brief Packed Shift Left Logical (MMX). inline void psllw(const MmReg& dst, const Mem& src) { _emitInstruction(kX86InstPSllW, &dst, &src); } //! @brief Packed Shift Left Logical (MMX). inline void psllw(const MmReg& dst, const Imm& src) { _emitInstruction(kX86InstPSllW, &dst, &src); } //! @brief Packed Shift Right Arithmetic (MMX). inline void psrad(const MmReg& dst, const MmReg& src) { _emitInstruction(kX86InstPSraD, &dst, &src); } //! @brief Packed Shift Right Arithmetic (MMX). inline void psrad(const MmReg& dst, const Mem& src) { _emitInstruction(kX86InstPSraD, &dst, &src); } //! @brief Packed Shift Right Arithmetic (MMX). inline void psrad(const MmReg& dst, const Imm& src) { _emitInstruction(kX86InstPSraD, &dst, &src); } //! @brief Packed Shift Right Arithmetic (MMX). inline void psraw(const MmReg& dst, const MmReg& src) { _emitInstruction(kX86InstPSraW, &dst, &src); } //! @brief Packed Shift Right Arithmetic (MMX). inline void psraw(const MmReg& dst, const Mem& src) { _emitInstruction(kX86InstPSraW, &dst, &src); } //! @brief Packed Shift Right Arithmetic (MMX). inline void psraw(const MmReg& dst, const Imm& src) { _emitInstruction(kX86InstPSraW, &dst, &src); } //! @brief Packed Shift Right Logical (MMX). inline void psrld(const MmReg& dst, const MmReg& src) { _emitInstruction(kX86InstPSrlD, &dst, &src); } //! @brief Packed Shift Right Logical (MMX). inline void psrld(const MmReg& dst, const Mem& src) { _emitInstruction(kX86InstPSrlD, &dst, &src); } //! @brief Packed Shift Right Logical (MMX). inline void psrld(const MmReg& dst, const Imm& src) { _emitInstruction(kX86InstPSrlD, &dst, &src); } //! @brief Packed Shift Right Logical (MMX). inline void psrlq(const MmReg& dst, const MmReg& src) { _emitInstruction(kX86InstPSrlQ, &dst, &src); } //! @brief Packed Shift Right Logical (MMX). inline void psrlq(const MmReg& dst, const Mem& src) { _emitInstruction(kX86InstPSrlQ, &dst, &src); } //! @brief Packed Shift Right Logical (MMX). inline void psrlq(const MmReg& dst, const Imm& src) { _emitInstruction(kX86InstPSrlQ, &dst, &src); } //! @brief Packed Shift Right Logical (MMX). inline void psrlw(const MmReg& dst, const MmReg& src) { _emitInstruction(kX86InstPSrlW, &dst, &src); } //! @brief Packed Shift Right Logical (MMX). inline void psrlw(const MmReg& dst, const Mem& src) { _emitInstruction(kX86InstPSrlW, &dst, &src); } //! @brief Packed Shift Right Logical (MMX). inline void psrlw(const MmReg& dst, const Imm& src) { _emitInstruction(kX86InstPSrlW, &dst, &src); } //! @brief Packed Subtract (MMX). inline void psubb(const MmReg& dst, const MmReg& src) { _emitInstruction(kX86InstPSubB, &dst, &src); } //! @brief Packed Subtract (MMX). inline void psubb(const MmReg& dst, const Mem& src) { _emitInstruction(kX86InstPSubB, &dst, &src); } //! @brief Packed Subtract (MMX). inline void psubw(const MmReg& dst, const MmReg& src) { _emitInstruction(kX86InstPSubW, &dst, &src); } //! @brief Packed Subtract (MMX). inline void psubw(const MmReg& dst, const Mem& src) { _emitInstruction(kX86InstPSubW, &dst, &src); } //! @brief Packed Subtract (MMX). inline void psubd(const MmReg& dst, const MmReg& src) { _emitInstruction(kX86InstPSubD, &dst, &src); } //! @brief Packed Subtract (MMX). inline void psubd(const MmReg& dst, const Mem& src) { _emitInstruction(kX86InstPSubD, &dst, &src); } //! @brief Packed Subtract with Saturation (MMX). inline void psubsb(const MmReg& dst, const MmReg& src) { _emitInstruction(kX86InstPSubSB, &dst, &src); } //! @brief Packed Subtract with Saturation (MMX). inline void psubsb(const MmReg& dst, const Mem& src) { _emitInstruction(kX86InstPSubSB, &dst, &src); } //! @brief Packed Subtract with Saturation (MMX). inline void psubsw(const MmReg& dst, const MmReg& src) { _emitInstruction(kX86InstPSubSW, &dst, &src); } //! @brief Packed Subtract with Saturation (MMX). inline void psubsw(const MmReg& dst, const Mem& src) { _emitInstruction(kX86InstPSubSW, &dst, &src); } //! @brief Packed Subtract with Unsigned Saturation (MMX). inline void psubusb(const MmReg& dst, const MmReg& src) { _emitInstruction(kX86InstPSubUSB, &dst, &src); } //! @brief Packed Subtract with Unsigned Saturation (MMX). inline void psubusb(const MmReg& dst, const Mem& src) { _emitInstruction(kX86InstPSubUSB, &dst, &src); } //! @brief Packed Subtract with Unsigned Saturation (MMX). inline void psubusw(const MmReg& dst, const MmReg& src) { _emitInstruction(kX86InstPSubUSW, &dst, &src); } //! @brief Packed Subtract with Unsigned Saturation (MMX). inline void psubusw(const MmReg& dst, const Mem& src) { _emitInstruction(kX86InstPSubUSW, &dst, &src); } //! @brief Unpack High Packed Data (MMX). inline void punpckhbw(const MmReg& dst, const MmReg& src) { _emitInstruction(kX86InstPunpckHBW, &dst, &src); } //! @brief Unpack High Packed Data (MMX). inline void punpckhbw(const MmReg& dst, const Mem& src) { _emitInstruction(kX86InstPunpckHBW, &dst, &src); } //! @brief Unpack High Packed Data (MMX). inline void punpckhwd(const MmReg& dst, const MmReg& src) { _emitInstruction(kX86InstPunpckHWD, &dst, &src); } //! @brief Unpack High Packed Data (MMX). inline void punpckhwd(const MmReg& dst, const Mem& src) { _emitInstruction(kX86InstPunpckHWD, &dst, &src); } //! @brief Unpack High Packed Data (MMX). inline void punpckhdq(const MmReg& dst, const MmReg& src) { _emitInstruction(kX86InstPunpckHDQ, &dst, &src); } //! @brief Unpack High Packed Data (MMX). inline void punpckhdq(const MmReg& dst, const Mem& src) { _emitInstruction(kX86InstPunpckHDQ, &dst, &src); } //! @brief Unpack High Packed Data (MMX). inline void punpcklbw(const MmReg& dst, const MmReg& src) { _emitInstruction(kX86InstPunpckLBW, &dst, &src); } //! @brief Unpack High Packed Data (MMX). inline void punpcklbw(const MmReg& dst, const Mem& src) { _emitInstruction(kX86InstPunpckLBW, &dst, &src); } //! @brief Unpack High Packed Data (MMX). inline void punpcklwd(const MmReg& dst, const MmReg& src) { _emitInstruction(kX86InstPunpckLWD, &dst, &src); } //! @brief Unpack High Packed Data (MMX). inline void punpcklwd(const MmReg& dst, const Mem& src) { _emitInstruction(kX86InstPunpckLWD, &dst, &src); } //! @brief Unpack High Packed Data (MMX). inline void punpckldq(const MmReg& dst, const MmReg& src) { _emitInstruction(kX86InstPunpckLDQ, &dst, &src); } //! @brief Unpack High Packed Data (MMX). inline void punpckldq(const MmReg& dst, const Mem& src) { _emitInstruction(kX86InstPunpckLDQ, &dst, &src); } //! @brief Bitwise Exclusive OR (MMX). inline void pxor(const MmReg& dst, const MmReg& src) { _emitInstruction(kX86InstPXor, &dst, &src); } //! @brief Bitwise Exclusive OR (MMX). inline void pxor(const MmReg& dst, const Mem& src) { _emitInstruction(kX86InstPXor, &dst, &src); } // ------------------------------------------------------------------------- // [3dNow] // ------------------------------------------------------------------------- //! @brief Faster EMMS (3dNow!). //! //! @note Use only for early AMD processors where is only 3dNow! or SSE. If //! CPU contains SSE2, it's better to use @c emms() ( @c femms() is mapped //! to @c emms() ). inline void femms() { _emitInstruction(kX86InstFEmms); } //! @brief Packed SP-FP to Integer Convert (3dNow!). inline void pf2id(const MmReg& dst, const MmReg& src) { _emitInstruction(kX86InstPF2ID, &dst, &src); } //! @brief Packed SP-FP to Integer Convert (3dNow!). inline void pf2id(const MmReg& dst, const Mem& src) { _emitInstruction(kX86InstPF2ID, &dst, &src); } //! @brief Packed SP-FP to Integer Word Convert (3dNow!). inline void pf2iw(const MmReg& dst, const MmReg& src) { _emitInstruction(kX86InstPF2IW, &dst, &src); } //! @brief Packed SP-FP to Integer Word Convert (3dNow!). inline void pf2iw(const MmReg& dst, const Mem& src) { _emitInstruction(kX86InstPF2IW, &dst, &src); } //! @brief Packed SP-FP Accumulate (3dNow!). inline void pfacc(const MmReg& dst, const MmReg& src) { _emitInstruction(kX86InstPFAcc, &dst, &src); } //! @brief Packed SP-FP Accumulate (3dNow!). inline void pfacc(const MmReg& dst, const Mem& src) { _emitInstruction(kX86InstPFAcc, &dst, &src); } //! @brief Packed SP-FP Addition (3dNow!). inline void pfadd(const MmReg& dst, const MmReg& src) { _emitInstruction(kX86InstPFAdd, &dst, &src); } //! @brief Packed SP-FP Addition (3dNow!). inline void pfadd(const MmReg& dst, const Mem& src) { _emitInstruction(kX86InstPFAdd, &dst, &src); } //! @brief Packed SP-FP Compare - dst == src (3dNow!). inline void pfcmpeq(const MmReg& dst, const MmReg& src) { _emitInstruction(kX86InstPFCmpEQ, &dst, &src); } //! @brief Packed SP-FP Compare - dst == src (3dNow!). inline void pfcmpeq(const MmReg& dst, const Mem& src) { _emitInstruction(kX86InstPFCmpEQ, &dst, &src); } //! @brief Packed SP-FP Compare - dst >= src (3dNow!). inline void pfcmpge(const MmReg& dst, const MmReg& src) { _emitInstruction(kX86InstPFCmpGE, &dst, &src); } //! @brief Packed SP-FP Compare - dst >= src (3dNow!). inline void pfcmpge(const MmReg& dst, const Mem& src) { _emitInstruction(kX86InstPFCmpGE, &dst, &src); } //! @brief Packed SP-FP Compare - dst > src (3dNow!). inline void pfcmpgt(const MmReg& dst, const MmReg& src) { _emitInstruction(kX86InstPFCmpGT, &dst, &src); } //! @brief Packed SP-FP Compare - dst > src (3dNow!). inline void pfcmpgt(const MmReg& dst, const Mem& src) { _emitInstruction(kX86InstPFCmpGT, &dst, &src); } //! @brief Packed SP-FP Maximum (3dNow!). inline void pfmax(const MmReg& dst, const MmReg& src) { _emitInstruction(kX86InstPFMax, &dst, &src); } //! @brief Packed SP-FP Maximum (3dNow!). inline void pfmax(const MmReg& dst, const Mem& src) { _emitInstruction(kX86InstPFMax, &dst, &src); } //! @brief Packed SP-FP Minimum (3dNow!). inline void pfmin(const MmReg& dst, const MmReg& src) { _emitInstruction(kX86InstPFMin, &dst, &src); } //! @brief Packed SP-FP Minimum (3dNow!). inline void pfmin(const MmReg& dst, const Mem& src) { _emitInstruction(kX86InstPFMin, &dst, &src); } //! @brief Packed SP-FP Multiply (3dNow!). inline void pfmul(const MmReg& dst, const MmReg& src) { _emitInstruction(kX86InstPFMul, &dst, &src); } //! @brief Packed SP-FP Multiply (3dNow!). inline void pfmul(const MmReg& dst, const Mem& src) { _emitInstruction(kX86InstPFMul, &dst, &src); } //! @brief Packed SP-FP Negative Accumulate (3dNow!). inline void pfnacc(const MmReg& dst, const MmReg& src) { _emitInstruction(kX86InstPFNAcc, &dst, &src); } //! @brief Packed SP-FP Negative Accumulate (3dNow!). inline void pfnacc(const MmReg& dst, const Mem& src) { _emitInstruction(kX86InstPFNAcc, &dst, &src); } //! @brief Packed SP-FP Mixed Accumulate (3dNow!). inline void pfpnacc(const MmReg& dst, const MmReg& src) { _emitInstruction(kX86InstPFPNAcc, &dst, &src); } //! @brief Packed SP-FP Mixed Accumulate (3dNow!). inline void pfpnacc(const MmReg& dst, const Mem& src) { _emitInstruction(kX86InstPFPNAcc, &dst, &src); } //! @brief Packed SP-FP Reciprocal Approximation (3dNow!). inline void pfrcp(const MmReg& dst, const MmReg& src) { _emitInstruction(kX86InstPFRcp, &dst, &src); } //! @brief Packed SP-FP Reciprocal Approximation (3dNow!). inline void pfrcp(const MmReg& dst, const Mem& src) { _emitInstruction(kX86InstPFRcp, &dst, &src); } //! @brief Packed SP-FP Reciprocal, First Iteration Step (3dNow!). inline void pfrcpit1(const MmReg& dst, const MmReg& src) { _emitInstruction(kX86InstPFRcpIt1, &dst, &src); } //! @brief Packed SP-FP Reciprocal, First Iteration Step (3dNow!). inline void pfrcpit1(const MmReg& dst, const Mem& src) { _emitInstruction(kX86InstPFRcpIt1, &dst, &src); } //! @brief Packed SP-FP Reciprocal, Second Iteration Step (3dNow!). inline void pfrcpit2(const MmReg& dst, const MmReg& src) { _emitInstruction(kX86InstPFRcpIt2, &dst, &src); } //! @brief Packed SP-FP Reciprocal, Second Iteration Step (3dNow!). inline void pfrcpit2(const MmReg& dst, const Mem& src) { _emitInstruction(kX86InstPFRcpIt2, &dst, &src); } //! @brief Packed SP-FP Reciprocal Square Root, First Iteration Step (3dNow!). inline void pfrsqit1(const MmReg& dst, const MmReg& src) { _emitInstruction(kX86InstPFRSqIt1, &dst, &src); } //! @brief Packed SP-FP Reciprocal Square Root, First Iteration Step (3dNow!). inline void pfrsqit1(const MmReg& dst, const Mem& src) { _emitInstruction(kX86InstPFRSqIt1, &dst, &src); } //! @brief Packed SP-FP Reciprocal Square Root Approximation (3dNow!). inline void pfrsqrt(const MmReg& dst, const MmReg& src) { _emitInstruction(kX86InstPFRSqrt, &dst, &src); } //! @brief Packed SP-FP Reciprocal Square Root Approximation (3dNow!). inline void pfrsqrt(const MmReg& dst, const Mem& src) { _emitInstruction(kX86InstPFRSqrt, &dst, &src); } //! @brief Packed SP-FP Subtract (3dNow!). inline void pfsub(const MmReg& dst, const MmReg& src) { _emitInstruction(kX86InstPFSub, &dst, &src); } //! @brief Packed SP-FP Subtract (3dNow!). inline void pfsub(const MmReg& dst, const Mem& src) { _emitInstruction(kX86InstPFSub, &dst, &src); } //! @brief Packed SP-FP Reverse Subtract (3dNow!). inline void pfsubr(const MmReg& dst, const MmReg& src) { _emitInstruction(kX86InstPFSubR, &dst, &src); } //! @brief Packed SP-FP Reverse Subtract (3dNow!). inline void pfsubr(const MmReg& dst, const Mem& src) { _emitInstruction(kX86InstPFSubR, &dst, &src); } //! @brief Packed DWords to SP-FP (3dNow!). inline void pi2fd(const MmReg& dst, const MmReg& src) { _emitInstruction(kX86InstPI2FD, &dst, &src); } //! @brief Packed DWords to SP-FP (3dNow!). inline void pi2fd(const MmReg& dst, const Mem& src) { _emitInstruction(kX86InstPI2FD, &dst, &src); } //! @brief Packed Words to SP-FP (3dNow!). inline void pi2fw(const MmReg& dst, const MmReg& src) { _emitInstruction(kX86InstPI2FW, &dst, &src); } //! @brief Packed Words to SP-FP (3dNow!). inline void pi2fw(const MmReg& dst, const Mem& src) { _emitInstruction(kX86InstPI2FW, &dst, &src); } //! @brief Packed swap DWord (3dNow!) inline void pswapd(const MmReg& dst, const MmReg& src) { _emitInstruction(kX86InstPSwapD, &dst, &src); } //! @brief Packed swap DWord (3dNow!) inline void pswapd(const MmReg& dst, const Mem& src) { _emitInstruction(kX86InstPSwapD, &dst, &src); } // -------------------------------------------------------------------------- // [SSE] // -------------------------------------------------------------------------- //! @brief Packed SP-FP Add (SSE). inline void addps(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstAddPS, &dst, &src); } //! @brief Packed SP-FP Add (SSE). inline void addps(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstAddPS, &dst, &src); } //! @brief Scalar SP-FP Add (SSE). inline void addss(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstAddSS, &dst, &src); } //! @brief Scalar SP-FP Add (SSE). inline void addss(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstAddSS, &dst, &src); } //! @brief Bit-wise Logical And Not For SP-FP (SSE). inline void andnps(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstAndnPS, &dst, &src); } //! @brief Bit-wise Logical And Not For SP-FP (SSE). inline void andnps(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstAndnPS, &dst, &src); } //! @brief Bit-wise Logical And For SP-FP (SSE). inline void andps(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstAndPS, &dst, &src); } //! @brief Bit-wise Logical And For SP-FP (SSE). inline void andps(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstAndPS, &dst, &src); } //! @brief Packed SP-FP Compare (SSE). inline void cmpps(const XmmReg& dst, const XmmReg& src, const Imm& imm8) { _emitInstruction(kX86InstCmpPS, &dst, &src, &imm8); } //! @brief Packed SP-FP Compare (SSE). inline void cmpps(const XmmReg& dst, const Mem& src, const Imm& imm8) { _emitInstruction(kX86InstCmpPS, &dst, &src, &imm8); } //! @brief Compare Scalar SP-FP Values (SSE). inline void cmpss(const XmmReg& dst, const XmmReg& src, const Imm& imm8) { _emitInstruction(kX86InstCmpSS, &dst, &src, &imm8); } //! @brief Compare Scalar SP-FP Values (SSE). inline void cmpss(const XmmReg& dst, const Mem& src, const Imm& imm8) { _emitInstruction(kX86InstCmpSS, &dst, &src, &imm8); } //! @brief Scalar Ordered SP-FP Compare and Set EFLAGS (SSE). inline void comiss(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstComISS, &dst, &src); } //! @brief Scalar Ordered SP-FP Compare and Set EFLAGS (SSE). inline void comiss(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstComISS, &dst, &src); } //! @brief Packed Signed INT32 to Packed SP-FP Conversion (SSE). inline void cvtpi2ps(const XmmReg& dst, const MmReg& src) { _emitInstruction(kX86InstCvtPI2PS, &dst, &src); } //! @brief Packed Signed INT32 to Packed SP-FP Conversion (SSE). inline void cvtpi2ps(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstCvtPI2PS, &dst, &src); } //! @brief Packed SP-FP to Packed INT32 Conversion (SSE). inline void cvtps2pi(const MmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstCvtPS2PI, &dst, &src); } //! @brief Packed SP-FP to Packed INT32 Conversion (SSE). inline void cvtps2pi(const MmReg& dst, const Mem& src) { _emitInstruction(kX86InstCvtPS2PI, &dst, &src); } //! @brief Scalar Signed INT32 to SP-FP Conversion (SSE). inline void cvtsi2ss(const XmmReg& dst, const GpReg& src) { _emitInstruction(kX86InstCvtSI2SS, &dst, &src); } //! @brief Scalar Signed INT32 to SP-FP Conversion (SSE). inline void cvtsi2ss(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstCvtSI2SS, &dst, &src); } //! @brief Scalar SP-FP to Signed INT32 Conversion (SSE). inline void cvtss2si(const GpReg& dst, const XmmReg& src) { _emitInstruction(kX86InstCvtSS2SI, &dst, &src); } //! @brief Scalar SP-FP to Signed INT32 Conversion (SSE). inline void cvtss2si(const GpReg& dst, const Mem& src) { _emitInstruction(kX86InstCvtSS2SI, &dst, &src); } //! @brief Packed SP-FP to Packed INT32 Conversion (truncate) (SSE). inline void cvttps2pi(const MmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstCvttPS2PI, &dst, &src); } //! @brief Packed SP-FP to Packed INT32 Conversion (truncate) (SSE). inline void cvttps2pi(const MmReg& dst, const Mem& src) { _emitInstruction(kX86InstCvttPS2PI, &dst, &src); } //! @brief Scalar SP-FP to Signed INT32 Conversion (truncate) (SSE). inline void cvttss2si(const GpReg& dst, const XmmReg& src) { _emitInstruction(kX86InstCvttSS2SI, &dst, &src); } //! @brief Scalar SP-FP to Signed INT32 Conversion (truncate) (SSE). inline void cvttss2si(const GpReg& dst, const Mem& src) { _emitInstruction(kX86InstCvttSS2SI, &dst, &src); } //! @brief Packed SP-FP Divide (SSE). inline void divps(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstDivPS, &dst, &src); } //! @brief Packed SP-FP Divide (SSE). inline void divps(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstDivPS, &dst, &src); } //! @brief Scalar SP-FP Divide (SSE). inline void divss(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstDivSS, &dst, &src); } //! @brief Scalar SP-FP Divide (SSE). inline void divss(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstDivSS, &dst, &src); } //! @brief Load Streaming SIMD Extension Control/Status (SSE). inline void ldmxcsr(const Mem& src) { _emitInstruction(kX86InstLdMXCSR, &src); } //! @brief Byte Mask Write (SSE). //! //! @note The default memory location is specified by DS:EDI. inline void maskmovq(const MmReg& data, const MmReg& mask) { _emitInstruction(kX86InstMaskMovQ, &data, &mask); } //! @brief Packed SP-FP Maximum (SSE). inline void maxps(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstMaxPS, &dst, &src); } //! @brief Packed SP-FP Maximum (SSE). inline void maxps(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstMaxPS, &dst, &src); } //! @brief Scalar SP-FP Maximum (SSE). inline void maxss(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstMaxSS, &dst, &src); } //! @brief Scalar SP-FP Maximum (SSE). inline void maxss(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstMaxSS, &dst, &src); } //! @brief Packed SP-FP Minimum (SSE). inline void minps(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstMinPS, &dst, &src); } //! @brief Packed SP-FP Minimum (SSE). inline void minps(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstMinPS, &dst, &src); } //! @brief Scalar SP-FP Minimum (SSE). inline void minss(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstMinSS, &dst, &src); } //! @brief Scalar SP-FP Minimum (SSE). inline void minss(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstMinSS, &dst, &src); } //! @brief Move Aligned Packed SP-FP Values (SSE). inline void movaps(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstMovAPS, &dst, &src); } //! @brief Move Aligned Packed SP-FP Values (SSE). inline void movaps(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstMovAPS, &dst, &src); } //! @brief Move Aligned Packed SP-FP Values (SSE). inline void movaps(const Mem& dst, const XmmReg& src) { _emitInstruction(kX86InstMovAPS, &dst, &src); } //! @brief Move DWord. inline void movd(const Mem& dst, const XmmReg& src) { _emitInstruction(kX86InstMovD, &dst, &src); } //! @brief Move DWord. inline void movd(const GpReg& dst, const XmmReg& src) { _emitInstruction(kX86InstMovD, &dst, &src); } //! @brief Move DWord. inline void movd(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstMovD, &dst, &src); } //! @brief Move DWord. inline void movd(const XmmReg& dst, const GpReg& src) { _emitInstruction(kX86InstMovD, &dst, &src); } //! @brief Move QWord (SSE). inline void movq(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstMovQ, &dst, &src); } //! @brief Move QWord (SSE). inline void movq(const Mem& dst, const XmmReg& src) { _emitInstruction(kX86InstMovQ, &dst, &src); } #if defined(ASMJIT_X64) //! @brief Move QWord (SSE). inline void movq(const GpReg& dst, const XmmReg& src) { _emitInstruction(kX86InstMovQ, &dst, &src); } #endif // ASMJIT_X64 //! @brief Move QWord (SSE). inline void movq(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstMovQ, &dst, &src); } #if defined(ASMJIT_X64) //! @brief Move QWord (SSE). inline void movq(const XmmReg& dst, const GpReg& src) { _emitInstruction(kX86InstMovQ, &dst, &src); } #endif // ASMJIT_X64 //! @brief Move 64 Bits Non Temporal (SSE). inline void movntq(const Mem& dst, const MmReg& src) { _emitInstruction(kX86InstMovNTQ, &dst, &src); } //! @brief High to Low Packed SP-FP (SSE). inline void movhlps(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstMovHLPS, &dst, &src); } //! @brief Move High Packed SP-FP (SSE). inline void movhps(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstMovHPS, &dst, &src); } //! @brief Move High Packed SP-FP (SSE). inline void movhps(const Mem& dst, const XmmReg& src) { _emitInstruction(kX86InstMovHPS, &dst, &src); } //! @brief Move Low to High Packed SP-FP (SSE). inline void movlhps(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstMovLHPS, &dst, &src); } //! @brief Move Low Packed SP-FP (SSE). inline void movlps(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstMovLPS, &dst, &src); } //! @brief Move Low Packed SP-FP (SSE). inline void movlps(const Mem& dst, const XmmReg& src) { _emitInstruction(kX86InstMovLPS, &dst, &src); } //! @brief Move Aligned Four Packed SP-FP Non Temporal (SSE). inline void movntps(const Mem& dst, const XmmReg& src) { _emitInstruction(kX86InstMovNTPS, &dst, &src); } //! @brief Move Scalar SP-FP (SSE). inline void movss(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstMovSS, &dst, &src); } //! @brief Move Scalar SP-FP (SSE). inline void movss(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstMovSS, &dst, &src); } //! @brief Move Scalar SP-FP (SSE). inline void movss(const Mem& dst, const XmmReg& src) { _emitInstruction(kX86InstMovSS, &dst, &src); } //! @brief Move Unaligned Packed SP-FP Values (SSE). inline void movups(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstMovUPS, &dst, &src); } //! @brief Move Unaligned Packed SP-FP Values (SSE). inline void movups(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstMovUPS, &dst, &src); } //! @brief Move Unaligned Packed SP-FP Values (SSE). inline void movups(const Mem& dst, const XmmReg& src) { _emitInstruction(kX86InstMovUPS, &dst, &src); } //! @brief Packed SP-FP Multiply (SSE). inline void mulps(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstMulPS, &dst, &src); } //! @brief Packed SP-FP Multiply (SSE). inline void mulps(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstMulPS, &dst, &src); } //! @brief Scalar SP-FP Multiply (SSE). inline void mulss(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstMulSS, &dst, &src); } //! @brief Scalar SP-FP Multiply (SSE). inline void mulss(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstMulSS, &dst, &src); } //! @brief Bit-wise Logical OR for SP-FP Data (SSE). inline void orps(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstOrPS, &dst, &src); } //! @brief Bit-wise Logical OR for SP-FP Data (SSE). inline void orps(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstOrPS, &dst, &src); } //! @brief Packed Average (SSE). inline void pavgb(const MmReg& dst, const MmReg& src) { _emitInstruction(kX86InstPAvgB, &dst, &src); } //! @brief Packed Average (SSE). inline void pavgb(const MmReg& dst, const Mem& src) { _emitInstruction(kX86InstPAvgB, &dst, &src); } //! @brief Packed Average (SSE). inline void pavgw(const MmReg& dst, const MmReg& src) { _emitInstruction(kX86InstPAvgW, &dst, &src); } //! @brief Packed Average (SSE). inline void pavgw(const MmReg& dst, const Mem& src) { _emitInstruction(kX86InstPAvgW, &dst, &src); } //! @brief Extract Word (SSE). inline void pextrw(const GpReg& dst, const MmReg& src, const Imm& imm8) { _emitInstruction(kX86InstPExtrW, &dst, &src, &imm8); } //! @brief Insert Word (SSE). inline void pinsrw(const MmReg& dst, const GpReg& src, const Imm& imm8) { _emitInstruction(kX86InstPInsRW, &dst, &src, &imm8); } //! @brief Insert Word (SSE). inline void pinsrw(const MmReg& dst, const Mem& src, const Imm& imm8) { _emitInstruction(kX86InstPInsRW, &dst, &src, &imm8); } //! @brief Packed Signed Integer Word Maximum (SSE). inline void pmaxsw(const MmReg& dst, const MmReg& src) { _emitInstruction(kX86InstPMaxSW, &dst, &src); } //! @brief Packed Signed Integer Word Maximum (SSE). inline void pmaxsw(const MmReg& dst, const Mem& src) { _emitInstruction(kX86InstPMaxSW, &dst, &src); } //! @brief Packed Unsigned Integer Byte Maximum (SSE). inline void pmaxub(const MmReg& dst, const MmReg& src) { _emitInstruction(kX86InstPMaxUB, &dst, &src); } //! @brief Packed Unsigned Integer Byte Maximum (SSE). inline void pmaxub(const MmReg& dst, const Mem& src) { _emitInstruction(kX86InstPMaxUB, &dst, &src); } //! @brief Packed Signed Integer Word Minimum (SSE). inline void pminsw(const MmReg& dst, const MmReg& src) { _emitInstruction(kX86InstPMinSW, &dst, &src); } //! @brief Packed Signed Integer Word Minimum (SSE). inline void pminsw(const MmReg& dst, const Mem& src) { _emitInstruction(kX86InstPMinSW, &dst, &src); } //! @brief Packed Unsigned Integer Byte Minimum (SSE). inline void pminub(const MmReg& dst, const MmReg& src) { _emitInstruction(kX86InstPMinUB, &dst, &src); } //! @brief Packed Unsigned Integer Byte Minimum (SSE). inline void pminub(const MmReg& dst, const Mem& src) { _emitInstruction(kX86InstPMinUB, &dst, &src); } //! @brief Move Byte Mask To Integer (SSE). inline void pmovmskb(const GpReg& dst, const MmReg& src) { _emitInstruction(kX86InstPMovMskB, &dst, &src); } //! @brief Packed Multiply High Unsigned (SSE). inline void pmulhuw(const MmReg& dst, const MmReg& src) { _emitInstruction(kX86InstPMulHUW, &dst, &src); } //! @brief Packed Multiply High Unsigned (SSE). inline void pmulhuw(const MmReg& dst, const Mem& src) { _emitInstruction(kX86InstPMulHUW, &dst, &src); } //! @brief Packed Sum of Absolute Differences (SSE). inline void psadbw(const MmReg& dst, const MmReg& src) { _emitInstruction(kX86InstPSADBW, &dst, &src); } //! @brief Packed Sum of Absolute Differences (SSE). inline void psadbw(const MmReg& dst, const Mem& src) { _emitInstruction(kX86InstPSADBW, &dst, &src); } //! @brief Packed Shuffle word (SSE). inline void pshufw(const MmReg& dst, const MmReg& src, const Imm& imm8) { _emitInstruction(kX86InstPShufW, &dst, &src, &imm8); } //! @brief Packed Shuffle word (SSE). inline void pshufw(const MmReg& dst, const Mem& src, const Imm& imm8) { _emitInstruction(kX86InstPShufW, &dst, &src, &imm8); } //! @brief Packed SP-FP Reciprocal (SSE). inline void rcpps(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstRcpPS, &dst, &src); } //! @brief Packed SP-FP Reciprocal (SSE). inline void rcpps(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstRcpPS, &dst, &src); } //! @brief Scalar SP-FP Reciprocal (SSE). inline void rcpss(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstRcpSS, &dst, &src); } //! @brief Scalar SP-FP Reciprocal (SSE). inline void rcpss(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstRcpSS, &dst, &src); } //! @brief Prefetch (SSE). inline void prefetch(const Mem& mem, const Imm& hint) { _emitInstruction(kX86InstPrefetch, &mem, &hint); } //! @brief Compute Sum of Absolute Differences (SSE). inline void psadbw(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstPSADBW, &dst, &src); } //! @brief Compute Sum of Absolute Differences (SSE). inline void psadbw(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstPSADBW, &dst, &src); } //! @brief Packed SP-FP Square Root Reciprocal (SSE). inline void rsqrtps(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstSqrtPS, &dst, &src); } //! @brief Packed SP-FP Square Root Reciprocal (SSE). inline void rsqrtps(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstSqrtPS, &dst, &src); } //! @brief Scalar SP-FP Square Root Reciprocal (SSE). inline void rsqrtss(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstSqrtSS, &dst, &src); } //! @brief Scalar SP-FP Square Root Reciprocal (SSE). inline void rsqrtss(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstSqrtSS, &dst, &src); } //! @brief Store fence (SSE). inline void sfence() { _emitInstruction(kX86InstSFence); } //! @brief Shuffle SP-FP (SSE). inline void shufps(const XmmReg& dst, const XmmReg& src, const Imm& imm8) { _emitInstruction(kX86InstShufPS, &dst, &src, &imm8); } //! @brief Shuffle SP-FP (SSE). inline void shufps(const XmmReg& dst, const Mem& src, const Imm& imm8) { _emitInstruction(kX86InstShufPS, &dst, &src, &imm8); } //! @brief Packed SP-FP Square Root (SSE). inline void sqrtps(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstSqrtPS, &dst, &src); } //! @brief Packed SP-FP Square Root (SSE). inline void sqrtps(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstSqrtPS, &dst, &src); } //! @brief Scalar SP-FP Square Root (SSE). inline void sqrtss(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstSqrtSS, &dst, &src); } //! @brief Scalar SP-FP Square Root (SSE). inline void sqrtss(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstSqrtSS, &dst, &src); } //! @brief Store Streaming SIMD Extension Control/Status (SSE). inline void stmxcsr(const Mem& dst) { _emitInstruction(kX86InstStMXCSR, &dst); } //! @brief Packed SP-FP Subtract (SSE). inline void subps(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstSubPS, &dst, &src); } //! @brief Packed SP-FP Subtract (SSE). inline void subps(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstSubPS, &dst, &src); } //! @brief Scalar SP-FP Subtract (SSE). inline void subss(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstSubSS, &dst, &src); } //! @brief Scalar SP-FP Subtract (SSE). inline void subss(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstSubSS, &dst, &src); } //! @brief Unordered Scalar SP-FP compare and set EFLAGS (SSE). inline void ucomiss(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstUComISS, &dst, &src); } //! @brief Unordered Scalar SP-FP compare and set EFLAGS (SSE). inline void ucomiss(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstUComISS, &dst, &src); } //! @brief Unpack High Packed SP-FP Data (SSE). inline void unpckhps(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstUnpckHPS, &dst, &src); } //! @brief Unpack High Packed SP-FP Data (SSE). inline void unpckhps(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstUnpckHPS, &dst, &src); } //! @brief Unpack Low Packed SP-FP Data (SSE). inline void unpcklps(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstUnpckLPS, &dst, &src); } //! @brief Unpack Low Packed SP-FP Data (SSE). inline void unpcklps(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstUnpckLPS, &dst, &src); } //! @brief Bit-wise Logical Xor for SP-FP Data (SSE). inline void xorps(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstXorPS, &dst, &src); } //! @brief Bit-wise Logical Xor for SP-FP Data (SSE). inline void xorps(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstXorPS, &dst, &src); } // -------------------------------------------------------------------------- // [SSE2] // -------------------------------------------------------------------------- //! @brief Packed DP-FP Add (SSE2). inline void addpd(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstAddPD, &dst, &src); } //! @brief Packed DP-FP Add (SSE2). inline void addpd(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstAddPD, &dst, &src); } //! @brief Scalar DP-FP Add (SSE2). inline void addsd(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstAddSD, &dst, &src); } //! @brief Scalar DP-FP Add (SSE2). inline void addsd(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstAddSD, &dst, &src); } //! @brief Bit-wise Logical And Not For DP-FP (SSE2). inline void andnpd(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstAndnPD, &dst, &src); } //! @brief Bit-wise Logical And Not For DP-FP (SSE2). inline void andnpd(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstAndnPD, &dst, &src); } //! @brief Bit-wise Logical And For DP-FP (SSE2). inline void andpd(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstAndPD, &dst, &src); } //! @brief Bit-wise Logical And For DP-FP (SSE2). inline void andpd(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstAndPD, &dst, &src); } //! @brief Flush Cache Line (SSE2). inline void clflush(const Mem& mem) { _emitInstruction(kX86InstClFlush, &mem); } //! @brief Packed DP-FP Compare (SSE2). inline void cmppd(const XmmReg& dst, const XmmReg& src, const Imm& imm8) { _emitInstruction(kX86InstCmpPD, &dst, &src, &imm8); } //! @brief Packed DP-FP Compare (SSE2). inline void cmppd(const XmmReg& dst, const Mem& src, const Imm& imm8) { _emitInstruction(kX86InstCmpPD, &dst, &src, &imm8); } //! @brief Compare Scalar SP-FP Values (SSE2). inline void cmpsd(const XmmReg& dst, const XmmReg& src, const Imm& imm8) { _emitInstruction(kX86InstCmpSD, &dst, &src, &imm8); } //! @brief Compare Scalar SP-FP Values (SSE2). inline void cmpsd(const XmmReg& dst, const Mem& src, const Imm& imm8) { _emitInstruction(kX86InstCmpSD, &dst, &src, &imm8); } //! @brief Scalar Ordered DP-FP Compare and Set EFLAGS (SSE2). inline void comisd(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstComISD, &dst, &src); } //! @brief Scalar Ordered DP-FP Compare and Set EFLAGS (SSE2). inline void comisd(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstComISD, &dst, &src); } //! @brief Convert Packed Dword Integers to Packed DP-FP Values (SSE2). inline void cvtdq2pd(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstCvtDQ2PD, &dst, &src); } //! @brief Convert Packed Dword Integers to Packed DP-FP Values (SSE2). inline void cvtdq2pd(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstCvtDQ2PD, &dst, &src); } //! @brief Convert Packed Dword Integers to Packed SP-FP Values (SSE2). inline void cvtdq2ps(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstCvtDQ2PS, &dst, &src); } //! @brief Convert Packed Dword Integers to Packed SP-FP Values (SSE2). inline void cvtdq2ps(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstCvtDQ2PS, &dst, &src); } //! @brief Convert Packed DP-FP Values to Packed Dword Integers (SSE2). inline void cvtpd2dq(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstCvtPD2DQ, &dst, &src); } //! @brief Convert Packed DP-FP Values to Packed Dword Integers (SSE2). inline void cvtpd2dq(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstCvtPD2DQ, &dst, &src); } //! @brief Convert Packed DP-FP Values to Packed Dword Integers (SSE2). inline void cvtpd2pi(const MmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstCvtPD2PI, &dst, &src); } //! @brief Convert Packed DP-FP Values to Packed Dword Integers (SSE2). inline void cvtpd2pi(const MmReg& dst, const Mem& src) { _emitInstruction(kX86InstCvtPD2PI, &dst, &src); } //! @brief Convert Packed DP-FP Values to Packed SP-FP Values (SSE2). inline void cvtpd2ps(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstCvtPD2PS, &dst, &src); } //! @brief Convert Packed DP-FP Values to Packed SP-FP Values (SSE2). inline void cvtpd2ps(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstCvtPD2PS, &dst, &src); } //! @brief Convert Packed Dword Integers to Packed DP-FP Values (SSE2). inline void cvtpi2pd(const XmmReg& dst, const MmReg& src) { _emitInstruction(kX86InstCvtPI2PD, &dst, &src); } //! @brief Convert Packed Dword Integers to Packed DP-FP Values (SSE2). inline void cvtpi2pd(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstCvtPI2PD, &dst, &src); } //! @brief Convert Packed SP-FP Values to Packed Dword Integers (SSE2). inline void cvtps2dq(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstCvtPS2DQ, &dst, &src); } //! @brief Convert Packed SP-FP Values to Packed Dword Integers (SSE2). inline void cvtps2dq(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstCvtPS2DQ, &dst, &src); } //! @brief Convert Packed SP-FP Values to Packed DP-FP Values (SSE2). inline void cvtps2pd(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstCvtPS2PD, &dst, &src); } //! @brief Convert Packed SP-FP Values to Packed DP-FP Values (SSE2). inline void cvtps2pd(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstCvtPS2PD, &dst, &src); } //! @brief Convert Scalar DP-FP Value to Dword Integer (SSE2). inline void cvtsd2si(const GpReg& dst, const XmmReg& src) { _emitInstruction(kX86InstCvtSD2SI, &dst, &src); } //! @brief Convert Scalar DP-FP Value to Dword Integer (SSE2). inline void cvtsd2si(const GpReg& dst, const Mem& src) { _emitInstruction(kX86InstCvtSD2SI, &dst, &src); } //! @brief Convert Scalar DP-FP Value to Scalar SP-FP Value (SSE2). inline void cvtsd2ss(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstCvtSD2SS, &dst, &src); } //! @brief Convert Scalar DP-FP Value to Scalar SP-FP Value (SSE2). inline void cvtsd2ss(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstCvtSD2SS, &dst, &src); } //! @brief Convert Dword Integer to Scalar DP-FP Value (SSE2). inline void cvtsi2sd(const XmmReg& dst, const GpReg& src) { _emitInstruction(kX86InstCvtSI2SD, &dst, &src); } //! @brief Convert Dword Integer to Scalar DP-FP Value (SSE2). inline void cvtsi2sd(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstCvtSI2SD, &dst, &src); } //! @brief Convert Scalar SP-FP Value to Scalar DP-FP Value (SSE2). inline void cvtss2sd(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstCvtSS2SD, &dst, &src); } //! @brief Convert Scalar SP-FP Value to Scalar DP-FP Value (SSE2). inline void cvtss2sd(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstCvtSS2SD, &dst, &src); } //! @brief Convert with Truncation Packed DP-FP Values to Packed Dword Integers (SSE2). inline void cvttpd2pi(const MmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstCvttPD2PI, &dst, &src); } //! @brief Convert with Truncation Packed DP-FP Values to Packed Dword Integers (SSE2). inline void cvttpd2pi(const MmReg& dst, const Mem& src) { _emitInstruction(kX86InstCvttPD2PI, &dst, &src); } //! @brief Convert with Truncation Packed DP-FP Values to Packed Dword Integers (SSE2). inline void cvttpd2dq(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstCvttPD2DQ, &dst, &src); } //! @brief Convert with Truncation Packed DP-FP Values to Packed Dword Integers (SSE2). inline void cvttpd2dq(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstCvttPD2DQ, &dst, &src); } //! @brief Convert with Truncation Packed SP-FP Values to Packed Dword Integers (SSE2). inline void cvttps2dq(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstCvttPS2DQ, &dst, &src); } //! @brief Convert with Truncation Packed SP-FP Values to Packed Dword Integers (SSE2). inline void cvttps2dq(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstCvttPS2DQ, &dst, &src); } //! @brief Convert with Truncation Scalar DP-FP Value to Signed Dword Integer (SSE2). inline void cvttsd2si(const GpReg& dst, const XmmReg& src) { _emitInstruction(kX86InstCvttSD2SI, &dst, &src); } //! @brief Convert with Truncation Scalar DP-FP Value to Signed Dword Integer (SSE2). inline void cvttsd2si(const GpReg& dst, const Mem& src) { _emitInstruction(kX86InstCvttSD2SI, &dst, &src); } //! @brief Packed DP-FP Divide (SSE2). inline void divpd(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstDivPD, &dst, &src); } //! @brief Packed DP-FP Divide (SSE2). inline void divpd(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstDivPD, &dst, &src); } //! @brief Scalar DP-FP Divide (SSE2). inline void divsd(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstDivSD, &dst, &src); } //! @brief Scalar DP-FP Divide (SSE2). inline void divsd(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstDivSD, &dst, &src); } //! @brief Load Fence (SSE2). inline void lfence() { _emitInstruction(kX86InstLFence); } //! @brief Store Selected Bytes of Double Quadword (SSE2). //! //! @note Target is DS:EDI. inline void maskmovdqu(const XmmReg& src, const XmmReg& mask) { _emitInstruction(kX86InstMaskMovDQU, &src, &mask); } //! @brief Return Maximum Packed Double-Precision FP Values (SSE2). inline void maxpd(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstMaxPD, &dst, &src); } //! @brief Return Maximum Packed Double-Precision FP Values (SSE2). inline void maxpd(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstMaxPD, &dst, &src); } //! @brief Return Maximum Scalar Double-Precision FP Value (SSE2). inline void maxsd(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstMaxSD, &dst, &src); } //! @brief Return Maximum Scalar Double-Precision FP Value (SSE2). inline void maxsd(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstMaxSD, &dst, &src); } //! @brief Memory Fence (SSE2). inline void mfence() { _emitInstruction(kX86InstMFence); } //! @brief Return Minimum Packed DP-FP Values (SSE2). inline void minpd(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstMinPD, &dst, &src); } //! @brief Return Minimum Packed DP-FP Values (SSE2). inline void minpd(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstMinPD, &dst, &src); } //! @brief Return Minimum Scalar DP-FP Value (SSE2). inline void minsd(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstMinSD, &dst, &src); } //! @brief Return Minimum Scalar DP-FP Value (SSE2). inline void minsd(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstMinSD, &dst, &src); } //! @brief Move Aligned DQWord (SSE2). inline void movdqa(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstMovDQA, &dst, &src); } //! @brief Move Aligned DQWord (SSE2). inline void movdqa(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstMovDQA, &dst, &src); } //! @brief Move Aligned DQWord (SSE2). inline void movdqa(const Mem& dst, const XmmReg& src) { _emitInstruction(kX86InstMovDQA, &dst, &src); } //! @brief Move Unaligned Double Quadword (SSE2). inline void movdqu(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstMovDQU, &dst, &src); } //! @brief Move Unaligned Double Quadword (SSE2). inline void movdqu(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstMovDQU, &dst, &src); } //! @brief Move Unaligned Double Quadword (SSE2). inline void movdqu(const Mem& dst, const XmmReg& src) { _emitInstruction(kX86InstMovDQU, &dst, &src); } //! @brief Extract Packed SP-FP Sign Mask (SSE2). inline void movmskps(const GpReg& dst, const XmmReg& src) { _emitInstruction(kX86InstMovMskPS, &dst, &src); } //! @brief Extract Packed DP-FP Sign Mask (SSE2). inline void movmskpd(const GpReg& dst, const XmmReg& src) { _emitInstruction(kX86InstMovMskPD, &dst, &src); } //! @brief Move Scalar Double-Precision FP Value (SSE2). inline void movsd(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstMovSD, &dst, &src); } //! @brief Move Scalar Double-Precision FP Value (SSE2). inline void movsd(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstMovSD, &dst, &src); } //! @brief Move Scalar Double-Precision FP Value (SSE2). inline void movsd(const Mem& dst, const XmmReg& src) { _emitInstruction(kX86InstMovSD, &dst, &src); } //! @brief Move Aligned Packed Double-Precision FP Values (SSE2). inline void movapd(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstMovAPD, &dst, &src); } //! @brief Move Aligned Packed Double-Precision FP Values (SSE2). inline void movapd(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstMovAPD, &dst, &src); } //! @brief Move Aligned Packed Double-Precision FP Values (SSE2). inline void movapd(const Mem& dst, const XmmReg& src) { _emitInstruction(kX86InstMovAPD, &dst, &src); } //! @brief Move Quadword from XMM to MMX Technology Register (SSE2). inline void movdq2q(const MmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstMovDQ2Q, &dst, &src); } //! @brief Move Quadword from MMX Technology to XMM Register (SSE2). inline void movq2dq(const XmmReg& dst, const MmReg& src) { _emitInstruction(kX86InstMovQ2DQ, &dst, &src); } //! @brief Move High Packed Double-Precision FP Value (SSE2). inline void movhpd(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstMovHPD, &dst, &src); } //! @brief Move High Packed Double-Precision FP Value (SSE2). inline void movhpd(const Mem& dst, const XmmReg& src) { _emitInstruction(kX86InstMovHPD, &dst, &src); } //! @brief Move Low Packed Double-Precision FP Value (SSE2). inline void movlpd(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstMovLPD, &dst, &src); } //! @brief Move Low Packed Double-Precision FP Value (SSE2). inline void movlpd(const Mem& dst, const XmmReg& src) { _emitInstruction(kX86InstMovLPD, &dst, &src); } //! @brief Store Double Quadword Using Non-Temporal Hint (SSE2). inline void movntdq(const Mem& dst, const XmmReg& src) { _emitInstruction(kX86InstMovNTDQ, &dst, &src); } //! @brief Store Store DWORD Using Non-Temporal Hint (SSE2). inline void movnti(const Mem& dst, const GpReg& src) { _emitInstruction(kX86InstMovNTI, &dst, &src); } //! @brief Store Packed Double-Precision FP Values Using Non-Temporal Hint (SSE2). inline void movntpd(const Mem& dst, const XmmReg& src) { _emitInstruction(kX86InstMovNTPD, &dst, &src); } //! @brief Move Unaligned Packed Double-Precision FP Values (SSE2). inline void movupd(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstMovUPD, &dst, &src); } //! @brief Move Unaligned Packed Double-Precision FP Values (SSE2). inline void movupd(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstMovUPD, &dst, &src); } //! @brief Move Unaligned Packed Double-Precision FP Values (SSE2). inline void movupd(const Mem& dst, const XmmReg& src) { _emitInstruction(kX86InstMovUPD, &dst, &src); } //! @brief Packed DP-FP Multiply (SSE2). inline void mulpd(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstMulPD, &dst, &src); } //! @brief Packed DP-FP Multiply (SSE2). inline void mulpd(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstMulPD, &dst, &src); } //! @brief Scalar DP-FP Multiply (SSE2). inline void mulsd(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstMulSD, &dst, &src); } //! @brief Scalar DP-FP Multiply (SSE2). inline void mulsd(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstMulSD, &dst, &src); } //! @brief Bit-wise Logical OR for DP-FP Data (SSE2). inline void orpd(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstOrPD, &dst, &src); } //! @brief Bit-wise Logical OR for DP-FP Data (SSE2). inline void orpd(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstOrPD, &dst, &src); } //! @brief Pack with Signed Saturation (SSE2). inline void packsswb(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstPackSSWB, &dst, &src); } //! @brief Pack with Signed Saturation (SSE2). inline void packsswb(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstPackSSWB, &dst, &src); } //! @brief Pack with Signed Saturation (SSE2). inline void packssdw(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstPackSSDW, &dst, &src); } //! @brief Pack with Signed Saturation (SSE2). inline void packssdw(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstPackSSDW, &dst, &src); } //! @brief Pack with Unsigned Saturation (SSE2). inline void packuswb(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstPackUSWB, &dst, &src); } //! @brief Pack with Unsigned Saturation (SSE2). inline void packuswb(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstPackUSWB, &dst, &src); } //! @brief Packed BYTE Add (SSE2). inline void paddb(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstPAddB, &dst, &src); } //! @brief Packed BYTE Add (SSE2). inline void paddb(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstPAddB, &dst, &src); } //! @brief Packed WORD Add (SSE2). inline void paddw(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstPAddW, &dst, &src); } //! @brief Packed WORD Add (SSE2). inline void paddw(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstPAddW, &dst, &src); } //! @brief Packed DWORD Add (SSE2). inline void paddd(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstPAddD, &dst, &src); } //! @brief Packed DWORD Add (SSE2). inline void paddd(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstPAddD, &dst, &src); } //! @brief Packed QWORD Add (SSE2). inline void paddq(const MmReg& dst, const MmReg& src) { _emitInstruction(kX86InstPAddQ, &dst, &src); } //! @brief Packed QWORD Add (SSE2). inline void paddq(const MmReg& dst, const Mem& src) { _emitInstruction(kX86InstPAddQ, &dst, &src); } //! @brief Packed QWORD Add (SSE2). inline void paddq(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstPAddQ, &dst, &src); } //! @brief Packed QWORD Add (SSE2). inline void paddq(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstPAddQ, &dst, &src); } //! @brief Packed Add with Saturation (SSE2). inline void paddsb(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstPAddSB, &dst, &src); } //! @brief Packed Add with Saturation (SSE2). inline void paddsb(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstPAddSB, &dst, &src); } //! @brief Packed Add with Saturation (SSE2). inline void paddsw(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstPAddSW, &dst, &src); } //! @brief Packed Add with Saturation (SSE2). inline void paddsw(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstPAddSW, &dst, &src); } //! @brief Packed Add Unsigned with Saturation (SSE2). inline void paddusb(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstPAddUSB, &dst, &src); } //! @brief Packed Add Unsigned with Saturation (SSE2). inline void paddusb(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstPAddUSB, &dst, &src); } //! @brief Packed Add Unsigned with Saturation (SSE2). inline void paddusw(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstPAddUSW, &dst, &src); } //! @brief Packed Add Unsigned with Saturation (SSE2). inline void paddusw(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstPAddUSW, &dst, &src); } //! @brief Logical AND (SSE2). inline void pand(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstPAnd, &dst, &src); } //! @brief Logical AND (SSE2). inline void pand(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstPAnd, &dst, &src); } //! @brief Logical AND Not (SSE2). inline void pandn(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstPAndN, &dst, &src); } //! @brief Logical AND Not (SSE2). inline void pandn(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstPAndN, &dst, &src); } //! @brief Spin Loop Hint (SSE2). inline void pause() { _emitInstruction(kX86InstPause); } //! @brief Packed Average (SSE2). inline void pavgb(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstPAvgB, &dst, &src); } //! @brief Packed Average (SSE2). inline void pavgb(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstPAvgB, &dst, &src); } //! @brief Packed Average (SSE2). inline void pavgw(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstPAvgW, &dst, &src); } //! @brief Packed Average (SSE2). inline void pavgw(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstPAvgW, &dst, &src); } //! @brief Packed Compare for Equal (BYTES) (SSE2). inline void pcmpeqb(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstPCmpEqB, &dst, &src); } //! @brief Packed Compare for Equal (BYTES) (SSE2). inline void pcmpeqb(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstPCmpEqB, &dst, &src); } //! @brief Packed Compare for Equal (WORDS) (SSE2). inline void pcmpeqw(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstPCmpEqW, &dst, &src); } //! @brief Packed Compare for Equal (WORDS) (SSE2). inline void pcmpeqw(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstPCmpEqW, &dst, &src); } //! @brief Packed Compare for Equal (DWORDS) (SSE2). inline void pcmpeqd(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstPCmpEqD, &dst, &src); } //! @brief Packed Compare for Equal (DWORDS) (SSE2). inline void pcmpeqd(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstPCmpEqD, &dst, &src); } //! @brief Packed Compare for Greater Than (BYTES) (SSE2). inline void pcmpgtb(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstPCmpGtB, &dst, &src); } //! @brief Packed Compare for Greater Than (BYTES) (SSE2). inline void pcmpgtb(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstPCmpGtB, &dst, &src); } //! @brief Packed Compare for Greater Than (WORDS) (SSE2). inline void pcmpgtw(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstPCmpGtW, &dst, &src); } //! @brief Packed Compare for Greater Than (WORDS) (SSE2). inline void pcmpgtw(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstPCmpGtW, &dst, &src); } //! @brief Packed Compare for Greater Than (DWORDS) (SSE2). inline void pcmpgtd(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstPCmpGtD, &dst, &src); } //! @brief Packed Compare for Greater Than (DWORDS) (SSE2). inline void pcmpgtd(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstPCmpGtD, &dst, &src); } //! @brief Packed Signed Integer Word Maximum (SSE2). inline void pmaxsw(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstPMaxSW, &dst, &src); } //! @brief Packed Signed Integer Word Maximum (SSE2). inline void pmaxsw(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstPMaxSW, &dst, &src); } //! @brief Packed Unsigned Integer Byte Maximum (SSE2). inline void pmaxub(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstPMaxUB, &dst, &src); } //! @brief Packed Unsigned Integer Byte Maximum (SSE2). inline void pmaxub(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstPMaxUB, &dst, &src); } //! @brief Packed Signed Integer Word Minimum (SSE2). inline void pminsw(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstPMinSW, &dst, &src); } //! @brief Packed Signed Integer Word Minimum (SSE2). inline void pminsw(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstPMinSW, &dst, &src); } //! @brief Packed Unsigned Integer Byte Minimum (SSE2). inline void pminub(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstPMinUB, &dst, &src); } //! @brief Packed Unsigned Integer Byte Minimum (SSE2). inline void pminub(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstPMinUB, &dst, &src); } //! @brief Move Byte Mask (SSE2). inline void pmovmskb(const GpReg& dst, const XmmReg& src) { _emitInstruction(kX86InstPMovMskB, &dst, &src); } //! @brief Packed Multiply High (SSE2). inline void pmulhw(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstPMulHW, &dst, &src); } //! @brief Packed Multiply High (SSE2). inline void pmulhw(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstPMulHW, &dst, &src); } //! @brief Packed Multiply High Unsigned (SSE2). inline void pmulhuw(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstPMulHUW, &dst, &src); } //! @brief Packed Multiply High Unsigned (SSE2). inline void pmulhuw(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstPMulHUW, &dst, &src); } //! @brief Packed Multiply Low (SSE2). inline void pmullw(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstPMulLW, &dst, &src); } //! @brief Packed Multiply Low (SSE2). inline void pmullw(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstPMulLW, &dst, &src); } //! @brief Packed Multiply to QWORD (SSE2). inline void pmuludq(const MmReg& dst, const MmReg& src) { _emitInstruction(kX86InstPMulUDQ, &dst, &src); } //! @brief Packed Multiply to QWORD (SSE2). inline void pmuludq(const MmReg& dst, const Mem& src) { _emitInstruction(kX86InstPMulUDQ, &dst, &src); } //! @brief Packed Multiply to QWORD (SSE2). inline void pmuludq(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstPMulUDQ, &dst, &src); } //! @brief Packed Multiply to QWORD (SSE2). inline void pmuludq(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstPMulUDQ, &dst, &src); } //! @brief Bitwise Logical OR (SSE2). inline void por(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstPOr, &dst, &src); } //! @brief Bitwise Logical OR (SSE2). inline void por(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstPOr, &dst, &src); } //! @brief Packed Shift Left Logical (SSE2). inline void pslld(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstPSllD, &dst, &src); } //! @brief Packed Shift Left Logical (SSE2). inline void pslld(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstPSllD, &dst, &src); } //! @brief Packed Shift Left Logical (SSE2). inline void pslld(const XmmReg& dst, const Imm& src) { _emitInstruction(kX86InstPSllD, &dst, &src); } //! @brief Packed Shift Left Logical (SSE2). inline void psllq(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstPSllQ, &dst, &src); } //! @brief Packed Shift Left Logical (SSE2). inline void psllq(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstPSllQ, &dst, &src); } //! @brief Packed Shift Left Logical (SSE2). inline void psllq(const XmmReg& dst, const Imm& src) { _emitInstruction(kX86InstPSllQ, &dst, &src); } //! @brief Packed Shift Left Logical (SSE2). inline void psllw(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstPSllW, &dst, &src); } //! @brief Packed Shift Left Logical (SSE2). inline void psllw(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstPSllW, &dst, &src); } //! @brief Packed Shift Left Logical (SSE2). inline void psllw(const XmmReg& dst, const Imm& src) { _emitInstruction(kX86InstPSllW, &dst, &src); } //! @brief Packed Shift Left Logical (SSE2). inline void pslldq(const XmmReg& dst, const Imm& src) { _emitInstruction(kX86InstPSllDQ, &dst, &src); } //! @brief Packed Shift Right Arithmetic (SSE2). inline void psrad(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstPSraD, &dst, &src); } //! @brief Packed Shift Right Arithmetic (SSE2). inline void psrad(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstPSraD, &dst, &src); } //! @brief Packed Shift Right Arithmetic (SSE2). inline void psrad(const XmmReg& dst, const Imm& src) { _emitInstruction(kX86InstPSraD, &dst, &src); } //! @brief Packed Shift Right Arithmetic (SSE2). inline void psraw(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstPSraW, &dst, &src); } //! @brief Packed Shift Right Arithmetic (SSE2). inline void psraw(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstPSraW, &dst, &src); } //! @brief Packed Shift Right Arithmetic (SSE2). inline void psraw(const XmmReg& dst, const Imm& src) { _emitInstruction(kX86InstPSraW, &dst, &src); } //! @brief Packed Subtract (SSE2). inline void psubb(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstPSubB, &dst, &src); } //! @brief Packed Subtract (SSE2). inline void psubb(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstPSubB, &dst, &src); } //! @brief Packed Subtract (SSE2). inline void psubw(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstPSubW, &dst, &src); } //! @brief Packed Subtract (SSE2). inline void psubw(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstPSubW, &dst, &src); } //! @brief Packed Subtract (SSE2). inline void psubd(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstPSubD, &dst, &src); } //! @brief Packed Subtract (SSE2). inline void psubd(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstPSubD, &dst, &src); } //! @brief Packed Subtract (SSE2). inline void psubq(const MmReg& dst, const MmReg& src) { _emitInstruction(kX86InstPSubQ, &dst, &src); } //! @brief Packed Subtract (SSE2). inline void psubq(const MmReg& dst, const Mem& src) { _emitInstruction(kX86InstPSubQ, &dst, &src); } //! @brief Packed Subtract (SSE2). inline void psubq(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstPSubQ, &dst, &src); } //! @brief Packed Subtract (SSE2). inline void psubq(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstPSubQ, &dst, &src); } //! @brief Packed Multiply and Add (SSE2). inline void pmaddwd(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstPMAddWD, &dst, &src); } //! @brief Packed Multiply and Add (SSE2). inline void pmaddwd(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstPMAddWD, &dst, &src); } //! @brief Shuffle Packed DWORDs (SSE2). inline void pshufd(const XmmReg& dst, const XmmReg& src, const Imm& imm8) { _emitInstruction(kX86InstPShufD, &dst, &src, &imm8); } //! @brief Shuffle Packed DWORDs (SSE2). inline void pshufd(const XmmReg& dst, const Mem& src, const Imm& imm8) { _emitInstruction(kX86InstPShufD, &dst, &src, &imm8); } //! @brief Shuffle Packed High Words (SSE2). inline void pshufhw(const XmmReg& dst, const XmmReg& src, const Imm& imm8) { _emitInstruction(kX86InstPShufHW, &dst, &src, &imm8); } //! @brief Shuffle Packed High Words (SSE2). inline void pshufhw(const XmmReg& dst, const Mem& src, const Imm& imm8) { _emitInstruction(kX86InstPShufHW, &dst, &src, &imm8); } //! @brief Shuffle Packed Low Words (SSE2). inline void pshuflw(const XmmReg& dst, const XmmReg& src, const Imm& imm8) { _emitInstruction(kX86InstPShufLW, &dst, &src, &imm8); } //! @brief Shuffle Packed Low Words (SSE2). inline void pshuflw(const XmmReg& dst, const Mem& src, const Imm& imm8) { _emitInstruction(kX86InstPShufLW, &dst, &src, &imm8); } //! @brief Packed Shift Right Logical (SSE2). inline void psrld(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstPSrlD, &dst, &src); } //! @brief Packed Shift Right Logical (SSE2). inline void psrld(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstPSrlD, &dst, &src); } //! @brief Packed Shift Right Logical (SSE2). inline void psrld(const XmmReg& dst, const Imm& src) { _emitInstruction(kX86InstPSrlD, &dst, &src); } //! @brief Packed Shift Right Logical (SSE2). inline void psrlq(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstPSrlQ, &dst, &src); } //! @brief Packed Shift Right Logical (SSE2). inline void psrlq(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstPSrlQ, &dst, &src); } //! @brief Packed Shift Right Logical (SSE2). inline void psrlq(const XmmReg& dst, const Imm& src) { _emitInstruction(kX86InstPSrlQ, &dst, &src); } //! @brief DQWord Shift Right Logical (MMX). inline void psrldq(const XmmReg& dst, const Imm& src) { _emitInstruction(kX86InstPSrlDQ, &dst, &src); } //! @brief Packed Shift Right Logical (SSE2). inline void psrlw(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstPSrlW, &dst, &src); } //! @brief Packed Shift Right Logical (SSE2). inline void psrlw(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstPSrlW, &dst, &src); } //! @brief Packed Shift Right Logical (SSE2). inline void psrlw(const XmmReg& dst, const Imm& src) { _emitInstruction(kX86InstPSrlW, &dst, &src); } //! @brief Packed Subtract with Saturation (SSE2). inline void psubsb(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstPSubSB, &dst, &src); } //! @brief Packed Subtract with Saturation (SSE2). inline void psubsb(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstPSubSB, &dst, &src); } //! @brief Packed Subtract with Saturation (SSE2). inline void psubsw(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstPSubSW, &dst, &src); } //! @brief Packed Subtract with Saturation (SSE2). inline void psubsw(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstPSubSW, &dst, &src); } //! @brief Packed Subtract with Unsigned Saturation (SSE2). inline void psubusb(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstPSubUSB, &dst, &src); } //! @brief Packed Subtract with Unsigned Saturation (SSE2). inline void psubusb(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstPSubUSB, &dst, &src); } //! @brief Packed Subtract with Unsigned Saturation (SSE2). inline void psubusw(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstPSubUSW, &dst, &src); } //! @brief Packed Subtract with Unsigned Saturation (SSE2). inline void psubusw(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstPSubUSW, &dst, &src); } //! @brief Unpack High Data (SSE2). inline void punpckhbw(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstPunpckHBW, &dst, &src); } //! @brief Unpack High Data (SSE2). inline void punpckhbw(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstPunpckHBW, &dst, &src); } //! @brief Unpack High Data (SSE2). inline void punpckhwd(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstPunpckHWD, &dst, &src); } //! @brief Unpack High Data (SSE2). inline void punpckhwd(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstPunpckHWD, &dst, &src); } //! @brief Unpack High Data (SSE2). inline void punpckhdq(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstPunpckHDQ, &dst, &src); } //! @brief Unpack High Data (SSE2). inline void punpckhdq(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstPunpckHDQ, &dst, &src); } //! @brief Unpack High Data (SSE2). inline void punpckhqdq(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstPunpckHQDQ, &dst, &src); } //! @brief Unpack High Data (SSE2). inline void punpckhqdq(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstPunpckHQDQ, &dst, &src); } //! @brief Unpack Low Data (SSE2). inline void punpcklbw(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstPunpckLBW, &dst, &src); } //! @brief Unpack Low Data (SSE2). inline void punpcklbw(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstPunpckLBW, &dst, &src); } //! @brief Unpack Low Data (SSE2). inline void punpcklwd(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstPunpckLWD, &dst, &src); } //! @brief Unpack Low Data (SSE2). inline void punpcklwd(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstPunpckLWD, &dst, &src); } //! @brief Unpack Low Data (SSE2). inline void punpckldq(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstPunpckLDQ, &dst, &src); } //! @brief Unpack Low Data (SSE2). inline void punpckldq(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstPunpckLDQ, &dst, &src); } //! @brief Unpack Low Data (SSE2). inline void punpcklqdq(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstPunpckLQDQ, &dst, &src); } //! @brief Unpack Low Data (SSE2). inline void punpcklqdq(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstPunpckLQDQ, &dst, &src); } //! @brief Bitwise Exclusive OR (SSE2). inline void pxor(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstPXor, &dst, &src); } //! @brief Bitwise Exclusive OR (SSE2). inline void pxor(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstPXor, &dst, &src); } //! @brief Shuffle DP-FP (SSE2). inline void shufpd(const XmmReg& dst, const XmmReg& src, const Imm& imm8) { _emitInstruction(kX86InstShufPD, &dst, &src, &imm8); } //! @brief Shuffle DP-FP (SSE2). inline void shufpd(const XmmReg& dst, const Mem& src, const Imm& imm8) { _emitInstruction(kX86InstShufPD, &dst, &src, &imm8); } //! @brief Compute Square Roots of Packed DP-FP Values (SSE2). inline void sqrtpd(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstSqrtPD, &dst, &src); } //! @brief Compute Square Roots of Packed DP-FP Values (SSE2). inline void sqrtpd(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstSqrtPD, &dst, &src); } //! @brief Compute Square Root of Scalar DP-FP Value (SSE2). inline void sqrtsd(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstSqrtSD, &dst, &src); } //! @brief Compute Square Root of Scalar DP-FP Value (SSE2). inline void sqrtsd(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstSqrtSD, &dst, &src); } //! @brief Packed DP-FP Subtract (SSE2). inline void subpd(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstSubPD, &dst, &src); } //! @brief Packed DP-FP Subtract (SSE2). inline void subpd(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstSubPD, &dst, &src); } //! @brief Scalar DP-FP Subtract (SSE2). inline void subsd(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstSubSD, &dst, &src); } //! @brief Scalar DP-FP Subtract (SSE2). inline void subsd(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstSubSD, &dst, &src); } //! @brief Scalar Unordered DP-FP Compare and Set EFLAGS (SSE2). inline void ucomisd(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstUComISD, &dst, &src); } //! @brief Scalar Unordered DP-FP Compare and Set EFLAGS (SSE2). inline void ucomisd(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstUComISD, &dst, &src); } //! @brief Unpack and Interleave High Packed Double-Precision FP Values (SSE2). inline void unpckhpd(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstUnpckHPD, &dst, &src); } //! @brief Unpack and Interleave High Packed Double-Precision FP Values (SSE2). inline void unpckhpd(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstUnpckHPD, &dst, &src); } //! @brief Unpack and Interleave Low Packed Double-Precision FP Values (SSE2). inline void unpcklpd(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstUnpckLPD, &dst, &src); } //! @brief Unpack and Interleave Low Packed Double-Precision FP Values (SSE2). inline void unpcklpd(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstUnpckLPD, &dst, &src); } //! @brief Bit-wise Logical OR for DP-FP Data (SSE2). inline void xorpd(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstXorPD, &dst, &src); } //! @brief Bit-wise Logical OR for DP-FP Data (SSE2). inline void xorpd(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstXorPD, &dst, &src); } // -------------------------------------------------------------------------- // [SSE3] // -------------------------------------------------------------------------- //! @brief Packed DP-FP Add/Subtract (SSE3). inline void addsubpd(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstAddSubPD, &dst, &src); } //! @brief Packed DP-FP Add/Subtract (SSE3). inline void addsubpd(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstAddSubPD, &dst, &src); } //! @brief Packed SP-FP Add/Subtract (SSE3). inline void addsubps(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstAddSubPS, &dst, &src); } //! @brief Packed SP-FP Add/Subtract (SSE3). inline void addsubps(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstAddSubPS, &dst, &src); } //! @brief Store Integer with Truncation (SSE3). inline void fisttp(const Mem& dst) { _emitInstruction(kX86InstFISttP, &dst); } //! @brief Packed DP-FP Horizontal Add (SSE3). inline void haddpd(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstHAddPD, &dst, &src); } //! @brief Packed DP-FP Horizontal Add (SSE3). inline void haddpd(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstHAddPD, &dst, &src); } //! @brief Packed SP-FP Horizontal Add (SSE3). inline void haddps(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstHAddPS, &dst, &src); } //! @brief Packed SP-FP Horizontal Add (SSE3). inline void haddps(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstHAddPS, &dst, &src); } //! @brief Packed DP-FP Horizontal Subtract (SSE3). inline void hsubpd(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstHSubPD, &dst, &src); } //! @brief Packed DP-FP Horizontal Subtract (SSE3). inline void hsubpd(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstHSubPD, &dst, &src); } //! @brief Packed SP-FP Horizontal Subtract (SSE3). inline void hsubps(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstHSubPS, &dst, &src); } //! @brief Packed SP-FP Horizontal Subtract (SSE3). inline void hsubps(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstHSubPS, &dst, &src); } //! @brief Load Unaligned Integer 128 Bits (SSE3). inline void lddqu(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstLdDQU, &dst, &src); } //! @brief Set Up Monitor Address (SSE3). inline void monitor() { _emitInstruction(kX86InstMonitor); } //! @brief Move One DP-FP and Duplicate (SSE3). inline void movddup(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstMovDDup, &dst, &src); } //! @brief Move One DP-FP and Duplicate (SSE3). inline void movddup(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstMovDDup, &dst, &src); } //! @brief Move Packed SP-FP High and Duplicate (SSE3). inline void movshdup(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstMovSHDup, &dst, &src); } //! @brief Move Packed SP-FP High and Duplicate (SSE3). inline void movshdup(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstMovSHDup, &dst, &src); } //! @brief Move Packed SP-FP Low and Duplicate (SSE3). inline void movsldup(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstMovSLDup, &dst, &src); } //! @brief Move Packed SP-FP Low and Duplicate (SSE3). inline void movsldup(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstMovSLDup, &dst, &src); } //! @brief Monitor Wait (SSE3). inline void mwait() { _emitInstruction(kX86InstMWait); } // -------------------------------------------------------------------------- // [SSSE3] // -------------------------------------------------------------------------- //! @brief Packed SIGN (SSSE3). inline void psignb(const MmReg& dst, const MmReg& src) { _emitInstruction(kX86InstPSignB, &dst, &src); } //! @brief Packed SIGN (SSSE3). inline void psignb(const MmReg& dst, const Mem& src) { _emitInstruction(kX86InstPSignB, &dst, &src); } //! @brief Packed SIGN (SSSE3). inline void psignb(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstPSignB, &dst, &src); } //! @brief Packed SIGN (SSSE3). inline void psignb(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstPSignB, &dst, &src); } //! @brief Packed SIGN (SSSE3). inline void psignw(const MmReg& dst, const MmReg& src) { _emitInstruction(kX86InstPSignW, &dst, &src); } //! @brief Packed SIGN (SSSE3). inline void psignw(const MmReg& dst, const Mem& src) { _emitInstruction(kX86InstPSignW, &dst, &src); } //! @brief Packed SIGN (SSSE3). inline void psignw(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstPSignW, &dst, &src); } //! @brief Packed SIGN (SSSE3). inline void psignw(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstPSignW, &dst, &src); } //! @brief Packed SIGN (SSSE3). inline void psignd(const MmReg& dst, const MmReg& src) { _emitInstruction(kX86InstPSignD, &dst, &src); } //! @brief Packed SIGN (SSSE3). inline void psignd(const MmReg& dst, const Mem& src) { _emitInstruction(kX86InstPSignD, &dst, &src); } //! @brief Packed SIGN (SSSE3). inline void psignd(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstPSignD, &dst, &src); } //! @brief Packed SIGN (SSSE3). inline void psignd(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstPSignD, &dst, &src); } //! @brief Packed Horizontal Add (SSSE3). inline void phaddw(const MmReg& dst, const MmReg& src) { _emitInstruction(kX86InstPHAddW, &dst, &src); } //! @brief Packed Horizontal Add (SSSE3). inline void phaddw(const MmReg& dst, const Mem& src) { _emitInstruction(kX86InstPHAddW, &dst, &src); } //! @brief Packed Horizontal Add (SSSE3). inline void phaddw(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstPHAddW, &dst, &src); } //! @brief Packed Horizontal Add (SSSE3). inline void phaddw(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstPHAddW, &dst, &src); } //! @brief Packed Horizontal Add (SSSE3). inline void phaddd(const MmReg& dst, const MmReg& src) { _emitInstruction(kX86InstPHAddD, &dst, &src); } //! @brief Packed Horizontal Add (SSSE3). inline void phaddd(const MmReg& dst, const Mem& src) { _emitInstruction(kX86InstPHAddD, &dst, &src); } //! @brief Packed Horizontal Add (SSSE3). inline void phaddd(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstPHAddD, &dst, &src); } //! @brief Packed Horizontal Add (SSSE3). inline void phaddd(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstPHAddD, &dst, &src); } //! @brief Packed Horizontal Add and Saturate (SSSE3). inline void phaddsw(const MmReg& dst, const MmReg& src) { _emitInstruction(kX86InstPHAddSW, &dst, &src); } //! @brief Packed Horizontal Add and Saturate (SSSE3). inline void phaddsw(const MmReg& dst, const Mem& src) { _emitInstruction(kX86InstPHAddSW, &dst, &src); } //! @brief Packed Horizontal Add and Saturate (SSSE3). inline void phaddsw(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstPHAddSW, &dst, &src); } //! @brief Packed Horizontal Add and Saturate (SSSE3). inline void phaddsw(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstPHAddSW, &dst, &src); } //! @brief Packed Horizontal Subtract (SSSE3). inline void phsubw(const MmReg& dst, const MmReg& src) { _emitInstruction(kX86InstPHSubW, &dst, &src); } //! @brief Packed Horizontal Subtract (SSSE3). inline void phsubw(const MmReg& dst, const Mem& src) { _emitInstruction(kX86InstPHSubW, &dst, &src); } //! @brief Packed Horizontal Subtract (SSSE3). inline void phsubw(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstPHSubW, &dst, &src); } //! @brief Packed Horizontal Subtract (SSSE3). inline void phsubw(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstPHSubW, &dst, &src); } //! @brief Packed Horizontal Subtract (SSSE3). inline void phsubd(const MmReg& dst, const MmReg& src) { _emitInstruction(kX86InstPHSubD, &dst, &src); } //! @brief Packed Horizontal Subtract (SSSE3). inline void phsubd(const MmReg& dst, const Mem& src) { _emitInstruction(kX86InstPHSubD, &dst, &src); } //! @brief Packed Horizontal Subtract (SSSE3). inline void phsubd(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstPHSubD, &dst, &src); } //! @brief Packed Horizontal Subtract (SSSE3). inline void phsubd(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstPHSubD, &dst, &src); } //! @brief Packed Horizontal Subtract and Saturate (SSSE3). inline void phsubsw(const MmReg& dst, const MmReg& src) { _emitInstruction(kX86InstPHSubSW, &dst, &src); } //! @brief Packed Horizontal Subtract and Saturate (SSSE3). inline void phsubsw(const MmReg& dst, const Mem& src) { _emitInstruction(kX86InstPHSubSW, &dst, &src); } //! @brief Packed Horizontal Subtract and Saturate (SSSE3). inline void phsubsw(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstPHSubSW, &dst, &src); } //! @brief Packed Horizontal Subtract and Saturate (SSSE3). inline void phsubsw(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstPHSubSW, &dst, &src); } //! @brief Multiply and Add Packed Signed and Unsigned Bytes (SSSE3). inline void pmaddubsw(const MmReg& dst, const MmReg& src) { _emitInstruction(kX86InstPMAddUBSW, &dst, &src); } //! @brief Multiply and Add Packed Signed and Unsigned Bytes (SSSE3). inline void pmaddubsw(const MmReg& dst, const Mem& src) { _emitInstruction(kX86InstPMAddUBSW, &dst, &src); } //! @brief Multiply and Add Packed Signed and Unsigned Bytes (SSSE3). inline void pmaddubsw(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstPMAddUBSW, &dst, &src); } //! @brief Multiply and Add Packed Signed and Unsigned Bytes (SSSE3). inline void pmaddubsw(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstPMAddUBSW, &dst, &src); } //! @brief Packed Absolute Value (SSSE3). inline void pabsb(const MmReg& dst, const MmReg& src) { _emitInstruction(kX86InstPAbsB, &dst, &src); } //! @brief Packed Absolute Value (SSSE3). inline void pabsb(const MmReg& dst, const Mem& src) { _emitInstruction(kX86InstPAbsB, &dst, &src); } //! @brief Packed Absolute Value (SSSE3). inline void pabsb(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstPAbsB, &dst, &src); } //! @brief Packed Absolute Value (SSSE3). inline void pabsb(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstPAbsB, &dst, &src); } //! @brief Packed Absolute Value (SSSE3). inline void pabsw(const MmReg& dst, const MmReg& src) { _emitInstruction(kX86InstPAbsW, &dst, &src); } //! @brief Packed Absolute Value (SSSE3). inline void pabsw(const MmReg& dst, const Mem& src) { _emitInstruction(kX86InstPAbsW, &dst, &src); } //! @brief Packed Absolute Value (SSSE3). inline void pabsw(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstPAbsW, &dst, &src); } //! @brief Packed Absolute Value (SSSE3). inline void pabsw(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstPAbsW, &dst, &src); } //! @brief Packed Absolute Value (SSSE3). inline void pabsd(const MmReg& dst, const MmReg& src) { _emitInstruction(kX86InstPAbsD, &dst, &src); } //! @brief Packed Absolute Value (SSSE3). inline void pabsd(const MmReg& dst, const Mem& src) { _emitInstruction(kX86InstPAbsD, &dst, &src); } //! @brief Packed Absolute Value (SSSE3). inline void pabsd(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstPAbsD, &dst, &src); } //! @brief Packed Absolute Value (SSSE3). inline void pabsd(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstPAbsD, &dst, &src); } //! @brief Packed Multiply High with Round and Scale (SSSE3). inline void pmulhrsw(const MmReg& dst, const MmReg& src) { _emitInstruction(kX86InstPMulHRSW, &dst, &src); } //! @brief Packed Multiply High with Round and Scale (SSSE3). inline void pmulhrsw(const MmReg& dst, const Mem& src) { _emitInstruction(kX86InstPMulHRSW, &dst, &src); } //! @brief Packed Multiply High with Round and Scale (SSSE3). inline void pmulhrsw(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstPMulHRSW, &dst, &src); } //! @brief Packed Multiply High with Round and Scale (SSSE3). inline void pmulhrsw(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstPMulHRSW, &dst, &src); } //! @brief Packed Shuffle Bytes (SSSE3). inline void pshufb(const MmReg& dst, const MmReg& src) { _emitInstruction(kX86InstPShufB, &dst, &src); } //! @brief Packed Shuffle Bytes (SSSE3). inline void pshufb(const MmReg& dst, const Mem& src) { _emitInstruction(kX86InstPShufB, &dst, &src); } //! @brief Packed Shuffle Bytes (SSSE3). inline void pshufb(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstPShufB, &dst, &src); } //! @brief Packed Shuffle Bytes (SSSE3). inline void pshufb(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstPShufB, &dst, &src); } //! @brief Packed Shuffle Bytes (SSSE3). inline void palignr(const MmReg& dst, const MmReg& src, const Imm& imm8) { _emitInstruction(kX86InstPAlignR, &dst, &src, &imm8); } //! @brief Packed Shuffle Bytes (SSSE3). inline void palignr(const MmReg& dst, const Mem& src, const Imm& imm8) { _emitInstruction(kX86InstPAlignR, &dst, &src, &imm8); } //! @brief Packed Shuffle Bytes (SSSE3). inline void palignr(const XmmReg& dst, const XmmReg& src, const Imm& imm8) { _emitInstruction(kX86InstPAlignR, &dst, &src, &imm8); } //! @brief Packed Shuffle Bytes (SSSE3). inline void palignr(const XmmReg& dst, const Mem& src, const Imm& imm8) { _emitInstruction(kX86InstPAlignR, &dst, &src, &imm8); } // -------------------------------------------------------------------------- // [SSE4.1] // -------------------------------------------------------------------------- //! @brief Blend Packed DP-FP Values (SSE4.1). inline void blendpd(const XmmReg& dst, const XmmReg& src, const Imm& imm8) { _emitInstruction(kX86InstBlendPD, &dst, &src, &imm8); } //! @brief Blend Packed DP-FP Values (SSE4.1). inline void blendpd(const XmmReg& dst, const Mem& src, const Imm& imm8) { _emitInstruction(kX86InstBlendPD, &dst, &src, &imm8); } //! @brief Blend Packed SP-FP Values (SSE4.1). inline void blendps(const XmmReg& dst, const XmmReg& src, const Imm& imm8) { _emitInstruction(kX86InstBlendPS, &dst, &src, &imm8); } //! @brief Blend Packed SP-FP Values (SSE4.1). inline void blendps(const XmmReg& dst, const Mem& src, const Imm& imm8) { _emitInstruction(kX86InstBlendPS, &dst, &src, &imm8); } //! @brief Variable Blend Packed DP-FP Values (SSE4.1). inline void blendvpd(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstBlendVPD, &dst, &src); } //! @brief Variable Blend Packed DP-FP Values (SSE4.1). inline void blendvpd(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstBlendVPD, &dst, &src); } //! @brief Variable Blend Packed SP-FP Values (SSE4.1). inline void blendvps(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstBlendVPS, &dst, &src); } //! @brief Variable Blend Packed SP-FP Values (SSE4.1). inline void blendvps(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstBlendVPS, &dst, &src); } //! @brief Dot Product of Packed DP-FP Values (SSE4.1). inline void dppd(const XmmReg& dst, const XmmReg& src, const Imm& imm8) { _emitInstruction(kX86InstDpPD, &dst, &src, &imm8); } //! @brief Dot Product of Packed DP-FP Values (SSE4.1). inline void dppd(const XmmReg& dst, const Mem& src, const Imm& imm8) { _emitInstruction(kX86InstDpPD, &dst, &src, &imm8); } //! @brief Dot Product of Packed SP-FP Values (SSE4.1). inline void dpps(const XmmReg& dst, const XmmReg& src, const Imm& imm8) { _emitInstruction(kX86InstDpPS, &dst, &src, &imm8); } //! @brief Dot Product of Packed SP-FP Values (SSE4.1). inline void dpps(const XmmReg& dst, const Mem& src, const Imm& imm8) { _emitInstruction(kX86InstDpPS, &dst, &src, &imm8); } //! @brief Extract Packed SP-FP Value (SSE4.1). inline void extractps(const XmmReg& dst, const XmmReg& src, const Imm& imm8) { _emitInstruction(kX86InstExtractPS, &dst, &src, &imm8); } //! @brief Extract Packed SP-FP Value (SSE4.1). inline void extractps(const XmmReg& dst, const Mem& src, const Imm& imm8) { _emitInstruction(kX86InstExtractPS, &dst, &src, &imm8); } //! @brief Load Double Quadword Non-Temporal Aligned Hint (SSE4.1). inline void movntdqa(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstMovNTDQA, &dst, &src); } //! @brief Compute Multiple Packed Sums of Absolute Difference (SSE4.1). inline void mpsadbw(const XmmReg& dst, const XmmReg& src, const Imm& imm8) { _emitInstruction(kX86InstMPSADBW, &dst, &src, &imm8); } //! @brief Compute Multiple Packed Sums of Absolute Difference (SSE4.1). inline void mpsadbw(const XmmReg& dst, const Mem& src, const Imm& imm8) { _emitInstruction(kX86InstMPSADBW, &dst, &src, &imm8); } //! @brief Pack with Unsigned Saturation (SSE4.1). inline void packusdw(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstPackUSDW, &dst, &src); } //! @brief Pack with Unsigned Saturation (SSE4.1). inline void packusdw(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstPackUSDW, &dst, &src); } //! @brief Variable Blend Packed Bytes (SSE4.1). inline void pblendvb(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstPBlendVB, &dst, &src); } //! @brief Variable Blend Packed Bytes (SSE4.1). inline void pblendvb(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstPBlendVB, &dst, &src); } //! @brief Blend Packed Words (SSE4.1). inline void pblendw(const XmmReg& dst, const XmmReg& src, const Imm& imm8) { _emitInstruction(kX86InstPBlendW, &dst, &src, &imm8); } //! @brief Blend Packed Words (SSE4.1). inline void pblendw(const XmmReg& dst, const Mem& src, const Imm& imm8) { _emitInstruction(kX86InstPBlendW, &dst, &src, &imm8); } //! @brief Compare Packed Qword Data for Equal (SSE4.1). inline void pcmpeqq(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstPCmpEqQ, &dst, &src); } //! @brief Compare Packed Qword Data for Equal (SSE4.1). inline void pcmpeqq(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstPCmpEqQ, &dst, &src); } //! @brief Extract Byte (SSE4.1). inline void pextrb(const GpReg& dst, const XmmReg& src, const Imm& imm8) { _emitInstruction(kX86InstPExtrB, &dst, &src, &imm8); } //! @brief Extract Byte (SSE4.1). inline void pextrb(const Mem& dst, const XmmReg& src, const Imm& imm8) { _emitInstruction(kX86InstPExtrB, &dst, &src, &imm8); } //! @brief Extract Dword (SSE4.1). inline void pextrd(const GpReg& dst, const XmmReg& src, const Imm& imm8) { _emitInstruction(kX86InstPExtrD, &dst, &src, &imm8); } //! @brief Extract Dword (SSE4.1). inline void pextrd(const Mem& dst, const XmmReg& src, const Imm& imm8) { _emitInstruction(kX86InstPExtrD, &dst, &src, &imm8); } //! @brief Extract Dword (SSE4.1). inline void pextrq(const GpReg& dst, const XmmReg& src, const Imm& imm8) { _emitInstruction(kX86InstPExtrQ, &dst, &src, &imm8); } //! @brief Extract Dword (SSE4.1). inline void pextrq(const Mem& dst, const XmmReg& src, const Imm& imm8) { _emitInstruction(kX86InstPExtrQ, &dst, &src, &imm8); } //! @brief Extract Word (SSE4.1). inline void pextrw(const GpReg& dst, const XmmReg& src, const Imm& imm8) { _emitInstruction(kX86InstPExtrW, &dst, &src, &imm8); } //! @brief Extract Word (SSE4.1). inline void pextrw(const Mem& dst, const XmmReg& src, const Imm& imm8) { _emitInstruction(kX86InstPExtrW, &dst, &src, &imm8); } //! @brief Packed Horizontal Word Minimum (SSE4.1). inline void phminposuw(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstPHMinPOSUW, &dst, &src); } //! @brief Packed Horizontal Word Minimum (SSE4.1). inline void phminposuw(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstPHMinPOSUW, &dst, &src); } //! @brief Insert Byte (SSE4.1). inline void pinsrb(const XmmReg& dst, const GpReg& src, const Imm& imm8) { _emitInstruction(kX86InstPInsRB, &dst, &src, &imm8); } //! @brief Insert Byte (SSE4.1). inline void pinsrb(const XmmReg& dst, const Mem& src, const Imm& imm8) { _emitInstruction(kX86InstPInsRB, &dst, &src, &imm8); } //! @brief Insert Dword (SSE4.1). inline void pinsrd(const XmmReg& dst, const GpReg& src, const Imm& imm8) { _emitInstruction(kX86InstPInsRD, &dst, &src, &imm8); } //! @brief Insert Dword (SSE4.1). inline void pinsrd(const XmmReg& dst, const Mem& src, const Imm& imm8) { _emitInstruction(kX86InstPInsRD, &dst, &src, &imm8); } //! @brief Insert Dword (SSE4.1). inline void pinsrq(const XmmReg& dst, const GpReg& src, const Imm& imm8) { _emitInstruction(kX86InstPInsRQ, &dst, &src, &imm8); } //! @brief Insert Dword (SSE4.1). inline void pinsrq(const XmmReg& dst, const Mem& src, const Imm& imm8) { _emitInstruction(kX86InstPInsRQ, &dst, &src, &imm8); } //! @brief Insert Word (SSE2). inline void pinsrw(const XmmReg& dst, const GpReg& src, const Imm& imm8) { _emitInstruction(kX86InstPInsRW, &dst, &src, &imm8); } //! @brief Insert Word (SSE2). inline void pinsrw(const XmmReg& dst, const Mem& src, const Imm& imm8) { _emitInstruction(kX86InstPInsRW, &dst, &src, &imm8); } //! @brief Maximum of Packed Word Integers (SSE4.1). inline void pmaxuw(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstPMaxUW, &dst, &src); } //! @brief Maximum of Packed Word Integers (SSE4.1). inline void pmaxuw(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstPMaxUW, &dst, &src); } //! @brief Maximum of Packed Signed Byte Integers (SSE4.1). inline void pmaxsb(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstPMaxSB, &dst, &src); } //! @brief Maximum of Packed Signed Byte Integers (SSE4.1). inline void pmaxsb(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstPMaxSB, &dst, &src); } //! @brief Maximum of Packed Signed Dword Integers (SSE4.1). inline void pmaxsd(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstPMaxSD, &dst, &src); } //! @brief Maximum of Packed Signed Dword Integers (SSE4.1). inline void pmaxsd(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstPMaxSD, &dst, &src); } //! @brief Maximum of Packed Unsigned Dword Integers (SSE4.1). inline void pmaxud(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstPMaxUD, &dst, &src); } //! @brief Maximum of Packed Unsigned Dword Integers (SSE4.1). inline void pmaxud(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstPMaxUD, &dst, &src); } //! @brief Minimum of Packed Signed Byte Integers (SSE4.1). inline void pminsb(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstPMinSB, &dst, &src); } //! @brief Minimum of Packed Signed Byte Integers (SSE4.1). inline void pminsb(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstPMinSB, &dst, &src); } //! @brief Minimum of Packed Word Integers (SSE4.1). inline void pminuw(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstPMinUW, &dst, &src); } //! @brief Minimum of Packed Word Integers (SSE4.1). inline void pminuw(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstPMinUW, &dst, &src); } //! @brief Minimum of Packed Dword Integers (SSE4.1). inline void pminud(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstPMinUD, &dst, &src); } //! @brief Minimum of Packed Dword Integers (SSE4.1). inline void pminud(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstPMinUD, &dst, &src); } //! @brief Minimum of Packed Dword Integers (SSE4.1). inline void pminsd(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstPMinSD, &dst, &src); } //! @brief Minimum of Packed Dword Integers (SSE4.1). inline void pminsd(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstPMinSD, &dst, &src); } //! @brief Packed Move with Sign Extend (SSE4.1). inline void pmovsxbw(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstPMovSXBW, &dst, &src); } //! @brief Packed Move with Sign Extend (SSE4.1). inline void pmovsxbw(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstPMovSXBW, &dst, &src); } //! @brief Packed Move with Sign Extend (SSE4.1). inline void pmovsxbd(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstPMovSXBD, &dst, &src); } //! @brief Packed Move with Sign Extend (SSE4.1). inline void pmovsxbd(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstPMovSXBD, &dst, &src); } //! @brief Packed Move with Sign Extend (SSE4.1). inline void pmovsxbq(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstPMovSXBQ, &dst, &src); } //! @brief Packed Move with Sign Extend (SSE4.1). inline void pmovsxbq(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstPMovSXBQ, &dst, &src); } //! @brief Packed Move with Sign Extend (SSE4.1). inline void pmovsxwd(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstPMovSXWD, &dst, &src); } //! @brief Packed Move with Sign Extend (SSE4.1). inline void pmovsxwd(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstPMovSXWD, &dst, &src); } //! @brief (SSE4.1). inline void pmovsxwq(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstPMovSXWQ, &dst, &src); } //! @brief (SSE4.1). inline void pmovsxwq(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstPMovSXWQ, &dst, &src); } //! @brief (SSE4.1). inline void pmovsxdq(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstPMovSXDQ, &dst, &src); } //! @brief (SSE4.1). inline void pmovsxdq(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstPMovSXDQ, &dst, &src); } //! @brief Packed Move with Zero Extend (SSE4.1). inline void pmovzxbw(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstPMovZXBW, &dst, &src); } //! @brief Packed Move with Zero Extend (SSE4.1). inline void pmovzxbw(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstPMovZXBW, &dst, &src); } //! @brief Packed Move with Zero Extend (SSE4.1). inline void pmovzxbd(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstPMovZXBD, &dst, &src); } //! @brief Packed Move with Zero Extend (SSE4.1). inline void pmovzxbd(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstPMovZXBD, &dst, &src); } //! @brief Packed Move with Zero Extend (SSE4.1). inline void pmovzxbq(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstPMovZXBQ, &dst, &src); } //! @brief Packed Move with Zero Extend (SSE4.1). inline void pmovzxbq(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstPMovZXBQ, &dst, &src); } //! @brief Packed Move with Zero Extend (SSE4.1). inline void pmovzxwd(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstPMovZXWD, &dst, &src); } //! @brief Packed Move with Zero Extend (SSE4.1). inline void pmovzxwd(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstPMovZXWD, &dst, &src); } //! @brief (SSE4.1). inline void pmovzxwq(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstPMovZXWQ, &dst, &src); } //! @brief (SSE4.1). inline void pmovzxwq(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstPMovZXWQ, &dst, &src); } //! @brief (SSE4.1). inline void pmovzxdq(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstPMovZXDQ, &dst, &src); } //! @brief (SSE4.1). inline void pmovzxdq(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstPMovZXDQ, &dst, &src); } //! @brief Multiply Packed Signed Dword Integers (SSE4.1). inline void pmuldq(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstPMulDQ, &dst, &src); } //! @brief Multiply Packed Signed Dword Integers (SSE4.1). inline void pmuldq(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstPMulDQ, &dst, &src); } //! @brief Multiply Packed Signed Integers and Store Low Result (SSE4.1). inline void pmulld(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstPMulLD, &dst, &src); } //! @brief Multiply Packed Signed Integers and Store Low Result (SSE4.1). inline void pmulld(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstPMulLD, &dst, &src); } //! @brief Logical Compare (SSE4.1). inline void ptest(const XmmReg& op1, const XmmReg& op2) { _emitInstruction(kX86InstPTest, &op1, &op2); } //! @brief Logical Compare (SSE4.1). inline void ptest(const XmmReg& op1, const Mem& op2) { _emitInstruction(kX86InstPTest, &op1, &op2); } //! Round Packed SP-FP Values @brief (SSE4.1). inline void roundps(const XmmReg& dst, const XmmReg& src, const Imm& imm8) { _emitInstruction(kX86InstRoundPS, &dst, &src, &imm8); } //! Round Packed SP-FP Values @brief (SSE4.1). inline void roundps(const XmmReg& dst, const Mem& src, const Imm& imm8) { _emitInstruction(kX86InstRoundPS, &dst, &src, &imm8); } //! @brief Round Scalar SP-FP Values (SSE4.1). inline void roundss(const XmmReg& dst, const XmmReg& src, const Imm& imm8) { _emitInstruction(kX86InstRoundSS, &dst, &src, &imm8); } //! @brief Round Scalar SP-FP Values (SSE4.1). inline void roundss(const XmmReg& dst, const Mem& src, const Imm& imm8) { _emitInstruction(kX86InstRoundSS, &dst, &src, &imm8); } //! @brief Round Packed DP-FP Values (SSE4.1). inline void roundpd(const XmmReg& dst, const XmmReg& src, const Imm& imm8) { _emitInstruction(kX86InstRoundPD, &dst, &src, &imm8); } //! @brief Round Packed DP-FP Values (SSE4.1). inline void roundpd(const XmmReg& dst, const Mem& src, const Imm& imm8) { _emitInstruction(kX86InstRoundPD, &dst, &src, &imm8); } //! @brief Round Scalar DP-FP Values (SSE4.1). inline void roundsd(const XmmReg& dst, const XmmReg& src, const Imm& imm8) { _emitInstruction(kX86InstRoundSD, &dst, &src, &imm8); } //! @brief Round Scalar DP-FP Values (SSE4.1). inline void roundsd(const XmmReg& dst, const Mem& src, const Imm& imm8) { _emitInstruction(kX86InstRoundSD, &dst, &src, &imm8); } // -------------------------------------------------------------------------- // [SSE4.2] // -------------------------------------------------------------------------- //! @brief Accumulate CRC32 Value (polynomial 0x11EDC6F41) (SSE4.2). inline void crc32(const GpReg& dst, const GpReg& src) { ASMJIT_ASSERT(dst.isRegType(kX86RegTypeGpd) || dst.isRegType(kX86RegTypeGpq)); _emitInstruction(kX86InstCrc32, &dst, &src); } //! @brief Accumulate CRC32 Value (polynomial 0x11EDC6F41) (SSE4.2). inline void crc32(const GpReg& dst, const Mem& src) { ASMJIT_ASSERT(dst.isRegType(kX86RegTypeGpd) || dst.isRegType(kX86RegTypeGpq)); _emitInstruction(kX86InstCrc32, &dst, &src); } //! @brief Packed Compare Explicit Length Strings, Return Index (SSE4.2). inline void pcmpestri(const XmmReg& dst, const XmmReg& src, const Imm& imm8) { _emitInstruction(kX86InstPCmpEStrI, &dst, &src, &imm8); } //! @brief Packed Compare Explicit Length Strings, Return Index (SSE4.2). inline void pcmpestri(const XmmReg& dst, const Mem& src, const Imm& imm8) { _emitInstruction(kX86InstPCmpEStrI, &dst, &src, &imm8); } //! @brief Packed Compare Explicit Length Strings, Return Mask (SSE4.2). inline void pcmpestrm(const XmmReg& dst, const XmmReg& src, const Imm& imm8) { _emitInstruction(kX86InstPCmpEStrM, &dst, &src, &imm8); } //! @brief Packed Compare Explicit Length Strings, Return Mask (SSE4.2). inline void pcmpestrm(const XmmReg& dst, const Mem& src, const Imm& imm8) { _emitInstruction(kX86InstPCmpEStrM, &dst, &src, &imm8); } //! @brief Packed Compare Implicit Length Strings, Return Index (SSE4.2). inline void pcmpistri(const XmmReg& dst, const XmmReg& src, const Imm& imm8) { _emitInstruction(kX86InstPCmpIStrI, &dst, &src, &imm8); } //! @brief Packed Compare Implicit Length Strings, Return Index (SSE4.2). inline void pcmpistri(const XmmReg& dst, const Mem& src, const Imm& imm8) { _emitInstruction(kX86InstPCmpIStrI, &dst, &src, &imm8); } //! @brief Packed Compare Implicit Length Strings, Return Mask (SSE4.2). inline void pcmpistrm(const XmmReg& dst, const XmmReg& src, const Imm& imm8) { _emitInstruction(kX86InstPCmpIStrM, &dst, &src, &imm8); } //! @brief Packed Compare Implicit Length Strings, Return Mask (SSE4.2). inline void pcmpistrm(const XmmReg& dst, const Mem& src, const Imm& imm8) { _emitInstruction(kX86InstPCmpIStrM, &dst, &src, &imm8); } //! @brief Compare Packed Data for Greater Than (SSE4.2). inline void pcmpgtq(const XmmReg& dst, const XmmReg& src) { _emitInstruction(kX86InstPCmpGtQ, &dst, &src); } //! @brief Compare Packed Data for Greater Than (SSE4.2). inline void pcmpgtq(const XmmReg& dst, const Mem& src) { _emitInstruction(kX86InstPCmpGtQ, &dst, &src); } //! @brief Return the Count of Number of Bits Set to 1 (SSE4.2). inline void popcnt(const GpReg& dst, const GpReg& src) { ASMJIT_ASSERT(!dst.isGpb()); ASMJIT_ASSERT(src.getRegType() == dst.getRegType()); _emitInstruction(kX86InstPopCnt, &dst, &src); } //! @brief Return the Count of Number of Bits Set to 1 (SSE4.2). inline void popcnt(const GpReg& dst, const Mem& src) { ASMJIT_ASSERT(!dst.isGpb()); _emitInstruction(kX86InstPopCnt, &dst, &src); } // ------------------------------------------------------------------------- // [AMD only] // ------------------------------------------------------------------------- //! @brief Prefetch (3dNow - Amd). //! //! Loads the entire 64-byte aligned memory sequence containing the //! specified memory address into the L1 data cache. The position of //! the specified memory address within the 64-byte cache line is //! irrelevant. If a cache hit occurs, or if a memory fault is detected, //! no bus cycle is initiated and the instruction is treated as a NOP. inline void amd_prefetch(const Mem& mem) { _emitInstruction(kX86InstAmdPrefetch, &mem); } //! @brief Prefetch and set cache to modified (3dNow - Amd). //! //! The PREFETCHW instruction loads the prefetched line and sets the //! cache-line state to Modified, in anticipation of subsequent data //! writes to the line. The PREFETCH instruction, by contrast, typically //! sets the cache-line state to Exclusive (depending on the hardware //! implementation). inline void amd_prefetchw(const Mem& mem) { _emitInstruction(kX86InstAmdPrefetchW, &mem); } // ------------------------------------------------------------------------- // [Intel only] // ------------------------------------------------------------------------- //! @brief Move Data After Swapping Bytes (SSE3 - Intel Atom). inline void movbe(const GpReg& dst, const Mem& src) { ASMJIT_ASSERT(!dst.isGpb()); _emitInstruction(kX86InstMovBE, &dst, &src); } //! @brief Move Data After Swapping Bytes (SSE3 - Intel Atom). inline void movbe(const Mem& dst, const GpReg& src) { ASMJIT_ASSERT(!src.isGpb()); _emitInstruction(kX86InstMovBE, &dst, &src); } // ------------------------------------------------------------------------- // [Emit Options] // ------------------------------------------------------------------------- //! @brief Assert LOCK# Signal Prefix. //! //! This instruction causes the processor's LOCK# signal to be asserted //! during execution of the accompanying instruction (turns the //! instruction into an atomic instruction). In a multiprocessor environment, //! the LOCK# signal insures that the processor has exclusive use of any shared //! memory while the signal is asserted. //! //! The LOCK prefix can be prepended only to the following instructions and //! to those forms of the instructions that use a memory operand: ADD, ADC, //! AND, BTC, BTR, BTS, CMPXCHG, DEC, INC, NEG, NOT, OR, SBB, SUB, XOR, XADD, //! and XCHG. An undefined opcode exception will be generated if the LOCK //! prefix is used with any other instruction. The XCHG instruction always //! asserts the LOCK# signal regardless of the presence or absence of the LOCK //! prefix. //! //! @sa @c kX86EmitOptionLock. inline void lock() { _emitOptions |= kX86EmitOptionLock; } //! @brief Force REX prefix to be emitted. //! //! This option should be used carefully, because there are unencodable //! combinations. If you want to access ah, bh, ch or dh registers then you //! can't emit REX prefix and it will cause an illegal instruction error. //! //! @note REX prefix is only valid for X64/AMD64 platform. //! //! @sa @c kX86EmitOptionRex. inline void rex() { _emitOptions |= kX86EmitOptionRex; } }; //! @} } // AsmJit namespace // [Api-End] #include "../core/apiend.h" // [Guard] #endif // _ASMJIT_X86_X86ASSEMBLER_H desmume/src/wifi.cpp000664 001750 001750 00000174341 12755534123 015613 0ustar00sergiosergio000000 000000 /* Copyright (C) 2007 Tim Seidel Copyright (C) 2008-2015 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the this software. If not, see . */ #include "types.h" #if defined(_WINDOWS) || defined(_WIN32) #include #include #define socket_t SOCKET #define sockaddr_t SOCKADDR #if defined(_WIN32) && !defined(_MSC_VER) #else #include "windriver.h" #endif #define PCAP_DEVICE_NAME description #elif !defined(VITA) #include #include #include #include #include #define socket_t int #define sockaddr_t struct sockaddr #define closesocket close #define PCAP_DEVICE_NAME name #endif #include "wifi.h" #include #include "utils/bits.h" #include "armcpu.h" #include "NDSSystem.h" #include "debug.h" #include "registers.h" #ifndef INVALID_SOCKET #define INVALID_SOCKET (socket_t)-1 #endif #define BASEPORT 7000 const u8 BroadcastMAC[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; bool bWFCUserWarned = false; #ifdef EXPERIMENTAL_WIFI_COMM socket_t wifi_socket = INVALID_SOCKET; sockaddr_t sendAddr; #ifndef WIN32 #include "pcap/pcap.h" #endif pcap_t *wifi_bridge = NULL; #endif //sometimes this isnt defined #ifndef PCAP_OPENFLAG_PROMISCUOUS #define PCAP_OPENFLAG_PROMISCUOUS 1 #endif static WifiHandler _defaultHandler; WifiHandler *CurrentWifiHandler = &_defaultHandler; wifimac_t wifiMac; SoftAP_t SoftAP; int wifi_lastmode; /******************************************************************************* WIFI TODO - emulate transmission delays for Beacon and Extra transfers - emulate delays when receiving as well (may need some queuing system) - take transfer rate and preamble into account - figure out RFSTATUS and RFPINS *******************************************************************************/ /******************************************************************************* Firmware info needed for if no firmware image is available see: http://www.akkit.org/info/dswifi.htm#WifiInit written in bytes, to avoid endianess issues *******************************************************************************/ u8 FW_Mac[6] = { 0x00, 0x09, 0xBF, 0x12, 0x34, 0x56 }; const u8 FW_WIFIInit[32] = { 0x02,0x00, 0x17,0x00, 0x26,0x00, 0x18,0x18, 0x48,0x00, 0x40,0x48, 0x58,0x00, 0x42,0x00, 0x40,0x01, 0x64,0x80, 0xE0,0xE0, 0x43,0x24, 0x0E,0x00, 0x32,0x00, 0xF4,0x01, 0x01,0x01 }; const u8 FW_BBInit[105] = { 0x6D, 0x9E, 0x40, 0x05, 0x1B, 0x6C, 0x48, 0x80, 0x38, 0x00, 0x35, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x00, 0x04, 0x01, 0xd8, 0xff, 0xff, 0xc7, 0xbb, 0x01, 0xb6, 0x7f, 0x5a, 0x01, 0x3f, 0x01, 0x3f, 0x36, 0x36, 0x00, 0x78, 0x28, 0x55, 0x08, 0x28, 0x16, 0x00, 0x01, 0x0e, 0x20, 0x02, 0x98, 0x98, 0x1f, 0x0a, 0x08, 0x04, 0x01, 0x00, 0x00, 0x00, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xfe, 0xfc, 0xfa, 0xfa, 0xf8, 0xf8, 0xf6, 0xa5, 0x12, 0x14, 0x12, 0x41, 0x23, 0x03, 0x04, 0x70, 0x35, 0x0E, 0x16, 0x16, 0x00, 0x00, 0x06, 0x01, 0xff, 0xfe, 0xff, 0xff, 0x00, 0x0e, 0x13, 0x00, 0x00, 0x28, 0x1c }; const u8 FW_RFInit[36] = { 0x07, 0xC0, 0x00, 0x03, 0x9C, 0x12, 0x28, 0x17, 0x14, 0xba, 0xe8, 0x1a, 0x6f, 0x45, 0x1d, 0xfa, 0xff, 0x23, 0x30, 0x1d, 0x24, 0x01, 0x00, 0x28, 0x00, 0x00, 0x2c, 0x03, 0x9c, 0x06, 0x22, 0x00, 0x08, 0x6f, 0xff, 0x0d }; const u8 FW_RFChannel[6*14] = { 0x28, 0x17, 0x14, /* Channel 1 */ 0xba, 0xe8, 0x1a, 0x37, 0x17, 0x14, /* Channel 2 */ 0x46, 0x17, 0x19, 0x45, 0x17, 0x14, /* Channel 3 */ 0xd1, 0x45, 0x1b, 0x54, 0x17, 0x14, /* Channel 4 */ 0x5d, 0x74, 0x19, 0x62, 0x17, 0x14, /* Channel 5 */ 0xe9, 0xa2, 0x1b, 0x71, 0x17, 0x14, /* Channel 6 */ 0x74, 0xd1, 0x19, 0x80, 0x17, 0x14, /* Channel 7 */ 0x00, 0x00, 0x18, 0x8e, 0x17, 0x14, /* Channel 8 */ 0x8c, 0x2e, 0x1a, 0x9d, 0x17, 0x14, /* Channel 9 */ 0x17, 0x5d, 0x18, 0xab, 0x17, 0x14, /* Channel 10 */ 0xa3, 0x8b, 0x1a, 0xba, 0x17, 0x14, /* Channel 11 */ 0x2f, 0xba, 0x18, 0xc8, 0x17, 0x14, /* Channel 12 */ 0xba, 0xe8, 0x1a, 0xd7, 0x17, 0x14, /* Channel 13 */ 0x46, 0x17, 0x19, 0xfa, 0x17, 0x14, /* Channel 14 */ 0x2f, 0xba, 0x18 }; const u8 FW_BBChannel[14] = { 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, /* channel 1- 6 */ 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, /* channel 7-10 */ 0xb5, 0xb5, /* channel 11-12 */ 0xb6, 0xb6 /* channel 13-14 */ }; FW_WFCProfile FW_WFCProfile1 = {"SoftAP", "", "", "", "", "", {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, 0, "", 0, 0, 0, {0, 0, 0, 0, 0, 0, 0}, 0, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0} }; FW_WFCProfile FW_WFCProfile2 = {"", "", "", "", "", "", {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, 0, "", 0, 0, 0xFF, {0, 0, 0, 0, 0, 0, 0}, 0, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0} }; FW_WFCProfile FW_WFCProfile3 = {"", "", "", "", "", "", {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, 0, "", 0, 0, 0xFF, {0, 0, 0, 0, 0, 0, 0}, 0, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0} }; /******************************************************************************* Communication interface *******************************************************************************/ struct WifiComInterface { bool (*Init)(); void (*DeInit)(); void (*Reset)(); void (*SendPacket)(u8* packet, u32 len); void (*msTrigger)(); }; #ifdef EXPERIMENTAL_WIFI_COMM bool SoftAP_Init(); void SoftAP_DeInit(); void SoftAP_Reset(); void SoftAP_SendPacket(u8 *packet, u32 len); void SoftAP_msTrigger(); WifiComInterface CI_SoftAP = { SoftAP_Init, SoftAP_DeInit, SoftAP_Reset, SoftAP_SendPacket, SoftAP_msTrigger }; bool Adhoc_Init(); void Adhoc_DeInit(); void Adhoc_Reset(); void Adhoc_SendPacket(u8* packet, u32 len); void Adhoc_msTrigger(); WifiComInterface CI_Adhoc = { Adhoc_Init, Adhoc_DeInit, Adhoc_Reset, Adhoc_SendPacket, Adhoc_msTrigger }; #endif WifiComInterface* wifiComs[] = { #ifdef EXPERIMENTAL_WIFI_COMM &CI_Adhoc, &CI_SoftAP, #endif NULL }; WifiComInterface* wifiCom; /******************************************************************************* Logging *******************************************************************************/ // 0: disable logging // 1: lowest logging, shows most important messages such as errors // 2: low logging, shows things such as warnings // 3: medium logging, for debugging, shows lots of stuff // 4: high logging, for debugging, shows almost everything, may slow down // 5: highest logging, for debugging, shows everything, may slow down a lot #define WIFI_LOGGING_LEVEL 3 #define WIFI_LOG_USE_LOGC 0 #define WIFI_LOG(level, ...) {} /******************************************************************************* Hax *******************************************************************************/ // TODO: find the right value // GBAtek says it is 10µs, however that value seems too small // (MP host sends floods of data frames, clients can't keep up) // 100 would make more sense since CMDCOUNT is set to 166 // that would be 16.6ms ~= 1 frame // however this is guessed, like a lot of the wifi here #define WIFI_CMDCOUNT_SLICE 100 /******************************************************************************* Helpers *******************************************************************************/ INLINE u32 WIFI_alignedLen(u32 len) { return ((len + 3) & ~3); } // Fast MAC compares INLINE bool WIFI_compareMAC(u8* a, u8* b) { return ((*(u32*)&a[0]) == (*(u32*)&b[0])) && ((*(u16*)&a[4]) == (*(u16*)&b[4])); } INLINE bool WIFI_isBroadcastMAC(u8* a) { return (a[0] & 0x01); //return ((*(u32*)&a[0]) == 0xFFFFFFFF) && ((*(u16*)&a[4]) == 0xFFFF); } /******************************************************************************* CRC32 (http://www.codeproject.com/KB/recipes/crc32_large.aspx) *******************************************************************************/ u32 WIFI_CRC32Table[256]; static u32 reflect(u32 ref, char ch) { u32 value = 0; for(int i = 1; i < (ch + 1); i++) { if (ref & 1) value |= 1 << (ch - i); ref >>= 1; } return value; } static u32 WIFI_calcCRC32(u8 *data, int len) { u32 crc = 0xFFFFFFFF; while(len--) crc = (crc >> 8) ^ WIFI_CRC32Table[(crc & 0xFF) ^ *data++]; return (crc ^ 0xFFFFFFFF); } static void WIFI_initCRC32Table() { static bool initialized = false; if(initialized) return; initialized = true; u32 polynomial = 0x04C11DB7; for(int i = 0; i < 0x100; i++) { WIFI_CRC32Table[i] = reflect(i, 8) << 24; for(int j = 0; j < 8; j++) WIFI_CRC32Table[i] = (WIFI_CRC32Table[i] << 1) ^ (WIFI_CRC32Table[i] & (1 << 31) ? polynomial : 0); WIFI_CRC32Table[i] = reflect(WIFI_CRC32Table[i], 32); } } /******************************************************************************* RF-Chip *******************************************************************************/ static void WIFI_resetRF(rffilter_t *rf) { /* reinitialize RF chip with the default values refer RF2958 docs */ /* CFG1 */ rf->CFG1.bits.IF_VGA_REG_EN = 1; rf->CFG1.bits.IF_VCO_REG_EN = 1; rf->CFG1.bits.RF_VCO_REG_EN = 1; rf->CFG1.bits.HYBERNATE = 0; rf->CFG1.bits.REF_SEL = 0; /* IFPLL1 */ rf->IFPLL1.bits.DAC = 3; rf->IFPLL1.bits.P1 = 0; rf->IFPLL1.bits.LD_EN1 = 0; rf->IFPLL1.bits.AUTOCAL_EN1 = 0; rf->IFPLL1.bits.PDP1 = 1; rf->IFPLL1.bits.CPL1 = 0; rf->IFPLL1.bits.LPF1 = 0; rf->IFPLL1.bits.VTC_EN1 = 1; rf->IFPLL1.bits.KV_EN1 = 0; rf->IFPLL1.bits.PLL_EN1 = 0; /* IFPLL2 */ rf->IFPLL2.bits.IF_N = 0x22; /* IFPLL3 */ rf->IFPLL3.bits.KV_DEF1 = 8; rf->IFPLL3.bits.CT_DEF1 = 7; rf->IFPLL3.bits.DN1 = 0x1FF; /* RFPLL1 */ rf->RFPLL1.bits.DAC = 3; rf->RFPLL1.bits.P = 0; rf->RFPLL1.bits.LD_EN = 0; rf->RFPLL1.bits.AUTOCAL_EN = 0; rf->RFPLL1.bits.PDP = 1; rf->RFPLL1.bits.CPL = 0; rf->RFPLL1.bits.LPF = 0; rf->RFPLL1.bits.VTC_EN = 0; rf->RFPLL1.bits.KV_EN = 0; rf->RFPLL1.bits.PLL_EN = 0; /* RFPLL2 */ rf->RFPLL2.bits.NUM2 = 0; rf->RFPLL2.bits.N2 = 0x5E; /* RFPLL3 */ rf->RFPLL3.bits.NUM2 = 0; /* RFPLL4 */ rf->RFPLL4.bits.KV_DEF = 8; rf->RFPLL4.bits.CT_DEF = 7; rf->RFPLL4.bits.DN = 0x145; /* CAL1 */ rf->CAL1.bits.LD_WINDOW = 2; rf->CAL1.bits.M_CT_VALUE = 8; rf->CAL1.bits.TLOCK = 7; rf->CAL1.bits.TVCO = 0x0F; /* TXRX1 */ rf->TXRX1.bits.TXBYPASS = 0; rf->TXRX1.bits.INTBIASEN = 0; rf->TXRX1.bits.TXENMODE = 0; rf->TXRX1.bits.TXDIFFMODE = 0; rf->TXRX1.bits.TXLPFBW = 2; rf->TXRX1.bits.RXLPFBW = 2; rf->TXRX1.bits.TXVGC = 0; rf->TXRX1.bits.PCONTROL = 0; rf->TXRX1.bits.RXDCFBBYPS = 0; /* PCNT1 */ rf->PCNT1.bits.TX_DELAY = 0; rf->PCNT1.bits.PC_OFFSET = 0; rf->PCNT1.bits.P_DESIRED = 0; rf->PCNT1.bits.MID_BIAS = 0; /* PCNT2 */ rf->PCNT2.bits.MIN_POWER = 0; rf->PCNT2.bits.MID_POWER = 0; rf->PCNT2.bits.MAX_POWER = 0; /* VCOT1 */ rf->VCOT1.bits.AUX1 = 0; rf->VCOT1.bits.AUX = 0; } void WIFI_setRF_CNT(u16 val) { if (!wifiMac.rfIOStatus.bits.busy) wifiMac.rfIOCnt.val = val; } void WIFI_setRF_DATA(u16 val, u8 part) { if (!wifiMac.rfIOStatus.bits.busy) { rfIOData_t *rfreg = (rfIOData_t *)&wifiMac.RF; switch (wifiMac.rfIOCnt.bits.readOperation) { case 1: /* read from RF chip */ /* low part of data is ignored on reads */ /* on high part, the address is read, and the data at this is written back */ if (part==1) { wifiMac.rfIOData.array16[part] = val; if (wifiMac.rfIOData.bits.address > (sizeof(wifiMac.RF) / 4)) return; /* out of bound */ /* get content of the addressed register */ wifiMac.rfIOData.bits.content = rfreg[wifiMac.rfIOData.bits.address].bits.content; } break; case 0: /* write to RF chip */ wifiMac.rfIOData.array16[part] = val; if (wifiMac.rfIOData.bits.address > (sizeof(wifiMac.RF) / 4)) return; /* out of bound */ /* the actual transfer is done on high part write */ if (part==1) { switch (wifiMac.rfIOData.bits.address) { case 5: /* write to upper part of the frequency filter */ case 6: /* write to lower part of the frequency filter */ { u32 channelFreqN; rfreg[wifiMac.rfIOData.bits.address].bits.content = wifiMac.rfIOData.bits.content; /* get the complete rfpll.n */ channelFreqN = (u32)wifiMac.RF.RFPLL3.bits.NUM2 + ((u32)wifiMac.RF.RFPLL2.bits.NUM2 << 18) + ((u32)wifiMac.RF.RFPLL2.bits.N2 << 24); /* frequency setting is out of range */ if (channelFreqN<0x00A2E8BA) return; /* substract base frequency (channel 1) */ channelFreqN -= 0x00A2E8BA; } return; case 13: /* special purpose register: TEST1, on write, the RF chip resets */ WIFI_resetRF(&wifiMac.RF); return; } /* set content of the addressed register */ rfreg[wifiMac.rfIOData.bits.address].bits.content = wifiMac.rfIOData.bits.content; } break; } } } u16 WIFI_getRF_DATA(u8 part) { if (!wifiMac.rfIOStatus.bits.busy) return wifiMac.rfIOData.array16[part]; else /* data is not (yet) available */ return 0; } u16 WIFI_getRF_STATUS() { return wifiMac.rfIOStatus.val; } /******************************************************************************* BB-Chip *******************************************************************************/ void WIFI_setBB_CNT(u16 val) { wifiMac.bbIOCnt.val = val; if(wifiMac.bbIOCnt.bits.mode == 1) wifiMac.BB.data[wifiMac.bbIOCnt.bits.address] = WIFI_IOREG(REG_WIFI_BBWRITE); } u8 WIFI_getBB_DATA() { if((!wifiMac.bbIOCnt.bits.enable) || (wifiMac.bbIOCnt.bits.mode != 2)) return 0; return wifiMac.BB.data[wifiMac.bbIOCnt.bits.address]; } /******************************************************************************* wifimac IO: a lot of the wifi regs are action registers, that are mirrored without action, so the default IO via MMU.c does not seem to be very suitable all registers are 16 bit *******************************************************************************/ static void WIFI_TXStart(u32 slot); static void WIFI_triggerIRQMask(u16 mask) { u16 oResult,nResult; oResult = wifiMac.IE & wifiMac.IF; wifiMac.IF = wifiMac.IF | (mask & ~0x0400); nResult = wifiMac.IE & wifiMac.IF; if (!oResult && nResult) { NDS_makeIrq(ARMCPU_ARM7,IRQ_BIT_ARM7_WIFI); /* cascade it via arm7 wifi irq */ } } static void WIFI_triggerIRQ(u8 irq) { switch (irq) { case WIFI_IRQ_TXSTART: break; case WIFI_IRQ_TIMEPREBEACON: if (wifiMac.TXPower & 0x0001) { //wifiMac.rfStatus = 1; //wifiMac.rfPins = 0x0084; } break; case WIFI_IRQ_TIMEBEACON: wifiMac.BeaconCount1 = wifiMac.BeaconInterval; if (wifiMac.ucmpEnable) { wifiMac.BeaconCount2 = 0xFFFF; wifiMac.TXCnt &= 0xFFF2; WIFI_TXStart(WIFI_TXSLOT_BEACON); if (wifiMac.ListenCount == 0) wifiMac.ListenCount = wifiMac.ListenInterval; wifiMac.ListenCount--; } break; case WIFI_IRQ_TIMEPOSTBEACON: if (wifiMac.TXPower & 0x0002) { //wifiMac.rfStatus = 9; //wifiMac.rfPins = 0x0004; } break; case WIFI_IRQ_UNK: WIFI_LOG(3, "IRQ 12 triggered.\n"); break; } WIFI_triggerIRQMask(1<DeInit(); } void WIFI_Reset() { #ifdef EXPERIMENTAL_WIFI_COMM //memset(&wifiMac, 0, sizeof(wifimac_t)); WIFI_resetRF(&wifiMac.RF); memset(wifiMac.IOPorts, 0, sizeof(wifiMac.IOPorts)); wifiMac.randomSeed = 1; wifiMac.crystalEnabled = FALSE; wifiMac.powerOn = FALSE; wifiMac.powerOnPending = FALSE; wifiMac.GlobalUsecTimer = wifiMac.usec = wifiMac.ucmp = 0ULL; //wifiMac.rfStatus = 0x0000; //wifiMac.rfPins = 0x0004; wifiMac.rfStatus = 0x0009; wifiMac.rfPins = 0x00C6; memset(wifiMac.TXSlots, 0, sizeof(wifiMac.TXSlots)); wifiMac.TXCurSlot = -1; wifiMac.TXCnt = wifiMac.TXStat = wifiMac.TXSeqNo = wifiMac.TXBusy = 0; while (!wifiMac.RXPacketQueue.empty()) wifiMac.RXPacketQueue.pop(); if((u32)CommonSettings.wifi.mode >= ARRAY_SIZE(wifiComs)) CommonSettings.wifi.mode = 0; if (wifiCom && (wifi_lastmode != CommonSettings.wifi.mode)) wifiCom->DeInit(); wifiCom = wifiComs[CommonSettings.wifi.mode]; if (wifiCom && (wifi_lastmode != CommonSettings.wifi.mode)) wifiCom->Init(); else if (wifiCom) wifiCom->Reset(); wifi_lastmode = CommonSettings.wifi.mode; bWFCUserWarned = false; #endif } INLINE u16 WIFI_GetRXFlags(u8* packet) { u16 ret = 0x0010; u16 frameCtl = *(u16*)&packet[0]; u32 bssid_offset = 10; frameCtl &= 0xE7FF; switch(frameCtl & 0x000C) { case 0x0000: // Management frame { bssid_offset = 16; if ((frameCtl & 0x00F0) == 0x0080) ret |= 0x0001; } break; case 0x0004: // Control frame ret |= 0x0005; break; case 0x0008: // Data frame { switch (frameCtl & 0x0300) { case 0x0000: bssid_offset = 16; break; case 0x0100: bssid_offset = 4; break; case 0x0200: bssid_offset = 10; break; } if (frameCtl == 0x0228) ret |= 0x000C; else if (frameCtl == 0x0218) ret |= 0x000D; else if (frameCtl == 0x0118) ret |= 0x000E; else ret |= 0x0008; } break; } if (frameCtl & 0x0400) ret |= 0x0100; if (WIFI_compareMAC(&packet[bssid_offset], &wifiMac.bss.bytes[0])) ret |= 0x8000; return ret; } INLINE void WIFI_MakeRXHeader(u8* buf, u16 flags, u16 xferRate, u16 len, u8 maxRSSI, u8 minRSSI) { *(u16*)&buf[0] = flags; // Unknown, seems to always be 0x0040 // except with from-DS-to-STA data+cfpoll frames (0228) *(u16*)&buf[2] = ((flags & 0xF) == 0xC) ? 0x0000 : 0x0040; // random (probably left unchanged) //*(u16*)&buf[4] = 0x0000; *(u16*)&buf[6] = xferRate; *(u16*)&buf[8] = len; // idk about those, really buf[10] = 0x20;//maxRSSI; buf[11] = 0xA0;//minRSSI; } static void WIFI_RXPutWord(u16 val) { /* abort when RX data queuing is not enabled */ if (!(wifiMac.RXCnt & 0x8000)) return; /* write the data to cursor position */ wifiMac.RAM[wifiMac.RXWriteCursor & 0xFFF] = val; /* move cursor by one */ wifiMac.RXWriteCursor++; /* wrap around */ if(wifiMac.RXWriteCursor >= (wifiMac.RXRangeEnd >> 1)) wifiMac.RXWriteCursor = (wifiMac.RXRangeBegin >> 1); wifiMac.RXTXAddr = wifiMac.RXWriteCursor; } #ifdef EXPERIMENTAL_WIFI_COMM static void WIFI_RXQueuePacket(u8* packet, u32 len) { if (!(wifiMac.RXCnt & 0x8000)) return; Wifi_RXPacket pkt; pkt.Data = packet; pkt.RemHWords = (len - 11) >> 1; pkt.CurOffset = 12; pkt.NotStarted = true; wifiMac.RXPacketQueue.push(pkt); } #endif template static void WIFI_IncrementRXStat() { u16 bitmasks[] = { 0x0001, 0, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, 0, 0x0100, 0, 0x0200, 0x0400, 0x0800, 0x1000}; u16 bitmask = bitmasks[stat]; wifiMac.RXStat[stat]++; if (wifiMac.RXStatIncIE & bitmask) { wifiMac.RXStatIncIF |= bitmask; WIFI_triggerIRQ(WIFI_IRQ_RXINC); } if (wifiMac.RXStat[stat] & 0x80) { if (wifiMac.RXStatOvfIE & bitmask) { wifiMac.RXStatOvfIF |= bitmask; WIFI_triggerIRQ(WIFI_IRQ_RXOVF); } } } // TODO: find out if this is correct at all // this was mostly guessed, like most of the MP reply functionality static void WIFI_DoAutoReply(u8* cmd) { cmd += 12; u16 frameCtl = *(u16*)&cmd[0] & 0xE7FF; if (frameCtl == 0x0228) { // if the packet we got is a multiplayer command (data+cf-poll), // check if it was destined to us u16 slaveflags = *(u16*)&cmd[24 + 2]; if (!(slaveflags & (1 << wifiMac.pid))) return; // if it was destined to us, (try to) send a reply u16 regval = WIFI_IOREG(REG_WIFI_TXBUF_REPLY1); wifiMac.TXSlots[WIFI_TXSLOT_MPREPLY].RegVal = regval; regval &= 0x0FFF; wifiMac.RAM[regval + 6 + 1] = *(u16*)&cmd[24]; WIFI_TXStart(WIFI_TXSLOT_MPREPLY); } /*else if (frameCtl == 0x0118) { // broadcast MP ACK // this packet appears to be sent automatically // PS: nope. Enabling this code causes NSMB to break the connection even quicker. // Probably it should send the ACK itself whenever it wants to... u8 ack[32]; *(u16*)&ack[0] = 0x0218; *(u16*)&ack[2] = 0x0000; *(u16*)&ack[4] = 0x0903; *(u16*)&ack[6] = 0x00BF; *(u16*)&ack[8] = 0x0300; memcpy(&ack[10], &wifiMac.mac.bytes[0], 6); memcpy(&ack[16], &wifiMac.mac.bytes[0], 6); *(u16*)&ack[22] = wifiMac.TXSeqNo << 4; wifiMac.TXSeqNo++; *(u16*)&ack[24] = 0x0555; // lol random *(u16*)&ack[26] = 0x0000; *(u32*)&ack[28] = 0x00000000; wifiCom->SendPacket(ack, 32); }*/ } static void WIFI_TXStart(u32 slot) { WIFI_LOG(4, "TX slot %i trying to send a packet: TXCnt = %04X, TXBufLoc = %04X\n", slot, wifiMac.TXCnt, wifiMac.TXSlots[slot].RegVal); u16 reg = wifiMac.TXSlots[slot].RegVal; if (BIT15(reg)) { u16 address = reg & 0x0FFF; if (address > 0x1000-6) { WIFI_LOG(1, "TX slot %i trying to send a packet overflowing from the TX buffer (address %04X). Attempt ignored.\n", slot, (address << 1)); return; } u16 txLen = wifiMac.RAM[address+5] & 0x3FFF; if (txLen == 0) // zero length { WIFI_LOG(1, "TX slot %i trying to send a packet with length field set to zero. Attempt ignored.\n", slot); return; } u32 timemask = ((wifiMac.RAM[address+4] & 0xFF) == 20) ? 7 : 15; wifiMac.TXSlots[slot].CurAddr = address + 6; wifiMac.TXSlots[slot].RemHWords = (txLen + 1) >> 1; wifiMac.TXSlots[slot].RemPreamble = (BIT2(WIFI_IOREG(REG_WIFI_PREAMBLE)) && (timemask == 7)) ? 96 : 192; wifiMac.TXSlots[slot].TimeMask = timemask; wifiMac.TXSlots[slot].NotStarted = true; if (wifiMac.TXCurSlot < 0) wifiMac.TXCurSlot = slot; wifiMac.TXBusy |= (1 << slot); //wifiMac.rfStatus = 3; //wifiMac.rfPins = 0x0046; } } static void WIFI_PreTXAdjustments(u32 slot) { u16 reg = wifiMac.TXSlots[slot].RegVal; u16 address = reg & 0x0FFF; u16 txLen = wifiMac.RAM[address+5] & 0x3FFF; // Set sequence number if required if ((!BIT13(reg)) || (slot == WIFI_TXSLOT_BEACON)) { wifiMac.RAM[address + 6 + 11] = wifiMac.TXSeqNo << 4; wifiMac.TXSeqNo++; // TODO: find out when this happens (if it actually happens at all) // real-life NSMB multiplayer traffic capture shows no such behavior //if (slot == WIFI_TXSLOT_MPCMD) wifiMac.TXSeqNo++; } // Set timestamp (for beacons only) if (slot == WIFI_TXSLOT_BEACON) { *(u64*)&wifiMac.RAM[address + 6 + 12] = wifiMac.usec; //((u8*)wifiMac.RAM)[((address+6+12)<<1) + WIFI_IOREG(0x84)] = 0x01; } // TODO: check if this is correct // this sometimes happens in real world, but not always /*if (slot == WIFI_TXSLOT_MPREPLY) { wifiMac.RAM[address + 6 + 12] |= 0x8000; }*/ // Calculate and set FCS u32 crc32 = WIFI_calcCRC32((u8*)&wifiMac.RAM[address + 6], txLen - 4); *(u32*)&wifiMac.RAM[address + 6 + ((txLen-4) >> 1)] = crc32; } void WIFI_write16(u32 address, u16 val) { BOOL action = FALSE; if (!nds.power2.wifi) return; u32 page = address & 0x7000; // 0x2000 - 0x3FFF: unused if ((page >= 0x2000) && (page < 0x4000)) return; WIFI_LOG(5, "Write at address %08X, %04X\n", address, val); /*if (address == 0x04804008 && val == 0x0200) { printf("WIFI: Write at address %08X, %04X, pc=%08X\n", address, val, NDS_ARM7.instruct_adr); emu_halt(); }*/ // 0x4000 - 0x5FFF: wifi RAM if ((page >= 0x4000) && (page < 0x6000)) { /* access to the circular buffer */ address &= 0x1FFF; /*if (address >= 0x958 && address < (0x95A)) //address < (0x958+0x2A)) printf("PACKET[%04X] = %04X %08X %08X\n", NDS_ARM7.R[12], val, NDS_ARM7.R[14], NDS_ARM7.R[5]);*/ wifiMac.RAM[address >> 1] = val; return; } // anything else: I/O ports // only the first mirror (0x0000 - 0x0FFF) causes a special action if (page == 0x0000) action = TRUE; address &= 0x0FFF; switch (address) { case REG_WIFI_ID: break; case REG_WIFI_MODE: { u16 oldval = wifiMac.macMode; if (!BIT0(oldval) && BIT0(val)) { WIFI_IOREG(0x034) = 0x0002; wifiMac.rfPins = 0x0046; wifiMac.rfStatus = 0x0009; WIFI_IOREG(0x27C) = 0x0005; } if (BIT0(oldval) && !BIT0(val)) { WIFI_IOREG(0x27C) = 0x000A; } if (BIT13(val)) { WIFI_IOREG(REG_WIFI_WRITECSRLATCH) = 0x0000; WIFI_IOREG(0x0C0) = 0x0000; WIFI_IOREG(0x0C4) = 0x0000; WIFI_IOREG(REG_WIFI_MAYBE_RATE) = 0x0000; WIFI_IOREG(0x278) = 0x000F; } if (BIT14(val)) { wifiMac.wepMode = 0x0000; wifiMac.TXStatCnt = 0x0000; WIFI_IOREG(REG_WIFI_0A) = 0x0000; wifiMac.mac.words[0] = 0x0000; wifiMac.mac.words[1] = 0x0000; wifiMac.mac.words[2] = 0x0000; wifiMac.bss.words[0] = 0x0000; wifiMac.bss.words[1] = 0x0000; wifiMac.bss.words[2] = 0x0000; wifiMac.pid = 0x0000; wifiMac.aid = 0x0000; WIFI_IOREG(REG_WIFI_RETRYLIMIT) = 0x0707; WIFI_IOREG(0x02E) = 0x0000; WIFI_IOREG(REG_WIFI_RXRANGEBEGIN) = 0x4000; WIFI_IOREG(REG_WIFI_RXRANGEEND) = 0x4800; wifiMac.RXRangeBegin = 0x0000; // 0x4000 wifiMac.RXRangeEnd = 0x0800; // 0x4800 WIFI_IOREG(0x084) = 0x0000; WIFI_IOREG(REG_WIFI_PREAMBLE) = 0x0001; WIFI_IOREG(REG_WIFI_RXFILTER) = 0x0401; WIFI_IOREG(0x0D4) = 0x0001; WIFI_IOREG(REG_WIFI_RXFILTER2) = 0x0008; WIFI_IOREG(0x0EC) = 0x3F03; WIFI_IOREG(0x194) = 0x0000; WIFI_IOREG(0x198) = 0x0000; WIFI_IOREG(0x1A2) = 0x0001; WIFI_IOREG(0x224) = 0x0003; WIFI_IOREG(0x230) = 0x0047; } wifiMac.macMode = val & 0xAFFF; } break; case REG_WIFI_WEP: wifiMac.wepMode = val; break; case REG_WIFI_TXSTATCNT: wifiMac.TXStatCnt = val; //printf("txstatcnt=%04X\n", val); break; case REG_WIFI_IE: wifiMac.IE = val; //printf("wifi ie write %04X\n", val); break; case REG_WIFI_IF: wifiMac.IF &= ~val; /* clear flagging bits */ break; case REG_WIFI_MAC0: case REG_WIFI_MAC1: case REG_WIFI_MAC2: wifiMac.mac.words[(address - REG_WIFI_MAC0) >> 1] = val; break; case REG_WIFI_BSS0: case REG_WIFI_BSS1: case REG_WIFI_BSS2: wifiMac.bss.words[(address - REG_WIFI_BSS0) >> 1] = val; break; case REG_WIFI_RETRYLIMIT: wifiMac.retryLimit = val; break; case REG_WIFI_WEPCNT: wifiMac.WEP_enable = (val & 0x8000) != 0; break; case REG_WIFI_POWERSTATE: wifiMac.powerOn = ((val & 0x0002)?TRUE:FALSE); if(wifiMac.powerOn) WIFI_triggerIRQ(WIFI_IRQ_RFWAKEUP); break; case REG_WIFI_POWERFORCE: if((val & 0x8000) && (!wifiMac.powerOnPending)) { /* BOOL newPower = ((val & 0x0001)?FALSE:TRUE); if(newPower != wifiMac.powerOn) { if(!newPower) wifiMac.powerOn = FALSE; else wifiMac.powerOnPending = TRUE; }*/ wifiMac.powerOn = ((val & 0x0001) ? FALSE : TRUE); } break; case REG_WIFI_POWERACK: if((val == 0x0000) && wifiMac.powerOnPending) { wifiMac.powerOn = TRUE; wifiMac.powerOnPending = FALSE; } break; case REG_WIFI_POWER_TX: wifiMac.TXPower = val & 0x0007; break; case REG_WIFI_RXCNT: wifiMac.RXCnt = val & 0xFF0E; if (BIT0(val)) { wifiMac.RXWriteCursor = WIFI_IOREG(REG_WIFI_WRITECSRLATCH); WIFI_IOREG(REG_WIFI_RXHWWRITECSR) = wifiMac.RXWriteCursor; //printf("latch RX cursor: %04X @ %08X\n", wifiMac.RXWriteCursor, NDS_ARM7.instruct_adr); } if (BIT7(val)) { WIFI_LOG(2, "TXBUF_REPLY=%04X\n", WIFI_IOREG(REG_WIFI_TXBUF_REPLY1)); wifiMac.TXSlots[WIFI_TXSLOT_MPREPLY].RegVal = WIFI_IOREG(REG_WIFI_TXBUF_REPLY1); WIFI_IOREG(REG_WIFI_TXBUF_REPLY1) = 0x0000; } if (!BIT15(val)) { while (!wifiMac.RXPacketQueue.empty()) wifiMac.RXPacketQueue.pop(); } break; case REG_WIFI_RXRANGEBEGIN: wifiMac.RXRangeBegin = val & 0x1FFE; if(wifiMac.RXWriteCursor < (wifiMac.RXRangeBegin >> 1)) wifiMac.RXWriteCursor = (wifiMac.RXRangeBegin >> 1); break; case REG_WIFI_RXRANGEEND: wifiMac.RXRangeEnd = val & 0x1FFE; if(wifiMac.RXWriteCursor >= (wifiMac.RXRangeEnd >> 1)) wifiMac.RXWriteCursor = (wifiMac.RXRangeBegin >> 1); break; case REG_WIFI_CIRCBUFRADR: wifiMac.CircBufReadAddress = (val & 0x1FFE); break; case REG_WIFI_RXREADCSR: wifiMac.RXReadCursor = val; break; case REG_WIFI_CIRCBUFWADR: wifiMac.CircBufWriteAddress = val; break; case REG_WIFI_CIRCBUFWRITE: /* set value into the circ buffer, and move cursor to the next hword on action */ //printf("wifi: circbuf fifo write at %04X, %04X (action=%i)\n", (wifiMac.CircBufWriteAddress & 0x1FFF), val, action); wifiMac.RAM[(wifiMac.CircBufWriteAddress >> 1) & 0xFFF] = val; if (action) { /* move to next hword */ wifiMac.CircBufWriteAddress+=2; if (wifiMac.CircBufWriteAddress == wifiMac.CircBufWrEnd) { /* on end of buffer, add skip hwords to it */ wifiMac.CircBufWrEnd += wifiMac.CircBufWrSkip * 2; } } break; case REG_WIFI_CIRCBUFWR_SKIP: wifiMac.CircBufWrSkip = val; break; case REG_WIFI_TXBUF_BEACON: wifiMac.TXSlots[WIFI_TXSLOT_BEACON].RegVal = val; if (BIT15(val)) WIFI_LOG(3, "Beacon transmission enabled to send the packet at %08X every %i milliseconds.\n", 0x04804000 + ((val & 0x0FFF) << 1), wifiMac.BeaconInterval); break; case REG_WIFI_TXBUF_CMD: wifiMac.TXSlots[WIFI_TXSLOT_MPCMD].RegVal = val; break; case REG_WIFI_TXBUF_LOC1: //printf("-------- TXBUF_LOC1 = %04X %08X --------\n", val, NDS_ARM7.instruct_adr); wifiMac.TXSlots[WIFI_TXSLOT_LOC1].RegVal = val; break; case REG_WIFI_TXBUF_LOC2: //printf("-------- TXBUF_LOC2 = %04X %08X --------\n", val, NDS_ARM7.instruct_adr); wifiMac.TXSlots[WIFI_TXSLOT_LOC2].RegVal = val; break; case REG_WIFI_TXBUF_LOC3: //printf("-------- TXBUF_LOC3 = %04X %08X --------\n", val, NDS_ARM7.instruct_adr); wifiMac.TXSlots[WIFI_TXSLOT_LOC3].RegVal = val; break; case REG_WIFI_TXRESET: WIFI_LOG(4, "Write to TXRESET: %04X\n", val); break; case REG_WIFI_TXREQ_RESET: wifiMac.TXCnt &= ~val; break; case REG_WIFI_TXREQ_SET: //printf("--- TXREQ=%04X ---\n", val); wifiMac.TXCnt |= val; if (BIT0(val)) WIFI_TXStart(WIFI_TXSLOT_LOC1); if (BIT1(val)) WIFI_TXStart(WIFI_TXSLOT_MPCMD); if (BIT2(val)) WIFI_TXStart(WIFI_TXSLOT_LOC2); if (BIT3(val)) WIFI_TXStart(WIFI_TXSLOT_LOC3); if (val & 0xFFF0) WIFI_LOG(2, "Unknown TXREQ bits set: %04X\n", val); break; case REG_WIFI_RFCNT: WIFI_setRF_CNT(val); break; case REG_WIFI_RFBUSY: /* CHECKME: read only? */ break; case REG_WIFI_RFDATA1: WIFI_setRF_DATA(val,0); break; case REG_WIFI_RFDATA2: WIFI_setRF_DATA(val,1); break; case REG_WIFI_USCOUNTERCNT: wifiMac.usecEnable = BIT0(val); break; case REG_WIFI_USCOMPARECNT: wifiMac.ucmpEnable = BIT0(val); break; case REG_WIFI_USCOUNTER0: wifiMac.usec = (wifiMac.usec & 0xFFFFFFFFFFFF0000ULL) | (u64)val; break; case REG_WIFI_USCOUNTER1: wifiMac.usec = (wifiMac.usec & 0xFFFFFFFF0000FFFFULL) | (u64)val << 16; break; case REG_WIFI_USCOUNTER2: wifiMac.usec = (wifiMac.usec & 0xFFFF0000FFFFFFFFULL) | (u64)val << 32; break; case REG_WIFI_USCOUNTER3: wifiMac.usec = (wifiMac.usec & 0x0000FFFFFFFFFFFFULL) | (u64)val << 48; break; case REG_WIFI_USCOMPARE0: wifiMac.ucmp = (wifiMac.ucmp & 0xFFFFFFFFFFFF0000ULL) | (u64)(val & 0xFFFE); // in NSMB multiplayer, Luigi sets USCOMPARE to the USCOUNTER of Mario, and sets bit0 // possibly bit0 writes USCOMPARE into USCOUNTER? // it seems to also trigger IRQ14 // in NSMB, Luigi sends packets on the first attempt only if we trigger IRQ14 here if (BIT0(val)) { //printf("OBSCURE BIT SET @ %08X\n", NDS_ARM7.instruct_adr); wifiMac.usec = wifiMac.ucmp; WIFI_triggerIRQ(WIFI_IRQ_TIMEBEACON); } break; case REG_WIFI_USCOMPARE1: wifiMac.ucmp = (wifiMac.ucmp & 0xFFFFFFFF0000FFFFULL) | (u64)val << 16; break; case REG_WIFI_USCOMPARE2: wifiMac.ucmp = (wifiMac.ucmp & 0xFFFF0000FFFFFFFFULL) | (u64)val << 32; break; case REG_WIFI_USCOMPARE3: wifiMac.ucmp = (wifiMac.ucmp & 0x0000FFFFFFFFFFFFULL) | (u64)val << 48; break; case REG_WIFI_BEACONPERIOD: wifiMac.BeaconInterval = val & 0x03FF; break; case REG_WIFI_BEACONCOUNT1: wifiMac.BeaconCount1 = val; break; case REG_WIFI_BEACONCOUNT2: wifiMac.BeaconCount2 = val; break; case REG_WIFI_BBCNT: WIFI_setBB_CNT(val); break; case REG_WIFI_RXBUF_COUNT: wifiMac.RXBufCount = val & 0x0FFF; break; case REG_WIFI_EXTRACOUNTCNT: wifiMac.eCountEnable = BIT0(val); break; case REG_WIFI_EXTRACOUNT: WIFI_LOG(3, "EXTRACOUNT=%i (%i µs)\n", val, val*WIFI_CMDCOUNT_SLICE); wifiMac.eCount = (u32)val * WIFI_CMDCOUNT_SLICE; break; case REG_WIFI_LISTENINT: wifiMac.ListenInterval = val & 0x00FF; break; case REG_WIFI_LISTENCOUNT: wifiMac.ListenCount = val & 0x00FF; break; case REG_WIFI_POWER_US: wifiMac.crystalEnabled = !BIT0(val); break; case REG_WIFI_IF_SET: WIFI_triggerIRQMask(val); break; case REG_WIFI_CIRCBUFRD_END: wifiMac.CircBufRdEnd = (val & 0x1FFE); break; case REG_WIFI_CIRCBUFRD_SKIP: wifiMac.CircBufRdSkip = val & 0xFFF; break; case REG_WIFI_AID_LOW: //printf("AID_LOW = %04X @ %08X %08X\n", val, NDS_ARM7.instruct_adr, NDS_ARM7.R[14]); wifiMac.pid = val & 0x0F; break; case REG_WIFI_AID_HIGH: //printf("AID_HIGH = %04X @ %08X %08X\n", val, NDS_ARM7.instruct_adr, NDS_ARM7.R[14]); wifiMac.aid = val & 0x07FF; break; case 0xD0: //printf("wifi: rxfilter=%04X\n", val); break; case 0x0E0: //printf("wifi: rxfilter2=%04X\n", val); break; case 0x84: //printf("TXBUF_TIM = %04X\n", val); break; case 0x94: printf("!!!!! TXBUF_REPLY = %04X !!!!!\n", val); break; case REG_WIFI_RXSTAT_INC_IE: wifiMac.RXStatIncIE = val; break; case REG_WIFI_RXSTAT_OVF_IE: wifiMac.RXStatOvfIE = val; break; case 0x1A8: case 0x1AC: case 0x1B0: case 0x1B2: case 0x1B4: case 0x1B6: case 0x1B8: case 0x1BA: case 0x1BC: case 0x1BE: WIFI_LOG(2, "Write to RXSTAT register: %03X = %04X\n", address, val); break; case 0x194: printf("TX_HDR_CNT = %04X\n", val); break; default: break; } WIFI_IOREG(address) = val; } u16 WIFI_read16(u32 address) { BOOL action = FALSE; if (!nds.power2.wifi) return 0; u32 page = address & 0x7000; // 0x2000 - 0x3FFF: unused if ((page >= 0x2000) && (page < 0x4000)) return 0xFFFF; WIFI_LOG(5, "Read at address %08X\n", address); // 0x4000 - 0x5FFF: wifi RAM if ((page >= 0x4000) && (page < 0x6000)) { return wifiMac.RAM[(address & 0x1FFF) >> 1]; } // anything else: I/O ports // only the first mirror causes a special action if (page == 0x0000) action = TRUE; address &= 0x0FFF; switch (address) { case REG_WIFI_ID: return WIFI_CHIPID; case REG_WIFI_MODE: return wifiMac.macMode; case REG_WIFI_WEP: return wifiMac.wepMode; case REG_WIFI_IE: return wifiMac.IE; case REG_WIFI_IF: return wifiMac.IF; case REG_WIFI_POWERSTATE: return ((wifiMac.powerOn ? 0x0000 : 0x0200) | (wifiMac.powerOnPending ? 0x0102 : 0x0000)); case REG_WIFI_RFDATA1: return WIFI_getRF_DATA(0); case REG_WIFI_RFDATA2: return WIFI_getRF_DATA(1); case REG_WIFI_RFBUSY: case REG_WIFI_BBBUSY: return 0; /* we are never busy :p */ case REG_WIFI_BBREAD: return WIFI_getBB_DATA(); case REG_WIFI_RANDOM: // probably not right, but it's better than using the unsaved and shared rand(). // at the very least, rand() shouldn't be used when movieMode is active. { u16 returnValue = wifiMac.randomSeed; wifiMac.randomSeed = (wifiMac.randomSeed & 1) ^ (((wifiMac.randomSeed << 1) & 0x7FE) | ((wifiMac.randomSeed >> 10) & 0x1)); return returnValue; } return 0; case REG_WIFI_MAC0: case REG_WIFI_MAC1: case REG_WIFI_MAC2: return wifiMac.mac.words[(address - REG_WIFI_MAC0) >> 1]; case REG_WIFI_BSS0: case REG_WIFI_BSS1: case REG_WIFI_BSS2: return wifiMac.bss.words[(address - REG_WIFI_BSS0) >> 1]; case REG_WIFI_RXCNT: return wifiMac.RXCnt; case REG_WIFI_CIRCBUFREAD: { u16 val = wifiMac.RAM[wifiMac.CircBufReadAddress >> 1]; if (action) { wifiMac.CircBufReadAddress += 2; if (wifiMac.CircBufReadAddress >= wifiMac.RXRangeEnd) { wifiMac.CircBufReadAddress = wifiMac.RXRangeBegin; } else { /* skip does not fire after a reset */ if (wifiMac.CircBufReadAddress == wifiMac.CircBufRdEnd) { wifiMac.CircBufReadAddress += wifiMac.CircBufRdSkip * 2; wifiMac.CircBufReadAddress &= 0x1FFE; if (wifiMac.CircBufReadAddress + wifiMac.RXRangeBegin == wifiMac.RXRangeEnd) wifiMac.CircBufReadAddress = 0; } } if (wifiMac.RXBufCount > 0) { if (wifiMac.RXBufCount == 1) { WIFI_triggerIRQ(WIFI_IRQ_RXCOUNTEXP); } wifiMac.RXBufCount--; } } return val; } case REG_WIFI_CIRCBUFRADR: return wifiMac.CircBufReadAddress; case REG_WIFI_RXBUF_COUNT: return wifiMac.RXBufCount; case REG_WIFI_TXREQ_READ: return wifiMac.TXCnt | 0x10; case REG_WIFI_TXBUSY: return wifiMac.TXBusy; case REG_WIFI_TXSTAT: return wifiMac.TXStat; case REG_WIFI_TXBUF_CMD: return wifiMac.TXSlots[WIFI_TXSLOT_MPCMD].RegVal; case REG_WIFI_TXBUF_REPLY2: return wifiMac.TXSlots[WIFI_TXSLOT_MPREPLY].RegVal; case REG_WIFI_TXBUF_LOC1: return wifiMac.TXSlots[WIFI_TXSLOT_LOC1].RegVal; case REG_WIFI_TXBUF_LOC2: return wifiMac.TXSlots[WIFI_TXSLOT_LOC2].RegVal; case REG_WIFI_TXBUF_LOC3: return wifiMac.TXSlots[WIFI_TXSLOT_LOC3].RegVal; case REG_WIFI_TXBUF_BEACON: return wifiMac.TXSlots[WIFI_TXSLOT_BEACON].RegVal; case REG_WIFI_EXTRACOUNTCNT: return wifiMac.eCountEnable?1:0; case REG_WIFI_EXTRACOUNT: return (u16)((wifiMac.eCount + (WIFI_CMDCOUNT_SLICE-1)) / WIFI_CMDCOUNT_SLICE); case REG_WIFI_USCOUNTER0: return (u16)wifiMac.usec; case REG_WIFI_USCOUNTER1: return (u16)(wifiMac.usec >> 16); case REG_WIFI_USCOUNTER2: return (u16)(wifiMac.usec >> 32); case REG_WIFI_USCOUNTER3: return (u16)(wifiMac.usec >> 48); case REG_WIFI_USCOMPARE0: return (u16)wifiMac.ucmp; case REG_WIFI_USCOMPARE1: return (u16)(wifiMac.ucmp >> 16); case REG_WIFI_USCOMPARE2: return (u16)(wifiMac.ucmp >> 32); case REG_WIFI_USCOMPARE3: return (u16)(wifiMac.ucmp >> 48); case REG_WIFI_BEACONCOUNT1: return wifiMac.BeaconCount1; case REG_WIFI_BEACONCOUNT2: return wifiMac.BeaconCount2; case REG_WIFI_LISTENCOUNT: return wifiMac.ListenCount; case REG_WIFI_POWER_US: return wifiMac.crystalEnabled?0:1; case REG_WIFI_CIRCBUFRD_END: return wifiMac.CircBufRdEnd; case REG_WIFI_CIRCBUFRD_SKIP: return wifiMac.CircBufRdSkip; case REG_WIFI_AID_LOW: return wifiMac.pid; case REG_WIFI_AID_HIGH: return wifiMac.aid; // RFSTATUS, RFPINS // TODO: figure out how to emulate those correctly // without breaking Nintendo's games case REG_WIFI_RFSTATUS: return wifiMac.rfStatus; //return 9; case REG_WIFI_RFPINS: return wifiMac.rfPins; //return 0x00C6; case REG_WIFI_RXSTAT_INC_IF: { u16 ret = wifiMac.RXStatIncIF; wifiMac.RXStatIncIF = 0; return ret; } case REG_WIFI_RXSTAT_OVF_IF: { u16 ret = wifiMac.RXStatOvfIF; wifiMac.RXStatOvfIF = 0; return ret; } case REG_WIFI_RXSTAT_INC_IE: return wifiMac.RXStatIncIE; case REG_WIFI_RXSTAT_OVF_IE: return wifiMac.RXStatOvfIE; case 0x1B0: case 0x1B2: case 0x1B4: case 0x1B6: case 0x1B8: case 0x1BA: case 0x1BC: case 0x1BE: { u16 ret = *(u16*)&wifiMac.RXStat[address & 0xF]; *(u16*)&wifiMac.RXStat[address & 0xF] = 0; return ret; } case REG_WIFI_RXTXADDR: return wifiMac.RXTXAddr; case 0x84: WIFI_LOG(2, "Read to TXBUF_TIM @ %08X %08X\n", NDS_ARM7.instruct_adr, NDS_ARM7.R[14]); break; default: // printf("wifi: read unhandled reg %03X\n", address); break; } return WIFI_IOREG(address); } void WIFI_usTrigger() { wifiMac.GlobalUsecTimer++; if (wifiMac.crystalEnabled) { /* a usec has passed */ if (wifiMac.usecEnable) wifiMac.usec++; // Note: the extra counter is decremented every 10 microseconds. // To avoid a modulo every microsecond, we multiply the counter // value by 10 and decrement it every microsecond :) if (wifiMac.eCountEnable) { if (wifiMac.eCount > 0) { wifiMac.eCount--; if (wifiMac.eCount == 0) WIFI_TXStart(WIFI_TXSLOT_MPCMD); } } // The beacon counters are in milliseconds // GBATek says they're decremented every 1024 usecs if (!(wifiMac.usec & 1023)) { wifiMac.BeaconCount1--; if (wifiMac.BeaconCount1 == (WIFI_IOREG(REG_WIFI_PREBEACONCOUNT) >> 10)) WIFI_triggerIRQ(WIFI_IRQ_TIMEPREBEACON); else if (wifiMac.BeaconCount1 == 0) WIFI_triggerIRQ(WIFI_IRQ_TIMEBEACON); if (wifiMac.BeaconCount2 > 0) { wifiMac.BeaconCount2--; if (wifiMac.BeaconCount2 == 0) WIFI_triggerIRQ(WIFI_IRQ_TIMEPOSTBEACON); } } } if ((wifiMac.ucmpEnable) && (wifiMac.ucmp == wifiMac.usec)) WIFI_triggerIRQ(WIFI_IRQ_TIMEBEACON); if (wifiMac.TXCurSlot >= 0) { Wifi_TXSlot& slot = wifiMac.TXSlots[wifiMac.TXCurSlot]; if (slot.RemPreamble > 0) slot.RemPreamble--; else if ((wifiMac.GlobalUsecTimer & slot.TimeMask) == 0) { if (slot.NotStarted) { WIFI_PreTXAdjustments(wifiMac.TXCurSlot); WIFI_triggerIRQ(WIFI_IRQ_TXSTART); if (wifiCom) wifiCom->SendPacket((u8*)&wifiMac.RAM[slot.CurAddr], slot.RemHWords << 1); slot.NotStarted = false; } slot.RemHWords--; slot.CurAddr++; wifiMac.RXTXAddr = slot.CurAddr; if (slot.RemHWords == 0) { if (wifiMac.TXCurSlot == WIFI_TXSLOT_MPCMD) { WIFI_triggerIRQ(WIFI_IRQ_UNK); if (BIT13(wifiMac.TXStatCnt)) { WIFI_triggerIRQ(WIFI_IRQ_TXEND); wifiMac.TXStat = 0x0B01; } else if (BIT14(wifiMac.TXStatCnt)) { WIFI_triggerIRQ(WIFI_IRQ_TXEND); wifiMac.TXStat = 0x0801; } slot.RegVal &= 0x7FFF; } else if (wifiMac.TXCurSlot == WIFI_TXSLOT_BEACON) { if (BIT15(wifiMac.TXStatCnt)) { WIFI_triggerIRQ(WIFI_IRQ_TXEND); wifiMac.TXStat = 0x0301; } } else if (wifiMac.TXCurSlot == WIFI_TXSLOT_MPREPLY) { WIFI_triggerIRQ(WIFI_IRQ_TXEND); slot.RegVal &= 0x7FFF; WIFI_IOREG(REG_WIFI_TXBUF_REPLY1) = 0; } else { WIFI_triggerIRQ(WIFI_IRQ_TXEND); wifiMac.TXStat = 0x0001 | (wifiMac.TXCurSlot == 0 ? 0 : ((wifiMac.TXCurSlot - 1) << 12)); if (BIT12(slot.RegVal)) wifiMac.TXStat |= 0x0700; slot.RegVal &= 0x7FFF; } u16 addr = slot.RegVal & 0x0FFF; wifiMac.RAM[addr] = 0x0001; wifiMac.RAM[addr+4] &= 0x00FF; wifiMac.TXBusy &= ~(1 << wifiMac.TXCurSlot); int nextslot = -1; for (int i = WIFI_TXSLOT_NUM-1; i >= 0; i--) { if (BIT_N(wifiMac.TXBusy, i)) { nextslot = i; break; } } if (nextslot < 0) { //wifiMac.rfStatus = 9; //wifiMac.rfPins = 0x00C6; wifiMac.TXCurSlot = -1; } else { wifiMac.TXCurSlot = nextslot; } } } } else if (!wifiMac.RXPacketQueue.empty()) { if ((wifiMac.GlobalUsecTimer & 7) == 0) { Wifi_RXPacket& pkt = wifiMac.RXPacketQueue.front(); if (pkt.NotStarted) { WIFI_RXPutWord(*(u16*)&pkt.Data[0]); WIFI_RXPutWord(*(u16*)&pkt.Data[2]); WIFI_RXPutWord(*(u16*)&pkt.Data[4]); WIFI_RXPutWord(*(u16*)&pkt.Data[6]); WIFI_RXPutWord(*(u16*)&pkt.Data[8]); WIFI_RXPutWord(*(u16*)&pkt.Data[10]); WIFI_triggerIRQ(WIFI_IRQ_RXSTART); pkt.NotStarted = false; //wifiMac.rfStatus = 1; wifiMac.rfPins = 0x00C7; } WIFI_RXPutWord(*(u16*)&pkt.Data[pkt.CurOffset]); pkt.CurOffset += 2; pkt.RemHWords--; if (pkt.RemHWords == 0) { wifiMac.RXWriteCursor = ((wifiMac.RXWriteCursor + 1) & (~1)); if (wifiMac.RXWriteCursor >= (wifiMac.RXRangeEnd >> 1)) wifiMac.RXWriteCursor = (wifiMac.RXRangeBegin >> 1); WIFI_IOREG(REG_WIFI_RXHWWRITECSR) = wifiMac.RXWriteCursor; wifiMac.RXNum++; WIFI_triggerIRQ(WIFI_IRQ_RXEND); WIFI_IncrementRXStat<7>(); WIFI_DoAutoReply(pkt.Data); delete[] pkt.Data; wifiMac.RXPacketQueue.pop(); wifiMac.rfStatus = 9; wifiMac.rfPins = 0x00C6; } } } if ((wifiMac.GlobalUsecTimer & 1023) == 0) if (wifiCom) wifiCom->msTrigger(); } /******************************************************************************* Ad-hoc communication interface *******************************************************************************/ #ifdef EXPERIMENTAL_WIFI_COMM #define ADHOC_MAGIC "NDSWIFI\0" #define ADHOC_PROTOCOL_VERSION 0x0100 // v1.0 typedef struct _Adhoc_FrameHeader { char magic[8]; // "NDSWIFI\0" (null terminated string) u16 version; // Ad-hoc protocol version (for example 0x0502 = v5.2) u16 packetLen; // Length of the packet } Adhoc_FrameHeader; bool Adhoc_Init() { BOOL opt_true = TRUE; int res; if (!CurrentWifiHandler->WIFI_SocketsAvailable()) { WIFI_LOG(1, "Ad-hoc: failed to initialize sockets.\n"); wifi_socket = INVALID_SOCKET; return false; } // Create an UDP socket wifi_socket = socket(AF_INET, SOCK_DGRAM, 0); if (wifi_socket < 0) { WIFI_LOG(1, "Ad-hoc: Failed to create socket.\n"); return false; } // Enable the socket to be bound to an address/port that is already in use // This enables us to communicate with another DeSmuME instance running on the same computer. res = setsockopt(wifi_socket, SOL_SOCKET, SO_REUSEADDR, (const char*)&opt_true, sizeof(BOOL)); // Bind the socket to any address on port 7000 sockaddr_t saddr; saddr.sa_family = AF_INET; *(u32*)&saddr.sa_data[2] = htonl(INADDR_ANY); *(u16*)&saddr.sa_data[0] = htons(BASEPORT); res = bind(wifi_socket, &saddr, sizeof(sockaddr_t)); if (res < 0) { WIFI_LOG(1, "Ad-hoc: failed to bind the socket.\n"); closesocket(wifi_socket); wifi_socket = INVALID_SOCKET; return false; } // Enable broadcast mode // Not doing so results in failure when sendto'ing to broadcast address res = setsockopt(wifi_socket, SOL_SOCKET, SO_BROADCAST, (const char*)&opt_true, sizeof(BOOL)); if (res < 0) { WIFI_LOG(1, "Ad-hoc: failed to enable broadcast mode.\n"); closesocket(wifi_socket); wifi_socket = INVALID_SOCKET; return false; } // Prepare an address structure for sending packets sendAddr.sa_family = AF_INET; *(u32*)&sendAddr.sa_data[2] = htonl(INADDR_BROADCAST); *(u16*)&sendAddr.sa_data[0] = htons(BASEPORT); Adhoc_Reset(); WIFI_LOG(1, "Ad-hoc: initialization successful.\n"); return true; } void Adhoc_DeInit() { if (wifi_socket >= 0) closesocket(wifi_socket); } void Adhoc_Reset() { CurrentWifiHandler->WIFI_GetUniqueMAC(FW_Mac); NDS_PatchFirmwareMAC(); printf("WIFI: ADHOC: MAC = %02X:%02X:%02X:%02X:%02X:%02X\n", FW_Mac[0], FW_Mac[1], FW_Mac[2], FW_Mac[3], FW_Mac[4], FW_Mac[5]); } void Adhoc_SendPacket(u8* packet, u32 len) { if (wifi_socket < 0) return; WIFI_LOG(3, "Ad-hoc: sending a packet of %i bytes, frame control: %04X\n", len, *(u16*)&packet[0]); u32 frameLen = sizeof(Adhoc_FrameHeader) + len; u8* frame = new u8[frameLen]; u8* ptr = frame; Adhoc_FrameHeader header; strncpy(header.magic, ADHOC_MAGIC, 8); header.version = ADHOC_PROTOCOL_VERSION; header.packetLen = len; memcpy(ptr, &header, sizeof(Adhoc_FrameHeader)); ptr += sizeof(Adhoc_FrameHeader); memcpy(ptr, packet, len); int nbytes = sendto(wifi_socket, (const char*)frame, frameLen, 0, &sendAddr, sizeof(sockaddr_t)); WIFI_LOG(4, "Ad-hoc: sent %i/%i bytes of packet.\n", nbytes, frameLen); delete[] frame; } void Adhoc_msTrigger() { if (wifi_socket < 0) return; // Check every millisecond if we received a packet fd_set fd; struct timeval tv; FD_ZERO(&fd); FD_SET(wifi_socket, &fd); tv.tv_sec = 0; tv.tv_usec = 0; if (select(1, &fd, 0, 0, &tv)) { sockaddr_t fromAddr; socklen_t fromLen = sizeof(sockaddr_t); u8 buf[1536]; u8* ptr; u16 packetLen; int nbytes = recvfrom(wifi_socket, (char*)buf, 1536, 0, &fromAddr, &fromLen); // No packet arrived (or there was an error) if (nbytes <= 0) return; ptr = buf; Adhoc_FrameHeader header = *(Adhoc_FrameHeader*)ptr; // Check the magic string in header if (strncmp(header.magic, ADHOC_MAGIC, 8)) return; // Check the ad-hoc protocol version if (header.version != ADHOC_PROTOCOL_VERSION) return; packetLen = header.packetLen - 4; ptr += sizeof(Adhoc_FrameHeader); // If the packet is for us, send it to the wifi core if (!WIFI_compareMAC(&ptr[10], &wifiMac.mac.bytes[0])) { if (WIFI_isBroadcastMAC(&ptr[16]) || WIFI_compareMAC(&ptr[16], &wifiMac.bss.bytes[0]) || WIFI_isBroadcastMAC(&wifiMac.bss.bytes[0])) { /* WIFI_LOG(3, "Ad-hoc: received a packet of %i bytes from %i.%i.%i.%i (port %i).\n", nbytes, (u8)fromAddr.sa_data[2], (u8)fromAddr.sa_data[3], (u8)fromAddr.sa_data[4], (u8)fromAddr.sa_data[5], ntohs(*(u16*)&fromAddr.sa_data[0]));*/ WIFI_LOG(3, "Ad-hoc: received a packet of %i bytes, frame control: %04X\n", packetLen, *(u16*)&ptr[0]); WIFI_LOG(4, "Storing packet at %08X.\n", 0x04804000 + (wifiMac.RXWriteCursor<<1)); u8* packet = new u8[12 + packetLen]; WIFI_MakeRXHeader(packet, WIFI_GetRXFlags(ptr), 20, packetLen, 0, 0); memcpy(&packet[12], ptr, packetLen); WIFI_RXQueuePacket(packet, 12+packetLen); } } } } /******************************************************************************* SoftAP (fake wifi access point) *******************************************************************************/ // Note on the CRC32 field in received packets: // The wifi hardware doesn't store the CRC32 in memory when receiving a packet // so the RX header length field is indeed header+body // Hence the CRC32 has been removed from those templates. // If you wanna change SoftAP's MAC address, change this // Warning, don't mistake this for an array, it isn't #define SOFTAP_MACADDR 0x00, 0xF0, 0x1A, 0x2B, 0x3C, 0x4D const u8 SoftAP_MACAddr[6] = {SOFTAP_MACADDR}; const u8 SoftAP_Beacon[] = { /* 802.11 header */ 0x80, 0x00, // Frame control 0x00, 0x00, // Duration ID 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // Receiver SOFTAP_MACADDR, // Sender SOFTAP_MACADDR, // BSSID 0x00, 0x00, // Sequence control /* Frame body */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Timestamp (modified later) 0x80, 0x00, // Beacon interval 0x21, 0x00, // Capablilty information 0x01, 0x02, 0x82, 0x84, // Supported rates 0x03, 0x01, 0x06, // Current channel 0x05, 0x04, 0x02, 0x01, 0x00, 0x00, // TIM (no idea what the hell it is) 0x00, 0x06, 'S', 'o', 'f', 't', 'A', 'P', // SSID }; const u8 SoftAP_ProbeResponse[] = { /* 802.11 header */ 0x50, 0x00, // Frame control 0x00, 0x00, // Duration ID 0x00, 0x09, 0xBF, 0x12, 0x34, 0x56, // Receiver SOFTAP_MACADDR, // Sender SOFTAP_MACADDR, // BSSID 0x00, 0x00, // Sequence control /* Frame body */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Timestamp (modified later) 0x80, 0x00, // Beacon interval 0x21, 0x00, // Capablilty information 0x01, 0x02, 0x82, 0x84, // Supported rates 0x03, 0x01, 0x06, // Current channel 0x00, 0x06, 'S', 'o', 'f', 't', 'A', 'P', // SSID }; const u8 SoftAP_AuthFrame[] = { /* 802.11 header */ 0xB0, 0x00, // Frame control 0x00, 0x00, // Duration ID 0x00, 0x09, 0xBF, 0x12, 0x34, 0x56, // Receiver SOFTAP_MACADDR, // Sender SOFTAP_MACADDR, // BSSID 0x00, 0x00, // Sequence control /* Frame body */ 0x00, 0x00, // Authentication algorithm 0x02, 0x00, // Authentication sequence 0x00, 0x00, // Status }; const u8 SoftAP_AssocResponse[] = { /* 802.11 header */ 0x10, 0x00, // Frame control 0x00, 0x00, // Duration ID 0x00, 0x09, 0xBF, 0x12, 0x34, 0x56, // Receiver SOFTAP_MACADDR, // Sender SOFTAP_MACADDR, // BSSID 0x00, 0x00, // Sequence control /* Frame body */ 0x21, 0x00, // Capability information 0x00, 0x00, // Status 0x01, 0xC0, // Assocation ID 0x01, 0x02, 0x82, 0x84, // Supported rates }; // Deauthentication frame - sent if the user chose not to connect to WFC const u8 SoftAP_DeauthFrame[] = { /* 802.11 header */ 0xC0, 0x00, // Frame control 0x00, 0x00, // Duration ID 0x00, 0x09, 0xBF, 0x12, 0x34, 0x56, // Receiver SOFTAP_MACADDR, // Sender SOFTAP_MACADDR, // BSSID 0x00, 0x00, // Sequence control /* Frame body */ 0x01, 0x00, // Reason code (is "unspecified" ok?) }; //todo - make a class to wrap this //todo - zeromus - inspect memory leak safety of all this static pcap_if_t * WIFI_index_device(pcap_if_t *alldevs, int index) { pcap_if_t *curr = alldevs; for(int i = 0; i < index; i++) { if (curr->next == NULL) { CommonSettings.wifi.infraBridgeAdapter = i; break; } curr = curr->next; } WIFI_LOG(2, "SoftAP: using %s as device.\n", curr->PCAP_DEVICE_NAME); return curr; } bool SoftAP_Init() { if (!CurrentWifiHandler->WIFI_PCapAvailable()) { WIFI_LOG(1, "SoftAP: PCap library not available on your system.\n"); wifi_bridge = NULL; return false; } char errbuf[PCAP_ERRBUF_SIZE]; pcap_if_t *alldevs; int ret = 0; ret = CurrentWifiHandler->PCAP_findalldevs(&alldevs, errbuf); if (ret == -1 || alldevs == NULL) { WIFI_LOG(1, "SoftAP: PCap: failed to find any network adapter: %s\n", errbuf); return false; } pcap_if_t* dev = WIFI_index_device(alldevs,CommonSettings.wifi.infraBridgeAdapter); wifi_bridge = CurrentWifiHandler->PCAP_open(dev->name, PACKET_SIZE, PCAP_OPENFLAG_PROMISCUOUS, 1, errbuf); if(wifi_bridge == NULL) { WIFI_LOG(1, "SoftAP: PCap: failed to open %s: %s\n", dev->PCAP_DEVICE_NAME, errbuf); return false; } CurrentWifiHandler->PCAP_freealldevs(alldevs); // Set non-blocking mode if (CurrentWifiHandler->PCAP_setnonblock(wifi_bridge, 1, errbuf) == -1) { WIFI_LOG(1, "SoftAP: PCap: failed to set non-blocking mode: %s\n", errbuf); CurrentWifiHandler->PCAP_close(wifi_bridge); wifi_bridge = NULL; return false; } SoftAP_Reset(); return true; } void SoftAP_DeInit() { if(wifi_bridge != NULL) CurrentWifiHandler->PCAP_close(wifi_bridge); } void SoftAP_Reset() { SoftAP.status = APStatus_Disconnected; SoftAP.seqNum = 0; } static bool SoftAP_IsDNSRequestToWFC(u16 ethertype, u8* body) { // Check the various headers... if (ntohs(ethertype) != 0x0800) return false; // EtherType: IP if (body[0] != 0x45) return false; // Version: 4, header len: 5 if (body[9] != 0x11) return false; // Protocol: UDP if (ntohs(*(u16*)&body[22]) != 53) return false; // Dest. port: 53 (DNS) if (htons(ntohs(*(u16*)&body[28+2])) & 0x8000) return false; // must be a query // Analyze each question u16 numquestions = ntohs(*(u16*)&body[28+4]); u32 curoffset = 28+12; for (u16 curquestion = 0; curquestion < numquestions; curquestion++) { // Assemble the requested domain name u8 bitlength = 0; char domainname[256] = ""; while ((bitlength = body[curoffset++]) != 0) { strncat(domainname, (const char*)&body[curoffset], bitlength); curoffset += bitlength; if (body[curoffset] != 0) strcat(domainname, "."); } // if the domain name contains nintendowifi.net // it is most likely a WFC server // (note, conntest.nintendowifi.net just contains a dummy HTML page and // is used for connection tests, I think we can let this one slide) if ((strstr(domainname, "nintendowifi.net") != NULL) && (strcmp(domainname, "conntest.nintendowifi.net") != 0)) return true; // Skip the type and class - we don't care about that curoffset += 4; } return false; } static void SoftAP_Deauthenticate() { u32 packetLen = sizeof(SoftAP_DeauthFrame); u8* packet = new u8[12 + packetLen]; memcpy(&packet[12], SoftAP_DeauthFrame, packetLen); memcpy(&packet[12 + 4], FW_Mac, 6); // Receiver MAC *(u16*)&packet[12 + 22] = SoftAP.seqNum << 4; // Sequence number SoftAP.seqNum++; u16 rxflags = 0x0010; if (WIFI_compareMAC(wifiMac.bss.bytes, &packet[12 + 16])) rxflags |= 0x8000; WIFI_MakeRXHeader(packet, rxflags, 20, packetLen, 0, 0); WIFI_RXQueuePacket(packet, 12 + packetLen); SoftAP.status = APStatus_Disconnected; } void SoftAP_SendPacket(u8 *packet, u32 len) { u16 frameCtl = *(u16*)&packet[0]; WIFI_LOG(3, "SoftAP: Received a packet of length %i bytes. Frame control = %04X\n", len, frameCtl); //use this to log wifi messages easily /*static int ctr=0; char buf[100]; sprintf(buf,"wifi%04d.txt",ctr); FILE* outf = fopen(buf,"wb"); fwrite(packet,1,len,outf); fclose(outf); ctr++;*/ switch((frameCtl >> 2) & 0x3) { case 0x0: // Management frame { u32 packetLen; u8* rpacket; switch((frameCtl >> 4) & 0xF) { case 0x4: // Probe request { packetLen = sizeof(SoftAP_ProbeResponse); rpacket = new u8[12 + packetLen]; memcpy(&rpacket[12], SoftAP_ProbeResponse, packetLen); // Add the timestamp *(u64*)&rpacket[12 + 24] = wifiMac.GlobalUsecTimer; } break; case 0xB: // Authentication { packetLen = sizeof(SoftAP_AuthFrame); rpacket = new u8[12 + packetLen]; memcpy(&rpacket[12], SoftAP_AuthFrame, packetLen); SoftAP.status = APStatus_Authenticated; } break; case 0x0: // Association request { if (SoftAP.status != APStatus_Authenticated) return; packetLen = sizeof(SoftAP_AssocResponse); rpacket = new u8[12 + packetLen]; memcpy(&rpacket[12], SoftAP_AssocResponse, packetLen); SoftAP.status = APStatus_Associated; WIFI_LOG(1, "SoftAP connected!\n"); } break; case 0xA: // Disassociation SoftAP.status = APStatus_Authenticated; return; case 0xC: // Deauthentication SoftAP.status = APStatus_Disconnected; WIFI_LOG(1, "SoftAP disconnected\n"); return; default: WIFI_LOG(2, "SoftAP: unknown management frame type %04X\n", (frameCtl >> 4) & 0xF); return; } memcpy(&rpacket[12 + 4], FW_Mac, 6); // Receiver MAC *(u16*)&rpacket[12 + 22] = SoftAP.seqNum << 4; // Sequence number SoftAP.seqNum++; u16 rxflags = 0x0010; if (WIFI_compareMAC(wifiMac.bss.bytes, &rpacket[12 + 16])) rxflags |= 0x8000; WIFI_MakeRXHeader(rpacket, rxflags, 20, packetLen, 0, 0); // make the RX header WIFI_RXQueuePacket(rpacket, 12 + packetLen); } break; case 0x2: // Data frame { // If it has a LLC/SLIP header, send it over the Ethernet if (((*(u16*)&packet[24]) == 0xAAAA) && ((*(u16*)&packet[26]) == 0x0003) && ((*(u16*)&packet[28]) == 0x0000)) { if (SoftAP.status != APStatus_Associated) return; if (SoftAP_IsDNSRequestToWFC(*(u16*)&packet[30], &packet[32])) { SoftAP_Deauthenticate(); return; } u32 epacketLen = ((len - 30 - 4) + 14); u8 epacket[2048]; //printf("----- SENDING ETHERNET PACKET: len=%i, ethertype=%04X -----\n", // len, *(u16*)&packet[30]); memcpy(&epacket[0], &packet[16], 6); memcpy(&epacket[6], &packet[10], 6); *(u16*)&epacket[12] = *(u16*)&packet[30]; memcpy(&epacket[14], &packet[32], epacketLen - 14); if(wifi_bridge != NULL) CurrentWifiHandler->PCAP_sendpacket(wifi_bridge, epacket, epacketLen); } else { WIFI_LOG(1, "SoftAP: received non-Ethernet data frame. wtf?\n"); } } break; } } INLINE void SoftAP_SendBeacon() { u32 packetLen = sizeof(SoftAP_Beacon); u8* packet = new u8[12 + packetLen]; memcpy(&packet[12], SoftAP_Beacon, packetLen); // Copy the beacon template *(u16*)&packet[12 + 22] = SoftAP.seqNum << 4; // Sequence number SoftAP.seqNum++; *(u64*)&packet[12 + 24] = wifiMac.GlobalUsecTimer; // Timestamp u16 rxflags = 0x0011; if (WIFI_compareMAC(wifiMac.bss.bytes, &packet[12 + 16])) rxflags |= 0x8000; WIFI_MakeRXHeader(packet, rxflags, 20, packetLen, 0, 0); WIFI_RXQueuePacket(packet, 12 + packetLen); } static void SoftAP_RXHandler(u_char* user, const struct pcap_pkthdr* h, const u_char* _data) { // safety checks if ((_data == NULL) || (h == NULL)) return; u8* data = (u8*)_data; // reject the packet if it wasn't for us if (!(WIFI_isBroadcastMAC(&data[0]) || WIFI_compareMAC(&data[0], wifiMac.mac.bytes))) return; // reject the packet if we just sent it if (WIFI_compareMAC(&data[6], wifiMac.mac.bytes)) return; // The packet was for us. Let's process it then. int wpacketLen = WIFI_alignedLen(26 + 6 + (h->len-14)); u8* wpacket = new u8[12 + wpacketLen]; u16 rxflags = 0x0018; if (WIFI_compareMAC(wifiMac.bss.bytes, (u8*)SoftAP_MACAddr)) rxflags |= 0x8000; // Make a valid 802.11 frame WIFI_MakeRXHeader(wpacket, rxflags, 20, wpacketLen, 0, 0); *(u16*)&wpacket[12+0] = 0x0208; *(u16*)&wpacket[12+2] = 0x0000; memcpy(&wpacket[12+4], &data[0], 6); memcpy(&wpacket[12+10], SoftAP_MACAddr, 6); memcpy(&wpacket[12+16], &data[6], 6); *(u16*)&wpacket[12+22] = SoftAP.seqNum << 4; *(u16*)&wpacket[12+24] = 0xAAAA; *(u16*)&wpacket[12+26] = 0x0003; *(u16*)&wpacket[12+28] = 0x0000; *(u16*)&wpacket[12+30] = *(u16*)&data[12]; memcpy(&wpacket[12+32], &data[14], h->len-14); SoftAP.seqNum++; WIFI_RXQueuePacket(wpacket, 12 + wpacketLen); } void SoftAP_msTrigger() { //zero sez: every 1/10 second? does it have to be precise? this is so costly.. // Okay for 128 ms then if((wifiMac.GlobalUsecTimer & 131071) == 0) SoftAP_SendBeacon(); // EXTREMELY EXPERIMENTAL packet receiving code // Can now receive 64 packets per millisecond. Completely arbitrary limit. Todo: tweak if needed. // But due to using non-blocking mode, this shouldn't be as slow as it used to be. if (wifi_bridge != NULL) CurrentWifiHandler->PCAP_dispatch(wifi_bridge, 64, SoftAP_RXHandler, NULL); } #endif desmume/src/libretro-common/conversion/float_to_s16_neon.S000664 001750 001750 00000002711 12755534123 025100 0ustar00sergiosergio000000 000000 /* RetroArch - A frontend for libretro. * Copyright (C) 2010-2014 - Hans-Kristian Arntzen * * RetroArch is free software: you can redistribute it and/or modify it under the terms * of the GNU General Public License as published by the Free Software Found- * ation, either version 3 of the License, or (at your option) any later version. * * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along with RetroArch. * If not, see . */ #if defined(__ARM_NEON__) #ifndef __MACH__ .arm #endif .align 4 .globl convert_float_s16_asm .globl _convert_float_s16_asm # convert_float_s16_asm(int16_t *out, const float *in, size_t samples) convert_float_s16_asm: _convert_float_s16_asm: # Hacky way to get a constant of 2^15. # ((2^4)^2)^2 * 0.5 = 2^15 vmov.f32 q8, #16.0 vmov.f32 q9, #0.5 vmul.f32 q8, q8, q8 vmul.f32 q8, q8, q8 vmul.f32 q8, q8, q9 1: # Preload here? vld1.f32 {q0-q1}, [r1]! vmul.f32 q0, q0, q8 vmul.f32 q1, q1, q8 vcvt.s32.f32 q0, q0 vcvt.s32.f32 q1, q1 vqmovn.s32 d4, q0 vqmovn.s32 d5, q1 vst1.f32 {d4-d5}, [r0]! # Guaranteed to get samples in multiples of 8. subs r2, r2, #8 bne 1b bx lr #endif desmume/src/addons/slot1comp_rom.h000664 001750 001750 00000002332 12755534123 020356 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2015 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the this software. If not, see . */ //this file contains the components used for emulating standard gamecard ROMs //this is largely done by accessing the rom provided in the core emulator #ifndef _SLOT1COMP_ROM_H #define _SLOT1COMP_ROM_H #include "slot1comp_protocol.h" #include "../types.h" class EMUFILE; class Slot1Comp_Rom { public: void start(eSlot1Operation operation, u32 addr); u32 read(); u32 getAddress(); u32 incAddress(); void savestate(EMUFILE* os); void loadstate(EMUFILE* is); private: u32 address; eSlot1Operation operation; }; #endif desmume/src/debug.h000664 001750 001750 00000012332 12755534123 015377 0ustar00sergiosergio000000 000000 /* Copyright (C) 2006 Guillaume Duhamel Copyright (C) 2006-2015 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the this software. If not, see . */ #ifndef DEBUG_H #define DEBUG_H #include #include #include #include #include "types.h" #include "mem.h" struct armcpu_t; class EMUFILE; struct DebugStatistics { DebugStatistics(); struct InstructionHits { InstructionHits(); u32 thumb[1024]; u32 arm[4096]; } instructionHits[2]; //one for each cpu s32 sequencerExecutionCounters[32]; void print(); void printSequencerExecutionCounters(); }; extern DebugStatistics DEBUG_statistics; void DEBUG_reset(); void DEBUG_dumpMemory(EMUFILE* fp); struct armcpu_t; class Logger { protected: void (*callback)(const Logger& logger, const char * format); std::ostream * out; unsigned int flags; static std::vector channels; static void fixSize(unsigned int channel); public: Logger(); ~Logger(); void vprintf(const char * format, std::va_list l, const char * filename, unsigned int line); void setOutput(std::ostream * o); void setCallback(void (*cback)(const Logger& logger, const char * message)); void setFlag(unsigned int flag); std::ostream& getOutput() const; static const int LINE = 1; static const int FILE = 2; static void log(unsigned int channel, const char * file, unsigned int line, const char * format, ...); static void log(unsigned int channel, const char * file, unsigned int line, std::ostream& os); static void log(unsigned int channel, const char * file, unsigned int line, unsigned int flag); static void log(unsigned int channel, const char * file, unsigned int line, void (*callback)(const Logger& logger, const char * message)); }; #if defined(DEBUG) || defined(GPUDEBUG) || defined(DIVDEBUG) || defined(SQRTDEBUG) || defined(DMADEBUG) || defined(DEVELOPER) #define LOGC(channel, ...) Logger::log(channel, __FILE__, __LINE__, __VA_ARGS__) #else #define LOGC(...) {} #endif #ifdef DEBUG #define LOG(...) LOGC(0, __VA_ARGS__) #else #define LOG(...) {} #endif #ifdef GPUDEBUG #define GPULOG(...) LOGC(1, __VA_ARGS__) #else #define GPULOG(...) {} #endif #ifdef DIVDEBUG #define DIVLOG(...) LOGC(2, __VA_ARGS__) #else #define DIVLOG(...) {} #endif #ifdef SQRTDEBUG #define SQRTLOG(...) LOGC(3, __VA_ARGS__) #else #define SQRTLOG(...) {} #endif #ifdef DMADEBUG #define DMALOG(...) LOGC(4, __VA_ARGS__) #else #define DMALOG(...) {} #endif #ifdef CFLASHDEBUG #define CFLASHLOG(...) LOGC(5, __VA_ARGS__) #else #define CFLASHLOG(...) {} #endif #ifdef UNTESTEDOPCODEDEBUG #define UNTESTEDOPCODELOG(...) LOGC(6, __VA_ARGS__) #else #define UNTESTEDOPCODELOG(...) {} #endif #ifdef DEVELOPER #define PROGINFO(...) LOGC(7, __VA_ARGS__) #else #define PROGINFO(...) {} #endif #define INFOC(channel, ...) Logger::log(channel, __FILE__, __LINE__, __VA_ARGS__) #define INFO(...) INFOC(10, __VA_ARGS__) void IdeasLog(armcpu_t* cpu); void NocashMessage(armcpu_t* cpu, int offset); enum EDEBUG_EVENT { DEBUG_EVENT_READ=1, //read from arm9 or arm7 bus, including cpu prefetch DEBUG_EVENT_WRITE=2, //write on arm9 or arm7 bus DEBUG_EVENT_EXECUTE=3, //prefetch on arm9 or arm7, triggered after the read event DEBUG_EVENT_ACL_EXCEPTION=4, //acl exception on arm9 DEBUG_EVENT_CACHE_MISS=5, //cache miss on arm9 }; enum EDEBUG_NOTIFY { DEBUG_NOTIFY_READ_BEYOND_END_OF_CART, DEBUG_NOTIFY_MAX }; class DebugNotify { public: void NextFrame(); void ReadBeyondEndOfCart(u32 addr, u32 romsize); private: std::bitset pingBits; std::bitset enableBits; bool ping(EDEBUG_NOTIFY which); }; extern DebugNotify DEBUG_Notify; //information about a debug event will be stuffed into here by the generator struct TDebugEventData { MMU_ACCESS_TYPE memAccessType; u32 procnum, addr, size, val; armcpu_t* cpu(); }; extern TDebugEventData DebugEventData; //bits in here are set according to what debug handlers are installed? //for now it is just a single bit extern u32 debugFlag; FORCEINLINE bool CheckDebugEvent(EDEBUG_EVENT event) { //for now, debug events are only handled in dev+ builds #ifndef DEVELOPER return false; #endif if(!debugFlag) return false; return true; } void HandleDebugEvent_Read(); void HandleDebugEvent_Write(); void HandleDebugEvent_Execute(); void HandleDebugEvent_ACL_Exception(); void HandleDebugEvent_CacheMiss(); inline void HandleDebugEvent(EDEBUG_EVENT event) { switch(event) { case DEBUG_EVENT_READ: HandleDebugEvent_Read(); return; case DEBUG_EVENT_WRITE: HandleDebugEvent_Write(); return; case DEBUG_EVENT_EXECUTE: HandleDebugEvent_Execute(); return; case DEBUG_EVENT_ACL_EXCEPTION: HandleDebugEvent_ACL_Exception(); return; case DEBUG_EVENT_CACHE_MISS: HandleDebugEvent_CacheMiss(); return; } } #endif desmume/src/libretro-common/formats/xml/test/Makefile000664 001750 001750 00000000662 12755534123 024145 0ustar00sergiosergio000000 000000 TARGET := rxml LIBRETRO_XML_DIR := .. LIBRETRO_COMM_DIR := ../../.. SOURCES := \ rxml_test.c \ $(LIBRETRO_XML_DIR)/rxml.c \ $(LIBRETRO_COMM_DIR)/streams/file_stream.c OBJS := $(SOURCES:.c=.o) CFLAGS += -DRXML_TEST -Wall -pedantic -std=gnu99 -g -I$(LIBRETRO_COMM_DIR)/include all: $(TARGET) %.o: %.c $(CC) -c -o $@ $< $(CFLAGS) $(TARGET): $(OBJS) $(CC) -o $@ $^ $(LDFLAGS) clean: rm -f $(TARGET) $(OBJS) .PHONY: clean desmume/src/utils/AsmJit/core/operand.cpp000664 001750 001750 00000001636 12755534123 021560 0ustar00sergiosergio000000 000000 // [AsmJit] // Complete JIT Assembler for C++ Language. // // [License] // Zlib - See COPYING file in this package. #define ASMJIT_EXPORTS // [Dependencies - AsmJit] #include "../core/operand.h" // [Api-Begin] #include "../core/apibegin.h" namespace AsmJit { // ============================================================================ // [AsmJit::Operand] // ============================================================================ const Operand noOperand; // ============================================================================ // [AsmJit::Imm] // ============================================================================ //! @brief Create signed immediate value operand. Imm imm(sysint_t i) { return Imm(i, false); } //! @brief Create unsigned immediate value operand. Imm uimm(sysuint_t i) { return Imm((sysint_t)i, true); } } // AsmJit namespace // [Api-End] #include "../core/apiend.h" desmume/src/libretro-common/compat/compat_getopt.c000664 001750 001750 00000012650 12755534123 023547 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2015 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (compat_getopt.c). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include #include #include #include #include #include #include #include #include #include #include #include char *optarg; int optind, opterr, optopt; static bool is_short_option(const char *str) { return str[0] == '-' && str[1] != '-'; } static bool is_long_option(const char *str) { return str[0] == '-' && str[1] == '-'; } static int find_short_index(char * const *argv) { int idx; for (idx = 0; argv[idx]; idx++) { if (is_short_option(argv[idx])) return idx; } return -1; } static int find_long_index(char * const *argv) { int idx; for (idx = 0; argv[idx]; idx++) { if (is_long_option(argv[idx])) return idx; } return -1; } static int parse_short(const char *optstring, char * const *argv) { bool extra_opt, takes_arg, embedded_arg; const char *opt = NULL; char arg = argv[0][1]; if (arg == ':') return '?'; opt = strchr(optstring, arg); if (!opt) return '?'; extra_opt = argv[0][2]; takes_arg = opt[1] == ':'; /* If we take an argument, and we see additional characters, * this is in fact the argument (i.e. -cfoo is same as -c foo). */ embedded_arg = extra_opt && takes_arg; if (takes_arg) { if (embedded_arg) { optarg = argv[0] + 2; optind++; } else { optarg = argv[1]; optind += 2; } return optarg ? opt[0] : '?'; } if (embedded_arg) { /* If we see additional characters, * and they don't take arguments, this * means we have multiple flags in one. */ memmove(&argv[0][1], &argv[0][2], strlen(&argv[0][2]) + 1); return opt[0]; } optind++; return opt[0]; } static int parse_long(const struct option *longopts, char * const *argv) { size_t indice; const struct option *opt = NULL; for (indice = 0; longopts[indice].name; indice++) { if (!strcmp(longopts[indice].name, &argv[0][2])) { opt = &longopts[indice]; break; } } if (!opt) return '?'; /* getopt_long has an "optional" arg, but we don't bother with that. */ if (opt->has_arg && !argv[1]) return '?'; if (opt->has_arg) { optarg = argv[1]; optind += 2; } else optind++; if (opt->flag) { *opt->flag = opt->val; return 0; } return opt->val; } static void shuffle_block(char **begin, char **last, char **end) { ptrdiff_t len = last - begin; const char **tmp = (const char**)calloc(len, sizeof(const char*)); retro_assert(tmp); memcpy((void*)tmp, begin, len * sizeof(const char*)); memmove(begin, last, (end - last) * sizeof(const char*)); memcpy(end - len, tmp, len * sizeof(const char*)); free((void*)tmp); } int getopt_long(int argc, char *argv[], const char *optstring, const struct option *longopts, int *longindex) { int short_index, long_index; (void)longindex; if (optind == 0) optind = 1; if (argc == 1) return -1; short_index = find_short_index(&argv[optind]); long_index = find_long_index(&argv[optind]); /* We're done here. */ if (short_index == -1 && long_index == -1) return -1; /* Reorder argv so that non-options come last. * Non-POSIXy, but that's what getopt does by default. */ if ((short_index > 0) && ((short_index < long_index) || (long_index == -1))) { shuffle_block(&argv[optind], &argv[optind + short_index], &argv[argc]); short_index = 0; } else if ((long_index > 0) && ((long_index < short_index) || (short_index == -1))) { shuffle_block(&argv[optind], &argv[optind + long_index], &argv[argc]); long_index = 0; } retro_assert(short_index == 0 || long_index == 0); if (short_index == 0) return parse_short(optstring, &argv[optind]); if (long_index == 0) return parse_long(longopts, &argv[optind]); return '?'; } desmume/src/libretro-common/streams/000700 001750 001750 00000000000 12756420131 020703 5ustar00sergiosergio000000 000000 desmume/src/libretro-common/libco/x86.c000664 001750 001750 00000005547 12755534123 021143 0ustar00sergiosergio000000 000000 /* libco.x86 (2009-10-12) author: byuu license: public domain */ #define LIBCO_C #include #include #include #ifdef __cplusplus extern "C" { #endif #if defined(_MSC_VER) #define fastcall __fastcall #elif defined(__GNUC__) #define fastcall __attribute__((fastcall)) #else #error "libco: please define fastcall macro" #endif static thread_local long co_active_buffer[64]; static thread_local cothread_t co_active_handle = 0; static void (fastcall *co_swap)(cothread_t, cothread_t) = 0; //ABI: fastcall static unsigned char co_swap_function[] = { 0x89, 0x22, /* mov [edx],esp */ 0x8b, 0x21, /* mov esp,[ecx] */ 0x58, /* pop eax */ 0x89, 0x6a, 0x04, /* mov [edx+0x04],ebp */ 0x89, 0x72, 0x08, /* mov [edx+0x08],esi */ 0x89, 0x7a, 0x0c, /* mov [edx+0x0c],edi */ 0x89, 0x5a, 0x10, /* mov [edx+0x10],ebx */ 0x8b, 0x69, 0x04, /* mov ebp,[ecx+0x04] */ 0x8b, 0x71, 0x08, /* mov esi,[ecx+0x08] */ 0x8b, 0x79, 0x0c, /* mov edi,[ecx+0x0c] */ 0x8b, 0x59, 0x10, /* mov ebx,[ecx+0x10] */ 0xff, 0xe0, /* jmp eax */ }; #ifdef _WIN32 #include void co_init(void) { DWORD old_privileges; VirtualProtect(co_swap_function, sizeof co_swap_function, PAGE_EXECUTE_READWRITE, &old_privileges); } #else #include #include void co_init(void) { unsigned long addr = (unsigned long)co_swap_function; unsigned long base = addr - (addr % sysconf(_SC_PAGESIZE)); unsigned long size = (addr - base) + sizeof co_swap_function; mprotect((void*)base, size, PROT_READ | PROT_WRITE | PROT_EXEC); } #endif static void crash(void) { assert(0); /* called only if cothread_t entrypoint returns */ } cothread_t co_active(void) { if(!co_active_handle) co_active_handle = &co_active_buffer; return co_active_handle; } cothread_t co_create(unsigned int size, void (*entrypoint)(void)) { cothread_t handle; if(!co_swap) { co_init(); co_swap = (void (fastcall*)(cothread_t, cothread_t))co_swap_function; } if(!co_active_handle) co_active_handle = &co_active_buffer; size += 256; /* allocate additional space for storage */ size &= ~15; /* align stack to 16-byte boundary */ if((handle = (cothread_t)malloc(size))) { long *p = (long*)((char*)handle + size); /* seek to top of stack */ *--p = (long)crash; /* crash if entrypoint returns */ *--p = (long)entrypoint; /* start of function */ *(long*)handle = (long)p; /* stack pointer */ } return handle; } void co_delete(cothread_t handle) { free(handle); } void co_switch(cothread_t handle) { register cothread_t co_previous_handle = co_active_handle; co_swap(co_active_handle = handle, co_previous_handle); } #ifdef __cplusplus } #endif desmume/src/libretro-common/include/clamping.h000664 001750 001750 00000004327 12755534123 022643 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2016 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (boolean.h). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef _LIBRETRO_SDK_CLAMPING_H #define _LIBRETRO_SDK_CLAMPING_H #include #include /** * clamp_float: * @val : initial value * @lower : lower limit that value should be clamped against * @upper : upper limit that value should be clamped against * * Clamps a floating point value. * * Returns: a clamped value of initial float value @val. */ static INLINE float clamp_float(float val, float lower, float upper) { if (val < lower) return lower; if (val > upper) return upper; return val; } /** * clamp_8bit: * @val : initial value * * Clamps an unsigned 8-bit value. * * Returns: a clamped value of initial unsigned 8-bit value @val. */ static INLINE uint8_t clamp_8bit(int val) { if (val > 255) return 255; if (val < 0) return 0; return (uint8_t)val; } #endif desmume/src/libretro-common/file/file_path.c000664 001750 001750 00000045123 12755534123 022272 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2016 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (file_path.c). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include #include #include #include #include #include #include #ifndef __MACH__ #include #include #endif #include #include #include /** * path_mkdir: * @dir : directory * * Create directory on filesystem. * * Returns: true (1) if directory could be created, otherwise false (0). **/ bool path_mkdir(const char *dir) { const char *target = NULL; /* Use heap. Real chance of stack overflow if we recurse too hard. */ char *basedir = strdup(dir); bool ret = false; if (!basedir) return false; path_parent_dir(basedir); if (!*basedir || !strcmp(basedir, dir)) goto end; if (path_is_directory(basedir)) { target = dir; ret = mkdir_norecurse(dir); } else { target = basedir; ret = path_mkdir(basedir); if (ret) { target = dir; ret = mkdir_norecurse(dir); } } end: if (target && !ret) printf("Failed to create directory: \"%s\".\n", target); free(basedir); return ret; } /** * path_get_extension: * @path : path * * Gets extension of file. Only '.'s * after the last slash are considered. * * Returns: extension part from the path. */ const char *path_get_extension(const char *path) { const char *ext = strrchr(path_basename(path), '.'); if (!ext) return ""; return ext + 1; } /** * path_remove_extension: * @path : path * * Removes the extension from the path and returns the result. * Removes all text after and including the last '.'. * Only '.'s after the last slash are considered. * * Returns: path with the extension part removed. */ char *path_remove_extension(char *path) { char *last = (char*)strrchr(path_basename(path), '.'); if (!last) return NULL; if (*last) *last = '\0'; return last; } /** * path_contains_compressed_file: * @path : path * * Checks if path contains a compressed file. * * Currently we only check for hash symbol (#) inside the pathname. * If path is ever expanded to a general URI, we should check for that here. * * Example: Somewhere in the path there might be a compressed file * E.g.: /path/to/file.7z#mygame.img * * Returns: true (1) if path contains compressed file, otherwise false (0). **/ bool path_contains_compressed_file(const char *path) { return (strchr(path, '#') != NULL); } /** * path_is_compressed_file: * @path : path * * Checks if path is a compressed file. * * Returns: true (1) if path is a compressed file, otherwise false (0). **/ bool path_is_compressed_file(const char* path) { #if defined(HAVE_COMPRESSION) && (defined(HAVE_ZLIB) || defined(HAVE_7ZIP)) const char* file_ext = path_get_extension(path); #ifdef HAVE_ZLIB if (!strcmp(file_ext, "zip")) return true; #endif #ifdef HAVE_7ZIP if (!strcmp(file_ext, "7z")) return true; #endif #endif return false; } /** * path_file_exists: * @path : path * * Checks if a file already exists at the specified path (@path). * * Returns: true (1) if file already exists, otherwise false (0). */ bool path_file_exists(const char *path) { FILE *dummy = fopen(path, "rb"); if (!dummy) return false; fclose(dummy); return true; } /** * fill_pathname: * @out_path : output path * @in_path : input path * @replace : what to replace * @size : buffer size of output path * * FIXME: Verify * * Replaces filename extension with 'replace' and outputs result to out_path. * The extension here is considered to be the string from the last '.' * to the end. * * Only '.'s after the last slash are considered as extensions. * If no '.' is present, in_path and replace will simply be concatenated. * 'size' is buffer size of 'out_path'. * E.g.: in_path = "/foo/bar/baz/boo.c", replace = ".asm" => * out_path = "/foo/bar/baz/boo.asm" * E.g.: in_path = "/foo/bar/baz/boo.c", replace = "" => * out_path = "/foo/bar/baz/boo" */ void fill_pathname(char *out_path, const char *in_path, const char *replace, size_t size) { char tmp_path[PATH_MAX_LENGTH] = {0}; char *tok = NULL; retro_assert(strlcpy(tmp_path, in_path, sizeof(tmp_path)) < sizeof(tmp_path)); if ((tok = (char*)strrchr(path_basename(tmp_path), '.'))) *tok = '\0'; fill_pathname_noext(out_path, tmp_path, replace, size); } /** * fill_pathname_noext: * @out_path : output path * @in_path : input path * @replace : what to replace * @size : buffer size of output path * * Appends a filename extension 'replace' to 'in_path', and outputs * result in 'out_path'. * * Assumes in_path has no extension. If an extension is still * present in 'in_path', it will be ignored. * */ void fill_pathname_noext(char *out_path, const char *in_path, const char *replace, size_t size) { retro_assert(strlcpy(out_path, in_path, size) < size); retro_assert(strlcat(out_path, replace, size) < size); } char *find_last_slash(const char *str) { const char *slash = strrchr(str, '/'); #ifdef _WIN32 const char *backslash = strrchr(str, '\\'); if (backslash && ((slash && backslash > slash) || !slash)) slash = backslash; #endif return (char*)slash; } /** * fill_pathname_slash: * @path : path * @size : size of path * * Assumes path is a directory. Appends a slash * if not already there. **/ void fill_pathname_slash(char *path, size_t size) { size_t path_len = strlen(path); const char *last_slash = find_last_slash(path); /* Try to preserve slash type. */ if (last_slash && (last_slash != (path + path_len - 1))) { char join_str[2]; strlcpy(join_str, last_slash, sizeof(join_str)); retro_assert(strlcat(path, join_str, size) < size); } else if (!last_slash) retro_assert(strlcat(path, path_default_slash(), size) < size); } /** * fill_pathname_dir: * @in_dir : input directory path * @in_basename : input basename to be appended to @in_dir * @replace : replacement to be appended to @in_basename * @size : size of buffer * * Appends basename of 'in_basename', to 'in_dir', along with 'replace'. * Basename of in_basename is the string after the last '/' or '\\', * i.e the filename without directories. * * If in_basename has no '/' or '\\', the whole 'in_basename' will be used. * 'size' is buffer size of 'in_dir'. * * E.g..: in_dir = "/tmp/some_dir", in_basename = "/some_content/foo.c", * replace = ".asm" => in_dir = "/tmp/some_dir/foo.c.asm" **/ void fill_pathname_dir(char *in_dir, const char *in_basename, const char *replace, size_t size) { const char *base = NULL; fill_pathname_slash(in_dir, size); base = path_basename(in_basename); retro_assert(strlcat(in_dir, base, size) < size); retro_assert(strlcat(in_dir, replace, size) < size); } /** * fill_pathname_base: * @out : output path * @in_path : input path * @size : size of output path * * Copies basename of @in_path into @out_path. **/ void fill_pathname_base(char *out, const char *in_path, size_t size) { const char *ptr_bak = NULL; const char *ptr = find_last_slash(in_path); (void)ptr_bak; if (ptr) ptr++; else ptr = in_path; #ifdef HAVE_COMPRESSION /* In case of compression, we also have to consider paths like * /path/to/archive.7z#mygame.img * and * /path/to/archive.7z#folder/mygame.img * basename would be mygame.img in both cases */ ptr_bak = ptr; ptr = strchr(ptr_bak,'#'); if (ptr) ptr++; else ptr = ptr_bak; #endif retro_assert(strlcpy(out, ptr, size) < size); } void fill_pathname_base_noext(char *out, const char *in_path, size_t size) { fill_pathname_base(out, in_path, size); path_remove_extension(out); } void fill_pathname_base_ext(char *out, const char *in_path, const char *ext, size_t size) { fill_pathname_base_noext(out, in_path, size); strlcat(out, ext, size); } /** * fill_pathname_basedir: * @out_dir : output directory * @in_path : input path * @size : size of output directory * * Copies base directory of @in_path into @out_path. * If in_path is a path without any slashes (relative current directory), * @out_path will get path "./". **/ void fill_pathname_basedir(char *out_dir, const char *in_path, size_t size) { if (out_dir != in_path) retro_assert(strlcpy(out_dir, in_path, size) < size); path_basedir(out_dir); } void fill_pathname_basedir_noext(char *out_dir, const char *in_path, size_t size) { fill_pathname_basedir(out_dir, in_path, size); path_remove_extension(out_dir); } /** * fill_pathname_parent_dir: * @out_dir : output directory * @in_dir : input directory * @size : size of output directory * * Copies parent directory of @in_dir into @out_dir. * Assumes @in_dir is a directory. Keeps trailing '/'. **/ void fill_pathname_parent_dir(char *out_dir, const char *in_dir, size_t size) { if (out_dir != in_dir) retro_assert(strlcpy(out_dir, in_dir, size) < size); path_parent_dir(out_dir); } /** * fill_dated_filename: * @out_filename : output filename * @ext : extension of output filename * @size : buffer size of output filename * * Creates a 'dated' filename prefixed by 'RetroArch', and * concatenates extension (@ext) to it. * * E.g.: * out_filename = "RetroArch-{month}{day}-{Hours}{Minutes}.{@ext}" **/ void fill_dated_filename(char *out_filename, const char *ext, size_t size) { time_t cur_time; time(&cur_time); strftime(out_filename, size, "RetroArch-%m%d-%H%M%S.", localtime(&cur_time)); strlcat(out_filename, ext, size); } /** * path_basedir: * @path : path * * Extracts base directory by mutating path. * Keeps trailing '/'. **/ void path_basedir(char *path) { char *last = NULL; if (strlen(path) < 2) return; #ifdef HAVE_COMPRESSION /* We want to find the directory with the zipfile in basedir. */ last = strchr(path,'#'); if (last) *last = '\0'; #endif last = find_last_slash(path); if (last) last[1] = '\0'; else snprintf(path, 3, ".%s", path_default_slash()); } /** * path_parent_dir: * @path : path * * Extracts parent directory by mutating path. * Assumes that path is a directory. Keeps trailing '/'. **/ void path_parent_dir(char *path) { size_t len = strlen(path); if (len && path_char_is_slash(path[len - 1])) path[len - 1] = '\0'; path_basedir(path); } /** * path_basename: * @path : path * * Get basename from @path. * * Returns: basename from path. **/ const char *path_basename(const char *path) { const char *last = find_last_slash(path); #ifdef HAVE_COMPRESSION const char *last_hash = NULL; /* We cut either at the last hash or the last slash; whichever comes last */ last_hash = strchr(path,'#'); if (last_hash > last) return last_hash + 1; #endif if (last) return last + 1; return path; } /** * path_is_absolute: * @path : path * * Checks if @path is an absolute path or a relative path. * * Returns: true (1) if path is absolute, false (1) if path is relative. **/ bool path_is_absolute(const char *path) { if (path[0] == '/') return true; #ifdef _WIN32 /* Many roads lead to Rome ... */ if ((strstr(path, "\\\\") == path) || strstr(path, ":/") || strstr(path, ":\\") || strstr(path, ":\\\\")) return true; #endif return false; } /** * path_resolve_realpath: * @buf : buffer for path * @size : size of buffer * * Turns relative paths into absolute path. * If relative, rebases on current working dir. **/ void path_resolve_realpath(char *buf, size_t size) { #ifndef RARCH_CONSOLE char tmp[PATH_MAX_LENGTH] = {0}; strlcpy(tmp, buf, sizeof(tmp)); #ifdef _WIN32 if (!_fullpath(buf, tmp, size)) strlcpy(buf, tmp, size); #else retro_assert(size >= PATH_MAX_LENGTH); /* NOTE: realpath() expects at least PATH_MAX_LENGTH bytes in buf. * Technically, PATH_MAX_LENGTH needn't be defined, but we rely on it anyways. * POSIX 2008 can automatically allocate for you, * but don't rely on that. */ if (!realpath(tmp, buf)) strlcpy(buf, tmp, size); #endif #endif } /** * fill_pathname_resolve_relative: * @out_path : output path * @in_refpath : input reference path * @in_path : input path * @size : size of @out_path * * Joins basedir of @in_refpath together with @in_path. * If @in_path is an absolute path, out_path = in_path. * E.g.: in_refpath = "/foo/bar/baz.a", in_path = "foobar.cg", * out_path = "/foo/bar/foobar.cg". **/ void fill_pathname_resolve_relative(char *out_path, const char *in_refpath, const char *in_path, size_t size) { if (path_is_absolute(in_path)) { retro_assert(strlcpy(out_path, in_path, size) < size); return; } fill_pathname_basedir(out_path, in_refpath, size); retro_assert(strlcat(out_path, in_path, size) < size); } /** * fill_pathname_join: * @out_path : output path * @dir : directory * @path : path * @size : size of output path * * Joins a directory (@dir) and path (@path) together. * Makes sure not to get two consecutive slashes * between directory and path. **/ void fill_pathname_join(char *out_path, const char *dir, const char *path, size_t size) { if (out_path != dir) retro_assert(strlcpy(out_path, dir, size) < size); if (*out_path) fill_pathname_slash(out_path, size); retro_assert(strlcat(out_path, path, size) < size); } static void fill_string_join(char *out_path, const char *append, size_t size) { if (*out_path) fill_pathname_slash(out_path, size); retro_assert(strlcat(out_path, append, size) < size); } void fill_pathname_join_special_ext(char *out_path, const char *dir, const char *path, const char *last, const char *ext, size_t size) { fill_pathname_join(out_path, dir, path, size); fill_string_join(out_path, last, size); strlcat(out_path, ext, size); } void fill_pathname_join_concat(char *out_path, const char *dir, const char *path, const char *concat, size_t size) { fill_pathname_join(out_path, dir, path, size); strlcat(out_path, concat, size); } void fill_pathname_join_noext(char *out_path, const char *dir, const char *path, size_t size) { fill_pathname_join(out_path, dir, path, size); path_remove_extension(out_path); } /** * fill_pathname_join_delim: * @out_path : output path * @dir : directory * @path : path * @delim : delimiter * @size : size of output path * * Joins a directory (@dir) and path (@path) together * using the given delimiter (@delim). **/ void fill_pathname_join_delim(char *out_path, const char *dir, const char *path, const char delim, size_t size) { size_t copied = strlcpy(out_path, dir, size); retro_assert(copied < size+1); out_path[copied] = delim; out_path[copied+1] = '\0'; retro_assert(strlcat(out_path, path, size) < size); } void fill_pathname_join_delim_concat(char *out_path, const char *dir, const char *path, const char delim, const char *concat, size_t size) { fill_pathname_join_delim(out_path, dir, path, delim, size); strlcat(out_path, concat, size); } /** * fill_short_pathname_representation: * @out_rep : output representation * @in_path : input path * @size : size of output representation * * Generates a short representation of path. It should only * be used for displaying the result; the output representation is not * binding in any meaningful way (for a normal path, this is the same as basename) * In case of more complex URLs, this should cut everything except for * the main image file. * * E.g.: "/path/to/game.img" -> game.img * "/path/to/myarchive.7z#folder/to/game.img" -> game.img */ void fill_short_pathname_representation(char* out_rep, const char *in_path, size_t size) { char path_short[PATH_MAX_LENGTH] = {0}; #ifdef HAVE_COMPRESSION char *last_hash = NULL; #endif fill_pathname(path_short, path_basename(in_path), "", sizeof(path_short)); #ifdef HAVE_COMPRESSION last_hash = (char*)strchr(path_short,'#'); if(last_hash != NULL) { /* We handle paths like: * /path/to/file.7z#mygame.img * short_name: mygame.img: * * We check whether something is actually * after the hash to avoid going over the buffer. */ retro_assert(strlen(last_hash) > 1); strlcpy(out_rep, last_hash + 1, size); } else #endif strlcpy(out_rep, path_short, size); } void fill_short_pathname_representation_noext(char* out_rep, const char *in_path, size_t size) { fill_short_pathname_representation(out_rep, in_path, size); path_remove_extension(out_rep); } desmume/src/utils/AsmJit/x86/000700 001750 001750 00000000000 12756420131 017071 5ustar00sergiosergio000000 000000 desmume/src/utils/AsmJit/core/context.h000664 001750 001750 00000011523 12755534123 021255 0ustar00sergiosergio000000 000000 // [AsmJit] // Complete JIT Assembler for C++ Language. // // [License] // Zlib - See COPYING file in this package. // [Guard] #ifndef _ASMJIT_CORE_CONTEXT_H #define _ASMJIT_CORE_CONTEXT_H // [Dependencies - AsmJit] #include "../core/build.h" namespace AsmJit { // ============================================================================ // [Forward Declarations] // ============================================================================ struct Assembler; struct MemoryManager; struct MemoryMarker; // ============================================================================ // [AsmJit::Context] // ============================================================================ //! @brief Class for changing behavior of code generated by @ref Assembler and //! @ref Compiler. struct Context { ASMJIT_NO_COPY(Context) // -------------------------------------------------------------------------- // [Construction / Destruction] // -------------------------------------------------------------------------- //! @brief Create a @c Context instance. ASMJIT_API Context(); //! @brief Destroy the @c Context instance. ASMJIT_API virtual ~Context(); // -------------------------------------------------------------------------- // [Interface] // -------------------------------------------------------------------------- //! @brief Allocate memory for code generated in @a assembler and reloc it //! to target location. //! //! This method is universal allowing any pre-process / post-process work //! with code generated by @c Assembler or @c Compiler. Because @c Compiler //! always uses @c Assembler it's allowed to access only the @c Assembler //! instance. //! //! This method is always last step when using code generation. You can use //! it to allocate memory for JIT code, saving code to remote process or a //! shared library. //! //! @retrurn Error value, see @c kError. virtual uint32_t generate(void** dest, Assembler* assembler) = 0; }; // ============================================================================ // [AsmJit::JitContext] // ============================================================================ struct JitContext : public Context { ASMJIT_NO_COPY(JitContext) // -------------------------------------------------------------------------- // [Construction / Destruction] // -------------------------------------------------------------------------- //! @brief Create a @c JitContext instance. ASMJIT_API JitContext(); //! @brief Destroy the @c JitContext instance. ASMJIT_API virtual ~JitContext(); // -------------------------------------------------------------------------- // [Memory Manager and Alloc Type] // -------------------------------------------------------------------------- // Note: These members can be ignored by all derived classes. They are here // only to privide default implementation. All other implementations (remote // code patching or making dynamic loadable libraries/executables) ignore // members accessed by these accessors. //! @brief Get the @c MemoryManager instance. inline MemoryManager* getMemoryManager() const { return _memoryManager; } //! @brief Set the @c MemoryManager instance. inline void setMemoryManager(MemoryManager* memoryManager) { _memoryManager = memoryManager; } //! @brief Get the type of allocation. inline uint32_t getAllocType() const { return _allocType; } //! @brief Set the type of allocation. inline void setAllocType(uint32_t allocType) { _allocType = allocType; } // -------------------------------------------------------------------------- // [Memory Marker] // -------------------------------------------------------------------------- //! @brief Get the @c MemoryMarker instance. inline MemoryMarker* getMemoryMarker() const { return _memoryMarker; } //! @brief Set the @c MemoryMarker instance. inline void setMemoryMarker(MemoryMarker* memoryMarker) { _memoryMarker = memoryMarker; } // -------------------------------------------------------------------------- // [Interface] // -------------------------------------------------------------------------- ASMJIT_API virtual uint32_t generate(void** dest, Assembler* assembler); // -------------------------------------------------------------------------- // [Statics] // -------------------------------------------------------------------------- ASMJIT_API static JitContext* getGlobal(); // -------------------------------------------------------------------------- // [Members] // -------------------------------------------------------------------------- //! @brief Memory manager. MemoryManager* _memoryManager; //! @brief Memory marker. MemoryMarker* _memoryMarker; //! @brief Type of allocation. uint32_t _allocType; }; } // AsmJit namespace // [Guard] #endif // _ASMJIT_CORE_CONTEXT_H desmume/src/libretro-common/lists/string_list.c000664 001750 001750 00000016144 12755534123 023120 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2016 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (string_list.c). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include #include #include #include #include #include #include #include /** * string_list_free * @list : pointer to string list object * * Frees a string list. */ void string_list_free(struct string_list *list) { size_t i; if (!list) return; for (i = 0; i < list->size; i++) free(list->elems[i].data); free(list->elems); free(list); } /** * string_list_capacity: * @list : pointer to string list * @cap : new capacity for string list. * * Change maximum capacity of string list's size. * * Returns: true (1) if successful, otherwise false (0). **/ static bool string_list_capacity(struct string_list *list, size_t cap) { struct string_list_elem *new_data = NULL; retro_assert(cap > list->size); new_data = (struct string_list_elem*) realloc(list->elems, cap * sizeof(*new_data)); if (!new_data) return false; if (cap > list->cap) memset(&new_data[list->cap], 0, sizeof(*new_data) * (cap - list->cap)); list->elems = new_data; list->cap = cap; return true; } /** * string_list_new: * * Creates a new string list. Has to be freed manually. * * Returns: new string list if successful, otherwise NULL. */ struct string_list *string_list_new(void) { struct string_list *list = (struct string_list*) calloc(1, sizeof(*list)); if (!list) return NULL; if (!string_list_capacity(list, 32)) { string_list_free(list); return NULL; } return list; } /** * string_list_append: * @list : pointer to string list * @elem : element to add to the string list * @attr : attributes of new element. * * Appends a new element to the string list. * * Returns: true (1) if successful, otherwise false (0). **/ bool string_list_append(struct string_list *list, const char *elem, union string_list_elem_attr attr) { char *data_dup = NULL; if (list->size >= list->cap && !string_list_capacity(list, list->cap * 2)) return false; data_dup = strdup(elem); if (!data_dup) return false; list->elems[list->size].data = data_dup; list->elems[list->size].attr = attr; list->size++; return true; } /** * string_list_set: * @list : pointer to string list * @idx : index of element in string list * @str : value for the element. * * Set value of element inside string list. **/ void string_list_set(struct string_list *list, unsigned idx, const char *str) { free(list->elems[idx].data); retro_assert(list->elems[idx].data = strdup(str)); } /** * string_list_join_concat: * @buffer : buffer that @list will be joined to. * @size : length of @buffer. * @list : pointer to string list. * @delim : delimiter character for @list. * * A string list will be joined/concatenated as a * string to @buffer, delimited by @delim. */ void string_list_join_concat(char *buffer, size_t size, const struct string_list *list, const char *delim) { size_t i, len = strlen(buffer); retro_assert(len < size); buffer += len; size -= len; for (i = 0; i < list->size; i++) { strlcat(buffer, list->elems[i].data, size); if ((i + 1) < list->size) strlcat(buffer, delim, size); } } /** * string_split: * @str : string to turn into a string list * @delim : delimiter character to use for splitting the string. * * Creates a new string list based on string @str, delimited by @delim. * * Returns: new string list if successful, otherwise NULL. */ struct string_list *string_split(const char *str, const char *delim) { char *save = NULL; char *copy = NULL; const char *tmp = NULL; struct string_list *list = string_list_new(); if (!list) goto error; copy = strdup(str); if (!copy) goto error; tmp = strtok_r(copy, delim, &save); while (tmp) { union string_list_elem_attr attr; memset(&attr, 0, sizeof(attr)); if (!string_list_append(list, tmp, attr)) goto error; tmp = strtok_r(NULL, delim, &save); } free(copy); return list; error: string_list_free(list); free(copy); return NULL; } /** * string_list_find_elem: * @list : pointer to string list * @elem : element to find inside the string list. * * Searches for an element (@elem) inside the string list. * * Returns: true (1) if element could be found, otherwise false (0). */ int string_list_find_elem(const struct string_list *list, const char *elem) { size_t i; if (!list) return false; for (i = 0; i < list->size; i++) { if (strcasecmp(list->elems[i].data, elem) == 0) return i+1; } return false; } /** * string_list_find_elem_prefix: * @list : pointer to string list * @prefix : prefix to append to @elem * @elem : element to find inside the string list. * * Searches for an element (@elem) inside the string list. Will * also search for the same element prefixed by @prefix. * * Returns: true (1) if element could be found, otherwise false (0). */ bool string_list_find_elem_prefix(const struct string_list *list, const char *prefix, const char *elem) { size_t i; char prefixed[PATH_MAX_LENGTH] = {0}; if (!list) return false; strlcpy(prefixed, prefix, sizeof(prefixed)); strlcat(prefixed, elem, sizeof(prefixed)); for (i = 0; i < list->size; i++) { if (strcasecmp(list->elems[i].data, elem) == 0 || strcasecmp(list->elems[i].data, prefixed) == 0) return true; } return false; } desmume/src/libretro-common/formats/bmp/rbmp_encode.c000664 001750 001750 00000015177 12755534123 024134 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2016 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (rbmp_encode.c). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include #include #include #include static bool write_header_bmp(RFILE *file, unsigned width, unsigned height, bool is32bpp) { uint8_t header[54]; unsigned line_size = (width * (is32bpp?4:3) + 3) & ~3; unsigned size = line_size * height + 54; unsigned size_array = line_size * height; /* Generic BMP stuff. */ /* signature */ header[0] = 'B'; header[1] = 'M'; /* file size */ header[2] = (uint8_t)(size >> 0); header[3] = (uint8_t)(size >> 8); header[4] = (uint8_t)(size >> 16); header[5] = (uint8_t)(size >> 24); /* reserved */ header[6] = 0; header[7] = 0; header[8] = 0; header[9] = 0; /* offset */ header[10] = 54; header[11] = 0; header[12] = 0; header[13] = 0; /* DIB size */ header[14] = 40; header[15] = 0; header[16] = 0; header[17] = 0; /* Width */ header[18] = (uint8_t)(width >> 0); header[19] = (uint8_t)(width >> 8); header[20] = (uint8_t)(width >> 16); header[21] = (uint8_t)(width >> 24); /* Height */ header[22] = (uint8_t)(height >> 0); header[23] = (uint8_t)(height >> 8); header[24] = (uint8_t)(height >> 16); header[25] = (uint8_t)(height >> 24); /* Color planes */ header[26] = 1; header[27] = 0; /* Bits per pixel */ header[28] = is32bpp?32:24; header[29] = 0; /* Compression method */ header[30] = 0; header[31] = 0; header[32] = 0; header[33] = 0; /* Image data size */ header[34] = (uint8_t)(size_array >> 0); header[35] = (uint8_t)(size_array >> 8); header[36] = (uint8_t)(size_array >> 16); header[37] = (uint8_t)(size_array >> 24); /* Horizontal resolution */ header[38] = 19; header[39] = 11; header[40] = 0; header[41] = 0; /* Vertical resolution */ header[42] = 19; header[43] = 11; header[44] = 0; header[45] = 0; /* Palette size */ header[46] = 0; header[47] = 0; header[48] = 0; header[49] = 0; /* Important color count */ header[50] = 0; header[51] = 0; header[52] = 0; header[53] = 0; return filestream_write(file, header, sizeof(header)) == sizeof(header); } static void dump_line_565_to_24(uint8_t *line, const uint16_t *src, unsigned width) { unsigned i; for (i = 0; i < width; i++) { uint16_t pixel = *src++; uint8_t b = (pixel >> 0) & 0x1f; uint8_t g = (pixel >> 5) & 0x3f; uint8_t r = (pixel >> 11) & 0x1f; *line++ = (b << 3) | (b >> 2); *line++ = (g << 2) | (g >> 4); *line++ = (r << 3) | (r >> 2); } } static void dump_line_32_to_24(uint8_t *line, const uint32_t *src, unsigned width) { unsigned i; for (i = 0; i < width; i++) { uint32_t pixel = *src++; *line++ = (pixel >> 0) & 0xff; *line++ = (pixel >> 8) & 0xff; *line++ = (pixel >> 16) & 0xff; } } static void dump_content(RFILE *file, const void *frame, int width, int height, int pitch, enum rbmp_source_type type) { int j; size_t line_size; uint8_t *line = NULL; int bytes_per_pixel = (type==RBMP_SOURCE_TYPE_ARGB8888?4:3); union { const uint8_t *u8; const uint16_t *u16; const uint32_t *u32; } u; u.u8 = (const uint8_t*)frame; line_size = (width * bytes_per_pixel + 3) & ~3; switch (type) { case RBMP_SOURCE_TYPE_BGR24: { /* BGR24 byte order input matches output. Can directly copy, but... need to make sure we pad it. */ uint32_t zeros = 0; int pad = line_size-pitch; for (j = 0; j < height; j++, u.u8 += pitch) { filestream_write(file, u.u8, pitch); if(pad != 0) filestream_write(file, &zeros, pad); } } break; case RBMP_SOURCE_TYPE_ARGB8888: /* ARGB8888 byte order input matches output. Can directly copy. */ for (j = 0; j < height; j++, u.u8 += pitch) filestream_write(file, u.u8, line_size); return; default: break; } /* allocate line buffer, and initialize the final four bytes to zero, for deterministic padding */ line = (uint8_t*)malloc(line_size); if (!line) return; *(uint32_t*)(line + line_size - 4) = 0; switch (type) { case RBMP_SOURCE_TYPE_XRGB888: for (j = 0; j < height; j++, u.u8 += pitch) { dump_line_32_to_24(line, u.u32, width); filestream_write(file, line, line_size); } break; case RBMP_SOURCE_TYPE_RGB565: for (j = 0; j < height; j++, u.u8 += pitch) { dump_line_565_to_24(line, u.u16, width); filestream_write(file, line, line_size); } break; default: break; } /* Free allocated line buffer */ free(line); } bool rbmp_save_image( const char *filename, const void *frame, unsigned width, unsigned height, unsigned pitch, enum rbmp_source_type type) { bool ret = false; RFILE *file = filestream_open(filename, RFILE_MODE_WRITE, -1); if (!file) return false; ret = write_header_bmp(file, width, height, type==RBMP_SOURCE_TYPE_ARGB8888); if (ret) dump_content(file, frame, width, height, pitch, type); filestream_close(file); return ret; } desmume/src/libretro-common/rthreads/000700 001750 001750 00000000000 12756420131 021041 5ustar00sergiosergio000000 000000 desmume/src/utils/AsmJit/core/build.h000664 001750 001750 00000022315 12755534123 020671 0ustar00sergiosergio000000 000000 // [AsmJit] // Complete JIT Assembler for C++ Language. // // [License] // Zlib - See COPYING file in this package. // [Guard] #ifndef _ASMJIT_CORE_BUILD_H #define _ASMJIT_CORE_BUILD_H // [Include] #include "../Config.h" #if defined(ASMJIT_EXPORTS) # if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS) # define _CRT_SECURE_NO_WARNINGS # endif // _MSC_VER #endif // ASMJIT_EXPORTS // Here should be optional include files that's needed fo successfuly // use macros defined here. Remember, AsmJit uses only AsmJit namespace // and all macros are used within it. #include #include #include #include // ============================================================================ // [AsmJit - OS] // ============================================================================ #if !defined(ASMJIT_WINDOWS) && !defined(ASMJIT_POSIX) #if defined(WINDOWS) || defined(_WINDOWS) || defined(__WINDOWS__) || defined(_WIN32) || defined(_WIN64) # define ASMJIT_WINDOWS #elif defined(__linux__) || defined(__unix__) || \ defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__NetBSD__) || \ defined(__DragonFly__) || defined(__BSD__) || defined(__FREEBSD__) || \ defined(__APPLE__) # define ASMJIT_POSIX #else # warning "AsmJit - Can't match operating system, using ASMJIT_POSIX" # define ASMJIT_POSIX #endif #endif // ============================================================================ // [AsmJit - Architecture] // ============================================================================ // define it only if it's not defined. In some systems we can // use -D command in compiler to bypass this autodetection. #if !defined(ASMJIT_X86) && !defined(ASMJIT_X64) # if defined(__x86_64__) || defined(__LP64) || defined(__IA64__) || \ defined(_M_X64) || defined(_WIN64) # define ASMJIT_X64 // x86-64 # else // _M_IX86, __INTEL__, __i386__ # define ASMJIT_X86 # endif #endif // ============================================================================ // [AsmJit - API] // ============================================================================ // Make AsmJit as shared library by default. #if !defined(ASMJIT_API) # if defined(ASMJIT_WINDOWS) # if defined(__GNUC__) # if defined(ASMJIT_EXPORTS) # define ASMJIT_API __attribute__((dllexport)) # else # define ASMJIT_API __attribute__((dllimport)) # endif // ASMJIT_EXPORTS # else # if defined(ASMJIT_EXPORTS) # define ASMJIT_API __declspec(dllexport) # else # define ASMJIT_API __declspec(dllimport) # endif // ASMJIT_EXPORTS # endif // __GNUC__ # else # if defined(__GNUC__) # if __GNUC__ >= 4 # define ASMJIT_API __attribute__((visibility("default"))) # define ASMJIT_VAR extern ASMJIT_API # endif // __GNUC__ >= 4 # endif // __GNUC__ # endif #endif // ASMJIT_API #if !defined(ASMJIT_VAR) # if defined(ASMJIT_API) # define ASMJIT_VAR extern ASMJIT_API # else # define ASMJIT_VAR # endif // ASMJIT_API #endif // !ASMJIT_VAR // [AsmJit - Memory Management] #if !defined(ASMJIT_MALLOC) # define ASMJIT_MALLOC ::malloc #endif // ASMJIT_MALLOC #if !defined(ASMJIT_REALLOC) # define ASMJIT_REALLOC ::realloc #endif // ASMJIT_REALLOC #if !defined(ASMJIT_FREE) # define ASMJIT_FREE ::free #endif // ASMJIT_FREE // ============================================================================ // [AsmJit - Calling Conventions] // ============================================================================ #if defined(ASMJIT_X86) # if defined(__GNUC__) # define ASMJIT_REGPARM_1 __attribute__((regparm(1))) # define ASMJIT_REGPARM_2 __attribute__((regparm(2))) # define ASMJIT_REGPARM_3 __attribute__((regparm(3))) # define ASMJIT_FASTCALL __attribute__((fastcall)) # define ASMJIT_STDCALL __attribute__((stdcall)) # define ASMJIT_CDECL __attribute__((cdecl)) # else # define ASMJIT_FASTCALL __fastcall # define ASMJIT_STDCALL __stdcall # define ASMJIT_CDECL __cdecl # endif #else # define ASMJIT_FASTCALL # define ASMJIT_STDCALL # define ASMJIT_CDECL #endif // ASMJIT_X86 #if !defined(ASMJIT_UNUSED) # define ASMJIT_UNUSED(var) ((void)var) #endif // ASMJIT_UNUSED #if !defined(ASMJIT_NOP) # define ASMJIT_NOP() ((void)0) #endif // ASMJIT_NOP // [AsmJit - C++ Compiler Support] #define ASMJIT_TYPE_TO_TYPE(_Type_) _Type_ #define ASMJIT_HAS_STANDARD_DEFINE_OPTIONS #define ASMJIT_HAS_PARTIAL_TEMPLATE_SPECIALIZATION // Support for VC6 #if defined(_MSC_VER) && (_MSC_VER < 1400) namespace AsmJit { template struct _Type2Type { typedef T Type; }; } #undef ASMJIT_TYPE_TO_TYPE #define ASMJIT_TYPE_TO_TYPE(_Type_) ::AsmJit::_Type2Type<_Type_>::Type #undef ASMJIT_HAS_STANDARD_DEFINE_OPTIONS #undef ASMJIT_HAS_PARTIAL_TEMPLATE_SPECIALIZATION #endif // ============================================================================ // [AsmJit - Types] // ============================================================================ #if defined(__MINGW32__) || defined(__MINGW64__) # include #endif // __MINGW32__ || __MINGW64__ #if defined(_MSC_VER) && (_MSC_VER < 1600) # if (_MSC_VER < 1300) typedef signed char int8_t; typedef signed short int16_t; typedef signed int int32_t; typedef signed __int64 int64_t; typedef unsigned char uint8_t; typedef unsigned short uint16_t; typedef unsigned int uint32_t; typedef unsigned __int64 uint64_t; # else typedef signed __int8 int8_t; typedef signed __int16 int16_t; typedef signed __int32 int32_t; typedef signed __int64 int64_t; typedef unsigned __int8 uint8_t; typedef unsigned __int16 uint16_t; typedef unsigned __int32 uint32_t; typedef unsigned __int64 uint64_t; # endif // _MSC_VER #else # include # include #endif typedef unsigned char uchar; typedef unsigned short ushort; typedef unsigned int uint; typedef unsigned long ulong; #if defined(ASMJIT_X86) typedef int32_t sysint_t; typedef uint32_t sysuint_t; #else typedef int64_t sysint_t; typedef uint64_t sysuint_t; #endif #if defined(_MSC_VER) # define ASMJIT_INT64_C(num) num##i64 # define ASMJIT_UINT64_C(num) num##ui64 #else # define ASMJIT_INT64_C(num) num##LL # define ASMJIT_UINT64_C(num) num##ULL #endif // ============================================================================ // [AsmJit - C++ Macros] // ============================================================================ #define ASMJIT_ARRAY_SIZE(A) (sizeof(A) / sizeof(*A)) #define ASMJIT_NO_COPY(__type__) \ private: \ inline __type__(const __type__& other); \ inline __type__& operator=(const __type__& other); \ public: // ============================================================================ // [AsmJit - Debug] // ============================================================================ // If ASMJIT_DEBUG and ASMJIT_NO_DEBUG is not defined then ASMJIT_DEBUG will be // detected using the compiler specific macros. This enables to set the build // type using IDE. #if !defined(ASMJIT_DEBUG) && !defined(ASMJIT_NO_DEBUG) #if defined(_DEBUG) #define ASMJIT_DEBUG #endif // _DEBUG #endif // !ASMJIT_DEBUG && !ASMJIT_NO_DEBUG // ============================================================================ // [AsmJit - Initialize/DontInitialize] // ============================================================================ // TODO: This should be moved to AsmJit namespace! // Skip documenting this. #if !defined(ASMJIT_NODOC) struct _Initialize {}; struct _DontInitialize {}; #endif // !ASMJIT_NODOC // ============================================================================ // [AsmJit - Void] // ============================================================================ // TODO: This should be moved to AsmJit namespace! //! @brief Void type which can be used in @ref FunctionDeclaration templates. struct Void {}; // ============================================================================ // [asmjit_cast<>] // ============================================================================ //! @brief Cast used to cast pointer to function. It's like reinterpret_cast<>, //! but uses internally C style cast to work with MinGW. //! //! If you are using single compiler and @c reinterpret_cast<> works for you, //! there is no reason to use @c asmjit_cast<>. If you are writing //! cross-platform software with various compiler support, consider using //! @c asmjit_cast<> instead of @c reinterpret_cast<>. template static inline T asmjit_cast(Z* p) { return (T)p; } // ============================================================================ // [AsmJit - OS Support] // ============================================================================ #if defined(ASMJIT_WINDOWS) #include #endif // ASMJIT_WINDOWS #if defined(__APPLE__) #include #ifndef MAC_OS_X_VERSION_10_7 // In Mac OS X, strnlen() is unsupported prior to v10.7, so define it here. static size_t strnlen(const char *s, size_t n) { const char *p = (const char *)memchr(s, 0, n); return(p ? p-s : n); } #endif #endif // __APPLE__ // [Guard] #endif // _ASMJIT_CORE_BUILD_H desmume/src/libretro-common/formats/png/test/rpng000755 001750 001750 00000314330 12755534123 023363 0ustar00sergiosergio000000 000000 ELF>P@@˜@8@%"@@@@@ÀÀ@@@@¥¥ ¥¥`¥`8X 0¥0¥`0¥`ðð@@DDPåtdøŒøŒ@øŒ@ÄÄQåtd/lib64/ld-linux-x86-64.so.2GNU GNUõx‹!îë^¦]­àê¢e‰X><ˆÁ @ <>Aºã’|CEÕìØqX8ò‹¹ñëÓïþÇ<¬aeîz' 6 gÄûdl%ôSSy £Ñn¥J ‡s˜Y×Jà4$8³€ØC«Êžír;*‡æTl‹Žp©`{P©`‚P©``©`  @2ð€@libz.so.1_ITM_deregisterTMCloneTable__gmon_start___Jv_RegisterClasses_ITM_registerTMCloneTabledeflatedeflateInit_inflateInit2_crc32inflateEnddeflateEndinflateinflateInit_libImlib2.so.1imlib_free_imageimlib_image_get_data_for_reading_onlyimlib_image_get_width_initimlib_context_set_image_finiimlib_load_imagelibc.so.6fopenstrrchrftellputsmkdirreallocabortstrdupstrftime__assert_failcallocstrlenmemset__errno_locationfseekmemcmpfputcstrtok_rlseekmemcpyfclosemallocstrcasecmprealpathstderrfilenofwritefreadlocaltimestrchrfprintfstrcmpstrerror__libc_start_mainsnprintffree__xstat_edata__bss_start_endGLIBC_2.14GLIBC_2.3GLIBC_2.2.5I”‘–“ii žui ¨ §` `©`?@§`H§`P§`X§``§`h§`p§`x§`€§` ˆ§` §` ˜§` §`¨§`°§`¸§`À§`ȧ`Ч`ا`à§`è§`ð§`ø§`¨`¨`¨`¨` ¨`!(¨`"0¨`#8¨`$@¨`%H¨`&P¨`'X¨`(`¨`)h¨`*p¨`+x¨`,€¨`-ˆ¨`.¨`/˜¨`0 ¨`1¨¨`2°¨`3¸¨`4À¨`5Ȩ`6Ш`7ب`8à¨`9è¨`:ð¨`;HƒìH‹u• H…Àtè‹HƒÄÃÿ5j• ÿ%l• @ÿ%j• héàÿÿÿÿ%b• héÐÿÿÿÿ%Z• héÀÿÿÿÿ%R• hé°ÿÿÿÿ%J• hé ÿÿÿÿ%B• héÿÿÿÿ%:• hé€ÿÿÿÿ%2• hépÿÿÿÿ%*• hé`ÿÿÿÿ%"• h éPÿÿÿÿ%• h é@ÿÿÿÿ%• h é0ÿÿÿÿ% • h é ÿÿÿÿ%• h éÿÿÿÿ%ú” héÿÿÿÿ%ò” héðþÿÿÿ%ê” héàþÿÿÿ%â” héÐþÿÿÿ%Ú” héÀþÿÿÿ%Ò” hé°þÿÿÿ%Ê” hé þÿÿÿ%” héþÿÿÿ%º” hé€þÿÿÿ%²” hépþÿÿÿ%ª” hé`þÿÿÿ%¢” héPþÿÿÿ%š” hé@þÿÿÿ%’” hé0þÿÿÿ%Š” hé þÿÿÿ%‚” héþÿÿÿ%z” héþÿÿÿ%r” héðýÿÿÿ%j” h éàýÿÿÿ%b” h!éÐýÿÿÿ%Z” h"éÀýÿÿÿ%R” h#é°ýÿÿÿ%J” h$é ýÿÿÿ%B” h%éýÿÿÿ%:” h&é€ýÿÿÿ%2” h'épýÿÿÿ%*” h(é`ýÿÿÿ%"” h)éPýÿÿÿ%” h*é@ýÿÿÿ%” h+é0ýÿÿÿ% ” h,é ýÿÿÿ%” h-éýÿÿÿ%ú“ h.éýÿÿÿ%ò“ h/éðüÿÿÿ%ê“ h0éàüÿÿÿ%â“ h1éÐüÿÿÿ%Ú“ h2éÀüÿÿÿ%Ò“ h3é°üÿÿÿ%Ê“ h4é üÿÿÿ%“ h5éüÿÿÿ%º“ h6é€üÿÿÿ%Ú‘ f1íI‰Ñ^H‰âHƒäðPTIÇÀЀ@HÇÁ`€@HÇÇÓ@è‡ýÿÿôfD¸W©`UH-P©`HƒøH‰åv¸H…Àt]¿P©`ÿàf„]Ã@f.„¾P©`UHîP©`HÁþH‰åH‰ðHÁè?HÆHÑþt¸H…Àt ]¿P©`ÿà]ÃfD€=a“ uUH‰åènÿÿÿ]ÆN“ óÃ@¿(¥`Hƒ?u듸H…ÀtñUH‰åÿÐ]ézÿÿÿUH‰åHƒìPH‰}ÈH‰uÀH‰U¸H‰M°ÆEÿHÇEðHÇEèH‹EȾH‰ÇèE7H‰EàHƒ}à„öH‹EàH‰Çè8H‹EàH‰ÇèP9ƒð„ÀuíHUÐH‹EàH‰ÖH‰Çèƒ;H‰EèHƒ}èu ÆEÿé°èÈ%H‰EðHƒ}ðu ÆEÿé—H‹UèH‹EðH‰ÖH‰Çèq%ƒð„ÀtÆEÿëwH‹EðH‰Çèe$ƒð„ÀtÆEÿë^H‹EðH‰Ç蘄ÀuðH‹EðH‰ÇèÏ$ƒð„ÀtÆEÿë4H‹M°H‹U¸H‹uÀH‹EðH‰Çè£"‰E܃}Üt߃}Üþtƒ}ÜÿuÆEÿëHƒ}àt H‹EàH‰Çè%;Hƒ}ðt H‹EðH‰Çè*#HÇEð¶Eÿƒð„ÀtH‹EÀH‹H‰Çèoûÿÿ¶EÿÉÃUH‰åHƒìpH‰}˜HÇEøÇE°PÿÇE´€ÿÇE¸@ÿÇE¼ˆÿÇEÀPÿÇEÄ€ÿÇEÈ@ÿÇËÿÇEÐÃÿÇEÔÓÿÇEØÃÿÇEÜÓÿÇEàÃÿÇEäÓÿÇEèÃÿÇEìÓÿHÇE¨ÇE¤ÇE HE°A¸¹ºH‰Æ¿@è¼3ƒð„Àt ¸é.HM HU¤Hu¨H‹E˜H‰Çè‹ýÿÿƒð„Àt ¸éH‹ H‹U˜¾@H‰Ç¸è×ûÿÿ‹M ‹U¤H‹j ¾!@H‰Ç¸è¸ûÿÿH‹E˜H‰ÇèìúÿÿH‰EðHƒ}ðu ¸é¨H‹EðH‰Çè[ûÿÿè–øÿÿ‰E¤èŽøÿÿ‰E èæúÿÿH‰Eø‹U¤‹E ¯Â‰ÀH…H‹M¨H‹EøH‰ÎH‰Çèìúÿÿ…Àt%H‹á H‰Áº¾¿6@è ûÿÿ¸ë4H‹¼ H‰Áº¾¿P@èåúÿÿè øÿÿH‹E¨H‰Çètùÿÿ¸ÉÃUH‰åHƒì ‰}ìH‰uàHÇEø@ƒ}ì~'H‹EàH‹H‹b ¾p@H‰Ç¸è°úÿÿ¸ëjƒ}ìu H‹EàH‹@H‰EøH‹0 H‰Áº¾¿†@èYúÿÿH‹EøH‰Çè„ýÿÿ…Àt%H‹ H‰Áº ¾¿–@è+úÿÿ¸ÿÿÿÿë¸ÉÃUH‰å‰}ì‰uè‰Uä‹Uì‹EèÐ+Eä‰Eü‹Eü+Eì‰Â‰ÐÁø1‰Uø)Eø‹Eü+Eè‰Â‰ÐÁø1‰Uô)Eô‹Eü+Eä‰Â‰ÐÁø1‰Uð)Eð‹Eø;Eô ‹Eø;Eð‹Eìë‹Eô;Eð‹Eèë‹Eä]ÃUH‰åH‰}øH‹Eø¶¶ÀÁà‰ÂH‹EøHƒÀ¶¶ÀÁà ÂH‹EøHƒÀ¶¶ÀÁà ÂH‹EøHƒÀ¶¶À Ð]ÃUH‰åHƒì H‰}èÇEüëA‹EüHÁàHàƒ@H‹H‹UèHJºH‰ÆH‰ÏèÐøÿÿ…Àu‹EüHÁàHèƒ@‹ëƒEüƒ}üv¹¸ÉÃUH‰åHƒì H‰}èÆEûH‹Eè¶@ ¶Àƒø‡'‰ÀH‹Å@‚@ÿàH‹Eè¶@<„2H‹Eè¶@<„"H‹S º±¾È@H‰Ç¸èœøÿÿÆEûéçÆEúÇEüë#‹Eü‹… „@H‹Eè¶@¶À9ÂuÆEúë ƒEüƒ}üv×¶Eúƒð„À„¹H‹çŒ ºÂ¾È@H‰Ç¸è0øÿÿÆEûé{ÆEùÇEüë#‹Eü‹…@„@H‹Eè¶@¶À9ÂuÆEùë ƒEüƒ}üv×¶Eùƒð„ÀtTH‹Œ ºÔ¾È@H‰Ç¸èÈ÷ÿÿÆEûéH‹XŒ ºØ¾È@H‰Ç¸è¡÷ÿÿÆEûéìëëH‹Eè¶@ <uA¹ã@ëA¹ç@H‹Eè¶@ ¶Àƒà…ÀtA¸ã@ëA¸ç@H‹Eè¶@ ¶Àƒà…Àt¿ã@ë¿ç@H‹Eè¶@ <uAºã@ëAºç@H‹Eè¶@¶ðH‹Eè‹HH‹Eè‹H‹ ‹ HƒìAQAPWM‰ÑA‰ð¾ð@H‰Ç¸èßöÿÿHƒÄ H‹Eè¶@ „Àt#H‹h‹ ºå¾È@H‰Ç¸è±öÿÿÆEû¶EûÉÃUH‰åH‰}èH‰uà‰U܉MØ‹EØÁè‰EØÇEüëmH‹Eà¶¶À‰Eø‹EØHEàH‹Eà¶¶À‰Eô‹EØHEàH‹Eà¶¶À‰Eð‹EØHEà‹EüH…H‹EèHЋUø‰ÑÁá‹UôÁâ Ê UðÊÿ‰ƒEü‹Eü;EÜr‹]ÃUH‰åH‰}ØH‰uЉỦMÈ‹EÈÁè‰EÈÇEüéƒH‹Eж¶À‰Eø‹EÈHEÐH‹Eж¶À‰Eô‹EÈHEÐH‹Eж¶À‰Eð‹EÈHEÐH‹Eж¶À‰Eì‹EÈHEЋEüH…H‹EØH‹EìÁà‰Á‹EøÁà Á‹EôÁà È Eð‰ƒEü‹Eü;EÌ‚qÿÿÿ]ÃUH‰åH‰}ØH‰uЉỦMȃ}ÈuTÇEüë>‹EüÀ‰ÂH‹EÐHж¶À‰Eô‹EüH…H‹EØHЋUôiÒÊÿ‰ƒEü‹Eü;EÌrºé¬‹EÈ‹…`„@‰Eð‹EȺ‰ÁÓâ‰Ðƒè‰EìÇEøÇEüës‹EøÁè‰Eè‹UèH‹EÐHж¶Ð‹EÈ÷؉Á‹Eøƒà)Á‰ÈƒÀ‰ÁÓú‰Ð‰Eä‹Eì!Eä‹Eä¯Eð‰Eä‹EüH…H‹EØHЋUäiÒÊÿ‰ƒEü‹EÈEø‹Eü;EÌr…]ÃUH‰åH‰}èH‰uà‰U܉MØ‹EØÁè‰EØÇEüëQH‹Eà¶¶À‰Eø‹EØHEàH‹Eà¶¶À‰Eô‹EØHEà‹EüH…H‹EèHЋUøiÒ‹MôÁá ʉƒEü‹Eü;EÜr§]ÃUH‰åH‰}ØH‰uЉỦMÈL‰EÀ‹EȺ‰ÁÓâ‰Ðƒè‰EôÇEøÇEüën‹EøÁè‰Eð‹UðH‹EÐHж¶Ð‹EÈ÷؉Á‹Eøƒà)Á‰ÈƒÀ‰ÁÓú‰Ð‰Eì‹Eô!Eì‹EüH…H‹EØH‹EìH …H‹EÀHÈ‹‰ƒEü‹EÈEø‹Eü;EÌrŠ]ÃUH‰åH‰}è‰uä‰UàH‰MØL‰EÐL‰MÈH‹Eè¶@ ¶Àƒø‡R‰ÀH‹Åx‚@ÿàH‹Eè¶@¶ÀƒÀP…ÀHÂÁø‰EüH‹Eè‹H‹Eè¶@¶À¯ÂƒÀÁè‰EøéH‹Eè¶@¶Ð‰ÐÀЃÀP…ÀHÂÁø‰EüH‹Eè‹H‹Eè¶@¶À¯Ð‰ÐÀЃÀÁè‰EøéÍH‹Eè¶@¶ÀƒÀP…ÀHÂÁø‰EüH‹Eè‹H‹Eè¶@¶À¯ÂƒÀÁè‰EøéH‹Eè¶@¶ÀÀƒÀP…ÀHÂÁø‰EüH‹Eè‹H‹Eè¶@¶À¯ÂÀƒÀÁè‰EøëPH‹Eè¶@¶ÀÁàƒÀP…ÀHÂÁø‰EüH‹Eè‹H‹Eè¶@¶À¯ÂÁàƒÀÁè‰EøëÇEüÇEøHƒ}Èt‹EøPH‹Eè‹@¯Â‰ÂH‹EÈH‰Hƒ}Øt H‹EØ‹Uü‰Hƒ}Ðt H‹EЋUø‰]ÃUH‰åH‰}èH‰uàH‰U؉MÔD‰EÐL‰MÈH‹EÈ‹PH‹Eà‹¯ÐH‹EÈ‹ЉÀHÁàHEèÇEøëqH‹EèH‰EðÇEüë/‹EüH…H‹EØHЋH‹Eð‰ƒEüH‹EÈ‹@‰ÀHÁàHEð‹Eü;EÔrɃEøH‹Eà‹H‹EÈ‹@ ¯Â‰ÀHÁàHEè‹EÔHÁàHEØ‹Eø;EÐr‡]ÃUH‰åHƒìH‰}øH‹EøH‹@0H…ÀtH‹EøH‹@0H‰ÇèÇîÿÿH‹EøHÇ@0H‹EøH‹@(H…ÀtH‹EøH‹@(H‰ÇèžîÿÿH‹EøHÇ@(H‹EøÆ@H‹EøÇ@hÉÃUH‰åSHƒì(H‰}ØH‰uÐH‹Eж@ƒð„À„-H‹Eض@ „À„H‹EØ‹H‹EЋ€€‰ÀHÁàHÀ‚@‹9Âv#H‹EØ‹PH‹EЋ€€‰ÀHÁàHÄ‚@‹9Âw ¸éèH‹EØ‹H‹EЋ€€‰ÀHÁàHÀ‚@‹)ÂH‹EЋ€€‰ÀHÁàHÈ‚@‹ÐHÿH‹EЋ€€‰ÀHÁàHÈ‚@‹‰Èº÷ó‰ÂH‹EЉPpH‹EØ‹PH‹EЋ€€‰ÀHÁàHÄ‚@‹)ÂH‹EЋ€€‰ÀHÁàHÌ‚@‹ÐHÿH‹EЋ€€‰ÀHÁàHÌ‚@‹‰Èº÷ó‰ÂH‹EЉPtH‹EЋPpH‹EЋ@t¯Â‰ÀHÁàH‰Çè«ìÿÿH‰ÂH‹EÐH‰PH‹EÐH‹@H…Àu ¸ÿÿÿÿéØH‹MÐH‹EØH‹PH‹H‰AH‰Q H‹EЋPpH‹EЉPH‹EЋPtH‹EЉPH‹EÐHpxH‹EЋPtH‹EЋ@pH‹MÐHyI‰ñA¸¹‰ÆèÿúÿÿH‹EÐH‹XxH‹EÐH‹€H‹@(H‹UÐH‹’ˆH‰×ÿÐH9ÃvH‹EÐH‹@H‰ÇèGìÿÿ¸ÿÿÿÿé,H‹EÐÆ@¸éH‹Eж@„Àt ¸éH‹EÐL@dH‹EÐHH`H‹EØ‹PH‹EØ‹0H}èH‹EØI‰ùH‰ÇèaúÿÿH‹EÐH‹€H‹@(H‹UÐH‹’ˆH‰×ÿÐH‰ÂH‹EèH9Âs ¸ÿÿÿÿéŸH‹EÐHÇ@@H‹EÐHÇ@PH‹EЋ@d‰ÀH‰Æ¿è²ìÿÿH‰ÂH‹EÐH‰P(H‹EЋ@d‰ÀH‰Æ¿è‘ìÿÿH‰ÂH‹EÐH‰P0H‹EÐH‹@(H…Àt'H‹EÐH‹@0H…ÀtH‹EÐÇ@hH‹EÐÆ@¸ëH‹EÐH‰Çè&üÿÿ¸ÿÿÿÿHƒÄ([]ÃUH‰åSHƒì8H‰}ØH‰uÐH‰UȉMă}ć ‹EÄH‹Å0ƒ@ÿàH‹EÈ‹@d‰ÂH‹EÈH‹H8H‹EÈH‹@0H‰ÎH‰ÇèwìÿÿéàÇEìë%H‹EÈH‹P0‹EìHÂH‹EÈH‹H8‹EìHȶˆƒEìH‹EÈ‹@`;EìwÏH‹EÈ‹@`‰EìëEH‹EÈH‹P0‹EìHÂH‹EÈH‹H0H‹EÈ‹@`‹uì)Ɖð‰ÀHȶH‹EÈH‹p8‹EìHð¶ȈƒEìH‹EÈ‹@d;Eìw¯éDÇEìë8H‹EÈH‹P0‹EìHÂH‹EÈH‹H(‹EìHȶH‹EÈH‹p8‹EìHð¶ȈƒEìH‹EÈ‹@d;Eìw¼éòÇEìëAH‹EÈH‹P(‹EìHжÐèˆEëH‹EÈH‹P0‹EìHÂH‹EÈH‹H8‹EìHȶ¶EëȈƒEìH‹EÈ‹@`;Eìw³H‹EÈ‹@`‰EìëgH‹EÈH‹P0H‹EÈ‹@`‹Mì)Á‰È‰ÀHж¶ÐH‹EÈH‹H(‹EìHȶ¶ÀÐÑøˆEêH‹EÈH‹P0‹EìHÂH‹EÈH‹H8‹EìHȶ¶EêȈƒEìH‹EÈ‹@d;EìwéÇEìëOH‹EÈH‹P0‹EìHH‹EÈH‹P(‹EìHж¶Àº‰Æ¿èðïÿÿ‰ÁH‹EÈH‹P8‹EìHжȈƒEìH‹EÈ‹@`;Eìw¥H‹EÈ‹@`‰Eìé‰H‹EÈH‹P0‹EìHH‹EÈH‹P(H‹EÈ‹@`‹Mì)Á‰È‰ÀHж¶ÐH‹EÈH‹H(‹EìHȶ¶ÈH‹EÈH‹p0H‹EÈ‹@`‹}ì)ljø‰ÀHð¶¶À‰Î‰ÇèLïÿÿ‰ÁH‹EÈH‹P8‹EìHжȈƒEìH‹EÈ‹@d;Eì‡gÿÿÿë ¸ÿÿÿÿéH‹Eж@ ¶Àƒø‡Ü‰ÀH‹ÅXƒ@ÿàH‹Eж@¶ÈH‹EЋH‹EÈH‹p0H‹EØH‰Çè¼óÿÿé¦H‹Eж@¶ÈH‹EЋH‹EÈH‹p0H‹EØH‰Çè=òÿÿëH‹EÈH‹xH‹Eж@¶ÈH‹EЋH‹EÈH‹p0H‹EØI‰øH‰ÇèúôÿÿëMH‹Eж@¶ÈH‹EЋH‹EÈH‹p0H‹EØH‰ÇèSôÿÿë&H‹Eж@¶ÈH‹EЋH‹EÈH‹p0H‹EØH‰ÇèYòÿÿH‹EÈ‹@d‰ÂH‹EÈH‹H0H‹EÈH‹@(H‰ÎH‰Çè~èÿÿ¸HƒÄ8[]ÃUH‰åHƒì0H‰}èH‰uàH‰UØÇEüH‹EØ‹PhH‹Eà‹@9ÂsNH‹EØH‹@8HHH‹UØH‰J8¶¶À‰EøH‹EØH‹@@HPH‹EØH‰P@H‹EèH‹‹MøH‹UØH‹uàH‰Çè0ûÿÿ‰Eüƒ}ü„’ƒ}üÿ„ˆH‹EØ‹@hPH‹E؉PhH‹EØH‹P8H‹EØ‹@d‰ÀHÂH‹EØH‰P8H‹EØH‹P@H‹EØ‹@d‰ÀHÂH‹EØH‰P@H‹EèH‹H‹Eà‹‰ÀHÁàHÂH‹EèH‰H‹EØH‹PPH‹Eà‹‰ÀHÂH‹EØH‰PP¸ëYH‹EØH‰ÇèŸöÿÿH‹EØH‹P8H‹EØH‹@@H÷ØHÂH‹EØH‰P8H‹EèH‹H‹EØH‹@PHÁàH÷ØHÂH‹EèH‰H‹EØHÇ@P‹EüÉÃUH‰åHƒì0H‰}èH‰uàH‰UØÇEüH‹EØ‹€€ƒø–ÀˆEûH‹EèH‹H‰Eð¶Eûƒð„Àt ¸é}H‹UØH‹EàH‰ÖH‰Çècöÿÿ‰Eüƒ}üu ¸éWƒ}üÿu ¸ÿÿÿÿéGH‹EØHPH‹EØH‰ÆH‰×è)öÿÿƒøÿu ¸þÿÿÿé!H‹EØHpH‹EØHHH‹EØH‰ÂH‰ÏèÅýÿÿ‰Eüƒ}üt؃}üþtƒ}üÿu ¸þÿÿÿéãH‹EØH‹P8H‹EØH‹@xHÂH‹EØH‰P8H‹EØH‹PHH‹EØH‹@xHÂH‹EØH‰PHH‹EØH‹€H‹@0H‹UØH‹Rx‰ÑH‹UØH‹’ˆ‰ÎH‰×ÿÐH‹EØ‹€€‰ÀHÁàL€À‚@H‹EØ‹xtH‹EØ‹HpH‹EØH‹PH‹uàH‹EðM‰ÁA‰øH‰ÇèôÿÿH‹EØH‹@H‰Çè¤ãÿÿH‹EØÇ@pH‹EØÇ@tH‹EØHÇ@xH‹EØÆ@¸ÉÃUH‰åHƒì0H‰}èH‰uàH‰UØH‹UØH‹MàH‹EèH‰ÎH‰Çèþÿÿ‰Eü‹Eüƒøÿ„ƒøÿƒøþt)ëv…ÀtƒøëlH‹EØ‹€€PH‹E؉€¸ë|H‹EØH‹@H…ÀtH‹EØH‹@H‰ÇèéâÿÿH‹EØH‹P8H‹EØH‹@HH÷ØHÂH‹EØH‰P8H‹EØHÇ@H¸ÿÿÿÿë.H‹EØH‹P8H‹EØH‹@HH÷ØHÂH‹EØH‰P8H‹EØHÇ@H‹EüÉÃUH‰åHƒìH‰}øH‰uðHƒ}øu¸ëMH‹Eø¶€¼„Àt H‹UøH‹EøHˆ°H‹EðH‰ÎH‰ÇèÊþÿÿëH‹UøH‹EøHˆ°H‹EðH‰ÎH‰ÇèkûÿÿÉÃUH‰åHƒì0H‰}èH‰uàH‰UØH‰MÐH‹EèH‹€H‹@H‹UèH‹’ˆH‰×ÿÐ…Àt*H‹EèH‹€H‹@ H‹UèH‹’ˆH‰×ÿÐ…Àt¸ë¸ˆEÿ€eÿ¶Eÿƒð„Àu>H‹EèH‹€H‹@HH‹UèH‹’ˆH‰×ÿЉEø‹Eøƒøÿ„úƒøt¸éëH‹EèH‹€H‹@H‹UèH‹’ˆH‰×ÿÐH‹Eè‹°H‹E؉H‹Eè‹´H‹EЉH‹Eè‹°H‹Eè‹€´¯Â‰ÀHÁàH‰Çè™àÿÿH‰ÂH‹EàH‰H‹EàH‹H…À„ŠH‹EèHÇ@HH‹EèHÇ@@H‹EèHÈH‹EèH‰PH‹Eè¶€¼<tH‹EèH‹UèH°H‰ÆH‰×èòÿÿƒøÿt4H‹EèÆ@¸ë3H‹EèH‹€H‹@H‹UèH‹’ˆH‰×ÿÐëëH‹EèÆ@¸ÿÿÿÿÉÃUH‰åH‰}èH‰uà‰UÜÇEü鈋Uü‰ÐÀЉÂH‹EèHж¶À‰Eø‹Uü‰ÐÀЃÀ‰ÂH‹EèHж¶À‰Eô‹Uü‰ÐÀЃÀ‰ÂH‹EèHж¶À‰Eð‹EüH…H‹EàHЋUø‰ÑÁá‹UôÁâ Ê UðÊÿ‰ƒEü‹Eü;EÜ‚lÿÿÿ¸]ÃUH‰åHƒì H‰}èH‰uàH‹EàH‹PH‹E苉ÀHÂH‹EàH‹H‰ÖH‰ÇèÇàÿÿH‰EøHƒ}øu¸ëH‹EàH‹UøH‰¸ÉÃUH‰åHƒì H‰}øH‰uðH‰UèH‰MàH‹EøHÇ@XH‹EøHÇ@8H‹EøHpXH‹Eø‹´H‹Eø‹€°H‹MøH¹°I‰ñA¸¹‰ÆèCíÿÿH‹Eø¶€¼<uH‹EøH‹@XHH‹EøH‰PXH‹EøH‹€H‹ÿÐH‰ÂH‹EøH‰ˆH‹EøH‹€ˆH…Àu ¸é¿H‹EøH‹€H‹@8H‹UøH‹’ˆH‰×ÿЃð„Àt ¸éH‹EøH‹@XH‰ÇèÌÝÿÿH‰ÂH‹EøH‰P8H‹EøH‹@8H…Àu¸ë`H‹EøH‹€H‹@H‹UøH‹r8H‹UøH‹’ H‹MøH‹IXA‰ÊH‹MøH‹‰¨A‰ÉH‹MøH‹¹ˆI‰ðH‰ÑD‰ÒD‰ÎÿÐH‹EøÆ¸ÉÃUH‰åHƒì H‰}èH‰uàÇEðÇEüë‹UüH‹EèHж‹EüˆTðƒEüƒ}üvâHEðH‰Çè%åÿÿ‰ÂH‹Eà‰ÇEüë#‹EüƒÀ‰ÂH‹EèHж‰ÁH‹Uà‹EüˆLƒEüƒ}üv׸ÉÃUH‰åHƒìH‰}øH‰uðHƒEøH‹EøH‰ÇèÃäÿÿ‰ÂH‹Eð‰H‹EøHƒÀH‰Çè«äÿÿ‰ÂH‹Eð‰PH‹Eø¶PH‹EðˆPH‹Eø¶P H‹EðˆP H‹Eø¶P H‹EðˆP H‹Eø¶P H‹EðˆP H‹Eø¶P H‹EðˆP H‹Eð‹…Àt H‹Eð‹@…Àu¸ë¸ÉÃUH‰åHƒì@H‰}ÈHÇEÐHÇEØH‹EÈH‹€ÀH‰EðHUÐH‹EðH‰ÖH‰Çè‡þÿÿƒð„Àt ¸éïH‹Eð¶PH‹EðˆHEÐH‰Çèäÿÿƒø‡†‰ÀH‹Ń@ÿàH‹Eȶ€˜„À…¦H‹Eȶ€™„À…“H‹Eȶ€š„À…€‹EЃø …aH‹EÈH°H‹EðH‰ÖH‰Çèqþÿÿƒð„À…?H‹EÈH°H‰Çèêãÿÿƒð„À…%H‹EÈÆ€˜éä‹Eк«ªªª÷â‰ÐÑè‰EìH‹Eȶ€˜ƒð„À…ûH‹Eȶ€›„À…èH‹Eȶ€š„À…ÕH‹Eȶ€™„À…‹Mк«ªªª‰È÷â‰ÐÑè‰ÂÒ‰È)Ð…À…–}쇌HƒEðH‹EÈHˆÈ‹UìH‹EðH‰ÎH‰Çèfúÿÿƒð„À…bH‹EÈÆ€›éH‹Eȶ€˜ƒð„À…@H‹Eȶ€š„À…-H‹Eȶ€¹<uH‹Eȶ€›ƒð„À…H‹EÈH HEÐH‰ÖH‰Çè™úÿÿƒð„À…âHƒEðÇEüë2H‹EÈH‹ ‹MüH‹EÈH‹€¨HÈH‹MüH‹EðHȶˆƒEü‹EÐ;EüwÆH‹EÈH‹€¨‹UЉÒHÂH‹EÈH‰¨H‹EÈÆ€™ë2H‹Eȶ€˜ƒð„Àu^H‹Eȶ€™ƒð„ÀuLH‹EÈÆ€šë?H‹EÈH‹€À‹UЃ ‰ÒHÂH‹EÈH‰À¸ëëëë ë ëëë¸ÉÃUH‰åHƒì0H‰}èH‰uàH‰UØH‰MÐH‹E趃ð„ÀtPH‹EèH‹€H…Àuè 'H‰ÂH‹EèH‰H‹MÐH‹UØH‹uàH‹EèH‰Çèœùÿÿƒð„Àt¸þÿÿÿëX¸ëQH‹Eè¶@ƒð„Àt/H‹MÐH‹UØH‹uàH‹EèH‰Çèxöÿÿ‰Eüƒ}üÿu¸þÿÿÿë¸ëH‹UàH‹EèH‰ÖH‰ÇèáõÿÿÉÃUH‰åHƒìH‰}øHƒ}ø„H‹EøH‹€ H…ÀtH‹EøH‹€ H‰Çè-ØÿÿH‹EøH‹@8H…ÀtH‹EøH‹@8H‰ÇèØÿÿH‹EøH‹€ˆH…Àt2H‹EøH‹€H‹@H‹UøH‹’ˆH‰×ÿÐH‹EøH‹€ˆH‰ÇèÎ×ÿÿH‹EøH‰ÇèÂ×ÿÿëÉÃUH‰åHƒì H‰}èHÇEðHƒ}èu¸ëpÇEüë!H‹EèH‹À‹EüHж‰Â‹EüˆTðƒEüƒ}üvÙHEðº¾À@H‰ÇèuØÿÿ…Àt¸ëH‹EèH‹€ÀHPH‹EèH‰À¸ÉÃUH‰åH‰}øHƒ}øu¸ëGH‹Eø¶€˜„Àt¸ë1H‹Eø¶€™„Àt¸ëH‹Eø¶€š„Àt¸ë¸]ÃUH‰åH‰}øH‰uðHƒ}øu¸ëH‹EøH‹UðH‰À¸]ÃUH‰åHƒì¾È¿è³×ÿÿH‰EøHƒ}øu¸ëH‹EøÉÃUH‰å‰}ì‰uè‰Uä‹Uì‹EèÐ+Eä‰Eü‹Eü+Eì‰Â‰ÐÁø1‰Uø)Eø‹Eü+Eè‰Â‰ÐÁø1‰Uô)Eô‹Eü+Eä‰Â‰ÐÁø1‰Uð)Eð‹Eø;Eô ‹Eø;Eð‹Eìë‹Eô;Eð‹Eèë‹Eä]ÃUH‰åH‰}ø‰uôH‹EøHPH‰Uø‹UôÁêˆH‹EøHPH‰Uø‹UôÁêˆH‹EøHPH‰Uø‹UôÁêˆH‹EøHPH‰Uø‹Uôˆ]ÃUH‰åHƒì0H‰}èH‰uàH‰UØÇEðè„#H‰EøH‹EøH‹@hH‹UØH‹MàH‰Î¿ÿЉEô‹UôHEð‰ÖH‰ÇèSÿÿÿHMðH‹EèºH‰ÎH‰Çèš8Hƒø”ÀÉÃUH‰åHƒì0H‰}ØH‰uÐÆEà0ÆEá0ÆEâ0ÆEã0ÆEäIÆEåHÆEæDÆEçRÆEèÆEéÆEêÆEëÆEìÆEíÆEîÆEïH‹Eж@ˆEðH‹Eж@ ˆEñH‹Eж@ ˆEòH‹Eж@ ˆEóH‹Eж@ ˆEôHEྠH‰ÇèšþÿÿH‹EЋHEàHƒÀ‰ÖH‰Çè‚þÿÿH‹EЋPHEàHƒÀ ‰ÖH‰ÇèiþÿÿHMàH‹EغH‰ÎH‰Çè°7Hƒøt¸ë/HEàHƒÀH‹MغH‰ÆH‰Ïèƒþÿÿƒð„Àt¸ë¸ÉÃUH‰åHƒì H‰}øH‰uðH‰UèH‹UèH‹MðH‹EøH‰ÎH‰ÇèG7H‰ÂH‹EèH9Ât¸ë2H‹EèHPüH‹EðHHH‹EøH‰ÎH‰Çèþÿÿƒð„Àt¸ë¸ÉÃUH‰åHƒì H‰}èÆEðÆEñÆEòÆEóÆEôIÆEõEÆEöNÆE÷DHMðH‹EèºH‰ÎH‰Çè¼6Hƒøt¸ë/HEðHƒÀH‹MèºH‰ÆH‰Ïèýÿÿƒð„Àt¸ë¸ÉÃUH‰åH‰}èH‰uà‰UÜÇEüëh‹EüH…H‹EàHЋ‰EøH‹EèHPH‰Uè‹UøÁêˆH‹EèHPH‰Uè‹UøÁêˆH‹EèHPH‰Uè‹UøˆH‹EèHPH‰Uè‹UøÁꈃEü‹Eü;EÜr]ÃUH‰åH‰}èH‰uà‰UÜÇEüë?H‹EèHPH‹EඈH‹EèHPH‹Eà¶@ˆH‹Eà¶PH‹E舃EüHƒEèHƒEà‹Eü;EÜr¹]ÃUH‰åH‰}èH‰uàÇEôHÇEøëH‹UèH‹EøHж¾À™1Ð)ÐEôHƒEøH‹EøH;EàrØ‹Eô]ÃUH‰åHƒì0H‰}èH‰uàH‰U؉MÔD‰EЋEÔ¯EЉEÔÇEüë.‹UüH‹EèHЋMüH‹UàHʶ ‹uüH‹UØHò¶)щʈƒEü‹Eü;EÔrÊ‹UÔH‹EèH‰ÖH‰Çè@ÿÿÿÉÃUH‰åHƒì(H‰}èH‰uà‰U܉MØ‹EܯE؉EÜÇEüë‹UüH‹EèH‹MüH‹EàHȶˆƒEü‹Eü;EØrÛ‹E؉Eüë3‹UüH‹EèH‹MüH‹EàHȶ‹Eü+E؉ÆH‹EàHð¶)Á‰ÈˆƒEü‹Eü;EÜrÅ‹UÜH‹EèH‰ÖH‰Çè›þÿÿÉÃUH‰åHƒì0H‰}èH‰uàH‰U؉MÔD‰EЋEÔ¯EЉEÔÇEüë.‹UüH‹EèHЋMüH‹UàHʶ‹uüH‹MØHñ¶ Ðé)ʈƒEü‹Eü;EÐrÊ‹EЉEüëJ‹UüH‹EèH‹MüH‹EàHȶ‹Eü+EЉÆH‹EàHð¶¶ð‹}üH‹EØHø¶¶ÀðÑø)Á‰ÈˆƒEü‹Eü;EÔr®‹UÔH‹EèH‰ÖH‰ÇèÉýÿÿÉÃUH‰åATSHƒì0H‰}ØH‰uÐH‰UȉMÄD‰EÀ‹EįEÀ‰EÄÇEìëF‹UìH‹EØH‹UìH‹EÐHÐD¶ ‹UìH‹EÈHж¶Àº‰Æ¿è ùÿÿA)ÄD‰àˆƒEì‹Eì;EÀr²‹EÀ‰Eìëh‹UìH‹EØH‹UìH‹EÐHÐD¶ ‹Eì+EÀ‰ÂH‹EÈHж¶Ð‹MìH‹EÈHȶ¶È‹Eì+EÀ‰ÆH‹EÐHð¶¶À‰Î‰Çè•øÿÿA)ÄD‰àˆƒEì‹Eì;EÄr‹UÄH‹EØH‰ÖH‰Çè¾üÿÿHƒÄ0[A\]ÃUH‰åHìÐH‰½HÿÿÿH‰µ@ÿÿÿ‰•<ÿÿÿ‰8ÿÿÿD‰…4ÿÿÿD‰0ÿÿÿÆEûHÇ…PÿÿÿHÇ…XÿÿÿHÇEðHÇEˆHÇEèHÇEàHÇEØHÇEÐHÇEÈHÇEÀHÇE¸HÇE°HÇE¨HÇE H‹…HÿÿÿHÇÂÿÿÿÿ¾H‰ÇèŸ.H‰E€Hƒ}€u'H‹d ºè¾„@H‰Ç¸è`ÏÿÿÆEûébèçH‰EðH‹E€º¾ˆ„@H‰Çè-1Hƒøt'H‹Ëc ºí¾„@H‰Ç¸èÏÿÿÆEûé‹…<ÿÿÿ‰…Pÿÿÿ‹…8ÿÿÿ‰…TÿÿÿÆ…Xÿÿÿƒ½0ÿÿÿu¸ë¸ˆ…YÿÿÿH•PÿÿÿH‹E€H‰ÖH‰Çèøÿÿƒð„Àt'H‹Mc ºô¾„@H‰Ç¸è–ÎÿÿÆEû阋…<ÿÿÿ¯…0ÿÿÿƒÀ¯…8ÿÿÿ‰ÀH‰EˆH‹EˆH‰Çè„ÌÿÿH‰EèHƒ}èu'H‹òb ºù¾„@H‰Ç¸è;ÎÿÿÆEûé=‹…<ÿÿÿ¯…0ÿÿÿ‰ÀH‰Æ¿èÆÍÿÿH‰E°Hƒ}°u'H‹¤b ºý¾„@H‰Ç¸èíÍÿÿÆEûéï‹…<ÿÿÿ¯…0ÿÿÿ‰ÀH‰ÇèíËÿÿH‰EØ‹…<ÿÿÿ¯…0ÿÿÿ‰ÀH‰ÇèÒËÿÿH‰EЋ…<ÿÿÿ¯…0ÿÿÿ‰ÀH‰Çè·ËÿÿH‰EÈ‹…<ÿÿÿ¯…0ÿÿÿ‰ÀH‰ÇèœËÿÿH‰EÀ‹…<ÿÿÿ¯…0ÿÿÿ‰ÀH‰ÇèËÿÿH‰E¸Hƒ}ØtHƒ}ÐtHƒ}ÈtHƒ}ÀtHƒ}¸u'H‹Óa º¾„@H‰Ç¸èÍÿÿÆEûéH‹EèH‰E¨ÇEü都0ÿÿÿu‹•<ÿÿÿH‹@ÿÿÿH‹EØH‰ÎH‰ÇèQøÿÿë‹•<ÿÿÿH‹@ÿÿÿH‹EØH‰ÎH‰Çè¾øÿÿ‹…<ÿÿÿ¯…0ÿÿÿ‰ÂH‹EØH‰ÖH‰Çèùÿÿ‰…|ÿÿÿ‹½0ÿÿÿ‹<ÿÿÿH‹U°H‹uØH‹EÐA‰øH‰Çè#ùÿÿ‰…xÿÿÿ‹0ÿÿÿ‹•<ÿÿÿH‹uØH‹EÈH‰Çèyùÿÿ‰…tÿÿÿ‹½0ÿÿÿ‹<ÿÿÿH‹U°H‹uØH‹EÀA‰øH‰Çèõùÿÿ‰…pÿÿÿ‹½0ÿÿÿ‹<ÿÿÿH‹U°H‹uØH‹E¸A‰øH‰Çèžúÿÿ‰…lÿÿÿÆEŸ‹…|ÿÿÿ‰E˜H‹EØH‰E‹…tÿÿÿ;E˜sÆEŸH‹EÈH‰E‹…tÿÿÿ‰E˜‹…xÿÿÿ;E˜sÆEŸH‹EÐH‰E‹…xÿÿÿ‰E˜‹…pÿÿÿ;E˜sÆEŸH‹EÀH‰E‹…pÿÿÿ‰E˜‹…lÿÿÿ;E˜sÆEŸH‹E¸H‰E‹…lÿÿÿ‰E˜H‹E¨HPH‰U¨¶UŸˆ‹…<ÿÿÿ¯…0ÿÿÿ‰ÂH‹MH‹E¨H‰ÎH‰ÇèrËÿÿ‹…<ÿÿÿ¯…0ÿÿÿ‰ÂH‹MØH‹E°H‰ÎH‰ÇèPËÿÿƒEü‹…<ÿÿÿ¯…0ÿÿÿ‰ÀHE¨‹…4ÿÿÿH…@ÿÿÿ‹Eü;…8ÿÿÿ‚ÞýÿÿH‹EˆHÀH‰ÇèîÈÿÿH‰EàHƒ}àu'H‹\_ ºF¾„@H‰Ç¸è¥ÊÿÿÆEûé§H‹EðH‹ÿÐH‰E Hƒ} u'H‹!_ ºK¾„@H‰Ç¸èjÊÿÿÆEûélH‹EðH‹@H‹UàHJH‹Uˆ4H‹UˆA‰ÑH‹UèH‹} I‰ÈH‰Ñ‰òD‰ÎÿÐH‹EðH‹@PH‹U ¾ H‰×ÿÐH‹EðH‹@`H‹U H‰×ÿЃøt8H‹EðH‹@XH‹U H‰×ÿÐH‹Š^ ºY¾„@H‰Ç¸èÓÉÿÿÆEûéÕH‹EðH‹@XH‹U H‰×ÿÐH‹EàHƒÀº¾«„@H‰ÇèßÉÿÿH‹EðH‹@(H‹U H‰×ÿЉÂH‹Eà‰ÖH‰ÇèòÿÿH‹EðH‹@(H‹U H‰×ÿÐHPH‹MàH‹E€H‰ÎH‰ÇèÙóÿÿƒð„Àt$H‹è] ºa¾„@H‰Ç¸è1ÉÿÿÆEûë6H‹E€H‰Çèôÿÿƒð„Àt#H‹±] ºd¾„@H‰Ç¸èúÈÿÿÆEûH‹E€H‰Çè€+H‹EèH‰Çè]ÇÿÿH‹EàH‰ÇèQÇÿÿH‹EØH‰ÇèEÇÿÿH‹E°H‰Çè9ÇÿÿH‹EÐH‰Çè-ÇÿÿH‹EÈH‰Çè!ÇÿÿH‹EÀH‰ÇèÇÿÿH‹E¸H‰Çè ÇÿÿH‹EðH‹@H‹U H‰×ÿжEûÉÃUH‰åHƒì H‰}øH‰uð‰Uì‰MèD‰Eä‹}ä‹Mè‹UìH‹uðH‹EøA¹A‰øH‰Çèå÷ÿÿÉÃUH‰åHƒì H‰}øH‰uð‰Uì‰MèD‰Eä‹}ä‹Mè‹UìH‹uðH‹EøA¹A‰øH‰Çè§÷ÿÿÉÃUH‰åH‰}èH‰uàH‰UØHÇEøH‹EØH‰EðHƒ}ðt7ëHƒEøHƒmðHƒ}ðt$H‹EèHPH‰UèH‹UàHJH‰Mඈ¶„ÀuËHƒ}ðu(Hƒ}ØtH‹EèÆëHƒEøH‹EàHPH‰Uà¶„ÀuèH‹Eø]ÃUH‰åHƒì0H‰}èH‰uàH‰UØH‹EèH‰ÇèÓÅÿÿH‰EøH‹EøHEèH‹EøH;EØv HÇEØëH‹EøH)EØH‹UØH‹MàH‹EèH‰ÎH‰ÇèÿÿÿH‰ÂH‹EøHÐÉÃUH‰åHƒì H‰}è‰uäHÇEø‹EäH‹Å ©`H‹EèH‰ÖH‰Çè÷ÄÿÿH‰EðHƒ}ðu ¸é+¿(èÈÄÿÿH‰EøHƒ}ø„¹H‹EøH‹UðH‰H‹EøHÇ@‹Eäƒøt:ƒøt5H‹EøH‹º¾H‰ÇèÄÿÿH‹EøH‹H‰Çè­ÃÿÿH‰ÂH‹EøH‰Pë‹Eä‰ÂH‹EøˆP!H‹EøH‹@H‰ÇèCÄÿÿH‰ÂH‹EøH‰PH‹EøH‹@H…Àt H‹EøH‹@H…Àt!H‹EøH‹PH‹EøH‰PH‹EøÆ@ þH‹EøëYëHƒ}øt5H‹EøH‹@H…ÀtH‹EøH‹@H‰Çè8ÄÿÿH‹EøHÇ@H‹EøH‰Çè ÄÿÿHÇEøH‹EðH‰ÇèLÅÿÿ¸ÉÃUH‰åHƒìH‰}øHƒ}øtJH‹Eø¶@ „Àx¿À„@è Ãÿÿè÷ÂÿÿH‹EøH‹º¾H‰ÇèþÂÿÿH‹EøÆ@ H‹EøHÇ@ëÉÃUH‰åHƒìH‰}øHƒ}øtJH‹Eø¶@ „Àx¿ø„@è¬Âÿÿè—ÂÿÿH‹EøH‹º¾H‰ÇèžÂÿÿH‹EøÆ@ H‹EøHÇ@ëÉÃUH‰åHƒì H‰}èHÇEøHƒ}èu ¸é„H‹EèH‹PH‹EèH‹@H)ÂH‰ÐH;EøsH‹EèH‹PH‹EèH‹@H)ÂH‰ÐH‰EøH‹Eè¶@ ¾À…Àt ƒøtvéöH‹Eè¶@!<u1H‹EèH‹@H‰EøH‹EèH‹H‹EèH‹@H‹Uø¾H‰ÇèIÃÿÿé¹H‹EèH‹H‹EèH‹HH‹EèH‹@H<H‹EøH‰ÑH‰Â¾èÃÿÿé…H‹Eè¶@!<uIHÇEðH‹EèH‹@H‰EøH‹EèH‹H‹EèH‹@H‹Uø¾H‰Çè€ÃÿÿH‰EðH‹EðH;Eøt6¸ëoH‹EèH‹H‹EèH‹HH‹EèH‹@H<H‹EøH‰ÑH‰Â¾è<ÃÿÿH‹EèH‹PH‹EøHÂH‹EèH‰PH‹EèH‹PH‹EèH‹@H9ÂuH‹EèÆ@ ÿH‹Eè¶@ ÀèÉÃUH‰åHƒìH‰}øH‰uðHƒ}ø„„H‹Eø¶@ „Àx¿0…@è™Àÿÿè„ÀÿÿH‹EøH‹@H;Eðv¿h…@è|ÀÿÿègÀÿÿH‹EøH‹UðH‰PH‹EøH‹PH‹EøH‹@H‰ÖH‰ÇèÂÿÿH‰ÂH‹EøH‰PH‹EøÆ@ ÿH‹EøH‹PH‹EøH‰PëÉÃUH‰åH‰}øH‰uðHƒ}øu¸ë1Hƒ}ðtH‹EøH‹PH‹EðH‰H‹Eø¶@ <ÿu H‹EøH‹@ë¸]ÃUH‰åH‰}øHƒ}øtH‹EøÆ@ ÿH‹EøH‹PH‹EøH‰Pë]ÃUH‰åHƒìH‰}øHƒ}øt_H‹Eø¶@ „Àx¿¨…@膿ÿÿèq¿ÿÿH‹EøH‹H‰Çè‚ÁÿÿH‹EøH‹@H‰Çè2ÀÿÿH‹EøHÇH‹EøHÇ@H‹EøH‰ÇèÀÿÿëÉÃUH‰åHƒì H‰}èH‹EèH‰EøHƒ}øtH‹EøH‹H‰Çèà¿ÿÿH‹EøH‰ÇèÔ¿ÿÿëÉÃUH‰åH‰}èH‹EèH‰EøHƒ}øu¸ëH‹EøH‹]ÃUH‰åH‰}èH‹EèH‰EøHƒ}øu¸ëH‹EøH‹@]ÃUH‰åHƒì0H‰}ØHÇEèÿÿÿÿÆEÿ¾¿è‰ÀÿÿH‰EðHƒ}ðu¸ëYH‹MðHUèH‹EØH‰ÎH‰Çè¼#…À•ÀˆEÿ¶Eÿƒð„ÀuH‹EèH…ÀxH‹EèH‰ÂH‹EðH‰PH‹EðëH‹EðH‰Çèéþÿÿ¸ÉÃUH‰åHƒì`H‰}ÈH‰uÀH‰U¸‰M´D‰E°D‰M¬HÇEøHÇEðH‹EH‰EèHEк¾H‰Çèo½ÿÿHƒ}ÀtH‹EÀ¾Ð…@H‰Çè)H‰EøHƒ}øtoH‹EÈH‰Ç耾ÿÿHPÿH‹EÈHжˆEç€}ç/th€}ç\tbH‹EÈH‰Çè9H‰EðHƒ}ðtKH‹UðH‹Eø¾Ò…@H‰Çè'*ƒð„Àu/ÇEÐH‹EøH‰Çèæ$H‹UÐH‹MÈH‹EèH‰ÎH‰Çèl&¶ÀëH‹EøH‰Çè¾$¸ÉÃUH‰åHì@H‰½èïÿÿH‰µàïÿÿH‰•Øïÿÿ‰ÔïÿÿD‰…ÐïÿÿD‰ÌïÿÿH‹…èïÿÿH‰ÇèH‰EøH‹EH‰EðHƒ}ø„H‹EðH‹@ H‹UøH‰ÖH‰Çèú(…À„éH•ðïÿÿ¸¹H‰×óH«H‹EðH‹@H…Àt0H‹…èïÿÿH‰ÇèH‰ÂH‹EðH‹pH…ðïÿÿ¹H‰ÇèÎë-H‹…èïÿÿH‰ÇèîH‰ÂH‹EðH‹0H…ðïÿÿ¹H‰ÇèÂH…ðïÿÿH‰Çèµ½ÿÿH‰ÂH‹EðH‰PD‹…Ìïÿÿ‹½Ðïÿÿ‹ÔïÿÿH‹•ØïÿÿH‹µàïÿÿH…ðïÿÿjjE‰ÁA‰øH‰Çè¡ HƒÄ‰ÂH‹EðˆP(¸ë¸ÉÃUH‰åH‰}è‰uäÇEøÁeäÇEüë"H‹EèHPH‰U趶ЋEü‰ÁÓâ‰Ð EøƒEü‹Eü;EärÖ‹Eø]ÃUH‰åHƒìPH‰}ØH‰uÐH‰UÈH‰MÀL‰E¸L‰M°H‹EØH‹@¾H‰Çè}ÿÿÿ‰Eü}üPKt ¸é©H‹EØH‹@HƒÀ ¾H‰ÇèNÿÿÿ‰ÂH‹EÀ‰H‹EØH‹@HƒÀ¾H‰Çè-ÿÿÿ‰ÂH‹E‰H‹EØH‹@HƒÀ¾H‰Çè ÿÿÿ‰ÂH‹E°‰H‹EØH‹@HƒÀ¾H‰Çèëþÿÿ‰ÂH‹E¸‰H‹EØH‹@HƒÀ¾H‰ÇèÊþÿÿ‰EøH‹EØH‹@HƒÀ¾H‰Çè®þÿÿ‰EôH‹EØH‹@HƒÀ ¾H‰Çè’þÿÿ‰Eð}øÿv ¸ÿÿÿÿ龋UøH‹EØH‹@HH.H‹EÐH‰ÎH‰Ç蓼ÿÿH‹EØH‹@HƒÀ*¾H‰ÇèEþÿÿ‰EìH‹EØH‹@‹UìHƒÂHоH‰Çè#þÿÿ‰EèH‹EØH‹@‹UìHƒÂHоH‰Çèþÿÿ‰EäH‹EØH‹@‹Mì‹UèHÑ‹UäHÊHƒÂHÂH‹EÈH‰‹Uø‹Eô‹EðÐP.H‹E‰¸ÉÃUH‰åHìPH‰½ÈïÿÿH‰µÀïÿÿH‰•¸ïÿÿH‰°ïÿÿHÇEðÇEìÇEèÇEäÇEàÇEÜH•Ðïÿÿ¸¹H‰×óH«LMäLEèHMàHUðHµÐïÿÿH‹…ÈïÿÿH}ÜWH}ìWH‰ÇèqýÿÿHƒÄ‰Eüƒ}üt‹Eüëb‹EìD‹MèD‹Eä‹MàH‹UðH‹µÀïÿÿH½Ðïÿÿÿµ¸ïÿÿPH‹…°ïÿÿÿÐHƒÄ…Àu¸ë#H‹…ÈïÿÿH‹@‹U܉ÒHÂH‹…ÈïÿÿH‰P¸ÉÃUH‰åSHƒì(H‰}ØH‰uÐè!H‰ÂH‹EØH‰P(H‹EØH‹@(H…Àu ¸ÿÿÿÿéiH‹EÐH‰Çè^ùÿÿH‰ÂH‹EØH‰H‹EØH‹H…Àu ¸ÿÿÿÿé=H‹EØH‹H‰Çèùÿÿ‰ÂH‹E؉P H‹EØ‹@ ƒø ¸ÿÿÿÿéH‹EØH‹H‰Çè²øÿÿH‰ÂH‹EØH‰PH‹EØH‹PH‹EØ‹@ H˜HƒèHÂH‹EØH‰PH‹EØH‹PH‹EØH‹@HƒÀH9Âw ¸ÿÿÿÿé²H‹EØH‹@¾H‰Çè©ûÿÿ=PKuHH‹EØH‹@HƒÀ¾H‰Çè‰ûÿÿ‰EìH‹EØH‹@‹UìHƒÂH H‹EØH‹PH‹EØ‹@ H˜HÐH9ÁtH‹EØH‹@HPÿH‹EØH‰Pé`ÿÿÿH‹EØH‹XH‹EØH‹@HƒÀ¾H‰Çèûÿÿ‰ÀHH‹EØH‰P¸HƒÄ([]ÃUH‰åHƒì0H‰}ø‰uôH‰UèH‰MàL‰EØD‰MðHƒ}øt'H‹EøH‹@H‹@H‹UøH‹H‰×ÿÐH‹EøH‹H‰Çè-·ÿÿHƒ}øtƒ}ôÿu ÇEôëSH‹EøH‹@H‹@h‹UH‹MøH‹IH‰Î¿ÿЉÂH‹Eø‰P‹UH‹EøH‹HH‹EèH‰ÎH‰Çè'ƒð„ÀtÇEôH‹EøH‹@H…ÀtH‹EøH‹@H‰Çè§¶ÿÿ‹EôÉÃUH‰åHƒì@H‰}èH‰uàH‰UØH‰MÐL‰EÈL‰MÀHƒ}èu ¸ÿÿÿÿéãH‹Eè‹@$ƒø‡¯‰ÀH‹ÅØ…@ÿàH‹UØH‹EèH‰ÖH‰Çè ýÿÿ…Àu H‹EèÇ@$ëH‹EèÇ@$ërH‹MÈH‹UÀH‹uÐH‹EèH‰ÇèÛûÿÿ‰Eüƒ}üt H‹EèÇ@$ƒ}üÿu?H‹EèÇ@$ë2H‹EàÆH‹EèH‹H…ÀtH‹EèH‹H‰Çè¹õÿÿH‹EèHÇëëH‹Eè‹@$ƒøt H‹Eè‹@$ƒøu¸ÿÿÿÿë¸ÉÃUH‰åHƒìH‰}øHƒ}øt@H‹EøH‹H…Àt4H‹EøÇ@$H‹EøA¹A¸¹º¾H‰Çè™þÿÿëÉÃUH‰åHƒì`H‰}¸H‰u°H‰U¨H‰M HUи¹H‰×óH«ÆEÏÇEôL‹E H‹}¨H‹M°H‹U¸HuÏHEÐM‰ÁI‰øH‰Çè7þÿÿ…ÀuëÔ¶EÏÉÃUH‰åH‰}èH‹EèH‹@H‰ÂH‹EèH‹@H)ÂH‰ÐH‰EøH‹UøH‰ÐHÁàHÐH…HÐHÁàH‰ÁH‹Eè‹@ HcðH‰ÈH™H÷þ]ÃUH‰åHƒìpH‰}¸H‰u°H‰U¨H‰M L‰E˜L‰MHÇEðÆEÿHUÀ¸¹H‰×óH«Hƒ}¨u ¸éÊH‹E¨¾Ð…@H‰ÇèžH‰EðHƒ}ðuÆEÿë|H‹E¸H‰EÀH‹E°H‰EØH‹E H‰EÐH‹EðH‰EàHUÀH‹u¨H‹E¸H‰ÑºbU@H‰ÇèŽþÿÿƒð„ÀtÆEÿë3¶Eèƒð„ÀtÆEÿë"H‹Eȶ„ÀtH‹MÈH‹UH‹E˜H‰ÎH‰ÇèíÿÿH‹EÈH…Àt H‹EÈH‰Çèo³ÿÿHƒ}ðt H‹EðH‰Çè5¶EÿÉÃUH‰åHƒì H‰}èH‰uàè]H‰EøHƒ}øt)H‹UøH‹uàH‹EèH‰ÑºTT@H‰Çèäýÿÿƒð„Àu H‹EøëëHƒ}øt H‹EøH‰ÇèϸÉÃUH‰åHƒì`H‰}ÈH‰uÀH‰U¸‰M´D‰E°D‰M¬‹E´…Àt ƒøt+éÍ‹U¬H‹M¸H‹EÈH‰ÎH‰Çèýƒð„À„ é§ÇEüHÇEÐHÇEØHÇEàHÇEèè‚H‰EèH‹EèH‹@@‹M¬‹U°H‹u¸H}ÐÿЃð„ÀuWH‹EèH‹@HH‹UÐH‰×ÿЉEüƒ}ütæD‹M°L‹E¸H‹MÀH‹UÈ‹uüHEЋ}W‹}¬WH‰ÇèúÿÿHƒÄ…Àuë ë¸ë¸ÉÃUH‰å¸ †@]ÃUH‰å¾p¿èý²ÿÿ]ÃUH‰åHƒì H‰}èH‹EèH‰EøHƒ}øt H‹EøH‰Çè´°ÿÿÉÃUH‰åH‰}è‰uä‰UàH‰MØL‰EÐH‹EèH‰EøHƒ}øt-H‹Eø‹Uä‰PH‹Eø‹Uà‰P H‹EøH‹UØH‰H‹EøH‹UÐH‰Pë]ÃUH‰åH‰}èH‹EèH‰EøHƒ}øu¸ëH‹Eø‹@]ÃUH‰åH‰}èH‹EèH‰EøHƒ}øu¸ëH‹Eø‹@ ]ÃUH‰åH‰}èH‹EèH‰EøHƒ}øu¸ëH‹EøH‹@(]ÃUH‰åH‰}è‰uäH‹EèH‰EøHƒ}øtH‹EøH‹P(‹EäH)ÂH‹EøH‰P(]ÃUH‰åHƒì H‰}èH‹EèH‰EøHƒ}øt H‹EøH‰Çè¼°ÿÿÉÃUH‰åHƒì H‰}èH‹EèH‰EøHƒ}øu¸ÿÿÿÿë&H‹Eø¾H‰Ç趯ÿÿ‰Eôƒ}ôu¸ë¸ÉÃUH‰åHƒì H‰}èH‹EèH‰EøHƒ}øu¸ë&H‹Eøºp¾†@H‰Çè±ÿÿ…Àt¸ë¸ÉÃUH‰åHƒì H‰}øH‰uð‰Uì‰MèHƒ}øu ¸éÒèÙýÿÿH‰ÂH‹EøH‰H‹EøH‹H…ÀtpH‹EøH‹¹pº†@¾ñÿÿÿH‰ÇèU¯ÿÿ…ÀuQ‹EèH‰Çè¯ÿÿH‰ÂH‹EøH‰PH‹EøH‹@H…Àt1H‹EøH‹xH‹EøH‹H‹Mð‹Uè‹uìI‰øH‰Çè™ýÿÿ¸ëGëëH‹EøH‹H‰ÇèRýÿÿH‹EøH‹H‰Çè¯ÿÿH‹EøH‹@H…ÀtH‹EøH‹@H‰Çèñ®ÿÿ¸ÉÃUH‰åHƒì H‰}èH‹EèH‰EøHƒ}øt4H‹Eø¾H‰Çèž®ÿÿ‰Eôƒ}ôu¸ëƒ}ôtƒ}ôûu ¸ë ë¸ÿÿÿÿÉÃUH‰åHƒì H‰}è‰uäH‹EèH‰EøHƒ}øt‹uäH‹Eø¹pº†@H‰ÇèÙ­ÿÿÉÃUH‰åHƒì ‰}üH‰uðH‰UèH‹Eè‰Â‹EüH‹MðH‰ÎH‰ÇèK®ÿÿÉÃUH‰å‰øˆEü€}ü/”À]ÃUH‰å¸ †@]ÃUH‰åHƒì0H‰}ØHÇEøH‹EØH‰ÇèÌ®ÿÿH‰EèÆE÷Hƒ}èu ¸éÃH‹EèH‰ÇèOH‹Eè¶„ÀttH‹UØH‹EèH‰ÖH‰Çè©®ÿÿ…Àt]H‹EèH‰ÇèÈ „ÀtH‹EØH‰EøH‹EØH‰ÇèT ˆE÷ë4H‹EèH‰EøH‹EèH‰Çè\ÿÿÿˆE÷€}÷tH‹EØH‰EøH‹EØH‰Çè ˆE÷Hƒ}øt!¶E÷ƒð„ÀtH‹EøH‰Æ¿¨†@¸èà«ÿÿH‹EèH‰Çè­ÿÿ¶E÷ÉÃUH‰åHƒì H‰}èH‹EèH‰Çèâ¾.H‰ÇèI­ÿÿH‰EøHƒ}øu¸Ë†@ëH‹EøHƒÀÉÃUH‰åHƒì H‰}èH‹EèH‰Ç衾.H‰Çè­ÿÿH‰EøHƒ}øu¸ëH‹Eø¶„ÀtH‹EøÆH‹EøÉÃUH‰åHƒìH‰}øH‹Eø¾#H‰Çè­ÿÿH…À•ÀÉÃUH‰åH‰}ø¸]ÃUH‰åHƒì H‰}èH‹Eè¾Ì†@H‰ÇèÝ«ÿÿH‰EøHƒ}øu¸ëH‹EøH‰ÇèO­ÿÿ¸ÉÃUH‰åHì0H‰½èïÿÿH‰µàïÿÿH‰•ØïÿÿH‰ÐïÿÿH•ðïÿÿ¸¹H‰×óH«HÇEøH‹àïÿÿH…ðïÿÿºH‰ÎH‰Çè.åÿÿH=ÿv¹pŠ@ºÙ¾Ï†@¿ð†@èÓªÿÿH…ðïÿÿH‰Çè`¾.H‰ÇèÇ«ÿÿH‰EøHƒ}øtH‹EøÆH‹•ÐïÿÿHðïÿÿH‹…èïÿÿH‰ÎH‰Çè¿äÿÿH;…Ðïÿÿr¹pŠ@ºÝ¾Ï†@¿8‡@ècªÿÿH‹•ÐïÿÿH‹ØïÿÿH‹…èïÿÿH‰ÎH‰ÇèåÿÿH;…Ðïÿÿr¹pŠ@ºÞ¾Ï†@¿p‡@è!ªÿÿÉÃUH‰åHƒì H‰}øH‰uðH‰UèH‰MàH‹UàH‹MðH‹EøH‰ÎH‰Çè)äÿÿH;Eàr¹€Š@ºò¾Ï†@¿ ‡@èЩÿÿH‹UàH‹MèH‹EøH‰ÎH‰Çè†äÿÿH;Eàr¹€Š@ºó¾Ï†@¿p‡@èš©ÿÿÉÃUH‰åHƒì H‰}èH‹Eè¾/H‰Ç芪ÿÿH‰EøH‹EøÉÃUH‰åHƒì0H‰}ØH‰uÐH‹EØH‰ÇèªÿÿH‰EøH‹EØH‰Çè­ÿÿÿH‰EðHƒ}ðtcH‹EøHPÿH‹EØHÐH;EðtNH‹MðHEàºH‰ÎH‰ÇèFãÿÿH‹UÐHMàH‹EØH‰ÎH‰ÇèÂãÿÿH;EÐrZ¹ Š@º¾Ï†@¿Ð‡@èÖ¨ÿÿHƒ}ðu;ècûÿÿH‰ÁH‹UÐH‹EØH‰ÎH‰ÇèãÿÿH;EÐr¹ Š@º¾Ï†@¿ˆ@蕨ÿÿÉÃUH‰åHƒì0H‰}èH‰uàH‰UØH‰MÐHÇEøH‹UÐH‹EèH‰ÖH‰ÇèîþÿÿH‹EàH‰ÇèîH‰EøH‹UÐH‹MøH‹EèH‰ÎH‰ÇèãÿÿH;EÐr¹ÀŠ@º3¾Ï†@¿@ˆ@è¨ÿÿH‹UÐH‹MØH‹EèH‰ÎH‰ÇèÎâÿÿH;EÐr¹ÀŠ@º4¾Ï†@¿pˆ@èâ§ÿÿÉÃUH‰åHƒì0H‰}èH‰uàH‰UØHÇEðH‹EàH‰Çè þÿÿH‰EøHƒ}øtHƒEøëH‹EàH‰EøH‹UØH‹MøH‹EèH‰ÎH‰ÇèÀáÿÿH;EØr¹àŠ@ºZ¾Ï†@¿ ˆ@èg§ÿÿÉÃUH‰åHƒì H‰}øH‰uðH‰UèH‹EøH;Eðt6H‹UèH‹MðH‹EøH‰ÎH‰ÇèiáÿÿH;Eèr¹‹@ºk¾Ï†@¿Èˆ@è§ÿÿH‹EøH‰ÇèÇÉÃUH‰åHƒì H‰}øH‰uðH‰UèH‹EøH;Eðt6H‹UèH‹MðH‹EøH‰ÎH‰ÇèáÿÿH;Eèr¹ ‹@º|¾Ï†@¿øˆ@è­¦ÿÿH‹EøH‰ÇèÙÉÃUH‰åHƒì0H‰}èH‰uàH‰UØHEøH‰Çè©ÿÿHEøH‰Ç貨ÿÿH‰ÂH‹uØH‹EèH‰Ñº&‰@H‰Çè·¨ÿÿH‹UØH‹MàH‹EèH‰ÎH‰Çè áÿÿÉÃUH‰åHƒì H‰}èHÇEøH‹EèH‰ÇèݦÿÿHƒøvLH‹EèH‰ÇètüÿÿH‰EøHƒ}øt H‹EøHƒÀÆë)è‡øÿÿH‰ÂH‹EèH‰Ñº=‰@¾H‰Ç¸èm¥ÿÿëÉÃUH‰åHƒì H‰}èH‹EèH‰Çèp¦ÿÿH‰EøHƒ}øt2H‹EøHPÿH‹EèHж¾À‰Çèøÿÿ„ÀtH‹EøHPÿH‹EèHÐÆH‹EèH‰Çè*ÿÿÿÉÃUH‰åHƒì H‰}èH‹EèH‰ÇèµûÿÿH‰EøHƒ}øt H‹EøHƒÀëH‹EèÉÃUH‰åH‰}øH‹Eø¶¾Ï†@¿è‰@èé¢ÿÿÉÃUH‰åHƒì H‰}øH‰uðH‰UèH‹Eø¶„ÀtH‹UèH‹EøH‰ÖH‰ÇèDùÿÿH‹UèH‹MðH‹EøH‰ÎH‰ÇèjÝÿÿH;Eèr¹ ‹@ºG¾Ï†@¿Š@è~¢ÿÿÉÃUH‰åHƒì@H‰}èH‰uàH‰U؉ÈL‰EȈEÔH‹UÈH‹MàH‹EèH‰ÎH‰ÇèÜÿÿH‰EøH‹EÈHƒÀH;Eøw¹À‹@ºY¾Ï†@¿GŠ@è¢ÿÿH‹UèH‹EøH¶EÔˆH‹EøHPH‹EèHÐÆH‹UÈH‹MØH‹EèH‰ÎH‰Çè¯ÜÿÿH;EÈr¹À‹@º^¾Ï†@¿è‰@èáÿÿÉÃUH‰åHì0H‰½èïÿÿH‰µàïÿÿH‰•ØïÿÿH•ðïÿÿ¸¹H‰×óH«HÇEøH‹…àïÿÿH‰ÇèüÿÿH‰ÆH…ðïÿÿ¹ºË†@H‰ÇèþõÿÿH…ðïÿÿ¾#H‰Çè’¢ÿÿH‰EøHƒ}øtNH‹EøH‰Çèë¡ÿÿHƒøw¹à‹@ºƒ¾Ï†@¿WŠ@è ¡ÿÿH‹EøHHH‹•ØïÿÿH‹…èïÿÿH‰ÎH‰Çè%Ûÿÿë H‹•ØïÿÿHðïÿÿH‹…èïÿÿH‰ÎH‰ÇèÛÿÿÉÃUH‰åHì°H‰½hÿÿÿ‰µdÿÿÿH‰•XÿÿÿH•pÿÿÿH‹…hÿÿÿH‰ÖH‰ÇèÞ…Ày¸ë`Hƒ½XÿÿÿtH‹E ‰ÂH‹…Xÿÿÿ‰‹…dÿÿÿƒøtƒørƒøt&ë+‹Eˆ%ð=@”Àë‹Eˆ%ð= ”Àë ¸ë¸ÉÃUH‰åHƒìH‰}øH‹Eøº¾H‰Çè9ÿÿÿÉÃUH‰åHƒìH‰}øH‹Eøº¾H‰ÇèÿÿÿÉÃUH‰åHƒìH‰}øH‹Eøº¾H‰ÇèñþÿÿÉÃUH‰åHƒì H‰}èÇEüHUüH‹Eè¾H‰ÇèÇþÿÿ„Àt‹Eüë¸ÿÿÿÿÉÃUH‰åHƒì H‰}èH‹Eè¾èH‰Çèð¡ÿÿ‰Eüƒ}üy#èÒ ÿÿ‹ƒøuH‹EèH‰Çèÿÿÿ„ÀtÇEüƒ}üy'è© ÿÿ‹‰ÇèP ÿÿH‰ÂH‹EèH‰Æ¿Œ@¸èwžÿÿƒ}ü”ÀÉÃUH‰åHƒìH‰}øHƒ}øu¸ÿÿÿÿë(H‹Eø‹%…ÀuH‹EøH‹@H‰Çè%žÿÿëH‹Eø‹@ÉÃUH‰åHƒì@H‰}؉uÔH‰UÈÇEüÇEìHÇEð¾¿èb ÿÿH‰EàHƒ}àu ¸éH‹Eà‹UÔ‰H‹Eà‹€äý‰ÂH‹Eà‰‹EÔ¶Àƒøt,ƒørƒøtKëjH‹Eà‹%…ÀuHÇEðŒ@ÇEüëJH‹Eà‹%…Àu HÇEðŒ@ë1ÇEüAMü€ë!H‹Eà‹%…Àu HÇEðŒ@ëÇEüH‹Eà‹%…Àu-H‹UðH‹EØH‰ÖH‰ÇèžÿÿH‰ÂH‹EàH‰PH‹EàH‹@H…Àu-ë2‹UüH‹E؉ÖH‰Ç¸è ÿÿ‰ÂH‹Eà‰PH‹Eà‹@ƒøÿtH‹EàëH‹EàH‰Çè¸ÉÃUH‰åHƒì H‰}øH‰uð‰UìHƒ}øtQH‹Eø‹%…ÀuH‹EøH‹@‹UìH‹MðH‰ÎH‰ÇèþœÿÿH˜ë/H‹Eø‹@‹UìH‹MðH‰Î‰Çè2žÿÿH…Àx ¸ë ëHÇÀÿÿÿÿÉÃUH‰åHƒìH‰}øHƒ}øtEH‹Eø‹%…ÀuH‹EøH‹@H‰Çè7œÿÿë/H‹Eø‹@º¾‰ÇèÍÿÿH…Àx ¸ë ëHÇÀÿÿÿÿÉÃUH‰åHƒìH‰}øH‹Eøº¾H‰ÇèÿÿÿÉÃUH‰åHƒì H‰}øH‰uðH‰UèHƒ}øtPHƒ}ðtIH‹Eø‹%…ÀuH‹EøH‹HH‹UèH‹Eð¾H‰Çèaÿÿë"H‹Eø‹@H‹UèH‹MðH‰Î‰Çè&œÿÿëHÇÀÿÿÿÿÉÃUH‰åHƒì H‰}øH‰uðH‰UèHƒ}øtIH‹Eø‹%…ÀuH‹EøH‹HH‹UèH‹Eð¾H‰Çè¤ÿÿë#H‹Eø‹@H‹UèH‹MðH‰Î‰ÇèÉÿÿëHÇÀÿÿÿÿÉÃUH‰åHƒìH‰}ø‰uôHƒ}øu¸ÿÿÿÿëH‹EøH‹P‹EôH‰Ö‰ÇèÛ›ÿÿÉÃUH‰åHƒìH‰}øHƒ}øtZH‹Eø‹%…ÀuH‹EøH‹@H…Àt+H‹EøH‹@H‰ÇèêœÿÿëH‹Eø‹@…À~H‹Eø‹@‰ÇèšÿÿH‹EøH‰Ç胛ÿÿ¸ë¸ÿÿÿÿÉÃUH‰åHƒì@H‰}ØH‰uÐH‰UÈHÇEðHÇEèHÇEøH‹EØHÇÂÿÿÿÿ¾H‰ÇèÆûÿÿH‰EàHƒ}àu3èð›ÿÿ‹‰Çè—›ÿÿH‰ÁH‹-1 H‹Uؾ"Œ@H‰Ç¸èwœÿÿéüH‹E຾H‰ÇèÛüÿÿH…À…ÖH‹EàH‰Çè>ýÿÿH‰EèHƒ}舾H‹EàH‰ÇèˆýÿÿH‹EèHƒÀH‰Çè<šÿÿH‰EøHƒ}ø„–H‹UèH‹MøH‹EàH‰ÎH‰ÇèwýÿÿH‰EðHƒ}ðy0è6›ÿÿ‹‰ÇèÝšÿÿH‰ÁH‹s0 H‹Uؾ9Œ@H‰Ç¸è½›ÿÿëEH‹EàH‰ÇèFþÿÿH‹EÐH‹UøH‰H‹UèH‹EøHÐÆHƒ}Èt H‹EÈH‹UðH‰¸ëOëëHƒ}àt H‹EàH‰ÇèúýÿÿHƒ}øt H‹EøH‰ÇèЙÿÿHƒ}Èt H‹EÈHÇÿÿÿÿH‹EÐHǸÉÃUH‰åHƒì0H‰}èH‰uàH‰UØHÇEøH‹EèHÇÂÿÿÿÿ¾H‰ÇèúÿÿH‰EðHƒ}ðu¸ë=H‹UØH‹MàH‹EðH‰ÎH‰ÇèÄüÿÿH‰EøH‹EðH‰ÇèVýÿÿH‹EøH;EØt¸ë¸ÉÃUH‰åHƒì H‰}èHƒ}ètWHÇEøë"H‹EèH‹H‹UøHÁâHÐH‹H‰Çèí˜ÿÿHƒEøH‹EèH‹@H;EøwÐH‹EèH‹H‰Çè˘ÿÿH‹EèH‰Ç还ÿÿëÉÃUH‰åHƒì H‰}èH‰uàHÇEøH‹EèH‹@H;Eàr¹°Œ@º?¾PŒ@¿mŒ@èË—ÿÿH‹EàHÁàH‰ÂH‹EèH‹H‰ÖH‰ÇèΙÿÿH‰EøHƒ}øu¸ëfH‹EèH‹@H;Eàs Doing tests... Test failed. ‰PNG  [RPNG]: Error in line %d. yesnoIHDR: (%u x %u), bpc = %u, palette = %s, color = %s, alpha = %s, adam7 = %s. -@@æ@™@æ@@æ@ö!@<#@4"@~"@¼"@<#@û"@e(@Ž(@*)@|)@V*@Ž+@^,@¸+@ß+@,@^,@8,@Ê9@ó9@P7@³8@ç7@™9@IHDRIDATIENDPLTEÀƒ@Ń@ʃ@σ@ÿU‰PNG  [RPNG]: Error in line %d. IDATrbwbr+bERROR - attempted file read operation while busyERROR - attempted file write operation while busyERROR - attempted file resize operation while busyERROR - attempted file shrink operation, not implementedERROR - attempted free() while busy|.Š]@ë\@]@b]@[]@1.2.8zlib`a@ua@Ÿa@ôa@b@Bb@jb@c@[c@Vd@°d@b@Çb@êd@†@/Failed to create directory: "%s". rb../../..//file/file_path.cstrlcpy_retro__(tmp_path, in_path, sizeof(tmp_path)) < sizeof(tmp_path)strlcpy_retro__(out_path, tmp_path, size) < sizestrlcat_retro__(out_path, replace, size) < sizestrlcpy_retro__(out_path, in_path, size) < sizestrlcat_retro__(path, join_str, size) < sizestrlcat_retro__(path, path_default_slash(), size) < sizestrlcat_retro__(in_dir, base, size) < sizestrlcat_retro__(in_dir, replace, size) < sizestrlcpy_retro__(out, ptr, size) < sizestrlcpy_retro__(out_dir, in_path, size) < sizestrlcpy_retro__(out_dir, in_dir, size) < sizeRetroArch-%m%d-%H%M%S..%ssize >= 4096strlcpy_retro__(out_path, in_refpath, size) < sizestrlcat_retro__(out_path, in_path, size) < sizestrlcpy_retro__(out_path, dir, size) < sizestrlcat_retro__(out_path, path, size) < sizestrlcat_retro__(out_path, append, size) < sizecopied < size+1strlen(last_hash) > 1fill_pathnamefill_pathname_noextfill_pathname_slashfill_pathname_dirfill_pathname_basefill_pathname_basedirfill_pathname_parent_dirpath_resolve_realpathfill_pathname_resolve_relativefill_pathname_joinfill_string_joinfill_pathname_join_delimfill_short_pathname_representationmkdir(%s) error: %s. rbwbw+Failed to open %s: %s Failed to read %s: %s ../../../lists/string_list.ccap > list->sizelist->elems[idx].data = strdup(str)len < sizestring_list_capacitystring_list_setstring_list_join_concat;Ä—È„ÿÿXˆÿÿàN‰ÿÿ8ߊÿÿXÛŒÿÿx‹ÿÿ˜ Žÿÿ¸[ŽÿÿؾŽÿÿø"‘ÿÿ¾‘ÿÿ8w’ÿÿX‘“ÿÿx”ÿÿ˜Ä”ÿÿ¸––ÿÿØX—ÿÿøÌ—ÿÿ>›ÿÿ@–Ÿÿÿh¡ÿÿˆÕ¢ÿÿ¨À£ÿÿÈ-¤ÿÿè¦ÿÿ¼¦ÿÿ(§ÿÿH¨ÿÿh(©ÿÿˆØ©ÿÿ¨­ÿÿÈá­ÿÿè‹®ÿÿ ¯ÿÿ( ~¯ÿÿH ®¯ÿÿh ݯÿÿˆ ^°ÿÿ¨ ¹°ÿÿÈ ,±ÿÿè K²ÿÿ ½²ÿÿ( ?³ÿÿH ʳÿÿh ,´ÿÿˆ v´ÿÿ¨ î´ÿÿÈ “µÿÿè e¶ÿÿ w·ÿÿ0 V¿ÿÿP ”¿ÿÿp Ò¿ÿÿ eÀÿÿ° ÐÀÿÿÐ CÂÿÿð £Âÿÿ Ãÿÿ0 ®ÄÿÿP PÅÿÿp Åÿÿ ÉÅÿÿ° >ÆÿÿÐ yÆÿÿð  Æÿÿ ÈÆÿÿ0 \ÇÿÿP jÈÿÿp ÓÉÿÿ !Êÿÿ° ÌÿÿÐ &Íÿÿð ÎÎÿÿ¦Ïÿÿ8¼ÐÿÿXÑÿÿx|Ñÿÿ˜ÕÑÿÿ¸òÒÿÿØYÓÿÿø]ÔÿÿhÔÿÿ8}ÔÿÿX§ÔÿÿxüÔÿÿ˜#Õÿÿ¸JÕÿÿØrÕÿÿø¥ÕÿÿÏÕÿÿ8ÖÿÿXcÖÿÿx^×ÿÿ˜¸×ÿÿ¸ò×ÿÿØØÿÿø1Øÿÿ<Øÿÿ8:ÙÿÿX{ÙÿÿxÊÙÿÿ˜ïÙÿÿ¸þÙÿÿØ@ÚÿÿøzÛÿÿÜÿÿ8(ÜÿÿXÝÿÿx¹Ýÿÿ˜4Þÿÿ¸—ÞÿÿØúÞÿÿø[ßÿÿÐßÿÿ84àÿÿXgàÿÿxˆàÿÿ˜&áÿÿ¸âÿÿزâÿÿøãÿÿØãÿÿ8ÒäÿÿXwåÿÿx›åÿÿ˜¿åÿÿ¸ãåÿÿØæÿÿøšæÿÿÞæÿÿ8GèÿÿX¿èÿÿx$éÿÿ˜Iéÿÿ¸½éÿÿØ+êÿÿø_êÿÿÔêÿÿ8œìÿÿX!íÿÿxŽíÿÿ˜dîÿÿ¸¾îÿÿØŒïÿÿøðÿÿ Õðÿÿ@Õñÿÿ`Hòÿÿ€hóÿÿ ØóÿÿèèóÿÿzRx pƒÿÿ*zRx $°ÿÿ€FJ w€?;*3$"D„ÿÿ‘A†C Œ d…ÿÿüA†C ÷ „[‡ÿÿ°A†C « ¤ë‡ÿÿA†C | ÄLˆÿÿOA†C J ä{ˆÿÿcA†C ^ ¾ˆÿÿdA†C _ $‹ÿÿœA†C — D~‹ÿÿ¹A†C ´ dŒÿÿA†C  „ÿÿ€A†C { ¤qÿÿ³A†C ® ÄŽÿÿÒA†C Í ä¶ÿÿÂA†C ½ XÿÿtA†C o $$¬ÿÿrA†C Eƒh $Lö“ÿÿXA†C EƒN t&˜ÿÿrA†C m ”x™ÿÿÍA†C È ´%›ÿÿëA†C æ Ôð›ÿÿmA†C h ô=œÿÿÙA†C Ô öÿÿ¶A†C ± 4ŒžÿÿYA†C T TÅžÿÿˆA†C ƒ t- ÿÿ‹A†C † ”˜ ÿÿ°A†C « ´(¡ÿÿ@A†C ; ÔH¤ÿÿÉA†C Ä ôñ¤ÿÿªA†C ¥ {¥ÿÿ”A†C  4ï¥ÿÿ_A†C Z T.¦ÿÿ0A†C k t>¦ÿÿ/A†C j ”M¦ÿÿA†C | ´®¦ÿÿ[A†C V Ôé¦ÿÿsA†C n ô<§ÿÿA†C  ;¨ÿÿrA†C m 4¨ÿÿ‚A†C } Tï¨ÿÿ‹A†C † tZ©ÿÿbA†C ] ”œ©ÿÿJA†C E ´Æ©ÿÿxA†C s Ôªÿÿ¥A†C   ô£ªÿÿÒA†C Í $U«ÿÿA†C GŒƒ <?¬ÿÿßA†C Ú \þ³ÿÿ>A†C y |´ÿÿ>A†C y œ:´ÿÿ“A†C Ž ¼­´ÿÿkA†C f Üø´ÿÿsA†C n üK¶ÿÿ`A†C [ ‹¶ÿÿ`A†C [ <˶ÿÿ«A†C ¦ \V¸ÿÿ¢A†C  |ظÿÿMA†C H œ¹ÿÿ,A†C g ¼¹ÿÿuA†C p Üf¹ÿÿ;A†C v ü¹ÿÿ'A†C b ˆ¹ÿÿ(A†C c <¹ÿÿ”A†C  \ºÿÿA†C   |òºÿÿiA†C d œ;¼ÿÿNA†C I ¼i¼ÿÿöA†C ñ Ü?¾ÿÿA†C   $ü.¿ÿÿ¨A†C Eƒž $ ®ÀÿÿØA†C Ó D fÁÿÿA†C  d \ÂÿÿVA†C Q „ ’ÂÿÿjA†C e ¤ ÜÂÿÿYA†C T Ä ÃÿÿA†C  ä ÄÿÿgA†C b  YÄÿÿA†C ÿ $ =Åÿÿ A†C F D (ÅÿÿA†C P d Åÿÿ*A†C e „ 'ÅÿÿUA†C P ¤ \Åÿÿ'A†C b Ä cÅÿÿ'A†C b ä jÅÿÿ(A†C c  rÅÿÿ3A†C n $ …Åÿÿ*A†C e D ÅÿÿJA†C E d ¹ÅÿÿJA†C E „ ãÅÿÿûA†C ö ¤ ¾ÆÿÿZA†C U Ä øÆÿÿ:A†C u ä Çÿÿ-A†C h  ÇÿÿA†C M $ Çÿÿ A†C F D üÆÿÿþA†C ù d ÚÇÿÿAA†C | „ ûÇÿÿOA†C J ¤ *Èÿÿ%A†C ` Ä /ÈÿÿA†C J ä ÈÿÿBA†C }  @Èÿÿ:A†C 5 $ ZÉÿÿ‡A†C ‚ D ÁÉÿÿ'A†C b d ÈÉÿÿßA†C Ú „ ‡Êÿÿ²A†C ­ ¤ Ëÿÿ{A†C v Ä tËÿÿcA†C ^ ä ·ËÿÿcA†C ^ úËÿÿaA†C \ $;ÌÿÿuA†C p DÌÿÿdA†C _ dÔÌÿÿ3A†C n „çÌÿÿ!A†C \ ¤èÌÿÿžA†C ™ ÄfÍÿÿÝA†C Ø ä#Îÿÿ¯A†C ª ²ÎÿÿkA†C f $ýÎÿÿ»A†C ¶ D˜ÏÿÿúA†C õ drÐÿÿ¥A†C   „÷Ðÿÿ$A†C _ ¤ûÐÿÿ$A†C _ ÄÿÐÿÿ$A†C _ äÑÿÿ8A†C s ÑÿÿA†C z $zÑÿÿDA†C  DžÑÿÿiA†C d dçÒÿÿxA†C s „?ÓÿÿeA†C ` ¤„Óÿÿ%A†C ` ĉÓÿÿtA†C o äÝÓÿÿnA†C i +Ôÿÿ4A†C o $?ÔÿÿuA†C p D”ÔÿÿÈA†C à d<Öÿÿ…A†C € „¡ÖÿÿmA†C h ¤îÖÿÿÖA†C Ñ Ä¤×ÿÿZA†C U äÞ×ÿÿÎA†C É $ŒØÿÿzA†C Eƒp ,ÞØÿÿÏA†C Ê LÙÿÿA†C û lmÚÿÿsA†C n ŒÀÚÿÿA†C   D¬ÀÛÿÿeBBŽE B(ŒH0†H8ƒM@r8A0A(B BBBôèÛÿÿ àÛÿÿ @@¸I  @ ð€@¥` ¥`õþÿo`@Ð@ @ ´ (§`(x @H @0 þÿÿo @ÿÿÿoðÿÿo„ @0¥`Ö@æ@ö@@@&@6@F@V@f@v@†@–@¦@¶@Æ@Ö@æ@ö@@@&@6@F@V@f@v@†@–@¦@¶@Æ@Ö@æ@ö@@@&@6@F@V@f@v@†@–@¦@¶@Æ@Ö@æ@ö@@@&@6@°„@³„@¶„@°„@³„@¶„@GCC: (GNU) 5.3.0,F@=,èƒ@R",*Õ<@õ,&+ÊL@þ,r,ÈM@n,—16S@*,"A`a@·,”Ie@³ ,›VÊq@È,FZ’s@‡,taz@8ä 7ŠF@=ZØ8†g‹iˆintBƒi8„i’•p^Øñ%òbÎ÷Ëø|ù¶ú ›û(*ü0®ý8Ûþ@ àH dP pX ÂQ` ]Wh îbp t bt px -F€ T‚ ¬]ƒ mˆ !{ î)˜ õ*  ü+¨ u,° .-¸ -/bÀ Å1sÄ ,–¡œQèQXžW9¢b œ •m † •ƒ †‰ • ô0?˜3M!)$Õbà~XJö§C#ÃF@‘œÊ‚#ƒ‘¸ƒ#Ê‘°E$Б¨‚$Б »&b‘L×'-‘@ret(Ño)Ö‘`ptr*‘Xi+á‘Pend`‰@MÊçÜükb×@üœpØkƒ‘ˆimgn¸‘`}op‘hq‹‘ ƒ{‘˜E|M‘”‚}M‘v § v‹ † {©¸bÓ@°œÜ|¸b‘\>¸²‘Pغƒ‘h ªW>E ªŠƒ@R"•ZØ8†g‹iˆintBƒi8„i’•p^Øñ%òbÎ÷Ëø|ù¶ú ›û(*ü0®ý8Ûþ@ àH dP pX Âa` ]gh îbp t bt px -F€ T‚ ¬mƒ }ˆ !{ î)˜ õ*  ü+¨ u,° .-¸ -/bÀ Å1ƒÄ •) † ,–¡œaèaXžg9¢b0œ •} †) •“ †™ •b­ô0?˜3M·78  •ì †\ ()*ƒ+)Ì ,¸U-ð­cx0ðÕ2 3‘4L_6aÖ7a 98v(?9Œ0¤:¨8r;Ò@=ØHh>îP»?XP@Ø` A hÊB“pö /Î.ìA¸¸A)G ­"¸aRÃvgŒM|¡¡’¡ÌÌA¸¸û®žîbÞ¸ ¸A-ô$Èu˜&wbÇx¡˜™y¡™îz¡š {¡›é|Ó  }¦°C~)ÀÆcÈP § -E /¸‚ 0¸ 1­ 2­ é 3­ ¨ 4­ % 5­ vM&6´ ûíןM/e·È‚Úõ ŠM8š÷Š ‚òÚ E BÓxDMyEM¸FMÁGM  JøƒL)Þ M-‰P)Þ R¸~SƒT)jbElM‚mMÞ n-posoM!˜W]Y¡ Z¡2[¡8\¡ƒ]]Æ^] _¦¸`)(Ia)0Àb)86c-@0d-Hëe-P» f-XbppgM`"hMdhiMhK p)pqˆ6 r𸠸s †ÿ, b‚œƒ~‘Ñ *bƒ@œ a*b‘\b*b‘Xc*b‘Tp,b‘lpa-b‘hpb.b‘dpc/b‘`ÐЏ@OœE bufŠA‘hŠeS@cœ» » ‘Xi‘M‘l’  id”“~•e € Y–Ö àƒ@Á ø   Ö † Æ /¦¡¶@dœ¢  ¦¢ ‘Xi¨M‘lret©¡‘kendç@-@ll §µ½  „@¶¡‘j ™@h§ÇÒ @„@È¡‘i¦ ¸ ¸ † M ¨ ¸ Ò †  !š ë@œœo ƒë]‘X¯ìA‘PEìM‘LbppìM‘HiîM‘l >@irô¸‘hgô¸‘dbô¸‘`"Ù¶@¹œ #ƒ]‘H#¯A‘@#EM‘¼$bppM‘¸%iM‘l Ý@%r ¸‘h%g ¸‘d%b ¸‘`%a ¸‘\"e o@œ! #ƒ]‘H#¯A‘@#EM‘¼#M‘¸%iM‘l%bitM‘h&(1 `„@%mulM‘`& M‘\@:ð %val!¸‘d @i& -M‘X%val.M‘T ¸ 1 † ! ";6‰ @€œÎ #ƒ6]‘X#¯7A‘P#E7M‘L$bpp8M‘H%i:M‘l ­ @M&²@¸‘h&]@¸‘d"aK !@³œ–#ƒK]‘H#¯LA‘@#ELM‘¼#MM‘¸#ÆM–‘°%iOM‘l%bitOM‘h& PM‘d C!@d& VM‘`%valWM‘\œ ¸"â^¼!@Òœ9# ^9‘X#E_M‘T#‚_M‘P#¢`D‘H#O`D‘@#`J‘¸%bppbM‘l&"cM‘h? ¦M-"M‰Ž#@œ#ƒ‰]‘X# Š9‘P#‹–‘H#@‹M‘D#}‹M‘@#K Œ‘¸%xŽM‘l%yŽM‘h Ô#@H%out•]‘`  š'œP$@tœ>#•œ>‘hb(š³bÄ$@rœ¤# ³9‘H#•´>‘@&¶-‘X)Zð(@( õb6(@XœX#ƒõ]‘H# õ9‘@#•ö>‘¸#¨öM‘´%iøM‘\…)@=6%avg ­‘[ Þ)@c%avg­‘Z(¿;bŽ,@rœè#ƒ;è‘X# ;9‘P#•<>‘H%ret>b‘l*endT¥-@ »,@N&¨BM‘h](.]b.@Íœk#p]è‘X# ^9‘P#•_>‘H%retab‘l&æb¡‘k&ƒc]‘`(= ŒbÍ/@ëœÊ#pŒè‘X# 9‘P#•Ž>‘H%retb‘l(`¨b¸0@mœ #¨ ‘h#ƒ¨è‘`(V ³b%1@Ùœ¾#³ ‘X#ƒ´è‘P#E´D‘H#‚´D‘@&°¶b‘h&“·¡‘o*endËã1@)ZæÊ2@)Ðéï2@+±î¡þ2@¶œT$bufî)‘X#% ï]‘P#ÌïM‘L%iñM‘l 3@„%rõ¸‘h%gö¸‘d%b÷¸‘`,Kþ¡´3@Yœ¤#þ» ‘X$bufþ¤‘P&w)‘hÓ(– ¡ 4@ˆœ #  ‘h#ƒ è‘`#E D‘X#‚ D‘P(Ô,¡•5@‹œf$buf,)‘X#,f‘P%i.M‘l&/l‘`ø ­| †(÷<¡ 6@°œ½$buf<)‘h# =¢ ‘`,{O¡Ð6@@œ@#O ‘¸%iQM‘l&Rø‘@%bufS)‘`)Z­ :@-&Ì|M‘\, ±b:@ÉœÀ#± ‘X#ƒ²è‘P#E²D‘H#‚²D‘@ •:@/%retÁb‘l.GËÙ:@ªœî#Ë ‘h,cÝ¡ƒ;@”œ<#Ý ‘X%ißM‘l&ßàÜ‘`/W ð¡<@_œn#ð ‘h/*þ¡v<@0œ¯#þ ‘h#ƒþ)‘`,…  ¦<@/œá&  ‘h Gñ †€ ) À@ á  †&ð©1 À‚@ 0 ªgø  , ŠÕ<@õãZØ8†g‹iˆintBƒi8„i’M ¬i p^Øñ$%òbÎ÷šËøš|ùš¶úš ›ûš(*üš0®ýš8Ûþš@ àšH dšP pšX Â\` ]bh îbp t bt px -F€ T‚ ¬hƒ xˆ !{ î)˜ õ*  ü+¨ u,° .-¸ -/bÀ Å1~Ä ,–¡œ\è\Xžb9¢b+§  x †$  Ž †”  b¨O f õÂTô0?˜3M·78W $øW M '*× Ž « ´ { P \ (u *ƒ +uÌ ,×U -<Ìcx 0<Õ 2W 3h‘ 4˜_ 6­Ö 7­ 9 8Â(? 9Ø0¤ :ô8r ;@ =$Hh >:P» ?hXP @$` AYhÊ BŽpB {Î .8Rh]××u“ Ìn×­žâ³ØMÈííÞí××Gú™:b*×Y×-@§ -ÀE /ׂ 0× 1Ì 2Ì é 3Ì ¨ 4Ì % 5Ì Ñ *bÕ<@œ9a*b‘\b*b‘Xc*b‘Tp,b‘lpa-b‘hpb.b‘dpc/b‘`² (V=@[œsbuf(u‘hval(בdL 0í±=@sœée0é‘Xƒ0‘PÞ 0-‘H3 2ï‘`6 3<‘hcrc5בdí Ìÿ † ;í$>@œKe;é‘H ;K‘@r =V‘PQ _ Ìf †˜ bíC?@rœ²ebé‘hƒb‘`Þ b-‘X× míµ?@‚œðemé‘Xƒo‘` “ † ð ~7@@‹œydst~u‘Xsrc~y‘PE~M‘Li€M‘lO@@dcolƒ×‘h × ‹Â@@bœØdst‹u‘Xsrc‹‘PE‹M‘LiM‘lË –M$A@Jœ0 ƒ–‘XÞ –-‘Pi˜-‘hcnt™M‘dÁ ŸMnA@xœ¤ þ Ÿu‘X Ÿ‘Pæ  ‘HE M‘Dbpp M‘@i¢M‘l§ ªMæA@¥œ þ ªu‘X ª‘PE«M‘Lbpp«M‘Hi­M‘l™ ·M‹B@Òœ~ þ ·u‘X ·‘Pæ ¸‘HE¸M‘Dbpp¸M‘@iºM‘lÊ ÄM]C@œõ þ Äu‘H Å‘@æ Å‘¸EÆM‘´bppÆM‘°iÈM‘\# ÒíoD@ßœú ‚ÒŽ‘¸~ƒÓ‘°~EÔM‘¬~‚ÔM‘¨~"ÔM‘¤~bppÔM‘ ~hÖM‘lret×í‘k Ø_‘À~6 Ú<‘`o Û-‘ø~d Üu‘XŸ Ýu‘P; Þu‘Hë ßu‘@Á àu‘¸ áu‘°= âu‘¨‹ ãu‘ ÷ äu‘˜å‘eæé‘ð~endfËK@H@¬ç M‘ì~Î M‘è~Z M‘ä~" M‘à~ò M‘Ü~¨Ì‘E M‘ˆ¤ ‘€ ] uíNL@>œh !‚uŽ‘h!ƒuy‘`!EvM‘\!‚vM‘X!"vM‘T þ |íŒL@>œÖ !‚|Ž‘h!ƒ|‘`!E}M‘\!‚}M‘X!"}M‘T€ )ë ˆ„@ ð"ªbHë ú ŠÊL@þº g‹†iˆint’rprZØB "„ÊL@“œõÕ "l‘Xó "y‘PÞ "„‘H Ú $„‘h n%„‘` ã 3„]M@kœÕ 3l‘Xó 3y‘PÞ 3„‘H len5„‘h!• r ŠÈM@n‰ ZØ8†g‹iˆintBƒi8„i’•pX 0§^Øñ$%òbÎ÷Ëø|ù¶ú ›û(*ü0®ý8Ûþ@ àH dP pX Â\` ]bh îbp t bt px -F€ T‚ ¬hƒ xˆ !{ î)˜ õ*  ü+¨ u,° .-¸ -/bÀ Å1~Ä ,–¡œ\è\Xžb9¢b+§ •x †$ •Ž †” • ç(ùfùƒ  -len -opT .T!œ; fÈM@sœfDŽ‘X.M‘Tif‘hfù‘`Z=äN@§™ J;O@`œ˜iJf‘h³ [›O@`œÄi[f‘hE k"ûO@«œ"ikf‘X’ m-‘hìP@Ij ƒ-‘`R •¦Q@¢œci•f‘hlen•-‘`( «HR@Mœ¡i«f‘hlen«¡‘`-^ ¶•R@,œÓi¶f‘h© ¿ÁR@uœÿi¿f‘h Ž †5 ÿ  ©`‡ú äŠ6S@*ZØ8†g‹iˆint’M ¬iŠp—Šb« wO fy ™Äbñ•iô0?˜3M·78 ÞM* Ë Ñ ˜   \ (g *w ƒ+g Ì ,å U-.Ú cx0. Õ2I 3Z ‘4Š _6Ÿ Ö7Ÿ 98´( ?9Ê0 ¤:æ8 r;@ =H h>,P »?ZX P@` AKh ÊB‘p4mÎ.*wDZ wO w å å  g…Ú`åŸ wð´ w¥Ê w Mºßß wÐß    å å9ìœ, w båK å  -2 10E² iGw žH ¹I ƒJ ó K½ ~Lû$ UM.(ÊNQtRÈÎb ‘ ‘  M å å å wM )1   ] ë 6 ‡P ò"gb$ßi%bp&w 3)Œ ƒ+„ ,? F/½ ë1½ Þ 2-cap3-g q09 ×;„ m<„ ®=‘ Ã>-ext? ü @ß(Œ ~MC;  GI\ ƒNw Þ O-SP;$•6S@;œ¡i•w‘Xƒ—¡‘h\†žqS@'œåižw‘Xƒ ¡‘hà¦-˜S@(œ#i¦w‘Xƒ¨¡‘h_®wÀS@”œŒ‚®‘‘Hret°«‘X)±ß‘oƒ²¡‘`ZÁAT@¹ÇbTT@œ‹‚È‘‘¸É‘‘°GÊ‘¨Ä ËM‘¤€Ìå‘ Þ Íå‘œÑ Îå‘}Ïw‘Ñ?‘@(Ò‘hJÓ‘‘`î Ô‘XZöOU@ÄT@o=䊑W’ûbbU@iœcHû‘‘Ø_û‘‘Ð_Gü‘È_Ä ýM‘Ä_€ýå‘À_Þ ý呼_Ñ þå‘}þw‘ext‘‘hƒc‘`ÛU@éi‘à_Êz pÿ!ŒåËV@Nœ×"ƒ‘X"Þ M‘TiM‘lvalå‘h#R%bW@öœß "]&ß ‘H"D&„‘@"G'å ‘¸"Ä (ë ‘°"Þ (ñ ‘¨"€(ñ ‘ "Ñ )ñ ‘"l)ë ‘+å‘\ù,å‘h8,å‘dÊ ,å‘`â-å‘X‰-å‘T.å‘l²Må#%LbY@œÓ "]Lß ‘¸_"M‘‘°_"}Mw‘¨_"M½‘ _GO‘`Ñ På‘\Þ Qå‘X€Rå‘TÄ SM‘PMTM‘LDUi‘À_retVb‘l#œkbZ@¨œ) "]kß ‘H"el‘‘@$0D„M‘\#¥bÆ[@ØœÔ "iž ‘h%retŸb‘d"‚ ‘‘X"¡‘‘P"G¢‘H"€£å‘`"Þ ¤å‘"Ñ ¥å‘&endÅ|\@'ûËbž\@œt "]Ìß ‘X"Ít ‘P"eΑ‘H"Ï‘‘@"н‘¸"}Ñw‘°]@=retâb‘lß(ú´]@Vœ¨ "]úß ‘h#Uß ^@jœ* "e‘‘¨"‘‘ "½‘˜"}w‘]²‘@ß‘¿)ª"bt^@Yœk "]"ß ‘X†%Ï‘h'”5ßÍ^@œ,"×6„‘¨"Ã7-‘ "8‘‘˜"®9‘‘"â:„‘ˆ%len:-‘€î <‘`ret=ß‘o}>Ѱ&endd¼_@'Ø rê_@gœŒ"‚r‘‘X"s‘‘Pî u‘h*Z€7`@'†ßQ`@œa"‚†‘‘¸"†‘‘°"G‡‘¨"Ä ‡M‘¤"€‡å‘ "Þ ‡å‘œ"Yˆå‘"}ˆw‘*Z¬Na@$`ret“b‘li”9‘@+¼°.Ua@ œ,P‡4nš  ÷Š`a@·0ZØ8†intg‹iˆ’p »pF/rTËs8sy”ó‚wÀPÛáÄú Ä    *Q   Ä Ä àpUÐ ëVÐ jW  ƒX¬ –ZÐ á[  D\¬( msg^y0 ]_ñ8 ƒaÐ@ }búH DcÄP ye?X Nf¬` Ôg¬h¸TÎñ4Î?Öhúj ÷ô0F˜3T·78 \ (q *w ƒ+q Ì , U-8 cx08 Õ2S 3d ‘4” _6© Ö7© 98¾( ?9Ô0 ¤:ð8 r;@ =/H h>EP »?dX P@/` Adh ÊBjp>wÎ.4wN d wY ‰ w   ‰ qj© wš)¾ w¯ Ô w TÄéé wÚé  ‰  Cö?/ w  E w ?5d  ‰ -KpÐw`a@œ"ua@*œÌƒ"w‘Xret$ ‘hŒ)Ÿa@Uœ>ƒ)w‘Xj*‘Tá+‘Pë,‰‘H–-q‘@0 ‘hZ<ôa@'œ|ƒ ‘hÑFb@'œºƒFw‘XH ‘h4P)Bb@(œøƒPw‘XR ‘h:Zjb@3œ@ƒZw‘XëZT‘T\ ‘h¶bb@*œzƒbw‘Xretd ‘hKi?Çb@JœÆƒiw‘X°k?‘dl ‘hŸyéc@Jœƒyw‘X{ ‘hm„é[c@ûœmi…‘hG†‰‘`€†‘\Þ †‘XZ›d@Ф?Vd@ZœÈƒ¤w‘X°¦?‘d§ ‘hZ¶©d@cº°d@:œƒºw‘X º?‘T¼ ‘hÂêd@-œ\crc‘lƒÉ‘`=Ã-‘XPÈ>  †@ :  _Še@³ šZØ8†intg‹iˆBƒi8„i’‹i p KÆ X 0Ö^ØñS %ò? Î÷š Ëøš |ùš ¶úš ›ûš( *üš0 ®ýš8 Ûþš@ àšH dšP pšX ‹` ]‘h î?p t ?t px -M€ [‚ ¬—ƒ §ˆ !{ î)˜˜ õ*˜  ü+˜¨ u,˜° .-¸ -/?À Å1­Ä ,–¡œ‹ è‹ Xž‘ 9¢?ZÖ  § †S  ½ †P &nûe@œûcn ‘le~À)e@ œü1û4e@þœ‰dir1À‘Hþ 3À‘h[5š‘Xret6û‘gendPøe@`À2f@AœÇ‚`À‘XextbÀ‘hOršsf@Oœ‚rš‘X¾tš‘hˆŠûÂf@%œ5‚ŠÀ‘h¦—ûçf@œe‚—À‘h³²ûöf@Bœ£‚²À‘X4´£‘hË‘Ò8g@:œ3âÒš‘Ø_ØÒÀ‘Ð_ÓÀ‘È_Þ Ó-‘À_ªÕ3‘à_tokÖš‘hÿT pŠ@  D†ÿ ÆT † Dèïrh@‡œÂâïš‘hØïÀ‘`ðÀ‘XÞ ð-‘PÿÒ €Š@ ÆÒ †Â!öšùh@'œströÀ‘X‚øÀ‘ht  i@ßœ¤‚ š‘HÞ  -‘@ü -‘h&À‘`ÿ¤  Š@li@Nœ©‘P  ¹ †E,ÿi@²œ6,š‘X9,À‘P-À‘HÞ --‘@…/À‘hÿF ÀŠ@ ÆF †6Ã?±j@{œÈout?š‘XØ?À‘PÞ ?-‘H¥AÀ‘`ptrBÀ‘hÿØ àŠ@ ÆØ †ÈMg,k@cœ<Wgš‘hØhÀ‘`Þ h-‘XÿL ‹@ ÆL †<xxk@cœ°Wxš‘hyÀ‘`Þ y-‘XÿÀ  ‹@ ÆÀ †°9Œòk@aœ Œš‘XextÀ‘PÞ -‘H­®‘h4žSl@uœ] ‚žš‘X¾ š‘h¶ºÈl@dœš ‚ºš‘Xlen¼-‘h AÊÀ,m@3œÛ ‚ÊÀ‘X¾ÌÀ‘h!Ääû_m@!œ ‚äÀ‘hÆù€m@žœo bufùš‘è_Þ ù-‘à_tmpü3‘ð_ÿo @‹@<Ön@Ýœâ âš‘hŸÀ‘`ØÀ‘XÞ -‘Pÿò `‹@ Æò †â Õ5ûn@¯œe â5š‘hdir6À‘`‚6À‘XÞ 6-‘Pÿe €‹@ÈcAªo@kœÉ âAš‘h9BÀ‘`Þ B-‘XÿÙ  ‹@ ÆÙ †É Up@»œk âUš‘XdirUÀ‘P‚VÀ‘H.VÆ‘DÞ V-‘¸õX-‘hÿk À‹@°ÜpÐp@úœñ 1pš‘Ø_ØqÀ‘Ð_Þ q-‘È_s3‘à_ztš‘hÿ à‹@ Æ †"ñ §L ‘ŠÊq@Ȥ†g‹iˆintÄ|-F}B%~B‚-£B'‚-Bƒ^’‹^U™^ž^é¯^pòå ™ÄWÝx.œz¹Œ{Úþ².üû0eN5†=œø>‘Š@p A{ iCW$„Ee(”J§0NÄ8pPÏ@a[ Hz\ XÓ] hÌjüx Ú  ²P BK= · 1 º ­R›Êq@¥œ›‚Rì‘Ø~.R‘Ô~Þ R5‘È~bufm;‘à~æ››or@$œÒ‚›ì‘h ›“r@$œ‚ ì‘h¬¥›·r@$œ2‚¥ì‘hÛªþÛr@8œp‚ªì‘X-¬þ‘lû›s@œdir»ì‘Xret½W‘l*i 6Š’s@‡›ZØ8†g‹iˆintBƒi8„i’M ¬i pX 0²^Øñ/%òbÎ÷šËøš|ùš¶úš ›ûš(*üš0®ýš8Ûþš@ àšH dšP pšX Âg` ]mh îbp t bt px -F€ T‚ ¬sƒ ƒˆ !{ î)˜ õ*  ü+¨ u,° .-¸ -/bÀ Å1‰Ä ,–¡œgègXžm9¢b6²  ƒ †/  ™ †Ÿ  O f ÃW $ÏW Eþ+GMfpQ+fdXbM'+× Ž « ´ { §Ì\b’s@Dœa\a‘hÄ1gaÖs@iœû‚g™‘H.gM‘Dleng¤‘¸&ib‘ljb‘\Ãl™‘`na‘PZì,u@³ñ¤?u@xœWña‘hñ¤‘` ñb‘\Z0®u@€4¤·u@eœ™4a‘hZRv@¡Vv@%œÇVa‘h[¤Av@tœ%[a‘hs[‘`len[-‘XZ}¬v@ú¤µv@nœƒa‘hs½‘`len-‘XZ˜w@Þœb#w@4œÂœa‘hcœb‘d©bWw@uœ©a‘hZÉÅw@U×bÌw@Èœ¡‚×™‘Hbufס‘@len×§‘¸retÙ¤‘`AÚ¤‘XîÛ‘heÜa‘PZJy@¤j”y@…œ‚™‘Xƒ½‘PÞ ¤‘Hret¤‘hea‘`ªmä ™Šz@8ŽZØ8†g‹iˆint’pŒ ò"Ç b$Ç i%b p&w 3)ó ƒ+y ,Ÿ F/$ ë1$ Þ 2- cap3-ÎP þ'z@mœpî 'p‘Xi)-‘hó<džz@ÖœÕî $‘hÿå °Œ@ŒåpÕîVp\{@Zœî Xp‘h-qǶ{@Μtî qp‘Xéq†‘PrŸ‘@$ty‘h ¶„|@zœÏî p‘XidxŽM‘Tstrކ‘Hÿß ÐŒ@ŒßpÏ xžþ|@Ïœg% žy‘XÞ ž-‘Pî Ÿg‘H.Ÿ†‘@i¡-‘hlen¡-‘`ÿ‚ àŒ@móŒ‚prƸpÍ}@œ"str¸†‘¸.¸†‘°Óºy‘P@»y‘htmp¼†‘`î ½p‘XZÕ®~@ÉŸ‘@ØäbÍ~@sœlî äg‘Xé䆑Piæ-‘hRÿÇ@@œÚî ÿg‘Ø_h†‘Ð_醑È_i-‘hÚ‘à_pÿ% : ; I$ > $ >   I : ;  : ; I8 : ;I8 : ; I !I/ &I< I: ; ( ( .: ; 'I@–B: ; I4: ; I4: ; I : ; .?: ; 'I@–B4: ; I?<% : ; I$ > $ >   I : ;  : ; I8 : ;I8 I !I/ : ; &I'II'I' : ;  I: ; (  : ; I8  : ; ( .: ; 'I@—B: ; I4: ; I.: ; 'I@–B: ; I4: ; I : ;   !.: ; '@—B".: ;'@—B#: ;I$: ;I%4: ;I&4: ;I'.: ;'@–B(.: ;'I@–B) : ;* : ;+.: ;'I@—B,.?: ;'I@–B- U..?: ;'@–B/.?: ;'I@—B04: ; I?<% : ; I$ > $ >   I : ;  : ; I8 : ;I8 : ; I !I/ &I'II< I: ; ( ('I'.: ; 'I@—B: ; I4: ; I.: ; '@—B.: ; 'I@–B: ; I4: ; I  : ;4: ;I .?: ;'I@–B!: ;I"4: ; I?<% $ > $ >  I&I: ; I.?: ; 'I@—B: ; I 4: ; I 4: ; I .?: ; 'I@–B% : ; I$ > $ >   I : ;  : ; I8 : ;I8 : ; I !I/ &I : ; I8 .?: ; 'I@–B: ; I4: ; I4: ; I : ; .?: ; '@–B : ; I.?: ; 'I@—B.?: ; '@—B% : ; I$ > $ >   I&I'I I  I: ;  (  : ;  : ; I8 'I' I: ;  : ;  : ; I : ; I8  : ; .: ; '@–B: ; I4: ; I.: ; 'I@—B.: ; 'I@–B4: ; I : ;  4: ;I4: ;II !I/!.: ;'I@—B": ;I#.: ;'I@–B$ U%: ;I& : ;'.?: ;'I@–B(.?: ;'@–B).?: ;'I@—B* : ;+.?: ;'I@—B,4: ; I?<% : ; I$ > $ >   I: ;I'I I '  : ;  : ; I8 : ; I8  : ; : ;I8 &I'I.: ; 'I@–B.: ; '@–B: ; I4: ; I.: ; '@—B4: ; I.: ; 'I@—B.: ; 'I@–B : ; : ; I4: ; I?% : ; I$ > $ >   I&I : ;  : ; I8 : ;I8 : ; I !I/ .: ;'I@—B: ;I.: ;'I@—B.?: ; 'I@–B: ; I4: ; I4: ; I : ; : ; I.?: ; 'I@—B.?: ; '@–B4I4!I/.?: ;'@–B: ;I4: ;I 4: ;I .?: ;'I@–B!.?: ;'I@—B% $ > $ > : ; I I&I : ;  : ; I8 I !I/  I: ;  ( .: ; 'I@–B: ; I4: ; I.?: ; 'I@–B4: ; I.?: ; 'I@–B: ; I% : ; I$ > $ >   I : ;  : ; I8 : ;I8 : ; I !I/ &I& : ; I8  I: ; ( (.?: ; 'I@–B: ; I: ; I4: ; I : ;  : ;.?: ;'I@–B: ;I.?: ;'@–B: ;I4: ;I4: ;I4: ; I?<% : ; I$ > $ >   I&I : ;  : ; I  : ;  : ; I8 : ; I8 .?: ; '@–B: ; I4: ; I.: ; 'I@–B: ; I4: ; I4I4I!I/ .?: ; 'I@–B : ;  U: ;I4: ;I4: ;II!I/‘èû /usr/lib/gcc/x86_64-unknown-linux-gnu/5.3.0/include/usr/include/bits/usr/include../../../include/formatsrpng_test.cstddef.htypes.hlibio.hstdint.hImlib2.hrpng.himage.hstdio.h F@$wKƒƒL¯¼ 0hvK[’vK[’K10K1 ô0K3ŸhfgPf3 u»u»ƒ­åK1½„ pƒuv( × »Öóu ¼ƒƒ *ÉwÊZ¼Y1å„håwg¼ÊôÉwYJ(û ../../../include../usr/lib/gcc/x86_64-unknown-linux-gnu/5.3.0/include/usr/include/bits/usr/include../../../include/file../../../include/formatsfilters.hrpng.cstddef.htypes.hlibio.hstdint.harchive_file.hrpng.hrpng_internal.hstdio.h ƒ@*É×KKL‚ƒYƒY=Õ.ƒE1 º’,ýJlY1¼Léòó'L’„K)J få'L’„K)J f­'Z'<< }J‚jÒJ‚iÓ J t Z € J‚h€<»#K2#’”ÉuÉuÉuv-J ‚@#’½ÉuÉuÉuÉuu/J º@%h’g#J‡[É=v’‘-gŸy#ž ‚3#’”ÉuÉvw%J ‚AZ>v’‘-gz(žŠA”ç­»Z"#Z­»ZÉ×0×å0uu#uƒu‘u‘B¡"“„‘J~)Š?»Éó»É󼃭<.ô"ÕL gs/@vós/&xÿ…É gר3,ó¡„¡» 0+ »»óôÈË­„w»Yxwi$Z‘ñJ¼»AJ¼Z‘4J¼Z’Y'J¿¼<'J¿Z‘KJ¼ååÇ=ÿ/ÿIJõ1¡ç%Z%1ñæ1¼0%#$Yx=v"»=¾ž¡­®» w¼Éå»=3=u/®­ ZgŸg ­¢’hfg Ÿ +Ÿ[ô­­»„Y3=“Ú0gvÉóÉ»wt É»=1óuvåæÉ2v×J#tWw¯"#ržC ØóøŸ¡õ»»0åÙƒ`t# ròD ƒY2缟ÉÉ- JÂY1ó)uv­Y2u»¼<å>Êó & ŸÉvj«>ª³vY1ôv‘;Ji>‘ÕJiY2óZ=ƒååååæž­vY1¼óæ‘  ò ò..1½%½­\X..1"ËZ(®[X.ä[%Z‘.J…Ê­1 #­¿.Ä ô½tC?? h/l<<%ot Y1KYfÎû ../../../file/usr/lib/gcc/x86_64-unknown-linux-gnu/5.3.0/include/usr/include../../../include/filearchive_file_zlib.cstddef.hzconf.hzlib.hstdint.harchive_file.h `a@Kå1»ƒu»DY„wŸ ­zÖ'1ƒ„uvu1ƒ„uvu1ƒ„uvƒ1­„uY?»ƒu»?¼„uv>gvY1»„uu‘uY3Yu ¡"ZË$st?A(ååÉôY1¼„w>gvfivtD%Y1å„uƒ@/uàû ../../../include/file../../..//file/usr/lib/gcc/x86_64-unknown-linux-gnu/5.3.0/include/usr/include/bits/usr/includefile_path.hfile_path.cstddef.htypes.htime.hstdio.hlibio.h e@î”v .NZ­}.»„óLu »¬iôƒƒæhƒét­Y»K .»»uuƒ .»»uu­uK.»g .‚Y .»Luv»Y.'g„&„'v)ƒ)ƒ<uºƒºƒ?»RK .óóõtMuº„uòz‚'<u„/󺃺ƒ <=ƒöuv‚ºƒ<=Ÿºƒ» <=Ÿºƒ»<>½ãvg <»ƒ  ôuÊr(  .»ótå!» <» òuŸK .ƒ­{Y .†ÎȈÉç<uôò†ºƒ»º}&.uŸº„­0ºƒ@=­0ºƒ<»ŸÖ„"ºƒ<åg„+u t ƒö-åóŒû ../../..//file/usr/include/bits/usr/include/sys/usr/includeretro_stat.ctypes.htypes.htime.hstat.h Êq@ÒÖ»{Ÿç f&#wY .»Y1»Y1»Y1»uƒZY . º <fºóvg'uïßû ../../../streams/usr/lib/gcc/x86_64-unknown-linux-gnu/5.3.0/include/usr/include/bits/usr/include../../../include/streamsfile_stream.cstddef.htypes.hstdio.hlibio.hfile_stream.h ’s@Ü»uvå"u1/uv„0u£— få…v .å ‚z.vx .å ‚z.z æÉÉ3׺df »Y12 tå&È¿It3<'u1¾ tå(¾jt<&u1»Y?=t tåÖ¢u1= tåÜož u1åuwO1» tæÉ  ­Ø¼et Y .=ƒƒƒ®v.[Ùó¯¼>¯Ÿv.1¼°Øu®at@C u»u»u­­Y .=ƒ­uvŸ¼ŸvY»›û ../../../lists../../../include/lists/usr/lib/gcc/x86_64-unknown-linux-gnu/5.3.0/includestring_list.cstring_list.hstddef.h z@'¼wŸ¹XØåÑ& .óƒÖ…çuv×<­»Y .ƒ1uvv»wK.=„KÇLvóuv»Ê=Y .=­)ƒ‚uôžƒƒ„ (KbXÜ <󃃃’¯ó¯Ÿ1ZËx‚ t»mf@ < »»Y .õuv (XÜY.æhŸ ÉÊ .*LpXY_old_offset_vtable_offsetGNU C99 5.3.0 -mtune=generic -march=x86-64 -g -O0 -std=gnu99IMAGE_PROCESS_ERROR_END_IO_save_endimlib_datashort intsizetype_IO_write_ptrmain_IO_buf_baseretval_markers_IO_read_endin_pathIMAGE_PROCESS_ERRORuint8_ttest_rpngstderrlong long int_lockImlib_Image_cur_column_posargvrpng_load_image_argb_sbuf_IO_FILEunsigned char__pad4argclong long unsigned intuint32_t_IO_marker_shortbuf_IO_write_base_unused2_IO_read_ptr_IO_buf_endnbio_t__pad1__pad2__pad3_Bool__pad5rpng_tshort unsigned int_IO_write_end__off64_t__off_tIMAGE_PROCESS_NEXT_chain_IO_backup_base_flags2_IO_read_base/home/squarepusher/libretro-super/retroarch/libretro-common/formats/png/testfile_len_IO_save_base_filenoIMAGE_PROCESS_ENDtest_dataimage_process_code_flags_IO_lock_trpng_test.cbuff_datapng_reverse_filter_adam7_deinterlace_passnew_bufferPNG_FILTER_UPinputrpng_load_image_argb_process_initprev_scanlinepalettefile_archive_file_handle_tidat_bufPNG_CHUNK_PLTEcorrect_bppmaskPNG_PROCESS_ENDpitchmul_tableadam7_pass_initializeddecoded_scanlineerrorpng_reverse_filter_iteraterpng_nbio_load_image_argb_iteratepass_sizevalid_bpppng_read_pltepng_reverse_filter_regular_iteratepng_pass_geompassesPNG_CHUNK_NOOPfloatrpng_nbio_load_image_argb_processpng_reverse_filter_adam7_iteratepitch_outchunk_mapfile_archive_file_backendpass_heightpng_chunkto_continuepng_line_filterdecodedPNG_FILTER_NONEhas_ihdrfalse_endPNG_FILTER_AVERAGEPNG_IHDR_COLOR_GRAY_ALPHAdwordinflate_initializedrpng_process_tadam7_restore_buf_sizerpng_nbio_load_image_freepng_reverse_filter_copy_line_pltPNG_CHUNK_IHDRPNG_PROCESS_ERROR_ENDpng_ihdrzstatusstride_xstride_yidentdword_bepng_reverse_filter_copy_line_rgbaPNG_IHDR_COLOR_PLTPNG_PROCESS_NEXTdepthinterlacepng_process_ihdrpass_widthpng_realloc_idatfile_archive_handledata_png_ihdr_color_typepng_chunk_typehas_idatbpp_out../rpng.cPNG_IHDR_COLOR_GRAYPNG_FILTER_SUBPNG_IHDR_COLOR_RGBAdata_restore_buf_sizepng_reverse_filter_deinitPNG_CHUNK_IDATrpng_set_buf_ptrpng_reverse_filter_copy_line_gray_alpharpng_nbio_load_image_argb_startPNG_PROCESS_ERRORpngppng_reverse_filter_initgrayuint64_tinflate_bufentriesread_chunk_headerto_nexthas_iendpng_parse_ihdrbytestream_crc_calculateidat_bufferpng_process_codepng_reverse_filter_adam7rpng_load_image_argb_process_inflate_initpng_magicPNG_CHUNK_ERRORpng_reverse_filter_copy_line_rgbinflate_buf_sizereal_checksumPNG_CHUNK_IENDcompressionPNG_FILTER_PAETHPNG_IHDR_COLOR_RGBpng_reverse_filter_copy_linestream_backendadam7_passdoublerpng_is_validpng_reverse_filter_copy_line_bwrpng_allochas_pltefilter_avgchosen_filteredRFILE_HINT_UNBUFFEREDfilter_paethpng_write_iendprevup_filteredencode_targetavg_filteredcopy_bgr24_lineavg_score../rpng_encode.cpaeth_filteredpng_write_crcsub_scoreencode_bufencode_buf_sizecopy_argb_lineRFILE_MODE_WRITEdeflate_bufRFILE_MODE_READ_WRITEsub_filteredup_scoreRFILE_MODE_READnone_scorepaeth_scorerpng_save_image_bgr24png_write_ihdrrpng_save_imagecrc_rawrgba_linemin_sad__ssize_tRFILErpng_save_image_argbihdr_rawRFILE_HINT_MMAPprev_encodedpng_write_idatfilter_subdword_write_befilter_upcount_saddestsrc_sizestrlcat_retro__source../../../compat/compat_strl.cstrlcpy_retro__nbio_get_ptrmodesnbio_opennbio_iteratenbio_resizenbio_cancelwritten../../../file/nbio/nbio_stdio.camountnbio_begin_readnbio_freenbio_begin_writecmodecommentlengthfile_archive_get_file_listzip_sizefound_contentZLIB_TRANSFER_DEINIT_ERRORfile_archive_parse_file_iterate_stepfile_extfile_archive_file_data_tpaybackfile_archive_file_cboffsetELfile_archive_extract_cbfile_archive_parse_file_progressZLIB_TRANSFER_NONEfile_archive_transfer_typenamelengthreturnerrsignaturefile_archive_parse_file_iterate_stoplast_charcdatapayloadfile_archive_parse_filefirst_extracted_file_pathRARCH_FILE_UNSUPPORTEDfooterfile_archive_decompress_data_to_filefile_archive_transfer_toffsetNLelemsptrdiff_tfile_archive_parse_file_iteratenew_pathfile_archive_freeRARCH_DIRECTORYstring_listfile_archive_parse_file_iterate_step_internalcsizefile_archive_dataZLIB_TRANSFER_ITERATEextraction_directoryzip_path_sizeZLIB_TRANSFER_INIT../../../file/archive_file.cRARCH_PLAIN_FILEZLIB_MODE_UNCOMPRESSEDread_from_fileextralengthcomment_lenzlib_backendRARCH_COMPRESSED_FILE_IN_ARCHIVEfile_archive_compression_modefile_archive_parse_file_initfile_archive_get_file_list_cbzip_pathfile_archive_sizestring_list_elem_attrZLIB_TRANSFER_DEINITvalid_extsext_listfile_archive_transferZLIB_MODE_DEFLATEcrc32file_archive_openzip_extract_userdatadeltaread_lefile_archive_extract_first_content_filefile_archive_get_default_file_backendout_pathRARCH_COMPRESSED_ARCHIVERARCH_FILETYPE_UNSETfile_archive_perform_modestring_list_elemopaquezlib_stream_compress_data_to_filezlib_stream_decompress_data_to_file_initnext_outzlib_stream_decompress_initBytealloc_funcuLongzlib_stream_get_avail_outsubtraction../../../file/archive_file_zlib.czlib_stream_freefree_funcdummyzlib_stream_decrement_total_outzlib_stream_get_avail_inBytefdata_typezalloczlib_stream_decompress_data_to_file_iteratezlib_stream_compress_freezlib_stream_newz_stream_snext_invoidpfz_streampz_streamlevelzlib_stream_crc32_calculateuIntzlib_stream_get_total_outadlerinternal_statezlib_stream_compress_initzfreetotal_inzlib_stream_setjoin_strptr_bakcur_timepath_parent_dirpath_resolve_realpathfill_short_pathname_representation__PRETTY_FUNCTION__path_get_extensionpath_char_is_slashfill_dated_filenamefill_pathname_basedirfill_string_joinfill_pathname_slashpath_contains_compressed_filepath_is_compressed_filelastfill_pathname_basefill_pathname_resolve_relativecopiedpath_mkdirin_dirout_filenamefill_pathname_join_delimpath_basedirpath_basenamepath_remove_extensionpath_default_slashfill_pathname_parent_dirfill_pathnamein_refpathtmp_pathpath_file_existspath_is_absolutefill_pathname_joinfill_pathname_noextpath_len__time_treplacepath_shortfind_last_slashout_repin_basenamefill_pathname_dirout_dir../../..//file/file_path.clast_hashst_rdevtv_nsecst_sizetv_sec__mode_tpath_is_validIS_VALIDmkdir_norecursest_ctimpath_get_size__syscall_slong_tst_devst_nlinkstat_modest_blksizest_gid__nlink_tIS_CHARACTER_SPECIAL__uid_tst_ino__blksize_tst_atim__pad0st_blocksst_mtim__ino_tst_uid../../..//file/retro_stat.cpath_statIS_DIRECTORY__dev_t__glibc_reservedtimespecpath_is_directoryst_modepath_is_character_special__blkcnt_t__gid_tfilesize../../../streams/file_stream.cfilestream_read_filefilestream_write_filefilestream_tellfilestream_closefilestream_rewindfilestream_seekmode_strfilestream_get_fdfilestream_putccontent_buffilestream_writewhencemode_intfilestream_readhintsfilestream_opencontent_buf_sizestring_list_find_elem_prefixnew_datastring_list_join_concatprefixed../../../lists/string_list.cstring_list_setstring_splitsavestring_list_find_elemstring_list_newstring_list_freestring_list_capacitydata_dupstring_list_appendcopyd+|…ó;TUq (u”•@@<@`@ @Ð@„ @ @ H @ x @  @ À@ @@P@ð€@@øŒ@À‘@¥` ¥`(¥`0¥` §`(§`©``©` !ñÿñÿ(¥` €@"À@5@Kh©`Z ¥` @¥`¬ñÿ¸F@‘Í×@ü×ñÿ"ƒ@ÞÀ@è@OñS@càƒ@@¶@d  „@/@„@>@œ_¶@¹o@¡`„@$°‰ @€Ø !@³ù¼!@ÒŽ#@Â1P$@tKÀ‚@pRÄ$@rj6(@X‡Ž,@rª.@ÍËÍ/@ëä¸0@mÿ%1@Ù)þ2@¶7 4@ˆY•5@‹k 6@°zñÿ"Õ<@Þˆ„@ˆV=@[—±=@s¥$>@´C?@rõ?@‚Ò7@@‹áÂ@@bñ$A@JûnA@xæA@¥‹B@Ò]C@(oD@ß8ñÿFñÿS ©`0Yñÿh6S@;zqS@'Œ˜S@(žÀS@”°TT@ÎbU@iæËV@NîW@öY@AZ@¨^Æ[@؃ ^@j›ñÿ¯`a@¿ua@*Пa@Uàôa@'ùb@'Bb@(-jb@3Mb@*gÇb@J‰c@J¥[c@ûÎVd@Zú°d@:êd@-0ñÿ<e@O)e@ bpŠ@{€Š@” Š@­ÀŠ@ÆàŠ@ß‹@ø ‹@@‹@*`‹@C€‹@\ ‹@uÀ‹@Žà‹@#§ñÿ´Êq@¥¾ñÿÌñÿÚ†z@Öï°Œ@ ÐŒ@! àŒ@ñÿ: ¥@H (¥`ñÿT øŒ@g (§`}  ¥`Ž ¥`¡ 0¥`ª Âf@%È ê ©`Þ ¶{@Îñ ;O@` Ua@ ' ’s@D9 J L^ rh@‡r n@Ý‘ ¥ ¸ Ѐ@È î P@*aÞ é #w@4ù  :@É. Av@t> „|@zN ·r@$\ k  ‘ ¤ ¦Q@¢° Ë s@Û  ð€@ó û &  / N ,m@3\  i@ßp Ù:@ªŠ ƒ;@”ª à€@± òk@aÅ Ös@iÕ ]M@kå ê_@g @@¬ "à€@ <@_+ 9 U ùh@'e @t |  k@c¨ º Î è ©`õ ÁR@uÿ 2f@A-8LawÍ^@ŸWw@u°þ|@ÏÈor@$Ú,k@cð¦<@/ûP©`”y@…3©`@Èl@dPt^@Yq„`€@e”ŒL@>ªz@m»HR@MÈ_m@!ÙÐp@úüNL@>%8ISl@uVtˆP©`”4e@þŸž\@¿“r@$Ùÿçf@+8g@:9›O@`J\{@ZZsf@Op€m@ž†p@»ŸÐ6@@ÁûO@«ÎÌw@Èãð´]@V´3@Y&:Nv@%‰ p©``tÊL@“„œ †@x©`©`½ªo@kÎûn@¯á?u@xñÍ}@þ±j@{%:ÈM@sDP©`K`wv<@0ˆµv@n™öf@BªÀÛr@8ÎQ`@èû•R@, ÿi@²®,Ó@°X  @1·u@eAÍ~@sinit.ccrtstuff.c__JCR_LIST__deregister_tm_clones__do_global_dtors_auxcompleted.6945__do_global_dtors_aux_fini_array_entryframe_dummy__frame_dummy_init_array_entryrpng_test.crpng_load_image_argbtest_rpngrpng.cpng_magicdword_bepng_chunk_typechunk_map.4413png_process_ihdrvalid_bpp.4428valid_bpp.4434png_reverse_filter_copy_line_rgbpng_reverse_filter_copy_line_rgbapng_reverse_filter_copy_line_bwmul_table.4475png_reverse_filter_copy_line_gray_alphapng_reverse_filter_copy_line_pltpng_pass_geompng_reverse_filter_adam7_deinterlace_passpng_reverse_filter_deinitpassespng_reverse_filter_initpng_reverse_filter_copy_linepng_reverse_filter_regular_iteratepng_reverse_filter_adam7_iteratepng_reverse_filter_adam7png_reverse_filter_iteraterpng_load_image_argb_process_inflate_initpng_read_plterpng_load_image_argb_process_initread_chunk_headerpng_parse_ihdrrpng_encode.cdword_write_bepng_write_crcpng_write_ihdrpng_write_idatpng_write_iendcopy_argb_linecopy_bgr24_linecount_sadfilter_upfilter_subfilter_avgfilter_paethrpng_save_imagecompat_strl.cnbio_stdio.cmodesarchive_file.cfile_archive_freefile_archive_datafile_archive_sizefile_archive_openfile_archive_get_file_list_cbfile_archive_extract_cbread_lefile_archive_parse_file_iterate_step_internalfile_archive_parse_file_iterate_stepfile_archive_parse_file_initfile_archive_decompress_data_to_filefile_archive_parse_filearchive_file_zlib.czlib_stream_newzlib_stream_freezlib_stream_setzlib_stream_get_avail_inzlib_stream_get_avail_outzlib_stream_get_total_outzlib_stream_decrement_total_outzlib_stream_compress_freezlib_stream_compress_data_to_filezlib_stream_decompress_initzlib_stream_decompress_data_to_file_initzlib_stream_decompress_data_to_file_iteratezlib_stream_compress_initzlib_stream_crc32_calculatefile_path.cpath_char_is_slashpath_default_slash__PRETTY_FUNCTION__.4426__PRETTY_FUNCTION__.4433__PRETTY_FUNCTION__.4445__PRETTY_FUNCTION__.4453__PRETTY_FUNCTION__.4461__PRETTY_FUNCTION__.4467__PRETTY_FUNCTION__.4473__PRETTY_FUNCTION__.4500__PRETTY_FUNCTION__.4507__PRETTY_FUNCTION__.4514__PRETTY_FUNCTION__.4520__PRETTY_FUNCTION__.4529__PRETTY_FUNCTION__.4537retro_stat.cpath_statfile_stream.cstring_list.cstring_list_capacity__PRETTY_FUNCTION__.4218__PRETTY_FUNCTION__.4234__PRETTY_FUNCTION__.4243__FRAME_END____JCR_END____GNU_EH_FRAME_HDR_GLOBAL_OFFSET_TABLE___init_array_end__init_array_start_DYNAMICpath_contains_compressed_fileimlib_image_get_widthstring_list_appendnbio_begin_readfile_archive_get_default_file_backendfilestream_get_fdimlib_free_imagefileno@@GLIBC_2.2.5fill_pathname_noextfill_pathname_resolve_relativememset@@GLIBC_2.2.5ftell@@GLIBC_2.2.5__libc_csu_finisnprintf@@GLIBC_2.2.5inflateEndfilestream_putcabort@@GLIBC_2.2.5rpng_nbio_load_image_argb_processfilestream_readstring_list_setpath_is_valid__gmon_start___Jv_RegisterClassesputs@@GLIBC_2.2.5fseek@@GLIBC_2.2.5nbio_resize__assert_fail@@GLIBC_2.2.5mkdir_norecursestrcasecmp@@GLIBC_2.2.5deflatedeflateInit_malloc@@GLIBC_2.2.5fopen@@GLIBC_2.2.5__libc_start_main@@GLIBC_2.2.5path_basenamefill_pathname_slashrpng_nbio_load_image_freerpng_nbio_load_image_argb_start__statfill_dated_filenamefilestream_openstrlcat_retro__file_archive_get_file_liststring_list_find_elem_prefixrpng_is_validinflateInit2__ITM_deregisterTMCloneTablefind_last_slash_IO_stdin_usedinflatefputc@@GLIBC_2.2.5fill_pathname_parent_dirfree@@GLIBC_2.2.5strlen@@GLIBC_2.2.5_ITM_registerTMCloneTable__data_startnbio_freepath_get_extensioncrc32__xstat@@GLIBC_2.2.5deflateEndrealpath@@GLIBC_2.3strrchr@@GLIBC_2.2.5strtok_r@@GLIBC_2.2.5file_archive_extract_first_content_filefilestream_closestring_list_join_concatpath_is_directoryfill_pathname_basedirrpng_alloc__TMC_END__strerror@@GLIBC_2.2.5filestream_write_file__dso_handlepath_parent_dirfile_archive_parse_file_progresslseek@@GLIBC_2.2.5__libc_csu_initrpng_save_image_bgr24string_list_freenbio_get_ptrpath_is_absolutefill_short_pathname_representationstrchr@@GLIBC_2.2.5rpng_save_image_argbfread@@GLIBC_2.2.5imlib_load_imagepath_basedir__errno_location@@GLIBC_2.2.5strdup@@GLIBC_2.2.5__bss_startpath_mkdirfile_archive_parse_file_iteratepath_is_character_specialimlib_image_get_data_for_reading_onlypath_is_compressed_filestrcmp@@GLIBC_2.2.5fill_pathnamenbio_begin_writestring_list_newpath_remove_extensionpath_resolve_realpathfill_pathname_join_delimrpng_nbio_load_image_argb_iteratenbio_iteratefilestream_read_fileinflateInit_file_archive_parse_file_iterate_stoppng_realloc_idatmemcmp@@GLIBC_2.2.5calloc@@GLIBC_2.2.5filestream_rewindfclose@@GLIBC_2.2.5strlcpy_retro__imlib_context_set_imagezlib_backendstderr@@GLIBC_2.2.5fill_string_joinfill_pathname_joinfilestream_seekstring_splitfill_pathname_basefwrite@@GLIBC_2.2.5realloc@@GLIBC_2.2.5nbio_open_edatafprintf@@GLIBC_2.2.5localtime@@GLIBC_2.2.5rpng_set_buf_ptrfilestream_writepath_file_existsstrftime@@GLIBC_2.2.5path_get_sizefile_archive_perform_modememcpy@@GLIBC_2.14nbio_cancelfill_pathname_dirmkdir@@GLIBC_2.2.5mainfilestream_tellstring_list_find_elem.symtab.strtab.shstrtab.interp.note.ABI-tag.note.gnu.build-id.gnu.hash.dynsym.dynstr.gnu.version.gnu.version_r.rela.dyn.rela.plt.init.plt.got.text.fini.rodata.eh_frame_hdr.eh_frame.init_array.fini_array.jcr.dynamic.got.plt.data.bss.comment.debug_aranges.debug_info.debug_abbrev.debug_line.debug_str.debug_ranges@#@ 1<@<$Döÿÿo`@`<N  @ 0VÐ@д^ÿÿÿo„ @„ „kþÿÿo @ @zH @H 0„Bx @x (Ž @ ‰À@À€”@@@P@P k£ð€@ð€ ©@ø ±øŒ@øŒÄ¿À‘@À‘TÉ¥`¥Õ ¥` ¥á(¥`(¥æ0¥`0¥ð˜ §` §ï(§`(§Ðø©`©P þ`©`P© 0P© a©q«\f'ͯ5|$MA0É?EL\À7ŽZÐ\$ àyWdesmume/src/addons/slot1comp_protocol.cpp000664 001750 001750 00000014205 12755534123 021757 0ustar00sergiosergio000000 000000 /* Copyright (C) 2012-2015 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the this software. If not, see . */ #include "slot1comp_protocol.h" #include #include "../armcpu.h" #include "../encrypt.h" #include "../emufile.h" #include "../utils/decrypt/decrypt.h" static _KEY1 key1((const u8*)arm7_key); void Slot1Comp_Protocol::reset(ISlot1Comp_Protocol_Client* client) { this->client = client; //we have to initialize this to something.. lets use dummy. //(need to clean this up...) memcpy(&command,"\x9F\0\0\0\0\0\0\0",8); operation = eSlot1Operation_9F_Dummy; length = 0; delay = 0; mode = eCardMode_RAW; } void Slot1Comp_Protocol::write_command_RAW(GC_Command command) { int cmd = command.bytes[0]; if(cmd == 0x9F) { operation = eSlot1Operation_9F_Dummy; length = 0x2000; } if(cmd == 0x90) { operation = eSlot1Operation_90_ChipID; length = 4; //we handle this operation ourselves } if(cmd == 0x3C) { //switch to KEY1 length = 0; mode = eCardMode_KEY1; //defer initialization of KEY1 until we know we need it, just to save some CPU time. //TODO - some information about these parameters //level == 2 //modulo == 8 key1.init(gameCode, 2, 0x08); GCLOG("[GC] KEY1 ACTIVATED\n"); } if(cmd == 0x00) { operation = eSlot1Operation_00_ReadHeader_Unencrypted; client->slot1client_startOperation(operation); } } void Slot1Comp_Protocol::write_command_KEY1(GC_Command command) { //decrypt the KEY1-format command u32 temp[2]; command.toCryptoBuffer(temp); key1.decrypt(temp); command.fromCryptoBuffer(temp); GCLOG("[GC] (key1-decrypted):"); command.print(); //and process it: int cmd = command.bytes[0]; switch(cmd&0xF0) { case 0x10: operation = eSlot1Operation_1x_ChipID; delay = 0x910, length = 4; //we handle this operation ourselves break; case 0x20: operation = eSlot1Operation_2x_SecureAreaLoad; delay = 0x910, length = 0x11A8; //TODO - more endian-safe way of doing this (theres examples in R4) { #ifdef MSB_FIRST u64 cmd64 = *(u64*)command.bytes; #else u64 cmd64 = bswap64(*(u64*)command.bytes); #endif //todo - parse into blocknumber u32 blocknumber = (cmd64>>44)&0xFFFF; if(blocknumber<4||blocknumber>7) printf("SLOT1 WARNING: INVALID BLOCKNUMBER FOR \"Get Secure Area Block\": 0x%04X\n",blocknumber); address = blocknumber*0x1000; } client->slot1client_startOperation(operation); break; case 0x40: //switch to KEY2 delay = 0x910, length = 0; //well.. not really... yet. GCLOG("[GC] KEY2 ACTIVATED\n"); break; case 0x60: //KEY2 disable? any info? break; case 0xA0: delay = 0x910, length = 0; mode = eCardMode_NORMAL; GCLOG("[GC] NORMAL MODE ACTIVATED\n"); break; } } void Slot1Comp_Protocol::write_command_NORMAL(GC_Command command) { switch(command.bytes[0]) { case 0xB7: { operation = eSlot1Operation_B7_Read; //TODO - more endian-safe way of doing this (theres examples in R4) #ifdef MSB_FIRST u64 cmd64 = *(u64*)command.bytes; #else u64 cmd64 = bswap64(*(u64*)command.bytes); #endif address = (u32)((cmd64 >> 24)); length = 0x200; client->slot1client_startOperation(operation); } break; case 0xB8: operation = eSlot1Operation_B8_ChipID; delay = 0, length = 4; //we handle this operation ourselves break; default: operation = eSlot1Operation_Unknown; client->slot1client_startOperation(operation); break; } } void Slot1Comp_Protocol::write_command(GC_Command command) { this->command = command; //unrecognized commands will do something depending on the current state of the card delay = 0; length = 0; address = 0; switch(mode) { case eCardMode_RAW: write_command_RAW(command); break; case eCardMode_KEY1: write_command_KEY1(command); break; case eCardMode_NORMAL: write_command_NORMAL(command); break; default: break; } } void Slot1Comp_Protocol::write_GCDATAIN(u8 PROCNUM, u32 val) { switch(operation) { case eSlot1Operation_Unknown: client->slot1client_write_GCDATAIN(operation,val); break; default: break; } } u32 Slot1Comp_Protocol::read_GCDATAIN(u8 PROCNUM) { switch(operation) { default: return client->slot1client_read_GCDATAIN(operation); case eSlot1Operation_9F_Dummy: return 0xFFFFFFFF; case eSlot1Operation_1x_ChipID: return chipId; case eSlot1Operation_90_ChipID: case eSlot1Operation_B8_ChipID: //Most games continuously compare the current chipId with the value in //stored in memory at boot-up, probably to know if the card was removed. //staff of kings verifies this (it also uses the arm7 IRQ 20 to detect card ejects) return chipId; } return 0xFFFFFFFF; } void Slot1Comp_Protocol::savestate(EMUFILE* os) { s32 version = 0; os->write32le(version); os->write32le((s32)mode); os->write32le((s32)operation); os->fwrite(command.bytes,8); os->write32le(address); os->write32le(length); os->write32le(delay); os->write32le(chipId); os->write32le(gameCode); } void Slot1Comp_Protocol::loadstate(EMUFILE* is) { s32 version = is->read32le(); mode = (eCardMode)is->read32le(); operation = (eSlot1Operation)is->read32le(); is->fread(command.bytes,8); address = is->read32le(); length = is->read32le(); delay = is->read32le(); chipId = is->read32le(); gameCode = is->read32le(); } desmume/src/movie.h000664 001750 001750 00000001471 12755534123 015432 0ustar00sergiosergio000000 000000 /* Copyright 2008-2015 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the this software. If not, see . */ #ifndef __MOVIE_H_ #define __MOVIE_H_ #include #include #include #include "utils/datetime.h" extern int currFrameCounter; #endif desmume/src/OGLRender_3_2.h000664 001750 001750 00000006256 12755534123 016545 0ustar00sergiosergio000000 000000 /* Copyright (C) 2006 yopyop Copyright (C) 2006-2007 shash Copyright (C) 2008-2016 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the this software. If not, see . */ #ifndef OGLRENDER_3_2_H #define OGLRENDER_3_2_H // Check minimum OpenGL header version #if !defined(GL_VERSION_3_2) #error OpenGL requires v3.2 headers or later. #endif #include "OGLRender.h" void OGLLoadEntryPoints_3_2(); void OGLCreateRenderer_3_2(OpenGLRenderer **rendererPtr); class OpenGLRenderer_3_2 : public OpenGLRenderer_2_1 { protected: virtual Render3DError InitExtensions(); virtual Render3DError InitEdgeMarkProgramBindings(); virtual Render3DError InitEdgeMarkProgramShaderLocations(); virtual Render3DError InitFogProgramBindings(); virtual Render3DError InitFogProgramShaderLocations(); virtual Render3DError InitFramebufferOutputProgramBindings(); virtual Render3DError InitFramebufferOutputShaderLocations(); virtual Render3DError CreateFBOs(); virtual void DestroyFBOs(); virtual Render3DError CreateMultisampledFBO(); virtual void DestroyMultisampledFBO(); virtual Render3DError CreateVAOs(); virtual void DestroyVAOs(); virtual Render3DError LoadGeometryShaders(std::string &outVertexShaderProgram, std::string &outFragmentShaderProgram); virtual Render3DError InitGeometryProgramBindings(); virtual Render3DError InitGeometryProgramShaderLocations(); virtual void DestroyGeometryProgram(); virtual void GetExtensionSet(std::set *oglExtensionSet); virtual Render3DError EnableVertexAttributes(); virtual Render3DError DisableVertexAttributes(); virtual Render3DError DownsampleFBO(); virtual Render3DError ReadBackPixels(); virtual Render3DError BeginRender(const GFX3D &engine); virtual Render3DError RenderEdgeMarking(const u16 *colorTable, const bool useAntialias); virtual Render3DError RenderFog(const u8 *densityTable, const u32 color, const u32 offset, const u8 shift, const bool alphaOnly); virtual Render3DError CreateToonTable(); virtual Render3DError DestroyToonTable(); virtual Render3DError UpdateToonTable(const u16 *toonTableBuffer); virtual Render3DError ClearUsingImage(const u16 *__restrict colorBuffer, const u32 *__restrict depthBuffer, const u8 *__restrict fogBuffer, const u8 *__restrict polyIDBuffer); virtual Render3DError ClearUsingValues(const FragmentColor &clearColor, const FragmentAttributes &clearAttributes) const; virtual void SetPolygonIndex(const size_t index); virtual Render3DError SetupPolygon(const POLY &thePoly); virtual Render3DError SetupTexture(const POLY &thePoly, bool enableTexturing); virtual Render3DError SetFramebufferSize(size_t w, size_t h); public: ~OpenGLRenderer_3_2(); }; #endif desmume/src/utils/AsmJit/x86/x86compilerfunc.cpp000664 001750 001750 00000250076 12755534123 022665 0ustar00sergiosergio000000 000000 // [AsmJit] // Complete JIT Assembler for C++ Language. // // [License] // Zlib - See COPYING file in this package. #define ASMJIT_EXPORTS // [Dependencies - AsmJit] #include "../core/intutil.h" #include "../core/stringutil.h" #include "../x86/x86compiler.h" #include "../x86/x86compilercontext.h" #include "../x86/x86compilerfunc.h" #include "../x86/x86compileritem.h" #include "../x86/x86cpuinfo.h" #include "../x86/x86util.h" // [Api-Begin] #include "../core/apibegin.h" namespace AsmJit { // ============================================================================ // [AsmJit::X86Assembler - Logging] // ============================================================================ // Defined in AsmJit/X86/X86Assembler.cpp. char* X86Assembler_dumpRegister(char* buf, uint32_t type, uint32_t index); char* X86Assembler_dumpOperand(char* buf, const Operand* op, uint32_t memRegType, uint32_t loggerFlags); // ============================================================================ // [AsmJit::X86CompilerFuncDecl - Construction / Destructioin] // ============================================================================ X86CompilerFuncDecl::X86CompilerFuncDecl(X86Compiler* x86Compiler) : CompilerFuncDecl(x86Compiler), _gpModifiedAndPreserved(0), _mmModifiedAndPreserved(0), _xmmModifiedAndPreserved(0), _movDqInstCode(kInstNone), _pePushPopStackSize(0), _peMovStackSize(0), _peAdjustStackSize(0), _memStackSize(0), _memStackSize16(0) { _decl = &_x86Decl; // Just clear to safe defaults. _funcHints |= IntUtil::maskFromIndex(kX86FuncHintPushPop); // Stack is always aligned to 16-bytes when using 64-bit OS. if (CompilerUtil::isStack16ByteAligned()) _funcHints |= IntUtil::maskFromIndex(kX86FuncHintAssume16ByteAlignment); _entryLabel = x86Compiler->newLabel(); _exitLabel = x86Compiler->newLabel(); _entryTarget = x86Compiler->_getTarget(_entryLabel.getId()); _exitTarget = x86Compiler->_getTarget(_exitLabel.getId()); _end = Compiler_newItem(x86Compiler, this); } X86CompilerFuncDecl::~X86CompilerFuncDecl() { } // ============================================================================ // [AsmJit::X86CompilerFuncDecl - Interface] // ============================================================================ void X86CompilerFuncDecl::prepare(CompilerContext& cc) { X86CompilerContext& x86Context = static_cast(cc); _offset = x86Context._currentOffset++; _prepareVariables(this); } CompilerItem* X86CompilerFuncDecl::translate(CompilerContext& cc) { X86CompilerContext& x86Context = static_cast(cc); _allocVariables(x86Context); return translated(); } // ============================================================================ // [AsmJit::X86CompilerFuncDecl - Misc] // ============================================================================ int X86CompilerFuncDecl::getMaxSize() const { // NOP. return 0; } // ============================================================================ // [AsmJit::X86CompilerFuncDecl - Prototype] // ============================================================================ void X86CompilerFuncDecl::setPrototype(uint32_t convention, uint32_t returnType, const uint32_t* arguments, uint32_t argumentsCount) { _x86Decl.setPrototype(convention, returnType, arguments, argumentsCount); } // ============================================================================ // [AsmJit::X86CompilerFuncDecl - Helpers] // ============================================================================ void X86CompilerFuncDecl::_createVariables() { X86Compiler* x86Compiler = getCompiler(); uint32_t i, count = _x86Decl.getArgumentsCount(); if (count == 0) return; _vars = reinterpret_cast(x86Compiler->getZoneMemory().alloc(count * sizeof(void*))); if (_vars == NULL) { x86Compiler->setError(kErrorNoHeapMemory); return; } char argNameStorage[64]; char* argName = NULL; bool debug = x86Compiler->getLogger() != NULL; if (debug) argName = argNameStorage; for (i = 0; i < count; i++) { FuncArg& arg = _x86Decl.getArgument(i); if (debug) snprintf(argName, ASMJIT_ARRAY_SIZE(argNameStorage), "arg_%u", i); uint32_t size = X86Util::getVarSizeFromVarType(arg.getVarType()); X86CompilerVar* cv = x86Compiler->_newVar(argName, arg.getVarType(), size); if (arg.getRegIndex() != kRegIndexInvalid) { cv->_isRegArgument = true; cv->regIndex = arg.getRegIndex(); } if (arg.getStackOffset() != kFuncStackInvalid) { cv->_isMemArgument = true; cv->homeMemoryOffset = arg.getStackOffset(); } _vars[i] = cv; } } void X86CompilerFuncDecl::_prepareVariables(CompilerItem* first) { uint32_t count = _x86Decl.getArgumentsCount(); if (count == 0) return; for (uint32_t i = 0; i < count; i++) { X86CompilerVar* cv = getVar(i); // This is where variable scope starts. cv->firstItem = first; // If this will not be changed then it will be deallocated immediately. cv->lastItem = first; } } void X86CompilerFuncDecl::_allocVariables(CompilerContext& cc) { X86CompilerContext& x86Context = static_cast(cc); uint32_t count = getDecl()->getArgumentsCount(); if (count == 0) return; for (uint32_t i = 0; i < count; i++) { X86CompilerVar* cv = getVar(i); if (cv->firstItem != NULL || cv->isArgument()) { // Variable is used. if (cv->regIndex != kRegIndexInvalid) { cv->state = kVarStateReg; // If variable is in register -> mark it as changed so it will not be // lost by first spill. cv->changed = true; x86Context._allocatedVariable(cv); } else if (cv->isMemArgument()) { cv->state = kVarStateMem; } } else { // Variable is not used. cv->regIndex = kRegIndexInvalid; } } } void X86CompilerFuncDecl::_preparePrologEpilog(CompilerContext& cc) { X86CompilerContext& x86Context = static_cast(cc); const X86CpuInfo* cpuInfo = X86CpuInfo::getGlobal(); clearFuncFlag( kX86FuncFlagPushPop | kX86FuncFlagEmitEmms | kX86FuncFlagEmitSFence | kX86FuncFlagEmitLFence | kX86FuncFlagAssume16ByteAlignment | kX86FuncFlagPerform16ByteAlignment); uint32_t accessibleMemoryBelowStack = 0; if (getDecl()->getConvention() == kX86FuncConvX64U) accessibleMemoryBelowStack = 128; if (getHint(kX86FuncHintAssume16ByteAlignment )) setFuncFlag(kX86FuncFlagAssume16ByteAlignment); if (getHint(kX86FuncHintPerform16ByteAlignment)) setFuncFlag(kX86FuncFlagPerform16ByteAlignment); if (getHint(kFuncHintNaked) != 0) setFuncFlag(kFuncFlagIsNaked); if (isCaller() && (x86Context._memBytesTotal > 0 || isAssumed16ByteAlignment())) setFuncFlag(kX86FuncFlagIsEspAdjusted); if (x86Context._memBytesTotal > accessibleMemoryBelowStack) setFuncFlag(kX86FuncFlagIsEspAdjusted); if (getHint(kX86FuncHintPushPop) != 0) setFuncFlag(kX86FuncFlagPushPop); if (getHint(kX86FuncHintEmms) != 0) setFuncFlag(kX86FuncFlagEmitEmms); if (getHint(kX86FuncHintSFence) != 0) setFuncFlag(kX86FuncFlagEmitSFence); if (getHint(kX86FuncHintLFence) != 0) setFuncFlag(kX86FuncFlagEmitLFence); // Updated to respect comment from issue #47, align also when using MMX code. if (!isAssumed16ByteAlignment() && !isNaked() && (x86Context._mem16BlocksCount + (x86Context._mem8BlocksCount > 0))) { // Have to align stack to 16-bytes. setFuncFlag(kX86FuncFlagIsEspAdjusted | kX86FuncFlagPerform16ByteAlignment); } _gpModifiedAndPreserved = x86Context._modifiedGpRegisters & _x86Decl.getGpPreservedMask() & (~IntUtil::maskFromIndex(kX86RegIndexEsp)); _mmModifiedAndPreserved = x86Context._modifiedMmRegisters & _x86Decl.getMmPreservedMask(); _xmmModifiedAndPreserved = x86Context._modifiedXmmRegisters & _x86Decl.getXmmPreservedMask(); _movDqInstCode = (isAssumed16ByteAlignment() | isPerformed16ByteAlignment()) ? kX86InstMovDQA : kX86InstMovDQU; // Prolog & Epilog stack size. { int32_t memGpSize = IntUtil::bitCount(_gpModifiedAndPreserved) * sizeof(intptr_t); int32_t memMmSize = IntUtil::bitCount(_mmModifiedAndPreserved) * 8; int32_t memXmmSize = IntUtil::bitCount(_xmmModifiedAndPreserved) * 16; if (hasFuncFlag(kX86FuncFlagPushPop)) { _pePushPopStackSize = memGpSize; _peMovStackSize = memXmmSize + IntUtil::align(memMmSize, 16); } else { _pePushPopStackSize = 0; _peMovStackSize = memXmmSize + IntUtil::align(memMmSize + memGpSize, 16); } } if (isPerformed16ByteAlignment()) { _peAdjustStackSize += IntUtil::delta(_pePushPopStackSize, 16); } else { int32_t v = 16 - sizeof(uintptr_t); if (!isNaked()) v -= sizeof(uintptr_t); v -= _pePushPopStackSize & 15; if (v < 0) v += 16; _peAdjustStackSize = v; //_peAdjustStackSize += IntUtil::delta(_pePushPopStackSize + v, 16); } // Memory stack size. _memStackSize = x86Context._memBytesTotal; _memStackSize16 = IntUtil::align(_memStackSize, 16); if (isNaked()) { x86Context._argumentsBaseReg = kX86RegIndexEsp; x86Context._argumentsBaseOffset = hasFuncFlag(kX86FuncFlagIsEspAdjusted) ? (_funcCallStackSize + _memStackSize16 + _peMovStackSize + _pePushPopStackSize + _peAdjustStackSize) : (_pePushPopStackSize); } else { x86Context._argumentsBaseReg = kX86RegIndexEbp; x86Context._argumentsBaseOffset = sizeof(sysint_t); } x86Context._variablesBaseReg = kX86RegIndexEsp; x86Context._variablesBaseOffset = _funcCallStackSize; if (!hasFuncFlag(kX86FuncFlagIsEspAdjusted)) x86Context._variablesBaseOffset = -_memStackSize16 - _peMovStackSize - _peAdjustStackSize; } void X86CompilerFuncDecl::_dumpFunction(CompilerContext& cc) { X86CompilerContext& x86Context = static_cast(cc); X86Compiler* x86Compiler = getCompiler(); Logger* logger = x86Compiler->getLogger(); ASMJIT_ASSERT(logger != NULL); uint32_t i; char _buf[1024]; char* p; // Log function prototype. { uint32_t argumentsCount = _x86Decl.getArgumentsCount(); bool first = true; logger->logString("; Function Prototype:\n"); logger->logString(";\n"); for (i = 0; i < argumentsCount; i++) { const FuncArg& a = _x86Decl.getArgument(i); X86CompilerVar* cv = getVar(i); if (first) { logger->logString("; IDX| Type | Sz | Home |\n"); logger->logString("; ---+----------+----+----------------+\n"); } char* memHome = memHome = _buf; if (a.hasRegIndex()) { Reg regOp(a.getRegIndex() | kX86RegTypeGpz, 0); X86Assembler_dumpOperand(memHome, ®Op, kX86RegTypeGpz, 0)[0] = '\0'; } else { Mem memOp; memOp._mem.base = kX86RegIndexEsp; memOp._mem.displacement = a.getStackOffset(); X86Assembler_dumpOperand(memHome, &memOp, kX86RegTypeGpz, 0)[0] = '\0'; } logger->logFormat("; %-3u| %-9s| %-3u| %-15s|\n", // Argument index. i, // Argument type. cv->getType() < kX86VarTypeCount ? x86VarInfo[cv->getType()].getName() : "invalid", // Argument size. cv->getSize(), // Argument memory home. memHome ); first = false; } logger->logString(";\n"); } // Log variables. { uint32_t variablesCount = (uint32_t)x86Compiler->_vars.getLength(); bool first = true; logger->logString("; Variables:\n"); logger->logString(";\n"); for (i = 0; i < variablesCount; i++) { X86CompilerVar* cv = static_cast(x86Compiler->_vars[i]); // If this variable is not related to this function then skip it. if (cv->funcScope != this) continue; // Get some information about variable type. const X86VarInfo& vinfo = x86VarInfo[cv->getType()]; if (first) { logger->logString("; ID | Type | Sz | Home | Register Access | Memory Access |\n"); logger->logString("; ---+----------+----+----------------+-------------------+-------------------+\n"); } char* memHome = (char*)"[None]"; if (cv->homeMemoryData != NULL) { VarMemBlock* memBlock = reinterpret_cast(cv->homeMemoryData); memHome = _buf; Mem memOp; if (cv->isMemArgument()) { const FuncArg& a = _x86Decl.getArgument(i); memOp._mem.base = x86Context._argumentsBaseReg; memOp._mem.displacement += x86Context._argumentsBaseOffset; memOp._mem.displacement += a.getStackOffset(); } else { memOp._mem.base = x86Context._variablesBaseReg; memOp._mem.displacement += x86Context._variablesBaseOffset; memOp._mem.displacement += memBlock->offset; } X86Assembler_dumpOperand(memHome, &memOp, kX86RegTypeGpz, 0)[0] = '\0'; } logger->logFormat("; %-3u| %-9s| %-3u| %-15s| r=%-4uw=%-4ux=%-4u| r=%-4uw=%-4ux=%-4u|\n", // Variable id. (uint)(i & kOperandIdValueMask), // Variable type. cv->getType() < kX86VarTypeCount ? vinfo.getName() : "invalid", // Variable size. cv->getSize(), // Variable memory home. memHome, // Register access count. (unsigned int)cv->regReadCount, (unsigned int)cv->regWriteCount, (unsigned int)cv->regRwCount, // Memory access count. (unsigned int)cv->memReadCount, (unsigned int)cv->memWriteCount, (unsigned int)cv->memRwCount ); first = false; } logger->logString(";\n"); } // Log modified registers. { p = _buf; uint32_t r; uint32_t modifiedRegisters = 0; for (r = 0; r < 3; r++) { bool first = true; uint32_t regs; uint32_t type; switch (r) { case 0: regs = x86Context._modifiedGpRegisters; type = kX86RegTypeGpz; p = StringUtil::copy(p, "; GP : "); break; case 1: regs = x86Context._modifiedMmRegisters; type = kX86RegTypeMm; p = StringUtil::copy(p, "; MM : "); break; case 2: regs = x86Context._modifiedXmmRegisters; type = kX86RegTypeXmm; p = StringUtil::copy(p, "; XMM: "); break; default: ASMJIT_ASSERT(0); } for (i = 0; i < kX86RegNumBase; i++) { if ((regs & IntUtil::maskFromIndex(i)) != 0) { if (!first) { *p++ = ','; *p++ = ' '; } p = X86Assembler_dumpRegister(p, type, i); first = false; modifiedRegisters++; } } *p++ = '\n'; } *p = '\0'; logger->logFormat("; Modified registers (%u):\n", (unsigned int)modifiedRegisters); logger->logString(_buf); } logger->logString("\n"); } void X86CompilerFuncDecl::_emitProlog(CompilerContext& cc) { X86CompilerContext& x86Context = static_cast(cc); X86Compiler* x86Compiler = getCompiler(); // -------------------------------------------------------------------------- // [Init] // -------------------------------------------------------------------------- uint32_t i, mask; uint32_t preservedGP = _gpModifiedAndPreserved; uint32_t preservedMM = _mmModifiedAndPreserved; uint32_t preservedXMM = _xmmModifiedAndPreserved; int32_t stackOffset = _getRequiredStackOffset(); int32_t stackPos; // -------------------------------------------------------------------------- // [Prolog] // -------------------------------------------------------------------------- if (x86Compiler->getLogger()) x86Compiler->comment("Prolog"); // Emit standard prolog entry code (but don't do it if function is set to be // naked). // // Also see the _prologEpilogStackAdjust variable. If function is naked (so // prolog and epilog will not contain "push ebp" and "mov ebp, esp", we need // to adjust stack by 8 bytes in 64-bit mode (this will give us that stack // will remain aligned to 16 bytes). if (!isNaked()) { x86Compiler->emit(kX86InstPush, zbp); x86Compiler->emit(kX86InstMov, zbp, zsp); } // Align manually stack-pointer to 16-bytes. if (isPerformed16ByteAlignment()) { ASMJIT_ASSERT(!isNaked()); x86Compiler->emit(kX86InstAnd, zsp, imm(-16)); } // -------------------------------------------------------------------------- // [Save Gp - Push/Pop] // -------------------------------------------------------------------------- if (preservedGP != 0 && hasFuncFlag(kX86FuncFlagPushPop)) { for (i = 0, mask = 1; i < kX86RegNumGp; i++, mask <<= 1) { if (preservedGP & mask) x86Compiler->emit(kX86InstPush, gpz(i)); } } // -------------------------------------------------------------------------- // [Adjust Scack] // -------------------------------------------------------------------------- if (isEspAdjusted()) { stackPos = _memStackSize16 + _funcCallStackSize; if (stackOffset != 0) x86Compiler->emit(kX86InstSub, zsp, imm(stackOffset)); } else { stackPos = -(_peMovStackSize + _peAdjustStackSize); //if (_pePushPop) stackPos += IntUtil::bitCount(preservedGP) * sizeof(sysint_t); } // -------------------------------------------------------------------------- // [Save Xmm - MovDqa/MovDqu] // -------------------------------------------------------------------------- if (preservedXMM != 0) { for (i = 0, mask = 1; i < kX86RegNumXmm; i++, mask <<= 1) { if (preservedXMM & mask) { x86Compiler->emit(_movDqInstCode, dqword_ptr(zsp, stackPos), xmm(i)); stackPos += 16; } } } // -------------------------------------------------------------------------- // [Save Mm - MovQ] // -------------------------------------------------------------------------- if (preservedMM != 0) { for (i = 0, mask = 1; i < 8; i++, mask <<= 1) { if (preservedMM & mask) { x86Compiler->emit(kX86InstMovQ, qword_ptr(zsp, stackPos), mm(i)); stackPos += 8; } } } // -------------------------------------------------------------------------- // [Save Gp - Mov] // -------------------------------------------------------------------------- if (preservedGP != 0 && !hasFuncFlag(kX86FuncFlagPushPop)) { for (i = 0, mask = 1; i < kX86RegNumGp; i++, mask <<= 1) { if (preservedGP & mask) { x86Compiler->emit(kX86InstMov, sysint_ptr(zsp, stackPos), gpz(i)); stackPos += sizeof(sysint_t); } } } // -------------------------------------------------------------------------- // [...] // -------------------------------------------------------------------------- if (x86Compiler->getLogger()) x86Compiler->comment("Body"); } void X86CompilerFuncDecl::_emitEpilog(CompilerContext& cc) { X86CompilerContext& x86Context = static_cast(cc); X86Compiler* x86Compiler = getCompiler(); const X86CpuInfo* cpuInfo = X86CpuInfo::getGlobal(); // -------------------------------------------------------------------------- // [Init] // -------------------------------------------------------------------------- uint32_t i, mask; uint32_t preservedGP = _gpModifiedAndPreserved; uint32_t preservedMM = _mmModifiedAndPreserved; uint32_t preservedXMM = _xmmModifiedAndPreserved; int32_t stackOffset = _getRequiredStackOffset(); int32_t stackPos; if (isEspAdjusted()) stackPos = _memStackSize16 + _funcCallStackSize; else stackPos = -(_peMovStackSize + _peAdjustStackSize); // -------------------------------------------------------------------------- // [Epilog] // -------------------------------------------------------------------------- if (x86Compiler->getLogger()) x86Compiler->comment("Epilog"); // -------------------------------------------------------------------------- // [Restore Xmm - MovDqa/ModDqu] // -------------------------------------------------------------------------- if (preservedXMM != 0) { for (i = 0, mask = 1; i < kX86RegNumXmm; i++, mask <<= 1) { if (preservedXMM & mask) { x86Compiler->emit(_movDqInstCode, xmm(i), dqword_ptr(zsp, stackPos)); stackPos += 16; } } } // -------------------------------------------------------------------------- // [Restore Mm - MovQ] // -------------------------------------------------------------------------- if (preservedMM != 0) { for (i = 0, mask = 1; i < 8; i++, mask <<= 1) { if (preservedMM & mask) { x86Compiler->emit(kX86InstMovQ, mm(i), qword_ptr(zsp, stackPos)); stackPos += 8; } } } // -------------------------------------------------------------------------- // [Restore Gp - Mov] // -------------------------------------------------------------------------- if (preservedGP != 0 && !hasFuncFlag(kX86FuncFlagPushPop)) { for (i = 0, mask = 1; i < kX86RegNumGp; i++, mask <<= 1) { if (preservedGP & mask) { x86Compiler->emit(kX86InstMov, gpz(i), sysint_ptr(zsp, stackPos)); stackPos += sizeof(sysint_t); } } } // -------------------------------------------------------------------------- // [Adjust Stack] // -------------------------------------------------------------------------- if (isEspAdjusted() && stackOffset != 0) x86Compiler->emit(kX86InstAdd, zsp, imm(stackOffset)); // -------------------------------------------------------------------------- // [Restore Gp - Push/Pop] // -------------------------------------------------------------------------- if (preservedGP != 0 && hasFuncFlag(kX86FuncFlagPushPop)) { for (i = kX86RegNumGp - 1, mask = 1 << i; (int32_t)i >= 0; i--, mask >>= 1) { if (preservedGP & mask) x86Compiler->emit(kX86InstPop, gpz(i)); } } // -------------------------------------------------------------------------- // [Emms] // -------------------------------------------------------------------------- if (hasFuncFlag(kX86FuncFlagEmitEmms)) x86Compiler->emit(kX86InstEmms); // -------------------------------------------------------------------------- // [MFence/SFence/LFence] // -------------------------------------------------------------------------- if (hasFuncFlag(kX86FuncFlagEmitSFence) & hasFuncFlag(kX86FuncFlagEmitLFence)) x86Compiler->emit(kX86InstMFence); else if (hasFuncFlag(kX86FuncFlagEmitSFence)) x86Compiler->emit(kX86InstSFence); else if (hasFuncFlag(kX86FuncFlagEmitLFence)) x86Compiler->emit(kX86InstLFence); // -------------------------------------------------------------------------- // [Epilog] // -------------------------------------------------------------------------- // Emit standard epilog leave code (if needed). if (!isNaked()) { // AMD seems to prefer LEAVE instead of MOV/POP sequence. if (cpuInfo->getVendorId() == kCpuAmd) { x86Compiler->emit(kX86InstLeave); } else { x86Compiler->emit(kX86InstMov, zsp, zbp); x86Compiler->emit(kX86InstPop, zbp); } } // Emit return. if (_x86Decl.getCalleePopsStack()) x86Compiler->emit(kX86InstRet, imm((int16_t)_x86Decl.getArgumentsStackSize())); else x86Compiler->emit(kX86InstRet); } // ============================================================================ // [AsmJit::X86CompilerFuncDecl - Function-Call] // ============================================================================ void X86CompilerFuncDecl::reserveStackForFunctionCall(int32_t size) { size = IntUtil::align(size, 16); if (size > _funcCallStackSize) _funcCallStackSize = size; setFuncFlag(kFuncFlagIsCaller); } // ============================================================================ // [AsmJit::X86CompilerFuncEnd - Construction / Destruction] // ============================================================================ X86CompilerFuncEnd::X86CompilerFuncEnd(X86Compiler* x86Compiler, X86CompilerFuncDecl* func) : CompilerFuncEnd(x86Compiler, func) { } X86CompilerFuncEnd::~X86CompilerFuncEnd() { } // ============================================================================ // [AsmJit::X86CompilerFuncEnd - Interface] // ============================================================================ void X86CompilerFuncEnd::prepare(CompilerContext& cc) { X86CompilerContext& x86Context = static_cast(cc); _offset = x86Context._currentOffset++; } CompilerItem* X86CompilerFuncEnd::translate(CompilerContext& cc) { _isTranslated = true; return NULL; } // ============================================================================ // [AsmJit::X86CompilerFuncRet - Construction / Destruction] // ============================================================================ X86CompilerFuncRet::X86CompilerFuncRet(X86Compiler* x86Compiler, X86CompilerFuncDecl* func, const Operand* first, const Operand* second) : CompilerFuncRet(x86Compiler, func, first, second) { /* // TODO:? // Check whether the return value is compatible. uint32_t retValType = function->_x86Decl.getReturnType(); bool valid = false; switch (retValType) { case kX86VarTypeGpd: case kX86VarTypeGpq: if ((_ret[0].isVar() && (reinterpret_cast(_ret[0]).isGpVar())) || (_ret[0].isImm())) { valid = true; } break; case kX86VarTypeX87: case kX86VarTypeX87SS: case kX86VarTypeX87SD: if ((_ret[0].isVar() && (reinterpret_cast(_ret[0]).isX87Var() || reinterpret_cast(_ret[0]).isXmmVar() )) ) { valid = true; } break; case kX86VarTypeMm: break; case kVarTypeInvalid: if (_ret[0].isNone() && _ret[1].isNone()) { valid = true; } break; default: break; } // Incompatible return value. if (!valid) { c->setError(kErrorIncompatibleReturnType); } */ } X86CompilerFuncRet::~X86CompilerFuncRet() { } // ============================================================================ // [AsmJit::X86CompilerFuncRet - Interface] // ============================================================================ void X86CompilerFuncRet::prepare(CompilerContext& cc) { X86CompilerContext& x86Context = static_cast(cc); X86Compiler* x86Compiler = x86Context.getCompiler(); uint32_t retValType = getFunc()->_x86Decl.getReturnType(); _offset = x86Context._currentOffset; if (retValType != kVarTypeInvalid) { uint32_t i; for (i = 0; i < 2; i++) { Operand& o = _ret[i]; if (o.isVar()) { ASMJIT_ASSERT(o.getId() != kInvalidValue); X86CompilerVar* cv = x86Compiler->_getVar(o.getId()); ASMJIT_ASSERT(cv != NULL); // First item (begin of variable scope). if (cv->firstItem == NULL) cv->firstItem = this; // Last item (end of variable scope). cv->lastItem = this; if (cv->workOffset == _offset) continue; if (!x86Context._isActive(cv)) x86Context._addActive(cv); cv->workOffset = _offset; cv->regReadCount++; if (X86Util::isVarTypeInt(cv->getType()) && X86Util::isVarTypeInt(retValType)) { x86Context._newRegisterHomeIndex(cv, (i == 0) ? kX86RegIndexEax : kX86RegIndexEdx); } } } } x86Context._currentOffset++; } CompilerItem* X86CompilerFuncRet::translate(CompilerContext& cc) { X86CompilerContext& x86Context = static_cast(cc); X86Compiler* x86Compiler = x86Context.getCompiler(); // Check whether the return value is compatible. uint32_t retValType = getFunc()->getDecl()->getReturnType(); uint32_t i; switch (retValType) { case kX86VarTypeGpd: case kX86VarTypeGpq: for (i = 0; i < 2; i++) { uint32_t dstIndex = (i == 0) ? kX86RegIndexEax : kX86RegIndexEdx; uint32_t srcIndex; if (_ret[i].isVar()) { if (reinterpret_cast(_ret[i]).isGpVar()) { X86CompilerVar* cv = x86Compiler->_getVar(_ret[i].getId()); ASMJIT_ASSERT(cv != NULL); srcIndex = cv->regIndex; if (srcIndex == kRegIndexInvalid) x86Compiler->emit(kX86InstMov, gpz(dstIndex), x86Context._getVarMem(cv)); else if (dstIndex != srcIndex) x86Compiler->emit(kX86InstMov, gpz(dstIndex), gpz(srcIndex)); } } else if (_ret[i].isImm()) { x86Compiler->emit(kX86InstMov, gpz(dstIndex), _ret[i]); } } break; case kX86VarTypeX87: case kX86VarTypeX87SS: case kX86VarTypeX87SD: // There is case that we need to return two values (Unix-ABI specific): // - FLD #2 //- FLD #1 i = 2; do { i--; uint32_t dsti = i; uint32_t srci; if (_ret[i].isVar()) { if (reinterpret_cast(_ret[i]).isX87Var()) { // TODO: X87 Support. } else if (reinterpret_cast(_ret[i]).isXmmVar()) { X86CompilerVar* cv = x86Compiler->_getVar(_ret[i].getId()); ASMJIT_ASSERT(cv != NULL); srci = cv->regIndex; if (srci != kRegIndexInvalid) x86Context.saveXmmVar(cv); switch (cv->getType()) { case kX86VarTypeXmmSS: case kX86VarTypeXmmPS: x86Compiler->emit(kX86InstFLd, _BaseVarMem(reinterpret_cast(_ret[i]), 4)); break; case kX86VarTypeXmmSD: case kX86VarTypeXmmPD: x86Compiler->emit(kX86InstFLd, _BaseVarMem(reinterpret_cast(_ret[i]), 8)); break; } } } } while (i != 0); break; case kX86VarTypeMm: for (i = 0; i < 2; i++) { uint32_t dsti = i; uint32_t srci; if (_ret[i].isVar()) { if (reinterpret_cast(_ret[i]).isGpVar()) { X86CompilerVar* cv = x86Compiler->_getVar(_ret[i].getId()); ASMJIT_ASSERT(cv != NULL); srci = cv->regIndex; uint32_t inst = _ret[i].isRegType(kX86RegTypeGpq) ? kX86InstMovQ : kX86InstMovD; if (srci == kRegIndexInvalid) x86Compiler->emit(inst, mm(dsti), x86Context._getVarMem(cv)); else #if defined(ASMJIT_X86) x86Compiler->emit(inst, mm(dsti), gpd(srci)); #else x86Compiler->emit(inst, mm(dsti), _ret[i].isRegType(kX86RegTypeGpq) ? gpq(srci) : gpd(srci)); #endif } else if (reinterpret_cast(_ret[i]).isMmVar()) { X86CompilerVar* cv = x86Compiler->_getVar(_ret[i].getId()); ASMJIT_ASSERT(cv != NULL); srci = cv->regIndex; uint32_t inst = kX86InstMovQ; if (srci == kRegIndexInvalid) x86Compiler->emit(inst, mm(dsti), x86Context._getVarMem(cv)); else if (dsti != srci) x86Compiler->emit(inst, mm(dsti), mm(srci)); } else if (reinterpret_cast(_ret[i]).isXmmVar()) { X86CompilerVar* cv = x86Compiler->_getVar(_ret[i].getId()); ASMJIT_ASSERT(cv != NULL); srci = cv->regIndex; uint32_t inst = kX86InstMovQ; if (reinterpret_cast(_ret[i]).getVarType() == kX86VarTypeXmmSS) inst = kX86InstMovD; if (srci == kRegIndexInvalid) x86Compiler->emit(inst, mm(dsti), x86Context._getVarMem(cv)); else x86Compiler->emit(inst, mm(dsti), xmm(srci)); } } } break; case kX86VarTypeXmm: case kX86VarTypeXmmPS: case kX86VarTypeXmmPD: for (i = 0; i < 2; i++) { uint32_t dsti = i; uint32_t srci; if (_ret[i].isVar()) { if (reinterpret_cast(_ret[i]).isGpVar()) { X86CompilerVar* cv = x86Compiler->_getVar(_ret[i].getId()); ASMJIT_ASSERT(cv != NULL); srci = cv->regIndex; uint32_t inst = _ret[i].isRegType(kX86RegTypeGpq) ? kX86InstMovQ : kX86InstMovD; if (srci == kRegIndexInvalid) x86Compiler->emit(inst, xmm(dsti), x86Context._getVarMem(cv)); else #if defined(ASMJIT_X86) x86Compiler->emit(inst, xmm(dsti), gpd(srci)); #else x86Compiler->emit(inst, xmm(dsti), _ret[i].isRegType(kX86RegTypeGpq) ? gpq(srci) : gpd(srci)); #endif } else if (reinterpret_cast(_ret[i]).isX87Var()) { // TODO: X87 Support. } else if (reinterpret_cast(_ret[i]).isMmVar()) { X86CompilerVar* cv = x86Compiler->_getVar(_ret[i].getId()); ASMJIT_ASSERT(cv != NULL); srci = cv->regIndex; if (srci == kRegIndexInvalid) x86Compiler->emit(kX86InstMovQ, xmm(dsti), x86Context._getVarMem(cv)); else x86Compiler->emit(kX86InstMovQ, xmm(dsti), mm(srci)); } else if (reinterpret_cast(_ret[i]).isXmmVar()) { X86CompilerVar* cv = x86Compiler->_getVar(_ret[i].getId()); ASMJIT_ASSERT(cv != NULL); srci = cv->regIndex; if (srci == kRegIndexInvalid) x86Compiler->emit(kX86InstMovDQA, xmm(dsti), x86Context._getVarMem(cv)); else if (dsti != srci) x86Compiler->emit(kX86InstMovDQA, xmm(dsti), xmm(srci)); } } } break; case kX86VarTypeXmmSS: for (i = 0; i < 2; i++) { uint32_t dsti = i; uint32_t srci; if (_ret[i].isVar()) { if (reinterpret_cast(_ret[i]).isX87Var()) { // TODO: X87 Support. } else if (reinterpret_cast(_ret[i]).isXmmVar()) { X86CompilerVar* cv = x86Compiler->_getVar(_ret[i].getId()); ASMJIT_ASSERT(cv != NULL); srci = cv->regIndex; switch (cv->getType()) { case kX86VarTypeXmm: if (srci == kRegIndexInvalid) x86Compiler->emit(kX86InstMovDQA, xmm(dsti), x86Context._getVarMem(cv)); else if (dsti != srci) x86Compiler->emit(kX86InstMovDQA, xmm(dsti), xmm(srci)); break; case kX86VarTypeXmmSS: case kX86VarTypeXmmPS: if (srci == kRegIndexInvalid) x86Compiler->emit(kX86InstMovSS, xmm(dsti), x86Context._getVarMem(cv)); else x86Compiler->emit(kX86InstMovSS, xmm(dsti), xmm(srci)); break; case kX86VarTypeXmmSD: case kX86VarTypeXmmPD: if (srci == kRegIndexInvalid) x86Compiler->emit(kX86InstCvtSD2SS, xmm(dsti), x86Context._getVarMem(cv)); else if (dsti != srci) x86Compiler->emit(kX86InstCvtSD2SS, xmm(dsti), xmm(srci)); break; } } } } break; case kX86VarTypeXmmSD: for (i = 0; i < 2; i++) { uint32_t dsti = i; uint32_t srci; if (_ret[i].isVar()) { if (reinterpret_cast(_ret[i]).isX87Var()) { // TODO: X87 Support. } else if (reinterpret_cast(_ret[i]).isXmmVar()) { X86CompilerVar* cv = x86Compiler->_getVar(_ret[i].getId()); ASMJIT_ASSERT(cv != NULL); srci = cv->regIndex; switch (cv->getType()) { case kX86VarTypeXmm: if (srci == kRegIndexInvalid) x86Compiler->emit(kX86InstMovDQA, xmm(dsti), x86Context._getVarMem(cv)); else if (dsti != srci) x86Compiler->emit(kX86InstMovDQA, xmm(dsti), xmm(srci)); break; case kX86VarTypeXmmSS: case kX86VarTypeXmmPS: if (srci == kRegIndexInvalid) x86Compiler->emit(kX86InstCvtSS2SD, xmm(dsti), x86Context._getVarMem(cv)); else x86Compiler->emit(kX86InstCvtSS2SD, xmm(dsti), xmm(srci)); break; case kX86VarTypeXmmSD: case kX86VarTypeXmmPD: if (srci == kRegIndexInvalid) x86Compiler->emit(kX86InstMovSD, xmm(dsti), x86Context._getVarMem(cv)); else x86Compiler->emit(kX86InstMovSD, xmm(dsti), xmm(srci)); break; } } } } break; case kInvalidValue: default: break; } if (mustEmitJump()) { x86Context._isUnreachable = 1; } for (i = 0; i < 2; i++) { if (_ret[i].isVar()) { X86CompilerVar* cv = x86Compiler->_getVar(_ret[i].getId()); x86Context._unuseVarOnEndOfScope(this, cv); } } return translated(); } void X86CompilerFuncRet::emit(Assembler& a) { X86Assembler& x86Asm = static_cast(a); if (mustEmitJump()) x86Asm.jmp(getFunc()->getExitLabel()); } // ============================================================================ // [AsmJit::X86CompilerFuncRet - Misc] // ============================================================================ int X86CompilerFuncRet::getMaxSize() const { return mustEmitJump() ? 15 : 0; } // ============================================================================ // [AsmJit::X86CompilerFuncCall - Construction / Destruction] // ============================================================================ X86CompilerFuncCall::X86CompilerFuncCall(X86Compiler* x86Compiler, X86CompilerFuncDecl* caller, const Operand* target) : CompilerFuncCall(x86Compiler, caller, target), _gpParams(0), _mmParams(0), _xmmParams(0), _variablesCount(0), _variables(NULL) { } X86CompilerFuncCall::~X86CompilerFuncCall() { memset(_argumentToVarRecord, 0, sizeof(VarCallRecord*) * kFuncArgsMax); } // ============================================================================ // [AsmJit::X86CompilerFuncCall - Interface] // ============================================================================ void X86CompilerFuncCall::prepare(CompilerContext& cc) { X86CompilerContext& x86Context = static_cast(cc); X86Compiler* x86Compiler = getCompiler(); // Prepare is similar to X86CompilerInst::prepare(). We collect unique variables // and update statistics, but we don't use standard alloc/free register calls. // // The calling function is also unique in variable allocator point of view, // because we need to alloc some variables that may be destroyed be the // callee (okay, may not, but this is not guaranteed). _offset = x86Context._currentOffset; // Tell EFunction that another function will be called inside. It needs this // information to reserve stack for the call and to mark esp adjustable. getCaller()->reserveStackForFunctionCall(static_cast(_x86Decl.getArgumentsStackSize())); uint32_t i; uint32_t argumentsCount = _x86Decl.getArgumentsCount(); uint32_t operandsCount = argumentsCount; uint32_t variablesCount = 0; // Create registers used as arguments mask. for (i = 0; i < argumentsCount; i++) { const FuncArg& fArg = _x86Decl.getArguments()[i]; if (fArg.hasRegIndex()) { switch (fArg.getVarType()) { case kX86VarTypeGpd: case kX86VarTypeGpq: _gpParams |= IntUtil::maskFromIndex(fArg.getRegIndex()); break; case kX86VarTypeMm: _mmParams |= IntUtil::maskFromIndex(fArg.getRegIndex()); break; case kX86VarTypeXmm: case kX86VarTypeXmmSS: case kX86VarTypeXmmPS: case kX86VarTypeXmmSD: case kX86VarTypeXmmPD: _xmmParams |= IntUtil::maskFromIndex(fArg.getRegIndex()); break; default: ASMJIT_ASSERT(0); } } else { x86Context.getFunc()->setFuncFlag(kX86FuncFlagIsEspAdjusted); } } // Call address. operandsCount++; // The first and the second return value. if (!_ret[0].isNone()) operandsCount++; if (!_ret[1].isNone()) operandsCount++; #define __GET_VARIABLE(__vardata__) \ { \ X86CompilerVar* _candidate = __vardata__; \ \ for (var = cur; ;) \ { \ if (var == _variables) \ { \ var = cur++; \ var->vdata = _candidate; \ break; \ } \ \ var--; \ \ if (var->vdata == _candidate) \ { \ break; \ } \ } \ \ ASMJIT_ASSERT(var != NULL); \ } for (i = 0; i < operandsCount; i++) { Operand& o = (i < argumentsCount) ? (_args[i]) : (i == argumentsCount ? _target : _ret[i - argumentsCount - 1]); if (o.isVar()) { ASMJIT_ASSERT(o.getId() != kInvalidValue); X86CompilerVar* cv = x86Compiler->_getVar(o.getId()); ASMJIT_ASSERT(cv != NULL); if (cv->workOffset == _offset) continue; if (!x86Context._isActive(cv)) x86Context._addActive(cv); cv->workOffset = _offset; variablesCount++; } else if (o.isMem()) { if ((o.getId() & kOperandIdTypeMask) == kOperandIdTypeVar) { X86CompilerVar* cv = x86Compiler->_getVar(o.getId()); ASMJIT_ASSERT(cv != NULL); x86Context._markMemoryUsed(cv); if (!x86Context._isActive(cv)) x86Context._addActive(cv); continue; } else if ((o._mem.base & kOperandIdTypeMask) == kOperandIdTypeVar) { X86CompilerVar* cv = x86Compiler->_getVar(o._mem.base); ASMJIT_ASSERT(cv != NULL); if (cv->workOffset == _offset) continue; if (!x86Context._isActive(cv)) x86Context._addActive(cv); cv->workOffset = _offset; variablesCount++; } if ((o._mem.index & kOperandIdTypeMask) == kOperandIdTypeVar) { X86CompilerVar* cv = x86Compiler->_getVar(o._mem.index); ASMJIT_ASSERT(cv != NULL); if (cv->workOffset == _offset) continue; if (!x86Context._isActive(cv)) x86Context._addActive(cv); cv->workOffset = _offset; variablesCount++; } } } // Traverse all active variables and set their funcCall pointer to this // call. This information can be used to choose between the preserved-first // and preserved-last register allocation. if (x86Context._active) { X86CompilerVar* first = static_cast(x86Context._active); X86CompilerVar* active = first; do { if (active->funcCall == NULL) active->funcCall = this; active = active->nextActive; } while (active != first); } if (!variablesCount) { x86Context._currentOffset++; return; } _variables = reinterpret_cast(x86Compiler->getZoneMemory().alloc(sizeof(VarCallRecord) * variablesCount)); if (!_variables) { x86Compiler->setError(kErrorNoHeapMemory); x86Context._currentOffset++; return; } _variablesCount = variablesCount; memset(_variables, 0, sizeof(VarCallRecord) * variablesCount); VarCallRecord* cur = _variables; VarCallRecord* var = NULL; for (i = 0; i < operandsCount; i++) { Operand& o = (i < argumentsCount) ? (_args[i]) : (i == argumentsCount ? _target : _ret[i - argumentsCount - 1]); if (o.isVar()) { X86CompilerVar* cv = x86Compiler->_getVar(o.getId()); ASMJIT_ASSERT(cv != NULL); __GET_VARIABLE(cv) _argumentToVarRecord[i] = var; if (i < argumentsCount) { const FuncArg& fArg = _x86Decl.getArgument(i); if (fArg.hasRegIndex()) { x86Context._newRegisterHomeIndex(cv, fArg.getRegIndex()); switch (fArg.getVarType()) { case kX86VarTypeGpd: case kX86VarTypeGpq: var->flags |= VarCallRecord::kFlagInGp; var->inCount++; break; case kX86VarTypeMm: var->flags |= VarCallRecord::kFlagInMm; var->inCount++; break; case kX86VarTypeXmm: case kX86VarTypeXmmSS: case kX86VarTypeXmmPS: case kX86VarTypeXmmSD: case kX86VarTypeXmmPD: var->flags |= VarCallRecord::kFlagInXmm; var->inCount++; break; default: ASMJIT_ASSERT(0); } } else { var->inCount++; } cv->regReadCount++; } else if (i == argumentsCount) { uint32_t mask = (~_x86Decl.getGpPreservedMask()) & (~_x86Decl.getGpArgumentsMask()) & (IntUtil::maskUpToIndex(kX86RegNumGp)); x86Context._newRegisterHomeIndex(cv, IntUtil::findFirstBit(mask)); x86Context._newRegisterHomeMask(cv, mask); var->flags |= VarCallRecord::kFlagCallReg; cv->regReadCount++; } else { switch (cv->getType()) { case kX86VarTypeGpd: case kX86VarTypeGpq: if (i == argumentsCount+1) var->flags |= VarCallRecord::kFlagOutEax; else var->flags |= VarCallRecord::kFlagOutEdx; break; case kX86VarTypeX87: case kX86VarTypeX87SS: case kX86VarTypeX87SD: #if defined(ASMJIT_X86) if (i == argumentsCount+1) var->flags |= VarCallRecord::kFlagOutSt0; else var->flags |= VarCallRecord::kFlagOutSt1; #else if (i == argumentsCount+1) var->flags |= VarCallRecord::kFlagOutXmm0; else var->flags |= VarCallRecord::kFlagOutXmm1; #endif break; case kX86VarTypeMm: var->flags |= VarCallRecord::kFlagOutMm0; break; case kX86VarTypeXmm: case kX86VarTypeXmmPS: case kX86VarTypeXmmPD: if (i == argumentsCount+1) var->flags |= VarCallRecord::kFlagOutXmm0; else var->flags |= VarCallRecord::kFlagOutXmm1; break; case kX86VarTypeXmmSS: case kX86VarTypeXmmSD: #if defined(ASMJIT_X86) if (i == argumentsCount+1) var->flags |= VarCallRecord::kFlagOutSt0; else var->flags |= VarCallRecord::kFlagOutSt1; #else if (i == argumentsCount+1) var->flags |= VarCallRecord::kFlagOutXmm0; else var->flags |= VarCallRecord::kFlagOutXmm1; #endif break; default: ASMJIT_ASSERT(0); } cv->regWriteCount++; } } else if (o.isMem()) { ASMJIT_ASSERT(i == argumentsCount); if ((o.getId() & kOperandIdTypeMask) == kOperandIdTypeVar) { X86CompilerVar* cv = x86Compiler->_getVar(o.getId()); ASMJIT_ASSERT(cv != NULL); cv->memReadCount++; } else if ((o._mem.base & kOperandIdTypeMask) == kOperandIdTypeVar) { X86CompilerVar* cv = x86Compiler->_getVar(reinterpret_cast(o).getBase()); ASMJIT_ASSERT(cv != NULL); cv->regReadCount++; __GET_VARIABLE(cv) var->flags |= VarCallRecord::kFlagCallReg | VarCallRecord::kFlagCallMem; } if ((o._mem.index & kOperandIdTypeMask) == kOperandIdTypeVar) { X86CompilerVar* cv = x86Compiler->_getVar(reinterpret_cast(o).getIndex()); ASMJIT_ASSERT(cv != NULL); cv->regReadCount++; __GET_VARIABLE(cv) var->flags |= VarCallRecord::kFlagCallReg | VarCallRecord::kFlagCallMem; } } } // Traverse all variables and update firstItem / lastItem. This // function is called from iterator that scans items using forward // direction so we can use this knowledge to optimize the process. // // Same code is in X86CompilerInst::prepare(). for (i = 0; i < _variablesCount; i++) { X86CompilerVar* v = _variables[i].vdata; // First item (begin of variable scope). if (v->firstItem == NULL) v->firstItem = this; // Last item (end of variable scope). v->lastItem = this; } x86Context._currentOffset++; #undef __GET_VARIABLE } CompilerItem* X86CompilerFuncCall::translate(CompilerContext& cc) { X86CompilerContext& x86Context = static_cast(cc); X86Compiler* x86Compiler = x86Context.getCompiler(); uint32_t i; uint32_t preserved, mask; uint32_t temporaryGpReg; uint32_t temporaryXmmReg; uint32_t offset = x86Context._currentOffset; // Constants. const FuncArg* targs = _x86Decl.getArguments(); uint32_t argumentsCount = _x86Decl.getArgumentsCount(); uint32_t variablesCount = _variablesCount; // Processed arguments kFuncArgsMax. uint8_t processed[kFuncArgsMax] = { 0 }; x86Compiler->comment("Call"); // These variables are used by the instruction so we set current offset // to their work offsets -> The getSpillCandidate() method never returns // the variable used by this instruction. for (i = 0; i < variablesCount; i++) { _variables[i].vdata->workOffset = offset; // Init back-reference to VarCallRecord. _variables[i].vdata->tPtr = &_variables[i]; } // -------------------------------------------------------------------------- // STEP 1: // // Spill variables which are not used by the function call and have to // be destroyed. These registers may be used by callee. // -------------------------------------------------------------------------- preserved = _x86Decl.getGpPreservedMask(); for (i = 0, mask = 1; i < kX86RegNumGp; i++, mask <<= 1) { X86CompilerVar* cv = x86Context._x86State.gp[i]; if (cv && cv->workOffset != offset && (preserved & mask) == 0) x86Context.spillGpVar(cv); } preserved = _x86Decl.getMmPreservedMask(); for (i = 0, mask = 1; i < kX86RegNumMm; i++, mask <<= 1) { X86CompilerVar* cv = x86Context._x86State.mm[i]; if (cv && cv->workOffset != offset && (preserved & mask) == 0) x86Context.spillMmVar(cv); } preserved = _x86Decl.getXmmPreservedMask(); for (i = 0, mask = 1; i < kX86RegNumXmm; i++, mask <<= 1) { X86CompilerVar* cv = x86Context._x86State.xmm[i]; if (cv && cv->workOffset != offset && (preserved & mask) == 0) x86Context.spillXmmVar(cv); } // -------------------------------------------------------------------------- // STEP 2: // // Move all arguments to the stack which all already in registers. // -------------------------------------------------------------------------- for (i = 0; i < argumentsCount; i++) { if (processed[i]) continue; const FuncArg& argType = targs[i]; if (argType.hasRegIndex()) continue; Operand& operand = _args[i]; if (operand.isVar()) { VarCallRecord* rec = _argumentToVarRecord[i]; X86CompilerVar* cv = x86Compiler->_getVar(operand.getId()); if (cv->regIndex != kRegIndexInvalid) { _moveAllocatedVariableToStack(cc, cv, argType); rec->inDone++; processed[i] = true; } } } // -------------------------------------------------------------------------- // STEP 3: // // Spill all non-preserved variables we moved to stack in STEP #2. // -------------------------------------------------------------------------- for (i = 0; i < argumentsCount; i++) { VarCallRecord* rec = _argumentToVarRecord[i]; if (!rec || processed[i]) continue; if (rec->inDone >= rec->inCount) { X86CompilerVar* cv = rec->vdata; if (cv->regIndex == kRegIndexInvalid) continue; if (rec->outCount) { // Variable will be rewritten by function return value, it's not needed // to spill it. It will be allocated again by X86CompilerFuncCall. x86Context.unuseVar(rec->vdata, kVarStateUnused); } else { switch (cv->getType()) { case kX86VarTypeGpd: case kX86VarTypeGpq: if ((_x86Decl.getGpPreservedMask() & IntUtil::maskFromIndex(cv->regIndex)) == 0) x86Context.spillGpVar(cv); break; case kX86VarTypeMm: if ((_x86Decl.getMmPreservedMask() & IntUtil::maskFromIndex(cv->regIndex)) == 0) x86Context.spillMmVar(cv); break; case kX86VarTypeXmm: case kX86VarTypeXmmSS: case kX86VarTypeXmmSD: case kX86VarTypeXmmPS: case kX86VarTypeXmmPD: if ((_x86Decl.getXmmPreservedMask() & IntUtil::maskFromIndex(cv->regIndex)) == 0) x86Context.spillXmmVar(cv); break; } } } } // -------------------------------------------------------------------------- // STEP 4: // // Get temporary register that we can use to pass input function arguments. // Now it's safe to do, because the non-needed variables should be spilled. // -------------------------------------------------------------------------- temporaryGpReg = _findTemporaryGpRegister(cc); temporaryXmmReg = _findTemporaryXmmRegister(cc); // If failed to get temporary register then we need just to pick one. if (temporaryGpReg == kRegIndexInvalid) { // TODO. } if (temporaryXmmReg == kRegIndexInvalid) { // TODO. } // -------------------------------------------------------------------------- // STEP 5: // // Move all remaining arguments to the stack (we can use temporary register). // or allocate it to the primary register. Also move immediates. // -------------------------------------------------------------------------- for (i = 0; i < argumentsCount; i++) { if (processed[i]) continue; const FuncArg& argType = targs[i]; if (argType.hasRegIndex()) continue; Operand& operand = _args[i]; if (operand.isVar()) { VarCallRecord* rec = _argumentToVarRecord[i]; X86CompilerVar* cv = x86Compiler->_getVar(operand.getId()); _moveSpilledVariableToStack(cc, cv, argType, temporaryGpReg, temporaryXmmReg); rec->inDone++; processed[i] = true; } else if (operand.isImm()) { // TODO. } } // -------------------------------------------------------------------------- // STEP 6: // // Allocate arguments to registers. // -------------------------------------------------------------------------- bool didWork; do { didWork = false; for (i = 0; i < argumentsCount; i++) { if (processed[i]) continue; VarCallRecord* rsrc = _argumentToVarRecord[i]; Operand& osrc = _args[i]; ASMJIT_ASSERT(osrc.isVar()); X86CompilerVar* vsrc = x86Compiler->_getVar(osrc.getId()); const FuncArg& srcArgType = targs[i]; X86CompilerVar* vdst = _getOverlappingVariable(cc, srcArgType); if (vsrc == vdst) { rsrc->inDone++; processed[i] = true; didWork = true; continue; } else if (vdst != NULL) { VarCallRecord* rdst = reinterpret_cast(vdst->tPtr); if (rdst == NULL) { x86Context.spillVar(vdst); vdst = NULL; } else if (rdst->inDone >= rdst->inCount && (rdst->flags & VarCallRecord::kFlagCallReg) == 0) { // Safe to spill. if (rdst->outCount || vdst->lastItem == this) x86Context.unuseVar(vdst, kVarStateUnused); else x86Context.spillVar(vdst); vdst = NULL; } else { uint32_t x = _x86Decl.findArgumentByRegCode(X86Util::getRegCodeFromVarType(vsrc->getType(), vsrc->regIndex)); bool doSpill = true; if ((vdst->getClass() & kX86VarClassGp) != 0) { // Try to emit mov to register which is possible for call() operand. if (x == kInvalidValue && (rdst->flags & VarCallRecord::kFlagCallReg) != 0) { uint32_t rIndex; uint32_t rBit; // The mask which contains registers which are not-preserved // (these that might be clobbered by the callee) and which are // not used to pass function arguments. Each register contained // in this mask is ideal to be used by call() instruction. uint32_t possibleMask = (~_x86Decl.getGpPreservedMask()) & (~_x86Decl.getGpArgumentsMask()) & (IntUtil::maskUpToIndex(kX86RegNumGp)); if (possibleMask != 0) { for (rIndex = 0, rBit = 1; rIndex < kX86RegNumGp; rIndex++, rBit <<= 1) { if ((possibleMask & rBit) != 0) { if (x86Context._x86State.gp[rIndex] == NULL) { // This is the best possible solution, the register is // free. We do not need to continue with this loop, the // rIndex will be used by the call(). break; } else { // Wait until the register is freed or try to find another. doSpill = false; didWork = true; } } } } else { // Try to find a register which is free and which is not used // to pass a function argument. possibleMask = _x86Decl.getGpPreservedMask(); for (rIndex = 0, rBit = 1; rIndex < kX86RegNumGp; rIndex++, rBit <<= 1) { if ((possibleMask & rBit) != 0) { // Found one. if (x86Context._x86State.gp[rIndex] == NULL) break; } } } if (rIndex < kX86RegNumGp) { if (temporaryGpReg == vsrc->regIndex) temporaryGpReg = rIndex; x86Compiler->emit(kX86InstMov, gpz(rIndex), gpz(vsrc->regIndex)); x86Context._x86State.gp[vsrc->regIndex] = NULL; x86Context._x86State.gp[rIndex] = vsrc; vsrc->regIndex = rIndex; x86Context._allocatedGpRegister(rIndex); doSpill = false; didWork = true; } } // Emit xchg instead of spill/alloc if possible. else if (x != kInvalidValue) { const FuncArg& dstArgType = targs[x]; if (X86Util::getVarClassFromVarType(dstArgType.getVarType()) == X86Util::getVarClassFromVarType(srcArgType.getVarType())) { uint32_t dstIndex = vdst->regIndex; uint32_t srcIndex = vsrc->regIndex; if (srcIndex == dstArgType.getRegIndex()) { #if defined(ASMJIT_X64) if (vdst->getType() != kX86VarTypeGpd || vsrc->getType() != kX86VarTypeGpd) x86Compiler->emit(kX86InstXchg, gpq(dstIndex), gpq(srcIndex)); else #endif x86Compiler->emit(kX86InstXchg, gpd(dstIndex), gpd(srcIndex)); x86Context._x86State.gp[srcIndex] = vdst; x86Context._x86State.gp[dstIndex] = vsrc; vdst->regIndex = srcIndex; vsrc->regIndex = dstIndex; rdst->inDone++; rsrc->inDone++; processed[i] = true; processed[x] = true; doSpill = false; } } } } if (doSpill) { x86Context.spillVar(vdst); vdst = NULL; } } } if (vdst == NULL) { VarCallRecord* rec = reinterpret_cast(vsrc->tPtr); _moveSrcVariableToRegister(cc, vsrc, srcArgType); switch (srcArgType.getVarType()) { case kX86VarTypeGpd: case kX86VarTypeGpq: x86Context._markGpRegisterModified(srcArgType.getRegIndex()); break; case kX86VarTypeMm: x86Context._markMmRegisterModified(srcArgType.getRegIndex()); break; case kX86VarTypeXmm: case kX86VarTypeXmmSS: case kX86VarTypeXmmSD: case kX86VarTypeXmmPS: case kX86VarTypeXmmPD: x86Context._markMmRegisterModified(srcArgType.getRegIndex()); break; } rec->inDone++; processed[i] = true; } } } while (didWork); // -------------------------------------------------------------------------- // STEP 7: // // Allocate operand used by CALL instruction. // -------------------------------------------------------------------------- for (i = 0; i < variablesCount; i++) { VarCallRecord& r = _variables[i]; if ((r.flags & VarCallRecord::kFlagCallReg) && (r.vdata->regIndex == kRegIndexInvalid)) { // If the register is not allocated and the call form is 'call reg' then // it's possible to keep it in memory. if ((r.flags & VarCallRecord::kFlagCallMem) == 0) { _target = r.vdata->asGpVar().m(); break; } if (temporaryGpReg == kRegIndexInvalid) temporaryGpReg = _findTemporaryGpRegister(cc); x86Context.allocGpVar(r.vdata, IntUtil::maskFromIndex(temporaryGpReg), kVarAllocRegister | kVarAllocRead); } } x86Context.translateOperands(&_target, 1); // -------------------------------------------------------------------------- // STEP 8: // // Spill all preserved variables. // -------------------------------------------------------------------------- preserved = _x86Decl.getGpPreservedMask(); for (i = 0, mask = 1; i < kX86RegNumGp; i++, mask <<= 1) { X86CompilerVar* vdata = x86Context._x86State.gp[i]; if (vdata && (preserved & mask) == 0) { VarCallRecord* rec = reinterpret_cast(vdata->tPtr); if (rec && (rec->outCount || rec->flags & VarCallRecord::kFlagUnuseAfterUse || vdata->lastItem == this)) x86Context.unuseVar(vdata, kVarStateUnused); else x86Context.spillGpVar(vdata); } } preserved = _x86Decl.getMmPreservedMask(); for (i = 0, mask = 1; i < kX86RegNumMm; i++, mask <<= 1) { X86CompilerVar* vdata = x86Context._x86State.mm[i]; if (vdata && (preserved & mask) == 0) { VarCallRecord* rec = reinterpret_cast(vdata->tPtr); if (rec && (rec->outCount || vdata->lastItem == this)) x86Context.unuseVar(vdata, kVarStateUnused); else x86Context.spillMmVar(vdata); } } preserved = _x86Decl.getXmmPreservedMask(); for (i = 0, mask = 1; i < kX86RegNumXmm; i++, mask <<= 1) { X86CompilerVar* vdata = x86Context._x86State.xmm[i]; if (vdata && (preserved & mask) == 0) { VarCallRecord* rec = reinterpret_cast(vdata->tPtr); if (rec && (rec->outCount || vdata->lastItem == this)) x86Context.unuseVar(vdata, kVarStateUnused); else x86Context.spillXmmVar(vdata); } } // -------------------------------------------------------------------------- // STEP 9: // // Emit CALL instruction. // -------------------------------------------------------------------------- x86Compiler->emit(kX86InstCall, _target); // Restore the stack offset. if (_x86Decl.getCalleePopsStack()) { int32_t s = static_cast(_x86Decl.getArgumentsStackSize()); if (s != 0) x86Compiler->emit(kX86InstSub, zsp, imm(s)); } // -------------------------------------------------------------------------- // STEP 10: // // Prepare others for return value(s) and cleanup. // -------------------------------------------------------------------------- // Clear temp data, see AsmJit::X86CompilerVar::temp why it's needed. for (i = 0; i < variablesCount; i++) { VarCallRecord* rec = &_variables[i]; X86CompilerVar* vdata = rec->vdata; if (rec->flags & (VarCallRecord::kFlagOutEax | VarCallRecord::kFlagOutEdx)) { if (vdata->getClass() & kX86VarClassGp) { x86Context.allocGpVar(vdata, IntUtil::maskFromIndex((rec->flags & VarCallRecord::kFlagOutEax) != 0 ? kX86RegIndexEax : kX86RegIndexEdx), kVarAllocRegister | kVarAllocWrite); vdata->changed = true; } } if (rec->flags & (VarCallRecord::kFlagOutMm0)) { if (vdata->getClass() & kX86VarClassMm) { x86Context.allocMmVar(vdata, IntUtil::maskFromIndex(kX86RegIndexMm0), kVarAllocRegister | kVarAllocWrite); vdata->changed = true; } } if (rec->flags & (VarCallRecord::kFlagOutXmm0 | VarCallRecord::kFlagOutXmm1)) { if (vdata->getClass() & kX86VarClassXmm) { x86Context.allocXmmVar(vdata, IntUtil::maskFromIndex((rec->flags & VarCallRecord::kFlagOutXmm0) != 0 ? kX86RegIndexXmm0 : kX86RegIndexXmm1), kVarAllocRegister | kVarAllocWrite); vdata->changed = true; } } if (rec->flags & (VarCallRecord::kFlagOutSt0 | VarCallRecord::kFlagOutSt1)) { if (vdata->getClass() & kX86VarClassXmm) { Mem mem(x86Context._getVarMem(vdata)); x86Context.unuseVar(vdata, kVarStateMem); switch (vdata->getType()) { case kX86VarTypeXmmSS: case kX86VarTypeXmmPS: { mem.setSize(4); x86Compiler->emit(kX86InstFStP, mem); break; } case kX86VarTypeXmmSD: case kX86VarTypeXmmPD: { mem.setSize(8); x86Compiler->emit(kX86InstFStP, mem); break; } default: { x86Compiler->comment("*** WARNING: Can't convert float return value to untyped XMM\n"); break; } } } } // Cleanup. vdata->tPtr = NULL; } for (i = 0; i < variablesCount; i++) { x86Context._unuseVarOnEndOfScope(this, &_variables[i]); } return translated(); } // ============================================================================ // [AsmJit::X86CompilerFuncCall - Misc] // ============================================================================ int X86CompilerFuncCall::getMaxSize() const { // TODO: Instruction max size. return 15; } bool X86CompilerFuncCall::_tryUnuseVar(CompilerVar* _v) { X86CompilerVar* cv = static_cast(_v); for (uint32_t i = 0; i < _variablesCount; i++) { if (_variables[i].vdata == cv) { _variables[i].flags |= VarCallRecord::kFlagUnuseAfterUse; return true; } } return false; } // ============================================================================ // [AsmJit::X86CompilerFuncCall - Helpers] // ============================================================================ uint32_t X86CompilerFuncCall::_findTemporaryGpRegister(CompilerContext& cc) { X86CompilerContext& x86Context = static_cast(cc); uint32_t i; uint32_t mask; uint32_t passedGP = _x86Decl.getGpArgumentsMask(); uint32_t candidate = kRegIndexInvalid; // Find all registers used to pass function arguments. We shouldn't use these // if possible. for (i = 0, mask = 1; i < kX86RegNumGp; i++, mask <<= 1) { if (x86Context._x86State.gp[i] == NULL) { // If this register is used to pass arguments to function, we will mark // it and use it only if there is no other one. if ((passedGP & mask) != 0) candidate = i; else return i; } } return candidate; } uint32_t X86CompilerFuncCall::_findTemporaryXmmRegister(CompilerContext& cc) { X86CompilerContext& x86Context = static_cast(cc); uint32_t i; uint32_t mask; uint32_t passedXMM = _x86Decl.getXmmArgumentsMask(); uint32_t candidate = kRegIndexInvalid; // Find all registers used to pass function arguments. We shouldn't use these // if possible. for (i = 0, mask = 1; i < kX86RegNumXmm; i++, mask <<= 1) { if (x86Context._x86State.xmm[i] == NULL) { // If this register is used to pass arguments to function, we will mark // it and use it only if there is no other one. if ((passedXMM & mask) != 0) candidate = i; else return i; } } return candidate; } X86CompilerVar* X86CompilerFuncCall::_getOverlappingVariable(CompilerContext& cc, const FuncArg& argType) const { X86CompilerContext& x86Context = static_cast(cc); ASMJIT_ASSERT(argType.getVarType() != kVarTypeInvalid); switch (argType.getVarType()) { case kX86VarTypeGpd: case kX86VarTypeGpq: return x86Context._x86State.gp[argType.getRegIndex()]; case kX86VarTypeMm: return x86Context._x86State.mm[argType.getRegIndex()]; case kX86VarTypeXmm: case kX86VarTypeXmmSS: case kX86VarTypeXmmSD: case kX86VarTypeXmmPS: case kX86VarTypeXmmPD: return x86Context._x86State.xmm[argType.getRegIndex()]; } return NULL; } void X86CompilerFuncCall::_moveAllocatedVariableToStack(CompilerContext& cc, X86CompilerVar* vdata, const FuncArg& argType) { X86CompilerContext& x86Context = static_cast(cc); X86Compiler* x86Compiler = x86Context.getCompiler(); ASMJIT_ASSERT(!argType.hasRegIndex()); ASMJIT_ASSERT(vdata->regIndex != kRegIndexInvalid); uint32_t src = vdata->regIndex; Mem dst = ptr(zsp, -(int)sizeof(uintptr_t) + argType.getStackOffset()); switch (vdata->getType()) { case kX86VarTypeGpd: switch (argType.getVarType()) { case kX86VarTypeGpd: x86Compiler->emit(kX86InstMov, dst, gpd(src)); return; #if defined(ASMJIT_X64) case kX86VarTypeGpq: case kX86VarTypeMm: x86Compiler->emit(kX86InstMov, dst, gpq(src)); return; #endif // ASMJIT_X64 } break; #if defined(ASMJIT_X64) case kX86VarTypeGpq: switch (argType.getVarType()) { case kX86VarTypeGpd: x86Compiler->emit(kX86InstMov, dst, gpd(src)); return; case kX86VarTypeGpq: x86Compiler->emit(kX86InstMov, dst, gpq(src)); return; case kX86VarTypeMm: x86Compiler->emit(kX86InstMovQ, dst, gpq(src)); return; } break; #endif // ASMJIT_X64 case kX86VarTypeMm: switch (argType.getVarType()) { case kX86VarTypeGpd: case kX86VarTypeX87SS: case kX86VarTypeXmmSS: x86Compiler->emit(kX86InstMovD, dst, mm(src)); return; case kX86VarTypeGpq: case kX86VarTypeMm: case kX86VarTypeX87SD: case kX86VarTypeXmmSD: x86Compiler->emit(kX86InstMovQ, dst, mm(src)); return; } break; // We allow incompatible types here, because the called can convert them // to correct format before function is called. case kX86VarTypeXmm: case kX86VarTypeXmmPS: case kX86VarTypeXmmPD: switch (argType.getVarType()) { case kX86VarTypeXmm: x86Compiler->emit(kX86InstMovDQU, dst, xmm(src)); return; case kX86VarTypeXmmSS: case kX86VarTypeXmmPS: x86Compiler->emit(kX86InstMovUPS, dst, xmm(src)); return; case kX86VarTypeXmmSD: case kX86VarTypeXmmPD: x86Compiler->emit(kX86InstMovUPD, dst, xmm(src)); return; } break; case kX86VarTypeXmmSS: switch (argType.getVarType()) { case kX86VarTypeX87SS: case kX86VarTypeXmm: case kX86VarTypeXmmSS: case kX86VarTypeXmmPS: case kX86VarTypeXmmSD: case kX86VarTypeXmmPD: x86Compiler->emit(kX86InstMovSS, dst, xmm(src)); return; } break; case kX86VarTypeXmmSD: switch (argType.getVarType()) { case kX86VarTypeX87SD: case kX86VarTypeXmm: case kX86VarTypeXmmSS: case kX86VarTypeXmmPS: case kX86VarTypeXmmSD: case kX86VarTypeXmmPD: x86Compiler->emit(kX86InstMovSD, dst, xmm(src)); return; } break; } x86Compiler->setError(kErrorIncompatibleArgumentType); } void X86CompilerFuncCall::_moveSpilledVariableToStack(CompilerContext& cc, X86CompilerVar* cv, const FuncArg& argType, uint32_t temporaryGpReg, uint32_t temporaryXmmReg) { X86CompilerContext& x86Context = static_cast(cc); X86Compiler* x86Compiler = x86Context.getCompiler(); ASMJIT_ASSERT(!argType.hasRegIndex()); ASMJIT_ASSERT(cv->regIndex == kRegIndexInvalid); Mem src = x86Context._getVarMem(cv); Mem dst = ptr(zsp, -(int)sizeof(sysint_t) + argType.getStackOffset()); switch (cv->getType()) { case kX86VarTypeGpd: switch (argType.getVarType()) { case kX86VarTypeGpd: x86Compiler->emit(kX86InstMov, gpd(temporaryGpReg), src); x86Compiler->emit(kX86InstMov, dst, gpd(temporaryGpReg)); return; #if defined(ASMJIT_X64) case kX86VarTypeGpq: case kX86VarTypeMm: x86Compiler->emit(kX86InstMov, gpd(temporaryGpReg), src); x86Compiler->emit(kX86InstMov, dst, gpq(temporaryGpReg)); return; #endif // ASMJIT_X64 } break; #if defined(ASMJIT_X64) case kX86VarTypeGpq: switch (argType.getVarType()) { case kX86VarTypeGpd: x86Compiler->emit(kX86InstMov, gpd(temporaryGpReg), src); x86Compiler->emit(kX86InstMov, dst, gpd(temporaryGpReg)); return; case kX86VarTypeGpq: case kX86VarTypeMm: x86Compiler->emit(kX86InstMov, gpq(temporaryGpReg), src); x86Compiler->emit(kX86InstMov, dst, gpq(temporaryGpReg)); return; } break; #endif // ASMJIT_X64 case kX86VarTypeMm: switch (argType.getVarType()) { case kX86VarTypeGpd: case kX86VarTypeX87SS: case kX86VarTypeXmmSS: x86Compiler->emit(kX86InstMov, gpd(temporaryGpReg), src); x86Compiler->emit(kX86InstMov, dst, gpd(temporaryGpReg)); return; case kX86VarTypeGpq: case kX86VarTypeMm: case kX86VarTypeX87SD: case kX86VarTypeXmmSD: // TODO return; } break; // We allow incompatible types here, because the caller can convert them // to correct format before function is called. case kX86VarTypeXmm: case kX86VarTypeXmmPS: case kX86VarTypeXmmPD: switch (argType.getVarType()) { case kX86VarTypeXmm: x86Compiler->emit(kX86InstMovDQU, xmm(temporaryXmmReg), src); x86Compiler->emit(kX86InstMovDQU, dst, xmm(temporaryXmmReg)); return; case kX86VarTypeXmmSS: case kX86VarTypeXmmPS: x86Compiler->emit(kX86InstMovUPS, xmm(temporaryXmmReg), src); x86Compiler->emit(kX86InstMovUPS, dst, xmm(temporaryXmmReg)); return; case kX86VarTypeXmmSD: case kX86VarTypeXmmPD: x86Compiler->emit(kX86InstMovUPD, xmm(temporaryXmmReg), src); x86Compiler->emit(kX86InstMovUPD, dst, xmm(temporaryXmmReg)); return; } break; case kX86VarTypeXmmSS: switch (argType.getVarType()) { case kX86VarTypeX87SS: case kX86VarTypeXmm: case kX86VarTypeXmmSS: case kX86VarTypeXmmPS: case kX86VarTypeXmmSD: case kX86VarTypeXmmPD: x86Compiler->emit(kX86InstMovSS, xmm(temporaryXmmReg), src); x86Compiler->emit(kX86InstMovSS, dst, xmm(temporaryXmmReg)); return; } break; case kX86VarTypeXmmSD: switch (argType.getVarType()) { case kX86VarTypeX87SD: case kX86VarTypeXmm: case kX86VarTypeXmmSS: case kX86VarTypeXmmPS: case kX86VarTypeXmmSD: case kX86VarTypeXmmPD: x86Compiler->emit(kX86InstMovSD, xmm(temporaryXmmReg), src); x86Compiler->emit(kX86InstMovSD, dst, xmm(temporaryXmmReg)); return; } break; } x86Compiler->setError(kErrorIncompatibleArgumentType); } void X86CompilerFuncCall::_moveSrcVariableToRegister(CompilerContext& cc, X86CompilerVar* cv, const FuncArg& argType) { X86CompilerContext& x86Context = static_cast(cc); X86Compiler* x86Compiler = x86Context.getCompiler(); uint32_t dst = argType.getRegIndex(); uint32_t src = cv->regIndex; if (src != kRegIndexInvalid) { switch (argType.getVarType()) { case kX86VarTypeGpd: switch (cv->getType()) { case kX86VarTypeGpd: #if defined(ASMJIT_X64) case kX86VarTypeGpq: #endif // ASMJIT_X64 x86Compiler->emit(kX86InstMov, gpd(dst), gpd(src)); return; case kX86VarTypeMm: x86Compiler->emit(kX86InstMovD, gpd(dst), mm(src)); return; } break; #if defined(ASMJIT_X64) case kX86VarTypeGpq: switch (cv->getType()) { case kX86VarTypeGpd: x86Compiler->emit(kX86InstMov, gpd(dst), gpd(src)); return; case kX86VarTypeGpq: x86Compiler->emit(kX86InstMov, gpq(dst), gpq(src)); return; case kX86VarTypeMm: x86Compiler->emit(kX86InstMovQ, gpq(dst), mm(src)); return; } break; #endif // ASMJIT_X64 case kX86VarTypeMm: switch (cv->getType()) { case kX86VarTypeGpd: x86Compiler->emit(kX86InstMovD, gpd(dst), gpd(src)); return; #if defined(ASMJIT_X64) case kX86VarTypeGpq: x86Compiler->emit(kX86InstMovQ, gpq(dst), gpq(src)); return; #endif // ASMJIT_X64 case kX86VarTypeMm: x86Compiler->emit(kX86InstMovQ, mm(dst), mm(src)); return; } break; case kX86VarTypeXmm: case kX86VarTypeXmmPS: case kX86VarTypeXmmPD: switch (cv->getType()) { case kX86VarTypeGpd: x86Compiler->emit(kX86InstMovD, xmm(dst), gpd(src)); return; #if defined(ASMJIT_X64) case kX86VarTypeGpq: x86Compiler->emit(kX86InstMovQ, xmm(dst), gpq(src)); return; #endif // ASMJIT_X64 case kX86VarTypeMm: x86Compiler->emit(kX86InstMovQ, xmm(dst), mm(src)); return; case kX86VarTypeXmm: case kX86VarTypeXmmSS: case kX86VarTypeXmmPS: case kX86VarTypeXmmSD: case kX86VarTypeXmmPD: x86Compiler->emit(kX86InstMovDQA, xmm(dst), xmm(src)); return; } break; case kX86VarTypeXmmSS: switch (cv->getType()) { case kX86VarTypeMm: x86Compiler->emit(kX86InstMovQ, xmm(dst), mm(src)); return; case kX86VarTypeXmm: x86Compiler->emit(kX86InstMovDQA, xmm(dst), xmm(src)); return; case kX86VarTypeXmmSS: case kX86VarTypeXmmPS: x86Compiler->emit(kX86InstMovSS, xmm(dst), xmm(src)); return; case kX86VarTypeXmmSD: case kX86VarTypeXmmPD: x86Compiler->emit(kX86InstCvtSD2SS, xmm(dst), xmm(src)); return; } break; case kX86VarTypeXmmSD: switch (cv->getType()) { case kX86VarTypeMm: x86Compiler->emit(kX86InstMovQ, xmm(dst), mm(src)); return; case kX86VarTypeXmm: x86Compiler->emit(kX86InstMovDQA, xmm(dst), xmm(src)); return; case kX86VarTypeXmmSS: case kX86VarTypeXmmPS: x86Compiler->emit(kX86InstCvtSS2SD, xmm(dst), xmm(src)); return; case kX86VarTypeXmmSD: case kX86VarTypeXmmPD: x86Compiler->emit(kX86InstMovSD, xmm(dst), xmm(src)); return; } break; } } else { Mem mem = x86Context._getVarMem(cv); switch (argType.getVarType()) { case kX86VarTypeGpd: switch (cv->getType()) { case kX86VarTypeGpd: #if defined(ASMJIT_X64) case kX86VarTypeGpq: #endif // ASMJIT_X64 x86Compiler->emit(kX86InstMov, gpd(dst), mem); return; case kX86VarTypeMm: x86Compiler->emit(kX86InstMovD, gpd(dst), mem); return; } break; #if defined(ASMJIT_X64) case kX86VarTypeGpq: switch (cv->getType()) { case kX86VarTypeGpd: x86Compiler->emit(kX86InstMov, gpd(dst), mem); return; case kX86VarTypeGpq: x86Compiler->emit(kX86InstMov, gpq(dst), mem); return; case kX86VarTypeMm: x86Compiler->emit(kX86InstMovQ, gpq(dst), mem); return; } break; #endif // ASMJIT_X64 case kX86VarTypeMm: switch (cv->getType()) { case kX86VarTypeGpd: x86Compiler->emit(kX86InstMovD, gpd(dst), mem); return; #if defined(ASMJIT_X64) case kX86VarTypeGpq: x86Compiler->emit(kX86InstMovQ, gpq(dst), mem); return; #endif // ASMJIT_X64 case kX86VarTypeMm: x86Compiler->emit(kX86InstMovQ, mm(dst), mem); return; } break; case kX86VarTypeXmm: case kX86VarTypeXmmPS: case kX86VarTypeXmmPD: switch (cv->getType()) { case kX86VarTypeGpd: x86Compiler->emit(kX86InstMovD, xmm(dst), mem); return; #if defined(ASMJIT_X64) case kX86VarTypeGpq: x86Compiler->emit(kX86InstMovQ, xmm(dst), mem); return; #endif // ASMJIT_X64 case kX86VarTypeMm: x86Compiler->emit(kX86InstMovQ, xmm(dst), mem); return; case kX86VarTypeXmm: case kX86VarTypeXmmSS: case kX86VarTypeXmmPS: case kX86VarTypeXmmSD: case kX86VarTypeXmmPD: x86Compiler->emit(kX86InstMovDQA, xmm(dst), mem); return; } break; case kX86VarTypeXmmSS: switch (cv->getType()) { case kX86VarTypeMm: x86Compiler->emit(kX86InstMovQ, xmm(dst), mem); return; case kX86VarTypeXmm: x86Compiler->emit(kX86InstMovDQA, xmm(dst), mem); return; case kX86VarTypeXmmSS: case kX86VarTypeXmmPS: x86Compiler->emit(kX86InstMovSS, xmm(dst), mem); return; case kX86VarTypeXmmSD: case kX86VarTypeXmmPD: x86Compiler->emit(kX86InstCvtSD2SS, xmm(dst), mem); return; } break; case kX86VarTypeXmmSD: switch (cv->getType()) { case kX86VarTypeMm: x86Compiler->emit(kX86InstMovQ, xmm(dst), mem); return; case kX86VarTypeXmm: x86Compiler->emit(kX86InstMovDQA, xmm(dst), mem); return; case kX86VarTypeXmmSS: case kX86VarTypeXmmPS: x86Compiler->emit(kX86InstCvtSS2SD, xmm(dst), mem); return; case kX86VarTypeXmmSD: case kX86VarTypeXmmPD: x86Compiler->emit(kX86InstMovSD, xmm(dst), mem); return; } break; } } x86Compiler->setError(kErrorIncompatibleArgumentType); } // Prototype & Arguments Management. void X86CompilerFuncCall::setPrototype(uint32_t callingConvention, uint32_t returnType, const uint32_t* arguments, uint32_t argumentsCount) { _x86Decl.setPrototype(callingConvention, returnType, arguments, argumentsCount); _args = reinterpret_cast( getCompiler()->getZoneMemory().alloc(sizeof(Operand) * argumentsCount)); memset(_args, 0, sizeof(Operand) * argumentsCount); } bool X86CompilerFuncCall::setArgument(uint32_t i, const Var& var) { ASMJIT_ASSERT(i < _x86Decl.getArgumentsCount()); if (i >= _x86Decl.getArgumentsCount()) return false; _args[i] = var; return true; } bool X86CompilerFuncCall::setArgument(uint32_t i, const Imm& imm) { ASMJIT_ASSERT(i < _x86Decl.getArgumentsCount()); if (i >= _x86Decl.getArgumentsCount()) return false; _args[i] = imm; return true; } bool X86CompilerFuncCall::setReturn(const Operand& first, const Operand& second) { _ret[0] = first; _ret[1] = second; return true; } } // AsmJit namespace // [Api-End] #include "../core/apiend.h" desmume/src/addons/slot1_retail_nand.cpp000664 001750 001750 00000017626 12755534123 021531 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2015 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the this software. If not, see . */ // Games with NAND Flash: // Ore/WarioWare D.I.Y. - chip: SAMSUNG 004 // KLC2811ANB-P204 // NTR-UORE-0 // - 128Mbit #include "slot1comp_rom.h" #include "slot1comp_protocol.h" #include "../slot1.h" #include "../NDSSystem.h" #include "../emufile.h" //quick architecture overview: //NAND receives GC bus commands from MMU.cpp //those are passed on to the protocol component for parsing //protocol calls back into NAND via ISlot1Comp_Protocol_Client interface for things the protocol doesn't know about (the contents of the rom, chiefly) //NAND utilizes the rom component for address logic and delivering data. //it also processes some commands itself which aren't rom-related (the NANDy stuff) class Slot1_Retail_NAND : public ISlot1Interface, public ISlot1Comp_Protocol_Client { private: u32 subAdr; Slot1Comp_Protocol protocol; Slot1Comp_Rom rom; u32 mode; u32 handle_save; //current NAND read/write start position //when this is changed, the read/write cursor will be reset to it //when it is set to the same value, the read/write cursor will NOT be reset //(this is since some value must necessarily come in on the protocol address, so the 'current save_start' is used as a special 'dont change' value u32 save_start; /* current NAND read/write cursor */ u32 save_adr; public: virtual Slot1Info const* info() { static Slot1InfoSimple info("Retail NAND","Slot1 retail NAND card emulation", 0x02); return &info; } virtual void connect() { protocol.reset(this); protocol.chipId = gameInfo.chipID; protocol.gameCode = T1ReadLong((u8*)gameInfo.header.gameCode,0); save_adr = 0; handle_save = 0; mode = 0; subAdr = T1ReadWord(gameInfo.header.reserved2, 0x6) << 17; } virtual void write_command(u8 PROCNUM, GC_Command command) { protocol.write_command(command); } virtual void write_GCDATAIN(u8 PROCNUM, u32 val) { protocol.write_GCDATAIN(PROCNUM, val); } virtual u32 read_GCDATAIN(u8 PROCNUM) { return protocol.read_GCDATAIN(PROCNUM); } virtual void slot1client_startOperation(eSlot1Operation operation) { //INFO("Start command: %02X%02X%02X%02X%02X%02X%02X%02X\t", // protocol.command.bytes[0], protocol.command.bytes[1], protocol.command.bytes[2], protocol.command.bytes[3], // protocol.command.bytes[4], protocol.command.bytes[5], protocol.command.bytes[6], protocol.command.bytes[7]); //INFO("FROM: %08X\n", NDS_ARM9.instruct_adr); u32 addressFromProtocol = (protocol.command.bytes[1] << 24) | (protocol.command.bytes[2] << 16) | (protocol.command.bytes[3] << 8) | protocol.command.bytes[4]; //pass the normal rom operations along to the rom component switch(operation) { case eSlot1Operation_00_ReadHeader_Unencrypted: rom.start(operation,addressFromProtocol); return; case eSlot1Operation_2x_SecureAreaLoad: rom.start(operation,protocol.address); return; default: break; } //handle special commands ourselves int cmd = protocol.command.bytes[0]; switch(cmd) { // Nand Init case 0x94: mode = cmd; break; // Nand Error? case 0xD6: break; //Nand Write Page case 0x81: mode = cmd; if(addressFromProtocol != save_start) { save_start = addressFromProtocol; save_adr = (addressFromProtocol & gameInfo.mask) - subAdr; } handle_save = 1; break; case 0x84: //Write disable case 0x85: //Write enable mode = cmd; break; case 0x8B: mode = cmd; handle_save = 0; MMU_new.backupDevice.flushBackup(); break; case 0xB7: if (handle_save) { mode = cmd; if(addressFromProtocol != save_start) { save_start = addressFromProtocol; save_adr = (addressFromProtocol & gameInfo.mask) - subAdr; } } else { rom.start(operation, addressFromProtocol); } break; case 0xB2: //Set save position mode = cmd; save_start = addressFromProtocol; //cursor resets regardless of whether save_start changed, that's what makes this special. //the cursor could be reset to the beginning of the previous save_start region save_adr = (addressFromProtocol & gameInfo.mask) - subAdr; handle_save = 1; break; } } virtual u32 slot1client_read_GCDATAIN(eSlot1Operation operation) { //pass the normal rom operations along to the rom component switch(operation) { case eSlot1Operation_00_ReadHeader_Unencrypted: case eSlot1Operation_2x_SecureAreaLoad: //case eSlot1Operation_B7_Read: return rom.read(); default: break; } //handle special commands ourselves int cmd = protocol.command.bytes[0]; int val = 0; switch(cmd) { // Nand Init? case 0x94: val = 0; mode = 0; break; //Rom/Save Read case 0xB7: { if(handle_save) { MMU_new.backupDevice.ensure(save_adr+4, (u8)0); val = MMU_new.backupDevice.readLong(save_adr, 0); save_adr += 4; } else { val = rom.read(); } } break; // Nand Status? case 0xD6: //0x80 == busy //0x40 == ?? //0x20 == ready? //0x10 == write enabled? switch (mode) { case 0x84: //Write disable val = 0x20202020; break; case 0x85: //Write enable val = 0x20202020 | 0x10101010; break; case 0x8B: val = 0x60606060 | 0x10101010; break; case 0xB2: //Set save position val = 0x20202020; break; default: val = 0x60606060; //0x20 == ready break; } break; } return val; } virtual void slot1client_write_GCDATAIN(eSlot1Operation operation, u32 val) { //pass the normal rom operations along to the rom component switch(operation) { case eSlot1Operation_00_ReadHeader_Unencrypted: case eSlot1Operation_B7_Read: case eSlot1Operation_2x_SecureAreaLoad: return; default: break; } //handle special commands ourselves int cmd = protocol.command.bytes[0]; u32 value = val; u32 adr = save_adr; switch(cmd) { case 0x81: //Nand Write MMU_new.backupDevice.ensure(adr+4, (u8)0); MMU_new.backupDevice.writeLong(adr, val); save_adr += 4; break; } } virtual void post_fakeboot(int PROCNUM) { // The BIOS leaves the card in NORMAL mode protocol.mode = eCardMode_NORMAL; } virtual void savestate(EMUFILE* os) { s32 version = 0; protocol.savestate(os); rom.savestate(os); os->write32le(version); os->write32le(mode); os->write32le(handle_save); os->write32le(save_adr); os->write32le(save_start); os->write32le(subAdr); } virtual void loadstate(EMUFILE* is) { s32 version = 0; protocol.loadstate(is); rom.loadstate(is); is->read32le(&version); // version 0 if (version >= 0) { is->read32le(&mode); is->read32le(&handle_save); is->read32le(&save_adr); is->read32le(&save_start); is->read32le(&subAdr); } } }; ISlot1Interface* construct_Slot1_Retail_NAND() { return new Slot1_Retail_NAND(); } desmume/src/libretro-common/file/nbio/000700 001750 001750 00000000000 12756420131 021073 5ustar00sergiosergio000000 000000 desmume/src/libretro-common/include/formats/rjpeg.h000664 001750 001750 00000003471 12755534123 023632 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2016 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (rjpeg.h). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef __LIBRETRO_SDK_FORMAT_RJPEG_H__ #define __LIBRETRO_SDK_FORMAT_RJPEG_H__ #include #include #include #include RETRO_BEGIN_DECLS typedef struct rjpeg rjpeg_t; int rjpeg_process_image(rjpeg_t *rjpeg, void **buf, size_t size, unsigned *width, unsigned *height); bool rjpeg_set_buf_ptr(rjpeg_t *rjpeg, void *data); void rjpeg_free(rjpeg_t *rjpeg); rjpeg_t *rjpeg_alloc(void); RETRO_END_DECLS #endif desmume/src/utils/AsmJit/core/operand.h000664 001750 001750 00000042263 12755534123 021226 0ustar00sergiosergio000000 000000 // [AsmJit] // Complete JIT Assembler for C++ Language. // // [License] // Zlib - See COPYING file in this package. // [Guard] #ifndef _ASMJIT_CORE_OPERAND_H #define _ASMJIT_CORE_OPERAND_H // [Dependencies - AsmJit] #include "../core/defs.h" namespace AsmJit { //! @addtogroup AsmJit_Core //! @{ // ============================================================================ // [AsmJit::_OperandData] // ============================================================================ //! @internal //! //! @brief Base operand data. struct _OpBase { //! @brief Type of operand, see @c kOperandType. uint8_t op; //! @brief Size of operand (register, address, immediate, or variable). uint8_t size; //! @brief Not used. uint8_t reserved[2]; //! @brief Operand ID (private variable for @c Assembler and @c Compiler classes). //! //! @note Uninitialized operand has always zero id. uint32_t id; }; //! @internal //! //! @brief Label operand data. struct _OpLabel { //! @brief Type of operand, see @c kOperandType (in this case @c kOperandLabel). uint8_t op; //! @brief Size of label, currently not used. uint8_t size; //! @brief Not used. uint8_t reserved[2]; //! @brief Operand ID. uint32_t id; }; //! @internal //! //! @brief Register operand data. struct _OpReg { //! @brief Type of operand, see @c kOperandType (in this case @c kOperandReg). uint8_t op; //! @brief Size of register. uint8_t size; //! @brief Not used. uint8_t reserved[2]; //! @brief Operand id. uint32_t id; //! @brief Register/Variable code, see @c REG. uint32_t code; }; //! @internal //! //! @brief Variable operand data. struct _OpVar { //! @brief Type of operand, see @c kOperandType (in this case @c kOperandVar). uint8_t op; //! @brief Size of variable (0 if don't known). uint8_t size; //! @brief Not used. uint8_t reserved[2]; //! @brief Operand ID. uint32_t id; //! @brief Type (and later also code) of register, see @c kX86RegType, @c kX86RegCode. //! //! @note Register code and variable code are two different things. In most //! cases regCode is very related to varType, but general purpose registers //! are divided to 64-bit, 32-bit, 16-bit and 8-bit entities so the regCode //! can be used to access these, varType remains unchanged from the //! initialization state. Variable type describes mainly variable type and //! home memory size. uint32_t regCode; //! @brief Type of variable. See @c kX86VarType enum. uint32_t varType; }; //! @internal //! //! @brief Memory operand data. struct _OpMem { //! @brief Type of operand, see @c kOperandType (in this case @c kOperandMem). uint8_t op; //! @brief Size of pointer. uint8_t size; //! @brief Memory operand type, see @c kOperandMemType. uint8_t type; //! @brief Segment override prefix, see @c kX86Seg. uint8_t segment : 4; //! @brief Emit MOV/LEA instruction using 16-bit/32-bit form of base/index //! registers. uint8_t sizePrefix : 1; //! @brief Index register shift/scale (0 to 3 inclusive, see @c kScale). uint8_t shift : 3; //! @brief Operand ID. uint32_t id; //! @brief Base register index, variable or label id. uint32_t base; //! @brief Index register index or variable id. uint32_t index; //! @brief Target (for 32-bit, absolute address). void* target; //! @brief Displacement. sysint_t displacement; }; //! @internal //! //! @brief Immediate operand data. struct _OpImm { //! @brief Type of operand, see @c kOperandType (in this case @c kOperandImm).. uint8_t op; //! @brief Size of immediate (or 0 to autodetect). uint8_t size; //! @brief @c true if immediate is unsigned. uint8_t isUnsigned; //! @brief Not used. uint8_t reserved; //! @brief Operand ID. uint32_t id; //! @brief Immediate value. sysint_t value; }; //! @internal //! //! @brief Binary operand data. struct _OpBin { //! @brief First four 32-bit integers. uint32_t u32[4]; //! @brief Second two 32-bit or 64-bit integers. uintptr_t uptr[2]; }; // ============================================================================ // [AsmJit::Operand] // ============================================================================ //! @brief Operand can contain register, memory location, immediate, or label. struct Operand { // -------------------------------------------------------------------------- // [Construction / Destruction] // -------------------------------------------------------------------------- //! @brief Create an uninitialized operand. inline Operand() { memset(this, 0, sizeof(Operand)); _base.id = kInvalidValue; } //! @brief Create a reference to @a other operand. inline Operand(const Operand& other) { _init(other); } #if !defined(ASMJIT_NODOC) inline Operand(const _DontInitialize&) {} #endif // ASMJIT_NODOC // -------------------------------------------------------------------------- // [Init & Copy] // -------------------------------------------------------------------------- //! @internal //! //! @brief Initialize operand to @a other (used by constructors). inline void _init(const Operand& other) { memcpy(this, &other, sizeof(Operand)); } //! @internal //! //! @brief Initialize operand to @a other (used by assign operators). inline void _copy(const Operand& other) { memcpy(this, &other, sizeof(Operand)); } // -------------------------------------------------------------------------- // [Data] // -------------------------------------------------------------------------- template inline T& getData() { return reinterpret_cast(_base); } template inline const T& getData() const { return reinterpret_cast(_base); } // -------------------------------------------------------------------------- // [Type] // -------------------------------------------------------------------------- //! @brief Get type of the operand, see @c kOperandType. inline uint32_t getType() const { return _base.op; } //! @brief Get whether the operand is none (@c kOperandNone). inline bool isNone() const { return (_base.op == kOperandNone); } //! @brief Get whether the operand is any (general purpose, mmx or sse) register (@c kOperandReg). inline bool isReg() const { return (_base.op == kOperandReg); } //! @brief Get whether the operand is memory address (@c kOperandMem). inline bool isMem() const { return (_base.op == kOperandMem); } //! @brief Get whether the operand is immediate (@c kOperandImm). inline bool isImm() const { return (_base.op == kOperandImm); } //! @brief Get whether the operand is label (@c kOperandLabel). inline bool isLabel() const { return (_base.op == kOperandLabel); } //! @brief Get whether the operand is variable (@c kOperandVar). inline bool isVar() const { return (_base.op == kOperandVar); } //! @brief Get whether the operand is variable or memory. inline bool isVarMem() const { return ((_base.op & (kOperandVar | kOperandMem)) != 0); } //! @brief Get whether the operand is register and type of register is @a regType. inline bool isRegType(uint32_t regType) const { return (_base.op == kOperandReg) & ((_reg.code & kRegTypeMask) == regType); } //! @brief Get whether the operand is register and code of register is @a regCode. inline bool isRegCode(uint32_t regCode) const { return (_base.op == kOperandReg) & (_reg.code == regCode); } //! @brief Get whether the operand is register and index of register is @a regIndex. inline bool isRegIndex(uint32_t regIndex) const { return (_base.op == kOperandReg) & ((_reg.code & kRegIndexMask) == (regIndex & kRegIndexMask)); } //! @brief Get whether the operand is any register or memory. inline bool isRegMem() const { return ((_base.op & (kOperandReg | kOperandMem)) != 0); } //! @brief Get whether the operand is register of @a regType type or memory. inline bool isRegTypeMem(uint32_t regType) const { return ((_base.op == kOperandReg) & ((_reg.code & kRegTypeMask) == regType)) | (_base.op == kOperandMem); } // -------------------------------------------------------------------------- // [Size] // -------------------------------------------------------------------------- //! @brief Get size of the operand in bytes. inline uint32_t getSize() const { return _base.size; } // -------------------------------------------------------------------------- // [Id] // -------------------------------------------------------------------------- //! @brief Return operand Id (Operand Id's are used internally by //! @c Assembler and @c Compiler classes). //! //! @note There is no way how to change or remove operand id. If you don't //! need the operand just assign different operand to this one. inline uint32_t getId() const { return _base.id; } // -------------------------------------------------------------------------- // [Members] // -------------------------------------------------------------------------- union { //! @brief Base operand data. _OpBase _base; //! @brief Label operand data. _OpLabel _lbl; //! @brief Register operand data. _OpReg _reg; //! @brief Variable operand data. _OpVar _var; //! @brief Memory operand data. _OpMem _mem; //! @brief Immediate operand data. _OpImm _imm; //! @brief Binary data. _OpBin _bin; }; }; ASMJIT_VAR const Operand noOperand; // ============================================================================ // [AsmJit::Reg] // ============================================================================ //! @brief Base class for all register operands. struct Reg : public Operand { // -------------------------------------------------------------------------- // [Construction / Destruction] // -------------------------------------------------------------------------- //! @brief Create a new base register. inline Reg(uint32_t code, uint32_t size) : Operand(_DontInitialize()) { _reg.op = kOperandReg; _reg.size = (uint8_t)size; _reg.id = kInvalidValue; _reg.code = code; } //! @brief Create a new reference to @a other. inline Reg(const Reg& other) : Operand(other) {} #if !defined(ASMJIT_NODOC) inline Reg(const _DontInitialize& dontInitialize) : Operand(dontInitialize) {} #endif // ASMJIT_NODOC // -------------------------------------------------------------------------- // [Reg Specific] // -------------------------------------------------------------------------- //! @brief Get register code, see @c REG. inline uint32_t getRegCode() const { return (uint32_t)(_reg.code); } //! @brief Get register type, see @c REG. inline uint32_t getRegType() const { return (uint32_t)(_reg.code & kRegTypeMask); } //! @brief Get register index (value from 0 to 7/15). inline uint32_t getRegIndex() const { return (uint32_t)(_reg.code & kRegIndexMask); } //! @brief Get whether register code is equal to @a code. inline bool isRegCode(uint32_t code) const { return _reg.code == code; } //! @brief Get whether register code is equal to @a type. inline bool isRegType(uint32_t type) const { return (uint32_t)(_reg.code & kRegTypeMask) == type; } //! @brief Get whether register index is equal to @a index. inline bool isRegIndex(uint32_t index) const { return (uint32_t)(_reg.code & kRegIndexMask) == index; } //! @brief Set register code to @a code. inline Reg& setCode(uint32_t code) { _reg.code = code; return *this; } //! @brief Set register size to @a size. inline Reg& setSize(uint32_t size) { _reg.size = static_cast(size); return *this; } // -------------------------------------------------------------------------- // [Operator Overload] // -------------------------------------------------------------------------- inline Reg& operator=(const Reg& other) { _copy(other); return *this; } inline bool operator==(const Reg& other) const { return getRegCode() == other.getRegCode(); } inline bool operator!=(const Reg& other) const { return getRegCode() != other.getRegCode(); } }; // ============================================================================ // [AsmJit::Imm] // ============================================================================ //! @brief Immediate operand. //! //! Immediate operand is part of instruction (it's inlined after it). //! //! To create immediate operand, use @c imm() and @c uimm() constructors //! or constructors provided by @c Immediate class itself. struct Imm : public Operand { // -------------------------------------------------------------------------- // [Construction / Destruction] // -------------------------------------------------------------------------- //! @brief Create a new immediate value (initial value is 0). Imm() : Operand(_DontInitialize()) { _imm.op = kOperandImm; _imm.size = 0; _imm.isUnsigned = false; _imm.reserved = 0; _imm.id = kInvalidValue; _imm.value = 0; } //! @brief Create a new signed immediate value, assigning the value to @a i. Imm(sysint_t i) : Operand(_DontInitialize()) { _imm.op = kOperandImm; _imm.size = 0; _imm.isUnsigned = false; _imm.reserved = 0; _imm.id = kInvalidValue; _imm.value = i; } //! @brief Create a new signed or unsigned immediate value, assigning the value to @a i. Imm(sysint_t i, bool isUnsigned) : Operand(_DontInitialize()) { _imm.op = kOperandImm; _imm.size = 0; _imm.isUnsigned = isUnsigned; _imm.reserved = 0; _imm.id = kInvalidValue; _imm.value = i; } //! @brief Create a new immediate value from @a other. inline Imm(const Imm& other) : Operand(other) { } // -------------------------------------------------------------------------- // [Immediate Specific] // -------------------------------------------------------------------------- //! @brief Get whether an immediate is unsigned value. inline bool isUnsigned() const { return _imm.isUnsigned != 0; } //! @brief Get signed immediate value. inline sysint_t getValue() const { return _imm.value; } //! @brief Get unsigned immediate value. inline sysuint_t getUValue() const { return static_cast(_imm.value); } //! @brief Set immediate value as signed type to @a val. inline Imm& setValue(sysint_t val, bool isUnsigned = false) { _imm.value = val; _imm.isUnsigned = isUnsigned; return *this; } //! @brief Set immediate value as unsigned type to @a val. inline Imm& setUValue(sysuint_t val) { _imm.value = (sysint_t)val; _imm.isUnsigned = true; return *this; } // -------------------------------------------------------------------------- // [Operator Overload] // -------------------------------------------------------------------------- //! @brief Assign a signed value @a val to the immediate operand. inline Imm& operator=(sysint_t val) { setValue(val); return *this; } //! @brief Assign @a other to the immediate operand. inline Imm& operator=(const Imm& other) { _copy(other); return *this; } }; //! @brief Create signed immediate value operand. ASMJIT_API Imm imm(sysint_t i); //! @brief Create unsigned immediate value operand. ASMJIT_API Imm uimm(sysuint_t i); // ============================================================================ // [AsmJit::Label] // ============================================================================ //! @brief Label (jump target or data location). //! //! Label represents locations typically used as jump targets, but may be also //! used as position where are stored constants or static variables. If you //! want to use @c Label you need first to associate it with @c Assembler or //! @c Compiler instance. To create new label use @c Assembler::newLabel() or //! @c Compiler::newLabel(). //! //! Example of using labels: //! //! @code //! // Create Assembler or Compiler instance. //! X86Assembler a; //! //! // Create Label instance. //! Label L_1(a); //! //! // ... your code ... //! //! // Using label, see @c AsmJit::Assembler or @c AsmJit::Compiler. //! a.jump(L_1); //! //! // ... your code ... //! //! // Bind label to current position, see @c AsmJit::Assembler::bind() or //! // @c AsmJit::Compiler::bind(). //! a.bind(L_1); //! @endcode struct Label : public Operand { // -------------------------------------------------------------------------- // [Construction / Destruction] // -------------------------------------------------------------------------- //! @brief Create new, unassociated label. inline Label() : Operand(_DontInitialize()) { _lbl.op = kOperandLabel; _lbl.size = 0; _lbl.id = kInvalidValue; } //! @brief Create reference to another label. inline Label(const Label& other) : Operand(other) {} //! @brief Destroy the label. inline ~Label() {} // -------------------------------------------------------------------------- // [Operator Overload] // -------------------------------------------------------------------------- #if !defined(ASMJIT_NODOC) inline Label& operator=(const Label& other) { _copy(other); return *this; } inline bool operator==(const Label& other) const { return _base.id == other._base.id; } inline bool operator!=(const Label& other) const { return _base.id != other._base.id; } #endif // ASMJIT_NODOC }; //! @} } // AsmJit namespace // [Guard] #endif // _ASMJIT_CORE_OPERAND_H desmume/src/libretro-common/features/features_cpu.c000664 001750 001750 00000047170 12755534123 023727 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2016 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (features_cpu.c). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include #include #if defined(_WIN32) #include #else #include #endif #include #include #include #include #if defined(_WIN32) && !defined(_XBOX) #include #endif #if defined(__CELLOS_LV2__) #ifndef _PPU_INTRINSICS_H #include #endif #elif defined(_XBOX360) #include #elif defined(_POSIX_MONOTONIC_CLOCK) || defined(ANDROID) || defined(__QNX__) /* POSIX_MONOTONIC_CLOCK is not being defined in Android headers despite support being present. */ #include #endif #if defined(__QNX__) && !defined(CLOCK_MONOTONIC) #define CLOCK_MONOTONIC 2 #endif #if defined(PSP) #include #include #endif #if defined(VITA) #include #include #endif #if defined(__PSL1GHT__) #include #elif defined(__CELLOS_LV2__) #include #endif #ifdef GEKKO #include #endif /* iOS/OSX specific. Lacks clock_gettime(), so implement it. */ #ifdef __MACH__ #include #ifndef CLOCK_MONOTONIC #define CLOCK_MONOTONIC 0 #endif #ifndef CLOCK_REALTIME #define CLOCK_REALTIME 0 #endif #if __IPHONE_OS_VERSION_MAX_ALLOWED < 100000 // this function is part of iOS 10 now static int clock_gettime(int clk_ik, struct timespec *t) { struct timeval now; int rv = gettimeofday(&now, NULL); if (rv) return rv; t->tv_sec = now.tv_sec; t->tv_nsec = now.tv_usec * 1000; return 0; } #endif #endif #ifdef EMSCRIPTEN #include #endif #if defined(BSD) || defined(__APPLE__) #include #endif #include /** * cpu_features_get_perf_counter: * * Gets performance counter. * * Returns: performance counter. **/ retro_perf_tick_t cpu_features_get_perf_counter(void) { retro_perf_tick_t time_ticks = 0; #if defined(_WIN32) long tv_sec, tv_usec; static const unsigned __int64 epoch = 11644473600000000ULL; FILETIME file_time; SYSTEMTIME system_time; ULARGE_INTEGER ularge; GetSystemTime(&system_time); SystemTimeToFileTime(&system_time, &file_time); ularge.LowPart = file_time.dwLowDateTime; ularge.HighPart = file_time.dwHighDateTime; tv_sec = (long)((ularge.QuadPart - epoch) / 10000000L); tv_usec = (long)(system_time.wMilliseconds * 1000); time_ticks = (1000000 * tv_sec + tv_usec); #elif defined(__linux__) || defined(__QNX__) || defined(__MACH__) struct timespec tv; if (clock_gettime(CLOCK_MONOTONIC, &tv) == 0) time_ticks = (retro_perf_tick_t)tv.tv_sec * 1000000000 + (retro_perf_tick_t)tv.tv_nsec; #elif defined(__GNUC__) && defined(__i386__) || defined(__i486__) || defined(__i686__) __asm__ volatile ("rdtsc" : "=A" (time_ticks)); #elif defined(__GNUC__) && defined(__x86_64__) unsigned a, d; __asm__ volatile ("rdtsc" : "=a" (a), "=d" (d)); time_ticks = (retro_perf_tick_t)a | ((retro_perf_tick_t)d << 32); #elif defined(__ARM_ARCH_6__) __asm__ volatile( "mrc p15, 0, %0, c9, c13, 0" : "=r"(time_ticks) ); #elif defined(__CELLOS_LV2__) || defined(_XBOX360) || defined(__powerpc__) || defined(__ppc__) || defined(__POWERPC__) time_ticks = __mftb(); #elif defined(GEKKO) time_ticks = gettime(); #elif defined(PSP) || defined(VITA) sceRtcGetCurrentTick(&time_ticks); #elif defined(_3DS) time_ticks = svcGetSystemTick(); #elif defined(__mips__) struct timeval tv; gettimeofday(&tv,NULL); time_ticks = (1000000 * tv.tv_sec + tv.tv_usec); #endif return time_ticks; } /** * cpu_features_get_time_usec: * * Gets time in microseconds. * * Returns: time in microseconds. **/ retro_time_t cpu_features_get_time_usec(void) { #if defined(_WIN32) static LARGE_INTEGER freq; LARGE_INTEGER count; /* Frequency is guaranteed to not change. */ if (!freq.QuadPart && !QueryPerformanceFrequency(&freq)) return 0; if (!QueryPerformanceCounter(&count)) return 0; return count.QuadPart * 1000000 / freq.QuadPart; #elif defined(__CELLOS_LV2__) return sys_time_get_system_time(); #elif defined(GEKKO) return ticks_to_microsecs(gettime()); #elif defined(_POSIX_MONOTONIC_CLOCK) || defined(__QNX__) || defined(ANDROID) || defined(__MACH__) struct timespec tv = {0}; if (clock_gettime(CLOCK_MONOTONIC, &tv) < 0) return 0; return tv.tv_sec * INT64_C(1000000) + (tv.tv_nsec + 500) / 1000; #elif defined(EMSCRIPTEN) return emscripten_get_now() * 1000; #elif defined(__mips__) struct timeval tv; gettimeofday(&tv,NULL); return (1000000 * tv.tv_sec + tv.tv_usec); #elif defined(_3DS) return osGetTime() * 1000; #elif defined(VITA) return sceKernelGetProcessTimeWide(); #else #error "Your platform does not have a timer function implemented in cpu_features_get_time_usec(). Cannot continue." #endif } #if defined(__x86_64__) || defined(__i386__) || defined(__i486__) || defined(__i686__) #define CPU_X86 #endif #if defined(_MSC_VER) && !defined(_XBOX) #if (_MSC_VER > 1310) #include #endif #endif #if defined(CPU_X86) && !defined(__MACH__) void x86_cpuid(int func, int flags[4]) { /* On Android, we compile RetroArch with PIC, and we * are not allowed to clobber the ebx register. */ #ifdef __x86_64__ #define REG_b "rbx" #define REG_S "rsi" #else #define REG_b "ebx" #define REG_S "esi" #endif #if defined(__GNUC__) __asm__ volatile ( "mov %%" REG_b ", %%" REG_S "\n" "cpuid\n" "xchg %%" REG_b ", %%" REG_S "\n" : "=a"(flags[0]), "=S"(flags[1]), "=c"(flags[2]), "=d"(flags[3]) : "a"(func)); #elif defined(_MSC_VER) __cpuid(flags, func); #else printf("Unknown compiler. Cannot check CPUID with inline assembly.\n"); memset(flags, 0, 4 * sizeof(int)); #endif } /* Only runs on i686 and above. Needs to be conditionally run. */ static uint64_t xgetbv_x86(uint32_t idx) { #if defined(__GNUC__) uint32_t eax, edx; __asm__ volatile ( /* Older GCC versions (Apple's GCC for example) do * not understand xgetbv instruction. * Stamp out the machine code directly. */ ".byte 0x0f, 0x01, 0xd0\n" : "=a"(eax), "=d"(edx) : "c"(idx)); return ((uint64_t)edx << 32) | eax; #elif _MSC_FULL_VER >= 160040219 /* Intrinsic only works on 2010 SP1 and above. */ return _xgetbv(idx); #else printf("Unknown compiler. Cannot check xgetbv bits.\n"); return 0; #endif } #endif #if defined(__ARM_NEON__) static void arm_enable_runfast_mode(void) { /* RunFast mode. Enables flush-to-zero and some * floating point optimizations. */ static const unsigned x = 0x04086060; static const unsigned y = 0x03000000; int r; __asm__ volatile( "fmrx %0, fpscr \n\t" /* r0 = FPSCR */ "and %0, %0, %1 \n\t" /* r0 = r0 & 0x04086060 */ "orr %0, %0, %2 \n\t" /* r0 = r0 | 0x03000000 */ "fmxr fpscr, %0 \n\t" /* FPSCR = r0 */ : "=r"(r) : "r"(x), "r"(y) ); } #endif #if defined(__linux__) && !defined(CPU_X86) static unsigned char check_arm_cpu_feature(const char* feature) { char line[1024]; unsigned char status = 0; RFILE *fp = filestream_open("/proc/cpuinfo", RFILE_MODE_READ_TEXT, -1); if (!fp) return 0; while (filestream_gets(fp, line, sizeof(line)) != NULL) { if (strncmp(line, "Features\t: ", 11)) continue; if (strstr(line + 11, feature) != NULL) status = 1; break; } filestream_close(fp); return status; } #if !defined(_SC_NPROCESSORS_ONLN) /* Parse an decimal integer starting from 'input', but not going further * than 'limit'. Return the value into '*result'. * * NOTE: Does not skip over leading spaces, or deal with sign characters. * NOTE: Ignores overflows. * * The function returns NULL in case of error (bad format), or the new * position after the decimal number in case of success (which will always * be <= 'limit'). */ static const char *parse_decimal(const char* input, const char* limit, int* result) { const char* p = input; int val = 0; while (p < limit) { int d = (*p - '0'); if ((unsigned)d >= 10U) break; val = val*10 + d; p++; } if (p == input) return NULL; *result = val; return p; } /* Parse a textual list of cpus and store the result inside a CpuList object. * Input format is the following: * - comma-separated list of items (no spaces) * - each item is either a single decimal number (cpu index), or a range made * of two numbers separated by a single dash (-). Ranges are inclusive. * * Examples: 0 * 2,4-127,128-143 * 0-1 */ static void cpulist_parse(CpuList* list, char **buf, ssize_t length) { const char* p = (const char*)buf; const char* end = p + length; /* NOTE: the input line coming from sysfs typically contains a * trailing newline, so take care of it in the code below */ while (p < end && *p != '\n') { int val, start_value, end_value; /* Find the end of current item, and put it into 'q' */ const char *q = (const char*)memchr(p, ',', end-p); if (!q) q = end; /* Get first value */ p = parse_decimal(p, q, &start_value); if (p == NULL) return; end_value = start_value; /* If we're not at the end of the item, expect a dash and * and integer; extract end value. */ if (p < q && *p == '-') { p = parse_decimal(p+1, q, &end_value); if (p == NULL) return; } /* Set bits CPU list bits */ for (val = start_value; val <= end_value; val++) { if ((unsigned)val < 32) list->mask |= (uint32_t)(1U << val); } /* Jump to next item */ p = q; if (p < end) p++; } } /* Read a CPU list from one sysfs file */ static void cpulist_read_from(CpuList* list, const char* filename) { ssize_t length; char *buf = NULL; list->mask = 0; if (filestream_read_file(filename, (void**)&buf, &length) != 1) return; cpulist_parse(list, &buf, length); if (buf) free(buf); buf = NULL; } #endif #endif /** * cpu_features_get_core_amount: * * Gets the amount of available CPU cores. * * Returns: amount of CPU cores available. **/ unsigned cpu_features_get_core_amount(void) { #if defined(_WIN32) && !defined(_XBOX) /* Win32 */ SYSTEM_INFO sysinfo; GetSystemInfo(&sysinfo); return sysinfo.dwNumberOfProcessors; #elif defined(GEKKO) return 1; #elif defined(PSP) return 1; #elif defined(VITA) return 4; #elif defined(_3DS) return 1; #elif defined(_SC_NPROCESSORS_ONLN) /* Linux, most UNIX-likes. */ long ret = sysconf(_SC_NPROCESSORS_ONLN); if (ret <= 0) return (unsigned)1; return ret; #elif defined(BSD) || defined(__APPLE__) /* BSD */ /* Copypasta from stackoverflow, dunno if it works. */ int num_cpu = 0; int mib[4]; size_t len = sizeof(num_cpu); mib[0] = CTL_HW; mib[1] = HW_AVAILCPU; sysctl(mib, 2, &num_cpu, &len, NULL, 0); if (num_cpu < 1) { mib[1] = HW_NCPU; sysctl(mib, 2, &num_cpu, &len, NULL, 0); if (num_cpu < 1) num_cpu = 1; } return num_cpu; #elif defined(__linux__) CpuList cpus_present[1]; CpuList cpus_possible[1]; int amount = 0; cpulist_read_from(cpus_present, "/sys/devices/system/cpu/present"); cpulist_read_from(cpus_possible, "/sys/devices/system/cpu/possible"); /* Compute the intersection of both sets to get the actual number of * CPU cores that can be used on this device by the kernel. */ cpus_present->mask &= cpus_possible->mask; amount = __builtin_popcount(cpus_present->mask); if (amount == 0) return 1; return amount; #elif defined(_XBOX360) return 3; #else /* No idea, assume single core. */ return 1; #endif } /* According to http://en.wikipedia.org/wiki/CPUID */ #define VENDOR_INTEL_b 0x756e6547 #define VENDOR_INTEL_c 0x6c65746e #define VENDOR_INTEL_d 0x49656e69 /** * cpu_features_get: * * Gets CPU features.. * * Returns: bitmask of all CPU features available. **/ uint64_t cpu_features_get(void) { int flags[4]; int vendor_shuffle[3]; char vendor[13] = {0}; size_t len = 0; uint64_t cpu_flags = 0; uint64_t cpu = 0; unsigned max_flag = 0; #if defined(CPU_X86) && !defined(__MACH__) int vendor_is_intel = 0; const int avx_flags = (1 << 27) | (1 << 28); #endif char buf[sizeof(" MMX MMXEXT SSE SSE2 SSE3 SSSE3 SS4 SSE4.2 AES AVX AVX2 NEON VMX VMX128 VFPU PS")]; memset(buf, 0, sizeof(buf)); (void)len; (void)cpu_flags; (void)flags; (void)max_flag; (void)vendor; (void)vendor_shuffle; #if defined(__MACH__) len = sizeof(size_t); if (sysctlbyname("hw.optional.mmx", NULL, &len, NULL, 0) == 0) { cpu |= RETRO_SIMD_MMX; cpu |= RETRO_SIMD_MMXEXT; } len = sizeof(size_t); if (sysctlbyname("hw.optional.sse", NULL, &len, NULL, 0) == 0) cpu |= RETRO_SIMD_SSE; len = sizeof(size_t); if (sysctlbyname("hw.optional.sse2", NULL, &len, NULL, 0) == 0) cpu |= RETRO_SIMD_SSE2; len = sizeof(size_t); if (sysctlbyname("hw.optional.sse3", NULL, &len, NULL, 0) == 0) cpu |= RETRO_SIMD_SSE3; len = sizeof(size_t); if (sysctlbyname("hw.optional.supplementalsse3", NULL, &len, NULL, 0) == 0) cpu |= RETRO_SIMD_SSSE3; len = sizeof(size_t); if (sysctlbyname("hw.optional.sse4_1", NULL, &len, NULL, 0) == 0) cpu |= RETRO_SIMD_SSE4; len = sizeof(size_t); if (sysctlbyname("hw.optional.sse4_2", NULL, &len, NULL, 0) == 0) cpu |= RETRO_SIMD_SSE42; len = sizeof(size_t); if (sysctlbyname("hw.optional.aes", NULL, &len, NULL, 0) == 0) cpu |= RETRO_SIMD_AES; len = sizeof(size_t); if (sysctlbyname("hw.optional.avx1_0", NULL, &len, NULL, 0) == 0) cpu |= RETRO_SIMD_AVX; len = sizeof(size_t); if (sysctlbyname("hw.optional.avx2_0", NULL, &len, NULL, 0) == 0) cpu |= RETRO_SIMD_AVX2; len = sizeof(size_t); if (sysctlbyname("hw.optional.altivec", NULL, &len, NULL, 0) == 0) cpu |= RETRO_SIMD_VMX; len = sizeof(size_t); if (sysctlbyname("hw.optional.neon", NULL, &len, NULL, 0) == 0) cpu |= RETRO_SIMD_NEON; #elif defined(CPU_X86) (void)avx_flags; x86_cpuid(0, flags); vendor_shuffle[0] = flags[1]; vendor_shuffle[1] = flags[3]; vendor_shuffle[2] = flags[2]; memcpy(vendor, vendor_shuffle, sizeof(vendor_shuffle)); /* printf("[CPUID]: Vendor: %s\n", vendor); */ vendor_is_intel = ( flags[1] == VENDOR_INTEL_b && flags[2] == VENDOR_INTEL_c && flags[3] == VENDOR_INTEL_d); max_flag = flags[0]; if (max_flag < 1) /* Does CPUID not support func = 1? (unlikely ...) */ return 0; x86_cpuid(1, flags); if (flags[3] & (1 << 23)) cpu |= RETRO_SIMD_MMX; if (flags[3] & (1 << 25)) { /* SSE also implies MMXEXT (according to FFmpeg source). */ cpu |= RETRO_SIMD_SSE; cpu |= RETRO_SIMD_MMXEXT; } if (flags[3] & (1 << 26)) cpu |= RETRO_SIMD_SSE2; if (flags[2] & (1 << 0)) cpu |= RETRO_SIMD_SSE3; if (flags[2] & (1 << 9)) cpu |= RETRO_SIMD_SSSE3; if (flags[2] & (1 << 19)) cpu |= RETRO_SIMD_SSE4; if (flags[2] & (1 << 20)) cpu |= RETRO_SIMD_SSE42; if ((flags[2] & (1 << 23))) cpu |= RETRO_SIMD_POPCNT; if (vendor_is_intel && (flags[2] & (1 << 22))) cpu |= RETRO_SIMD_MOVBE; if (flags[2] & (1 << 25)) cpu |= RETRO_SIMD_AES; /* Must only perform xgetbv check if we have * AVX CPU support (guaranteed to have at least i686). */ if (((flags[2] & avx_flags) == avx_flags) && ((xgetbv_x86(0) & 0x6) == 0x6)) cpu |= RETRO_SIMD_AVX; if (max_flag >= 7) { x86_cpuid(7, flags); if (flags[1] & (1 << 5)) cpu |= RETRO_SIMD_AVX2; } x86_cpuid(0x80000000, flags); max_flag = flags[0]; if (max_flag >= 0x80000001u) { x86_cpuid(0x80000001, flags); if (flags[3] & (1 << 23)) cpu |= RETRO_SIMD_MMX; if (flags[3] & (1 << 22)) cpu |= RETRO_SIMD_MMXEXT; } #elif defined(__linux__) if (check_arm_cpu_feature("neon")) { cpu |= RETRO_SIMD_NEON; #ifdef __ARM_NEON__ arm_enable_runfast_mode(); #endif } if (check_arm_cpu_feature("vfpv3")) cpu |= RETRO_SIMD_VFPV3; if (check_arm_cpu_feature("vfpv4")) cpu |= RETRO_SIMD_VFPV4; #if 0 check_arm_cpu_feature("swp"); check_arm_cpu_feature("half"); check_arm_cpu_feature("thumb"); check_arm_cpu_feature("fastmult"); check_arm_cpu_feature("vfp"); check_arm_cpu_feature("edsp"); check_arm_cpu_feature("thumbee"); check_arm_cpu_feature("tls"); check_arm_cpu_feature("idiva"); check_arm_cpu_feature("idivt"); #endif #elif defined(__ARM_NEON__) cpu |= RETRO_SIMD_NEON; arm_enable_runfast_mode(); #elif defined(__ALTIVEC__) cpu |= RETRO_SIMD_VMX; #elif defined(XBOX360) cpu |= RETRO_SIMD_VMX128; #elif defined(PSP) cpu |= RETRO_SIMD_VFPU; #elif defined(GEKKO) cpu |= RETRO_SIMD_PS; #endif if (cpu & RETRO_SIMD_MMX) strlcat(buf, " MMX", sizeof(buf)); if (cpu & RETRO_SIMD_MMXEXT) strlcat(buf, " MMXEXT", sizeof(buf)); if (cpu & RETRO_SIMD_SSE) strlcat(buf, " SSE", sizeof(buf)); if (cpu & RETRO_SIMD_SSE2) strlcat(buf, " SSE2", sizeof(buf)); if (cpu & RETRO_SIMD_SSE3) strlcat(buf, " SSE3", sizeof(buf)); if (cpu & RETRO_SIMD_SSSE3) strlcat(buf, " SSSE3", sizeof(buf)); if (cpu & RETRO_SIMD_SSE4) strlcat(buf, " SSE4", sizeof(buf)); if (cpu & RETRO_SIMD_SSE42) strlcat(buf, " SSE4.2", sizeof(buf)); if (cpu & RETRO_SIMD_AES) strlcat(buf, " AES", sizeof(buf)); if (cpu & RETRO_SIMD_AVX) strlcat(buf, " AVX", sizeof(buf)); if (cpu & RETRO_SIMD_AVX2) strlcat(buf, " AVX2", sizeof(buf)); if (cpu & RETRO_SIMD_NEON) strlcat(buf, " NEON", sizeof(buf)); if (cpu & RETRO_SIMD_VFPV3) strlcat(buf, " VFPv3", sizeof(buf)); if (cpu & RETRO_SIMD_VFPV4) strlcat(buf, " VFPv4", sizeof(buf)); if (cpu & RETRO_SIMD_VMX) strlcat(buf, " VMX", sizeof(buf)); if (cpu & RETRO_SIMD_VMX128) strlcat(buf, " VMX128", sizeof(buf)); if (cpu & RETRO_SIMD_VFPU) strlcat(buf, " VFPU", sizeof(buf)); if (cpu & RETRO_SIMD_PS) strlcat(buf, " PS", sizeof(buf)); return cpu; } gpu-debug.diff000664 001750 001750 00000006713 12755534123 014431 0ustar00sergiosergio000000 000000 diff --git a/desmume/src/GPU.cpp b/desmume/src/GPU.cpp index b95c304..84006de 100644 --- a/desmume/src/GPU.cpp +++ b/desmume/src/GPU.cpp @@ -1355,53 +1355,27 @@ static void lineNull(GPU *gpu) template void lineText(GPU *gpu) { - if(gpu->debug) - { - const s32 wh = gpu->BGSize[gpu->currBgNum][0]; - renderline_textBG(gpu, 0, gpu->currLine, wh); - } - else - { - const u16 vofs = gpu->getVOFS(gpu->currBgNum); - const u16 hofs = gpu->getHOFS(gpu->currBgNum); - renderline_textBG(gpu, hofs, gpu->currLine + vofs, 256); - } + const u16 vofs = gpu->getVOFS(gpu->currBgNum); + const u16 hofs = gpu->getHOFS(gpu->currBgNum); + renderline_textBG(gpu, hofs, gpu->currLine + vofs, 256); } template void lineRot(GPU *gpu) { - if (gpu->debug) - { - static const BGxPARMS debugParams = {256, 0, 0, -77, 0, (s16)gpu->currLine*GPU_FRAMEBUFFER_NATIVE_WIDTH}; - const s32 wh = gpu->BGSize[gpu->currBgNum][0]; - rotBG2(gpu, debugParams, wh); - } - else - { - BGxPARMS ¶ms = (gpu->currBgNum == 2) ? (gpu->dispx_st)->dispx_BG2PARMS : (gpu->dispx_st)->dispx_BG3PARMS; - - rotBG2(gpu, params, 256); - params.BGxX += params.BGxPB; - params.BGxY += params.BGxPD; - } + BGxPARMS ¶ms = (gpu->currBgNum == 2) ? (gpu->dispx_st)->dispx_BG2PARMS : (gpu->dispx_st)->dispx_BG3PARMS; + + rotBG2(gpu, params, 256); + params.BGxX += params.BGxPB; + params.BGxY += params.BGxPD; } template void lineExtRot(GPU *gpu) { - if (gpu->debug) - { - static BGxPARMS debugParams = {256, 0, 0, -77, 0, (s16)gpu->currLine*GPU_FRAMEBUFFER_NATIVE_WIDTH}; - const s32 wh = gpu->BGSize[gpu->currBgNum][0]; - extRotBG2(gpu, debugParams, wh); - } - else - { - BGxPARMS ¶ms = (gpu->currBgNum == 2) ? (gpu->dispx_st)->dispx_BG2PARMS : (gpu->dispx_st)->dispx_BG3PARMS; - - extRotBG2(gpu, params, 256); - params.BGxX += params.BGxPB; - params.BGxY += params.BGxPD; - } + BGxPARMS ¶ms = (gpu->currBgNum == 2) ? (gpu->dispx_st)->dispx_BG2PARMS : (gpu->dispx_st)->dispx_BG3PARMS; + + extRotBG2(gpu, params, 256); + params.BGxX += params.BGxPB; + params.BGxY += params.BGxPD; } /*****************************************************************************/ diff --git a/desmume/src/GPU.h b/desmume/src/GPU.h index e5b1576..1c82f10 100644 --- a/desmume/src/GPU.h +++ b/desmume/src/GPU.h @@ -615,16 +615,12 @@ enum GPULayerType struct GPU { GPU() - : debug(false) {} // some structs are becoming redundant // some functions too (no need to recopy some vars as it is done by MMU) REG_DISPx * dispx_st; - //this indicates whether this gpu is handling debug tools - bool debug; - CACHE_ALIGN u16 sprColor[GPU_FRAMEBUFFER_NATIVE_WIDTH]; CACHE_ALIGN u8 sprAlpha[GPU_FRAMEBUFFER_NATIVE_WIDTH]; CACHE_ALIGN u8 sprType[GPU_FRAMEBUFFER_NATIVE_WIDTH]; @@ -845,16 +841,6 @@ size_t GPU_GetFramebufferWidth(); size_t GPU_GetFramebufferHeight(); void GPU_SetFramebufferSize(size_t w, size_t h); -//these are functions used by debug tools which want to render layers etc outside the context of the emulation -namespace GPU_EXT -{ - void textBG(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 *dst_alpha, u8 *typeTab, u8 *prioTab); -void sprite2D(GPU *gpu, u16 l, u8 *dst, u8 *dst_alpha, u8 *typeTab, u8 *prioTab); - typedef struct { GPU *gpu; desmume/src/rasterize.cpp000664 001750 001750 00000200247 12755534123 016660 0ustar00sergiosergio000000 000000 /* Copyright (C) 2009-2015 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the this software. If not, see . */ //nothing in this file should be assumed to be accurate // //the shape rasterizers contained herein are based on code supplied by Chris Hecker from //http://chrishecker.com/Miscellaneous_Technical_Articles //TODO - due to a late change of a y-coord flipping, our winding order is wrong //this causes us to have to flip the verts for every front-facing poly. //a performance improvement would be to change the winding order logic //so that this is done less frequently #include "rasterize.h" #include #include #include #include #if defined(_MSC_VER) && _MSC_VER == 1600 #define SLEEP_HACK_2011 #endif #ifdef SLEEP_HACK_2011 #include #endif #ifndef _MSC_VER #include #endif #ifdef ENABLE_SSE2 #include #endif #ifdef ENABLE_SSSE3 #include #endif #include "common.h" #include "matrix.h" #include "render3D.h" #include "gfx3d.h" #include "texcache.h" #include "MMU.h" #include "NDSSystem.h" #include "utils/task.h" //#undef FORCEINLINE //#define FORCEINLINE //#undef INLINE //#define INLINE using std::min; using std::max; using std::swap; static u8 modulate_table[64][64]; static u8 decal_table[32][64][64]; static u8 index_lookup_table[65]; static u8 index_start_table[8]; typedef int fixed28_4; // handle floor divides and mods correctly static FORCEINLINE void FloorDivMod(long Numerator, long Denominator, long &Floor, long &Mod, bool& failure) { //These must be caused by invalid or degenerate shapes.. not sure yet. //check it out in the mario face intro of SM64 //so, we have to take out the assert. //I do know that we handle SOME invalid shapes without crashing, //since I see them acting poppy in a way that doesnt happen in the HW.. so alas it is also incorrect. //This particular incorrectness is not likely ever to get fixed! //assert(Denominator > 0); //but we have to bail out since our handling for these cases currently steps scanlines //the wrong way and goes totally nuts (freezes) if(Denominator<=0) failure = true; if(Numerator >= 0) { // positive case, C is okay Floor = Numerator / Denominator; Mod = Numerator % Denominator; } else { // Numerator is negative, do the right thing Floor = -((-Numerator) / Denominator); Mod = (-Numerator) % Denominator; if(Mod) { // there is a remainder Floor--; Mod = Denominator - Mod; } } } static FORCEINLINE fixed28_4 FloatToFixed28_4( float Value ) { return (fixed28_4)(Value * 16); } static FORCEINLINE float Fixed28_4ToFloat( fixed28_4 Value ) { return Value / 16.0f; } //inline fixed16_16 FloatToFixed16_16( float Value ) { // return (fixed16_6)(Value * 65536); //} //inline float Fixed16_16ToFloat( fixed16_16 Value ) { // return Value / 65536.0; //} static FORCEINLINE fixed28_4 Fixed28_4Mul( fixed28_4 A, fixed28_4 B ) { // could make this asm to prevent overflow return (A * B) / 16; // 28.4 * 28.4 = 24.8 / 16 = 28.4 } static FORCEINLINE int Ceil28_4( fixed28_4 Value ) { int ReturnValue; int Numerator = Value - 1 + 16; if(Numerator >= 0) { ReturnValue = Numerator/16; } else { // deal with negative numerators correctly ReturnValue = -((-Numerator)/16); ReturnValue -= ((-Numerator) % 16) ? 1 : 0; } return ReturnValue; } struct edge_fx_fl { edge_fx_fl() {} edge_fx_fl(int Top, int Bottom, VERT** verts, bool& failure); FORCEINLINE int Step(); VERT** verts; long X, XStep, Numerator, Denominator; // DDA info for x long ErrorTerm; int Y, Height; // current y and vertical count struct Interpolant { float curr, step, stepExtra; FORCEINLINE void doStep() { curr += step; } FORCEINLINE void doStepExtra() { curr += stepExtra; } FORCEINLINE void initialize(float value) { curr = value; step = 0; stepExtra = 0; } FORCEINLINE void initialize(float top, float bottom, float dx, float dy, long XStep, float XPrestep, float YPrestep) { dx = 0; dy *= (bottom-top); curr = top + YPrestep * dy + XPrestep * dx; step = XStep * dx + dy; stepExtra = dx; } }; static const int NUM_INTERPOLANTS = 7; union { struct { Interpolant invw,z,u,v,color[3]; }; Interpolant interpolants[NUM_INTERPOLANTS]; }; void FORCEINLINE doStepInterpolants() { for(int i=0;iverts = verts; Y = Ceil28_4((fixed28_4)verts[Top]->y); int YEnd = Ceil28_4((fixed28_4)verts[Bottom]->y); Height = YEnd - Y; X = Ceil28_4((fixed28_4)verts[Top]->x); int XEnd = Ceil28_4((fixed28_4)verts[Bottom]->x); int Width = XEnd - X; // can be negative // even if Height == 0, give some info for horizontal line poly if(Height != 0 || Width != 0) { long dN = long(verts[Bottom]->y - verts[Top]->y); long dM = long(verts[Bottom]->x - verts[Top]->x); if (dN != 0) { long InitialNumerator = (long)(dM*16*Y - dM*verts[Top]->y + dN*verts[Top]->x - 1 + dN*16); FloorDivMod(InitialNumerator,dN*16,X,ErrorTerm,failure); FloorDivMod(dM*16,dN*16,XStep,Numerator,failure); Denominator = dN*16; } else { XStep = Width; Numerator = 0; ErrorTerm = 0; Denominator = 1; dN = 1; } float YPrestep = Fixed28_4ToFloat((fixed28_4)(Y*16 - verts[Top]->y)); float XPrestep = Fixed28_4ToFloat((fixed28_4)(X*16 - verts[Top]->x)); float dy = 1/Fixed28_4ToFloat(dN); float dx = 1/Fixed28_4ToFloat(dM); invw.initialize(1/verts[Top]->w,1/verts[Bottom]->w,dx,dy,XStep,XPrestep,YPrestep); u.initialize(verts[Top]->u,verts[Bottom]->u,dx,dy,XStep,XPrestep,YPrestep); v.initialize(verts[Top]->v,verts[Bottom]->v,dx,dy,XStep,XPrestep,YPrestep); z.initialize(verts[Top]->z,verts[Bottom]->z,dx,dy,XStep,XPrestep,YPrestep); for(int i=0;i<3;i++) color[i].initialize(verts[Top]->fcolor[i],verts[Bottom]->fcolor[i],dx,dy,XStep,XPrestep,YPrestep); } else { // even if Width == 0 && Height == 0, give some info for pixel poly // example: Castlevania Portrait of Ruin, warp stone XStep = 1; Numerator = 0; Denominator = 1; ErrorTerm = 0; invw.initialize(1/verts[Top]->w); u.initialize(verts[Top]->u); v.initialize(verts[Top]->v); z.initialize(verts[Top]->z); for(int i=0;i<3;i++) color[i].initialize(verts[Top]->fcolor[i]); } } FORCEINLINE int edge_fx_fl::Step() { X += XStep; Y++; Height--; doStepInterpolants(); ErrorTerm += Numerator; if(ErrorTerm >= Denominator) { X++; ErrorTerm -= Denominator; doStepExtraInterpolants(); } return Height; } static FORCEINLINE void alphaBlend(FragmentColor &dst, const FragmentColor src) { if (src.a == 0) return; if (src.a == 31 || dst.a == 0 || !gfx3d.renderState.enableAlphaBlending) dst = src; else { const u8 alpha = src.a + 1; const u8 invAlpha = 32 - alpha; dst.r = (alpha*src.r + invAlpha*dst.r) >> 5; dst.g = (alpha*src.g + invAlpha*dst.g) >> 5; dst.b = (alpha*src.b + invAlpha*dst.b) >> 5; dst.a = max(src.a, dst.a); } } template class RasterizerUnit { protected: SoftRasterizerRenderer *_softRender; TexCacheItem *lastTexKey; VERT* verts[MAX_CLIPPED_VERTS]; int polynum; public: bool _debug_thisPoly; int SLI_MASK; int SLI_VALUE; void SetRenderer(SoftRasterizerRenderer *theRenderer) { this->_softRender = theRenderer; } struct Sampler { bool enabled; int width, height; s32 wmask, hmask; int wrap; int wshift; int texFormat; void setup(u32 texParam) { texFormat = (texParam>>26)&7; wshift = ((texParam>>20)&0x07) + 3; width=(1 << wshift); height=(8 << ((texParam>>23)&0x07)); wmask = width-1; hmask = height-1; wrap = (texParam>>16)&0xF; enabled = gfx3d.renderState.enableTexturing && (texFormat!=0); } FORCEINLINE void clamp(s32 &val, const int size, const s32 sizemask) { if(val<0) val = 0; if(val>sizemask) val = sizemask; } FORCEINLINE void hclamp(s32 &val) { clamp(val,width,wmask); } FORCEINLINE void vclamp(s32 &val) { clamp(val,height,hmask); } FORCEINLINE void repeat(s32 &val, const int size, const s32 sizemask) { val &= sizemask; } FORCEINLINE void hrepeat(s32 &val) { repeat(val,width,wmask); } FORCEINLINE void vrepeat(s32 &val) { repeat(val,height,hmask); } FORCEINLINE void flip(s32 &val, const int size, const s32 sizemask) { val &= ((size<<1)-1); if(val>=size) val = (size<<1)-val-1; } FORCEINLINE void hflip(s32 &val) { flip(val,width,wmask); } FORCEINLINE void vflip(s32 &val) { flip(val,height,hmask); } FORCEINLINE void dowrap(s32 &iu, s32 &iv) { switch (wrap) { //flip none case 0x0: hclamp(iu); vclamp(iv); break; case 0x1: hrepeat(iu); vclamp(iv); break; case 0x2: hclamp(iu); vrepeat(iv); break; case 0x3: hrepeat(iu); vrepeat(iv); break; //flip S case 0x4: hclamp(iu); vclamp(iv); break; case 0x5: hflip(iu); vclamp(iv); break; case 0x6: hclamp(iu); vrepeat(iv); break; case 0x7: hflip(iu); vrepeat(iv); break; //flip T case 0x8: hclamp(iu); vclamp(iv); break; case 0x9: hrepeat(iu); vclamp(iv); break; case 0xA: hclamp(iu); vflip(iv); break; case 0xB: hrepeat(iu); vflip(iv); break; //flip both case 0xC: hclamp(iu); vclamp(iv); break; case 0xD: hflip(iu); vclamp(iv); break; case 0xE: hclamp(iu); vflip(iv); break; case 0xF: hflip(iu); vflip(iv); break; } } } sampler; FORCEINLINE FragmentColor sample(const float u, const float v) { //finally, we can use floor here. but, it is slower than we want. //the best solution is probably to wait until the pipeline is full of fixed point s32 iu = 0; s32 iv = 0; if (!CommonSettings.GFX3D_TXTHack) { iu = s32floor(u); iv = s32floor(v); } else { iu = round_s(u); iv = round_s(v); } sampler.dowrap(iu, iv); FragmentColor color; color.color = ((u32*)lastTexKey->decoded)[(iv< 0.0) return floorf(val*256.0f+0.5f)/256.0f; //this value(256.0) is good result.(I think) return -1.0*floorf(fabs(val)*256.0f+0.5f)/256.0f; } FORCEINLINE void shade(const PolygonMode polygonMode, const FragmentColor src, FragmentColor &dst, const float texCoordU, const float texCoordV) { static const FragmentColor colorWhite = MakeFragmentColor(0x3F, 0x3F, 0x3F, 0x1F); const FragmentColor mainTexColor = (sampler.enabled) ? sample(texCoordU, texCoordV) : colorWhite; switch (polygonMode) { case POLYGON_MODE_MODULATE: dst.r = modulate_table[mainTexColor.r][src.r]; dst.g = modulate_table[mainTexColor.g][src.g]; dst.b = modulate_table[mainTexColor.b][src.b]; dst.a = modulate_table[GFX3D_5TO6(mainTexColor.a)][GFX3D_5TO6(src.a)]>>1; //dst.a = 28; //#ifdef _MSC_VER //if(GetAsyncKeyState(VK_SHIFT)) { // //debugging tricks // dst = shader.materialColor; // if(GetAsyncKeyState(VK_TAB)) { // u8 alpha = dst.a; // dst.color = polynum*8+8; // dst.a = alpha; // } //} //#endif break; case POLYGON_MODE_DECAL: { if (sampler.enabled) { dst.r = decal_table[mainTexColor.a][mainTexColor.r][src.r]; dst.g = decal_table[mainTexColor.a][mainTexColor.g][src.g]; dst.b = decal_table[mainTexColor.a][mainTexColor.b][src.b]; dst.a = src.a; } else { dst = src; } } break; case POLYGON_MODE_TOONHIGHLIGHT: { const FragmentColor toonColor = this->_softRender->toonColor32LUT[src.r >> 1]; if (gfx3d.renderState.shading == GFX3D_State::HIGHLIGHT) { // Tested in the "Shadows of Almia" logo in the Pokemon Ranger: Shadows of Almia title screen. // Also tested in Advance Wars: Dual Strike and Advance Wars: Days of Ruin when tiles highlight // during unit selection. dst.r = modulate_table[mainTexColor.r][src.r]; dst.g = modulate_table[mainTexColor.g][src.r]; dst.b = modulate_table[mainTexColor.b][src.r]; dst.a = modulate_table[GFX3D_5TO6(mainTexColor.a)][GFX3D_5TO6(src.a)] >> 1; dst.r = min(0x3F, (dst.r + toonColor.r)); dst.g = min(0x3F, (dst.g + toonColor.g)); dst.b = min(0x3F, (dst.b + toonColor.b)); } else { dst.r = modulate_table[mainTexColor.r][toonColor.r]; dst.g = modulate_table[mainTexColor.g][toonColor.g]; dst.b = modulate_table[mainTexColor.b][toonColor.b]; dst.a = modulate_table[GFX3D_5TO6(mainTexColor.a)][GFX3D_5TO6(src.a)] >> 1; } } break; case POLYGON_MODE_SHADOW: //is this right? only with the material color? dst = src; break; } } template FORCEINLINE void pixel(const PolygonAttributes &polyAttr, const size_t fragmentIndex, FragmentColor &dstColor, float r, float g, float b, float invu, float invv, float w, float z) { FragmentColor srcColor; FragmentColor shaderOutput; bool isOpaquePixel; u32 &dstAttributeDepth = this->_softRender->_framebufferAttributes->depth[fragmentIndex]; u8 &dstAttributeOpaquePolyID = this->_softRender->_framebufferAttributes->opaquePolyID[fragmentIndex]; u8 &dstAttributeTranslucentPolyID = this->_softRender->_framebufferAttributes->translucentPolyID[fragmentIndex]; u8 &dstAttributeStencil = this->_softRender->_framebufferAttributes->stencil[fragmentIndex]; u8 &dstAttributeIsFogged = this->_softRender->_framebufferAttributes->isFogged[fragmentIndex]; u8 &dstAttributeIsTranslucentPoly = this->_softRender->_framebufferAttributes->isTranslucentPoly[fragmentIndex]; // not sure about the w-buffer depth value: this value was chosen to make the skybox, castle window decals, and water level render correctly in SM64 // hack: when using z-depth, drop some LSBs so that the overworld map in Dragon Quest IV shows up correctly const u32 newDepth = (gfx3d.renderState.wbuffer) ? u32floor(4096*w) : DS_DEPTH15TO24( u32floor(z*0x7FFF) ) & 0x00FFFFFC; // run the depth test if (polyAttr.enableDepthEqualTest) { const u32 minDepth = max(0x00000000, dstAttributeDepth - SOFTRASTERIZER_DEPTH_EQUAL_TEST_TOLERANCE); const u32 maxDepth = min(0x00FFFFFF, dstAttributeDepth + SOFTRASTERIZER_DEPTH_EQUAL_TEST_TOLERANCE); if (newDepth < minDepth || newDepth > maxDepth) { goto depth_fail; } } else { if (newDepth >= dstAttributeDepth) goto depth_fail; } //handle shadow polys if (isShadowPolygon) { if (polyAttr.polygonID == 0) goto rejected_fragment; else { if (dstAttributeStencil == 0) goto rejected_fragment; //shadow polys have a special check here to keep from self-shadowing when user //has tried to prevent it from happening //if this isnt here, then the vehicle select in mariokart will look terrible if (dstAttributeOpaquePolyID == polyAttr.polygonID) goto rejected_fragment; } } //perspective-correct the colors r = (r * w) + 0.5f; g = (g * w) + 0.5f; b = (b * w) + 0.5f; //this is a HACK: //we are being very sloppy with our interpolation precision right now //and rather than fix it, i just want to clamp it srcColor = MakeFragmentColor(max(0x00, min(0x3F,u32floor(r))), max(0x00, min(0x3F,u32floor(g))), max(0x00, min(0x3F,u32floor(b))), polyAttr.alpha); //pixel shader shade(polyAttr.polygonMode, srcColor, shaderOutput, invu * w, invv * w); // handle alpha test if ( shaderOutput.a == 0 || (this->_softRender->currentRenderState->enableAlphaTest && shaderOutput.a < this->_softRender->currentRenderState->alphaTestRef) ) { goto rejected_fragment; } // write pixel values to the framebuffer isOpaquePixel = (shaderOutput.a == 0x1F); if (isOpaquePixel) { dstAttributeOpaquePolyID = polyAttr.polygonID; dstAttributeIsTranslucentPoly = polyAttr.isTranslucent; dstAttributeIsFogged = polyAttr.enableRenderFog; dstColor = shaderOutput; } else { //dont overwrite pixels on translucent polys with the same polyids if (dstAttributeTranslucentPolyID == polyAttr.polygonID) goto rejected_fragment; //originally we were using a test case of shadows-behind-trees in sm64ds //but, it looks bad in that game. this is actually correct //if this isnt correct, then complex shape cart shadows in mario kart don't work right dstAttributeTranslucentPolyID = polyAttr.polygonID; //alpha blending and write color alphaBlend(dstColor, shaderOutput); dstAttributeIsFogged = (dstAttributeIsFogged && polyAttr.enableRenderFog); } //depth writing if (isOpaquePixel || polyAttr.enableAlphaDepthWrite) dstAttributeDepth = newDepth; //shadow cases: (need multi-bit stencil buffer to cope with all of these, especially the mariokart complex shadows) //1. sm64 (standing near signs and blocks) //2. mariokart (no glitches in shadow shape in kart selector) //3. mariokart (no junk beneath platform in kart selector / no shadow beneath grate floor in bowser stage) //(specifically, the shadows in mario kart are complicated concave shapes) goto done; depth_fail: if (isShadowPolygon && polyAttr.polygonID == 0) dstAttributeStencil++; rejected_fragment: done: ; if (isShadowPolygon && polyAttr.polygonID != 0 && dstAttributeStencil) dstAttributeStencil--; } //draws a single scanline template FORCEINLINE void drawscanline(const PolygonAttributes &polyAttr, FragmentColor *dstColor, const size_t framebufferWidth, const size_t framebufferHeight, edge_fx_fl *pLeft, edge_fx_fl *pRight, bool lineHack) { int XStart = pLeft->X; int width = pRight->X - XStart; // HACK: workaround for vertical/slant line poly if (lineHack && width == 0) { int leftWidth = pLeft->XStep; if (pLeft->ErrorTerm + pLeft->Numerator >= pLeft->Denominator) leftWidth++; int rightWidth = pRight->XStep; if (pRight->ErrorTerm + pRight->Numerator >= pRight->Denominator) rightWidth++; width = max(1, max(abs(leftWidth), abs(rightWidth))); } //these are the starting values, taken from the left edge float invw = pLeft->invw.curr; float u = pLeft->u.curr; float v = pLeft->v.curr; float z = pLeft->z.curr; float color[3] = { pLeft->color[0].curr, pLeft->color[1].curr, pLeft->color[2].curr }; //our dx values are taken from the steps up until the right edge float invWidth = 1.0f / width; float dinvw_dx = (pRight->invw.curr - invw) * invWidth; float du_dx = (pRight->u.curr - u) * invWidth; float dv_dx = (pRight->v.curr - v) * invWidth; float dz_dx = (pRight->z.curr - z) * invWidth; float dc_dx[3] = { (pRight->color[0].curr - color[0]) * invWidth, (pRight->color[1].curr - color[1]) * invWidth, (pRight->color[2].curr - color[2]) * invWidth }; size_t adr = (pLeft->Y*framebufferWidth)+XStart; //CONSIDER: in case some other math is wrong (shouldve been clipped OK), we might go out of bounds here. //better check the Y value. if (RENDERER && (pLeft->Y < 0 || pLeft->Y > (framebufferHeight - 1))) { printf("rasterizer rendering at y=%d! oops!\n",pLeft->Y); return; } if (!RENDERER && (pLeft->Y < 0 || pLeft->Y >= framebufferHeight)) { printf("rasterizer rendering at y=%d! oops!\n",pLeft->Y); return; } int x = XStart; if (x < 0) { if (RENDERER && !lineHack) { printf("rasterizer rendering at x=%d! oops!\n",x); return; } invw += dinvw_dx * -x; u += du_dx * -x; v += dv_dx * -x; z += dz_dx * -x; color[0] += dc_dx[0] * -x; color[1] += dc_dx[1] * -x; color[2] += dc_dx[2] * -x; adr += -x; width -= -x; x = 0; } if (x+width > framebufferWidth) { if (RENDERER && !lineHack && framebufferWidth == GPU_FRAMEBUFFER_NATIVE_WIDTH) { printf("rasterizer rendering at x=%d! oops!\n",x+width-1); return; } width = framebufferWidth - x; } while (width-- > 0) { pixel(polyAttr, adr, dstColor[adr], color[0], color[1], color[2], u, v, 1.0f/invw, z); adr++; x++; invw += dinvw_dx; u += du_dx; v += dv_dx; z += dz_dx; color[0] += dc_dx[0]; color[1] += dc_dx[1]; color[2] += dc_dx[2]; } } //runs several scanlines, until an edge is finished template void runscanlines(const PolygonAttributes &polyAttr, FragmentColor *dstColor, const size_t framebufferWidth, const size_t framebufferHeight, edge_fx_fl *left, edge_fx_fl *right, bool horizontal, bool lineHack) { //oh lord, hack city for edge drawing //do not overstep either of the edges int Height = min(left->Height,right->Height); bool first=true; //HACK: special handling for horizontal line poly if (lineHack && left->Height == 0 && right->Height == 0 && left->YY>=0) { bool draw = (!SLI || (left->Y & SLI_MASK) == SLI_VALUE); if(draw) drawscanline(polyAttr, dstColor, framebufferWidth, framebufferHeight, left,right,lineHack); } while(Height--) { bool draw = (!SLI || (left->Y & SLI_MASK) == SLI_VALUE); if(draw) drawscanline(polyAttr, dstColor, framebufferWidth, framebufferHeight, left,right,lineHack); const int xl = left->X; const int xr = right->X; const int y = left->Y; left->Step(); right->Step(); if(!RENDERER && _debug_thisPoly) { //debug drawing bool top = (horizontal&&first); bool bottom = (!Height&&horizontal); if(Height || top || bottom) { if(draw) { int nxl = left->X; int nxr = right->X; if(top) { int xs = min(xl,xr); int xe = max(xl,xr); for (int x = xs; x <= xe; x++) { int adr = (y*framebufferWidth)+x; dstColor[adr].r = 63; dstColor[adr].g = 0; dstColor[adr].b = 0; } } else if(bottom) { int xs = min(xl,xr); int xe = max(xl,xr); for (int x = xs; x <= xe; x++) { int adr = (y*framebufferWidth)+x; dstColor[adr].r = 63; dstColor[adr].g = 0; dstColor[adr].b = 0; } } else { int xs = min(xl,nxl); int xe = max(xl,nxl); for (int x = xs; x <= xe; x++) { int adr = (y*framebufferWidth)+x; dstColor[adr].r = 63; dstColor[adr].g = 0; dstColor[adr].b = 0; } xs = min(xr,nxr); xe = max(xr,nxr); for (int x = xs; x <= xe; x++) { int adr = (y*framebufferWidth)+x; dstColor[adr].r = 63; dstColor[adr].g = 0; dstColor[adr].b = 0; } } } } first = false; } } } //rotates verts counterclockwise template INLINE void rot_verts() { #define ROTSWAP(X) if(type>X) swap(verts[X-1],verts[X]); ROTSWAP(1); ROTSWAP(2); ROTSWAP(3); ROTSWAP(4); ROTSWAP(5); ROTSWAP(6); ROTSWAP(7); ROTSWAP(8); ROTSWAP(9); } //rotate verts until vert0.y is minimum, and then vert0.x is minimum in case of ties //this is a necessary precondition for our shape engine template void sort_verts(bool backwards) { //if the verts are backwards, reorder them first if (backwards) for (size_t i = 0; i < type/2; i++) swap(verts[i],verts[type-i-1]); for (;;) { //this was the only way we could get this to unroll #define CHECKY(X) if(type>X) if(verts[0]->y > verts[X]->y) goto doswap; CHECKY(1); CHECKY(2); CHECKY(3); CHECKY(4); CHECKY(5); CHECKY(6); CHECKY(7); CHECKY(8); CHECKY(9); break; doswap: rot_verts(); } while (verts[0]->y == verts[1]->y && verts[0]->x > verts[1]->x) { rot_verts(); // hack for VC++ 2010 (bug in compiler optimization?) // freeze on 3D // TODO: study it #ifdef SLEEP_HACK_2011 Sleep(0); // nop #endif } } //This function can handle any convex N-gon up to octagons //verts must be clockwise. //I didnt reference anything for this algorithm but it seems like I've seen it somewhere before. //Maybe it is like crow's algorithm template void shape_engine(const PolygonAttributes &polyAttr, FragmentColor *dstColor, const size_t framebufferWidth, const size_t framebufferHeight, int type, const bool backwards, bool lineHack) { bool failure = false; switch(type) { case 3: sort_verts<3>(backwards); break; case 4: sort_verts<4>(backwards); break; case 5: sort_verts<5>(backwards); break; case 6: sort_verts<6>(backwards); break; case 7: sort_verts<7>(backwards); break; case 8: sort_verts<8>(backwards); break; case 9: sort_verts<9>(backwards); break; case 10: sort_verts<10>(backwards); break; default: printf("skipping type %d\n",type); return; } //we are going to step around the polygon in both directions starting from vert 0. //right edges will be stepped over clockwise and left edges stepped over counterclockwise. //these variables track that stepping, but in order to facilitate wrapping we start extra high //for the counter we're decrementing. int lv = type, rv = 0; edge_fx_fl left, right; bool step_left = true, step_right = true; for (;;) { //generate new edges if necessary. we must avoid regenerating edges when they are incomplete //so that they can be continued on down the shape assert(rv != type); int _lv = lv==type?0:lv; //make sure that we ask for vert 0 when the variable contains the starting value if (step_left) left = edge_fx_fl(_lv,lv-1,(VERT**)&verts, failure); if (step_right) right = edge_fx_fl(rv,rv+1,(VERT**)&verts, failure); step_left = step_right = false; //handle a failure in the edge setup due to nutty polys if(failure) return; bool horizontal = left.Y == right.Y; runscanlines(polyAttr, dstColor, framebufferWidth, framebufferHeight, &left, &right, horizontal, lineHack); //if we ran out of an edge, step to the next one if (right.Height == 0) { step_right = true; rv++; } if (left.Height == 0) { step_left = true; lv--; } //this is our completion condition: when our stepped edges meet in the middle if (lv<=rv+1) break; } } template FORCEINLINE void mainLoop() { const size_t polyCount = this->_softRender->_clippedPolyCount; if (polyCount == 0) { return; } FragmentColor *dstColor = this->_softRender->GetFramebuffer(); const size_t dstWidth = this->_softRender->GetFramebufferWidth(); const size_t dstHeight = this->_softRender->GetFramebufferHeight(); lastTexKey = NULL; const GFX3D_Clipper::TClippedPoly &firstClippedPoly = this->_softRender->clippedPolys[0]; const POLY &firstPoly = *firstClippedPoly.poly; PolygonAttributes polyAttr = firstPoly.getAttributes(); u32 lastPolyAttr = firstPoly.polyAttr; u32 lastTexParams = firstPoly.texParam; u32 lastTexPalette = firstPoly.texPalette; sampler.setup(firstPoly.texParam); //iterate over polys for (size_t i = 0; i < polyCount; i++) { if (!RENDERER) _debug_thisPoly = (i == this->_softRender->_debug_drawClippedUserPoly); if (!this->_softRender->polyVisible[i]) continue; polynum = i; GFX3D_Clipper::TClippedPoly &clippedPoly = this->_softRender->clippedPolys[i]; const POLY &thePoly = *clippedPoly.poly; const PolygonType type = clippedPoly.type; if (lastPolyAttr != thePoly.polyAttr) { polyAttr = thePoly.getAttributes(); lastPolyAttr = thePoly.polyAttr; } if (lastTexParams != thePoly.texParam || lastTexPalette != thePoly.texPalette) { sampler.setup(thePoly.texParam); lastTexParams = thePoly.texParam; lastTexPalette = thePoly.texPalette; } lastTexKey = this->_softRender->polyTexKeys[i]; for (int j = 0; j < type; j++) this->verts[j] = &clippedPoly.clipVerts[j]; for (int j = type; j < MAX_CLIPPED_VERTS; j++) this->verts[j] = NULL; if (polyAttr.polygonMode == POLYGON_MODE_SHADOW) { shape_engine(polyAttr, dstColor, dstWidth, dstHeight, type, !this->_softRender->polyBackfacing[i], (thePoly.vtxFormat & 4) && CommonSettings.GFX3D_LineHack); } else { shape_engine(polyAttr, dstColor, dstWidth, dstHeight, type, !this->_softRender->polyBackfacing[i], (thePoly.vtxFormat & 4) && CommonSettings.GFX3D_LineHack); } } } }; //rasterizerUnit #define _MAX_CORES 16 static Task rasterizerUnitTask[_MAX_CORES]; static RasterizerUnit rasterizerUnit[_MAX_CORES]; static RasterizerUnit _HACK_viewer_rasterizerUnit; static size_t rasterizerCores = 0; static bool rasterizerUnitTasksInited = false; static void* execRasterizerUnit(void *arg) { intptr_t which = (intptr_t)arg; rasterizerUnit[which].mainLoop(); return 0; } static void* SoftRasterizer_RunCalculateVertices(void *arg) { SoftRasterizerRenderer *softRender = (SoftRasterizerRenderer *)arg; softRender->performViewportTransforms(); softRender->performBackfaceTests(); softRender->performCoordAdjustment(); return NULL; } static void* SoftRasterizer_RunSetupTextures(void *arg) { SoftRasterizerRenderer *softRender = (SoftRasterizerRenderer *)arg; softRender->setupTextures(); return NULL; } static void* SoftRasterizer_RunUpdateTables(void *arg) { SoftRasterizerRenderer *softRender = (SoftRasterizerRenderer *)arg; softRender->UpdateToonTable(softRender->currentRenderState->u16ToonTable); softRender->UpdateFogTable(softRender->currentRenderState->fogDensityTable); softRender->UpdateEdgeMarkColorTable(softRender->currentRenderState->edgeMarkColorTable); return NULL; } static void* SoftRasterizer_RunClearFramebuffer(void *arg) { SoftRasterizerRenderer *softRender = (SoftRasterizerRenderer *)arg; softRender->ClearFramebuffer(*softRender->currentRenderState); return NULL; } static void* SoftRasterizer_RunRenderEdgeMarkAndFog(void *arg) { SoftRasterizerPostProcessParams *params = (SoftRasterizerPostProcessParams *)arg; params->renderer->RenderEdgeMarkingAndFog(*params); return NULL; } void _HACK_Viewer_ExecUnit() { _HACK_viewer_rasterizerUnit.mainLoop(); } static Render3D* SoftRasterizerRendererCreate() { #if defined(ENABLE_SSSE3) return new SoftRasterizerRenderer_SSSE3; #elif defined(ENABLE_SSE2) return new SoftRasterizerRenderer_SSE2; #else return new SoftRasterizerRenderer; #endif } static void SoftRasterizerRendererDestroy() { if (CurrentRenderer != BaseRenderer) { #if defined(ENABLE_SSSE3) delete (SoftRasterizerRenderer_SSSE3 *)CurrentRenderer; #elif defined(ENABLE_SSE2) delete (SoftRasterizerRenderer_SSE2 *)CurrentRenderer; #else delete (SoftRasterizerRenderer *)CurrentRenderer; #endif CurrentRenderer = BaseRenderer; } } GPU3DInterface gpu3DRasterize = { "SoftRasterizer", SoftRasterizerRendererCreate, SoftRasterizerRendererDestroy }; SoftRasterizerRenderer::SoftRasterizerRenderer() { _renderID = RENDERID_SOFTRASTERIZER; _renderName = "SoftRasterizer"; _debug_drawClippedUserPoly = -1; clippedPolys = clipper.clippedPolys = new GFX3D_Clipper::TClippedPoly[POLYLIST_SIZE*2]; _stateSetupNeedsFinish = false; _renderGeometryNeedsFinish = false; _framebufferAttributes = NULL; if (!rasterizerUnitTasksInited) { _HACK_viewer_rasterizerUnit._debug_thisPoly = false; _HACK_viewer_rasterizerUnit.SLI_MASK = 1; _HACK_viewer_rasterizerUnit.SLI_VALUE = 0; rasterizerCores = CommonSettings.num_cores; if (rasterizerCores > _MAX_CORES) rasterizerCores = _MAX_CORES; if (rasterizerCores == 0 || rasterizerCores == 1) { rasterizerCores = 1; rasterizerUnit[0]._debug_thisPoly = false; rasterizerUnit[0].SLI_MASK = 0; rasterizerUnit[0].SLI_VALUE = 0; postprocessParam = new SoftRasterizerPostProcessParams[rasterizerCores]; postprocessParam[0].renderer = this; postprocessParam[0].startLine = 0; postprocessParam[0].endLine = _framebufferHeight; postprocessParam[0].enableEdgeMarking = true; postprocessParam[0].enableFog = true; postprocessParam[0].fogColor = 0x80FFFFFF; postprocessParam[0].fogAlphaOnly = false; } else { const size_t linesPerThread = _framebufferHeight / rasterizerCores; postprocessParam = new SoftRasterizerPostProcessParams[rasterizerCores]; for (size_t i = 0; i < rasterizerCores; i++) { rasterizerUnit[i]._debug_thisPoly = false; rasterizerUnit[i].SLI_MASK = (rasterizerCores - 1); rasterizerUnit[i].SLI_VALUE = i; rasterizerUnitTask[i].start(); postprocessParam[i].renderer = this; postprocessParam[i].startLine = i * linesPerThread; postprocessParam[i].endLine = (i < rasterizerCores - 1) ? (i + 1) * linesPerThread : _framebufferHeight; postprocessParam[i].enableEdgeMarking = true; postprocessParam[i].enableFog = true; postprocessParam[i].fogColor = 0x80FFFFFF; postprocessParam[i].fogAlphaOnly = false; } } rasterizerUnitTasksInited = true; } InitTables(); Reset(); printf("SoftRast Initialized with cores=%d\n", (int)rasterizerCores); } SoftRasterizerRenderer::~SoftRasterizerRenderer() { if (rasterizerCores > 1) { for (size_t i = 0; i < rasterizerCores; i++) { rasterizerUnitTask[i].finish(); rasterizerUnitTask[i].shutdown(); } } rasterizerUnitTasksInited = false; delete[] postprocessParam; postprocessParam = NULL; delete _framebufferAttributes; _framebufferAttributes = NULL; } Render3DError SoftRasterizerRenderer::InitTables() { static bool needTableInit = true; if (needTableInit) { for (size_t i = 0; i < 64; i++) { for (size_t j = 0; j < 64; j++) { modulate_table[i][j] = ((i+1) * (j+1) - 1) >> 6; for (size_t a = 0; a < 32; a++) decal_table[a][i][j] = ((i*a) + (j*(31-a))) >> 5; } } //these tables are used to increment through vert lists without having to do wrapping logic/math u8 idx = 0; for (u8 i = 3; i <= 8; i++) { index_start_table[i-3] = idx; for (u8 j = 0; j < i; j++) { u8 a = j; u8 b = j+1; if (b == i) b = 0; index_lookup_table[idx++] = a; index_lookup_table[idx++] = b; } } needTableInit = false; } return RENDER3DERROR_NOERR; } template size_t SoftRasterizerRenderer::performClipping(const VERTLIST *vertList, const POLYLIST *polyList, const INDEXLIST *indexList) { //submit all polys to clipper clipper.reset(); for (size_t i = 0; i < polyList->count; i++) { const POLY &poly = polyList->list[indexList->list[i]]; const VERT *clipVerts[4] = { &vertList->list[poly.vertIndexes[0]], &vertList->list[poly.vertIndexes[1]], &vertList->list[poly.vertIndexes[2]], poly.type==POLYGON_TYPE_QUAD ?&vertList->list[poly.vertIndexes[3]] :NULL }; clipper.clipPoly(poly, clipVerts); } return clipper.clippedPolyCounter; } template void SoftRasterizerRenderer::performViewportTransforms() { size_t i; const float xfactor = (float)this->_framebufferWidth/(float)GPU_FRAMEBUFFER_NATIVE_WIDTH; const float yfactor = (float)this->_framebufferHeight/(float)GPU_FRAMEBUFFER_NATIVE_HEIGHT; const float xmax = (float)this->_framebufferWidth-(CUSTOM?0.001f:0); //fudge factor to keep from overrunning render buffers const float ymax = (float)this->_framebufferHeight-(CUSTOM?0.001f:0); /* viewport transforms */ for (i = 0; i < this->_clippedPolyCount; i++) { GFX3D_Clipper::TClippedPoly &poly = clippedPolys[i]; for (size_t j = 0; j < poly.type; j++) { VIEWPORT viewport; VERT &vert = poly.clipVerts[j]; /* homogeneous divide */ vert.coord[0] = (vert.coord[0]+vert.coord[3]) / (2*vert.coord[3]); vert.coord[1] = (vert.coord[1]+vert.coord[3]) / (2*vert.coord[3]); vert.coord[2] = (vert.coord[2]+vert.coord[3]) / (2*vert.coord[3]); vert.texcoord[0] /= vert.coord[3]; vert.texcoord[1] /= vert.coord[3]; //CONSIDER: do we need to guarantee that these are in bounds? perhaps not. //vert.coord[0] = max(0.0f,min(1.0f,vert.coord[0])); //vert.coord[1] = max(0.0f,min(1.0f,vert.coord[1])); //vert.coord[2] = max(0.0f,min(1.0f,vert.coord[2])); //perspective-correct the colors vert.fcolor[0] /= vert.coord[3]; vert.fcolor[1] /= vert.coord[3]; vert.fcolor[2] /= vert.coord[3]; //viewport transformation viewport.decode(poly.poly->viewport); vert.coord[0] *= viewport.width * xfactor; vert.coord[0] += viewport.x * xfactor; vert.coord[1] *= viewport.height * yfactor; vert.coord[1] += viewport.y * yfactor; vert.coord[1] = ymax - vert.coord[1]; //well, i guess we need to do this to keep Princess Debut from rendering huge polys. //there must be something strange going on vert.coord[0] = max(0.0f,min(xmax,vert.coord[0])); vert.coord[1] = max(0.0f,min(ymax,vert.coord[1])); } } } //these templates needed to be instantiated manually template void SoftRasterizerRenderer::performViewportTransforms(); template void SoftRasterizerRenderer::performViewportTransforms(); void SoftRasterizerRenderer::performCoordAdjustment() { size_t i; for (i = 0; i < this->_clippedPolyCount; i++) { size_t j, k; GFX3D_Clipper::TClippedPoly &clippedPoly = clippedPolys[i]; const PolygonType type = clippedPoly.type; VERT *verts = &clippedPoly.clipVerts[0]; //here is a hack which needs to be removed. //at some point our shape engine needs these to be converted to "fixed point" //which is currently just a float for (j = 0; j < type; j++) for (k = 0; k < 2; k++) verts[j].coord[k] = (float)(int)(16.0f * verts[j].coord[k]); } } void SoftRasterizerRenderer::setupTextures() { size_t i; if (this->_clippedPolyCount == 0) return; const GFX3D_Clipper::TClippedPoly &firstClippedPoly = this->clippedPolys[0]; const POLY &firstPoly = *firstClippedPoly.poly; u32 lastTexParams = firstPoly.texParam; u32 lastTexPalette = firstPoly.texPalette; TexCacheItem *lastTexKey = TexCache_SetTexture(TexFormat_15bpp, firstPoly.texParam, firstPoly.texPalette); for (i = 0; i < this->_clippedPolyCount; i++) { const GFX3D_Clipper::TClippedPoly &clippedPoly = clippedPolys[i]; const POLY &thePoly = *clippedPoly.poly; //make sure all the textures we'll need are cached //(otherwise on a multithreaded system there will be multiple writers-- //this SHOULD be read-only, although some day the texcache may collect statistics or something //and then it won't be safe. if (lastTexParams != thePoly.texParam || lastTexPalette != thePoly.texPalette) { lastTexKey = TexCache_SetTexture(TexFormat_15bpp, thePoly.texParam, thePoly.texPalette); lastTexParams = thePoly.texParam; lastTexPalette = thePoly.texPalette; } //printf("%08X %d\n",poly->texParam,rasterizerUnit[0].textures.currentNum); polyTexKeys[i] = lastTexKey; } } bool PolygonIsVisible(const PolygonAttributes &polyAttr, const bool backfacing) { //this was added after adding multi-bit stencil buffer //it seems that we also need to prevent drawing back faces of shadow polys for rendering if (polyAttr.polygonMode == POLYGON_MODE_SHADOW && polyAttr.polygonID != 0) return !backfacing; //another reasonable possibility is that we should be forcing back faces to draw (mariokart doesnt use them) //and then only using a single bit buffer (but a cursory test of this doesnt actually work) // //this code needs to be here for shadows in wizard of oz to work. switch (polyAttr.surfaceCullingMode) { case 0: break; case 1: return backfacing; case 2: return !backfacing; case 3: return true; default: assert(false); break; } return false; } void SoftRasterizerRenderer::performBackfaceTests() { size_t i; for (i = 0; i < this->_clippedPolyCount; i++) { size_t j; const GFX3D_Clipper::TClippedPoly &clippedPoly = clippedPolys[i]; const POLY &thePoly = *clippedPoly.poly; const PolygonType type = clippedPoly.type; const VERT *verts = &clippedPoly.clipVerts[0]; const PolygonAttributes polyAttr = thePoly.getAttributes(); //HACK: backface culling //this should be moved to gfx3d, but first we need to redo the way the lists are built //because it is too convoluted right now. //(must we throw out verts if a poly gets backface culled? if not, then it might be easier) //an older approach //(not good enough for quads and other shapes) //float ab[2], ac[2]; Vector2Copy(ab, verts[1].coord); Vector2Copy(ac, verts[2].coord); Vector2Subtract(ab, verts[0].coord); //Vector2Subtract(ac, verts[0].coord); float cross = Vector2Cross(ab, ac); polyAttr.backfacing = (cross>0); //a better approach // we have to support somewhat non-convex polygons (see NSMB world map 1st screen). // this version should handle those cases better. const size_t n = type - 1; float facing = (verts[0].y + verts[n].y) * (verts[0].x - verts[n].x) + (verts[1].y + verts[0].y) * (verts[1].x - verts[0].x) + (verts[2].y + verts[1].y) * (verts[2].x - verts[1].x); for (j = 2; j < n; j++) facing += (verts[j+1].y + verts[j].y) * (verts[j+1].x - verts[j].x); polyBackfacing[i] = (facing < 0); polyVisible[i] = PolygonIsVisible(polyAttr, polyBackfacing[i]); } } Render3DError SoftRasterizerRenderer::BeginRender(const GFX3D &engine) { if (rasterizerCores > 1) { size_t i; /* Force all threads to finish before rendering with new data */ for (i = 0; i < rasterizerCores; i++) rasterizerUnitTask[i].finish(); } // Keep the current render states for later use this->currentRenderState = (GFX3D_State *)&engine.renderState; if (CommonSettings.GFX3D_HighResolutionInterpolateColor) this->_clippedPolyCount = this->performClipping(engine.vertlist, engine.polylist, &engine.indexlist); else this->_clippedPolyCount = this->performClipping(engine.vertlist, engine.polylist, &engine.indexlist); if (rasterizerCores >= 4) { rasterizerUnitTask[0].execute(&SoftRasterizer_RunCalculateVertices, this); rasterizerUnitTask[1].execute(&SoftRasterizer_RunSetupTextures, this); rasterizerUnitTask[2].execute(&SoftRasterizer_RunUpdateTables, this); rasterizerUnitTask[3].execute(&SoftRasterizer_RunClearFramebuffer, this); this->_stateSetupNeedsFinish = true; } else { this->performViewportTransforms(); this->performBackfaceTests(); this->performCoordAdjustment(); this->setupTextures(); this->UpdateToonTable(engine.renderState.u16ToonTable); if (this->currentRenderState->enableEdgeMarking) this->UpdateEdgeMarkColorTable(this->currentRenderState->edgeMarkColorTable); if (this->currentRenderState->enableFog) this->UpdateFogTable(this->currentRenderState->fogDensityTable); this->ClearFramebuffer(engine.renderState); this->_stateSetupNeedsFinish = false; } return RENDER3DERROR_NOERR; } Render3DError SoftRasterizerRenderer::RenderGeometry( const GFX3D_State &renderState, const POLYLIST *polyList, const INDEXLIST *indexList) { /* If multithreaded, allow for states to finish setting up */ if (this->_stateSetupNeedsFinish) { rasterizerUnitTask[0].finish(); rasterizerUnitTask[1].finish(); rasterizerUnitTask[2].finish(); rasterizerUnitTask[3].finish(); this->_stateSetupNeedsFinish = false; } // Render the geometry if (rasterizerCores > 1) { size_t i; for (i = 0; i < rasterizerCores; i++) rasterizerUnitTask[i].execute(&execRasterizerUnit, (void *)i); this->_renderGeometryNeedsFinish = true; } else { rasterizerUnit[0].mainLoop(); this->_renderGeometryNeedsFinish = false; TexCache_EvictFrame(); // Since we're finishing geometry rendering here and now, also check the texture cache now. } // printf("rendered %d of %d polys after backface culling\n",gfx3d.polylist->count-culled,gfx3d.polylist->count); return RENDER3DERROR_NOERR; } // This method is currently unused right now, in favor of the new multithreaded // SoftRasterizerRenderer::RenderEdgeMarkingAndFog() method. But let's keep this // one around for reference just in case something goes horribly wrong with the // new multithreaded method. Render3DError SoftRasterizerRenderer::RenderEdgeMarking(const u16 *colorTable, const bool useAntialias) { size_t i, x, y, r; // TODO: Old edge marking algorithm which tests only polyID, but checks the 8 surrounding pixels. Can this be removed? // this looks ok although it's still pretty much a hack, // it needs to be redone with low-level accuracy at some point, // but that should probably wait until the shape renderer is more accurate. // a good test case for edge marking is Sonic Rush: // - the edges are completely sharp/opaque on the very brief title screen intro, // - the level-start intro gets a pseudo-antialiasing effect around the silhouette, // - the character edges in-level are clearly transparent, and also show well through shield powerups. y = 0; for (i = 0; y < this->_framebufferHeight; y++) { for (x = 0; x < this->_framebufferWidth; x++, i++) { const u8 polyID = this->_framebufferAttributes->opaquePolyID[i]; if (this->edgeMarkDisabled[polyID>>3]) continue; if (this->_framebufferAttributes->isTranslucentPoly[i] != 0) continue; // > is used instead of != to prevent double edges // between overlapping polys of different IDs. // also note that the edge generally goes on the outside, not the inside, (maybe needs to change later) // and that polys with the same edge color can make edges against each other. const FragmentColor edgeColor = this->edgeMarkTable[polyID>>3]; #define PIXOFFSET(dx,dy) ((dx)+(this->_framebufferWidth*(dy))) #define ISEDGE(dx,dy) ((x+(dx) < this->_framebufferWidth) && (y+(dy) < this->_framebufferHeight) && polyID > this->_framebufferAttributes->opaquePolyID[i+PIXOFFSET(dx,dy)]) #define DRAWEDGE(dx,dy) alphaBlend(_framebufferColor[i+PIXOFFSET(dx,dy)], edgeColor) bool upleft = ISEDGE(-1,-1); bool up = ISEDGE( 0,-1); bool upright = ISEDGE( 1,-1); bool left = ISEDGE(-1, 0); bool right = ISEDGE( 1, 0); bool downleft = ISEDGE(-1, 1); bool down = ISEDGE( 0, 1); bool downright = ISEDGE( 1, 1); if(upleft && upright && downleft && !downright) DRAWEDGE(-1,-1); if(up && !down) DRAWEDGE(0,-1); if(upleft && upright && !downleft && downright) DRAWEDGE(1,-1); if(left && !right) DRAWEDGE(-1,0); if(right && !left) DRAWEDGE(1,0); if(upleft && !upright && downleft && downright) DRAWEDGE(-1,1); if(down && !up) DRAWEDGE(0,1); if(!upleft && upright && downleft && downright) DRAWEDGE(1,1); #undef PIXOFFSET #undef ISEDGE #undef DRAWEDGE } } return RENDER3DERROR_NOERR; } Render3DError SoftRasterizerRenderer::UpdateEdgeMarkColorTable(const u16 *edgeMarkColorTable) { size_t i; //TODO: need to test and find out whether these get grabbed at flush time, or at render time //we can do this by rendering a 3d frame and then freezing the system, but only changing the edge mark colors for (i = 0; i < 8; i++) { const u16 col = edgeMarkColorTable[i]; this->edgeMarkTable[i].color = RGB15TO5555(col, (this->currentRenderState->enableAntialiasing) ? 0x10 : 0x1F); this->edgeMarkTable[i].r = GFX3D_5TO6(this->edgeMarkTable[i].r); this->edgeMarkTable[i].g = GFX3D_5TO6(this->edgeMarkTable[i].g); this->edgeMarkTable[i].b = GFX3D_5TO6(this->edgeMarkTable[i].b); //zero 20-jun-2013 - this doesnt make any sense. at least, it should be related to the 0x8000 bit. if this is undocumented behaviour, lets write about which scenario proves it here, or which scenario is requiring this code. //// this seems to be the only thing that selectively disables edge marking //edgeMarkDisabled[i] = (col == 0x7FFF); this->edgeMarkDisabled[i] = false; } return RENDER3DERROR_NOERR; } Render3DError SoftRasterizerRenderer::UpdateFogTable(const u8 *fogDensityTable) { #if 0 //TODO - this might be a little slow; //we might need to hash all the variables and only recompute this when something changes const int increment = (0x400 >> shift); for (u32 i = 0; i < 32768; i++) { if (i < offset) { fogTable[i] = densityTable[0]; continue; } for (int j = 0; j < 32; j++) { u32 value = offset + increment*(j+1); if (i <= value) { if (j == 0) { fogTable[i] = densityTable[0]; goto done; } else { fogTable[i] = ((value-i)*(densityTable[j-1]) + (increment-(value-i))*(densityTable[j]))/increment; goto done; } } } fogTable[i] = (densityTable[31]); done: ; } #else // this should behave exactly the same as the previous loop, // except much faster. (because it's not a 2d loop and isn't so branchy either) // maybe it's fast enough to not need to be cached, now. const int increment = ((1 << 10) >> this->currentRenderState->fogShift); const int incrementDivShift = 10 - this->currentRenderState->fogShift; u32 fogOffset = min(max(this->currentRenderState->fogOffset, 0), 32768); u32 iMin = min(32768, (( 1 + 1) << incrementDivShift) + fogOffset + 1 - increment); u32 iMax = min(32768, ((32 + 1) << incrementDivShift) + fogOffset + 1 - increment); assert(iMin <= iMax); // If the fog factor is 127, then treat it as 128. u8 fogFactor = (fogDensityTable[0] == 127) ? 128 : fogDensityTable[0]; memset(this->fogTable, fogFactor, iMin); for(u32 i = iMin; i < iMax; i++) { int num = (i - fogOffset + (increment-1)); int j = (num >> incrementDivShift) - 1; u32 value = (num & ~(increment-1)) + fogOffset; u32 diff = value - i; assert(j >= 1 && j < 32); fogFactor = ((diff*(fogDensityTable[j-1]) + (increment-diff)*(fogDensityTable[j])) >> incrementDivShift); this->fogTable[i] = (fogFactor == 127) ? 128 : fogFactor; } fogFactor = (fogDensityTable[31] == 127) ? 128 : fogDensityTable[31]; memset(this->fogTable+iMax, fogFactor, 32768-iMax); #endif return RENDER3DERROR_NOERR; } // This method is currently unused right now, in favor of the new multithreaded // SoftRasterizerRenderer::RenderEdgeMarkingAndFog() method. But let's keep this // one around for reference just in case something goes horribly wrong with the // new multithreaded method. Render3DError SoftRasterizerRenderer::RenderFog(const u8 *densityTable, const u32 color, const u32 offset, const u8 shift, const bool alphaOnly) { size_t i; u32 r = GFX3D_5TO6((color)&0x1F); u32 g = GFX3D_5TO6((color>>5)&0x1F); u32 b = GFX3D_5TO6((color>>10)&0x1F); u32 a = (color>>16)&0x1F; const size_t framebufferFragmentCount = this->_framebufferWidth * this->_framebufferHeight; if (!alphaOnly) { for (i = 0; i < framebufferFragmentCount; i++) { const size_t fogIndex = this->_framebufferAttributes->depth[i] >> 9; const u8 fog = (this->_framebufferAttributes->isFogged[i] != 0) ? this->fogTable[fogIndex] : 0; FragmentColor &destFragmentColor = this->_framebufferColor[i]; destFragmentColor.r = ((128-fog)*destFragmentColor.r + r*fog)>>7; destFragmentColor.g = ((128-fog)*destFragmentColor.g + g*fog)>>7; destFragmentColor.b = ((128-fog)*destFragmentColor.b + b*fog)>>7; destFragmentColor.a = ((128-fog)*destFragmentColor.a + a*fog)>>7; } } else { for (i = 0; i < framebufferFragmentCount; i++) { const size_t fogIndex = this->_framebufferAttributes->depth[i] >> 9; const u8 fog = (this->_framebufferAttributes->isFogged[i] != 0) ? this->fogTable[fogIndex] : 0; FragmentColor &destFragmentColor = this->_framebufferColor[i]; destFragmentColor.a = ((128-fog)*destFragmentColor.a + a*fog)>>7; } } return RENDER3DERROR_NOERR; } Render3DError SoftRasterizerRenderer::RenderEdgeMarkingAndFog(const SoftRasterizerPostProcessParams ¶m) { size_t i, x; size_t y = param.startLine; for (i = param.startLine * this->_framebufferWidth; y < param.endLine; y++) { for (x = 0; x < this->_framebufferWidth; x++, i++) { FragmentColor &dstColor = this->_framebufferColor[i]; const u32 depth = this->_framebufferAttributes->depth[i]; const u8 polyID = this->_framebufferAttributes->opaquePolyID[i]; // TODO: New edge marking algorithm which tests both polyID and depth, but only checks 4 surrounding pixels. Can we keep this one? if (param.enableEdgeMarking) { // this looks ok although it's still pretty much a hack, // it needs to be redone with low-level accuracy at some point, // but that should probably wait until the shape renderer is more accurate. // a good test case for edge marking is Sonic Rush: // - the edges are completely sharp/opaque on the very brief title screen intro, // - the level-start intro gets a pseudo-antialiasing effect around the silhouette, // - the character edges in-level are clearly transparent, and also show well through shield powerups. bool up = false; bool left = false; bool right = false; bool down = false; #define PIXOFFSET(dx,dy) ((dx)+(this->_framebufferWidth*(dy))) #define ISEDGE(dx,dy) ((x+(dx) < this->_framebufferWidth) && (y+(dy) < this->_framebufferHeight) && polyID != this->_framebufferAttributes->opaquePolyID[i+PIXOFFSET(dx,dy)] && depth >= this->_framebufferAttributes->depth[i+PIXOFFSET(dx,dy)]) #define DRAWEDGE(dx,dy) alphaBlend(dstColor, this->edgeMarkTable[this->_framebufferAttributes->opaquePolyID[i+PIXOFFSET(dx,dy)] >> 3]) if (this->edgeMarkDisabled[polyID>>3] || this->_framebufferAttributes->isTranslucentPoly[i] != 0) goto END_EDGE_MARK; up = ISEDGE( 0,-1); left = ISEDGE(-1, 0); right = ISEDGE( 1, 0); down = ISEDGE( 0, 1); if (right) DRAWEDGE( 1, 0); else if (down) DRAWEDGE( 0, 1); else if (left) DRAWEDGE(-1, 0); else if (up) DRAWEDGE( 0,-1); #undef PIXOFFSET #undef ISEDGE #undef DRAWEDGE END_EDGE_MARK: ; } if (param.enableFog) { const u32 r = GFX3D_5TO6( (param.fogColor ) & 0x1F ); const u32 g = GFX3D_5TO6( (param.fogColor >> 5) & 0x1F ); const u32 b = GFX3D_5TO6( (param.fogColor >> 10) & 0x1F ); const u32 a = (param.fogColor >> 16) & 0x1F; const size_t fogIndex = depth >> 9; assert(fogIndex < 32768); const u8 fog = (this->_framebufferAttributes->isFogged[i] != 0) ? this->fogTable[fogIndex] : 0; if (!param.fogAlphaOnly) { dstColor.r = ( (128-fog)*dstColor.r + r*fog ) >> 7; dstColor.g = ( (128-fog)*dstColor.g + g*fog ) >> 7; dstColor.b = ( (128-fog)*dstColor.b + b*fog ) >> 7; } dstColor.a = ( (128-fog)*dstColor.a + a*fog ) >> 7; } } } return RENDER3DERROR_NOERR; } Render3DError SoftRasterizerRenderer::UpdateToonTable(const u16 *toonTableBuffer) { size_t i; /* convert the toon colors */ for (i = 0; i < 32; i++) { u32 u32temp = RGB15TO32_NOALPHA(toonTableBuffer[i]); #ifdef MSB_FIRST this->toonColor32LUT[i].r = (u32temp >> 2) & 0x3F; this->toonColor32LUT[i].g = (u32temp >> 10) & 0x3F; this->toonColor32LUT[i].b = (u32temp >> 18) & 0x3F; #else this->toonColor32LUT[i].color = (u32temp >> 2) & 0x3F3F3F3F; #endif //printf("%d %d %d %d\n", this->toonColor32LUT[i].r, this->toonColor32LUT[i].g, this->toonColor32LUT[i].b, this->toonColor32LUT[i].a); } return RENDER3DERROR_NOERR; } Render3DError SoftRasterizerRenderer::ClearUsingImage(const u16 *__restrict colorBuffer, const u32 *__restrict depthBuffer, const u8 *__restrict fogBuffer, const u8 *__restrict polyIDBuffer) { size_t y; const size_t xRatio = (size_t)((GPU_FRAMEBUFFER_NATIVE_WIDTH << 16) / this->_framebufferWidth) + 1; const size_t yRatio = (size_t)((GPU_FRAMEBUFFER_NATIVE_HEIGHT << 16) / this->_framebufferHeight) + 1; size_t iw = 0; for (y = 0; y < this->_framebufferHeight; y++) { size_t x; const size_t readLine = (size_t)(((y * yRatio) >> 16) * GPU_FRAMEBUFFER_NATIVE_WIDTH); for (x = 0; x < this->_framebufferWidth; x++, iw++) { const size_t ir = readLine + ((x * xRatio) >> 16); this->_framebufferColor[iw].color = RGB15TO6665(colorBuffer[ir] & 0x7FFF, (colorBuffer[ir] >> 15) * 0x1F); this->_framebufferAttributes->depth[iw] = depthBuffer[ir]; this->_framebufferAttributes->isFogged[iw] = fogBuffer[ir]; this->_framebufferAttributes->opaquePolyID[iw] = polyIDBuffer[ir]; this->_framebufferAttributes->translucentPolyID[iw] = kUnsetTranslucentPolyID; this->_framebufferAttributes->isTranslucentPoly[iw] = 0; this->_framebufferAttributes->stencil[iw] = 0; } } return RENDER3DERROR_NOERR; } Render3DError SoftRasterizerRenderer::ClearUsingValues(const FragmentColor &clearColor, const FragmentAttributes &clearAttributes) const { size_t i; FragmentColor convertedClearColor = clearColor; convertedClearColor.r = GFX3D_5TO6(clearColor.r); convertedClearColor.g = GFX3D_5TO6(clearColor.g); convertedClearColor.b = GFX3D_5TO6(clearColor.b); for (i = 0; i < (this->_framebufferWidth * this->_framebufferHeight); i++) { this->_framebufferAttributes->SetAtIndex(i, clearAttributes); this->_framebufferColor[i] = convertedClearColor; } return RENDER3DERROR_NOERR; } Render3DError SoftRasterizerRenderer::Reset() { if (rasterizerCores > 1) { size_t i; for (i = 0; i < rasterizerCores; i++) { rasterizerUnitTask[i].finish(); rasterizerUnit[i].SetRenderer(this); } } else rasterizerUnit[0].SetRenderer(this); this->_stateSetupNeedsFinish = false; this->_renderGeometryNeedsFinish = false; memset(this->clearImageColor16Buffer, 0, sizeof(this->clearImageColor16Buffer)); memset(this->clearImageDepthBuffer, 0, sizeof(this->clearImageDepthBuffer)); memset(this->clearImagePolyIDBuffer, 0, sizeof(this->clearImagePolyIDBuffer)); memset(this->clearImageFogBuffer, 0, sizeof(this->clearImageFogBuffer)); TexCache_Reset(); return RENDER3DERROR_NOERR; } Render3DError SoftRasterizerRenderer::Render(const GFX3D &engine) { Render3DError error = RENDER3DERROR_NOERR; error = this->BeginRender(engine); if (error != RENDER3DERROR_NOERR) return error; this->RenderGeometry(engine.renderState, engine.polylist, &engine.indexlist); this->EndRender(engine.frameCtr); return error; } Render3DError SoftRasterizerRenderer::EndRender(const u64 frameCount) { // If we're not multithreaded, then just do the post-processing steps now. if (!this->_renderGeometryNeedsFinish) { if (this->currentRenderState->enableEdgeMarking || this->currentRenderState->enableFog) { this->postprocessParam[0].enableEdgeMarking = this->currentRenderState->enableEdgeMarking; this->postprocessParam[0].enableFog = this->currentRenderState->enableFog; this->postprocessParam[0].fogColor = this->currentRenderState->fogColor; this->postprocessParam[0].fogAlphaOnly = this->currentRenderState->enableFogAlphaOnly; this->RenderEdgeMarkingAndFog(this->postprocessParam[0]); } this->FlushFramebuffer(GPU->GetEngineMain()->Get3DFramebufferRGBA6665(), GPU->GetEngineMain()->Get3DFramebufferRGBA5551()); } return RENDER3DERROR_NOERR; } Render3DError SoftRasterizerRenderer::RenderFinish() { size_t i; if (!this->_renderGeometryNeedsFinish) return RENDER3DERROR_NOERR; // Allow for the geometry rendering to finish. this->_renderGeometryNeedsFinish = false; for (i = 0; i < rasterizerCores; i++) rasterizerUnitTask[i].finish(); // Now that geometry rendering is finished on all threads, check the texture cache. TexCache_EvictFrame(); // Do multithreaded post-processing. if (this->currentRenderState->enableEdgeMarking || this->currentRenderState->enableFog) { size_t i; for (i = 0; i < rasterizerCores; i++) { this->postprocessParam[i].enableEdgeMarking = this->currentRenderState->enableEdgeMarking; this->postprocessParam[i].enableFog = this->currentRenderState->enableFog; this->postprocessParam[i].fogColor = this->currentRenderState->fogColor; this->postprocessParam[i].fogAlphaOnly = this->currentRenderState->enableFogAlphaOnly; rasterizerUnitTask[i].execute(&SoftRasterizer_RunRenderEdgeMarkAndFog, &this->postprocessParam[i]); } /* Allow for post-processing to finish. */ for (i = 0; i < rasterizerCores; i++) rasterizerUnitTask[i].finish(); } this->FlushFramebuffer(GPU->GetEngineMain()->Get3DFramebufferRGBA6665(), GPU->GetEngineMain()->Get3DFramebufferRGBA5551()); return RENDER3DERROR_NOERR; } Render3DError SoftRasterizerRenderer::SetFramebufferSize(size_t w, size_t h) { if (w < GPU_FRAMEBUFFER_NATIVE_WIDTH || h < GPU_FRAMEBUFFER_NATIVE_HEIGHT) return RENDER3DERROR_NOERR; const size_t newFramebufferColorSizeBytes = w * h * sizeof(FragmentColor); FragmentColor *oldFramebufferColor = this->_framebufferColor; FragmentColor *newFramebufferColor = (FragmentColor *)memalign_alloc_aligned(newFramebufferColorSizeBytes); FragmentAttributesBuffer *oldFramebufferAttributes = this->_framebufferAttributes; FragmentAttributesBuffer *newFramebufferAttributes = new FragmentAttributesBuffer(w * h); this->_framebufferWidth = w; this->_framebufferHeight = h; this->_framebufferColorSizeBytes = newFramebufferColorSizeBytes; this->_framebufferColor = newFramebufferColor; this->_framebufferAttributes = newFramebufferAttributes; if (rasterizerCores == 0 || rasterizerCores == 1) { postprocessParam[0].startLine = 0; postprocessParam[0].endLine = h; } else { size_t i; const size_t linesPerThread = h / rasterizerCores; for (i = 0; i < rasterizerCores; i++) { postprocessParam[i].startLine = i * linesPerThread; postprocessParam[i].endLine = (i < rasterizerCores - 1) ? (i + 1) * linesPerThread : h; } } memalign_free(oldFramebufferColor); delete oldFramebufferAttributes; return RENDER3DERROR_NOERR; } #ifdef ENABLE_SSE2 Render3DError SoftRasterizerRenderer_SSE2::ClearUsingValues(const FragmentColor &clearColor, const FragmentAttributes &clearAttributes) const { size_t i; FragmentColor convertedClearColor = clearColor; convertedClearColor.r = GFX3D_5TO6(clearColor.r); convertedClearColor.g = GFX3D_5TO6(clearColor.g); convertedClearColor.b = GFX3D_5TO6(clearColor.b); const __m128i color_vec128 = _mm_set1_epi32(convertedClearColor.color); const __m128i attrDepth_vec128 = _mm_set1_epi32(clearAttributes.depth); const __m128i attrOpaquePolyID_vec128 = _mm_set1_epi8(clearAttributes.opaquePolyID); const __m128i attrTranslucentPolyID_vec128 = _mm_set1_epi8(clearAttributes.translucentPolyID); const __m128i attrStencil_vec128 = _mm_set1_epi8(clearAttributes.stencil); const __m128i attrIsFogged_vec128 = _mm_set1_epi8(clearAttributes.isFogged); const __m128i attrIsTranslucentPoly_vec128 = _mm_set1_epi8(clearAttributes.isTranslucentPoly); const size_t pixCount = this->_framebufferWidth * this->_framebufferHeight; const size_t ssePixCount = pixCount - (pixCount % 16); for (i = 0; i < ssePixCount; i += 16) { _mm_stream_si128((__m128i *)(this->_framebufferColor + i + 0), color_vec128); _mm_stream_si128((__m128i *)(this->_framebufferColor + i + 4), color_vec128); _mm_stream_si128((__m128i *)(this->_framebufferColor + i + 8), color_vec128); _mm_stream_si128((__m128i *)(this->_framebufferColor + i + 12), color_vec128); _mm_stream_si128((__m128i *)(this->_framebufferAttributes->depth + i + 0), attrDepth_vec128); _mm_stream_si128((__m128i *)(this->_framebufferAttributes->depth + i + 4), attrDepth_vec128); _mm_stream_si128((__m128i *)(this->_framebufferAttributes->depth + i + 8), attrDepth_vec128); _mm_stream_si128((__m128i *)(this->_framebufferAttributes->depth + i + 12), attrDepth_vec128); _mm_stream_si128((__m128i *)(this->_framebufferAttributes->opaquePolyID + i), attrOpaquePolyID_vec128); _mm_stream_si128((__m128i *)(this->_framebufferAttributes->translucentPolyID + i), attrTranslucentPolyID_vec128); _mm_stream_si128((__m128i *)(this->_framebufferAttributes->stencil + i), attrStencil_vec128); _mm_stream_si128((__m128i *)(this->_framebufferAttributes->isFogged + i), attrIsFogged_vec128); _mm_stream_si128((__m128i *)(this->_framebufferAttributes->isTranslucentPoly + i), attrIsTranslucentPoly_vec128); } for (; i < pixCount; i++) { this->_framebufferColor[i] = convertedClearColor; this->_framebufferAttributes->SetAtIndex(i, clearAttributes); } return RENDER3DERROR_NOERR; } #endif // ENABLE_SSE2 desmume/src/libretro-common/include/glsym/rglgen.h000664 001750 001750 00000003512 12755534123 023455 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2015 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this libretro SDK code part (glsym). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef RGLGEN_H__ #define RGLGEN_H__ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include "rglgen_headers.h" RETRO_BEGIN_DECLS struct rglgen_sym_map; typedef void (*rglgen_func_t)(void); typedef rglgen_func_t (*rglgen_proc_address_t)(const char*); void rglgen_resolve_symbols(rglgen_proc_address_t proc); void rglgen_resolve_symbols_custom(rglgen_proc_address_t proc, const struct rglgen_sym_map *map); RETRO_END_DECLS #endif desmume/src/libretro-common/include/streams/interface_stream.h000664 001750 001750 00000005406 12755534123 026041 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2015 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (interface_stream.h). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef _LIBRETRO_SDK_INTERFACE_STREAM_H #define _LIBRETRO_SDK_INTERFACE_STREAM_H #include #include #include #include #include enum intfstream_type { INTFSTREAM_FILE = 0, INTFSTREAM_MEMORY }; typedef struct intfstream_internal intfstream_internal_t; typedef struct intfstream intfstream_t; typedef struct intfstream_info { struct { struct { uint8_t *data; unsigned size; } buf; bool writable; } memory; enum intfstream_type type; } intfstream_info_t; void *intfstream_init(intfstream_info_t *info); bool intfstream_resize(intfstream_internal_t *intf, intfstream_info_t *info); bool intfstream_open(intfstream_internal_t *intf, const char *path, unsigned mode, ssize_t len); ssize_t intfstream_read(intfstream_internal_t *intf, void *s, size_t len); ssize_t intfstream_write(intfstream_internal_t *intf, const void *s, size_t len); char *intfstream_gets(intfstream_internal_t *intf, char *buffer, size_t len); int intfstream_getc(intfstream_internal_t *intf); int intfstream_seek(intfstream_internal_t *intf, int offset, int whence); void intfstream_rewind(intfstream_internal_t *intf); int intfstream_tell(intfstream_internal_t *intf); void intfstream_putc(intfstream_internal_t *intf, int c); int intfstream_close(intfstream_internal_t *intf); #endif desmume/src/libretro-common/hash/000700 001750 001750 00000000000 12756420131 020150 5ustar00sergiosergio000000 000000 desmume/src/libretro-common/compat/compat_posix_string.c000664 001750 001750 00000005233 12755534123 024774 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2015 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (compat.c). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include #include #include #ifdef _WIN32 #undef strcasecmp #undef strdup #undef isblank #undef strtok_r #include #include #include #include #include int retro_strcasecmp__(const char *a, const char *b) { while (*a && *b) { int a_ = tolower(*a); int b_ = tolower(*b); if (a_ != b_) return a_ - b_; a++; b++; } return tolower(*a) - tolower(*b); } char *retro_strdup__(const char *orig) { size_t len = strlen(orig) + 1; char *ret = (char*)malloc(len); if (!ret) return NULL; strlcpy(ret, orig, len); return ret; } int retro_isblank__(int c) { return (c == ' ') || (c == '\t'); } char *retro_strtok_r__(char *str, const char *delim, char **saveptr) { char *first = NULL; if (!saveptr || !delim) return NULL; if (str) *saveptr = str; do { char *ptr = NULL; first = *saveptr; while (*first && strchr(delim, *first)) *first++ = '\0'; if (*first == '\0') return NULL; ptr = first + 1; while (*ptr && !strchr(delim, *ptr)) ptr++; *saveptr = ptr + (*ptr ? 1 : 0); *ptr = '\0'; } while (strlen(first) == 0); return first; } #endif desmume/src/libretro-common/formats/xml/rxml.c000664 001750 001750 00000026741 12755534123 022662 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2016 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (rxml.c). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include #include #include #include #include #include #include #include #include #include struct rxml_document { struct rxml_node *root_node; }; struct rxml_node *rxml_root_node(rxml_document_t *doc) { if (doc) return doc->root_node; return NULL; } static void rxml_free_node(struct rxml_node *node) { struct rxml_node *head = NULL; struct rxml_attrib_node *attrib_node_head = NULL; if (!node) return; for (head = node->children; head; ) { struct rxml_node *next_node = (struct rxml_node*)head->next; rxml_free_node(head); head = next_node; } for (attrib_node_head = node->attrib; attrib_node_head; ) { struct rxml_attrib_node *next_attrib = NULL; if (!attrib_node_head) continue; next_attrib = (struct rxml_attrib_node*)attrib_node_head->next; if (!next_attrib) continue; if (attrib_node_head->attrib) free(attrib_node_head->attrib); if (attrib_node_head->value) free(attrib_node_head->value); if (attrib_node_head) free(attrib_node_head); attrib_node_head = next_attrib; } if (node->name) free(node->name); if (node->data) free(node->data); if (node) free(node); } static bool validate_header(const char **ptr) { if (memcmp(*ptr, "\n"); if (!eol) return false; /* Always use UTF-8. Don't really care to check. */ *ptr = eol + 3; return true; } return true; } static bool range_is_space(const char *begin, const char *end) { for (; begin < end; begin++) if (!isspace(*begin)) return false; return true; } static void skip_spaces(const char **ptr_) { const char *ptr = *ptr_; while (isspace(*ptr)) ptr++; *ptr_ = ptr; } static char *strdup_range(const char *begin, const char *end) { ptrdiff_t len = end - begin; char *ret = (char*)malloc(len + 1); if (!ret) return NULL; memcpy(ret, begin, len); ret[len] = '\0'; return ret; } static char *strdup_range_escape(const char *begin, const char *end) { /* Escaping is ignored. Assume we don't deal with that. */ return strdup_range(begin, end); } static struct rxml_attrib_node *rxml_parse_attrs(const char *str) { char *copy = strdup(str); if (!copy) return NULL; char *last_char = copy + strlen(copy) - 1; if (*last_char == '/') *last_char = '\0'; struct rxml_attrib_node *list = NULL; struct rxml_attrib_node *tail = NULL; char *attrib = NULL; char *value = NULL; char *save; const char *elem = strtok_r(copy, " \n\t\f\v\r", &save); while (elem) { const char *eq = strstr(elem, "=\""); if (!eq) goto end; const char *end = strrchr(eq + 2, '\"'); if (!end || end != (elem + strlen(elem) - 1)) goto end; attrib = strdup_range_escape(elem, eq); value = strdup_range_escape(eq + 2, end); if (!attrib || !value) goto end; struct rxml_attrib_node *new_node = (struct rxml_attrib_node*)calloc(1, sizeof(*new_node)); if (!new_node) goto end; new_node->attrib = attrib; new_node->value = value; attrib = NULL; value = NULL; if (tail) { tail->next = new_node; tail = new_node; } else list = tail = new_node; elem = strtok_r(NULL, " \n\t\f\v\r", &save); } end: if (copy) free(copy); if (attrib) free(attrib); if (value) free(value); return list; } static char *find_first_space(const char *str) { while (*str && !isspace(*str)) str++; return isspace(*str) ? (char*)str : NULL; } static bool rxml_parse_tag(struct rxml_node *node, const char *str) { const char *str_ptr = str; skip_spaces(&str_ptr); const char *name_end = find_first_space(str_ptr); if (name_end) { node->name = strdup_range(str_ptr, name_end); if (!node->name || !*node->name) return false; node->attrib = rxml_parse_attrs(name_end); return true; } else { node->name = strdup(str_ptr); return node->name && *node->name; } } static struct rxml_node *rxml_parse_node(const char **ptr_) { const char *ptr = NULL; const char *closing = NULL; char *str = NULL; bool is_closing = false; struct rxml_node *node = (struct rxml_node*)calloc(1, sizeof(*node)); if (!node) return NULL; skip_spaces(ptr_); ptr = *ptr_; if (*ptr != '<') goto error; closing = strchr(ptr, '>'); if (!closing) goto error; str = strdup_range(ptr + 1, closing); if (!str) goto error; if (!rxml_parse_tag(node, str)) goto error; /* Are spaces between / and > allowed? */ is_closing = strstr(ptr, "/>") + 1 == closing; /* Look for more data. Either child nodes or data. */ if (!is_closing) { size_t closing_tag_size = strlen(node->name) + 4; char *closing_tag = (char*)malloc(closing_tag_size); const char *cdata_start = NULL; const char *child_start = NULL; const char *closing_start = NULL; if (!closing_tag) goto error; snprintf(closing_tag, closing_tag_size, "", node->name); cdata_start = strstr(closing + 1, ""); if (!cdata_end) { free(closing_tag); goto error; } node->data = strdup_range(cdata_start + strlen("data = strdup_range(closing + 1, closing_start); else { /* Parse all child nodes. */ struct rxml_node *list = NULL; struct rxml_node *tail = NULL; const char *first_start = NULL; const char *first_closing = NULL; ptr = child_start; first_start = strchr(ptr, '<'); first_closing = strstr(ptr, "next = new_node; tail = new_node; } else list = tail = new_node; first_start = strchr(ptr, '<'); first_closing = strstr(ptr, "children = list; closing_start = strstr(ptr, closing_tag); if (!closing_start) { free(closing_tag); goto error; } } *ptr_ = closing_start + strlen(closing_tag); free(closing_tag); } else *ptr_ = closing + 1; if (str) free(str); return node; error: if (str) free(str); rxml_free_node(node); return NULL; } static char *purge_xml_comments(const char *str) { size_t len = strlen(str); char *new_str = (char*)malloc(len + 1); if (!new_str) return NULL; new_str[len] = '\0'; char *copy_dest = new_str; const char *copy_src = str; for (;;) { ptrdiff_t copy_len; const char *comment_start = strstr(copy_src, ""); if (!comment_start || !comment_end) break; copy_len = comment_start - copy_src; memcpy(copy_dest, copy_src, copy_len); copy_dest += copy_len; copy_src = comment_end + strlen("-->"); } /* Avoid strcpy() as OpenBSD is anal and hates you * for using it even when it's perfectly safe. */ len = strlen(copy_src); memcpy(copy_dest, copy_src, len); copy_dest[len] = '\0'; return new_str; } rxml_document_t *rxml_load_document(const char *path) { #ifndef RXML_TEST RARCH_WARN("Using RXML as drop in for libxml2. Behavior might be very buggy.\n"); #endif char *memory_buffer = NULL; char *new_memory_buffer = NULL; const char *mem_ptr = NULL; long len = 0; RFILE *file = filestream_open(path, RFILE_MODE_READ, -1); if (!file) return NULL; rxml_document_t *doc = (rxml_document_t*)calloc(1, sizeof(*doc)); if (!doc) goto error; filestream_seek(file, 0, SEEK_END); len = filestream_tell(file); filestream_rewind(file); memory_buffer = (char*)malloc(len + 1); if (!memory_buffer) goto error; memory_buffer[len] = '\0'; if (filestream_read(file, memory_buffer, len) != (size_t)len) goto error; filestream_close(file); file = NULL; mem_ptr = memory_buffer; if (!validate_header(&mem_ptr)) goto error; new_memory_buffer = purge_xml_comments(mem_ptr); if (!new_memory_buffer) goto error; free(memory_buffer); mem_ptr = memory_buffer = new_memory_buffer; doc->root_node = rxml_parse_node(&mem_ptr); if (!doc->root_node) goto error; free(memory_buffer); return doc; error: free(memory_buffer); filestream_close(file); rxml_free_document(doc); return NULL; } void rxml_free_document(rxml_document_t *doc) { if (!doc) return; if (doc->root_node) rxml_free_node(doc->root_node); free(doc); } char *rxml_node_attrib(struct rxml_node *node, const char *attrib) { struct rxml_attrib_node *attribs = NULL; for (attribs = node->attrib; attribs; attribs = attribs->next) { if (!strcmp(attrib, attribs->attrib)) return attribs->value; } return NULL; } desmume/src/libretro-common/include/conversion/float_to_s16.h000664 001750 001750 00000007347 12755534123 025543 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2016 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (float_to_s16.h). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef __LIBRETRO_SDK_CONVERSION_FLOAT_TO_S16_H__ #define __LIBRETRO_SDK_CONVERSION_FLOAT_TO_S16_H__ #include RETRO_BEGIN_DECLS #include #include /** * convert_float_to_s16_C: * @out : output buffer * @in : input buffer * @samples : size of samples to be converted * * Converts floating point * to signed integer 16-bit. * * C implementation callback function. **/ void convert_float_to_s16_C(int16_t *out, const float *in, size_t samples); #if defined(__SSE2__) #define convert_float_to_s16 convert_float_to_s16_SSE2 /** * convert_float_to_s16_SSE2: * @out : output buffer * @in : input buffer * @samples : size of samples to be converted * * Converts floating point * to signed integer 16-bit. * * SSE2 implementation callback function. **/ void convert_float_to_s16_SSE2(int16_t *out, const float *in, size_t samples); #elif defined(__ALTIVEC__) #define convert_float_to_s16 convert_float_to_s16_altivec /** * convert_float_to_s16_altivec: * @out : output buffer * @in : input buffer * @samples : size of samples to be converted * * Converts floating point * to signed integer 16-bit. * * AltiVec implementation callback function. **/ void convert_float_to_s16_altivec(int16_t *out, const float *in, size_t samples); #elif defined(__ARM_NEON__) && !defined(VITA) #define convert_float_to_s16 convert_float_to_s16_arm void (*convert_float_to_s16_arm)(int16_t *out, const float *in, size_t samples); void convert_float_s16_asm(int16_t *out, const float *in, size_t samples); #elif defined(_MIPS_ARCH_ALLEGREX) #define convert_float_to_s16 convert_float_to_s16_ALLEGREX /** * convert_float_to_s16_ALLEGREX: * @out : output buffer * @in : input buffer * @samples : size of samples to be converted * * Converts floating point * to signed integer 16-bit. * * MIPS ALLEGREX implementation callback function. **/ void convert_float_to_s16_ALLEGREX(int16_t *out, const float *in, size_t samples); #else #define convert_float_to_s16 convert_float_to_s16_C #endif /** * convert_float_to_s16_init_simd: * * Sets up function pointers for conversion * functions based on CPU features. **/ void convert_float_to_s16_init_simd(void); RETRO_END_DECLS #endif desmume/src/libretro-common/utils/Makefile000664 001750 001750 00000003540 12755534123 022051 0ustar00sergiosergio000000 000000 compiler := gcc extra_flags := use_neon := 0 release := release DYLIB := ifeq ($(platform),) platform = unix ifeq ($(shell uname -a),) platform = win else ifneq ($(findstring MINGW,$(shell uname -a)),) platform = win else ifneq ($(findstring Darwin,$(shell uname -a)),) platform = osx arch = intel ifeq ($(shell uname -p),powerpc) arch = ppc endif else ifneq ($(findstring win,$(shell uname -a)),) platform = win endif endif ifeq ($(platform),gcc) extra_rules_gcc := $(shell $(compiler) -dumpmachine) endif ifneq (,$(findstring armv7,$(extra_rules_gcc))) extra_flags += -mcpu=cortex-a9 -mtune=cortex-a9 -mfpu=neon use_neon := 1 endif ifneq (,$(findstring hardfloat,$(extra_rules_gcc))) extra_flags += -mfloat-abi=hard endif ifeq (release,$(build)) extra_flags += -O2 endif ifeq (debug,$(build)) extra_flags += -O0 -g endif ldflags := -shared -Wl,--version-script=link.T ifeq ($(platform), unix) DYLIB = else ifeq ($(platform), osx) compiler := $(CC) DYLIB = ldflags := -dynamiclib else extra_flags += -static-libgcc -static-libstdc++ DYLIB = exe endif CC := $(compiler) CXX := $(subst CC,++,$(compiler)) flags := -fPIC $(extra_flags) -I../../libretro-common/include asflags := -fPIC $(extra_flags) LDFLAGS := -lz flags += -std=c99 -DMD5_BUILD_UTILITY ifeq (1,$(use_neon)) ASMFLAGS := -INEON/asm asflags += -mfpu=neon endif OBJS += djb2.o md5.o sha1.o crc32.o UTILS += djb2$(DYLIB) md5$(DYLIB) sha1$(DYLIB) crc32$(DYLIB) all: djb2$(DYLIB) md5$(DYLIB) sha1$(DYLIB) crc32$(DYLIB) djb2$(DYLIB): djb2.o md5$(DYLIB): md5.o sha1$(DYLIB): sha1.o crc32$(DYLIB): crc32.o %.o: %.S $(CC) -c -o $@ $(asflags) $(LDFLAGS) $(ASMFLAGS) $< %.o: %.c $(CC) -c -o $@ $(flags) $< %.$(DYLIB): %.o $(CC) -o $@ $(ldflags) $(flags) $^ clean: rm -f *.o rm -f djb2$(DYLIB) md5$(DYLIB) sha1$(DYLIB) crc32$(DYLIB) strip: strip -s *.$(DYLIB) desmume/src/libretro-common/crt/000700 001750 001750 00000000000 12756420131 020015 5ustar00sergiosergio000000 000000 desmume/src/texcache.h000664 001750 001750 00000005246 12755534123 016103 0ustar00sergiosergio000000 000000 /* Copyright (C) 2006 yopyop Copyright (C) 2006-2007 shash Copyright (C) 2008-2015 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the this software. If not, see . */ #ifndef _TEXCACHE_H_ #define _TEXCACHE_H_ #include #include "types.h" enum TexCache_TexFormat { TexFormat_None, //used when nothing yet is cached TexFormat_32bpp, //used by ogl renderer TexFormat_15bpp //used by rasterizer }; class TexCacheItem; typedef std::multimap TTexCacheItemMultimap; typedef void (*TexCacheItemDeleteCallback)(TexCacheItem *texItem, void *param1, void *param2); class TexCacheItem { private: TexCacheItemDeleteCallback _deleteCallback; void *_deleteCallbackParam1; void *_deleteCallbackParam2; public: TexCacheItem() : decode_len(0) , decoded(NULL) , suspectedInvalid(false) , assumedInvalid(false) , _deleteCallback(NULL) , _deleteCallbackParam1(NULL) , _deleteCallbackParam2(NULL) , cacheFormat(TexFormat_None) {} ~TexCacheItem() { delete[] decoded; if(_deleteCallback != NULL) _deleteCallback(this, this->_deleteCallbackParam1, this->_deleteCallbackParam2); } u32 decode_len; u32 mode; u8* decoded; //decoded texture data bool suspectedInvalid; bool assumedInvalid; TTexCacheItemMultimap::iterator iterator; int getTextureMode() const { return (int)((texformat>>26)&0x07); } u32 texformat, texpal; u32 sizeX, sizeY; float invSizeX, invSizeY; u32 texid; //used by ogl renderer for the texid TexCache_TexFormat cacheFormat; struct Dump { ~Dump() { delete[] texture; } int textureSize, indexSize; static const int maxTextureSize=128*1024; u8* texture; u8 palette[256*2]; } dump; TexCacheItemDeleteCallback GetDeleteCallback() { return this->_deleteCallback; } void SetDeleteCallback(TexCacheItemDeleteCallback callbackFunc, void *inParam1, void *inParam2) { this->_deleteCallback = callbackFunc; this->_deleteCallbackParam1 = inParam1; this->_deleteCallbackParam2 = inParam2; } }; void TexCache_Invalidate(); void TexCache_Reset(); void TexCache_EvictFrame(); TexCacheItem* TexCache_SetTexture(TexCache_TexFormat TEXFORMAT, u32 format, u32 texpal); #endif desmume/src/utils/decrypt/crc.cpp000664 001750 001750 00000020742 12755534123 020231 0ustar00sergiosergio000000 000000 //taken from ndstool //http://devkitpro.svn.sourceforge.net/viewvc/devkitpro/trunk/tools/nds/ndstool/source/crc.cpp?revision=1587 /* crc.cpp - this file is part of DeSmuME * * Copyright (C) 2005-2006 Rafael Vuijk * * This file is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This file is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ /* Cyclic Redundancy Code (CRC) functions by Rafael Vuijk (aka DarkFader) */ unsigned short ccitt16tab[] = { 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7, 0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF, 0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6, 0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE, 0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485, 0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D, 0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4, 0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC, 0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823, 0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B, 0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12, 0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A, 0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41, 0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49, 0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70, 0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78, 0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F, 0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067, 0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E, 0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256, 0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D, 0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, 0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C, 0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634, 0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB, 0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3, 0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A, 0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92, 0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9, 0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1, 0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8, 0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0 }; unsigned short crc16tab[] = { 0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241, 0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440, 0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40, 0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841, 0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40, 0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41, 0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641, 0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040, 0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240, 0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441, 0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41, 0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840, 0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41, 0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40, 0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640, 0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041, 0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240, 0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441, 0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41, 0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840, 0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41, 0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40, 0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640, 0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041, 0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241, 0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440, 0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40, 0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841, 0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40, 0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41, 0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641, 0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040 }; unsigned long crc32tab[] = { 0x00000000L, 0x77073096L, 0xEE0E612CL, 0x990951BAL, 0x076DC419L, 0x706AF48FL, 0xE963A535L, 0x9E6495A3L, 0x0EDB8832L, 0x79DCB8A4L, 0xE0D5E91EL, 0x97D2D988L, 0x09B64C2BL, 0x7EB17CBDL, 0xE7B82D07L, 0x90BF1D91L, 0x1DB71064L, 0x6AB020F2L, 0xF3B97148L, 0x84BE41DEL, 0x1ADAD47DL, 0x6DDDE4EBL, 0xF4D4B551L, 0x83D385C7L, 0x136C9856L, 0x646BA8C0L, 0xFD62F97AL, 0x8A65C9ECL, 0x14015C4FL, 0x63066CD9L, 0xFA0F3D63L, 0x8D080DF5L, 0x3B6E20C8L, 0x4C69105EL, 0xD56041E4L, 0xA2677172L, 0x3C03E4D1L, 0x4B04D447L, 0xD20D85FDL, 0xA50AB56BL, 0x35B5A8FAL, 0x42B2986CL, 0xDBBBC9D6L, 0xACBCF940L, 0x32D86CE3L, 0x45DF5C75L, 0xDCD60DCFL, 0xABD13D59L, 0x26D930ACL, 0x51DE003AL, 0xC8D75180L, 0xBFD06116L, 0x21B4F4B5L, 0x56B3C423L, 0xCFBA9599L, 0xB8BDA50FL, 0x2802B89EL, 0x5F058808L, 0xC60CD9B2L, 0xB10BE924L, 0x2F6F7C87L, 0x58684C11L, 0xC1611DABL, 0xB6662D3DL, 0x76DC4190L, 0x01DB7106L, 0x98D220BCL, 0xEFD5102AL, 0x71B18589L, 0x06B6B51FL, 0x9FBFE4A5L, 0xE8B8D433L, 0x7807C9A2L, 0x0F00F934L, 0x9609A88EL, 0xE10E9818L, 0x7F6A0DBBL, 0x086D3D2DL, 0x91646C97L, 0xE6635C01L, 0x6B6B51F4L, 0x1C6C6162L, 0x856530D8L, 0xF262004EL, 0x6C0695EDL, 0x1B01A57BL, 0x8208F4C1L, 0xF50FC457L, 0x65B0D9C6L, 0x12B7E950L, 0x8BBEB8EAL, 0xFCB9887CL, 0x62DD1DDFL, 0x15DA2D49L, 0x8CD37CF3L, 0xFBD44C65L, 0x4DB26158L, 0x3AB551CEL, 0xA3BC0074L, 0xD4BB30E2L, 0x4ADFA541L, 0x3DD895D7L, 0xA4D1C46DL, 0xD3D6F4FBL, 0x4369E96AL, 0x346ED9FCL, 0xAD678846L, 0xDA60B8D0L, 0x44042D73L, 0x33031DE5L, 0xAA0A4C5FL, 0xDD0D7CC9L, 0x5005713CL, 0x270241AAL, 0xBE0B1010L, 0xC90C2086L, 0x5768B525L, 0x206F85B3L, 0xB966D409L, 0xCE61E49FL, 0x5EDEF90EL, 0x29D9C998L, 0xB0D09822L, 0xC7D7A8B4L, 0x59B33D17L, 0x2EB40D81L, 0xB7BD5C3BL, 0xC0BA6CADL, 0xEDB88320L, 0x9ABFB3B6L, 0x03B6E20CL, 0x74B1D29AL, 0xEAD54739L, 0x9DD277AFL, 0x04DB2615L, 0x73DC1683L, 0xE3630B12L, 0x94643B84L, 0x0D6D6A3EL, 0x7A6A5AA8L, 0xE40ECF0BL, 0x9309FF9DL, 0x0A00AE27L, 0x7D079EB1L, 0xF00F9344L, 0x8708A3D2L, 0x1E01F268L, 0x6906C2FEL, 0xF762575DL, 0x806567CBL, 0x196C3671L, 0x6E6B06E7L, 0xFED41B76L, 0x89D32BE0L, 0x10DA7A5AL, 0x67DD4ACCL, 0xF9B9DF6FL, 0x8EBEEFF9L, 0x17B7BE43L, 0x60B08ED5L, 0xD6D6A3E8L, 0xA1D1937EL, 0x38D8C2C4L, 0x4FDFF252L, 0xD1BB67F1L, 0xA6BC5767L, 0x3FB506DDL, 0x48B2364BL, 0xD80D2BDAL, 0xAF0A1B4CL, 0x36034AF6L, 0x41047A60L, 0xDF60EFC3L, 0xA867DF55L, 0x316E8EEFL, 0x4669BE79L, 0xCB61B38CL, 0xBC66831AL, 0x256FD2A0L, 0x5268E236L, 0xCC0C7795L, 0xBB0B4703L, 0x220216B9L, 0x5505262FL, 0xC5BA3BBEL, 0xB2BD0B28L, 0x2BB45A92L, 0x5CB36A04L, 0xC2D7FFA7L, 0xB5D0CF31L, 0x2CD99E8BL, 0x5BDEAE1DL, 0x9B64C2B0L, 0xEC63F226L, 0x756AA39CL, 0x026D930AL, 0x9C0906A9L, 0xEB0E363FL, 0x72076785L, 0x05005713L, 0x95BF4A82L, 0xE2B87A14L, 0x7BB12BAEL, 0x0CB61B38L, 0x92D28E9BL, 0xE5D5BE0DL, 0x7CDCEFB7L, 0x0BDBDF21L, 0x86D3D2D4L, 0xF1D4E242L, 0x68DDB3F8L, 0x1FDA836EL, 0x81BE16CDL, 0xF6B9265BL, 0x6FB077E1L, 0x18B74777L, 0x88085AE6L, 0xFF0F6A70L, 0x66063BCAL, 0x11010B5CL, 0x8F659EFFL, 0xF862AE69L, 0x616BFFD3L, 0x166CCF45L, 0xA00AE278L, 0xD70DD2EEL, 0x4E048354L, 0x3903B3C2L, 0xA7672661L, 0xD06016F7L, 0x4969474DL, 0x3E6E77DBL, 0xAED16A4AL, 0xD9D65ADCL, 0x40DF0B66L, 0x37D83BF0L, 0xA9BCAE53L, 0xDEBB9EC5L, 0x47B2CF7FL, 0x30B5FFE9L, 0xBDBDF21CL, 0xCABAC28AL, 0x53B39330L, 0x24B4A3A6L, 0xBAD03605L, 0xCDD70693L, 0x54DE5729L, 0x23D967BFL, 0xB3667A2EL, 0xC4614AB8L, 0x5D681B02L, 0x2A6F2B94L, 0xB40BBE37L, 0xC30C8EA1L, 0x5A05DF1BL, 0x2D02EF8DL }; desmume/dsm.txt000664 001750 001750 00000010541 12755534123 014675 0ustar00sergiosergio000000 000000 DSM is ascii plain text. It is derived from the FCEUX FM2 format. It consists of several key-value pairs followed by an inputlog section. The inputlog section can be identified by its starting with a | (pipe). The inputlog section terminates at eof. Newlines may be \r\n or \n Key-value pairs consist of a key identifier, followed by a space separator, followed by the value text. Value text is always terminated by a newline, which the value text will not include. The value text is parsed differently depending on the type of the key. The key-value pairs may be in any order, except that the first key must be version. Integer keys (also used for booleans, with a 1 or 0) will have a value that is a simple integer not to exceed 32bits - version (required) - the version of the movie file format; for now it is always 3 - emuVersion (required) - the version of the emulator used to produce the movie - rerecordCount (optional) - the rerecord count - romChecksum (optional) - the CRC32 of the rom used to make the movie. should match values specified on advanscene.com - romSerial (optional) - a concatenation of other uniquely identifying information about the rom (name,gamecode,makercode) - useExtBios (optional) - were bios files was used? defaults to false. - swiFromBios (optional) - were swi emulated by ExtBios? (alternative is internal HLE bios). defaults to false. The rom identification information may be used at a later point to warn about mismatches between movies and roms, but is not right now. String keys have values that consist of the remainder of the key-value pair line. As a consequence, string values cannot contain newlines. - romFilename (required) - the name of the file used to record the movie - comment (optional) - simply a memo. by convention, the first token in the comment value is the subject of the comment. by convention, subsequent comments with the same subject will have their ordering preserved and may be used to approximate multiline comments. by convention, the author of the movie should be stored in comment(s) with a subject of: author Hex string keys (used for binary blobs) will have a value that is like 0x0123456789ABCDEF... - romChecksum (required) - this is currently unused. GUID keys have a value which is in the standard guid format: 452DE2C3-EF43-2FA9-77AC-0677FC51543B - guid (required) a unique identifier for a movie, generated when the movie is created, which is used when loading a savestate to make sure it belongs to the current movie. The inputlog section consists of lines beginning and ending with a | (pipe). The fields are as follows, except as noted in note C. |c|.............XXX YYY Z| 'R','L','D','U','T','S','B','A','Y','X','W','E','G' field c is a variable length decimal integer which is a bitfield corresponding to miscellaneous input states which are valid at the start of the frame. Therefore, no miscellaneous commands is represented by a value of 0. Here are the currently defined bit values: 0x01 - Microphone Noise (hardcoded noise sample; to be held through duration of frame) 0x02 - Reset 0x04 - Lid the format of the main section is as follows: the field begins with 13 characters which constitute a bitfield. any character other than ' ' or '.' means that the button was pressed. by convention, the following mnemonics will be used in a column to remind us of which button corresponds to which column: RLDUTSBAYXWEG (Right,Left,Down,Up,sTart,Select,B,A,Y,X,lshoulder,rshoulder,debuG) This ordering is based on FCEUX to a certain extent, and arbitrary after that. W and E were chosen for shoulders to suggest West and East for Left and Right. While the emulator supports a 'lid' button, and to some extent a 'blow' button, these are not supported in the movies. XXX: %03d, the x position of the stylus (0,0 topleft, 255,191 bottomright) YYY: %03d, the y position of the stylus Z: %1d, 1 if the stylus is pressed pressed; 0 if not Additional fields after this main section may be added later without breaking the file format. * Notes * A. There is no key-value pair that indicates the length of the movie. This must be read by scanning the inputlog and counting the number of lines. B. All movies start from power-on. C. The emulator uses these framerate constants arm7_cycles_per_frame = 560190 frames_per_second = 59.8261 desmume/src/utils/AsmJit/core/assembler.cpp000664 001750 001750 00000011166 12755534123 022104 0ustar00sergiosergio000000 000000 // [AsmJit] // Complete JIT Assembler for C++ Language. // // [License] // Zlib - See COPYING file in this package. #define ASMJIT_EXPORTS // [Dependencies - AsmJit] #include "../core/assembler.h" #include "../core/memorymanager.h" #include "../core/intutil.h" // [Dependenceis - C] #include // [Api-Begin] #include "../core/apibegin.h" namespace AsmJit { // ============================================================================ // [AsmJit::Assembler - Construction / Destruction] // ============================================================================ Assembler::Assembler(Context* context) : _zoneMemory(16384 - sizeof(ZoneChunk) - 32), _buffer(), _context(context != NULL ? context : static_cast(JitContext::getGlobal())), _logger(NULL), _error(kErrorOk), _properties(0), _emitOptions(0), _trampolineSize(0), _inlineComment(NULL), _unusedLinks(NULL) { } Assembler::~Assembler() { } // ============================================================================ // [AsmJit::Assembler - Logging] // ============================================================================ void Assembler::setLogger(Logger* logger) { _logger = logger; } // ============================================================================ // [AsmJit::Assembler - Error Handling] // ============================================================================ void Assembler::setError(uint32_t error) { _error = error; if (_error == kErrorOk) return; if (_logger) _logger->logFormat("*** ASSEMBLER ERROR: %s (%u).\n", getErrorString(error), (unsigned int)error); } // ============================================================================ // [AsmJit::Assembler - Properties] // ============================================================================ uint32_t Assembler::getProperty(uint32_t propertyId) const { if (propertyId > 31) return 0; return (_properties & (IntUtil::maskFromIndex(propertyId))) != 0; } void Assembler::setProperty(uint32_t propertyId, uint32_t value) { if (propertyId > 31) return; if (value) _properties |= IntUtil::maskFromIndex(propertyId); else _properties &= ~IntUtil::maskFromIndex(propertyId); } // ============================================================================ // [AsmJit::Assembler - TakeCode] // ============================================================================ uint8_t* Assembler::takeCode() { uint8_t* code = _buffer.take(); _relocData.clear(); _zoneMemory.clear(); if (_error != kErrorOk) setError(kErrorOk); return code; } // ============================================================================ // [AsmJit::Assembler - Clear / Reset] // ============================================================================ void Assembler::clear() { _purge(); if (_error != kErrorOk) setError(kErrorOk); } void Assembler::reset() { _purge(); _zoneMemory.reset(); _buffer.reset(); _labels.reset(); _relocData.reset(); if (_error != kErrorOk) setError(kErrorOk); } void Assembler::_purge() { _zoneMemory.clear(); _buffer.clear(); _emitOptions = 0; _trampolineSize = 0; _inlineComment = NULL; _unusedLinks = NULL; _labels.clear(); _relocData.clear(); } // ============================================================================ // [AsmJit::Assembler - Emit] // ============================================================================ void Assembler::embed(const void* data, size_t len) { if (!canEmit()) return; if (_logger) { size_t i, j; size_t max; char buf[128]; char dot[] = ".data "; char* p; memcpy(buf, dot, ASMJIT_ARRAY_SIZE(dot) - 1); for (i = 0; i < len; i += 16) { max = (len - i < 16) ? len - i : 16; p = buf + ASMJIT_ARRAY_SIZE(dot) - 1; for (j = 0; j < max; j++) p += sprintf(p, "%02X", reinterpret_cast(data)[i+j]); *p++ = '\n'; *p = '\0'; _logger->logString(buf); } } _buffer.emitData(data, len); } // ============================================================================ // [AsmJit::Assembler - Helpers] // ============================================================================ Assembler::LabelLink* Assembler::_newLabelLink() { LabelLink* link = _unusedLinks; if (link) { _unusedLinks = link->prev; } else { link = (LabelLink*)_zoneMemory.alloc(sizeof(LabelLink)); if (link == NULL) return NULL; } // clean link link->prev = NULL; link->offset = 0; link->displacement = 0; link->relocId = -1; return link; } } // AsmJit namespace // [Api-End] #include "../core/apiend.h" desmume/src/utils/AsmJit/core/virtualmemory.h000664 001750 001750 00000005001 12755534123 022502 0ustar00sergiosergio000000 000000 // [AsmJit] // Complete JIT Assembler for C++ Language. // // [License] // Zlib - See COPYING file in this package. // [Guard] #ifndef _ASMJIT_CORE_VIRTUALMEMORY_H #define _ASMJIT_CORE_VIRTUALMEMORY_H // [Dependencies - AsmJit] #include "../core/build.h" // [Api-Begin] #include "../core/apibegin.h" namespace AsmJit { //! @addtogroup AsmJit_Core //! @{ // ============================================================================ // [AsmJit::VirtualMemory] // ============================================================================ //! @brief Class that helps with allocating memory for executing code //! generated by JIT compiler. //! //! There are defined functions that provides facility to allocate and free //! memory where can be executed code. If processor and operating system //! supports execution protection then you can't run code from normally //! malloc()'ed memory. //! //! Functions are internally implemented by operating system dependent way. //! VirtualAlloc() function is used for Windows operating system and mmap() //! for posix ones. If you want to study or create your own functions, look //! at VirtualAlloc() or mmap() documentation (depends on you target OS). //! //! Under posix operating systems is also useable mprotect() function, that //! can enable execution protection to malloc()'ed memory block. struct VirtualMemory { //! @brief Allocate virtual memory. //! //! Pages are readable/writeable, but they are not guaranteed to be //! executable unless 'canExecute' is true. Returns the address of //! allocated memory, or NULL if failed. ASMJIT_API static void* alloc(size_t length, size_t* allocated, bool canExecute); //! @brief Free memory allocated by @c alloc() ASMJIT_API static void free(void* addr, size_t length); #if defined(ASMJIT_WINDOWS) //! @brief Allocate virtual memory of @a hProcess. //! //! @note This function is Windows specific. ASMJIT_API static void* allocProcessMemory(HANDLE hProcess, size_t length, size_t* allocated, bool canExecute); //! @brief Free virtual memory of @a hProcess. //! //! @note This function is Windows specific. ASMJIT_API static void freeProcessMemory(HANDLE hProcess, void* addr, size_t length); #endif // ASMJIT_WINDOWS //! @brief Get the alignment guaranteed by alloc(). ASMJIT_API static size_t getAlignment(); //! @brief Get size of single page. ASMJIT_API static size_t getPageSize(); }; //! @} } // AsmJit namespace // [Api-End] #include "../core/apiend.h" // [Guard] #endif // _ASMJIT_CORE_VIRTUALMEMORY_H desmume/src/addons/slot1_retail_auto.cpp000664 001750 001750 00000005411 12755534123 021546 0ustar00sergiosergio000000 000000 /* Copyright (C) 2013-2105 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the this software. If not, see . */ #include "../slot1.h" #include "../NDSSystem.h" class Slot1_Retail_Auto : public ISlot1Interface { private: ISlot1Interface *mSelectedImplementation; public: Slot1_Retail_Auto() : mSelectedImplementation(NULL) { } virtual Slot1Info const* info() { static Slot1InfoSimple info("Retail (Auto)","Slot1 Retail (auto-selection) card emulation", 0xFE); return &info; } virtual void connect() { NDS_SLOT1_TYPE selection = NDS_SLOT1_RETAIL_MCROM; //check game ID in core emulator and select right implementation if ((memcmp(gameInfo.header.gameCode, "UOR", 3) == 0) || // WarioWare - D.I.Y. (U)(E)(EUR) / Made in Ore (J) (memcmp(gameInfo.header.gameCode, "UXBP", 4) == 0) // Jam with the Band (EUR) ) selection = NDS_SLOT1_RETAIL_NAND; slot1_selected_type = selection; mSelectedImplementation = slot1_List[selection]; mSelectedImplementation->connect(); printf("Slot1 auto-selected device type: %s\n",mSelectedImplementation->info()->name()); } virtual void disconnect() { if(mSelectedImplementation) mSelectedImplementation->disconnect(); mSelectedImplementation = NULL; } virtual void write_command(u8 PROCNUM, GC_Command command) { mSelectedImplementation->write_command(PROCNUM, command); } virtual void write_GCDATAIN(u8 PROCNUM, u32 val) { mSelectedImplementation->write_GCDATAIN(PROCNUM, val); } virtual u32 read_GCDATAIN(u8 PROCNUM) { return mSelectedImplementation->read_GCDATAIN(PROCNUM); } virtual u8 auxspi_transaction(int PROCNUM, u8 value) { return mSelectedImplementation->auxspi_transaction(PROCNUM, value); } virtual void auxspi_reset(int PROCNUM) { mSelectedImplementation->auxspi_reset(PROCNUM); } virtual void post_fakeboot(int PROCNUM) { mSelectedImplementation->post_fakeboot(PROCNUM); } virtual void savestate(EMUFILE* os) { mSelectedImplementation->savestate(os); } virtual void loadstate(EMUFILE* is) { mSelectedImplementation->loadstate(is); } }; ISlot1Interface* construct_Slot1_Retail_Auto() { return new Slot1_Retail_Auto(); } desmume/src/libretro-common/glsym/rglgen.c000664 001750 001750 00000003454 12755534123 022032 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2015 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this libretro SDK code part (glsym). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include #include #include #include void rglgen_resolve_symbols_custom(rglgen_proc_address_t proc, const struct rglgen_sym_map *map) { for (; map->sym; map++) { rglgen_func_t func = proc(map->sym); memcpy(map->ptr, &func, sizeof(func)); } } void rglgen_resolve_symbols(rglgen_proc_address_t proc) { rglgen_resolve_symbols_custom(proc, rglgen_symbol_map); } desmume/src/libretro-common/formats/png/rpng.c000664 001750 001750 00000072165 12755534123 022633 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2016 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (rpng.c). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include #include #include #include #ifdef GEKKO #include #endif #include #include #include #include #include "rpng_internal.h" enum png_ihdr_color_type { PNG_IHDR_COLOR_GRAY = 0, PNG_IHDR_COLOR_RGB = 2, PNG_IHDR_COLOR_PLT = 3, PNG_IHDR_COLOR_GRAY_ALPHA = 4, PNG_IHDR_COLOR_RGBA = 6 }; enum png_line_filter { PNG_FILTER_NONE = 0, PNG_FILTER_SUB, PNG_FILTER_UP, PNG_FILTER_AVERAGE, PNG_FILTER_PAETH }; enum png_chunk_type { PNG_CHUNK_NOOP = 0, PNG_CHUNK_ERROR, PNG_CHUNK_IHDR, PNG_CHUNK_IDAT, PNG_CHUNK_PLTE, PNG_CHUNK_tRNS, PNG_CHUNK_IEND }; struct adam7_pass { unsigned x; unsigned y; unsigned stride_x; unsigned stride_y; }; struct idat_buffer { uint8_t *data; size_t size; }; struct png_chunk { uint32_t size; char type[4]; uint8_t *data; }; struct rpng_process { bool inflate_initialized; bool adam7_pass_initialized; bool pass_initialized; uint32_t *data; uint32_t *palette; struct png_ihdr ihdr; uint8_t *prev_scanline; uint8_t *decoded_scanline; uint8_t *inflate_buf; size_t restore_buf_size; size_t adam7_restore_buf_size; size_t data_restore_buf_size; size_t inflate_buf_size; unsigned bpp; unsigned pitch; unsigned h; struct { unsigned width; unsigned height; size_t size; unsigned pos; } pass; void *stream; const struct file_archive_file_backend *stream_backend; }; struct rpng { struct rpng_process *process; bool has_ihdr; bool has_idat; bool has_iend; bool has_plte; bool has_trns; struct idat_buffer idat_buf; struct png_ihdr ihdr; uint8_t *buff_data; uint32_t palette[256]; }; static INLINE uint32_t dword_be(const uint8_t *buf) { return (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | (buf[3] << 0); } static enum png_chunk_type png_chunk_type(const struct png_chunk *chunk) { unsigned i; struct { const char *id; enum png_chunk_type type; } static const chunk_map[] = { { "IHDR", PNG_CHUNK_IHDR }, { "IDAT", PNG_CHUNK_IDAT }, { "IEND", PNG_CHUNK_IEND }, { "PLTE", PNG_CHUNK_PLTE }, { "tRNS", PNG_CHUNK_tRNS }, }; for (i = 0; i < ARRAY_SIZE(chunk_map); i++) { if (memcmp(chunk->type, chunk_map[i].id, 4) == 0) return chunk_map[i].type; } return PNG_CHUNK_NOOP; } static bool png_process_ihdr(struct png_ihdr *ihdr) { unsigned i; bool ret = true; switch (ihdr->color_type) { case PNG_IHDR_COLOR_RGB: case PNG_IHDR_COLOR_GRAY_ALPHA: case PNG_IHDR_COLOR_RGBA: if (ihdr->depth != 8 && ihdr->depth != 16) GOTO_END_ERROR(); break; case PNG_IHDR_COLOR_GRAY: { static const unsigned valid_bpp[] = { 1, 2, 4, 8, 16 }; bool correct_bpp = false; for (i = 0; i < ARRAY_SIZE(valid_bpp); i++) { if (valid_bpp[i] == ihdr->depth) { correct_bpp = true; break; } } if (!correct_bpp) GOTO_END_ERROR(); } break; case PNG_IHDR_COLOR_PLT: { static const unsigned valid_bpp[] = { 1, 2, 4, 8 }; bool correct_bpp = false; for (i = 0; i < ARRAY_SIZE(valid_bpp); i++) { if (valid_bpp[i] == ihdr->depth) { correct_bpp = true; break; } } if (!correct_bpp) GOTO_END_ERROR(); } break; default: GOTO_END_ERROR(); } #ifdef RPNG_TEST fprintf(stderr, "IHDR: (%u x %u), bpc = %u, palette = %s, color = %s, alpha = %s, adam7 = %s.\n", ihdr->width, ihdr->height, ihdr->depth, (ihdr->color_type == PNG_IHDR_COLOR_PLT) ? "yes" : "no", (ihdr->color_type & PNG_IHDR_COLOR_RGB) ? "yes" : "no", (ihdr->color_type & PNG_IHDR_COLOR_GRAY_ALPHA) ? "yes" : "no", ihdr->interlace == 1 ? "yes" : "no"); #endif if (ihdr->compression != 0) GOTO_END_ERROR(); end: return ret; } static void png_reverse_filter_copy_line_rgb(uint32_t *data, const uint8_t *decoded, unsigned width, unsigned bpp) { unsigned i; bpp /= 8; for (i = 0; i < width; i++) { uint32_t r, g, b; r = *decoded; decoded += bpp; g = *decoded; decoded += bpp; b = *decoded; decoded += bpp; data[i] = (0xffu << 24) | (r << 16) | (g << 8) | (b << 0); } } static void png_reverse_filter_copy_line_rgba(uint32_t *data, const uint8_t *decoded, unsigned width, unsigned bpp) { unsigned i; bpp /= 8; for (i = 0; i < width; i++) { uint32_t r, g, b, a; r = *decoded; decoded += bpp; g = *decoded; decoded += bpp; b = *decoded; decoded += bpp; a = *decoded; decoded += bpp; data[i] = (a << 24) | (r << 16) | (g << 8) | (b << 0); } } static void png_reverse_filter_copy_line_bw(uint32_t *data, const uint8_t *decoded, unsigned width, unsigned depth) { unsigned i, bit; static const unsigned mul_table[] = { 0, 0xff, 0x55, 0, 0x11, 0, 0, 0, 0x01 }; unsigned mul, mask; if (depth == 16) { for (i = 0; i < width; i++) { uint32_t val = decoded[i << 1]; data[i] = (val * 0x010101) | (0xffu << 24); } return; } mul = mul_table[depth]; mask = (1 << depth) - 1; bit = 0; for (i = 0; i < width; i++, bit += depth) { unsigned byte = bit >> 3; unsigned val = decoded[byte] >> (8 - depth - (bit & 7)); val &= mask; val *= mul; data[i] = (val * 0x010101) | (0xffu << 24); } } static void png_reverse_filter_copy_line_gray_alpha(uint32_t *data, const uint8_t *decoded, unsigned width, unsigned bpp) { unsigned i; bpp /= 8; for (i = 0; i < width; i++) { uint32_t gray, alpha; gray = *decoded; decoded += bpp; alpha = *decoded; decoded += bpp; data[i] = (gray * 0x010101) | (alpha << 24); } } static void png_reverse_filter_copy_line_plt(uint32_t *data, const uint8_t *decoded, unsigned width, unsigned depth, const uint32_t *palette) { switch (depth) { case 1: { unsigned w = width / 8; unsigned i; for (i = 0; i < w; i++, decoded++) { *data++ = palette[(*decoded >> 7) & 1]; *data++ = palette[(*decoded >> 6) & 1]; *data++ = palette[(*decoded >> 5) & 1]; *data++ = palette[(*decoded >> 4) & 1]; *data++ = palette[(*decoded >> 3) & 1]; *data++ = palette[(*decoded >> 2) & 1]; *data++ = palette[(*decoded >> 1) & 1]; *data++ = palette[*decoded & 1]; } switch (width & 7) { case 7: data[6] = palette[(*decoded >> 1) & 1]; case 6: data[5] = palette[(*decoded >> 2) & 1]; case 5: data[4] = palette[(*decoded >> 3) & 1]; case 4: data[3] = palette[(*decoded >> 4) & 1]; case 3: data[2] = palette[(*decoded >> 5) & 1]; case 2: data[1] = palette[(*decoded >> 6) & 1]; case 1: data[0] = palette[(*decoded >> 7) & 1]; break; } } break; case 2: { unsigned w = width / 4; unsigned i; for (i = 0; i < w; i++, decoded++) { *data++ = palette[(*decoded >> 6) & 3]; *data++ = palette[(*decoded >> 4) & 3]; *data++ = palette[(*decoded >> 2) & 3]; *data++ = palette[*decoded & 3]; } switch (width & 3) { case 3: data[2] = palette[(*decoded >> 2) & 3]; case 2: data[1] = palette[(*decoded >> 4) & 3]; case 1: data[0] = palette[(*decoded >> 6) & 3]; break; } } break; case 4: { unsigned w = width / 2; unsigned i; for (i = 0; i < w; i++, decoded++) { *data++ = palette[*decoded >> 4]; *data++ = palette[*decoded & 0x0f]; } if (width & 1) { *data = palette[*decoded >> 4]; } } break; case 8: { unsigned i; for (i = 0; i < width; i++, decoded++, data++) { *data = palette[*decoded]; } } break; } } static void png_pass_geom(const struct png_ihdr *ihdr, unsigned width, unsigned height, unsigned *bpp_out, unsigned *pitch_out, size_t *pass_size) { unsigned bpp; unsigned pitch; switch (ihdr->color_type) { case PNG_IHDR_COLOR_GRAY: bpp = (ihdr->depth + 7) / 8; pitch = (ihdr->width * ihdr->depth + 7) / 8; break; case PNG_IHDR_COLOR_RGB: bpp = (ihdr->depth * 3 + 7) / 8; pitch = (ihdr->width * ihdr->depth * 3 + 7) / 8; break; case PNG_IHDR_COLOR_PLT: bpp = (ihdr->depth + 7) / 8; pitch = (ihdr->width * ihdr->depth + 7) / 8; break; case PNG_IHDR_COLOR_GRAY_ALPHA: bpp = (ihdr->depth * 2 + 7) / 8; pitch = (ihdr->width * ihdr->depth * 2 + 7) / 8; break; case PNG_IHDR_COLOR_RGBA: bpp = (ihdr->depth * 4 + 7) / 8; pitch = (ihdr->width * ihdr->depth * 4 + 7) / 8; break; default: bpp = 0; pitch = 0; break; } if (pass_size) *pass_size = (pitch + 1) * ihdr->height; if (bpp_out) *bpp_out = bpp; if (pitch_out) *pitch_out = pitch; } static void png_reverse_filter_adam7_deinterlace_pass(uint32_t *data, const struct png_ihdr *ihdr, const uint32_t *input, unsigned pass_width, unsigned pass_height, const struct adam7_pass *pass) { unsigned x, y; data += pass->y * ihdr->width + pass->x; for (y = 0; y < pass_height; y++, data += ihdr->width * pass->stride_y, input += pass_width) { uint32_t *out = data; for (x = 0; x < pass_width; x++, out += pass->stride_x) *out = input[x]; } } static void png_reverse_filter_deinit(struct rpng_process *pngp) { if (pngp->decoded_scanline) free(pngp->decoded_scanline); pngp->decoded_scanline = NULL; if (pngp->prev_scanline) free(pngp->prev_scanline); pngp->prev_scanline = NULL; pngp->pass_initialized = false; pngp->h = 0; } static const struct adam7_pass passes[] = { { 0, 0, 8, 8 }, { 4, 0, 8, 8 }, { 0, 4, 4, 8 }, { 2, 0, 4, 4 }, { 0, 2, 2, 4 }, { 1, 0, 2, 2 }, { 0, 1, 1, 2 }, }; static int png_reverse_filter_init(const struct png_ihdr *ihdr, struct rpng_process *pngp) { size_t pass_size; if (!pngp->adam7_pass_initialized && ihdr->interlace) { if (ihdr->width <= passes[pngp->pass.pos].x || ihdr->height <= passes[pngp->pass.pos].y) /* Empty pass */ return 1; pngp->pass.width = (ihdr->width - passes[pngp->pass.pos].x + passes[pngp->pass.pos].stride_x - 1) / passes[pngp->pass.pos].stride_x; pngp->pass.height = (ihdr->height - passes[pngp->pass.pos].y + passes[pngp->pass.pos].stride_y - 1) / passes[pngp->pass.pos].stride_y; pngp->data = (uint32_t*)malloc( pngp->pass.width * pngp->pass.height * sizeof(uint32_t)); if (!pngp->data) return -1; pngp->ihdr = *ihdr; pngp->ihdr.width = pngp->pass.width; pngp->ihdr.height = pngp->pass.height; png_pass_geom(&pngp->ihdr, pngp->pass.width, pngp->pass.height, NULL, NULL, &pngp->pass.size); if (pngp->pass.size > pngp->stream_backend->stream_get_total_out(pngp->stream)) { free(pngp->data); return -1; } pngp->adam7_pass_initialized = true; return 0; } if (pngp->pass_initialized) return 0; png_pass_geom(ihdr, ihdr->width, ihdr->height, &pngp->bpp, &pngp->pitch, &pass_size); if (pngp->stream_backend->stream_get_total_out(pngp->stream) < pass_size) return -1; pngp->restore_buf_size = 0; pngp->data_restore_buf_size = 0; pngp->prev_scanline = (uint8_t*)calloc(1, pngp->pitch); pngp->decoded_scanline = (uint8_t*)calloc(1, pngp->pitch); if (!pngp->prev_scanline || !pngp->decoded_scanline) goto error; pngp->h = 0; pngp->pass_initialized = true; return 0; error: png_reverse_filter_deinit(pngp); return -1; } static int png_reverse_filter_copy_line(uint32_t *data, const struct png_ihdr *ihdr, struct rpng_process *pngp, unsigned filter) { unsigned i; switch (filter) { case PNG_FILTER_NONE: memcpy(pngp->decoded_scanline, pngp->inflate_buf, pngp->pitch); break; case PNG_FILTER_SUB: for (i = 0; i < pngp->bpp; i++) pngp->decoded_scanline[i] = pngp->inflate_buf[i]; for (i = pngp->bpp; i < pngp->pitch; i++) pngp->decoded_scanline[i] = pngp->decoded_scanline[i - pngp->bpp] + pngp->inflate_buf[i]; break; case PNG_FILTER_UP: for (i = 0; i < pngp->pitch; i++) pngp->decoded_scanline[i] = pngp->prev_scanline[i] + pngp->inflate_buf[i]; break; case PNG_FILTER_AVERAGE: for (i = 0; i < pngp->bpp; i++) { uint8_t avg = pngp->prev_scanline[i] >> 1; pngp->decoded_scanline[i] = avg + pngp->inflate_buf[i]; } for (i = pngp->bpp; i < pngp->pitch; i++) { uint8_t avg = (pngp->decoded_scanline[i - pngp->bpp] + pngp->prev_scanline[i]) >> 1; pngp->decoded_scanline[i] = avg + pngp->inflate_buf[i]; } break; case PNG_FILTER_PAETH: for (i = 0; i < pngp->bpp; i++) pngp->decoded_scanline[i] = paeth(0, pngp->prev_scanline[i], 0) + pngp->inflate_buf[i]; for (i = pngp->bpp; i < pngp->pitch; i++) pngp->decoded_scanline[i] = paeth(pngp->decoded_scanline[i - pngp->bpp], pngp->prev_scanline[i], pngp->prev_scanline[i - pngp->bpp]) + pngp->inflate_buf[i]; break; default: return IMAGE_PROCESS_ERROR_END; } switch (ihdr->color_type) { case PNG_IHDR_COLOR_GRAY: png_reverse_filter_copy_line_bw(data, pngp->decoded_scanline, ihdr->width, ihdr->depth); break; case PNG_IHDR_COLOR_RGB: png_reverse_filter_copy_line_rgb(data, pngp->decoded_scanline, ihdr->width, ihdr->depth); break; case PNG_IHDR_COLOR_PLT: png_reverse_filter_copy_line_plt(data, pngp->decoded_scanline, ihdr->width, ihdr->depth, pngp->palette); break; case PNG_IHDR_COLOR_GRAY_ALPHA: png_reverse_filter_copy_line_gray_alpha(data, pngp->decoded_scanline, ihdr->width, ihdr->depth); break; case PNG_IHDR_COLOR_RGBA: png_reverse_filter_copy_line_rgba(data, pngp->decoded_scanline, ihdr->width, ihdr->depth); break; } memcpy(pngp->prev_scanline, pngp->decoded_scanline, pngp->pitch); return IMAGE_PROCESS_NEXT; } static int png_reverse_filter_regular_iterate(uint32_t **data, const struct png_ihdr *ihdr, struct rpng_process *pngp) { int ret = IMAGE_PROCESS_END; if (pngp->h < ihdr->height) { unsigned filter = *pngp->inflate_buf++; pngp->restore_buf_size += 1; ret = png_reverse_filter_copy_line(*data, ihdr, pngp, filter); } if (ret == IMAGE_PROCESS_END || ret == IMAGE_PROCESS_ERROR_END) goto end; pngp->h++; pngp->inflate_buf += pngp->pitch; pngp->restore_buf_size += pngp->pitch; *data += ihdr->width; pngp->data_restore_buf_size += ihdr->width; return IMAGE_PROCESS_NEXT; end: png_reverse_filter_deinit(pngp); pngp->inflate_buf -= pngp->restore_buf_size; *data -= pngp->data_restore_buf_size; pngp->data_restore_buf_size = 0; return ret; } static int png_reverse_filter_adam7_iterate(uint32_t **data_, const struct png_ihdr *ihdr, struct rpng_process *pngp) { int ret = 0; bool to_next = pngp->pass.pos < ARRAY_SIZE(passes); uint32_t *data = *data_; if (!to_next) return IMAGE_PROCESS_END; ret = png_reverse_filter_init(ihdr, pngp); if (ret == 1) return IMAGE_PROCESS_NEXT; if (ret == -1) return IMAGE_PROCESS_ERROR_END; if (png_reverse_filter_init(&pngp->ihdr, pngp) == -1) return IMAGE_PROCESS_ERROR; do{ ret = png_reverse_filter_regular_iterate(&pngp->data, &pngp->ihdr, pngp); }while(ret == IMAGE_PROCESS_NEXT); if (ret == IMAGE_PROCESS_ERROR || ret == IMAGE_PROCESS_ERROR_END) return IMAGE_PROCESS_ERROR; pngp->inflate_buf += pngp->pass.size; pngp->adam7_restore_buf_size += pngp->pass.size; pngp->stream_backend->stream_decrement_total_out(pngp->stream, pngp->pass.size); png_reverse_filter_adam7_deinterlace_pass(data, ihdr, pngp->data, pngp->pass.width, pngp->pass.height, &passes[pngp->pass.pos]); free(pngp->data); pngp->pass.width = 0; pngp->pass.height = 0; pngp->pass.size = 0; pngp->adam7_pass_initialized = false; return IMAGE_PROCESS_NEXT; } static int png_reverse_filter_adam7(uint32_t **data_, const struct png_ihdr *ihdr, struct rpng_process *pngp) { int ret = png_reverse_filter_adam7_iterate(data_, ihdr, pngp); switch (ret) { case IMAGE_PROCESS_ERROR_END: case IMAGE_PROCESS_END: break; case IMAGE_PROCESS_NEXT: pngp->pass.pos++; return 0; case IMAGE_PROCESS_ERROR: if (pngp->data) free(pngp->data); pngp->inflate_buf -= pngp->adam7_restore_buf_size; pngp->adam7_restore_buf_size = 0; return -1; } pngp->inflate_buf -= pngp->adam7_restore_buf_size; pngp->adam7_restore_buf_size = 0; return ret; } static int png_reverse_filter_iterate(rpng_t *rpng, uint32_t **data) { if (!rpng) return false; if (rpng->ihdr.interlace) return png_reverse_filter_adam7(data, &rpng->ihdr, rpng->process); return png_reverse_filter_regular_iterate(data, &rpng->ihdr, rpng->process); } static int rpng_load_image_argb_process_inflate_init(rpng_t *rpng, uint32_t **data, unsigned *width, unsigned *height) { int zstatus; struct rpng_process *process = (struct rpng_process*)rpng->process; bool to_continue = (process->stream_backend->stream_get_avail_in(process->stream) > 0 && process->stream_backend->stream_get_avail_out(process->stream) > 0); if (!to_continue) goto end; zstatus = process->stream_backend->stream_decompress_data_to_file_iterate(process->stream); switch (zstatus) { case 1: goto end; case -1: goto error; default: break; } return 0; end: process->stream_backend->stream_free(process->stream); *width = rpng->ihdr.width; *height = rpng->ihdr.height; #ifdef GEKKO /* we often use these in textures, make sure they're 32-byte aligned */ *data = (uint32_t*)memalign(32, rpng->ihdr.width * rpng->ihdr.height * sizeof(uint32_t)); #else *data = (uint32_t*)malloc(rpng->ihdr.width * rpng->ihdr.height * sizeof(uint32_t)); #endif if (!*data) goto false_end; process->adam7_restore_buf_size = 0; process->restore_buf_size = 0; process->palette = rpng->palette; if (rpng->ihdr.interlace != 1) if (png_reverse_filter_init(&rpng->ihdr, process) == -1) goto false_end; process->inflate_initialized = true; return 1; error: false_end: process->inflate_initialized = false; return -1; } static bool png_read_plte(uint8_t *buf, uint32_t *buffer, unsigned entries) { unsigned i; for (i = 0; i < entries; i++) { uint32_t r = buf[3 * i + 0]; uint32_t g = buf[3 * i + 1]; uint32_t b = buf[3 * i + 2]; buffer[i] = (r << 16) | (g << 8) | (b << 0) | (0xffu << 24); } return true; } static bool png_read_trns(uint8_t *buf, uint32_t *palette, unsigned entries) { unsigned i; for (i = 0; i < entries; i++, buf++, palette++) { *palette = (*palette & 0x00ffffff) | *buf << 24; } return true; } bool png_realloc_idat(const struct png_chunk *chunk, struct idat_buffer *buf) { uint8_t *new_buffer = (uint8_t*)realloc(buf->data, buf->size + chunk->size); if (!new_buffer) return false; buf->data = new_buffer; return true; } static struct rpng_process *rpng_process_init(rpng_t *rpng, unsigned *width, unsigned *height) { uint8_t *inflate_buf = NULL; struct rpng_process *process = (struct rpng_process*)calloc(1, sizeof(*process)); if (!process) return NULL; process->stream_backend = file_archive_get_default_file_backend(); png_pass_geom(&rpng->ihdr, rpng->ihdr.width, rpng->ihdr.height, NULL, NULL, &process->inflate_buf_size); if (rpng->ihdr.interlace == 1) /* To be sure. */ process->inflate_buf_size *= 2; process->stream = process->stream_backend->stream_new(); if (!process->stream) { free(process); return NULL; } if (!process->stream_backend->stream_decompress_init(process->stream)) { free(process); return NULL; } inflate_buf = (uint8_t*)malloc(process->inflate_buf_size); if (!inflate_buf) goto error; process->inflate_buf = inflate_buf; process->stream_backend->stream_set( process->stream, rpng->idat_buf.size, process->inflate_buf_size, rpng->idat_buf.data, process->inflate_buf); return process; error: if (process) { if (process->stream) process->stream_backend->stream_free(process->stream); free(process); } return NULL; } static bool read_chunk_header(uint8_t *buf, struct png_chunk *chunk) { unsigned i; uint8_t dword[4] = {0}; for (i = 0; i < 4; i++) dword[i] = buf[i]; chunk->size = dword_be(dword); for (i = 0; i < 4; i++) chunk->type[i] = buf[i + 4]; return true; } static bool png_parse_ihdr(uint8_t *buf, struct png_ihdr *ihdr) { buf += 4 + 4; ihdr->width = dword_be(buf + 0); ihdr->height = dword_be(buf + 4); ihdr->depth = buf[8]; ihdr->color_type = buf[9]; ihdr->compression = buf[10]; ihdr->filter = buf[11]; ihdr->interlace = buf[12]; if (ihdr->width == 0 || ihdr->height == 0) return false; return true; } bool rpng_iterate_image(rpng_t *rpng) { unsigned i; struct png_chunk chunk = {0}; uint8_t *buf = (uint8_t*)rpng->buff_data; if (!read_chunk_header(buf, &chunk)) return false; *buf += 8; #if 0 for (i = 0; i < 4; i++) { fprintf(stderr, "chunktype: %c\n", chunk.type[i]); } #endif switch (png_chunk_type(&chunk)) { case PNG_CHUNK_NOOP: default: break; case PNG_CHUNK_ERROR: goto error; case PNG_CHUNK_IHDR: if (rpng->has_ihdr || rpng->has_idat || rpng->has_iend) goto error; if (chunk.size != 13) goto error; if (!png_parse_ihdr(buf, &rpng->ihdr)) goto error; if (!png_process_ihdr(&rpng->ihdr)) goto error; rpng->has_ihdr = true; break; case PNG_CHUNK_PLTE: { unsigned entries = chunk.size / 3; if (!rpng->has_ihdr || rpng->has_plte || rpng->has_iend || rpng->has_idat || rpng->has_trns) goto error; if (chunk.size % 3) goto error; if (entries > 256) goto error; buf += 8; if (!png_read_plte(buf, rpng->palette, entries)) goto error; rpng->has_plte = true; } break; case PNG_CHUNK_tRNS: if (rpng->has_idat) goto error; if (rpng->ihdr.color_type == PNG_IHDR_COLOR_PLT) { /* we should compare with the number of palette entries */ if (chunk.size > 256) goto error; buf += 8; if (!png_read_trns(buf, rpng->palette, chunk.size)) goto error; } /* TODO: support colorkey in grayscale and truecolor images */ rpng->has_trns = true; break; case PNG_CHUNK_IDAT: if (!(rpng->has_ihdr) || rpng->has_iend || (rpng->ihdr.color_type == PNG_IHDR_COLOR_PLT && !(rpng->has_plte))) goto error; if (!png_realloc_idat(&chunk, &rpng->idat_buf)) goto error; buf += 8; for (i = 0; i < chunk.size; i++) rpng->idat_buf.data[i + rpng->idat_buf.size] = buf[i]; rpng->idat_buf.size += chunk.size; rpng->has_idat = true; break; case PNG_CHUNK_IEND: if (!(rpng->has_ihdr) || !(rpng->has_idat)) goto error; rpng->has_iend = true; goto error; } rpng->buff_data += chunk.size + 12; return true; error: return false; } int rpng_process_image(rpng_t *rpng, void **_data, size_t size, unsigned *width, unsigned *height) { uint32_t **data = (uint32_t**)_data; (void)size; if (!rpng->process) { struct rpng_process *process = rpng_process_init( rpng, width, height); if (!process) goto error; rpng->process = process; return IMAGE_PROCESS_NEXT; } if (!rpng->process->inflate_initialized) { if (rpng_load_image_argb_process_inflate_init(rpng, data, width, height) == -1) goto error; return IMAGE_PROCESS_NEXT; } return png_reverse_filter_iterate(rpng, data); error: if (rpng->process) { if (rpng->process->inflate_buf) free(rpng->process->inflate_buf); if (rpng->process->stream) rpng->process->stream_backend->stream_free(rpng->process->stream); free(rpng->process); } return IMAGE_PROCESS_ERROR; } void rpng_free(rpng_t *rpng) { if (!rpng) return; if (rpng->idat_buf.data) free(rpng->idat_buf.data); if (rpng->process) { if (rpng->process->inflate_buf) free(rpng->process->inflate_buf); if (rpng->process->stream) { if (rpng->process->stream_backend) rpng->process->stream_backend->stream_free(rpng->process->stream); free(rpng->process->stream); } free(rpng->process); } free(rpng); } bool rpng_start(rpng_t *rpng) { unsigned i; char header[8] = {0}; if (!rpng) return false; for (i = 0; i < 8; i++) header[i] = rpng->buff_data[i]; if (memcmp(header, png_magic, sizeof(png_magic)) != 0) return false; rpng->buff_data += 8; return true; } bool rpng_is_valid(rpng_t *rpng) { if (!rpng) return false; if (rpng->has_ihdr) return true; if (rpng->has_idat) return true; if (rpng->has_iend) return true; return false; } bool rpng_set_buf_ptr(rpng_t *rpng, void *data) { if (!rpng) return false; rpng->buff_data = (uint8_t*)data; return true; } rpng_t *rpng_alloc(void) { rpng_t *rpng = (rpng_t*)calloc(1, sizeof(rpng_t)); if (!rpng) return NULL; return rpng; } desmume/000700 001750 001750 00000000000 12756420130 013325 5ustar00sergiosergio000000 000000 desmume/src/libretro-common/include/retro_common.h000664 001750 001750 00000003510 12755534123 023545 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2016 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (retro_common.h). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef _LIBRETRO_COMMON_RETRO_COMMON_H #define _LIBRETRO_COMMON_RETRO_COMMON_H /* This file is designed to normalize the libretro-common compiling environment. It is not to be used in public API headers, as they should be designed as leanly as possible. Nonetheless.. in the meantime, if you do something like use ssize_t, which is not fully portable, in a public API, you may need this. */ /* conditional compilation is handled inside here */ #include #endif desmume/src/utils/AsmJit/core/memorymarker.cpp000664 001750 001750 00000001145 12755534123 022635 0ustar00sergiosergio000000 000000 // [AsmJit] // Complete JIT Assembler for C++ Language. // // [License] // Zlib - See COPYING file in this package. #define ASMJIT_EXPORTS // [Dependencies - AsmJit] #include "../core/build.h" #include "../core/memorymarker.h" // [Api-Begin] #include "../core/apibegin.h" namespace AsmJit { // ============================================================================ // [AsmJit::MemoryMarker] // ============================================================================ MemoryMarker::MemoryMarker() {} MemoryMarker::~MemoryMarker() {} } // AsmJit namespace // [Api-End] #include "../core/apiend.h" desmume/src/libretro/link.T000664 001750 001750 00000000046 12755534123 017043 0ustar00sergiosergio000000 000000 { global: retro_*; local: *; }; desmume/src/libretro-common/formats/xml/test/000700 001750 001750 00000000000 12756420131 022457 5ustar00sergiosergio000000 000000 desmume/src/libretro-common/include/glsym/glsym_es3.h000664 001750 001750 00000044347 12755534123 024117 0ustar00sergiosergio000000 000000 #ifndef RGLGEN_DECL_H__ #define RGLGEN_DECL_H__ #ifdef __cplusplus extern "C" { #endif #ifdef GL_APIENTRY typedef void (GL_APIENTRY *RGLGENGLDEBUGPROC)(GLenum, GLenum, GLuint, GLenum, GLsizei, const GLchar*, GLvoid*); typedef void (GL_APIENTRY *RGLGENGLDEBUGPROCKHR)(GLenum, GLenum, GLuint, GLenum, GLsizei, const GLchar*, GLvoid*); #else #ifndef APIENTRY #define APIENTRY #endif #ifndef APIENTRYP #define APIENTRYP APIENTRY * #endif typedef void (APIENTRY *RGLGENGLDEBUGPROCARB)(GLenum, GLenum, GLuint, GLenum, GLsizei, const GLchar*, GLvoid*); typedef void (APIENTRY *RGLGENGLDEBUGPROC)(GLenum, GLenum, GLuint, GLenum, GLsizei, const GLchar*, GLvoid*); #endif #ifndef GL_OES_EGL_image typedef void *GLeglImageOES; #endif #if !defined(GL_OES_fixed_point) && !defined(HAVE_OPENGLES2) typedef GLint GLfixed; #endif #if defined(OSX) && !defined(MAC_OS_X_VERSION_10_7) typedef long long int GLint64; typedef unsigned long long int GLuint64; typedef unsigned long long int GLuint64EXT; typedef struct __GLsync *GLsync; #endif typedef void (GL_APIENTRYP RGLSYMGLBLENDBARRIERKHRPROC) (void); typedef void (GL_APIENTRYP RGLSYMGLDEBUGMESSAGECONTROLKHRPROC) (GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled); typedef void (GL_APIENTRYP RGLSYMGLDEBUGMESSAGEINSERTKHRPROC) (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *buf); typedef void (GL_APIENTRYP RGLSYMGLDEBUGMESSAGECALLBACKKHRPROC) (RGLGENGLDEBUGPROCKHR callback, const void *userParam); typedef GLuint (GL_APIENTRYP RGLSYMGLGETDEBUGMESSAGELOGKHRPROC) (GLuint count, GLsizei bufSize, GLenum *sources, GLenum *types, GLuint *ids, GLenum *severities, GLsizei *lengths, GLchar *messageLog); typedef void (GL_APIENTRYP RGLSYMGLPUSHDEBUGGROUPKHRPROC) (GLenum source, GLuint id, GLsizei length, const GLchar *message); typedef void (GL_APIENTRYP RGLSYMGLPOPDEBUGGROUPKHRPROC) (void); typedef void (GL_APIENTRYP RGLSYMGLOBJECTLABELKHRPROC) (GLenum identifier, GLuint name, GLsizei length, const GLchar *label); typedef void (GL_APIENTRYP RGLSYMGLGETOBJECTLABELKHRPROC) (GLenum identifier, GLuint name, GLsizei bufSize, GLsizei *length, GLchar *label); typedef void (GL_APIENTRYP RGLSYMGLOBJECTPTRLABELKHRPROC) (const void *ptr, GLsizei length, const GLchar *label); typedef void (GL_APIENTRYP RGLSYMGLGETOBJECTPTRLABELKHRPROC) (const void *ptr, GLsizei bufSize, GLsizei *length, GLchar *label); typedef void (GL_APIENTRYP RGLSYMGLGETPOINTERVKHRPROC) (GLenum pname, void **params); typedef GLenum (GL_APIENTRYP RGLSYMGLGETGRAPHICSRESETSTATUSKHRPROC) (void); typedef void (GL_APIENTRYP RGLSYMGLREADNPIXELSKHRPROC) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void *data); typedef void (GL_APIENTRYP RGLSYMGLGETNUNIFORMFVKHRPROC) (GLuint program, GLint location, GLsizei bufSize, GLfloat *params); typedef void (GL_APIENTRYP RGLSYMGLGETNUNIFORMIVKHRPROC) (GLuint program, GLint location, GLsizei bufSize, GLint *params); typedef void (GL_APIENTRYP RGLSYMGLGETNUNIFORMUIVKHRPROC) (GLuint program, GLint location, GLsizei bufSize, GLuint *params); typedef void (GL_APIENTRYP RGLSYMGLEGLIMAGETARGETTEXTURE2DOESPROC) (GLenum target, GLeglImageOES image); typedef void (GL_APIENTRYP RGLSYMGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC) (GLenum target, GLeglImageOES image); typedef void (GL_APIENTRYP RGLSYMGLCOPYIMAGESUBDATAOESPROC) (GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth); typedef void (GL_APIENTRYP RGLSYMGLENABLEIOESPROC) (GLenum target, GLuint index); typedef void (GL_APIENTRYP RGLSYMGLDISABLEIOESPROC) (GLenum target, GLuint index); typedef void (GL_APIENTRYP RGLSYMGLBLENDEQUATIONIOESPROC) (GLuint buf, GLenum mode); typedef void (GL_APIENTRYP RGLSYMGLBLENDEQUATIONSEPARATEIOESPROC) (GLuint buf, GLenum modeRGB, GLenum modeAlpha); typedef void (GL_APIENTRYP RGLSYMGLBLENDFUNCIOESPROC) (GLuint buf, GLenum src, GLenum dst); typedef void (GL_APIENTRYP RGLSYMGLBLENDFUNCSEPARATEIOESPROC) (GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha); typedef void (GL_APIENTRYP RGLSYMGLCOLORMASKIOESPROC) (GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a); typedef GLboolean (GL_APIENTRYP RGLSYMGLISENABLEDIOESPROC) (GLenum target, GLuint index); typedef void (GL_APIENTRYP RGLSYMGLDRAWELEMENTSBASEVERTEXOESPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLint basevertex); typedef void (GL_APIENTRYP RGLSYMGLDRAWRANGEELEMENTSBASEVERTEXOESPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices, GLint basevertex); typedef void (GL_APIENTRYP RGLSYMGLDRAWELEMENTSINSTANCEDBASEVERTEXOESPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex); typedef void (GL_APIENTRYP RGLSYMGLMULTIDRAWELEMENTSBASEVERTEXOESPROC) (GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei primcount, const GLint *basevertex); typedef void (GL_APIENTRYP RGLSYMGLFRAMEBUFFERTEXTUREOESPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level); typedef void (GL_APIENTRYP RGLSYMGLGETPROGRAMBINARYOESPROC) (GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, void *binary); typedef void (GL_APIENTRYP RGLSYMGLPROGRAMBINARYOESPROC) (GLuint program, GLenum binaryFormat, const void *binary, GLint length); typedef void *(GL_APIENTRYP RGLSYMGLMAPBUFFEROESPROC) (GLenum target, GLenum access); typedef GLboolean (GL_APIENTRYP RGLSYMGLUNMAPBUFFEROESPROC) (GLenum target); typedef void (GL_APIENTRYP RGLSYMGLGETBUFFERPOINTERVOESPROC) (GLenum target, GLenum pname, void **params); typedef void (GL_APIENTRYP RGLSYMGLPRIMITIVEBOUNDINGBOXOESPROC) (GLfloat minX, GLfloat minY, GLfloat minZ, GLfloat minW, GLfloat maxX, GLfloat maxY, GLfloat maxZ, GLfloat maxW); typedef void (GL_APIENTRYP RGLSYMGLMINSAMPLESHADINGOESPROC) (GLfloat value); typedef void (GL_APIENTRYP RGLSYMGLPATCHPARAMETERIOESPROC) (GLenum pname, GLint value); typedef void (GL_APIENTRYP RGLSYMGLTEXIMAGE3DOESPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels); typedef void (GL_APIENTRYP RGLSYMGLTEXSUBIMAGE3DOESPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels); typedef void (GL_APIENTRYP RGLSYMGLCOPYTEXSUBIMAGE3DOESPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); typedef void (GL_APIENTRYP RGLSYMGLCOMPRESSEDTEXIMAGE3DOESPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data); typedef void (GL_APIENTRYP RGLSYMGLCOMPRESSEDTEXSUBIMAGE3DOESPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data); typedef void (GL_APIENTRYP RGLSYMGLFRAMEBUFFERTEXTURE3DOESPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset); typedef void (GL_APIENTRYP RGLSYMGLTEXPARAMETERIIVOESPROC) (GLenum target, GLenum pname, const GLint *params); typedef void (GL_APIENTRYP RGLSYMGLTEXPARAMETERIUIVOESPROC) (GLenum target, GLenum pname, const GLuint *params); typedef void (GL_APIENTRYP RGLSYMGLGETTEXPARAMETERIIVOESPROC) (GLenum target, GLenum pname, GLint *params); typedef void (GL_APIENTRYP RGLSYMGLGETTEXPARAMETERIUIVOESPROC) (GLenum target, GLenum pname, GLuint *params); typedef void (GL_APIENTRYP RGLSYMGLSAMPLERPARAMETERIIVOESPROC) (GLuint sampler, GLenum pname, const GLint *param); typedef void (GL_APIENTRYP RGLSYMGLSAMPLERPARAMETERIUIVOESPROC) (GLuint sampler, GLenum pname, const GLuint *param); typedef void (GL_APIENTRYP RGLSYMGLGETSAMPLERPARAMETERIIVOESPROC) (GLuint sampler, GLenum pname, GLint *params); typedef void (GL_APIENTRYP RGLSYMGLGETSAMPLERPARAMETERIUIVOESPROC) (GLuint sampler, GLenum pname, GLuint *params); typedef void (GL_APIENTRYP RGLSYMGLTEXBUFFEROESPROC) (GLenum target, GLenum internalformat, GLuint buffer); typedef void (GL_APIENTRYP RGLSYMGLTEXBUFFERRANGEOESPROC) (GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size); typedef void (GL_APIENTRYP RGLSYMGLTEXSTORAGE3DMULTISAMPLEOESPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations); typedef void (GL_APIENTRYP RGLSYMGLTEXTUREVIEWOESPROC) (GLuint texture, GLenum target, GLuint origtexture, GLenum internalformat, GLuint minlevel, GLuint numlevels, GLuint minlayer, GLuint numlayers); typedef void (GL_APIENTRYP RGLSYMGLBINDVERTEXARRAYOESPROC) (GLuint array); typedef void (GL_APIENTRYP RGLSYMGLDELETEVERTEXARRAYSOESPROC) (GLsizei n, const GLuint *arrays); typedef void (GL_APIENTRYP RGLSYMGLGENVERTEXARRAYSOESPROC) (GLsizei n, GLuint *arrays); typedef GLboolean (GL_APIENTRYP RGLSYMGLISVERTEXARRAYOESPROC) (GLuint array); typedef void (GL_APIENTRYP RGLSYMGLFRAMEBUFFERTEXTUREMULTIVIEWOVRPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint baseViewIndex, GLsizei numViews); typedef void (GL_APIENTRYP RGLSYMGLFRAMEBUFFERTEXTUREMULTISAMPLEMULTIVIEWOVRPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLsizei samples, GLint baseViewIndex, GLsizei numViews); #define glBlendBarrierKHR __rglgen_glBlendBarrierKHR #define glDebugMessageControlKHR __rglgen_glDebugMessageControlKHR #define glDebugMessageInsertKHR __rglgen_glDebugMessageInsertKHR #define glDebugMessageCallbackKHR __rglgen_glDebugMessageCallbackKHR #define glGetDebugMessageLogKHR __rglgen_glGetDebugMessageLogKHR #define glPushDebugGroupKHR __rglgen_glPushDebugGroupKHR #define glPopDebugGroupKHR __rglgen_glPopDebugGroupKHR #define glObjectLabelKHR __rglgen_glObjectLabelKHR #define glGetObjectLabelKHR __rglgen_glGetObjectLabelKHR #define glObjectPtrLabelKHR __rglgen_glObjectPtrLabelKHR #define glGetObjectPtrLabelKHR __rglgen_glGetObjectPtrLabelKHR #define glGetPointervKHR __rglgen_glGetPointervKHR #define glGetGraphicsResetStatusKHR __rglgen_glGetGraphicsResetStatusKHR #define glReadnPixelsKHR __rglgen_glReadnPixelsKHR #define glGetnUniformfvKHR __rglgen_glGetnUniformfvKHR #define glGetnUniformivKHR __rglgen_glGetnUniformivKHR #define glGetnUniformuivKHR __rglgen_glGetnUniformuivKHR #define glEGLImageTargetTexture2DOES __rglgen_glEGLImageTargetTexture2DOES #define glEGLImageTargetRenderbufferStorageOES __rglgen_glEGLImageTargetRenderbufferStorageOES #define glCopyImageSubDataOES __rglgen_glCopyImageSubDataOES #define glEnableiOES __rglgen_glEnableiOES #define glDisableiOES __rglgen_glDisableiOES #define glBlendEquationiOES __rglgen_glBlendEquationiOES #define glBlendEquationSeparateiOES __rglgen_glBlendEquationSeparateiOES #define glBlendFunciOES __rglgen_glBlendFunciOES #define glBlendFuncSeparateiOES __rglgen_glBlendFuncSeparateiOES #define glColorMaskiOES __rglgen_glColorMaskiOES #define glIsEnablediOES __rglgen_glIsEnablediOES #define glDrawElementsBaseVertexOES __rglgen_glDrawElementsBaseVertexOES #define glDrawRangeElementsBaseVertexOES __rglgen_glDrawRangeElementsBaseVertexOES #define glDrawElementsInstancedBaseVertexOES __rglgen_glDrawElementsInstancedBaseVertexOES #define glMultiDrawElementsBaseVertexOES __rglgen_glMultiDrawElementsBaseVertexOES #define glFramebufferTextureOES __rglgen_glFramebufferTextureOES #define glGetProgramBinaryOES __rglgen_glGetProgramBinaryOES #define glProgramBinaryOES __rglgen_glProgramBinaryOES #define glMapBufferOES __rglgen_glMapBufferOES #define glUnmapBufferOES __rglgen_glUnmapBufferOES #define glGetBufferPointervOES __rglgen_glGetBufferPointervOES #define glPrimitiveBoundingBoxOES __rglgen_glPrimitiveBoundingBoxOES #define glMinSampleShadingOES __rglgen_glMinSampleShadingOES #define glPatchParameteriOES __rglgen_glPatchParameteriOES #define glTexImage3DOES __rglgen_glTexImage3DOES #define glTexSubImage3DOES __rglgen_glTexSubImage3DOES #define glCopyTexSubImage3DOES __rglgen_glCopyTexSubImage3DOES #define glCompressedTexImage3DOES __rglgen_glCompressedTexImage3DOES #define glCompressedTexSubImage3DOES __rglgen_glCompressedTexSubImage3DOES #define glFramebufferTexture3DOES __rglgen_glFramebufferTexture3DOES #define glTexParameterIivOES __rglgen_glTexParameterIivOES #define glTexParameterIuivOES __rglgen_glTexParameterIuivOES #define glGetTexParameterIivOES __rglgen_glGetTexParameterIivOES #define glGetTexParameterIuivOES __rglgen_glGetTexParameterIuivOES #define glSamplerParameterIivOES __rglgen_glSamplerParameterIivOES #define glSamplerParameterIuivOES __rglgen_glSamplerParameterIuivOES #define glGetSamplerParameterIivOES __rglgen_glGetSamplerParameterIivOES #define glGetSamplerParameterIuivOES __rglgen_glGetSamplerParameterIuivOES #define glTexBufferOES __rglgen_glTexBufferOES #define glTexBufferRangeOES __rglgen_glTexBufferRangeOES #define glTexStorage3DMultisampleOES __rglgen_glTexStorage3DMultisampleOES #define glTextureViewOES __rglgen_glTextureViewOES #define glBindVertexArrayOES __rglgen_glBindVertexArrayOES #define glDeleteVertexArraysOES __rglgen_glDeleteVertexArraysOES #define glGenVertexArraysOES __rglgen_glGenVertexArraysOES #define glIsVertexArrayOES __rglgen_glIsVertexArrayOES #define glFramebufferTextureMultiviewOVR __rglgen_glFramebufferTextureMultiviewOVR #define glFramebufferTextureMultisampleMultiviewOVR __rglgen_glFramebufferTextureMultisampleMultiviewOVR extern RGLSYMGLBLENDBARRIERKHRPROC __rglgen_glBlendBarrierKHR; extern RGLSYMGLDEBUGMESSAGECONTROLKHRPROC __rglgen_glDebugMessageControlKHR; extern RGLSYMGLDEBUGMESSAGEINSERTKHRPROC __rglgen_glDebugMessageInsertKHR; extern RGLSYMGLDEBUGMESSAGECALLBACKKHRPROC __rglgen_glDebugMessageCallbackKHR; extern RGLSYMGLGETDEBUGMESSAGELOGKHRPROC __rglgen_glGetDebugMessageLogKHR; extern RGLSYMGLPUSHDEBUGGROUPKHRPROC __rglgen_glPushDebugGroupKHR; extern RGLSYMGLPOPDEBUGGROUPKHRPROC __rglgen_glPopDebugGroupKHR; extern RGLSYMGLOBJECTLABELKHRPROC __rglgen_glObjectLabelKHR; extern RGLSYMGLGETOBJECTLABELKHRPROC __rglgen_glGetObjectLabelKHR; extern RGLSYMGLOBJECTPTRLABELKHRPROC __rglgen_glObjectPtrLabelKHR; extern RGLSYMGLGETOBJECTPTRLABELKHRPROC __rglgen_glGetObjectPtrLabelKHR; extern RGLSYMGLGETPOINTERVKHRPROC __rglgen_glGetPointervKHR; extern RGLSYMGLGETGRAPHICSRESETSTATUSKHRPROC __rglgen_glGetGraphicsResetStatusKHR; extern RGLSYMGLREADNPIXELSKHRPROC __rglgen_glReadnPixelsKHR; extern RGLSYMGLGETNUNIFORMFVKHRPROC __rglgen_glGetnUniformfvKHR; extern RGLSYMGLGETNUNIFORMIVKHRPROC __rglgen_glGetnUniformivKHR; extern RGLSYMGLGETNUNIFORMUIVKHRPROC __rglgen_glGetnUniformuivKHR; extern RGLSYMGLEGLIMAGETARGETTEXTURE2DOESPROC __rglgen_glEGLImageTargetTexture2DOES; extern RGLSYMGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC __rglgen_glEGLImageTargetRenderbufferStorageOES; extern RGLSYMGLCOPYIMAGESUBDATAOESPROC __rglgen_glCopyImageSubDataOES; extern RGLSYMGLENABLEIOESPROC __rglgen_glEnableiOES; extern RGLSYMGLDISABLEIOESPROC __rglgen_glDisableiOES; extern RGLSYMGLBLENDEQUATIONIOESPROC __rglgen_glBlendEquationiOES; extern RGLSYMGLBLENDEQUATIONSEPARATEIOESPROC __rglgen_glBlendEquationSeparateiOES; extern RGLSYMGLBLENDFUNCIOESPROC __rglgen_glBlendFunciOES; extern RGLSYMGLBLENDFUNCSEPARATEIOESPROC __rglgen_glBlendFuncSeparateiOES; extern RGLSYMGLCOLORMASKIOESPROC __rglgen_glColorMaskiOES; extern RGLSYMGLISENABLEDIOESPROC __rglgen_glIsEnablediOES; extern RGLSYMGLDRAWELEMENTSBASEVERTEXOESPROC __rglgen_glDrawElementsBaseVertexOES; extern RGLSYMGLDRAWRANGEELEMENTSBASEVERTEXOESPROC __rglgen_glDrawRangeElementsBaseVertexOES; extern RGLSYMGLDRAWELEMENTSINSTANCEDBASEVERTEXOESPROC __rglgen_glDrawElementsInstancedBaseVertexOES; extern RGLSYMGLMULTIDRAWELEMENTSBASEVERTEXOESPROC __rglgen_glMultiDrawElementsBaseVertexOES; extern RGLSYMGLFRAMEBUFFERTEXTUREOESPROC __rglgen_glFramebufferTextureOES; extern RGLSYMGLGETPROGRAMBINARYOESPROC __rglgen_glGetProgramBinaryOES; extern RGLSYMGLPROGRAMBINARYOESPROC __rglgen_glProgramBinaryOES; extern RGLSYMGLMAPBUFFEROESPROC __rglgen_glMapBufferOES; extern RGLSYMGLUNMAPBUFFEROESPROC __rglgen_glUnmapBufferOES; extern RGLSYMGLGETBUFFERPOINTERVOESPROC __rglgen_glGetBufferPointervOES; extern RGLSYMGLPRIMITIVEBOUNDINGBOXOESPROC __rglgen_glPrimitiveBoundingBoxOES; extern RGLSYMGLMINSAMPLESHADINGOESPROC __rglgen_glMinSampleShadingOES; extern RGLSYMGLPATCHPARAMETERIOESPROC __rglgen_glPatchParameteriOES; extern RGLSYMGLTEXIMAGE3DOESPROC __rglgen_glTexImage3DOES; extern RGLSYMGLTEXSUBIMAGE3DOESPROC __rglgen_glTexSubImage3DOES; extern RGLSYMGLCOPYTEXSUBIMAGE3DOESPROC __rglgen_glCopyTexSubImage3DOES; extern RGLSYMGLCOMPRESSEDTEXIMAGE3DOESPROC __rglgen_glCompressedTexImage3DOES; extern RGLSYMGLCOMPRESSEDTEXSUBIMAGE3DOESPROC __rglgen_glCompressedTexSubImage3DOES; extern RGLSYMGLFRAMEBUFFERTEXTURE3DOESPROC __rglgen_glFramebufferTexture3DOES; extern RGLSYMGLTEXPARAMETERIIVOESPROC __rglgen_glTexParameterIivOES; extern RGLSYMGLTEXPARAMETERIUIVOESPROC __rglgen_glTexParameterIuivOES; extern RGLSYMGLGETTEXPARAMETERIIVOESPROC __rglgen_glGetTexParameterIivOES; extern RGLSYMGLGETTEXPARAMETERIUIVOESPROC __rglgen_glGetTexParameterIuivOES; extern RGLSYMGLSAMPLERPARAMETERIIVOESPROC __rglgen_glSamplerParameterIivOES; extern RGLSYMGLSAMPLERPARAMETERIUIVOESPROC __rglgen_glSamplerParameterIuivOES; extern RGLSYMGLGETSAMPLERPARAMETERIIVOESPROC __rglgen_glGetSamplerParameterIivOES; extern RGLSYMGLGETSAMPLERPARAMETERIUIVOESPROC __rglgen_glGetSamplerParameterIuivOES; extern RGLSYMGLTEXBUFFEROESPROC __rglgen_glTexBufferOES; extern RGLSYMGLTEXBUFFERRANGEOESPROC __rglgen_glTexBufferRangeOES; extern RGLSYMGLTEXSTORAGE3DMULTISAMPLEOESPROC __rglgen_glTexStorage3DMultisampleOES; extern RGLSYMGLTEXTUREVIEWOESPROC __rglgen_glTextureViewOES; extern RGLSYMGLBINDVERTEXARRAYOESPROC __rglgen_glBindVertexArrayOES; extern RGLSYMGLDELETEVERTEXARRAYSOESPROC __rglgen_glDeleteVertexArraysOES; extern RGLSYMGLGENVERTEXARRAYSOESPROC __rglgen_glGenVertexArraysOES; extern RGLSYMGLISVERTEXARRAYOESPROC __rglgen_glIsVertexArrayOES; extern RGLSYMGLFRAMEBUFFERTEXTUREMULTIVIEWOVRPROC __rglgen_glFramebufferTextureMultiviewOVR; extern RGLSYMGLFRAMEBUFFERTEXTUREMULTISAMPLEMULTIVIEWOVRPROC __rglgen_glFramebufferTextureMultisampleMultiviewOVR; struct rglgen_sym_map { const char *sym; void *ptr; }; extern const struct rglgen_sym_map rglgen_symbol_map[]; #ifdef __cplusplus } #endif #endif desmume/src/cheatSystem.cpp000664 001750 001750 00000055144 12755534123 017145 0ustar00sergiosergio000000 000000 /* Copyright (C) 2009-2015 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the this software. If not, see . */ #include "cheatSystem.h" #include "utils/bits.h" #include "NDSSystem.h" #include "common.h" #include "mem.h" #include "MMU.h" #ifdef DEBUG #include "debug.h" #endif #include "utils/xstring.h" #ifndef _MSC_VER #include #endif #if defined(_WIN32) && !defined(_MSC_VER) #define sscanf_s sscanf #endif CHEATS *cheats = NULL; void CHEATS::clear() { list.resize(0); currentGet = 0; } void CHEATS::init(char *path) { clear(); strcpy((char *)filename, path); } BOOL CHEATS::add(u8 size, u32 address, u32 val, char *description, BOOL enabled) { size_t num = list.size(); list.push_back(CHEATS_LIST()); list[num].code[0][0] = address & 0x00FFFFFF; list[num].code[0][1] = val; list[num].num = 1; list[num].type = 0; list[num].size = size; this->setDescription(description, num); list[num].enabled = enabled; return TRUE; } BOOL CHEATS::update(u8 size, u32 address, u32 val, char *description, BOOL enabled, u32 pos) { if (pos >= list.size()) return FALSE; list[pos].code[0][0] = address & 0x00FFFFFF; list[pos].code[0][1] = val; list[pos].num = 1; list[pos].type = 0; list[pos].size = size; this->setDescription(description, pos); list[pos].enabled = enabled; return TRUE; } void CHEATS::ARparser(CHEATS_LIST& list) { u8 type = 0; u8 subtype = 0; u32 hi = 0; u32 lo = 0; u32 addr = 0; u32 val = 0; // AR temporary vars & flags u32 offset = 0; u32 datareg = 0; u32 loopcount = 0; u32 counter = 0; u32 if_flag = 0; s32 loopbackline = 0; u32 loop_flag = 0; for (int i=0; i < list.num; i++) { type = list.code[i][0] >> 28; subtype = (list.code[i][0] >> 24) & 0x0F; hi = list.code[i][0] & 0x0FFFFFFF; lo = list.code[i][1]; if (if_flag > 0) { if ((type == 0x0E)) i += ((lo + 7) / 8); if ( (type == 0x0D) && (subtype == 0)) if_flag--; // ENDIF if ( (type == 0x0D) && (subtype == 2)) // NEXT & Flush { if (loop_flag) i = (loopbackline-1); else { offset = 0; datareg = 0; loopcount = 0; counter = 0; if_flag = 0; loop_flag = 0; } } continue; } switch (type) { case 0x00: { if (hi==0) { //manual hook } else if ((hi==0x0000AA99) && (lo==0)) // 0000AA99 00000000 parameter bytes 9..10 for above code (padded with 00s) { //parameter bytes 9..10 for above code (padded with 00s) } else // 0XXXXXXX YYYYYYYY word[XXXXXXX+offset] = YYYYYYYY { addr = hi + offset; _MMU_write32(addr, lo); } } break; case 0x01: // 1XXXXXXX 0000YYYY half[XXXXXXX+offset] = YYYY addr = hi + offset; _MMU_write16(addr, lo); break; case 0x02: // 2XXXXXXX 000000YY byte[XXXXXXX+offset] = YY addr = hi + offset; _MMU_write08(addr, lo); break; case 0x03: // 3XXXXXXX YYYYYYYY IF YYYYYYYY > word[XXXXXXX] ;unsigned if (hi == 0) hi = offset; // V1.54+ val = _MMU_read32(hi); if ( lo > val ) { if (if_flag > 0) if_flag--; } else { if_flag++; } break; case 0x04: // 4XXXXXXX YYYYYYYY IF YYYYYYYY < word[XXXXXXX] ;unsigned if ((hi == 0x04332211) && (lo == 88776655)) //44332211 88776655 parameter bytes 1..8 for above code (example) { break; } if (hi == 0) hi = offset; // V1.54+ val = _MMU_read32(hi); if ( lo < val ) { if (if_flag > 0) if_flag--; } else { if_flag++; } break; case 0x05: // 5XXXXXXX YYYYYYYY IF YYYYYYYY = word[XXXXXXX] if (hi == 0) hi = offset; // V1.54+ val = _MMU_read32(hi); if ( lo == val ) { if (if_flag > 0) if_flag--; } else { if_flag++; } break; case 0x06: // 6XXXXXXX YYYYYYYY IF YYYYYYYY <> word[XXXXXXX] if (hi == 0) hi = offset; // V1.54+ val = _MMU_read32(hi); if ( lo != val ) { if (if_flag > 0) if_flag--; } else { if_flag++; } break; case 0x07: // 7XXXXXXX ZZZZYYYY IF YYYY > ((not ZZZZ) AND half[XXXXXXX]) if (hi == 0) hi = offset; // V1.54+ val = _MMU_read16(hi); if ( (lo & 0xFFFF) > ( (~(lo >> 16)) & val) ) { if (if_flag > 0) if_flag--; } else { if_flag++; } break; case 0x08: // 8XXXXXXX ZZZZYYYY IF YYYY < ((not ZZZZ) AND half[XXXXXXX]) if (hi == 0) hi = offset; // V1.54+ val = _MMU_read16(hi); if ( (lo & 0xFFFF) < ( (~(lo >> 16)) & val) ) { if (if_flag > 0) if_flag--; } else { if_flag++; } break; case 0x09: // 9XXXXXXX ZZZZYYYY IF YYYY = ((not ZZZZ) AND half[XXXXXXX]) if (hi == 0) hi = offset; // V1.54+ val = _MMU_read16(hi); if ( (lo & 0xFFFF) == ( (~(lo >> 16)) & val) ) { if (if_flag > 0) if_flag--; } else { if_flag++; } break; case 0x0A: // AXXXXXXX ZZZZYYYY IF YYYY <> ((not ZZZZ) AND half[XXXXXXX]) if (hi == 0) hi = offset; // V1.54+ val = _MMU_read16(hi); if ( (lo & 0xFFFF) != ( (~(lo >> 16)) & val) ) { if (if_flag > 0) if_flag--; } else { if_flag++; } break; case 0x0B: // BXXXXXXX 00000000 offset = word[XXXXXXX+offset] addr = hi + offset; offset = _MMU_read32(addr);; break; case 0x0C: switch (subtype) { case 0x0: // C0000000 YYYYYYYY FOR loopcount=0 to YYYYYYYY ;execute Y+1 times if (loopcount < (lo+1)) loop_flag = 1; else loop_flag = 0; loopcount++; loopbackline = i; break; case 0x4: // C4000000 00000000 offset = address of the C4000000 code ; V1.54 printf("AR: untested code C4\n"); break; case 0x5: // C5000000 XXXXYYYY counter=counter+1, IF (counter AND YYYY) = XXXX ; V1.54 counter++; if ( (counter & (lo & 0xFFFF)) == ((lo >> 8) & 0xFFFF) ) { if (if_flag > 0) if_flag--; } else { if_flag++; } break; case 0x6: // C6000000 XXXXXXXX [XXXXXXXX]=offset ; V1.54 _MMU_write32(lo, offset); break; } break; case 0x0D: { switch (subtype) { case 0x0: // D0000000 00000000 ENDIF break; case 0x1: // D1000000 00000000 NEXT loopcount if (loop_flag) i = (loopbackline-1); break; case 0x2: // D2000000 00000000 NEXT loopcount, and then FLUSH everything if (loop_flag) i = (loopbackline-1); else { offset = 0; datareg = 0; loopcount = 0; counter = 0; if_flag = 0; loop_flag = 0; } break; case 0x3: // D3000000 XXXXXXXX offset = XXXXXXXX offset = lo; break; case 0x4: // D4000000 XXXXXXXX datareg = datareg + XXXXXXXX datareg += lo; break; case 0x5: // D5000000 XXXXXXXX datareg = XXXXXXXX datareg = lo; break; case 0x6: // D6000000 XXXXXXXX word[XXXXXXXX+offset]=datareg, offset=offset+4 addr = lo + offset; _MMU_write32(addr, datareg); offset += 4; break; case 0x7: // D7000000 XXXXXXXX half[XXXXXXXX+offset]=datareg, offset=offset+2 addr = lo + offset; _MMU_write16(addr, datareg); offset += 2; break; case 0x8: // D8000000 XXXXXXXX byte[XXXXXXXX+offset]=datareg, offset=offset+1 addr = lo + offset; _MMU_write08(addr, datareg); offset += 1; break; case 0x9: // D9000000 XXXXXXXX datareg = word[XXXXXXXX+offset] addr = lo + offset; datareg = _MMU_read32(addr); break; case 0xA: // DA000000 XXXXXXXX datareg = half[XXXXXXXX+offset] addr = lo + offset; datareg = _MMU_read16(addr); break; case 0xB: // DB000000 XXXXXXXX datareg = byte[XXXXXXXX+offset] ;bugged on pre-v1.54 addr = lo + offset; datareg = _MMU_read08(addr); break; case 0xC: // DC000000 XXXXXXXX offset = offset + XXXXXXXX offset += lo; break; } } break; case 0xE: // EXXXXXXX YYYYYYYY Copy YYYYYYYY parameter bytes to [XXXXXXXX+offset...] { u8 *tmp_code = (u8*)(list.code[i+1]); u32 addr = hi+offset; u32 maxByteReadLocation = ((2 * 4) * (MAX_XX_CODE - i - 1)) - 1; // 2 = 2 array dimensions, 4 = 4 bytes per array element if (lo <= maxByteReadLocation) { for (u32 t = 0; t < lo; t++) { u8 tmp = tmp_code[t]; _MMU_write08(addr, tmp); addr++; } } i += ((lo + 7) / 8); } break; case 0xF: // FXXXXXXX YYYYYYYY Copy YYYYYYYY bytes from [offset..] to [XXXXXXX...] for (u32 t = 0; t < lo; t++) { u8 tmp = _MMU_read08(offset+t); _MMU_write08(hi+t, tmp); } break; default: #ifdef DEBUG PROGINFO("AR: ERROR unknown command 0x%2X at %08X:%08X\n", type, hi, lo); #endif break; } } } BOOL CHEATS::add_AR_Direct(CHEATS_LIST cheat) { size_t num = list.size(); list.push_back(cheat); list[num].type = 1; return TRUE; } BOOL CHEATS::add_AR(char *code, char *description, BOOL enabled) { //if (num == MAX_CHEAT_LIST) return FALSE; size_t num = list.size(); CHEATS_LIST temp; if (!CHEATS::XXCodeFromString(&temp, code)) return FALSE; list.push_back(temp); list[num].type = 1; this->setDescription(description, num); list[num].enabled = enabled; return TRUE; } BOOL CHEATS::update_AR(char *code, char *description, BOOL enabled, u32 pos) { if (pos >= list.size()) return FALSE; if (code != NULL) { if (!CHEATS::XXCodeFromString(this->getItemByIndex(pos), code)) return FALSE; this->setDescription(description, pos); list[pos].type = 1; } list[pos].enabled = enabled; return TRUE; } BOOL CHEATS::add_CB(char *code, char *description, BOOL enabled) { //if (num == MAX_CHEAT_LIST) return FALSE; size_t num = list.size(); if (!CHEATS::XXCodeFromString(this->getItemByIndex(num), code)) return FALSE; list[num].type = 2; this->setDescription(description, num); list[num].enabled = enabled; return TRUE; } BOOL CHEATS::update_CB(char *code, char *description, BOOL enabled, u32 pos) { if (pos >= list.size()) return FALSE; if (code != NULL) { if (!CHEATS::XXCodeFromString(this->getItemByIndex(pos), code)) return FALSE; list[pos].type = 2; this->setDescription(description, pos); } list[pos].enabled = enabled; return TRUE; } BOOL CHEATS::remove(u32 pos) { if (pos >= list.size()) return FALSE; if (list.size() == 0) return FALSE; list.erase(list.begin()+pos); return TRUE; } void CHEATS::getListReset() { currentGet = 0; return; } BOOL CHEATS::getList(CHEATS_LIST *cheat) { BOOL result = FALSE; if (currentGet >= this->list.size()) { this->getListReset(); return result; } result = this->get(cheat, currentGet++); return result; } CHEATS_LIST* CHEATS::getListPtr() { return &this->list[0]; } BOOL CHEATS::get(CHEATS_LIST *cheat, u32 pos) { CHEATS_LIST *item = this->getItemByIndex(pos); if (item == NULL) { return FALSE; } *cheat = *item; return TRUE; } CHEATS_LIST* CHEATS::getItemByIndex(const u32 pos) { if (pos >= this->getSize()) { return NULL; } return &this->list[pos]; } u32 CHEATS::getSize() { return list.size(); } size_t CHEATS::getActiveCount() { size_t activeCheatCount = 0; const size_t cheatListCount = this->getSize(); for (size_t i = 0; i < cheatListCount; i++) { if (list[i].enabled) { activeCheatCount++; } } return activeCheatCount; } void CHEATS::setDescription(const char *description, u32 pos) { strncpy(list[pos].description, description, sizeof(list[pos].description)); list[pos].description[sizeof(list[pos].description) - 1] = '\0'; } char *CHEATS::clearCode(char *s) { char *buf = s; if (!s) return NULL; if (!*s) return s; for (u32 i = 0; i < strlen(s); i++) { if (s[i] == ';') break; if (strchr(hexValid, s[i])) { *buf = s[i]; buf++; } } *buf = 0; return s; } void CHEATS::process() { if (CommonSettings.cheatsDisable) return; if (list.size() == 0) return; size_t num = list.size(); for (size_t i = 0; i < num; i++) { if (!list[i].enabled) continue; switch (list[i].type) { case 0: // internal cheat system { //INFO("list at 0x02|%06X value %i (size %i)\n",list[i].code[0], list[i].lo[0], list[i].size); u32 addr = list[i].code[0][0] | 0x02000000; u32 val = list[i].code[0][1]; switch (list[i].size) { case 0: _MMU_write08(addr,val); break; case 1: _MMU_write16(addr,val); break; case 2: { u32 tmp = _MMU_read32(addr); tmp &= 0xFF000000; tmp |= (val & 0x00FFFFFF); _MMU_write32(addr,tmp); break; } case 3: _MMU_write32(addr,val); break; } break; } //end case 0 internal cheat system case 1: // Action Replay ARparser(list[i]); break; case 2: // Codebreaker break; default: continue; } } } void CHEATS::getXXcodeString(CHEATS_LIST list, char *res_buf) { char buf[50] = { 0 }; for (int i=0; i < list.num; i++) { sprintf(buf, "%08X %08X\n", list.code[i][0], list.code[i][1]); strcat(res_buf, buf); } } BOOL CHEATS::XXCodeFromString(CHEATS_LIST *cheatItem, const std::string codeString) { return CHEATS::XXCodeFromString(cheatItem, codeString.c_str()); } BOOL CHEATS::XXCodeFromString(CHEATS_LIST *cheatItem, const char *codeString) { BOOL result = FALSE; if (cheatItem == NULL || codeString == NULL) { return result; } int count = 0; u16 t = 0; char tmp_buf[sizeof(cheatItem->code) * 2 + 1]; memset(tmp_buf, 0, sizeof(tmp_buf)); size_t code_len = strlen(codeString); // remove wrong chars for (size_t i=0; i < code_len; i++) { char c = codeString[i]; //apparently 100% of pokemon codes were typed with the letter O in place of zero in some places //so let's try to adjust for that here static const char *AR_Valid = "Oo0123456789ABCDEFabcdef"; if (strchr(AR_Valid, c)) { if(c=='o' || c=='O') c='0'; tmp_buf[t++] = c; } } size_t len = strlen(tmp_buf); if ((len % 16) != 0) return result; // error // TODO: syntax check count = (len / 16); for (int i=0; i < count; i++) { char buf[9] = {0}; memcpy(buf, tmp_buf+(i*16), 8); sscanf(buf, "%x", &cheatItem->code[i][0]); memcpy(buf, tmp_buf+(i*16) + 8, 8); sscanf(buf, "%x", &cheatItem->code[i][1]); } cheatItem->num = count; cheatItem->size = 0; result = TRUE; return result; } // ========================================================================= Export void CHEATSEXPORT::R4decrypt(u8 *buf, u32 len, u32 n) { size_t r = 0; while (r < len) { size_t i ; u16 key = n ^ 0x484A; for (i = 0 ; i < 512 && i < len - r ; i ++) { u8 _xor = 0; if (key & 0x4000) _xor |= 0x80; if (key & 0x1000) _xor |= 0x40; if (key & 0x0800) _xor |= 0x20; if (key & 0x0200) _xor |= 0x10; if (key & 0x0080) _xor |= 0x08; if (key & 0x0040) _xor |= 0x04; if (key & 0x0002) _xor |= 0x02; if (key & 0x0001) _xor |= 0x01; u32 k = ((buf[i] << 8) ^ key) << 16; u32 x = k; for (u8 j = 1; j < 32; j ++) x ^= k >> j; key = 0x0000; if (BIT_N(x, 23)) key |= 0x8000; if (BIT_N(k, 22)) key |= 0x4000; if (BIT_N(k, 21)) key |= 0x2000; if (BIT_N(k, 20)) key |= 0x1000; if (BIT_N(k, 19)) key |= 0x0800; if (BIT_N(k, 18)) key |= 0x0400; if (BIT_N(k, 17) != BIT_N(x, 31)) key |= 0x0200; if (BIT_N(k, 16) != BIT_N(x, 30)) key |= 0x0100; if (BIT_N(k, 30) != BIT_N(k, 29)) key |= 0x0080; if (BIT_N(k, 29) != BIT_N(k, 28)) key |= 0x0040; if (BIT_N(k, 28) != BIT_N(k, 27)) key |= 0x0020; if (BIT_N(k, 27) != BIT_N(k, 26)) key |= 0x0010; if (BIT_N(k, 26) != BIT_N(k, 25)) key |= 0x0008; if (BIT_N(k, 25) != BIT_N(k, 24)) key |= 0x0004; if (BIT_N(k, 25) != BIT_N(x, 26)) key |= 0x0002; if (BIT_N(k, 24) != BIT_N(x, 25)) key |= 0x0001; buf[i] ^= _xor; } buf+= 512; r += 512; n += 1; } } bool CHEATSEXPORT::load(char *path) { size_t elements_read; error = 0; fp = fopen(path, "rb"); if (!fp) { printf("Error open database\n"); error = 1; return false; } const char *headerID = "R4 CheatCode"; char buf[255] = {0}; elements_read = fread(buf, 1, strlen(headerID), fp); if (elements_read != strlen(headerID)) printf("Unexpectedly short cheat code?\n"); if (strncmp(buf, headerID, strlen(headerID)) != 0) { // check encrypted R4decrypt((u8 *)buf, strlen(headerID), 0); if (strcmp(buf, headerID) != 0) { error = 2; return false; } encrypted = true; } fseek(fp, 0, SEEK_END); fsize = ftell(fp); fseek(fp, 0, SEEK_SET); if (!search()) { printf("ERROR: cheat in database not found\n"); error = 3; return false; } if (!getCodes()) { printf("ERROR: export cheats failed\n"); error = 4; return false; } return true; } void CHEATSEXPORT::close() { if (fp) fclose(fp); if (cheats) { delete [] cheats; cheats = NULL; } } bool CHEATSEXPORT::search() { size_t elements_read; if (!fp) return false; u32 pos = 0x0100; FAT_R4 fat_tmp = {0}; u8 buf[512] = {0}; CRC = 0; encOffset = 0; u32 t = 0; memset(date, 0, sizeof(date)); if (encrypted) { fseek(fp, 0, SEEK_SET); elements_read = fread(&buf[0], 1, 512, fp); if (elements_read != 512) printf("%s:\nDid not read 512 elements.\n\n", "CHEATSEXPORT"); R4decrypt((u8 *)&buf[0], 512, 0); memcpy(&date[0], &buf[0x10], 16); } else { fseek(fp, 0x10, SEEK_SET); elements_read = fread(&date, 16, 1, fp); if (elements_read != 512) printf("%s:\nDid not read 16 bytes.\n\n", "CHEATSEXPORT"); fseek(fp, pos, SEEK_SET); elements_read = fread(&fat_tmp, sizeof(fat), 1, fp); if (elements_read != 1) printf("%s:\nDid not read sizeof(fat) bytes.\n\n", "CHEATSEXPORT"); } while (1) { if (encrypted) { memcpy(&fat, &buf[pos % 512], sizeof(fat)); pos += sizeof(fat); if ((pos>>9) > t) { t++; elements_read = fread(&buf[0], 1, 512, fp); if (elements_read != 512) printf("%s:\nDid not read 512 bytes.\n\n", "CHEATSEXPORT"); R4decrypt((u8 *)&buf[0], 512, t); } memcpy(&fat_tmp, &buf[pos % 512], sizeof(fat_tmp)); // next } else { memcpy(&fat, &fat_tmp, sizeof(fat)); elements_read = fread(&fat_tmp, sizeof(fat_tmp), 1, fp); if (elements_read != 512) printf("%s:\nDid not read 512 bytes.\n\n", "CHEATSEXPORT"); } //printf("serial: %s, offset %08X\n", fat.serial, fat.addr); if (memcmp(gameInfo.header.gameCode, &fat.serial[0], 4) == 0) { dataSize = fat_tmp.addr?(fat_tmp.addr - fat.addr):0; if (encrypted) { encOffset = fat.addr % 512; dataSize += encOffset; } if (!dataSize) return false; CRC = fat.CRC; char buf[5] = {0}; memcpy(&buf, &fat.serial[0], 4); printf("Cheats: found %s CRC %08X at 0x%08llX, size %i byte(s)\n", buf, fat.CRC, fat.addr, dataSize - encOffset); return true; } if (fat.addr == 0) break; } memset(&fat, 0, sizeof(FAT_R4)); return false; } bool CHEATSEXPORT::getCodes() { if (!fp) return false; u32 pos = 0; u32 pos_cht = 0; u8 *data = new u8 [dataSize+8]; if (!data) return false; memset(data, 0, dataSize+8); fseek(fp, fat.addr - encOffset, SEEK_SET); if (fread(data, 1, dataSize, fp) != dataSize) { delete [] data; data = NULL; return false; } if (encrypted) R4decrypt(data, dataSize, fat.addr >> 9); intptr_t ptrMask = (~0 << 2); u8 *gameTitlePtr = (u8 *)data + encOffset; memset(gametitle, 0, CHEAT_DB_GAME_TITLE_SIZE); memcpy(gametitle, gameTitlePtr, strlen((const char *)gameTitlePtr)); u32 *cmd = (u32 *)(((intptr_t)gameTitlePtr + strlen((const char *)gameTitlePtr) + 4) & ptrMask); numCheats = cmd[0] & 0x0FFFFFFF; cmd += 9; cheats = new CHEATS_LIST[numCheats]; memset(cheats, 0, sizeof(CHEATS_LIST) * numCheats); while (pos < numCheats) { u32 folderNum = 1; u8 *folderName = NULL; u8 *folderNote = NULL; if ((*cmd & 0xF0000000) == 0x10000000) // Folder { folderNum = (*cmd & 0x00FFFFFF); folderName = (u8*)((intptr_t)cmd + 4); folderNote = (u8*)((intptr_t)folderName + strlen((char*)folderName) + 1); pos++; cmd = (u32 *)(((intptr_t)folderName + strlen((char*)folderName) + 1 + strlen((char*)folderNote) + 1 + 3) & ptrMask); } for (u32 i = 0; i < folderNum; i++) // in folder { u8 *cheatName = (u8 *)((intptr_t)cmd + 4); u8 *cheatNote = (u8 *)((intptr_t)cheatName + strlen((char*)cheatName) + 1); u32 *cheatData = (u32 *)(((intptr_t)cheatNote + strlen((char*)cheatNote) + 1 + 3) & ptrMask); u32 cheatDataLen = *cheatData++; u32 numberCodes = cheatDataLen / 2; if (numberCodes <= MAX_XX_CODE) { std::string descriptionStr = ""; if ( folderName && *folderName ) { descriptionStr += (char *)folderName; descriptionStr += ": "; } descriptionStr += (char *)cheatName; if ( cheatNote && *cheatNote ) { descriptionStr += " | "; descriptionStr += (char *)cheatNote; } strncpy(cheats[pos_cht].description, descriptionStr.c_str(), sizeof(cheats[pos_cht].description)); cheats[pos_cht].description[sizeof(cheats[pos_cht].description) - 1] = '\0'; cheats[pos_cht].num = numberCodes; cheats[pos_cht].type = 1; for(u32 j = 0, t = 0; j < numberCodes; j++, t+=2 ) { cheats[pos_cht].code[j][0] = (u32)*(cheatData+t); //printf("%i: %08X ", j, cheats[pos_cht].code[j][0]); cheats[pos_cht].code[j][1] = (u32)*(cheatData+t+1); //printf("%08X\n", cheats[pos_cht].code[j][1]); } pos_cht++; } pos++; cmd = (u32 *)((intptr_t)cmd + ((*cmd + 1)*4)); } }; delete [] data; numCheats = pos_cht; //for (int i = 0; i < numCheats; i++) // printf("%i: %s\n", i, cheats[i].description); return true; } CHEATS_LIST *CHEATSEXPORT::getCheats() { return cheats; } u32 CHEATSEXPORT::getCheatsNum() { return numCheats; } desmume/src/utils/emufat.h000664 001750 001750 00000064473 12755534123 016747 0ustar00sergiosergio000000 000000 /* Copyright 2009-2015 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the this software. If not, see . */ //based on Arduino SdFat Library ( http://code.google.com/p/sdfatlib/ ) //Copyright (C) 2009 by William Greiman //based on mkdosfs - utility to create FAT/MS-DOS filesystems //Copyright (C) 1991 Linus Torvalds //Copyright (C) 1992-1993 Remy Card //Copyright (C) 1993-1994 David Hudson //Copyright (C) 1998 H. Peter Anvin //Copyright (C) 1998-2005 Roman Hodek //based on libfat //Copyright (c) 2006 Michael "Chishm" Chisholm #ifndef EMUFAT_H #define EMUFAT_H #include #include #include "../types.h" class EMUFILE; #define BOOTCODE_SIZE 448 #define BOOTCODE_FAT32_SIZE 420 // use the gnu style oflag in open() /** open() oflag for reading */ static const u8 EO_READ = 0X01; /** open() oflag - same as O_READ */ static const u8 EO_RDONLY = EO_READ; /** open() oflag for write */ static const u8 EO_WRITE = 0X02; /** open() oflag - same as O_WRITE */ static const u8 EO_WRONLY = EO_WRITE; /** open() oflag for reading and writing */ static const u8 EO_RDWR = (EO_READ | EO_WRITE); /** open() oflag mask for access modes */ static const u8 EO_ACCMODE = (EO_READ | EO_WRITE); /** The file offset shall be set to the end of the file prior to each write. */ static const u8 EO_APPEND = 0X04; /** synchronous writes - call sync() after each write */ static const u8 EO_SYNC = 0X08; /** create the file if nonexistent */ static const u8 EO_CREAT = 0X10; /** If O_CREAT and O_EXCL are set, open() shall fail if the file exists */ static const u8 EO_EXCL = 0X20; /** truncate the file to zero length */ static const u8 EO_TRUNC = 0X40; //Value for byte 510 of boot block or MBR static const u8 BOOTSIG0 = 0X55; //Value for byte 511 of boot block or MBR static const u8 BOOTSIG1 = 0XAA; static void (*dateTime_)(u16* date, u16* time) = NULL; #include "PACKED.h" //A partition table entry for a MBR formatted storage device. //The MBR partition table has four entries. struct __PACKED TPartitionRecord { //Boot Indicator . Indicates whether the volume is the active //partition. Legal values include: 0X00. Do not use for booting. //0X80 Active partition. u8 boot; //Head part of Cylinder-head-sector address of the first block in //the partition. Legal values are 0-255. Only used in old PC BIOS. u8 beginHead; struct { //Sector part of Cylinder-head-sector address of the first block in //the partition. Legal values are 1-63. Only used in old PC BIOS. u32 beginSector : 6; //High bits cylinder for first block in partition. u32 beginCylinderHigh : 2; }; //Combine beginCylinderLow with beginCylinderHigh. Legal values //are 0-1023. Only used in old PC BIOS. u8 beginCylinderLow; //Partition type. See defines that begin with PART_TYPE_ for //some Microsoft partition types. u8 type; //head part of cylinder-head-sector address of the last sector in the //partition. Legal values are 0-255. Only used in old PC BIOS. u8 endHead; struct { //Sector part of cylinder-head-sector address of the last sector in //the partition. Legal values are 1-63. Only used in old PC BIOS. u32 endSector : 6; // High bits of end cylinder u32 endCylinderHigh : 2; }; //Combine endCylinderLow with endCylinderHigh. Legal values //are 0-1023. Only used in old PC BIOS. u8 endCylinderLow; //Logical block address of the first block in the partition. u32 firstSector; //Length of the partition, in blocks. u32 totalSectors; }; //Master Boot Record: //The first block of a storage device that is formatted with a MBR. struct __PACKED TMasterBootRecord { //Code Area for master boot program. u8 codeArea[440]; //Optional WindowsNT disk signature. May contain more boot code. u32 diskSignature; //Usually zero but may be more boot code. u16 usuallyZero; //Partition tables. TPartitionRecord part[4]; //First MBR signature byte. Must be 0X55 u8 mbrSig0; //Second MBR signature byte. Must be 0XAA u8 mbrSig1; }; struct __PACKED msdos_volume_info { u8 drive_number; /* BIOS drive number */ u8 RESERVED; /* Unused */ u8 ext_boot_sign; /* 0x29 if fields below exist (DOS 3.3+) */ u32 volume_id; /* Volume ID number */ u8 volume_label[11];/* Volume label */ u8 fs_type[8]; /* Typically FAT12 or FAT16 */ }; //Boot sector for a FAT16 or FAT32 volume. struct __PACKED TFat32BootSector { //X86 jmp to boot program u8 jmpToBootCode[3]; //informational only - don't depend on it u8 oemName[8]; //Count of bytes per sector. This value may take on only the //following values: 512, 1024, 2048 or 4096 u16 bytesPerSector; //Number of sectors per allocation unit. This value must be a //power of 2 that is greater than 0. The legal values are //1, 2, 4, 8, 16, 32, 64, and 128. u8 sectorsPerCluster; //cluster_size //Number of sectors before the first FAT. //This value must not be zero. u16 reservedSectorCount; //The count of FAT data structures on the volume. This field should //always contain the value 2 for any FAT volume of any type. u8 fatCount; //For FAT12 and FAT16 volumes, this field contains the count of //32-byte directory entries in the root directory. For FAT32 volumes, //this field must be set to 0. For FAT12 and FAT16 volumes, this //value should always specify a count that when multiplied by 32 //results in a multiple of bytesPerSector. FAT16 volumes should //use the value 512. u16 rootDirEntryCount; //dir_entries //This field is the old 16-bit total count of sectors on the volume. //This count includes the count of all sectors in all four regions //of the volume. This field can be 0; if it is 0, then totalSectors32 //must be non-zero. For FAT32 volumes, this field must be 0. For //FAT12 and FAT16 volumes, this field contains the sector count, and //totalSectors32 is 0 if the total sector count fits //(is less than 0x10000). u16 totalSectors16; //This dates back to the old MS-DOS 1.x media determination and is //no longer usually used for anything. 0xF8 is the standard value //for fixed (non-removable) media. For removable media, 0xF0 is //frequently used. Legal values are 0xF0 or 0xF8-0xFF. u8 mediaType; //Count of sectors occupied by one FAT on FAT12/FAT16 volumes. //On FAT32 volumes this field must be 0, and sectorsPerFat32 //contains the FAT size count. u16 sectorsPerFat16; //Sectors per track for interrupt 0x13. Not used otherwise. u16 sectorsPerTrack; //Number of heads for interrupt 0x13. Not used otherwise. u16 headCount; //Count of hidden sectors preceding the partition that contains this //FAT volume. This field is generally only relevant for media //visible on interrupt 0x13. u32 hiddenSectors; //This field is the new 32-bit total count of sectors on the volume. //This count includes the count of all sectors in all four regions //of the volume. This field can be 0; if it is 0, then //totalSectors16 must be non-zero. u32 totalSectors32; union { struct __PACKED { msdos_volume_info vi; u8 boot_code[BOOTCODE_SIZE]; } oldfat; struct __PACKED { //Count of sectors occupied by one FAT on FAT32 volumes. u32 sectorsPerFat32; //fat32_length; /* sectors/FAT */ //This field is only defined for FAT32 media and does not exist on //FAT12 and FAT16 media. //Bits 0-3 -- Zero-based number of active FAT. // Only valid if mirroring is disabled. //Bits 4-6 -- Reserved. //Bit 7 -- 0 means the FAT is mirrored at runtime into all FATs. // -- 1 means only one FAT is active; it is the one referenced in bits 0-3. //Bits 8-15 -- Reserved. u16 fat32Flags;// flags; /* bit 8: fat mirroring, low 4: active fat */ //FAT32 version. High byte is major revision number. //Low byte is minor revision number. Only 0.0 define. u16 fat32Version;//version[2]; /* major, minor filesystem version */ //Cluster number of the first cluster of the root directory for FAT32. //This usually 2 but not required to be 2. u32 fat32RootCluster; //root_cluster; /* first cluster in root directory */ //Sector number of FSINFO structure in the reserved area of the //FAT32 volume. Usually 1. u16 fat32FSInfo;// info_sector; /* filesystem info sector */ //If non-zero, indicates the sector number in the reserved area //of the volume of a copy of the boot record. Usually 6. //No value other than 6 is recommended. u16 fat32BackBootBlock; //backup_boot; /* backup boot sector */ //Reserved for future expansion. Code that formats FAT32 volumes //should always set all of the bytes of this field to 0. u8 fat32Reserved[12]; //reserved2[6]; /* Unused */ msdos_volume_info vi; u8 boot_code[BOOTCODE_FAT32_SIZE]; } fat32; }; u8 boot_sign[2]; }; #include "PACKED_END.h" // End Of Chain values for FAT entries //FAT16 end of chain value used by Microsoft. static const u16 FAT16EOC = 0XFFFF; //Minimum value for FAT16 EOC. Use to test for EOC. static const u16 FAT16EOC_MIN = 0XFFF8; //FAT32 end of chain value used by Microsoft. static const u32 FAT32EOC = 0X0FFFFFFF; //Minimum value for FAT32 EOC. Use to test for EOC. static const u32 FAT32EOC_MIN = 0X0FFFFFF8; //Mask a for FAT32 entry. Entries are 28 bits. static const u32 FAT32MASK = 0X0FFFFFFF; //------------------------------------------------------------------------------ //\struct directoryEntry //\brief FAT short directory entry //Short means short 8.3 name, not the entry size. // //Date Format. A FAT directory entry date stamp is a 16-bit field that is //basically a date relative to the MS-DOS epoch of 01/01/1980. Here is the //format (bit 0 is the LSB of the 16-bit word, bit 15 is the MSB of the //16-bit word): // //Bits 9-15: Count of years from 1980, valid value range 0-127 //inclusive (1980-2107). // //Bits 5-8: Month of year, 1 = January, valid value range 1-12 inclusive. //Bits 0-4: Day of month, valid value range 1-31 inclusive. //Time Format. A FAT directory entry time stamp is a 16-bit field that has //a granularity of 2 seconds. Here is the format (bit 0 is the LSB of the //16-bit word, bit 15 is the MSB of the 16-bit word). // //Bits 11-15: Hours, valid value range 0-23 inclusive. // //Bits 5-10: Minutes, valid value range 0-59 inclusive. // //Bits 0-4: 2-second count, valid value range 0-29 inclusive (0 - 58 seconds). // //The valid time range is from Midnight 00:00:00 to 23:59:58. struct TDirectoryEntry { //Short 8.3 name. //The first eight bytes contain the file name with blank fill. //The last three bytes contain the file extension with blank fill. u8 name[11]; //Entry attributes. //The upper two bits of the attribute byte are reserved and should //always be set to 0 when a file is created and never modified or //looked at after that. See defines that begin with DIR_ATT_. u8 attributes; //Reserved for use by Windows NT. Set value to 0 when a file is //created and never modify or look at it after that. u8 reservedNT; //The granularity of the seconds part of creationTime is 2 seconds //so this field is a count of tenths of a second and its valid //value range is 0-199 inclusive. (WHG note - seems to be hundredths) u8 creationTimeTenths; //Time file was created. u16 creationTime; //Date file was created. u16 creationDate; //Last access date. Note that there is no last access time, only //a date. This is the date of last read or write. In the case of //a write, this should be set to the same date as lastWriteDate. u16 lastAccessDate; //High word of this entry's first cluster number (always 0 for a //FAT12 or FAT16 volume). u16 firstClusterHigh; //Time of last write. File creation is considered a write. u16 lastWriteTime; // Date of last write. File creation is considered a write. u16 lastWriteDate; // Low word of this entry's first cluster number. u16 firstClusterLow; //32-bit unsigned holding this file's size in bytes. u32 fileSize; }; //escape for name[0] = 0xE5 static const u8 DIR_NAME_0XE5 = 0x05; //name[0] value for entry that is free after being "deleted" static const u8 DIR_NAME_DELETED = 0xE5; //name[0] value for entry that is free and no allocated entries follow static const u8 DIR_NAME_FREE = 0x00; //file is read-only static const u8 DIR_ATT_READ_ONLY = 0x01; //File should hidden in directory listings static const u8 DIR_ATT_HIDDEN = 0x02; //Entry is for a system file static const u8 DIR_ATT_SYSTEM = 0x04; //Directory entry contains the volume label static const u8 DIR_ATT_VOLUME_ID = 0x08; //Entry is for a directory static const u8 DIR_ATT_DIRECTORY = 0x10; //Old DOS archive bit for backup support static const u8 DIR_ATT_ARCHIVE = 0x20; //Test value for long name entry. Test is //(d->attributes & DIR_ATT_LONG_NAME_MASK) == DIR_ATT_LONG_NAME. static const u8 DIR_ATT_LONG_NAME = 0x0F; //Test mask for long name entry static const u8 DIR_ATT_LONG_NAME_MASK = 0x3F; //defined attribute bits static const u8 DIR_ATT_DEFINED_BITS = 0x3F; //Directory entry is part of a long name static inline u8 DIR_IS_LONG_NAME(const TDirectoryEntry* dir) { return (dir->attributes & DIR_ATT_LONG_NAME_MASK) == DIR_ATT_LONG_NAME; } //Mask for file/subdirectory tests static const u8 DIR_ATT_FILE_TYPE_MASK = (DIR_ATT_VOLUME_ID | DIR_ATT_DIRECTORY); //Directory entry is for a file static inline u8 DIR_IS_FILE(const TDirectoryEntry* dir) { return (dir->attributes & DIR_ATT_FILE_TYPE_MASK) == 0; } //Directory entry is for a subdirectory static inline u8 DIR_IS_SUBDIR(const TDirectoryEntry* dir) { return (dir->attributes & DIR_ATT_FILE_TYPE_MASK) == DIR_ATT_DIRECTORY; } //Directory entry is for a file or subdirectory static inline u8 DIR_IS_FILE_OR_SUBDIR(const TDirectoryEntry* dir) { return (dir->attributes & DIR_ATT_VOLUME_ID) == 0; } // flags for timestamp /** set the file's last access date */ static const u8 T_ACCESS = 1; /** set the file's creation date and time */ static const u8 T_CREATE = 2; /** Set the file's write date and time */ static const u8 T_WRITE = 4; // values for type_ /** This SdFile has not been opened. */ static const u8 FAT_FILE_TYPE_CLOSED = 0; /** SdFile for a file */ static const u8 FAT_FILE_TYPE_NORMAL = 1; /** SdFile for a FAT16 root directory */ static const u8 FAT_FILE_TYPE_ROOT16 = 2; /** SdFile for a FAT32 root directory */ static const u8 FAT_FILE_TYPE_ROOT32 = 3; /** SdFile for a subdirectory */ static const u8 FAT_FILE_TYPE_SUBDIR = 4; /** Test value for directory type */ static const u8 FAT_FILE_TYPE_MIN_DIR = FAT_FILE_TYPE_ROOT16; /** date field for FAT directory entry */ static inline u16 FAT_DATE(u16 year, u8 month, u8 day) { return (year - 1980) << 9 | month << 5 | day; } /** year part of FAT directory date field */ static inline u16 FAT_YEAR(u16 fatDate) { return 1980 + (fatDate >> 9); } /** month part of FAT directory date field */ static inline u8 FAT_MONTH(u16 fatDate) { return (fatDate >> 5) & 0XF; } /** day part of FAT directory date field */ static inline u8 FAT_DAY(u16 fatDate) { return fatDate & 0X1F; } /** time field for FAT directory entry */ static inline u16 FAT_TIME(u8 hour, u8 minute, u8 second) { return hour << 11 | minute << 5 | second >> 1; } /** hour part of FAT directory time field */ static inline u8 FAT_HOUR(u16 fatTime) { return fatTime >> 11; } /** minute part of FAT directory time field */ static inline u8 FAT_MINUTE(u16 fatTime) { return(fatTime >> 5) & 0X3F; } /** second part of FAT directory time field */ static inline u8 FAT_SECOND(u16 fatTime) { return 2*(fatTime & 0X1F); } /** Default date for file timestamps is 1 Jan 2000 */ static const u16 FAT_DEFAULT_DATE = ((2000 - 1980) << 9) | (1 << 5) | 1; /** Default time for file timestamp is 1 am */ static const u16 FAT_DEFAULT_TIME = (1 << 11); //------------------------------------------------------ class EmuFat; class EmuFatVolume; class EmuFatFile; union cache_t { /** Used to access cached file data blocks. */ u8 data[512]; /** Used to access cached FAT16 entries. */ u16 fat16[256]; /** Used to access cached FAT32 entries. */ u32 fat32[128]; /** Used to access cached directory entries. */ TDirectoryEntry dir[16]; /** Used to access a cached MasterBoot Record. */ TMasterBootRecord mbr; /** Used to access to a cached FAT boot sector. */ TFat32BootSector fbs; }; class EmuFatFile { public: /** Create an instance of EmuFatFile. */ EmuFatFile() : type_(FAT_FILE_TYPE_CLOSED) {} bool writeError; void clearUnbufferedRead(void) { flags_ &= ~F_FILE_UNBUFFERED_READ; } void setUnbufferedRead(void) { if (isFile()) flags_ |= F_FILE_UNBUFFERED_READ; } u8 unbufferedRead(void) const { return flags_ & F_FILE_UNBUFFERED_READ; } u8 close(void); u8 contiguousRange(u32* bgnBlock, u32* endBlock); u8 createContiguous(EmuFatFile* dirFile, const char* fileName, u32 size); /** \return The current cluster number for a file or directory. */ u32 curCluster(void) const {return curCluster_;} /** \return The current position for a file or directory. */ u32 curPosition(void) const {return curPosition_;} u8 rmDir(void); u8 rmRfStar(void); s16 read(void) { u8 b; return read(&b, 1) == 1 ? b : -1; } s32 read(void* buf, u32 nbyte); s8 readDir(TDirectoryEntry* dir); s32 write(const void* buf, u32 nbyte); u8 openRoot(EmuFatVolume* vol); u8 timestamp(u8 flag, u16 year, u8 month, u8 day, u8 hour, u8 minute, u8 second); u8 sync(void); u8 makeDir(EmuFatFile* dir, const char* dirName); u8 open(EmuFatFile* dirFile, u16 index, u8 oflag); u8 open(EmuFatFile* dirFile, const char* fileName, u8 oflag); u8 remove(EmuFatFile* dirFile, const char* fileName); u8 remove(void); u8 dirEntry(TDirectoryEntry* dir); u8 seekCur(u32 pos) { return seekSet(curPosition_ + pos); } /** * Set the files current position to end of file. Useful to position * a file for append. See seekSet(). */ u8 seekEnd(void) {return seekSet(fileSize_);} u8 seekSet(u32 pos); u8 type(void) const {return type_;} u8 truncate(u32 size); u32 dirBlock(void) const {return dirBlock_;} /** \return Index of this file's directory in the block dirBlock. */ u8 dirIndex(void) const {return dirIndex_;} static void dirName(const TDirectoryEntry& dir, char* name); /** \return The total number of bytes in a file or directory. */ u32 fileSize(void) const {return fileSize_;} /** \return The first cluster number for a file or directory. */ u32 firstCluster(void) const {return firstCluster_;} /** \return True if this is a SdFile for a directory else false. */ u8 isDir(void) const {return type_ >= FAT_FILE_TYPE_MIN_DIR;} /** \return True if this is a SdFile for a file else false. */ u8 isFile(void) const {return type_ == FAT_FILE_TYPE_NORMAL;} /** \return True if this is a SdFile for an open file/directory else false. */ u8 isOpen(void) const {return type_ != FAT_FILE_TYPE_CLOSED;} /** \return True if this is a SdFile for a subdirectory else false. */ u8 isSubDir(void) const {return type_ == FAT_FILE_TYPE_SUBDIR;} /** \return True if this is a SdFile for the root directory. */ u8 isRoot(void) const { return type_ == FAT_FILE_TYPE_ROOT16 || type_ == FAT_FILE_TYPE_ROOT32; } /** Set the file's current position to zero. */ void rewind(void) { curPosition_ = curCluster_ = 0; } private: // bits defined in flags_ // should be 0XF static const u8 F_OFLAG = (EO_ACCMODE | EO_APPEND | EO_SYNC); // available bits static const u8 F_UNUSED = 0x30; // use unbuffered SD read static const u8 F_FILE_UNBUFFERED_READ = 0X40; // sync of directory entry required static const u8 F_FILE_DIR_DIRTY = 0x80; // make sure F_OFLAG is ok void ctassert() { retro_assert(!((F_UNUSED | F_FILE_UNBUFFERED_READ | F_FILE_DIR_DIRTY) & F_OFLAG)); } // private data u8 flags_; // See above for definition of flags_ bits u8 type_; // type of file see above for values u32 curCluster_; // cluster for current file position u32 curPosition_; // current file position in bytes from beginning u32 dirBlock_; // SD block that contains directory entry for file u8 dirIndex_; // index of entry in dirBlock 0 <= dirIndex_ <= 0XF u32 fileSize_; // file size in bytes u32 firstCluster_; // first cluster of file EmuFatVolume* vol_; // volume where file is located // private functions u8 addCluster(void); u8 addDirCluster(void); TDirectoryEntry* cacheDirEntry(u8 action); static u8 make83Name(const char* str, u8* name); u8 openCachedEntry(u8 cacheIndex, u8 oflags); TDirectoryEntry* readDirCache(void); }; class EmuFatVolume { public: EmuFatVolume() :allocSearchStart_(2), fatType_(0) {} //Initialize a FAT volume. Try partition one first then try super floppy format. //dev The Sd2Card where the volume is located. //return The value one, true, is returned for success and //the value zero, false, is returned for failure. Reasons for //failure include not finding a valid partition, not finding a valid //FAT file system or an I/O error. bool init(EmuFat* dev) { return init(dev, 1) ? true : init(dev, 0);} bool init(EmuFat* dev, u8 part); bool format(u32 sectors); bool formatNew(u32 sectors); // inline functions that return volume info //The volume's cluster size in blocks. u8 blocksPerCluster(void) const {return blocksPerCluster_;} //The number of blocks in one FAT. u32 blocksPerFat(void) const {return blocksPerFat_;} //The total number of clusters in the volume. // u32 clusterCount(void) const {return clusterCount_;} //The shift count required to multiply by blocksPerCluster. // u8 clusterSizeShift(void) const {return clusterSizeShift_;} //The logical block number for the start of file data. // u32 dataStartBlock(void) const {return dataStartBlock_;} //The number of FAT structures on the volume. // u8 fatCount(void) const {return fatCount_;} //The logical block number for the start of the first FAT. // u32 fatStartBlock(void) const {return fatStartBlock_;} //The FAT type of the volume. Values are 12, 16 or 32. // u8 fatType(void) const {return fatType_;} //The number of entries in the root directory for FAT16 volumes. // u32 rootDirEntryCount(void) const {return rootDirEntryCount_;} //The logical block number for the start of the root directory on FAT16 volumes or the first cluster number on FAT32 volumes. // u32 rootDirStart(void) const {return rootDirStart_;} EmuFat* dev_; private: friend class EmuFatFile; u32 allocSearchStart_; // start cluster for alloc search u8 blocksPerCluster_; // cluster size in blocks u32 blocksPerFat_; // FAT size in blocks u32 clusterCount_; // clusters in one FAT u8 clusterSizeShift_; // shift to convert cluster count to block count u32 dataStartBlock_; // first data block number u8 fatCount_; // number of FATs on volume u32 fatStartBlock_; // start block for first FAT u8 fatType_; // volume type (12, 16, OR 32) u16 rootDirEntryCount_; // number of entries in FAT16 root dir u32 rootDirStart_; // root start block for FAT16, cluster for FAT32 u8 allocContiguous(u32 count, u32* curCluster); u8 blockOfCluster(u32 position) const { return (position >> 9) & (blocksPerCluster_ - 1);} u32 clusterStartBlock(u32 cluster) const { return dataStartBlock_ + ((cluster - 2) << clusterSizeShift_);} u32 blockNumber(u32 cluster, u32 position) const { return clusterStartBlock(cluster) + blockOfCluster(position);} u8 fatGet(u32 cluster, u32* value) const; u8 fatPut(u32 cluster, u32 value); u8 fatPutEOC(u32 cluster) { return fatPut(cluster, 0x0FFFFFFF); } u8 chainSize(u32 beginCluster, u32* size) const; u8 freeChain(u32 cluster); u8 isEOC(u32 cluster) const { return cluster >= (fatType_ == 16 ? FAT16EOC_MIN : FAT32EOC_MIN); } u8 readData(u32 block, u16 offset, u16 count, u8* dst); u8 writeBlock(u32 block, const u8* dst); }; class EmuFat { public: EmuFat(const char* fname, bool readonly=false); EmuFat(); EmuFat(EMUFILE* fileNotToDelete); virtual ~EmuFat(); private: EMUFILE* m_pFile; bool m_readonly, m_owns; friend class EmuFatVolume; friend class EmuFatFile; // value for action argument in cacheRawBlock to indicate read from cache static const u8 CACHE_FOR_READ = 0; // value for action argument in cacheRawBlock to indicate cache dirty static const u8 CACHE_FOR_WRITE = 1; struct Cache { Cache() : cacheBlockNumber_(0xFFFFFFFF) , cacheDirty_(0) // cacheFlush() will write block if true , cacheMirrorBlock_(0) // mirror block for second FAT {} cache_t cacheBuffer_; // 512 byte cache for device blocks u32 cacheBlockNumber_; // Logical number of block in the cache u8 cacheDirty_; // cacheFlush() will write block if true u32 cacheMirrorBlock_; // block number for mirror FAT } cache_; u8 cacheRawBlock(u32 blockNumber, u8 action); void cacheSetDirty() {cache_.cacheDirty_ |= CACHE_FOR_WRITE;} u8 cacheZeroBlock(u32 blockNumber); u8 cacheFlush(); void cacheReset(); //IO functions: u8 readBlock(u32 block, u8* dst); u8 writeBlock(u32 blockNumber, const u8* src); u8 readData(u32 block, u16 offset, u16 count, u8* dst); void truncate(u32 size); }; #endif //EMUFAT_H desmume/src/arm_instructions.cpp000664 001750 001750 00000435756 12755534123 020272 0ustar00sergiosergio000000 000000 /* Copyright (C) 2006 yopyop Copyright (C) 2006-2007 shash Copyright (C) 2008-2016 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the this software. If not, see . */ // ARM core TODO: // - Check all the LDM/STM opcodes: quirks when Rb included in Rlist; opcodes // operating on user registers (LDMXX2/STMXX2) // - Force User mode memory access for LDRx/STRx opcodes with bit24=0 and bit21=1 // (has to be done at memory side; once the PU is emulated well enough) // - Check LDMxx2/STMxx2 (those opcodes that act on User mode registers instead // of current ones) //#define UNTESTEDOPCODEDEBUG #include "utils/bits.h" #include "instructions.h" #include "cp15.h" #ifdef DEBUG #include "debug.h" #endif #include "MMU.h" #include "armcpu.h" #include "NDSSystem.h" #include "MMU_timing.h" #include "bios.h" #define cpu (&ARMPROC) #define TEMPLATE template //----------------------------------------------------------------------------- // Shifting macros //----------------------------------------------------------------------------- #define LSL_IMM \ u32 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)]<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 \ u32 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 \ u32 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 \ u32 shift_op = ((i>>7)&0x1F); \ if(shift_op==0) \ { \ shift_op = ((u32)cpu->CPSR.bits.C<<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) \ { \ shift_op = ((u32)cpu->CPSR.bits.C<<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&0x1F)==0)) \ shift_op=cpu->R[REG_POS(i,0)]; \ else \ shift_op = ROR(cpu->R[REG_POS(i,0)],(shift_op&0x1F)); #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&=0x1F; \ 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); \ } \ } #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) //----------------------------------------------------------------------------- // Undefined instruction //----------------------------------------------------------------------------- TEMPLATE static u32 FASTCALL OP_UND(const u32 i) { TRAPUNDEF(cpu); return 1; } //----------------------------------------------------------------------------- // AND / ANDS // Timing: OK //----------------------------------------------------------------------------- #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) \ 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->changeCPSR(); \ cpu->R[15] &= (0xFFFFFFFC|(((u32)cpu->CPSR.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; TEMPLATE static u32 FASTCALL OP_AND_LSL_IMM(const u32 i) { LSL_IMM; OP_AND(1, 3); } TEMPLATE static u32 FASTCALL OP_AND_LSL_REG(const u32 i) { LSL_REG; OP_AND(2, 4); } TEMPLATE static u32 FASTCALL OP_AND_LSR_IMM(const u32 i) { LSR_IMM; OP_AND(1, 3); } TEMPLATE static u32 FASTCALL OP_AND_LSR_REG(const u32 i) { LSR_REG; OP_AND(2, 4); } TEMPLATE static u32 FASTCALL OP_AND_ASR_IMM(const u32 i) { ASR_IMM; OP_AND(1, 3); } TEMPLATE static u32 FASTCALL OP_AND_ASR_REG(const u32 i) { ASR_REG; OP_AND(2, 4); } TEMPLATE static u32 FASTCALL OP_AND_ROR_IMM(const u32 i) { ROR_IMM; OP_AND(1, 3); } TEMPLATE static u32 FASTCALL OP_AND_ROR_REG(const u32 i) { ROR_REG; OP_AND(2, 4); } TEMPLATE static u32 FASTCALL OP_AND_IMM_VAL(const u32 i) { IMM_VALUE; OP_AND(1, 3); } TEMPLATE static u32 FASTCALL OP_AND_S_LSL_IMM(const u32 i) { S_LSL_IMM; OP_ANDS(1, 3); } TEMPLATE static u32 FASTCALL OP_AND_S_LSL_REG(const u32 i) { S_LSL_REG; OP_ANDS(2, 4); } TEMPLATE static u32 FASTCALL OP_AND_S_LSR_IMM(const u32 i) { S_LSR_IMM; OP_ANDS(1, 3); } TEMPLATE static u32 FASTCALL OP_AND_S_LSR_REG(const u32 i) { S_LSR_REG; OP_ANDS(2, 4); } TEMPLATE static u32 FASTCALL OP_AND_S_ASR_IMM(const u32 i) { S_ASR_IMM; OP_ANDS(1, 3); } TEMPLATE static u32 FASTCALL OP_AND_S_ASR_REG(const u32 i) { S_ASR_REG; OP_ANDS(2, 4); } TEMPLATE static u32 FASTCALL OP_AND_S_ROR_IMM(const u32 i) { S_ROR_IMM; OP_ANDS(1, 3); } TEMPLATE static u32 FASTCALL OP_AND_S_ROR_REG(const u32 i) { S_ROR_REG; OP_ANDS(2, 4); } TEMPLATE static u32 FASTCALL OP_AND_S_IMM_VAL(const u32 i) { S_IMM_VALUE; OP_ANDS(1, 3); } //----------------------------------------------------------------------------- // EOR / EORS //----------------------------------------------------------------------------- #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->changeCPSR(); \ cpu->R[15] &= (0xFFFFFFFC|(((u32)cpu->CPSR.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; TEMPLATE static u32 FASTCALL OP_EOR_LSL_IMM(const u32 i) { LSL_IMM; OP_EOR(1, 3); } TEMPLATE static u32 FASTCALL OP_EOR_LSL_REG(const u32 i) { LSL_REG; OP_EOR(2, 4); } TEMPLATE static u32 FASTCALL OP_EOR_LSR_IMM(const u32 i) { LSR_IMM; OP_EOR(1, 3); } TEMPLATE static u32 FASTCALL OP_EOR_LSR_REG(const u32 i) { LSR_REG; OP_EOR(2, 4); } TEMPLATE static u32 FASTCALL OP_EOR_ASR_IMM(const u32 i) { ASR_IMM; OP_EOR(1, 3); } TEMPLATE static u32 FASTCALL OP_EOR_ASR_REG(const u32 i) { ASR_REG; OP_EOR(2, 4); } TEMPLATE static u32 FASTCALL OP_EOR_ROR_IMM(const u32 i) { ROR_IMM; OP_EOR(1, 3); } TEMPLATE static u32 FASTCALL OP_EOR_ROR_REG(const u32 i) { ROR_REG; OP_EOR(2, 4); } TEMPLATE static u32 FASTCALL OP_EOR_IMM_VAL(const u32 i) { IMM_VALUE; OP_EOR(1, 3); } TEMPLATE static u32 FASTCALL OP_EOR_S_LSL_IMM(const u32 i) { S_LSL_IMM; OP_EORS(1, 3); } TEMPLATE static u32 FASTCALL OP_EOR_S_LSL_REG(const u32 i) { S_LSL_REG; OP_EORS(2, 4); } TEMPLATE static u32 FASTCALL OP_EOR_S_LSR_IMM(const u32 i) { S_LSR_IMM; OP_EORS(1, 3); } TEMPLATE static u32 FASTCALL OP_EOR_S_LSR_REG(const u32 i) { S_LSR_REG; OP_EORS(2, 4); } TEMPLATE static u32 FASTCALL OP_EOR_S_ASR_IMM(const u32 i) { S_ASR_IMM; OP_EORS(1, 3); } TEMPLATE static u32 FASTCALL OP_EOR_S_ASR_REG(const u32 i) { S_ASR_REG; OP_EORS(2, 4); } TEMPLATE static u32 FASTCALL OP_EOR_S_ROR_IMM(const u32 i) { S_ROR_IMM; OP_EORS(1, 3); } TEMPLATE static u32 FASTCALL OP_EOR_S_ROR_REG(const u32 i) { S_ROR_REG; OP_EORS(2, 4); } TEMPLATE static u32 FASTCALL OP_EOR_S_IMM_VAL(const u32 i) { S_IMM_VALUE; OP_EORS(1, 3); } //----------------------------------------------------------------------------- // SUB / SUBS //----------------------------------------------------------------------------- #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 OP_SUBS(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->changeCPSR(); \ cpu->R[15] &= (0xFFFFFFFC|(((u32)cpu->CPSR.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 = !BorrowFrom(v, shift_op); \ cpu->CPSR.bits.V = OverflowFromSUB(cpu->R[REG_POS(i,12)], v, shift_op); \ return a; TEMPLATE static u32 FASTCALL OP_SUB_LSL_IMM(const u32 i) { LSL_IMM; OP_SUB(1, 3); } TEMPLATE static u32 FASTCALL OP_SUB_LSL_REG(const u32 i) { LSL_REG; OP_SUB(2, 4); } TEMPLATE static u32 FASTCALL OP_SUB_LSR_IMM(const u32 i) { LSR_IMM; OP_SUB(1, 3); } TEMPLATE static u32 FASTCALL OP_SUB_LSR_REG(const u32 i) { LSR_REG; OP_SUB(2, 4); } TEMPLATE static u32 FASTCALL OP_SUB_ASR_IMM(const u32 i) { ASR_IMM; OP_SUB(1, 3); } TEMPLATE static u32 FASTCALL OP_SUB_ASR_REG(const u32 i) { ASR_REG; OP_SUB(2, 4); } TEMPLATE static u32 FASTCALL OP_SUB_ROR_IMM(const u32 i) { ROR_IMM; OP_SUB(1, 3); } TEMPLATE static u32 FASTCALL OP_SUB_ROR_REG(const u32 i) { ROR_REG; OP_SUB(2, 4); } TEMPLATE static u32 FASTCALL OP_SUB_IMM_VAL(const u32 i) { IMM_VALUE; OP_SUB(1, 3); } TEMPLATE static u32 FASTCALL OP_SUB_S_LSL_IMM(const u32 i) { u32 v = cpu->R[REG_POS(i,16)]; LSL_IMM; OP_SUBS(1, 3); } TEMPLATE static u32 FASTCALL OP_SUB_S_LSL_REG(const u32 i) { u32 v = cpu->R[REG_POS(i,16)]; LSL_REG; OP_SUBS(2, 4); } TEMPLATE static u32 FASTCALL OP_SUB_S_LSR_IMM(const u32 i) { u32 v = cpu->R[REG_POS(i,16)]; LSR_IMM; OP_SUBS(1, 3); } TEMPLATE static u32 FASTCALL OP_SUB_S_LSR_REG(const u32 i) { u32 v = cpu->R[REG_POS(i,16)]; LSR_REG; OP_SUBS(2, 4); } TEMPLATE static u32 FASTCALL OP_SUB_S_ASR_IMM(const u32 i) { u32 v = cpu->R[REG_POS(i,16)]; ASR_IMM; OP_SUBS(1, 3); } TEMPLATE static u32 FASTCALL OP_SUB_S_ASR_REG(const u32 i) { u32 v = cpu->R[REG_POS(i,16)]; ASR_REG; OP_SUBS(2, 4); } TEMPLATE static u32 FASTCALL OP_SUB_S_ROR_IMM(const u32 i) { u32 v = cpu->R[REG_POS(i,16)]; ROR_IMM; OP_SUBS(1, 3); } TEMPLATE static u32 FASTCALL OP_SUB_S_ROR_REG(const u32 i) { u32 v = cpu->R[REG_POS(i,16)]; ROR_REG; OP_SUBS(2, 4); } TEMPLATE static u32 FASTCALL OP_SUB_S_IMM_VAL(const u32 i) { u32 v = cpu->R[REG_POS(i,16)]; IMM_VALUE; OP_SUBS(1, 3); } //----------------------------------------------------------------------------- // RSB / RSBS //----------------------------------------------------------------------------- #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->changeCPSR(); \ cpu->R[15] &= (0xFFFFFFFC|(((u32)cpu->CPSR.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 = !BorrowFrom(shift_op, v); \ cpu->CPSR.bits.V = OverflowFromSUB(cpu->R[REG_POS(i,12)], shift_op, v); \ return a; TEMPLATE static u32 FASTCALL OP_RSB_LSL_IMM(const u32 i) { LSL_IMM; OP_RSB(1, 3); } TEMPLATE static u32 FASTCALL OP_RSB_LSL_REG(const u32 i) { LSL_REG; OP_RSB(2, 4); } TEMPLATE static u32 FASTCALL OP_RSB_LSR_IMM(const u32 i) { LSR_IMM; OP_RSB(1, 3); } TEMPLATE static u32 FASTCALL OP_RSB_LSR_REG(const u32 i) { LSR_REG; OP_RSB(2, 4); } TEMPLATE static u32 FASTCALL OP_RSB_ASR_IMM(const u32 i) { ASR_IMM; OP_RSB(1, 3); } TEMPLATE static u32 FASTCALL OP_RSB_ASR_REG(const u32 i) { ASR_REG; OP_RSB(2, 4); } TEMPLATE static u32 FASTCALL OP_RSB_ROR_IMM(const u32 i) { ROR_IMM; OP_RSB(1, 3); } TEMPLATE static u32 FASTCALL OP_RSB_ROR_REG(const u32 i) { ROR_REG; OP_RSB(2, 4); } TEMPLATE static u32 FASTCALL OP_RSB_IMM_VAL(const u32 i) { IMM_VALUE; OP_RSB(1, 3); } TEMPLATE static u32 FASTCALL OP_RSB_S_LSL_IMM(const u32 i) { u32 v = cpu->R[REG_POS(i,16)]; LSL_IMM; OP_RSBS(1, 3); } TEMPLATE static u32 FASTCALL OP_RSB_S_LSL_REG(const u32 i) { u32 v = cpu->R[REG_POS(i,16)]; LSL_REG; OP_RSBS(2, 4); } TEMPLATE static u32 FASTCALL OP_RSB_S_LSR_IMM(const u32 i) { u32 v = cpu->R[REG_POS(i,16)]; LSR_IMM; OP_RSBS(1, 3); } TEMPLATE static u32 FASTCALL OP_RSB_S_LSR_REG(const u32 i) { u32 v = cpu->R[REG_POS(i,16)]; LSR_REG; OP_RSBS(2, 4); } TEMPLATE static u32 FASTCALL OP_RSB_S_ASR_IMM(const u32 i) { u32 v = cpu->R[REG_POS(i,16)]; ASR_IMM; OP_RSBS(1, 3); } TEMPLATE static u32 FASTCALL OP_RSB_S_ASR_REG(const u32 i) { u32 v = cpu->R[REG_POS(i,16)]; ASR_REG; OP_RSBS(2, 4); } TEMPLATE static u32 FASTCALL OP_RSB_S_ROR_IMM(const u32 i) { u32 v = cpu->R[REG_POS(i,16)]; ROR_IMM; OP_RSBS(1, 3); } TEMPLATE static u32 FASTCALL OP_RSB_S_ROR_REG(const u32 i) { u32 v = cpu->R[REG_POS(i,16)]; ROR_REG; OP_RSBS(2, 4); } TEMPLATE static u32 FASTCALL OP_RSB_S_IMM_VAL(const u32 i) { u32 v = cpu->R[REG_POS(i,16)]; IMM_VALUE; OP_RSBS(1, 3); } //----------------------------------------------------------------------------- // ADD / ADDS //----------------------------------------------------------------------------- #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; #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->changeCPSR(); \ cpu->R[15] &= (0xFFFFFFFC|(((u32)cpu->CPSR.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 = CarryFrom(v, shift_op); \ cpu->CPSR.bits.V = OverflowFromADD(cpu->R[REG_POS(i,12)], v, shift_op); \ return a; TEMPLATE static u32 FASTCALL OP_ADD_LSL_IMM(const u32 i) { LSL_IMM; OP_ADD(1, 3); } TEMPLATE static u32 FASTCALL OP_ADD_LSL_REG(const u32 i) { LSL_REG; OP_ADD(2, 4); } TEMPLATE static u32 FASTCALL OP_ADD_LSR_IMM(const u32 i) { LSR_IMM; OP_ADD(1, 3); } TEMPLATE static u32 FASTCALL OP_ADD_LSR_REG(const u32 i) { LSR_REG; OP_ADD(2, 4); } TEMPLATE static u32 FASTCALL OP_ADD_ASR_IMM(const u32 i) { ASR_IMM; OP_ADD(1, 3); } TEMPLATE static u32 FASTCALL OP_ADD_ASR_REG(const u32 i) { ASR_REG; OP_ADD(2, 4); } TEMPLATE static u32 FASTCALL OP_ADD_ROR_IMM(const u32 i) { ROR_IMM; OP_ADD(1, 3); } TEMPLATE static u32 FASTCALL OP_ADD_ROR_REG(const u32 i) { ROR_REG; OP_ADD(2, 4); } TEMPLATE static u32 FASTCALL OP_ADD_IMM_VAL(const u32 i) { IMM_VALUE; OP_ADD(1, 3); } TEMPLATE static u32 FASTCALL OP_ADD_S_LSL_IMM(const u32 i) { u32 v = cpu->R[REG_POS(i,16)]; LSL_IMM; OP_ADDS(1, 3); } TEMPLATE static u32 FASTCALL OP_ADD_S_LSL_REG(const u32 i) { u32 v = cpu->R[REG_POS(i,16)]; LSL_REG; OP_ADDS(2, 4); } TEMPLATE static u32 FASTCALL OP_ADD_S_LSR_IMM(const u32 i) { u32 v = cpu->R[REG_POS(i,16)]; LSR_IMM; OP_ADDS(1, 3); } TEMPLATE static u32 FASTCALL OP_ADD_S_LSR_REG(const u32 i) { u32 v = cpu->R[REG_POS(i,16)]; LSR_REG; OP_ADDS(2, 4); } TEMPLATE static u32 FASTCALL OP_ADD_S_ASR_IMM(const u32 i) { u32 v = cpu->R[REG_POS(i,16)]; ASR_IMM; OP_ADDS(1, 3); } TEMPLATE static u32 FASTCALL OP_ADD_S_ASR_REG(const u32 i) { u32 v = cpu->R[REG_POS(i,16)]; ASR_REG; OP_ADDS(2, 4); } TEMPLATE static u32 FASTCALL OP_ADD_S_ROR_IMM(const u32 i) { u32 v = cpu->R[REG_POS(i,16)]; ROR_IMM; OP_ADDS(1, 3); } TEMPLATE static u32 FASTCALL OP_ADD_S_ROR_REG(const u32 i) { u32 v = cpu->R[REG_POS(i,16)]; ROR_REG; OP_ADDS(2, 4); } TEMPLATE static u32 FASTCALL OP_ADD_S_IMM_VAL(const u32 i) { u32 v = cpu->R[REG_POS(i,16)]; IMM_VALUE; OP_ADDS(1, 3); } //----------------------------------------------------------------------------- // ADC / ADCS //----------------------------------------------------------------------------- #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; #define OP_ADCS(a, b) \ { \ if(REG_POS(i,12)==15) \ { \ cpu->R[REG_POS(i,12)] = v + shift_op + cpu->CPSR.bits.C; \ Status_Reg SPSR = cpu->SPSR; \ armcpu_switchMode(cpu, SPSR.bits.mode); \ cpu->CPSR=SPSR; \ cpu->changeCPSR(); \ cpu->R[15] &= (0xFFFFFFFC|(((u32)cpu->CPSR.bits.T)<<1)); \ cpu->next_instruction = cpu->R[15]; \ return b; \ } \ if (!cpu->CPSR.bits.C) \ { \ cpu->R[REG_POS(i,12)] = v + shift_op; \ cpu->CPSR.bits.C = cpu->R[REG_POS(i,12)] < v; \ } \ else \ { \ cpu->R[REG_POS(i,12)] = v + shift_op + 1; \ cpu->CPSR.bits.C = cpu->R[REG_POS(i,12)] <= v; \ } \ 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.V = BIT31((v ^ shift_op ^ -1) & (v ^ cpu->R[REG_POS(i, 12)]));\ return a; \ } TEMPLATE static u32 FASTCALL OP_ADC_LSL_IMM(const u32 i) { LSL_IMM; OP_ADC(1, 3); } TEMPLATE static u32 FASTCALL OP_ADC_LSL_REG(const u32 i) { LSL_REG; OP_ADC(2, 4); } TEMPLATE static u32 FASTCALL OP_ADC_LSR_IMM(const u32 i) { LSR_IMM; OP_ADC(1, 3); } TEMPLATE static u32 FASTCALL OP_ADC_LSR_REG(const u32 i) { LSR_REG; OP_ADC(2, 4); } TEMPLATE static u32 FASTCALL OP_ADC_ASR_IMM(const u32 i) { ASR_IMM; OP_ADC(1, 3); } TEMPLATE static u32 FASTCALL OP_ADC_ASR_REG(const u32 i) { ASR_REG; OP_ADC(2, 4); } TEMPLATE static u32 FASTCALL OP_ADC_ROR_IMM(const u32 i) { ROR_IMM; OP_ADC(1, 3); } TEMPLATE static u32 FASTCALL OP_ADC_ROR_REG(const u32 i) { ROR_REG; OP_ADC(2, 4); } TEMPLATE static u32 FASTCALL OP_ADC_IMM_VAL(const u32 i) { IMM_VALUE; OP_ADC(1, 3); } TEMPLATE static u32 FASTCALL OP_ADC_S_LSL_IMM(const u32 i) { u32 v = cpu->R[REG_POS(i,16)]; LSL_IMM; OP_ADCS(1, 3); } TEMPLATE static u32 FASTCALL OP_ADC_S_LSL_REG(const u32 i) { u32 v = cpu->R[REG_POS(i,16)]; LSL_REG; OP_ADCS(2, 4); } TEMPLATE static u32 FASTCALL OP_ADC_S_LSR_IMM(const u32 i) { u32 v = cpu->R[REG_POS(i,16)]; LSR_IMM; OP_ADCS(1, 3); } TEMPLATE static u32 FASTCALL OP_ADC_S_LSR_REG(const u32 i) { u32 v = cpu->R[REG_POS(i,16)]; LSR_REG; OP_ADCS(2, 4); } TEMPLATE static u32 FASTCALL OP_ADC_S_ASR_IMM(const u32 i) { u32 v = cpu->R[REG_POS(i,16)]; ASR_IMM; OP_ADCS(1, 3); } TEMPLATE static u32 FASTCALL OP_ADC_S_ASR_REG(const u32 i) { u32 v = cpu->R[REG_POS(i,16)]; ASR_REG; OP_ADCS(2, 4); } TEMPLATE static u32 FASTCALL OP_ADC_S_ROR_IMM(const u32 i) { u32 v = cpu->R[REG_POS(i,16)]; ROR_IMM; OP_ADCS(1, 3); } TEMPLATE static u32 FASTCALL OP_ADC_S_ROR_REG(const u32 i) { u32 v = cpu->R[REG_POS(i,16)]; ROR_REG; OP_ADCS(2, 4); } TEMPLATE static u32 FASTCALL OP_ADC_S_IMM_VAL(const u32 i) { u32 v = cpu->R[REG_POS(i,16)]; IMM_VALUE; OP_ADCS(1, 3); } //----------------------------------------------------------------------------- // SBC / SBCS //----------------------------------------------------------------------------- #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; #define OP_SBCS(a, b) \ { \ if(REG_POS(i,12)==15) \ { \ cpu->R[REG_POS(i,12)] = v - shift_op - !cpu->CPSR.bits.C; \ Status_Reg SPSR = cpu->SPSR; \ armcpu_switchMode(cpu, SPSR.bits.mode); \ cpu->CPSR=SPSR; \ cpu->changeCPSR(); \ cpu->R[15] &= (0xFFFFFFFC|(((u32)cpu->CPSR.bits.T)<<1)); \ cpu->next_instruction = cpu->R[15]; \ return b; \ } \ if (!cpu->CPSR.bits.C) \ { \ cpu->R[REG_POS(i,12)] = v - shift_op - 1; \ cpu->CPSR.bits.C = v > shift_op; \ } \ else \ { \ cpu->R[REG_POS(i,12)] = v - shift_op; \ cpu->CPSR.bits.C = v >= shift_op; \ } \ 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.V = BIT31((v ^ shift_op) & (v ^ cpu->R[REG_POS(i, 12)])); \ return a; \ } TEMPLATE static u32 FASTCALL OP_SBC_LSL_IMM(const u32 i) { LSL_IMM; OP_SBC(1, 3); } TEMPLATE static u32 FASTCALL OP_SBC_LSL_REG(const u32 i) { LSL_REG; OP_SBC(2, 4); } TEMPLATE static u32 FASTCALL OP_SBC_LSR_IMM(const u32 i) { LSR_IMM; OP_SBC(1, 3); } TEMPLATE static u32 FASTCALL OP_SBC_LSR_REG(const u32 i) { LSR_REG; OP_SBC(2, 4); } TEMPLATE static u32 FASTCALL OP_SBC_ASR_IMM(const u32 i) { ASR_IMM; OP_SBC(1, 3); } TEMPLATE static u32 FASTCALL OP_SBC_ASR_REG(const u32 i) { ASR_REG; OP_SBC(2, 4); } TEMPLATE static u32 FASTCALL OP_SBC_ROR_IMM(const u32 i) { ROR_IMM; OP_SBC(1, 3); } TEMPLATE static u32 FASTCALL OP_SBC_ROR_REG(const u32 i) { ROR_REG; OP_SBC(2, 4); } TEMPLATE static u32 FASTCALL OP_SBC_IMM_VAL(const u32 i) { IMM_VALUE; OP_SBC(1, 3); } TEMPLATE static u32 FASTCALL OP_SBC_S_LSL_IMM(const u32 i) { u32 v = cpu->R[REG_POS(i,16)]; LSL_IMM; OP_SBCS(1, 3); } TEMPLATE static u32 FASTCALL OP_SBC_S_LSL_REG(const u32 i) { u32 v = cpu->R[REG_POS(i,16)]; LSL_REG; OP_SBCS(2, 4); } TEMPLATE static u32 FASTCALL OP_SBC_S_LSR_IMM(const u32 i) { u32 v = cpu->R[REG_POS(i,16)]; LSR_IMM; OP_SBCS(1, 3); } TEMPLATE static u32 FASTCALL OP_SBC_S_LSR_REG(const u32 i) { u32 v = cpu->R[REG_POS(i,16)]; LSR_REG; OP_SBCS(2, 4); } TEMPLATE static u32 FASTCALL OP_SBC_S_ASR_IMM(const u32 i) { u32 v = cpu->R[REG_POS(i,16)]; ASR_IMM; OP_SBCS(1, 3); } TEMPLATE static u32 FASTCALL OP_SBC_S_ASR_REG(const u32 i) { u32 v = cpu->R[REG_POS(i,16)]; ASR_REG; OP_SBCS(2, 4); } TEMPLATE static u32 FASTCALL OP_SBC_S_ROR_IMM(const u32 i) { u32 v = cpu->R[REG_POS(i,16)]; ROR_IMM; OP_SBCS(1, 3); } TEMPLATE static u32 FASTCALL OP_SBC_S_ROR_REG(const u32 i) { u32 v = cpu->R[REG_POS(i,16)]; ROR_REG; OP_SBCS(2, 4); } TEMPLATE static u32 FASTCALL OP_SBC_S_IMM_VAL(const u32 i) { u32 v = cpu->R[REG_POS(i,16)]; IMM_VALUE; OP_SBCS(1, 3); } //----------------------------------------------------------------------------- // RSC / RSCS //----------------------------------------------------------------------------- #define OP_RSC(a, b) \ cpu->R[REG_POS(i,12)] = shift_op - cpu->R[REG_POS(i,16)] + cpu->CPSR.bits.C - 1; \ if(REG_POS(i,12)==15) \ { \ cpu->next_instruction = cpu->R[15]; \ return b; \ } \ return a; #define OP_RSCS(a, b) \ { \ if(REG_POS(i,12)==15) \ { \ cpu->R[REG_POS(i,12)] = shift_op - v - !cpu->CPSR.bits.C; \ Status_Reg SPSR = cpu->SPSR; \ armcpu_switchMode(cpu, SPSR.bits.mode); \ cpu->CPSR=SPSR; \ cpu->changeCPSR(); \ cpu->R[15] &= (0xFFFFFFFC|(((u32)cpu->CPSR.bits.T)<<1)); \ cpu->next_instruction = cpu->R[15]; \ return b; \ } \ if (!cpu->CPSR.bits.C) \ { \ cpu->R[REG_POS(i,12)] = shift_op - v - 1; \ cpu->CPSR.bits.C = shift_op > v; \ } \ else \ { \ cpu->R[REG_POS(i,12)] = shift_op - v; \ cpu->CPSR.bits.C = shift_op >= v; \ } \ 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.V = BIT31((shift_op ^ v) & (shift_op ^ cpu->R[REG_POS(i, 12)])); \ return a; \ } TEMPLATE static u32 FASTCALL OP_RSC_LSL_IMM(const u32 i) { LSL_IMM; OP_RSC(1, 3); } TEMPLATE static u32 FASTCALL OP_RSC_LSL_REG(const u32 i) { LSL_REG; OP_RSC(2, 4); } TEMPLATE static u32 FASTCALL OP_RSC_LSR_IMM(const u32 i) { LSR_IMM; OP_RSC(1, 3); } TEMPLATE static u32 FASTCALL OP_RSC_LSR_REG(const u32 i) { LSR_REG; OP_RSC(2, 4); } TEMPLATE static u32 FASTCALL OP_RSC_ASR_IMM(const u32 i) { ASR_IMM; OP_RSC(1, 3); } TEMPLATE static u32 FASTCALL OP_RSC_ASR_REG(const u32 i) { ASR_REG; OP_RSC(2, 4); } TEMPLATE static u32 FASTCALL OP_RSC_ROR_IMM(const u32 i) { ROR_IMM; OP_RSC(1, 3); } TEMPLATE static u32 FASTCALL OP_RSC_ROR_REG(const u32 i) { ROR_REG; OP_RSC(2, 4); } TEMPLATE static u32 FASTCALL OP_RSC_IMM_VAL(const u32 i) { IMM_VALUE; OP_RSC(1, 3); } TEMPLATE static u32 FASTCALL OP_RSC_S_LSL_IMM(const u32 i) { u32 v = cpu->R[REG_POS(i,16)]; LSL_IMM; OP_RSCS(1,3); } TEMPLATE static u32 FASTCALL OP_RSC_S_LSL_REG(const u32 i) { u32 v = cpu->R[REG_POS(i,16)]; LSL_REG; OP_RSCS(2,4); } TEMPLATE static u32 FASTCALL OP_RSC_S_LSR_IMM(const u32 i) { u32 v = cpu->R[REG_POS(i,16)]; LSR_IMM; OP_RSCS(1,3); } TEMPLATE static u32 FASTCALL OP_RSC_S_LSR_REG(const u32 i) { u32 v = cpu->R[REG_POS(i,16)]; LSR_REG; OP_RSCS(2,4); } TEMPLATE static u32 FASTCALL OP_RSC_S_ASR_IMM(const u32 i) { u32 v = cpu->R[REG_POS(i,16)]; ASR_IMM; OP_RSCS(1,3); } TEMPLATE static u32 FASTCALL OP_RSC_S_ASR_REG(const u32 i) { u32 v = cpu->R[REG_POS(i,16)]; ASR_REG; OP_RSCS(2,4); } TEMPLATE static u32 FASTCALL OP_RSC_S_ROR_IMM(const u32 i) { u32 v = cpu->R[REG_POS(i,16)]; ROR_IMM; OP_RSCS(1,3); } TEMPLATE static u32 FASTCALL OP_RSC_S_ROR_REG(const u32 i) { u32 v = cpu->R[REG_POS(i,16)]; ROR_REG; OP_RSCS(2,4); } TEMPLATE static u32 FASTCALL OP_RSC_S_IMM_VAL(const u32 i) { u32 v = cpu->R[REG_POS(i,16)]; IMM_VALUE; OP_RSCS(1,3); } //----------------------------------------------------------------------------- // TST //----------------------------------------------------------------------------- #define OP_TST(a) \ { \ u32 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; \ } TEMPLATE static u32 FASTCALL OP_TST_LSL_IMM(const u32 i) { S_LSL_IMM; OP_TST(1); } TEMPLATE static u32 FASTCALL OP_TST_LSL_REG(const u32 i) { S_LSL_REG; OP_TST(2); } TEMPLATE static u32 FASTCALL OP_TST_LSR_IMM(const u32 i) { S_LSR_IMM; OP_TST(1); } TEMPLATE static u32 FASTCALL OP_TST_LSR_REG(const u32 i) { S_LSR_REG; OP_TST(2); } TEMPLATE static u32 FASTCALL OP_TST_ASR_IMM(const u32 i) { S_ASR_IMM; OP_TST(1); } TEMPLATE static u32 FASTCALL OP_TST_ASR_REG(const u32 i) { S_ASR_REG; OP_TST(2); } TEMPLATE static u32 FASTCALL OP_TST_ROR_IMM(const u32 i) { S_ROR_IMM; OP_TST(1); } TEMPLATE static u32 FASTCALL OP_TST_ROR_REG(const u32 i) { S_ROR_REG; OP_TST(2); } TEMPLATE static u32 FASTCALL OP_TST_IMM_VAL(const u32 i) { 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; \ } TEMPLATE static u32 FASTCALL OP_TEQ_LSL_IMM(const u32 i) { S_LSL_IMM; OP_TEQ(1); } TEMPLATE static u32 FASTCALL OP_TEQ_LSL_REG(const u32 i) { S_LSL_REG; OP_TEQ(2); } TEMPLATE static u32 FASTCALL OP_TEQ_LSR_IMM(const u32 i) { S_LSR_IMM; OP_TEQ(1); } TEMPLATE static u32 FASTCALL OP_TEQ_LSR_REG(const u32 i) { S_LSR_REG; OP_TEQ(2); } TEMPLATE static u32 FASTCALL OP_TEQ_ASR_IMM(const u32 i) { S_ASR_IMM; OP_TEQ(1); } TEMPLATE static u32 FASTCALL OP_TEQ_ASR_REG(const u32 i) { S_ASR_REG; OP_TEQ(2); } TEMPLATE static u32 FASTCALL OP_TEQ_ROR_IMM(const u32 i) { S_ROR_IMM; OP_TEQ(1); } TEMPLATE static u32 FASTCALL OP_TEQ_ROR_REG(const u32 i) { S_ROR_REG; OP_TEQ(2); } TEMPLATE static u32 FASTCALL OP_TEQ_IMM_VAL(const u32 i) { 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 = !BorrowFrom(cpu->R[REG_POS(i,16)], shift_op); \ cpu->CPSR.bits.V = OverflowFromSUB(tmp, cpu->R[REG_POS(i,16)], shift_op); \ return a; \ } TEMPLATE static u32 FASTCALL OP_CMP_LSL_IMM(const u32 i) { LSL_IMM; OP_CMP(1); } TEMPLATE static u32 FASTCALL OP_CMP_LSL_REG(const u32 i) { LSL_REG; OP_CMP(2); } TEMPLATE static u32 FASTCALL OP_CMP_LSR_IMM(const u32 i) { LSR_IMM; OP_CMP(1); } TEMPLATE static u32 FASTCALL OP_CMP_LSR_REG(const u32 i) { LSR_REG; OP_CMP(2); } TEMPLATE static u32 FASTCALL OP_CMP_ASR_IMM(const u32 i) { ASR_IMM; OP_CMP(1); } TEMPLATE static u32 FASTCALL OP_CMP_ASR_REG(const u32 i) { ASR_REG; OP_CMP(2); } TEMPLATE static u32 FASTCALL OP_CMP_ROR_IMM(const u32 i) { ROR_IMM; OP_CMP(1); } TEMPLATE static u32 FASTCALL OP_CMP_ROR_REG(const u32 i) { ROR_REG; OP_CMP(2); } TEMPLATE static u32 FASTCALL OP_CMP_IMM_VAL(const u32 i) { 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 = CarryFrom(cpu->R[REG_POS(i,16)], shift_op); \ cpu->CPSR.bits.V = OverflowFromADD(tmp, cpu->R[REG_POS(i,16)], shift_op); \ return a; \ } TEMPLATE static u32 FASTCALL OP_CMN_LSL_IMM(const u32 i) { LSL_IMM; OP_CMN(1); } TEMPLATE static u32 FASTCALL OP_CMN_LSL_REG(const u32 i) { LSL_REG; OP_CMN(2); } TEMPLATE static u32 FASTCALL OP_CMN_LSR_IMM(const u32 i) { LSR_IMM; OP_CMN(1); } TEMPLATE static u32 FASTCALL OP_CMN_LSR_REG(const u32 i) { LSR_REG; OP_CMN(2); } TEMPLATE static u32 FASTCALL OP_CMN_ASR_IMM(const u32 i) { ASR_IMM; OP_CMN(1); } TEMPLATE static u32 FASTCALL OP_CMN_ASR_REG(const u32 i) { ASR_REG; OP_CMN(2); } TEMPLATE static u32 FASTCALL OP_CMN_ROR_IMM(const u32 i) { ROR_IMM; OP_CMN(1); } TEMPLATE static u32 FASTCALL OP_CMN_ROR_REG(const u32 i) { ROR_REG; OP_CMN(2); } TEMPLATE static u32 FASTCALL OP_CMN_IMM_VAL(const u32 i) { IMM_VALUE; OP_CMN(1); } //----------------------------------------------------------------------------- // ORR / ORRS //----------------------------------------------------------------------------- #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; #define OP_ORRS(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->changeCPSR(); \ cpu->R[15] &= (0xFFFFFFFC|(((u32)cpu->CPSR.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; \ } TEMPLATE static u32 FASTCALL OP_ORR_LSL_IMM(const u32 i) { LSL_IMM; OP_ORR(1, 3); } TEMPLATE static u32 FASTCALL OP_ORR_LSL_REG(const u32 i) { LSL_REG; OP_ORR(2, 4); } TEMPLATE static u32 FASTCALL OP_ORR_LSR_IMM(const u32 i) { LSR_IMM; OP_ORR(1, 3); } TEMPLATE static u32 FASTCALL OP_ORR_LSR_REG(const u32 i) { LSR_REG; OP_ORR(2, 4); } TEMPLATE static u32 FASTCALL OP_ORR_ASR_IMM(const u32 i) { ASR_IMM; OP_ORR(1, 3); } TEMPLATE static u32 FASTCALL OP_ORR_ASR_REG(const u32 i) { ASR_REG; OP_ORR(2, 4); } TEMPLATE static u32 FASTCALL OP_ORR_ROR_IMM(const u32 i) { ROR_IMM; OP_ORR(1, 3); } TEMPLATE static u32 FASTCALL OP_ORR_ROR_REG(const u32 i) { ROR_REG; OP_ORR(2, 4); } TEMPLATE static u32 FASTCALL OP_ORR_IMM_VAL(const u32 i) { IMM_VALUE; OP_ORR(1, 3); } TEMPLATE static u32 FASTCALL OP_ORR_S_LSL_IMM(const u32 i) { S_LSL_IMM; OP_ORRS(1,3); } TEMPLATE static u32 FASTCALL OP_ORR_S_LSL_REG(const u32 i) { S_LSL_REG; OP_ORRS(2,4); } TEMPLATE static u32 FASTCALL OP_ORR_S_LSR_IMM(const u32 i) { S_LSR_IMM; OP_ORRS(1,3); } TEMPLATE static u32 FASTCALL OP_ORR_S_LSR_REG(const u32 i) { S_LSR_REG; OP_ORRS(2,4); } TEMPLATE static u32 FASTCALL OP_ORR_S_ASR_IMM(const u32 i) { S_ASR_IMM; OP_ORRS(1,3); } TEMPLATE static u32 FASTCALL OP_ORR_S_ASR_REG(const u32 i) { S_ASR_REG; OP_ORRS(2,4); } TEMPLATE static u32 FASTCALL OP_ORR_S_ROR_IMM(const u32 i) { S_ROR_IMM; OP_ORRS(1,3); } TEMPLATE static u32 FASTCALL OP_ORR_S_ROR_REG(const u32 i) { S_ROR_REG; OP_ORRS(2,4); } TEMPLATE static u32 FASTCALL OP_ORR_S_IMM_VAL(const u32 i) { S_IMM_VALUE; OP_ORRS(1,3); } //----------------------------------------------------------------------------- // MOV / MOVS //----------------------------------------------------------------------------- #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_MOVS(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->changeCPSR(); \ cpu->R[15] &= (0xFFFFFFFC|(((u32)cpu->CPSR.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; TEMPLATE static u32 FASTCALL OP_MOV_LSL_IMM(const u32 i) { if (i == 0xE1A00000) // nop: MOV R0, R0 return 1; LSL_IMM; OP_MOV(1,3); } TEMPLATE static u32 FASTCALL OP_MOV_LSL_REG(const u32 i) { LSL_REG; if (REG_POS(i,0) == 15) shift_op += 4; OP_MOV(2,4); } TEMPLATE static u32 FASTCALL OP_MOV_LSR_IMM(const u32 i) { LSR_IMM; OP_MOV(1,3); } TEMPLATE static u32 FASTCALL OP_MOV_LSR_REG(const u32 i) { LSR_REG; if (REG_POS(i,0) == 15) shift_op += 4; OP_MOV(2,4); } TEMPLATE static u32 FASTCALL OP_MOV_ASR_IMM(const u32 i) { ASR_IMM; OP_MOV(1,3); } TEMPLATE static u32 FASTCALL OP_MOV_ASR_REG(const u32 i) { ASR_REG; OP_MOV(2,4); } TEMPLATE static u32 FASTCALL OP_MOV_ROR_IMM(const u32 i) { ROR_IMM; OP_MOV(1,3); } TEMPLATE static u32 FASTCALL OP_MOV_ROR_REG(const u32 i) { ROR_REG; OP_MOV(2,4); } TEMPLATE static u32 FASTCALL OP_MOV_IMM_VAL(const u32 i) { IMM_VALUE; OP_MOV(1,3); } TEMPLATE static u32 FASTCALL OP_MOV_S_LSL_IMM(const u32 i) { S_LSL_IMM; OP_MOVS(1,3); } TEMPLATE static u32 FASTCALL OP_MOV_S_LSL_REG(const u32 i) { S_LSL_REG; if (REG_POS(i,0) == 15) shift_op += 4; OP_MOVS(2,4); } TEMPLATE static u32 FASTCALL OP_MOV_S_LSR_IMM(const u32 i) { S_LSR_IMM; OP_MOVS(1,3); } TEMPLATE static u32 FASTCALL OP_MOV_S_LSR_REG(const u32 i) { S_LSR_REG; if (REG_POS(i,0) == 15) shift_op += 4; OP_MOVS(2,4); } TEMPLATE static u32 FASTCALL OP_MOV_S_ASR_IMM(const u32 i) { S_ASR_IMM; OP_MOVS(1,3); } TEMPLATE static u32 FASTCALL OP_MOV_S_ASR_REG(const u32 i) { S_ASR_REG; OP_MOVS(2,4); } TEMPLATE static u32 FASTCALL OP_MOV_S_ROR_IMM(const u32 i) { S_ROR_IMM; OP_MOVS(1,3); } TEMPLATE static u32 FASTCALL OP_MOV_S_ROR_REG(const u32 i) { S_ROR_REG; OP_MOVS(2,4); } TEMPLATE static u32 FASTCALL OP_MOV_S_IMM_VAL(const u32 i) { S_IMM_VALUE; OP_MOVS(1,3); } //----------------------------------------------------------------------------- // BIC / BICS //----------------------------------------------------------------------------- #define OP_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 OP_BICS(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->changeCPSR(); \ cpu->R[15] &= (0xFFFFFFFC|(((u32)cpu->CPSR.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; TEMPLATE static u32 FASTCALL OP_BIC_LSL_IMM(const u32 i) { LSL_IMM; OP_BIC(1,3); } TEMPLATE static u32 FASTCALL OP_BIC_LSL_REG(const u32 i) { LSL_REG; OP_BIC(2,4); } TEMPLATE static u32 FASTCALL OP_BIC_LSR_IMM(const u32 i) { LSR_IMM; OP_BIC(1,3); } TEMPLATE static u32 FASTCALL OP_BIC_LSR_REG(const u32 i) { LSR_REG; OP_BIC(2,4); } TEMPLATE static u32 FASTCALL OP_BIC_ASR_IMM(const u32 i) { ASR_IMM; OP_BIC(1,3); } TEMPLATE static u32 FASTCALL OP_BIC_ASR_REG(const u32 i) { ASR_REG; OP_BIC(2,4); } TEMPLATE static u32 FASTCALL OP_BIC_ROR_IMM(const u32 i) { ROR_IMM; OP_BIC(1,3); } TEMPLATE static u32 FASTCALL OP_BIC_ROR_REG(const u32 i) { ROR_REG; OP_BIC(2,4); } TEMPLATE static u32 FASTCALL OP_BIC_IMM_VAL(const u32 i) { IMM_VALUE; OP_BIC(1,3); } TEMPLATE static u32 FASTCALL OP_BIC_S_LSL_IMM(const u32 i) { S_LSL_IMM; OP_BICS(1,3); } TEMPLATE static u32 FASTCALL OP_BIC_S_LSL_REG(const u32 i) { S_LSL_REG; OP_BICS(2,4); } TEMPLATE static u32 FASTCALL OP_BIC_S_LSR_IMM(const u32 i) { S_LSR_IMM; OP_BICS(1,3); } TEMPLATE static u32 FASTCALL OP_BIC_S_LSR_REG(const u32 i) { S_LSR_REG; OP_BICS(2,4); } TEMPLATE static u32 FASTCALL OP_BIC_S_ASR_IMM(const u32 i) { S_ASR_IMM; OP_BICS(1,3); } TEMPLATE static u32 FASTCALL OP_BIC_S_ASR_REG(const u32 i) { S_ASR_REG; OP_BICS(2,4); } TEMPLATE static u32 FASTCALL OP_BIC_S_ROR_IMM(const u32 i) { S_ROR_IMM; OP_BICS(1,3); } TEMPLATE static u32 FASTCALL OP_BIC_S_ROR_REG(const u32 i) { S_ROR_REG; OP_BICS(2,4); } TEMPLATE static u32 FASTCALL OP_BIC_S_IMM_VAL(const u32 i) { S_IMM_VALUE; OP_BICS(1,3); } //----------------------------------------------------------------------------- // MVN / MVNS //----------------------------------------------------------------------------- #define OP_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 OP_MVNS(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->changeCPSR(); \ cpu->R[15] &= (0xFFFFFFFC|(((u32)cpu->CPSR.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; TEMPLATE static u32 FASTCALL OP_MVN_LSL_IMM(const u32 i) { LSL_IMM; OP_MVN(1,3); } TEMPLATE static u32 FASTCALL OP_MVN_LSL_REG(const u32 i) { LSL_REG; OP_MVN(2,4); } TEMPLATE static u32 FASTCALL OP_MVN_LSR_IMM(const u32 i) { LSR_IMM; OP_MVN(1,3); } TEMPLATE static u32 FASTCALL OP_MVN_LSR_REG(const u32 i) { LSR_REG; OP_MVN(2,4); } TEMPLATE static u32 FASTCALL OP_MVN_ASR_IMM(const u32 i) { ASR_IMM; OP_MVN(1,3); } TEMPLATE static u32 FASTCALL OP_MVN_ASR_REG(const u32 i) { ASR_REG; OP_MVN(2,4); } TEMPLATE static u32 FASTCALL OP_MVN_ROR_IMM(const u32 i) { ROR_IMM; OP_MVN(1,3); } TEMPLATE static u32 FASTCALL OP_MVN_ROR_REG(const u32 i) { ROR_REG; OP_MVN(2,4); } TEMPLATE static u32 FASTCALL OP_MVN_IMM_VAL(const u32 i) { IMM_VALUE; OP_MVN(1,3); } TEMPLATE static u32 FASTCALL OP_MVN_S_LSL_IMM(const u32 i) { S_LSL_IMM; OP_MVNS(1,3); } TEMPLATE static u32 FASTCALL OP_MVN_S_LSL_REG(const u32 i) { S_LSL_REG; OP_MVNS(2,4); } TEMPLATE static u32 FASTCALL OP_MVN_S_LSR_IMM(const u32 i) { S_LSR_IMM; OP_MVNS(1,3); } TEMPLATE static u32 FASTCALL OP_MVN_S_LSR_REG(const u32 i) { S_LSR_REG; OP_MVNS(2,4); } TEMPLATE static u32 FASTCALL OP_MVN_S_ASR_IMM(const u32 i) { S_ASR_IMM; OP_MVNS(1,3); } TEMPLATE static u32 FASTCALL OP_MVN_S_ASR_REG(const u32 i) { S_ASR_REG; OP_MVNS(2,4); } TEMPLATE static u32 FASTCALL OP_MVN_S_ROR_IMM(const u32 i) { S_ROR_IMM; OP_MVNS(1,3); } TEMPLATE static u32 FASTCALL OP_MVN_S_ROR_REG(const u32 i) { S_ROR_REG; OP_MVNS(2,4); } TEMPLATE static u32 FASTCALL OP_MVN_S_IMM_VAL(const u32 i) { S_IMM_VALUE; OP_MVNS(1,3); } //----------------------------------------------------------------------------- // MUL / MULS / MLA / MLAS //----------------------------------------------------------------------------- #define MUL_Mxx_END(c) \ v >>= 8; \ if((v==0)||(v==0xFFFFFF)) \ return c+1; \ v >>= 8; \ if((v==0)||(v==0xFFFF)) \ return c+2; \ v >>= 8; \ if((v==0)||(v==0xFF)) \ return c+3; \ return c+4; \ TEMPLATE static u32 FASTCALL OP_MUL(const u32 i) { u32 v = cpu->R[REG_POS(i,8)]; cpu->R[REG_POS(i,16)] = cpu->R[REG_POS(i,0)] * v; MUL_Mxx_END(1); } TEMPLATE static u32 FASTCALL OP_MLA(const u32 i) { u32 v = cpu->R[REG_POS(i,8)]; cpu->R[REG_POS(i,16)] = cpu->R[REG_POS(i,0)] * v + cpu->R[REG_POS(i,12)]; MUL_Mxx_END(2); } TEMPLATE static u32 FASTCALL OP_MUL_S(const u32 i) { u32 v = cpu->R[REG_POS(i,8)]; cpu->R[REG_POS(i,16)] = cpu->R[REG_POS(i,0)] * v; cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,16)]); cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,16)]==0); MUL_Mxx_END(1); } TEMPLATE static u32 FASTCALL OP_MLA_S(const u32 i) { u32 v = cpu->R[REG_POS(i,8)]; cpu->R[REG_POS(i,16)] = cpu->R[REG_POS(i,0)] * 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); MUL_Mxx_END(2); } //----------------------------------------------------------------------------- // UMULL / UMULLS / UMLAL / UMLALS //----------------------------------------------------------------------------- #define MUL_UMxxL_END(c) \ v >>= 8; \ if(v==0) \ return c+1; \ v >>= 8; \ if(v==0) \ return c+2; \ v >>= 8; \ if(v==0) \ return c+3; \ return c+4; \ TEMPLATE static u32 FASTCALL OP_UMULL(const u32 i) { u32 v = cpu->R[REG_POS(i,8)]; u64 res = (u64)cpu->R[REG_POS(i,0)] * (u64)v; cpu->R[REG_POS(i,12)] = (u32)res; cpu->R[REG_POS(i,16)] = (u32)(res>>32); MUL_UMxxL_END(2); } TEMPLATE static u32 FASTCALL OP_UMLAL(const u32 i) { u32 v = cpu->R[REG_POS(i,8)]; u64 res = (u64)cpu->R[REG_POS(i,0)] * (u64)v; // RdLo = (Rm * Rs)[31:0] + RdLo /* Unsigned multiplication */ // RdHi = (Rm * Rs)[63:32] + RdHi + CarryFrom((Rm * Rs)[31:0] + RdLo) u32 tmp = (u32)res; // low cpu->R[REG_POS(i,16)] = (u32)(res>>32) + cpu->R[REG_POS(i,16)] + CarryFrom(tmp, cpu->R[REG_POS(i,12)]); cpu->R[REG_POS(i,12)] += tmp; MUL_UMxxL_END(3); } TEMPLATE static u32 FASTCALL OP_UMULL_S(const u32 i) { u32 v = cpu->R[REG_POS(i,8)]; u64 res = ((u64)cpu->R[REG_POS(i,0)] * (u64)v); 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); MUL_UMxxL_END(2); } TEMPLATE static u32 FASTCALL OP_UMLAL_S(const u32 i) { u32 v = cpu->R[REG_POS(i,8)]; u64 res = (u64)cpu->R[REG_POS(i,0)] * (u64)v; // RdLo = (Rm * Rs)[31:0] + RdLo /* Unsigned multiplication */ // RdHi = (Rm * Rs)[63:32] + RdHi + CarryFrom((Rm * Rs)[31:0] + RdLo) u32 tmp = (u32)res; // low cpu->R[REG_POS(i,16)] = (u32)(res>>32) + cpu->R[REG_POS(i,16)] + CarryFrom(tmp, cpu->R[REG_POS(i,12)]); cpu->R[REG_POS(i,12)] += tmp; 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); MUL_UMxxL_END(3); } //----------------------------------------------------------------------------- // SMULL / SMULLS / SMLAL / SMLALS //----------------------------------------------------------------------------- #define MUL_SMxxL_END(c) \ v &= 0xFFFFFFFF; \ v >>= 8; \ if((v==0)||(v==0xFFFFFF)) \ return c+1; \ v >>= 8; \ if((v==0)||(v==0xFFFF)) \ return c+2; \ v >>= 8; \ if((v==0)||(v==0xFF)) \ return c+3; \ return c+4; \ TEMPLATE static u32 FASTCALL OP_SMULL(const u32 i) { s64 v = (s32)cpu->R[REG_POS(i,8)]; s64 res = v * (s64)(s32)cpu->R[REG_POS(i,0)]; cpu->R[REG_POS(i,12)] = (u32)res; cpu->R[REG_POS(i,16)] = (u32)(res>>32); MUL_SMxxL_END(2); } TEMPLATE static u32 FASTCALL OP_SMLAL(const u32 i) { s64 v = (s32)cpu->R[REG_POS(i,8)]; s64 res = v * (s64)(s32)cpu->R[REG_POS(i,0)]; //LOG("%08X * %08X + %08X%08X\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)]); u32 tmp = (u32)res; cpu->R[REG_POS(i,16)] = (u32)(res>>32) + cpu->R[REG_POS(i,16)] + CarryFrom(tmp, cpu->R[REG_POS(i,12)]); cpu->R[REG_POS(i,12)] += tmp; //LOG("= %08X%08X %08X%08X\n", cpu->R[REG_POS(i,16)], cpu->R[REG_POS(i,12)], res); MUL_SMxxL_END(3); } TEMPLATE static u32 FASTCALL OP_SMULL_S(const u32 i) { s64 v = (s32)cpu->R[REG_POS(i,8)]; s64 res = v * (s64)(s32)cpu->R[REG_POS(i,0)]; 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); MUL_SMxxL_END(2); } TEMPLATE static u32 FASTCALL OP_SMLAL_S(const u32 i) { s64 v = (s32)cpu->R[REG_POS(i,8)]; s64 res = v * (s64)(s32)cpu->R[REG_POS(i,0)]; u32 tmp = (u32)res; cpu->R[REG_POS(i,16)] = (u32)(res>>32) + cpu->R[REG_POS(i,16)] + CarryFrom(tmp, cpu->R[REG_POS(i,12)]); cpu->R[REG_POS(i,12)] += tmp; 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); MUL_SMxxL_END(3); } //----------------------------------------------------------------------------- // SWP / SWPB //----------------------------------------------------------------------------- TEMPLATE static u32 FASTCALL OP_SWP(const u32 i) { u32 adr = cpu->R[REG_POS(i,16)]; u32 tmp = ROR(READ32(cpu->mem_if->data, adr), (adr & 3)<<3); WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,0)]); cpu->R[REG_POS(i,12)] = tmp; u32 c = MMU_memAccessCycles(adr); c += MMU_memAccessCycles(adr); return MMU_aluMemCycles(4, c); } TEMPLATE static u32 FASTCALL OP_SWPB(const u32 i) { 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; u32 c = MMU_memAccessCycles(adr); c += MMU_memAccessCycles(adr); return MMU_aluMemCycles(4, c); } //----------------------------------------------------------------------------- // LDRH //----------------------------------------------------------------------------- TEMPLATE static u32 FASTCALL OP_LDRH_P_IMM_OFF(const u32 i) { u32 adr = cpu->R[REG_POS(i,16)] + IMM_OFF; cpu->R[REG_POS(i,12)] = (u32)READ16(cpu->mem_if->data, adr); return MMU_aluMemAccessCycles(3,adr); } TEMPLATE static u32 FASTCALL OP_LDRH_M_IMM_OFF(const u32 i) { u32 adr = cpu->R[REG_POS(i,16)] - IMM_OFF; cpu->R[REG_POS(i,12)] = (u32)READ16(cpu->mem_if->data, adr); return MMU_aluMemAccessCycles(3,adr); } TEMPLATE static u32 FASTCALL OP_LDRH_P_REG_OFF(const u32 i) { 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 MMU_aluMemAccessCycles(3,adr); } TEMPLATE static u32 FASTCALL OP_LDRH_M_REG_OFF(const u32 i) { 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 MMU_aluMemAccessCycles(3,adr); } TEMPLATE static u32 FASTCALL OP_LDRH_PRE_INDE_P_IMM_OFF(const u32 i) { 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 MMU_aluMemAccessCycles(3,adr); } TEMPLATE static u32 FASTCALL OP_LDRH_PRE_INDE_M_IMM_OFF(const u32 i) { 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 MMU_aluMemAccessCycles(3,adr); } TEMPLATE static u32 FASTCALL OP_LDRH_PRE_INDE_P_REG_OFF(const u32 i) { 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 MMU_aluMemAccessCycles(3,adr); } TEMPLATE static u32 FASTCALL OP_LDRH_PRE_INDE_M_REG_OFF(const u32 i) { 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 MMU_aluMemAccessCycles(3,adr); } TEMPLATE static u32 FASTCALL OP_LDRH_POS_INDE_P_IMM_OFF(const u32 i) { u32 adr = cpu->R[REG_POS(i,16)]; cpu->R[REG_POS(i,16)] += IMM_OFF; cpu->R[REG_POS(i,12)] = (u32)READ16(cpu->mem_if->data, adr); return MMU_aluMemAccessCycles(3,adr); } TEMPLATE static u32 FASTCALL OP_LDRH_POS_INDE_M_IMM_OFF(const u32 i) { u32 adr = cpu->R[REG_POS(i,16)]; cpu->R[REG_POS(i,16)] -= IMM_OFF; cpu->R[REG_POS(i,12)] = (u32)READ16(cpu->mem_if->data, adr); return MMU_aluMemAccessCycles(3,adr); } TEMPLATE static u32 FASTCALL OP_LDRH_POS_INDE_P_REG_OFF(const u32 i) { u32 adr = cpu->R[REG_POS(i,16)]; 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 MMU_aluMemAccessCycles(3,adr); } TEMPLATE static u32 FASTCALL OP_LDRH_POS_INDE_M_REG_OFF(const u32 i) { u32 adr = cpu->R[REG_POS(i,16)]; 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 MMU_aluMemAccessCycles(3,adr); } //----------------------------------------------------------------------------- // STRH //----------------------------------------------------------------------------- TEMPLATE static u32 FASTCALL OP_STRH_P_IMM_OFF(const u32 i) { u32 adr = cpu->R[REG_POS(i,16)] + IMM_OFF; WRITE16(cpu->mem_if->data, adr, (u16)cpu->R[REG_POS(i,12)]); return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static u32 FASTCALL OP_STRH_M_IMM_OFF(const u32 i) { u32 adr = cpu->R[REG_POS(i,16)] - IMM_OFF; WRITE16(cpu->mem_if->data, adr, (u16)cpu->R[REG_POS(i,12)]); return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static u32 FASTCALL OP_STRH_P_REG_OFF(const u32 i) { 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 MMU_aluMemAccessCycles(2,adr); } TEMPLATE static u32 FASTCALL OP_STRH_M_REG_OFF(const u32 i) { 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 MMU_aluMemAccessCycles(2,adr); } TEMPLATE static u32 FASTCALL OP_STRH_PRE_INDE_P_IMM_OFF(const u32 i) { 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 MMU_aluMemAccessCycles(2,adr); } TEMPLATE static u32 FASTCALL OP_STRH_PRE_INDE_M_IMM_OFF(const u32 i) { 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 MMU_aluMemAccessCycles(2,adr); } TEMPLATE static u32 FASTCALL OP_STRH_PRE_INDE_P_REG_OFF(const u32 i) { u32 adr = cpu->R[REG_POS(i,16)] + cpu->R[REG_POS(i,0)]; cpu->R[REG_POS(i,16)] = adr; WRITE16(cpu->mem_if->data, adr, (u16)cpu->R[REG_POS(i,12)]); return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static u32 FASTCALL OP_STRH_PRE_INDE_M_REG_OFF(const u32 i) { u32 adr = cpu->R[REG_POS(i,16)] - cpu->R[REG_POS(i,0)]; cpu->R[REG_POS(i,16)] = adr; WRITE16(cpu->mem_if->data, adr, (u16)cpu->R[REG_POS(i,12)]); return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static u32 FASTCALL OP_STRH_POS_INDE_P_IMM_OFF(const u32 i) { 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 MMU_aluMemAccessCycles(2,adr); } TEMPLATE static u32 FASTCALL OP_STRH_POS_INDE_M_IMM_OFF(const u32 i) { 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 MMU_aluMemAccessCycles(2,adr); } TEMPLATE static u32 FASTCALL OP_STRH_POS_INDE_P_REG_OFF(const u32 i) { 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 MMU_aluMemAccessCycles(2,adr); } TEMPLATE static u32 FASTCALL OP_STRH_POS_INDE_M_REG_OFF(const u32 i) { 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 MMU_aluMemAccessCycles(2,adr); } //----------------------------------------------------------------------------- // LDRSH //----------------------------------------------------------------------------- TEMPLATE static u32 FASTCALL OP_LDRSH_P_IMM_OFF(const u32 i) { 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 MMU_aluMemAccessCycles(3,adr); } TEMPLATE static u32 FASTCALL OP_LDRSH_M_IMM_OFF(const u32 i) { 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 MMU_aluMemAccessCycles(3,adr); } TEMPLATE static u32 FASTCALL OP_LDRSH_P_REG_OFF(const u32 i) { 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 MMU_aluMemAccessCycles(3,adr); } TEMPLATE static u32 FASTCALL OP_LDRSH_M_REG_OFF(const u32 i) { 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 MMU_aluMemAccessCycles(3,adr); } TEMPLATE static u32 FASTCALL OP_LDRSH_PRE_INDE_P_IMM_OFF(const u32 i) { u32 adr = cpu->R[REG_POS(i,16)] + IMM_OFF; cpu->R[REG_POS(i,16)] = adr; cpu->R[REG_POS(i,12)] = (s32)((s16)READ16(cpu->mem_if->data, adr)); return MMU_aluMemAccessCycles(3,adr); } TEMPLATE static u32 FASTCALL OP_LDRSH_PRE_INDE_M_IMM_OFF(const u32 i) { u32 adr = cpu->R[REG_POS(i,16)] - IMM_OFF; cpu->R[REG_POS(i,16)] = adr; cpu->R[REG_POS(i,12)] = (s32)((s16)READ16(cpu->mem_if->data, adr)); return MMU_aluMemAccessCycles(3,adr); } TEMPLATE static u32 FASTCALL OP_LDRSH_PRE_INDE_P_REG_OFF(const u32 i) { 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)] = (s32)((s16)READ16(cpu->mem_if->data, adr)); return MMU_aluMemAccessCycles(3,adr); } TEMPLATE static u32 FASTCALL OP_LDRSH_PRE_INDE_M_REG_OFF(const u32 i) { 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)] = (s32)((s16)READ16(cpu->mem_if->data, adr)); return MMU_aluMemAccessCycles(3,adr); } TEMPLATE static u32 FASTCALL OP_LDRSH_POS_INDE_P_IMM_OFF(const u32 i) { u32 adr = cpu->R[REG_POS(i,16)]; cpu->R[REG_POS(i,16)] += IMM_OFF; cpu->R[REG_POS(i,12)] = (s32)((s16)READ16(cpu->mem_if->data, adr)); return MMU_aluMemAccessCycles(3,adr); } TEMPLATE static u32 FASTCALL OP_LDRSH_POS_INDE_M_IMM_OFF(const u32 i) { u32 adr = cpu->R[REG_POS(i,16)]; cpu->R[REG_POS(i,16)] -= IMM_OFF; cpu->R[REG_POS(i,12)] = (s32)((s16)READ16(cpu->mem_if->data, adr)); return MMU_aluMemAccessCycles(3,adr); } TEMPLATE static u32 FASTCALL OP_LDRSH_POS_INDE_P_REG_OFF(const u32 i) { u32 adr = cpu->R[REG_POS(i,16)]; 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 MMU_aluMemAccessCycles(3,adr); } TEMPLATE static u32 FASTCALL OP_LDRSH_POS_INDE_M_REG_OFF(const u32 i) { u32 adr = cpu->R[REG_POS(i,16)]; 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 MMU_aluMemAccessCycles(3,adr); } //----------------------------------------------------------------------------- // LDRSB //----------------------------------------------------------------------------- TEMPLATE static u32 FASTCALL OP_LDRSB_P_IMM_OFF(const u32 i) { 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 MMU_aluMemAccessCycles(3,adr); } TEMPLATE static u32 FASTCALL OP_LDRSB_M_IMM_OFF(const u32 i) { 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 MMU_aluMemAccessCycles(3,adr); } TEMPLATE static u32 FASTCALL OP_LDRSB_P_REG_OFF(const u32 i) { 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 MMU_aluMemAccessCycles(3,adr); } TEMPLATE static u32 FASTCALL OP_LDRSB_M_REG_OFF(const u32 i) { 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 MMU_aluMemAccessCycles(3,adr); } TEMPLATE static u32 FASTCALL OP_LDRSB_PRE_INDE_P_IMM_OFF(const u32 i) { u32 adr = cpu->R[REG_POS(i,16)] + IMM_OFF; cpu->R[REG_POS(i,16)] = adr; cpu->R[REG_POS(i,12)] = (s32)((s8)READ8(cpu->mem_if->data, adr)); return MMU_aluMemAccessCycles(3,adr); } TEMPLATE static u32 FASTCALL OP_LDRSB_PRE_INDE_M_IMM_OFF(const u32 i) { u32 adr = cpu->R[REG_POS(i,16)] - IMM_OFF; cpu->R[REG_POS(i,16)] = adr; cpu->R[REG_POS(i,12)] = (s32)((s8)READ8(cpu->mem_if->data, adr)); return MMU_aluMemAccessCycles(3,adr); } TEMPLATE static u32 FASTCALL OP_LDRSB_PRE_INDE_P_REG_OFF(const u32 i) { 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)] = (s32)((s8)READ8(cpu->mem_if->data, adr)); return MMU_aluMemAccessCycles(3,adr); } TEMPLATE static u32 FASTCALL OP_LDRSB_PRE_INDE_M_REG_OFF(const u32 i) { 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)] = (s32)((s8)READ8(cpu->mem_if->data, adr)); return MMU_aluMemAccessCycles(3,adr); } TEMPLATE static u32 FASTCALL OP_LDRSB_POS_INDE_P_IMM_OFF(const u32 i) { u32 adr = cpu->R[REG_POS(i,16)]; cpu->R[REG_POS(i,16)] += IMM_OFF; cpu->R[REG_POS(i,12)] = (s32)((s8)READ8(cpu->mem_if->data, adr)); return MMU_aluMemAccessCycles(3,adr); } TEMPLATE static u32 FASTCALL OP_LDRSB_POS_INDE_M_IMM_OFF(const u32 i) { u32 adr = cpu->R[REG_POS(i,16)]; cpu->R[REG_POS(i,16)] -= IMM_OFF; cpu->R[REG_POS(i,12)] = (s32)((s8)READ8(cpu->mem_if->data, adr)); return MMU_aluMemAccessCycles(3,adr); } TEMPLATE static u32 FASTCALL OP_LDRSB_POS_INDE_P_REG_OFF(const u32 i) { u32 adr = cpu->R[REG_POS(i,16)]; 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 MMU_aluMemAccessCycles(3,adr); } TEMPLATE static u32 FASTCALL OP_LDRSB_POS_INDE_M_REG_OFF(const u32 i) { u32 adr = cpu->R[REG_POS(i,16)]; 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 MMU_aluMemAccessCycles(3,adr); } //----------------------------------------------------------------------------- // MRS / MSR //----------------------------------------------------------------------------- TEMPLATE static u32 FASTCALL OP_MRS_CPSR(const u32 i) { cpu->R[REG_POS(i,12)] = cpu->CPSR.val; return 1; } TEMPLATE static u32 FASTCALL OP_MRS_SPSR(const u32 i) { cpu->R[REG_POS(i,12)] = cpu->SPSR.val; return 1; } #define OP_MSR_CPSR_(operand) \ u32 byte_mask = (cpu->CPSR.bits.mode == USR)?(BIT19(i)?0xFF000000:0x00000000): \ (BIT16(i)?0x000000FF:0x00000000) | \ (BIT17(i)?0x0000FF00:0x00000000) | \ (BIT18(i)?0x00FF0000:0x00000000) | \ (BIT19(i)?0xFF000000:0x00000000); \ if(cpu->CPSR.bits.mode != USR && BIT16(i)) \ { armcpu_switchMode(cpu, operand & 0x1F); } \ cpu->CPSR.val = (cpu->CPSR.val & ~byte_mask) | (operand & byte_mask); \ cpu->changeCPSR(); #define OP_MSR_SPSR_(operand) \ if(cpu->CPSR.bits.mode == USR || cpu->CPSR.bits.mode == SYS) return 1; \ u32 byte_mask = (BIT16(i)?0x000000FF:0x00000000) | \ (BIT17(i)?0x0000FF00:0x00000000) | \ (BIT18(i)?0x00FF0000:0x00000000) | \ (BIT19(i)?0xFF000000:0x00000000); \ cpu->SPSR.val = (cpu->SPSR.val & ~byte_mask) | (operand & byte_mask); \ cpu->changeCPSR(); //#define __NEW_MSR #ifdef __NEW_MSR #define v4T_UNALLOC_MASK 0x0FFFFF00 #define v4T_USER_MASK 0xF0000000 #define v4T_PRIV_MASK 0x0000000F #define v4T_STATE_MASK 0x00000020 #define v5TE_UNALLOC_MASK 0x07FFFF00 #define v5TE_USER_MASK 0xF8000000 #define v5TE_PRIV_MASK 0x0000000F #define v5TE_STATE_MASK 0x00000020 #endif TEMPLATE static u32 FASTCALL OP_MSR_CPSR(const u32 i) { u32 operand = cpu->R[REG_POS(i,0)]; #ifdef __NEW_MSR u32 mask = 0; u32 byte_mask = (BIT16(i)?0x000000FF:0x00000000) | (BIT17(i)?0x0000FF00:0x00000000) | (BIT18(i)?0x00FF0000:0x00000000) | (BIT19(i)?0xFF000000:0x00000000); const u32 unallocMask = PROCNUM?v4T_UNALLOC_MASK: v5TE_UNALLOC_MASK; const u32 userMask = PROCNUM?v4T_USER_MASK : v5TE_USER_MASK; const u32 privMask = PROCNUM?v4T_PRIV_MASK : v5TE_PRIV_MASK; const u32 stateMask = PROCNUM?v4T_STATE_MASK : v5TE_STATE_MASK; if ((operand & unallocMask) != 0) printf("ARM%c: MSR_CPSR_REG UNPREDICTABLE UNALLOC (operand %08X)\n", PROCNUM?'7':'9', operand); if (cpu->CPSR.bits.mode != USR) // Privileged mode { if (BIT16(i)) armcpu_switchMode(cpu, operand & 0x1F); if ((operand & stateMask) != 0) printf("ARM%c: MSR_CPSR_REG UNPREDICTABLE STATE (operand %08X)\n", PROCNUM?'7':'9', operand); else mask = byte_mask & (userMask | privMask); } else mask = byte_mask & userMask; u32 new_val = ((cpu->CPSR.val & (~mask)) | (operand & mask)); cpu->CPSR.val = ((cpu->CPSR.val & (~mask)) | (operand & mask)); cpu->changeCPSR(); #else OP_MSR_CPSR_(operand); #endif return 1; } TEMPLATE static u32 FASTCALL OP_MSR_SPSR(const u32 i) { //printf("OP_MSR_SPSR\n"); u32 operand = cpu->R[REG_POS(i,0)]; OP_MSR_SPSR_(operand); return 1; } TEMPLATE static u32 FASTCALL OP_MSR_CPSR_IMM_VAL(const u32 i) { //printf("OP_MSR_CPSR_IMM_VAL\n"); IMM_VALUE; OP_MSR_CPSR_(shift_op); return 1; } TEMPLATE static u32 FASTCALL OP_MSR_SPSR_IMM_VAL(const u32 i) { //printf("OP_MSR_SPSR_IMM_VAL\n"); IMM_VALUE; OP_MSR_SPSR_(shift_op); return 1; } //----------------------------------------------------------------------------- // Branch //----------------------------------------------------------------------------- TEMPLATE static u32 FASTCALL OP_BX(const u32 i) { u32 tmp = cpu->R[REG_POS(i, 0)]; if (REG_POS(i, 0) == 15) { //printf("ARM%c: BX using PC as operand\n", PROCNUM?'7':'9'); //emu_halt(); } cpu->CPSR.bits.T = BIT0(tmp); cpu->R[15] = tmp & (0xFFFFFFFC|(cpu->CPSR.bits.T<<1)); cpu->next_instruction = cpu->R[15]; return 3; } TEMPLATE static u32 FASTCALL OP_BLX_REG(const u32 i) { u32 tmp = cpu->R[REG_POS(i, 0)]; cpu->R[14] = cpu->next_instruction; cpu->CPSR.bits.T = BIT0(tmp); cpu->R[15] = tmp & (0xFFFFFFFC|(cpu->CPSR.bits.T<<1)); cpu->next_instruction = cpu->R[15]; return 3; } #define SIGNEXTEND_24(i) (((s32)i<<8)>>8) TEMPLATE static u32 FASTCALL OP_B(const u32 i) { #ifdef DEBUG static const u32 mov_r12_r12 = 0xE1A0C00C; const u32 last = _MMU_read32(cpu->instruct_adr-4); if(last == mov_r12_r12) { const u32 next = _MMU_read16(cpu->instruct_adr+4); if(next == 0x6464) NocashMessage(cpu, 8); } #endif u32 off = SIGNEXTEND_24(i); if(CONDITION(i)==0xF) { cpu->R[14] = cpu->next_instruction; cpu->CPSR.bits.T = 1; } cpu->R[15] += (off<<2); cpu->R[15] &= (0xFFFFFFFC|(cpu->CPSR.bits.T<<1)); cpu->next_instruction = cpu->R[15]; return 3; } TEMPLATE static u32 FASTCALL OP_BL(const u32 i) { u32 off = SIGNEXTEND_24(i); if(CONDITION(i)==0xF) { cpu->CPSR.bits.T = 1; cpu->R[15] += 2; } cpu->R[14] = cpu->next_instruction; cpu->R[15] += (off<<2); cpu->R[15] &= (0xFFFFFFFC|(cpu->CPSR.bits.T<<1)); cpu->next_instruction = cpu->R[15]; return 3; } //----------------------------------------------------------------------------- // CLZ //----------------------------------------------------------------------------- const 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 }; TEMPLATE static u32 FASTCALL OP_CLZ(const u32 i) { 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 / QDADD / QSUB / QDSUB //----------------------------------------------------------------------------- TEMPLATE static u32 FASTCALL OP_QADD(const u32 i) { u32 res = cpu->R[REG_POS(i,16)]+cpu->R[REG_POS(i,0)]; //LOG("spe add\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; } TEMPLATE static u32 FASTCALL OP_QSUB(const u32 i) { u32 res = cpu->R[REG_POS(i,0)]-cpu->R[REG_POS(i,16)]; //LOG("spe add\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; } TEMPLATE static u32 FASTCALL OP_QDADD(const u32 i) { u32 mul = cpu->R[REG_POS(i,16)]<<1; u32 res; //LOG("spe add\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; } TEMPLATE static u32 FASTCALL OP_QDSUB(const u32 i) { u32 mul = cpu->R[REG_POS(i,16)]<<1; u32 res; //LOG("spe add\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) TEMPLATE static u32 FASTCALL OP_SMUL_B_B(const u32 i) { // checked //INFO("SMUL_B_B\n"); cpu->R[REG_POS(i,16)] = (u32)(LWORD(cpu->R[REG_POS(i,0)])* LWORD(cpu->R[REG_POS(i,8)])); return 2; } TEMPLATE static u32 FASTCALL OP_SMUL_B_T(const u32 i) { //INFO("SMUL_B_T\n"); cpu->R[REG_POS(i,16)] = (u32)(LWORD(cpu->R[REG_POS(i,0)])* HWORD(cpu->R[REG_POS(i,8)])); return 2; } TEMPLATE static u32 FASTCALL OP_SMUL_T_B(const u32 i) { //INFO("SMUL_T_B\n"); cpu->R[REG_POS(i,16)] = (u32)(HWORD(cpu->R[REG_POS(i,0)])* LWORD(cpu->R[REG_POS(i,8)])); return 2; } TEMPLATE static u32 FASTCALL OP_SMUL_T_T(const u32 i) { //INFO("SMUL_T_T\n"); cpu->R[REG_POS(i,16)] = (u32)(HWORD(cpu->R[REG_POS(i,0)])* HWORD(cpu->R[REG_POS(i,8)])); return 2; } //----------------------------------------------------------------------------- // SMLA //----------------------------------------------------------------------------- TEMPLATE static u32 FASTCALL OP_SMLA_B_B(const u32 i) { u32 tmp = (u32)((s16)cpu->R[REG_POS(i,0)]* (s16)cpu->R[REG_POS(i,8)]); cpu->R[REG_POS(i,16)] = tmp + cpu->R[REG_POS(i,12)]; if (OverflowFromADD(cpu->R[REG_POS(i,16)], tmp, cpu->R[REG_POS(i,12)])) cpu->CPSR.bits.Q = 1; //INFO("SMLABB %08X * %08X + %08X = %08X\n", (s16)cpu->R[REG_POS(i,0)], (s16)cpu->R[REG_POS(i,8)], cpu->R[REG_POS(i,12)], (s32)cpu->R[REG_POS(i,16)]); return 2; } TEMPLATE static u32 FASTCALL OP_SMLA_B_T(const u32 i) { 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)]; //INFO("SMLABT R%d:%08X * R%d:%08X + R%d:%08X = %08X\n", REG_POS(i,0), cpu->R[REG_POS(i,0)], REG_POS(i,8), cpu->R[REG_POS(i,8)], REG_POS(i,12), 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; } TEMPLATE static u32 FASTCALL OP_SMLA_T_B(const u32 i) { 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)]; //INFO("SMLATB %08X * %08X + %08X = %08X\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; } TEMPLATE static u32 FASTCALL OP_SMLA_T_T(const u32 i) { 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)]; //INFO("SMLATT %08X * %08X + %08X = %08X\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 //----------------------------------------------------------------------------- TEMPLATE static u32 FASTCALL OP_SMLAL_B_B(const u32 i) { 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)]; //INFO("SMLALBB %08X * %08X + %08X%08X = %08X%08X\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; } TEMPLATE static u32 FASTCALL OP_SMLAL_B_T(const u32 i) { 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)]; //INFO("SMLALBT %08X * %08X + %08X%08X = %08X%08X\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; } TEMPLATE static u32 FASTCALL OP_SMLAL_T_B(const u32 i) { 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)]; //INFO("SMLALTB %08X * %08X + %08X%08X = %08X%08X\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; } TEMPLATE static u32 FASTCALL OP_SMLAL_T_T(const u32 i) { 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)]; //INFO("SMLALTT %08X * %08X + %08X%08X = %08X%08X\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 //----------------------------------------------------------------------------- TEMPLATE static u32 FASTCALL OP_SMULW_B(const u32 i) { s64 tmp = (s64)LWORD(cpu->R[REG_POS(i,8)]) * (s64)((s32)cpu->R[REG_POS(i,0)]); //INFO("SMULWB %08X * %08X = %08X\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; } TEMPLATE static u32 FASTCALL OP_SMULW_T(const u32 i) { s64 tmp = (s64)HWORD(cpu->R[REG_POS(i,8)]) * (s64)((s32)cpu->R[REG_POS(i,0)]); //INFO("SMULWT %08X * %08X = %08X\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 //----------------------------------------------------------------------------- TEMPLATE static u32 FASTCALL OP_SMLAW_B(const u32 i) { 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)]; //INFO("SMLAWB %08X * %08X + %08X = %08X\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((u32)tmp, a, cpu->R[REG_POS(i,16)])) cpu->CPSR.bits.Q = 1; return 2; } TEMPLATE static u32 FASTCALL OP_SMLAW_T(const u32 i) { 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)]; //INFO("SMLAWT %08X * %08X + %08X = %08X\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((u32)tmp, a, cpu->R[REG_POS(i,16)])) cpu->CPSR.bits.Q = 1; return 2; } //----------------------------------------------------------------------------- // LDR //----------------------------------------------------------------------------- #define OP_LDR(a, b) \ cpu->R[REG_POS(i,12)] = ROR(READ32(cpu->mem_if->data, adr), 8*(adr&3)); \ \ if(REG_POS(i,12)==15) \ { \ if (PROCNUM == 0) \ { \ cpu->CPSR.bits.T = BIT0(cpu->R[15]); \ cpu->R[15] &= 0xFFFFFFFE; \ } \ else \ { \ cpu->R[15] &= 0xFFFFFFFC; \ } \ cpu->next_instruction = cpu->R[15]; \ return MMU_aluMemAccessCycles(b,adr); \ } \ \ return MMU_aluMemAccessCycles(a,adr); // PRE #define OP_LDR_W(a, b) \ cpu->R[REG_POS(i,16)] = adr;\ cpu->R[REG_POS(i,12)] = ROR(READ32(cpu->mem_if->data, adr), 8*(adr&3)); \ \ if(REG_POS(i,12)==15) \ { \ if (PROCNUM == 0) \ { \ cpu->CPSR.bits.T = BIT0(cpu->R[15]); \ cpu->R[15] &= 0xFFFFFFFE; \ } \ else \ { \ cpu->R[15] &= 0xFFFFFFFC; \ } \ cpu->next_instruction = cpu->R[15]; \ return MMU_aluMemAccessCycles(b,adr); \ } \ \ return MMU_aluMemAccessCycles(a,adr); // POST #define OP_LDR_W2(a, b, c) \ u32 adr = cpu->R[REG_POS(i,16)]; \ cpu->R[REG_POS(i,16)] = adr + c;\ cpu->R[REG_POS(i,12)] = ROR(READ32(cpu->mem_if->data, adr), 8*(adr&3)); \ \ if(REG_POS(i,12)==15) \ { \ if (PROCNUM == 0) \ { \ cpu->CPSR.bits.T = BIT0(cpu->R[15]); \ cpu->R[15] &= 0xFFFFFFFE; \ } \ else \ { \ cpu->R[15] &= 0xFFFFFFFC; \ } \ cpu->next_instruction = cpu->R[15]; \ return MMU_aluMemAccessCycles(b,adr); \ } \ \ return MMU_aluMemAccessCycles(a,adr); TEMPLATE static u32 FASTCALL OP_LDR_P_IMM_OFF(const u32 i) { u32 adr = cpu->R[REG_POS(i,16)] + IMM_OFF_12; OP_LDR(3, 5); } TEMPLATE static u32 FASTCALL OP_LDR_M_IMM_OFF(const u32 i) { u32 adr = cpu->R[REG_POS(i,16)] - IMM_OFF_12; OP_LDR(3, 5); } TEMPLATE static u32 FASTCALL OP_LDR_P_LSL_IMM_OFF(const u32 i) { LSL_IMM; u32 adr = cpu->R[REG_POS(i,16)] + shift_op; OP_LDR(3, 5); } TEMPLATE static u32 FASTCALL OP_LDR_M_LSL_IMM_OFF(const u32 i) { LSL_IMM; u32 adr = cpu->R[REG_POS(i,16)] - shift_op; OP_LDR(3, 5); } TEMPLATE static u32 FASTCALL OP_LDR_P_LSR_IMM_OFF(const u32 i) { LSR_IMM; u32 adr = cpu->R[REG_POS(i,16)] + shift_op; OP_LDR(3, 5); } TEMPLATE static u32 FASTCALL OP_LDR_M_LSR_IMM_OFF(const u32 i) { LSR_IMM; u32 adr = cpu->R[REG_POS(i,16)] - shift_op; OP_LDR(3, 5); } TEMPLATE static u32 FASTCALL OP_LDR_P_ASR_IMM_OFF(const u32 i) { ASR_IMM; u32 adr = cpu->R[REG_POS(i,16)] + shift_op; OP_LDR(3, 5); } TEMPLATE static u32 FASTCALL OP_LDR_M_ASR_IMM_OFF(const u32 i) { ASR_IMM; u32 adr = cpu->R[REG_POS(i,16)] - shift_op; OP_LDR(3, 5); } TEMPLATE static u32 FASTCALL OP_LDR_P_ROR_IMM_OFF(const u32 i) { ROR_IMM; u32 adr = cpu->R[REG_POS(i,16)] + shift_op; OP_LDR(3, 5); } TEMPLATE static u32 FASTCALL OP_LDR_M_ROR_IMM_OFF(const u32 i) { ROR_IMM; u32 adr = cpu->R[REG_POS(i,16)] - shift_op; OP_LDR(3, 5); } TEMPLATE static u32 FASTCALL OP_LDR_P_IMM_OFF_PREIND(const u32 i) { u32 adr = cpu->R[REG_POS(i,16)] + IMM_OFF_12; OP_LDR_W(3, 5); } TEMPLATE static u32 FASTCALL OP_LDR_M_IMM_OFF_PREIND(const u32 i) { u32 adr = cpu->R[REG_POS(i,16)] - IMM_OFF_12; OP_LDR_W(3, 5); } TEMPLATE static u32 FASTCALL OP_LDR_P_LSL_IMM_OFF_PREIND(const u32 i) { LSL_IMM; u32 adr = cpu->R[REG_POS(i,16)] + shift_op; OP_LDR_W(3, 5); } TEMPLATE static u32 FASTCALL OP_LDR_M_LSL_IMM_OFF_PREIND(const u32 i) { LSL_IMM; u32 adr = cpu->R[REG_POS(i,16)] - shift_op; OP_LDR_W(3, 5); } TEMPLATE static u32 FASTCALL OP_LDR_P_LSR_IMM_OFF_PREIND(const u32 i) { LSR_IMM; u32 adr = cpu->R[REG_POS(i,16)] + shift_op; OP_LDR_W(3, 5); } TEMPLATE static u32 FASTCALL OP_LDR_M_LSR_IMM_OFF_PREIND(const u32 i) { LSR_IMM; u32 adr = cpu->R[REG_POS(i,16)] - shift_op; OP_LDR_W(3, 5); } TEMPLATE static u32 FASTCALL OP_LDR_P_ASR_IMM_OFF_PREIND(const u32 i) { ASR_IMM; u32 adr = cpu->R[REG_POS(i,16)] + shift_op; OP_LDR_W(3, 5); } TEMPLATE static u32 FASTCALL OP_LDR_M_ASR_IMM_OFF_PREIND(const u32 i) { ASR_IMM; u32 adr = cpu->R[REG_POS(i,16)] - shift_op; OP_LDR_W(3, 5); } TEMPLATE static u32 FASTCALL OP_LDR_P_ROR_IMM_OFF_PREIND(const u32 i) { ROR_IMM; u32 adr = cpu->R[REG_POS(i,16)] + shift_op; OP_LDR_W(3, 5); } TEMPLATE static u32 FASTCALL OP_LDR_M_ROR_IMM_OFF_PREIND(const u32 i) { ROR_IMM; u32 adr = cpu->R[REG_POS(i,16)] - shift_op; OP_LDR_W(3, 5); } TEMPLATE static u32 FASTCALL OP_LDR_P_IMM_OFF_POSTIND(const u32 i) { OP_LDR_W2(3, 5, IMM_OFF_12); } TEMPLATE static u32 FASTCALL OP_LDR_M_IMM_OFF_POSTIND(const u32 i) { OP_LDR_W2(3, 5, -IMM_OFF_12); } TEMPLATE static u32 FASTCALL OP_LDR_P_LSL_IMM_OFF_POSTIND(const u32 i) { LSL_IMM; OP_LDR_W2(3, 5, shift_op); } TEMPLATE static u32 FASTCALL OP_LDR_M_LSL_IMM_OFF_POSTIND(const u32 i) { LSL_IMM; OP_LDR_W2(3, 5, -shift_op); } TEMPLATE static u32 FASTCALL OP_LDR_P_LSR_IMM_OFF_POSTIND(const u32 i) { LSR_IMM; OP_LDR_W2(3, 5, shift_op); } TEMPLATE static u32 FASTCALL OP_LDR_M_LSR_IMM_OFF_POSTIND(const u32 i) { LSR_IMM; OP_LDR_W2(3, 5, -shift_op); } TEMPLATE static u32 FASTCALL OP_LDR_P_ASR_IMM_OFF_POSTIND(const u32 i) { ASR_IMM; OP_LDR_W2(3, 5, shift_op); } TEMPLATE static u32 FASTCALL OP_LDR_M_ASR_IMM_OFF_POSTIND(const u32 i) { ASR_IMM; OP_LDR_W2(3, 5, -shift_op); } TEMPLATE static u32 FASTCALL OP_LDR_P_ROR_IMM_OFF_POSTIND(const u32 i) { ROR_IMM; OP_LDR_W2(3, 5, shift_op); } TEMPLATE static u32 FASTCALL OP_LDR_M_ROR_IMM_OFF_POSTIND(const u32 i) { ROR_IMM; OP_LDR_W2(3, 5, -shift_op); } //----------------------------------------------------------------------------- // LDREX //----------------------------------------------------------------------------- TEMPLATE static u32 FASTCALL OP_LDREX(const u32 i) { printf("LDREX\n"); u32 adr = cpu->R[REG_POS(i,16)]; cpu->R[REG_POS(i,12)] = ROR(READ32(cpu->mem_if->data, adr), 8*(adr&3)); return MMU_aluMemAccessCycles(3,adr); } //----------------------------------------------------------------------------- // LDRB //----------------------------------------------------------------------------- TEMPLATE static u32 FASTCALL OP_LDRB_P_IMM_OFF(const u32 i) { u32 adr = cpu->R[REG_POS(i,16)] + IMM_OFF_12; cpu->R[REG_POS(i,12)] = (u32)READ8(cpu->mem_if->data, adr); return MMU_aluMemAccessCycles(3,adr); } TEMPLATE static u32 FASTCALL OP_LDRB_M_IMM_OFF(const u32 i) { u32 adr = cpu->R[REG_POS(i,16)] - IMM_OFF_12; cpu->R[REG_POS(i,12)] = (u32)READ8(cpu->mem_if->data, adr); return MMU_aluMemAccessCycles(3,adr); } TEMPLATE static u32 FASTCALL OP_LDRB_P_LSL_IMM_OFF(const u32 i) { LSL_IMM; u32 adr = cpu->R[REG_POS(i,16)] + shift_op; cpu->R[REG_POS(i,12)] = (u32)READ8(cpu->mem_if->data, adr); return MMU_aluMemAccessCycles(3,adr); } TEMPLATE static u32 FASTCALL OP_LDRB_M_LSL_IMM_OFF(const u32 i) { LSL_IMM; u32 adr = cpu->R[REG_POS(i,16)] - shift_op; cpu->R[REG_POS(i,12)] = (u32)READ8(cpu->mem_if->data, adr);; return MMU_aluMemAccessCycles(3,adr); } TEMPLATE static u32 FASTCALL OP_LDRB_P_LSR_IMM_OFF(const u32 i) { LSR_IMM; u32 adr = cpu->R[REG_POS(i,16)] + shift_op; cpu->R[REG_POS(i,12)] = READ8(cpu->mem_if->data, adr); return MMU_aluMemAccessCycles(3,adr); } TEMPLATE static u32 FASTCALL OP_LDRB_M_LSR_IMM_OFF(const u32 i) { LSR_IMM; u32 adr = cpu->R[REG_POS(i,16)] - shift_op; cpu->R[REG_POS(i,12)] = (u32)READ8(cpu->mem_if->data, adr); return MMU_aluMemAccessCycles(3,adr); } TEMPLATE static u32 FASTCALL OP_LDRB_P_ASR_IMM_OFF(const u32 i) { ASR_IMM; u32 adr = cpu->R[REG_POS(i,16)] + shift_op; cpu->R[REG_POS(i,12)] = (u32)READ8(cpu->mem_if->data, adr); return MMU_aluMemAccessCycles(3,adr); } TEMPLATE static u32 FASTCALL OP_LDRB_M_ASR_IMM_OFF(const u32 i) { ASR_IMM; u32 adr = cpu->R[REG_POS(i,16)] - shift_op; cpu->R[REG_POS(i,12)] = (u32)READ8(cpu->mem_if->data, adr); return MMU_aluMemAccessCycles(3,adr); } TEMPLATE static u32 FASTCALL OP_LDRB_P_ROR_IMM_OFF(const u32 i) { ROR_IMM; u32 adr = cpu->R[REG_POS(i,16)] + shift_op; cpu->R[REG_POS(i,12)] = (u32)READ8(cpu->mem_if->data, adr); return MMU_aluMemAccessCycles(3,adr); } TEMPLATE static u32 FASTCALL OP_LDRB_M_ROR_IMM_OFF(const u32 i) { ROR_IMM; u32 adr = cpu->R[REG_POS(i,16)] - shift_op; cpu->R[REG_POS(i,12)] = (u32)READ8(cpu->mem_if->data, adr); return MMU_aluMemAccessCycles(3,adr); } TEMPLATE static u32 FASTCALL OP_LDRB_P_IMM_OFF_PREIND(const u32 i) { u32 adr = cpu->R[REG_POS(i,16)] + IMM_OFF_12; cpu->R[REG_POS(i,16)] = adr; cpu->R[REG_POS(i,12)] = (u32)READ8(cpu->mem_if->data, adr); return MMU_aluMemAccessCycles(3,adr); } TEMPLATE static u32 FASTCALL OP_LDRB_M_IMM_OFF_PREIND(const u32 i) { u32 adr = cpu->R[REG_POS(i,16)] - IMM_OFF_12; cpu->R[REG_POS(i,16)] = adr; cpu->R[REG_POS(i,12)] = (u32)READ8(cpu->mem_if->data, adr);; return MMU_aluMemAccessCycles(3,adr); } TEMPLATE static u32 FASTCALL OP_LDRB_P_LSL_IMM_OFF_PREIND(const u32 i) { LSL_IMM; u32 adr = cpu->R[REG_POS(i,16)] + shift_op; cpu->R[REG_POS(i,16)] = adr; cpu->R[REG_POS(i,12)] = (u32)READ8(cpu->mem_if->data, adr); return MMU_aluMemAccessCycles(3,adr); } TEMPLATE static u32 FASTCALL OP_LDRB_M_LSL_IMM_OFF_PREIND(const u32 i) { LSL_IMM; u32 adr = cpu->R[REG_POS(i,16)] - shift_op; cpu->R[REG_POS(i,16)] = adr; cpu->R[REG_POS(i,12)] = (u32)READ8(cpu->mem_if->data, adr); return MMU_aluMemAccessCycles(3,adr); } TEMPLATE static u32 FASTCALL OP_LDRB_P_LSR_IMM_OFF_PREIND(const u32 i) { LSR_IMM; u32 adr = cpu->R[REG_POS(i,16)] + shift_op; cpu->R[REG_POS(i,16)] = adr; cpu->R[REG_POS(i,12)] = (u32)READ8(cpu->mem_if->data, adr); return MMU_aluMemAccessCycles(3,adr); } TEMPLATE static u32 FASTCALL OP_LDRB_M_LSR_IMM_OFF_PREIND(const u32 i) { LSR_IMM; u32 adr = cpu->R[REG_POS(i,16)] - shift_op; cpu->R[REG_POS(i,16)] = adr; cpu->R[REG_POS(i,12)] = (u32)READ8(cpu->mem_if->data, adr); return MMU_aluMemAccessCycles(3,adr); } TEMPLATE static u32 FASTCALL OP_LDRB_P_ASR_IMM_OFF_PREIND(const u32 i) { ASR_IMM; u32 adr = cpu->R[REG_POS(i,16)] + shift_op; cpu->R[REG_POS(i,16)] = adr; cpu->R[REG_POS(i,12)] = (u32)READ8(cpu->mem_if->data, adr); return MMU_aluMemAccessCycles(3,adr); } TEMPLATE static u32 FASTCALL OP_LDRB_M_ASR_IMM_OFF_PREIND(const u32 i) { ASR_IMM; u32 adr = cpu->R[REG_POS(i,16)] - shift_op; cpu->R[REG_POS(i,16)] = adr; cpu->R[REG_POS(i,12)] = (u32)READ8(cpu->mem_if->data, adr); return MMU_aluMemAccessCycles(3,adr); } TEMPLATE static u32 FASTCALL OP_LDRB_P_ROR_IMM_OFF_PREIND(const u32 i) { ROR_IMM; u32 adr = cpu->R[REG_POS(i,16)] + shift_op; cpu->R[REG_POS(i,16)] = adr; cpu->R[REG_POS(i,12)] = (u32)READ8(cpu->mem_if->data, adr); return MMU_aluMemAccessCycles(3,adr); } TEMPLATE static u32 FASTCALL OP_LDRB_M_ROR_IMM_OFF_PREIND(const u32 i) { ROR_IMM; u32 adr = cpu->R[REG_POS(i,16)] - shift_op; cpu->R[REG_POS(i,16)] = adr; cpu->R[REG_POS(i,12)] = (u32)READ8(cpu->mem_if->data, adr); return MMU_aluMemAccessCycles(3,adr); } TEMPLATE static u32 FASTCALL OP_LDRB_P_IMM_OFF_POSTIND(const u32 i) { u32 adr = cpu->R[REG_POS(i,16)]; cpu->R[REG_POS(i,16)] = adr + IMM_OFF_12; cpu->R[REG_POS(i,12)] = (u32)READ8(cpu->mem_if->data, adr); return MMU_aluMemAccessCycles(3,adr); } TEMPLATE static u32 FASTCALL OP_LDRB_M_IMM_OFF_POSTIND(const u32 i) { u32 adr = cpu->R[REG_POS(i,16)]; cpu->R[REG_POS(i,16)] = adr - IMM_OFF_12; cpu->R[REG_POS(i,12)] = (u32)READ8(cpu->mem_if->data, adr); return MMU_aluMemAccessCycles(3,adr); } TEMPLATE static u32 FASTCALL OP_LDRB_P_LSL_IMM_OFF_POSTIND(const u32 i) { LSL_IMM; u32 adr = cpu->R[REG_POS(i,16)]; cpu->R[REG_POS(i,16)] = adr + shift_op; cpu->R[REG_POS(i,12)] = (u32)READ8(cpu->mem_if->data, adr); return MMU_aluMemAccessCycles(3,adr); } TEMPLATE static u32 FASTCALL OP_LDRB_M_LSL_IMM_OFF_POSTIND(const u32 i) { LSL_IMM; u32 adr = cpu->R[REG_POS(i,16)]; cpu->R[REG_POS(i,16)] = adr - shift_op; cpu->R[REG_POS(i,12)] = (u32)READ8(cpu->mem_if->data, adr); return MMU_aluMemAccessCycles(3,adr); } TEMPLATE static u32 FASTCALL OP_LDRB_P_LSR_IMM_OFF_POSTIND(const u32 i) { LSR_IMM; u32 adr = cpu->R[REG_POS(i,16)]; cpu->R[REG_POS(i,16)] = adr + shift_op; cpu->R[REG_POS(i,12)] = (u32)READ8(cpu->mem_if->data, adr); return MMU_aluMemAccessCycles(3,adr); } TEMPLATE static u32 FASTCALL OP_LDRB_M_LSR_IMM_OFF_POSTIND(const u32 i) { LSR_IMM; u32 adr = cpu->R[REG_POS(i,16)]; cpu->R[REG_POS(i,16)] = adr - shift_op; cpu->R[REG_POS(i,12)] = (u32)READ8(cpu->mem_if->data, adr); return MMU_aluMemAccessCycles(3,adr); } TEMPLATE static u32 FASTCALL OP_LDRB_P_ASR_IMM_OFF_POSTIND(const u32 i) { ASR_IMM; u32 adr = cpu->R[REG_POS(i,16)]; cpu->R[REG_POS(i,16)] = adr + shift_op; cpu->R[REG_POS(i,12)] = (u32)READ8(cpu->mem_if->data, adr); return MMU_aluMemAccessCycles(3,adr); } TEMPLATE static u32 FASTCALL OP_LDRB_M_ASR_IMM_OFF_POSTIND(const u32 i) { ASR_IMM; u32 adr = cpu->R[REG_POS(i,16)]; cpu->R[REG_POS(i,16)] = adr - shift_op; cpu->R[REG_POS(i,12)] = (u32)READ8(cpu->mem_if->data, adr); return MMU_aluMemAccessCycles(3,adr); } TEMPLATE static u32 FASTCALL OP_LDRB_P_ROR_IMM_OFF_POSTIND(const u32 i) { ROR_IMM; u32 adr = cpu->R[REG_POS(i,16)]; cpu->R[REG_POS(i,16)] = adr + shift_op; cpu->R[REG_POS(i,12)] = (u32)READ8(cpu->mem_if->data, adr); return MMU_aluMemAccessCycles(3,adr); } TEMPLATE static u32 FASTCALL OP_LDRB_M_ROR_IMM_OFF_POSTIND(const u32 i) { ROR_IMM; u32 adr = cpu->R[REG_POS(i,16)]; cpu->R[REG_POS(i,16)] = adr - shift_op; cpu->R[REG_POS(i,12)] = (u32)READ8(cpu->mem_if->data, adr); return MMU_aluMemAccessCycles(3,adr); } //----------------------------------------------------------------------------- // STR //----------------------------------------------------------------------------- TEMPLATE static u32 FASTCALL OP_STR_P_IMM_OFF(const u32 i) { u32 adr = cpu->R[REG_POS(i,16)] + IMM_OFF_12; WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static u32 FASTCALL OP_STR_M_IMM_OFF(const u32 i) { u32 adr = cpu->R[REG_POS(i,16)] - IMM_OFF_12; WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static u32 FASTCALL OP_STR_P_LSL_IMM_OFF(const u32 i) { LSL_IMM; u32 adr = cpu->R[REG_POS(i,16)] + shift_op; WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static u32 FASTCALL OP_STR_M_LSL_IMM_OFF(const u32 i) { LSL_IMM; u32 adr = cpu->R[REG_POS(i,16)] - shift_op; WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static u32 FASTCALL OP_STR_P_LSR_IMM_OFF(const u32 i) { LSR_IMM; u32 adr = cpu->R[REG_POS(i,16)] + shift_op; WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static u32 FASTCALL OP_STR_M_LSR_IMM_OFF(const u32 i) { LSR_IMM; u32 adr = cpu->R[REG_POS(i,16)] - shift_op; WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static u32 FASTCALL OP_STR_P_ASR_IMM_OFF(const u32 i) { ASR_IMM; u32 adr = cpu->R[REG_POS(i,16)] + shift_op; WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static u32 FASTCALL OP_STR_M_ASR_IMM_OFF(const u32 i) { ASR_IMM; u32 adr = cpu->R[REG_POS(i,16)] - shift_op; WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static u32 FASTCALL OP_STR_P_ROR_IMM_OFF(const u32 i) { ROR_IMM; u32 adr = cpu->R[REG_POS(i,16)] + shift_op; WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static u32 FASTCALL OP_STR_M_ROR_IMM_OFF(const u32 i) { ROR_IMM; u32 adr = cpu->R[REG_POS(i,16)] - shift_op; WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static u32 FASTCALL OP_STR_P_IMM_OFF_PREIND(const u32 i) { u32 adr = cpu->R[REG_POS(i,16)] + IMM_OFF_12; cpu->R[REG_POS(i,16)] = adr; WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static u32 FASTCALL OP_STR_M_IMM_OFF_PREIND(const u32 i) { u32 adr = cpu->R[REG_POS(i,16)] - IMM_OFF_12; cpu->R[REG_POS(i,16)] = adr; WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static u32 FASTCALL OP_STR_P_LSL_IMM_OFF_PREIND(const u32 i) { LSL_IMM; u32 adr = cpu->R[REG_POS(i,16)] + shift_op; cpu->R[REG_POS(i,16)] = adr; WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static u32 FASTCALL OP_STR_M_LSL_IMM_OFF_PREIND(const u32 i) { LSL_IMM; u32 adr = cpu->R[REG_POS(i,16)] - shift_op; cpu->R[REG_POS(i,16)] = adr; WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static u32 FASTCALL OP_STR_P_LSR_IMM_OFF_PREIND(const u32 i) { LSR_IMM; u32 adr = cpu->R[REG_POS(i,16)] + shift_op; cpu->R[REG_POS(i,16)] = adr; WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static u32 FASTCALL OP_STR_M_LSR_IMM_OFF_PREIND(const u32 i) { LSR_IMM; u32 adr = cpu->R[REG_POS(i,16)] - shift_op; cpu->R[REG_POS(i,16)] = adr; WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static u32 FASTCALL OP_STR_P_ASR_IMM_OFF_PREIND(const u32 i) { ASR_IMM; u32 adr = cpu->R[REG_POS(i,16)] + shift_op; cpu->R[REG_POS(i,16)] = adr; WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static u32 FASTCALL OP_STR_M_ASR_IMM_OFF_PREIND(const u32 i) { ASR_IMM; u32 adr = cpu->R[REG_POS(i,16)] - shift_op; cpu->R[REG_POS(i,16)] = adr; WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static u32 FASTCALL OP_STR_P_ROR_IMM_OFF_PREIND(const u32 i) { ROR_IMM; u32 adr = cpu->R[REG_POS(i,16)] + shift_op; cpu->R[REG_POS(i,16)] = adr; WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static u32 FASTCALL OP_STR_M_ROR_IMM_OFF_PREIND(const u32 i) { ROR_IMM; u32 adr = cpu->R[REG_POS(i,16)] - shift_op; cpu->R[REG_POS(i,16)] = adr; WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static u32 FASTCALL OP_STR_P_IMM_OFF_POSTIND(const u32 i) { 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 MMU_aluMemAccessCycles(2,adr); } TEMPLATE static u32 FASTCALL OP_STR_M_IMM_OFF_POSTIND(const u32 i) { 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 MMU_aluMemAccessCycles(2,adr); } TEMPLATE static u32 FASTCALL OP_STR_P_LSL_IMM_OFF_POSTIND(const u32 i) { LSL_IMM; 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 + shift_op; return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static u32 FASTCALL OP_STR_M_LSL_IMM_OFF_POSTIND(const u32 i) { LSL_IMM; 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 - shift_op; return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static u32 FASTCALL OP_STR_P_LSR_IMM_OFF_POSTIND(const u32 i) { LSR_IMM; 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 + shift_op; return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static u32 FASTCALL OP_STR_M_LSR_IMM_OFF_POSTIND(const u32 i) { LSR_IMM; 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 - shift_op; return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static u32 FASTCALL OP_STR_P_ASR_IMM_OFF_POSTIND(const u32 i) { ASR_IMM; 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 + shift_op; return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static u32 FASTCALL OP_STR_M_ASR_IMM_OFF_POSTIND(const u32 i) { ASR_IMM; 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 - shift_op; return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static u32 FASTCALL OP_STR_P_ROR_IMM_OFF_POSTIND(const u32 i) { ROR_IMM; 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 + shift_op; return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static u32 FASTCALL OP_STR_M_ROR_IMM_OFF_POSTIND(const u32 i) { ROR_IMM; 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 - shift_op; return MMU_aluMemAccessCycles(2,adr); } //----------------------------------------------------------------------------- // STREX //----------------------------------------------------------------------------- TEMPLATE static u32 FASTCALL OP_STREX(const u32 i) { printf("STREX\n"); u32 adr = cpu->R[REG_POS(i,16)]; WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,0)]); cpu->R[REG_POS(i,12)] = 0; return MMU_aluMemAccessCycles(2,adr); } //----------------------------------------------------------------------------- // STRB //----------------------------------------------------------------------------- TEMPLATE static u32 FASTCALL OP_STRB_P_IMM_OFF(const u32 i) { 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 MMU_aluMemAccessCycles(2,adr); } TEMPLATE static u32 FASTCALL OP_STRB_M_IMM_OFF(const u32 i) { 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 MMU_aluMemAccessCycles(2,adr); } TEMPLATE static u32 FASTCALL OP_STRB_P_LSL_IMM_OFF(const u32 i) { LSL_IMM; u32 adr = cpu->R[REG_POS(i,16)] + shift_op; WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static u32 FASTCALL OP_STRB_M_LSL_IMM_OFF(const u32 i) { LSL_IMM; u32 adr = cpu->R[REG_POS(i,16)] - shift_op; WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static u32 FASTCALL OP_STRB_P_LSR_IMM_OFF(const u32 i) { LSR_IMM; u32 adr = cpu->R[REG_POS(i,16)] + shift_op; WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static u32 FASTCALL OP_STRB_M_LSR_IMM_OFF(const u32 i) { LSR_IMM; u32 adr = cpu->R[REG_POS(i,16)] - shift_op; WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static u32 FASTCALL OP_STRB_P_ASR_IMM_OFF(const u32 i) { ASR_IMM; u32 adr = cpu->R[REG_POS(i,16)] + shift_op; WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static u32 FASTCALL OP_STRB_M_ASR_IMM_OFF(const u32 i) { ASR_IMM; u32 adr = cpu->R[REG_POS(i,16)] - shift_op; WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static u32 FASTCALL OP_STRB_P_ROR_IMM_OFF(const u32 i) { ROR_IMM; u32 adr = cpu->R[REG_POS(i,16)] + shift_op; WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static u32 FASTCALL OP_STRB_M_ROR_IMM_OFF(const u32 i) { ROR_IMM; u32 adr = cpu->R[REG_POS(i,16)] - shift_op; WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static u32 FASTCALL OP_STRB_P_IMM_OFF_PREIND(const u32 i) { u32 adr = cpu->R[REG_POS(i,16)] + IMM_OFF_12; cpu->R[REG_POS(i,16)] = adr; WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static u32 FASTCALL OP_STRB_M_IMM_OFF_PREIND(const u32 i) { u32 adr = cpu->R[REG_POS(i,16)] - IMM_OFF_12; cpu->R[REG_POS(i,16)] = adr; WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static u32 FASTCALL OP_STRB_P_LSL_IMM_OFF_PREIND(const u32 i) { LSL_IMM; u32 adr = cpu->R[REG_POS(i,16)] + shift_op; cpu->R[REG_POS(i,16)] = adr; WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static u32 FASTCALL OP_STRB_M_LSL_IMM_OFF_PREIND(const u32 i) { LSL_IMM; u32 adr = cpu->R[REG_POS(i,16)] - shift_op; cpu->R[REG_POS(i,16)] = adr; WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static u32 FASTCALL OP_STRB_P_LSR_IMM_OFF_PREIND(const u32 i) { LSR_IMM; u32 adr = cpu->R[REG_POS(i,16)] + shift_op; cpu->R[REG_POS(i,16)] = adr; WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static u32 FASTCALL OP_STRB_M_LSR_IMM_OFF_PREIND(const u32 i) { LSR_IMM; u32 adr = cpu->R[REG_POS(i,16)] - shift_op; cpu->R[REG_POS(i,16)] = adr; WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static u32 FASTCALL OP_STRB_P_ASR_IMM_OFF_PREIND(const u32 i) { ASR_IMM; u32 adr = cpu->R[REG_POS(i,16)] + shift_op; cpu->R[REG_POS(i,16)] = adr; WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static u32 FASTCALL OP_STRB_M_ASR_IMM_OFF_PREIND(const u32 i) { ASR_IMM; u32 adr = cpu->R[REG_POS(i,16)] - shift_op; cpu->R[REG_POS(i,16)] = adr; WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static u32 FASTCALL OP_STRB_P_ROR_IMM_OFF_PREIND(const u32 i) { ROR_IMM; u32 adr = cpu->R[REG_POS(i,16)] + shift_op; cpu->R[REG_POS(i,16)] = adr; WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static u32 FASTCALL OP_STRB_M_ROR_IMM_OFF_PREIND(const u32 i) { ROR_IMM; u32 adr = cpu->R[REG_POS(i,16)] - shift_op; cpu->R[REG_POS(i,16)] = adr; WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static u32 FASTCALL OP_STRB_P_IMM_OFF_POSTIND(const u32 i) { 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 MMU_aluMemAccessCycles(2,adr); } TEMPLATE static u32 FASTCALL OP_STRB_M_IMM_OFF_POSTIND(const u32 i) { 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 MMU_aluMemAccessCycles(2,adr); } TEMPLATE static u32 FASTCALL OP_STRB_P_LSL_IMM_OFF_POSTIND(const u32 i) { LSL_IMM; 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 + shift_op; return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static u32 FASTCALL OP_STRB_M_LSL_IMM_OFF_POSTIND(const u32 i) { LSL_IMM; 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 - shift_op; return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static u32 FASTCALL OP_STRB_P_LSR_IMM_OFF_POSTIND(const u32 i) { LSR_IMM; 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 + shift_op; return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static u32 FASTCALL OP_STRB_M_LSR_IMM_OFF_POSTIND(const u32 i) { LSR_IMM; 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 - shift_op; return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static u32 FASTCALL OP_STRB_P_ASR_IMM_OFF_POSTIND(const u32 i) { ASR_IMM; 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 + shift_op; return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static u32 FASTCALL OP_STRB_M_ASR_IMM_OFF_POSTIND(const u32 i) { ASR_IMM; 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 - shift_op; return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static u32 FASTCALL OP_STRB_P_ROR_IMM_OFF_POSTIND(const u32 i) { ROR_IMM; 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 + shift_op; return MMU_aluMemAccessCycles(2,adr); } TEMPLATE static u32 FASTCALL OP_STRB_M_ROR_IMM_OFF_POSTIND(const u32 i) { ROR_IMM; 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 - shift_op; return MMU_aluMemAccessCycles(2,adr); } //----------------------------------------------------------------------------- // LDMIA / LDMIB / LDMDA / LDMDB //----------------------------------------------------------------------------- #define OP_L_IA(reg, adr) if(BIT##reg(i)) \ { \ registres[reg] = READ32(cpu->mem_if->data, start); \ c += MMU_memAccessCycles(start); \ adr += 4; \ } #define OP_L_IB(reg, adr) if(BIT##reg(i)) \ { \ adr += 4; \ registres[reg] = READ32(cpu->mem_if->data, start); \ c += MMU_memAccessCycles(start); \ } #define OP_L_DA(reg, adr) if(BIT##reg(i)) \ { \ registres[reg] = READ32(cpu->mem_if->data, start); \ c += MMU_memAccessCycles(start); \ adr -= 4; \ } #define OP_L_DB(reg, adr) if(BIT##reg(i)) \ { \ adr -= 4; \ registres[reg] = READ32(cpu->mem_if->data, start); \ c += MMU_memAccessCycles(start); \ } TEMPLATE static u32 FASTCALL OP_LDMIA(const u32 i) { u32 c = 0; u32 start = cpu->R[REG_POS(i,16)]; u32 * registres = cpu->R; 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); // TODO // The general-purpose registers loaded can include the PC. If they do, the word loaded for the PC is treated // as an address and a branch occurs to that address. In ARMv5 and above, bit[0] of the loaded value // determines whether execution continues after this branch in ARM state or in Thumb state, as though a BX // (loaded_value) instruction had been executed (but see also The T and J bits on page A2-15 for operation on // non-T variants of ARMv5). In earlier versions of the architecture, bits[1:0] of the loaded value are ignored // and execution continues in ARM state, as though the instruction MOV PC,(loaded_value) had been executed. // //value = Memory[address,4] //if (architecture version 5 or above) then // pc = value AND 0xFFFFFFFE // T Bit = value[0] //else // pc = value AND 0xFFFFFFFC if (PROCNUM == 0) { cpu->CPSR.bits.T = BIT0(tmp); registres[15] = tmp & 0xFFFFFFFE; } else registres[15] = tmp & 0xFFFFFFFC; //start += 4; cpu->next_instruction = registres[15]; c += MMU_memAccessCycles(start); } return MMU_aluMemCycles(2, c); } TEMPLATE static u32 FASTCALL OP_LDMIB(const u32 i) { u32 c = 0; u32 start = cpu->R[REG_POS(i,16)]; u32 * registres = cpu->R; 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)) { start += 4; c += MMU_memAccessCycles(start); u32 tmp = READ32(cpu->mem_if->data, start); if (PROCNUM == 0) { cpu->CPSR.bits.T = BIT0(tmp); registres[15] = tmp & 0xFFFFFFFE; } else registres[15] = tmp & 0xFFFFFFFC; cpu->next_instruction = registres[15]; return MMU_aluMemCycles(4, c); } return MMU_aluMemCycles(2, c); } TEMPLATE static u32 FASTCALL OP_LDMDA(const u32 i) { u32 c = 0; u32 start = cpu->R[REG_POS(i,16)]; u32 * registres = cpu->R; if(BIT15(i)) { u32 tmp = READ32(cpu->mem_if->data, start); if (PROCNUM == 0) { cpu->CPSR.bits.T = BIT0(tmp); registres[15] = tmp & 0xFFFFFFFE; } else registres[15] = tmp & 0xFFFFFFFC; c += MMU_memAccessCycles(start); 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 MMU_aluMemCycles(2, c); } TEMPLATE static u32 FASTCALL OP_LDMDB(const u32 i) { u32 c = 0; u32 start = cpu->R[REG_POS(i,16)]; u32 * registres = cpu->R; if(BIT15(i)) { start -= 4; u32 tmp = READ32(cpu->mem_if->data, start); if (PROCNUM == 0) { cpu->CPSR.bits.T = BIT0(tmp); registres[15] = tmp & 0xFFFFFFFE; } else registres[15] = tmp & 0xFFFFFFFC; cpu->next_instruction = registres[15]; c += MMU_memAccessCycles(start); } 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 MMU_aluMemCycles(2, c); } TEMPLATE static u32 FASTCALL OP_LDMIA_W(const u32 i) { u32 c = 0; u32 start = cpu->R[REG_POS(i,16)]; u32 bitList = (~((2 << REG_POS(i,16))-1)) & 0xFFFF; u32 * registres = cpu->R; 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); if (PROCNUM == 0) { cpu->CPSR.bits.T = BIT0(tmp); registres[15] = tmp & 0xFFFFFFFE; } else registres[15] = tmp & 0xFFFFFFFC; c += MMU_memAccessCycles(start); 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 MMU_aluMemCycles(BIT15(i)?4:2, c); } TEMPLATE static u32 FASTCALL OP_LDMIB_W(const u32 i) { u32 c = 0; u32 start = cpu->R[REG_POS(i,16)]; u32 bitList = (~((2 << REG_POS(i,16))-1)) & 0xFFFF; u32 * registres = cpu->R; 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 += MMU_memAccessCycles(start); tmp = READ32(cpu->mem_if->data, start); if (PROCNUM == 0) { cpu->CPSR.bits.T = BIT0(tmp); registres[15] = tmp & 0xFFFFFFFE; } else registres[15] = tmp & 0xFFFFFFFC; 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 MMU_aluMemCycles(BIT15(i)?4:2, c); } TEMPLATE static u32 FASTCALL OP_LDMDA_W(const u32 i) { u32 c = 0; u32 start = cpu->R[REG_POS(i,16)]; u32 bitList = (~((2 << REG_POS(i,16))-1)) & 0xFFFF; u32 * registres = cpu->R; if(BIT15(i)) { u32 tmp = READ32(cpu->mem_if->data, start); if (PROCNUM == 0) { cpu->CPSR.bits.T = BIT0(tmp); registres[15] = tmp & 0xFFFFFFFE; } else registres[15] = tmp & 0xFFFFFFFC; c += MMU_memAccessCycles(start); 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 MMU_aluMemCycles(2, c); } TEMPLATE static u32 FASTCALL OP_LDMDB_W(const u32 i) { u32 c = 0; u32 start = cpu->R[REG_POS(i,16)]; u32 bitList = (~((2 << REG_POS(i,16))-1)) & 0xFFFF; u32 * registres = cpu->R; if(BIT15(i)) { u32 tmp; start -= 4; tmp = READ32(cpu->mem_if->data, start); if (PROCNUM == 0) { cpu->CPSR.bits.T = BIT0(tmp); registres[15] = tmp & 0xFFFFFFFE; } else registres[15] = tmp & 0xFFFFFFFC; cpu->next_instruction = registres[15]; c += MMU_memAccessCycles(start); } 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 MMU_aluMemCycles(2, c); } TEMPLATE static u32 FASTCALL OP_LDMIA2(const u32 i) { u32 oldmode = 0; u32 c = 0; u32 start = cpu->R[REG_POS(i,16)]; u32 * registres; if(BIT15(i)==0) { if((cpu->CPSR.bits.mode==USR)||(cpu->CPSR.bits.mode==SYS)) { printf("ERROR1\n"); return 1; } oldmode = armcpu_switchMode(cpu, SYS); } registres = cpu->R; 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) { armcpu_switchMode(cpu, oldmode); } else { 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; cpu->changeCPSR(); //start += 4; cpu->next_instruction = cpu->R[15]; c += MMU_memAccessCycles(start); } return MMU_aluMemCycles(2, c); } TEMPLATE static u32 FASTCALL OP_LDMIB2(const u32 i) { u32 oldmode = 0; u32 c = 0; u32 start = cpu->R[REG_POS(i,16)]; u32 * registres; UNTESTEDOPCODELOG("Untested opcode: OP_LDMIB2 \n"); if(BIT15(i)==0) { if((cpu->CPSR.bits.mode==USR)||(cpu->CPSR.bits.mode==SYS)) { printf("ERROR1\n"); return 1; } oldmode = armcpu_switchMode(cpu, SYS); } registres = cpu->R; 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); } else { 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->changeCPSR(); cpu->next_instruction = registres[15]; c += MMU_memAccessCycles(start); } return MMU_aluMemCycles(2, c); } TEMPLATE static u32 FASTCALL OP_LDMDA2(const u32 i) { u32 oldmode = 0; u32 c = 0; u32 * registres; u32 start = cpu->R[REG_POS(i,16)]; UNTESTEDOPCODELOG("Untested opcode: OP_LDMDA2 \n"); if(BIT15(i)==0) { if((cpu->CPSR.bits.mode==USR)||(cpu->CPSR.bits.mode==SYS)) { printf("ERROR1\n"); return 1; } oldmode = armcpu_switchMode(cpu, SYS); } registres = cpu->R; if(BIT15(i)) { u32 tmp = READ32(cpu->mem_if->data, start); registres[15] = tmp & (0XFFFFFFFC | (BIT0(tmp)<<1)); cpu->CPSR = cpu->SPSR; cpu->changeCPSR(); c += MMU_memAccessCycles(start); 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; cpu->changeCPSR(); } return MMU_aluMemCycles(2, c); } TEMPLATE static u32 FASTCALL OP_LDMDB2(const u32 i) { u32 oldmode = 0; u32 c = 0; u32 * registres; u32 start = cpu->R[REG_POS(i,16)]; if(BIT15(i)==0) { if((cpu->CPSR.bits.mode==USR)||(cpu->CPSR.bits.mode==SYS)) { printf("ERROR1\n"); return 1; } oldmode = armcpu_switchMode(cpu, SYS); } registres = cpu->R; 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->changeCPSR(); cpu->next_instruction = registres[15]; c += MMU_memAccessCycles(start); } 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; cpu->changeCPSR(); } return MMU_aluMemCycles(2, c); } TEMPLATE static u32 FASTCALL OP_LDMIA2_W(const u32 i) { u32 c = 0; u32 oldmode = 0; u32 start = cpu->R[REG_POS(i,16)]; u32 * registres; u32 tmp; Status_Reg SPSR; // emu_halt(); if(BIT15(i)==0) { if((cpu->CPSR.bits.mode==USR)||(cpu->CPSR.bits.mode==SYS)) { printf("ERROR1\n"); return 1; } oldmode = armcpu_switchMode(cpu, SYS); } registres = cpu->R; 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) { if (!BIT_N(i, REG_POS(i,16))) registres[REG_POS(i,16)] = start; armcpu_switchMode(cpu, oldmode); return MMU_aluMemCycles(2, c); } if (!BIT_N(i, REG_POS(i,16))) 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->changeCPSR(); cpu->next_instruction = registres[15]; c += MMU_memAccessCycles(start); return MMU_aluMemCycles(2, c); } TEMPLATE static u32 FASTCALL OP_LDMIB2_W(const u32 i) { u32 c = 0; u32 oldmode = 0; u32 start = cpu->R[REG_POS(i,16)]; u32 * registres; u32 tmp; Status_Reg SPSR; if(BIT15(i)==0) { if((cpu->CPSR.bits.mode==USR)||(cpu->CPSR.bits.mode==SYS)) { printf("ERROR1\n"); return 1; } oldmode = armcpu_switchMode(cpu, SYS); } registres = cpu->R; 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) { if (!BIT_N(i, REG_POS(i,16))) registres[REG_POS(i,16)] = start; armcpu_switchMode(cpu, oldmode); return MMU_aluMemCycles(2, c); } if (!BIT_N(i, REG_POS(i,16))) 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->changeCPSR(); cpu->next_instruction = registres[15]; SPSR = cpu->SPSR; armcpu_switchMode(cpu, SPSR.bits.mode); cpu->CPSR=SPSR; cpu->changeCPSR(); c += MMU_memAccessCycles(start); return MMU_aluMemCycles(2, c); } TEMPLATE static u32 FASTCALL OP_LDMDA2_W(const u32 i) { u32 c = 0; u32 oldmode = 0; u32 start = cpu->R[REG_POS(i,16)]; u32 * registres; Status_Reg SPSR; // emu_halt(); if(BIT15(i)==0) { if((cpu->CPSR.bits.mode==USR)||(cpu->CPSR.bits.mode==SYS)) { printf("ERROR1\n"); return 1; } oldmode = armcpu_switchMode(cpu, SYS); } registres = cpu->R; if(BIT15(i)) { if (BIT_N(i, REG_POS(i,16))) printf("error1_1\n"); u32 tmp = READ32(cpu->mem_if->data, start); registres[15] = tmp & (0XFFFFFFFC | (BIT0(tmp)<<1)); c += MMU_memAccessCycles(start); 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 (!BIT_N(i, REG_POS(i,16))) registres[REG_POS(i,16)] = start; if(BIT15(i)==0) { armcpu_switchMode(cpu, oldmode); return MMU_aluMemCycles(2, c); } SPSR = cpu->SPSR; armcpu_switchMode(cpu, SPSR.bits.mode); cpu->CPSR=SPSR; cpu->changeCPSR(); return MMU_aluMemCycles(2, c); } TEMPLATE static u32 FASTCALL OP_LDMDB2_W(const u32 i) { u32 c = 0; u32 oldmode = 0; u32 start = cpu->R[REG_POS(i,16)]; u32 * registres; Status_Reg SPSR; // emu_halt(); if(BIT15(i)==0) { if((cpu->CPSR.bits.mode==USR)||(cpu->CPSR.bits.mode==SYS)) { printf("ERROR1\n"); return 1; } oldmode = armcpu_switchMode(cpu, SYS); } registres = cpu->R; if(BIT15(i)) { if (BIT_N(i, REG_POS(i,16))) printf("error1_2\n"); u32 tmp; start -= 4; tmp = READ32(cpu->mem_if->data, start); c += MMU_memAccessCycles(start); registres[15] = tmp & (0XFFFFFFFC | (BIT0(tmp)<<1)); cpu->CPSR = cpu->SPSR; cpu->changeCPSR(); 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); if (!BIT_N(i, REG_POS(i,16))) registres[REG_POS(i,16)] = start; if(BIT15(i)==0) { armcpu_switchMode(cpu, oldmode); return MMU_aluMemCycles(2, c); } SPSR = cpu->SPSR; armcpu_switchMode(cpu, SPSR.bits.mode); cpu->CPSR=SPSR; cpu->changeCPSR(); return MMU_aluMemCycles(2, c); } //----------------------------------------------------------------------------- // STMIA / STMIB / STMDA / STMDB //----------------------------------------------------------------------------- TEMPLATE static u32 FASTCALL OP_STMIA(const u32 i) { u32 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_memAccessCycles(start); start += 4; } } return MMU_aluMemCycles(1, c); } TEMPLATE static u32 FASTCALL OP_STMIB(const u32 i) { u32 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_memAccessCycles(start); } } return MMU_aluMemCycles(1, c); } TEMPLATE static u32 FASTCALL OP_STMDA(const u32 i) { u32 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_memAccessCycles(start); start -= 4; } } return MMU_aluMemCycles(1, c); } TEMPLATE static u32 FASTCALL OP_STMDB(const u32 i) { u32 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_memAccessCycles(start); } } return MMU_aluMemCycles(1, c); } TEMPLATE static u32 FASTCALL OP_STMIA_W(const u32 i) { u32 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_memAccessCycles(start); start += 4; } } cpu->R[REG_POS(i,16)] = start; return MMU_aluMemCycles(1, c); } TEMPLATE static u32 FASTCALL OP_STMIB_W(const u32 i) { u32 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_memAccessCycles(start); } } cpu->R[REG_POS(i,16)] = start; return MMU_aluMemCycles(1, c); } TEMPLATE static u32 FASTCALL OP_STMDA_W(const u32 i) { u32 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_memAccessCycles(start); start -= 4; } } cpu->R[REG_POS(i,16)] = start; return MMU_aluMemCycles(1, c); } TEMPLATE static u32 FASTCALL OP_STMDB_W(const u32 i) { u32 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_memAccessCycles(start); } } cpu->R[REG_POS(i,16)] = start; return MMU_aluMemCycles(1, c); } TEMPLATE static u32 FASTCALL OP_STMIA2(const u32 i) { u32 c, b; u32 start; u32 oldmode; if(cpu->CPSR.bits.mode==USR) return 2; c = 0; start = cpu->R[REG_POS(i,16)]; oldmode = armcpu_switchMode(cpu, SYS); UNTESTEDOPCODELOG("Untested opcode: OP_STMIA2 \n"); for(b=0; b<16; b++) { if(BIT_N(i, b)) { WRITE32(cpu->mem_if->data, start, cpu->R[b]); c += MMU_memAccessCycles(start); start += 4; } } armcpu_switchMode(cpu, oldmode); return MMU_aluMemCycles(1, c); } TEMPLATE static u32 FASTCALL OP_STMIB2(const u32 i) { u32 c, b; u32 start; u32 oldmode; if(cpu->CPSR.bits.mode==USR) return 2; c = 0; start = cpu->R[REG_POS(i,16)]; oldmode = armcpu_switchMode(cpu, SYS); UNTESTEDOPCODELOG("Untested opcode: OP_STMIB2 \n"); for(b=0; b<16; b++) { if(BIT_N(i, b)) { start += 4; WRITE32(cpu->mem_if->data, start, cpu->R[b]); c += MMU_memAccessCycles(start); } } armcpu_switchMode(cpu, oldmode); return MMU_aluMemCycles(1, c); } TEMPLATE static u32 FASTCALL OP_STMDA2(const u32 i) { u32 c, b; u32 start; u32 oldmode; if(cpu->CPSR.bits.mode==USR) return 2; c = 0; start = cpu->R[REG_POS(i,16)]; oldmode = armcpu_switchMode(cpu, SYS); UNTESTEDOPCODELOG("Untested opcode: OP_STMDA2 \n"); for(b=0; b<16; b++) { if(BIT_N(i, 15-b)) { WRITE32(cpu->mem_if->data, start, cpu->R[15-b]); c += MMU_memAccessCycles(start); start -= 4; } } armcpu_switchMode(cpu, oldmode); return MMU_aluMemCycles(1, c); } TEMPLATE static u32 FASTCALL OP_STMDB2(const u32 i) { u32 c, b; u32 start; u32 oldmode; if(cpu->CPSR.bits.mode==USR) return 2; 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_memAccessCycles(start); } } armcpu_switchMode(cpu, oldmode); return MMU_aluMemCycles(1, c); } TEMPLATE static u32 FASTCALL OP_STMIA2_W(const u32 i) { u32 c, b; u32 start; u32 oldmode; if(cpu->CPSR.bits.mode==USR) return 2; c=0; start = cpu->R[REG_POS(i,16)]; oldmode = armcpu_switchMode(cpu, SYS); UNTESTEDOPCODELOG("Untested opcode: OP_STMIA2_W \n"); for(b=0; b<16; b++) { if(BIT_N(i, b)) { WRITE32(cpu->mem_if->data, start, cpu->R[b]); c += MMU_memAccessCycles(start); start += 4; } } cpu->R[REG_POS(i,16)] = start; armcpu_switchMode(cpu, oldmode); return MMU_aluMemCycles(1, c); } TEMPLATE static u32 FASTCALL OP_STMIB2_W(const u32 i) { u32 c, b; u32 start; u32 oldmode; if(cpu->CPSR.bits.mode==USR) return 2; 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_memAccessCycles(start); } } armcpu_switchMode(cpu, oldmode); cpu->R[REG_POS(i,16)] = start; return MMU_aluMemCycles(1, c); } TEMPLATE static u32 FASTCALL OP_STMDA2_W(const u32 i) { u32 c, b; u32 start; u32 oldmode; if(cpu->CPSR.bits.mode==USR) return 2; c = 0; start = cpu->R[REG_POS(i,16)]; oldmode = armcpu_switchMode(cpu, SYS); UNTESTEDOPCODELOG("Untested opcode: OP_STMDA2_W \n"); for(b=0; b<16; b++) { if(BIT_N(i, 15-b)) { WRITE32(cpu->mem_if->data, start, cpu->R[15-b]); c += MMU_memAccessCycles(start); start -= 4; } } cpu->R[REG_POS(i,16)] = start; armcpu_switchMode(cpu, oldmode); return MMU_aluMemCycles(1, c); } TEMPLATE static u32 FASTCALL OP_STMDB2_W(const u32 i) { u32 c, b; u32 start; u32 oldmode; if(cpu->CPSR.bits.mode==USR) return 2; c = 0; start = cpu->R[REG_POS(i,16)]; oldmode = armcpu_switchMode(cpu, SYS); UNTESTEDOPCODELOG("Untested opcode: OP_STMDB2_W \n"); 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_memAccessCycles(start); } } cpu->R[REG_POS(i,16)] = start; armcpu_switchMode(cpu, oldmode); return MMU_aluMemCycles(1, c); } //----------------------------------------------------------------------------- // LDRD / STRD //----------------------------------------------------------------------------- TEMPLATE static u32 FASTCALL OP_LDRD_STRD_POST_INDEX(const u32 i) { u32 Rd_num = REG_POS( i, 12); u32 addr = cpu->R[REG_POS(i,16)]; u32 index; //printf("%s POST\n", BIT5(i)?"STRD":"LDRD"); /* 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; u32 c = 0; 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]); c += MMU_memAccessCycles(addr); c += MMU_memAccessCycles(addr + 4); } else { cpu->R[Rd_num] = READ32(cpu->mem_if->data, addr); cpu->R[Rd_num + 1] = READ32(cpu->mem_if->data, addr + 4); c += MMU_memAccessCycles(addr); c += MMU_memAccessCycles(addr + 4); } } return MMU_aluMemCycles(3, c); } TEMPLATE static u32 FASTCALL OP_LDRD_STRD_OFFSET_PRE_INDEX(const u32 i) { u32 Rd_num = REG_POS( i, 12); u32 addr = cpu->R[REG_POS(i,16)]; u32 index; //printf("%s PRE\n", BIT5(i)?"STRD":"LDRD"); // 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; else addr -= index; u32 c = 0; 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]); c += MMU_memAccessCycles(addr); c += MMU_memAccessCycles(addr + 4); // W bit - writeback if ( BIT21(i)) cpu->R[REG_POS(i,16)] = addr; } else { // W bit - writeback if ( BIT21(i)) cpu->R[REG_POS(i,16)] = addr; cpu->R[Rd_num] = READ32(cpu->mem_if->data, addr); cpu->R[Rd_num + 1] = READ32(cpu->mem_if->data, addr + 4); c += MMU_memAccessCycles(addr); c += MMU_memAccessCycles(addr + 4); } } return MMU_aluMemCycles(3, c); } //----------------------------------------------------------------------------- // STC // the NDS has no coproc that responses to a STC, no feedback is given to the arm //----------------------------------------------------------------------------- TEMPLATE static u32 FASTCALL OP_STC_P_IMM_OFF(const u32 i) { //INFO("OP_STC_P_IMM_OFF\n"); return TRAPUNDEF(cpu); } TEMPLATE static u32 FASTCALL OP_STC_M_IMM_OFF(const u32 i) { //INFO("OP_STC_M_IMM_OFF\n"); return TRAPUNDEF(cpu); } TEMPLATE static u32 FASTCALL OP_STC_P_PREIND(const u32 i) { //INFO("OP_STC_P_PREIND\n"); return TRAPUNDEF(cpu); } TEMPLATE static u32 FASTCALL OP_STC_M_PREIND(const u32 i) { //INFO("OP_STC_M_PREIND\n"); return TRAPUNDEF(cpu); } TEMPLATE static u32 FASTCALL OP_STC_P_POSTIND(const u32 i) { //INFO("OP_STC_P_POSTIND: cp_num %i\n", (i>>8)&0x0F); return TRAPUNDEF(cpu); } TEMPLATE static u32 FASTCALL OP_STC_M_POSTIND(const u32 i) { //INFO("OP_STC_M_POSTIND\n"); return TRAPUNDEF(cpu); } TEMPLATE static u32 FASTCALL OP_STC_OPTION(const u32 i) { //INFO("OP_STC_OPTION\n"); return TRAPUNDEF(cpu); } //----------------------------------------------------------------------------- // LDC // the NDS has no coproc that responses to a LDC, no feedback is given to the arm //----------------------------------------------------------------------------- TEMPLATE static u32 FASTCALL OP_LDC_P_IMM_OFF(const u32 i) { //INFO("OP_LDC_P_IMM_OFF\n"); return TRAPUNDEF(cpu); } TEMPLATE static u32 FASTCALL OP_LDC_M_IMM_OFF(const u32 i) { //INFO("OP_LDC_M_IMM_OFF\n"); return TRAPUNDEF(cpu); } TEMPLATE static u32 FASTCALL OP_LDC_P_PREIND(const u32 i) { //INFO("OP_LDC_P_PREIND\n"); return TRAPUNDEF(cpu); } TEMPLATE static u32 FASTCALL OP_LDC_M_PREIND(const u32 i) { //INFO("OP_LDC_M_PREIND\n"); return TRAPUNDEF(cpu); } TEMPLATE static u32 FASTCALL OP_LDC_P_POSTIND(const u32 i) { //INFO("OP_LDC_P_POSTIND\n"); return TRAPUNDEF(cpu); } TEMPLATE static u32 FASTCALL OP_LDC_M_POSTIND(const u32 i) { //INFO("OP_LDC_M_POSTIND\n"); return TRAPUNDEF(cpu); } TEMPLATE static u32 FASTCALL OP_LDC_OPTION(const u32 i) { //INFO("OP_LDC_OPTION\n"); return TRAPUNDEF(cpu); } //----------------------------------------------------------------------------- // MCR / MRC //----------------------------------------------------------------------------- TEMPLATE static u32 FASTCALL OP_MCR(const u32 i) { u32 cpnum = REG_POS(i, 8); if(cpnum != 15) { //emu_halt(); //INFO("Stopped (OP_MCR) \n"); #ifdef DEBUG INFO("ARM%c: MCR P%i, 0, R%i, C%i, C%i, %i, %i (don't allocated coprocessor)\n", PROCNUM?'7':'9', cpnum, REG_POS(i, 12), REG_POS(i, 16), REG_POS(i, 0), (i>>21)&0x7, (i>>5)&0x7); #endif return 2; } cp15.moveARM2CP(cpu->R[REG_POS(i, 12)], REG_POS(i, 16), REG_POS(i, 0), (i>>21)&0x7, (i>>5)&0x7); return 2; } TEMPLATE static u32 FASTCALL OP_MRC(const u32 i) { //if (PROCNUM != 0) return 1; u32 cpnum = REG_POS(i, 8); if(cpnum != 15) { //emu_halt(); //INFO("Stopped (OP_MRC) \n"); #ifdef DEBUG INFO("ARM%c: MRC P%i, 0, R%i, C%i, C%i, %i, %i (don't allocated coprocessor)\n", PROCNUM?'7':'9', cpnum, REG_POS(i, 12), REG_POS(i, 16), REG_POS(i, 0), (i>>21)&0x7, (i>>5)&0x7); #endif return 2; } // ARM REF: //data = value from Coprocessor[cp_num] //if Rd is R15 then // N flag = data[31] // Z flag = data[30] // C flag = data[29] // V flag = data[28] //else /* Rd is not R15 */ // Rd = data u32 data = 0; cp15.moveCP2ARM(&data, REG_POS(i, 16), REG_POS(i, 0), (i>>21)&0x7, (i>>5)&0x7); if (REG_POS(i, 12) == 15) { cpu->CPSR.bits.N = BIT31(data); cpu->CPSR.bits.Z = BIT30(data); cpu->CPSR.bits.C = BIT29(data); cpu->CPSR.bits.V = BIT28(data); } else cpu->R[REG_POS(i, 12)] = data; //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 //----------------------------------------------------------------------------- TEMPLATE static u32 FASTCALL OP_SWI(const u32 i) { u32 swinum = (i>>16)&0xFF; //ideas-style debug prints (execute this SWI with the null terminated string address in R0) if(swinum==0xFC) { #ifdef DEBUG IdeasLog(cpu); #endif return 0; } //if the user has changed the intVector to point away from the nds bioses, //then it doesn't really make any sense to use the builtin SWI's since //the bios ones aren't getting called anyway bool bypassBuiltinSWI = (cpu->intVector == 0x00000000 && PROCNUM==0) || (cpu->intVector == 0xFFFF0000 && PROCNUM==1); //printf("ARM%c SWI %02X\t; %s\n", PROCNUM?'7':'9', (swinum & 0x1F), ARM_swi_names[PROCNUM][(swinum & 0x1F)]); if(cpu->swi_tab && !bypassBuiltinSWI) { swinum &= 0x1F; return cpu->swi_tab[swinum]() + 3; } else { /* 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->next_instruction; cpu->SPSR = tmp; /* save old CPSR as new SPSR */ cpu->CPSR.bits.T = 0; /* handle as ARM32 code */ cpu->CPSR.bits.I = 1; cpu->changeCPSR(); cpu->R[15] = cpu->intVector + 0x08; cpu->next_instruction = cpu->R[15]; return 3; } } //----------------------------------------------------------------------------- // BKPT //----------------------------------------------------------------------------- TEMPLATE static u32 FASTCALL OP_BKPT(const u32 i) { /* ARM-ref if (not overridden by debug hardware) R14_abt = address of BKPT instruction + 4 SPSR_abt = CPSR CPSR[4:0] = 0b10111 // Enter Abort mode CPSR[5] = 0 // Execute in ARM state // CPSR[6] is unchanged CPSR[7] = 1 // Disable normal interrupts CPSR[8] = 1 // Disable imprecise aborts - v6 only CPSR[9] = CP15_reg1_EEbit if high vectors configured then PC = 0xFFFF000C else PC = 0x0000000C */ /* static u32 last_bkpt = 0xFFFFFFFF; if(i != last_bkpt) printf("ARM OP_BKPT triggered\n"); last_bkpt = i; //this is not 100% correctly emulated, but it does the job cpu->next_instruction = cpu->instruct_adr; return 4; */ printf("ARM OP_BKPT triggered\n"); Status_Reg tmp = cpu->CPSR; armcpu_switchMode(cpu, ABT); // enter abt mode cpu->R[14] = cpu->instruct_adr + 4; cpu->SPSR = tmp; // save old CPSR as new SPSR cpu->CPSR.bits.T = 0; // handle as ARM32 code cpu->CPSR.bits.I = 1; cpu->changeCPSR(); cpu->R[15] = cpu->intVector + 0x0C; cpu->next_instruction = cpu->R[15]; return 4; } //----------------------------------------------------------------------------- // CDP //----------------------------------------------------------------------------- TEMPLATE static u32 FASTCALL OP_CDP(const u32 i) { //INFO("Stopped (OP_CDP) \n"); return TRAPUNDEF(cpu); } //----------------------------------------------------------------------------- // The End //----------------------------------------------------------------------------- const OpFunc arm_instructions_set[2][4096] = {{ #define TABDECL(x) x<0> #include "instruction_tabdef.inc" #undef TABDECL },{ #define TABDECL(x) x<1> #include "instruction_tabdef.inc" #undef TABDECL }}; #define TABDECL(x) #x const char* arm_instruction_names[4096] = { #include "instruction_tabdef.inc" }; #undef TABDECL desmume/src/utils/AsmJit/core/compilerfunc.cpp000664 001750 001750 00000010773 12755534123 022620 0ustar00sergiosergio000000 000000 // [AsmJit] // Complete JIT Assembler for C++ Language. // // [License] // Zlib - See COPYING file in this package. #define ASMJIT_EXPORTS // [Dependencies - AsmJit] #include "../core/assembler.h" #include "../core/compiler.h" #include "../core/compilerfunc.h" #include "../core/compileritem.h" #include "../core/intutil.h" #include "../core/logger.h" // [Api-Begin] #include "../core/apibegin.h" namespace AsmJit { // ============================================================================ // [AsmJit::CompilerFuncDecl - Construction / Destruction] // ============================================================================ CompilerFuncDecl::CompilerFuncDecl(Compiler* compiler) : CompilerItem(compiler, kCompilerItemFuncDecl), _entryTarget(NULL), _exitTarget(NULL), _end(NULL), _decl(NULL), _vars(NULL), _funcHints(0), _funcFlags(0), _funcCallStackSize(0) { } CompilerFuncDecl::~CompilerFuncDecl() { } // ============================================================================ // [AsmJit::CompilerFuncDecl - Hints] // ============================================================================ void CompilerFuncDecl::setHint(uint32_t hint, uint32_t value) { if (hint > 31) return; if (value) _funcHints |= IntUtil::maskFromIndex(hint); else _funcHints &= ~IntUtil::maskFromIndex(hint); } uint32_t CompilerFuncDecl::getHint(uint32_t hint) const { if (hint > 31) return 0; return (_funcHints & IntUtil::maskFromIndex(hint)) != 0; } // ============================================================================ // [AsmJit::CompilerFuncEnd - Construction / Destruction] // ============================================================================ CompilerFuncEnd::CompilerFuncEnd(Compiler* compiler, CompilerFuncDecl* func) : CompilerItem(compiler, kCompilerItemFuncEnd), _func(func) { } CompilerFuncEnd::~CompilerFuncEnd() { } // ============================================================================ // [AsmJit::CompilerFuncEnd - Interface] // ============================================================================ CompilerItem* CompilerFuncEnd::translate(CompilerContext& cc) { _isTranslated = true; return NULL; } // ============================================================================ // [AsmJit::CompilerFuncRet - Construction / Destruction] // ============================================================================ CompilerFuncRet::CompilerFuncRet(Compiler* compiler, CompilerFuncDecl* func, const Operand* first, const Operand* second) : CompilerItem(compiler, kCompilerItemFuncRet), _func(func) { if (first != NULL) _ret[0] = *first; if (second != NULL) _ret[1] = *second; } CompilerFuncRet::~CompilerFuncRet() { } // ============================================================================ // [AsmJit::CompilerFuncRet - Misc] // ============================================================================ bool CompilerFuncRet::mustEmitJump() const { // Iterate over next items until we found an item which emits a real instruction. CompilerItem* item = this->getNext(); while (item) { switch (item->getType()) { // Interesting item. case kCompilerItemEmbed: case kCompilerItemInst: case kCompilerItemFuncCall: case kCompilerItemFuncRet: return true; // Non-interesting item. case kCompilerItemComment: case kCompilerItemMark: case kCompilerItemAlign: case kCompilerItemHint: break; case kCompilerItemTarget: if (static_cast(item)->getLabel().getId() == getFunc()->getExitLabel().getId()) return false; break; // Invalid items - these items shouldn't be here. We are inside the // function, after prolog. case kCompilerItemFuncDecl: break; // We can't go forward from here. case kCompilerItemFuncEnd: return false; } item = item->getNext(); } return false; } // ============================================================================ // [AsmJit::CompilerFuncCall - Construction / Destruction] // ============================================================================ CompilerFuncCall::CompilerFuncCall(Compiler* compiler, CompilerFuncDecl* caller, const Operand* target) : CompilerItem(compiler, kCompilerItemFuncCall), _caller(caller), _decl(NULL), _args(NULL) { if (target != NULL) _target = *target; } CompilerFuncCall::~CompilerFuncCall() { } } // AsmJit namespace // [Api-Begin] #include "../core/apibegin.h" desmume/src/libretro-common/libco/sjlj.c000664 001750 001750 00000004537 12755534123 021456 0ustar00sergiosergio000000 000000 /* libco.sjlj (2008-01-28) author: Nach license: public domain */ /* * Note this was designed for UNIX systems. Based on ideas expressed in a paper * by Ralf Engelschall. * For SJLJ on other systems, one would want to rewrite springboard() and * co_create() and hack the jmb_buf stack pointer. */ #define LIBCO_C #include #include #include #include #ifdef __cplusplus extern "C" { #endif typedef struct { sigjmp_buf context; void (*coentry)(void); void *stack; } cothread_struct; static thread_local cothread_struct co_primary; static thread_local cothread_struct *creating, *co_running = 0; static void springboard(int ignored) { if(sigsetjmp(creating->context, 0)) co_running->coentry(); } cothread_t co_active(void) { if (!co_running) co_running = &co_primary; return (cothread_t)co_running; } cothread_t co_create(unsigned int size, void (*coentry)(void)) { if(!co_running) co_running = &co_primary; cothread_struct *thread = (cothread_struct*)malloc(sizeof(cothread_struct)); if(thread) { stack_t stack; stack_t old_stack; struct sigaction handler = {{0}}; struct sigaction old_handler = {{0}}; thread->coentry = thread->stack = 0; stack.ss_flags = 0; stack.ss_size = size; thread->stack = stack.ss_sp = malloc(size); if(stack.ss_sp && !sigaltstack(&stack, &old_stack)) { handler.sa_handler = springboard; handler.sa_flags = SA_ONSTACK; sigemptyset(&handler.sa_mask); creating = thread; if(!sigaction(SIGUSR1, &handler, &old_handler)) { if(!raise(SIGUSR1)) thread->coentry = coentry; sigaltstack(&old_stack, 0); sigaction(SIGUSR1, &old_handler, 0); } } if(thread->coentry != coentry) { co_delete(thread); thread = 0; } } return (cothread_t)thread; } void co_delete(cothread_t cothread) { if (cothread) { if(((cothread_struct*)cothread)->stack) free(((cothread_struct*)cothread)->stack); free(cothread); } } void co_switch(cothread_t cothread) { if (!sigsetjmp(co_running->context, 0)) { co_running = (cothread_struct*)cothread; siglongjmp(co_running->context, 1); } } #ifdef __cplusplus } #endif desmume/src/libretro-common/include/compat/strcasestr.h000664 001750 001750 00000003576 12755534123 024536 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2016 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (strcasestr.h). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef __LIBRETRO_SDK_COMPAT_STRCASESTR_H #define __LIBRETRO_SDK_COMPAT_STRCASESTR_H #include #if defined(RARCH_INTERNAL) && defined(HAVE_CONFIG_H) #include "../../../config.h" #endif #ifndef HAVE_STRCASESTR #include RETRO_BEGIN_DECLS /* Avoid possible naming collisions during link * since we prefer to use the actual name. */ #define strcasestr(haystack, needle) strcasestr_retro__(haystack, needle) char *strcasestr(const char *haystack, const char *needle); RETRO_END_DECLS #endif #endif desmume/src/addons/slot2_rumblepak.cpp000664 001750 001750 00000003212 12755534123 021216 0ustar00sergiosergio000000 000000 /* Copyright (C) 2009 CrazyMax Copyright (C) 2009-2013 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the this software. If not, see . */ #include "../slot2.h" void (*FeedbackON)(bool enable) = NULL; class Slot2_RumblePak : public ISlot2Interface { private: u16 old_val_rumble; public: virtual Slot2Info const* info() { static Slot2InfoSimple info("Rumble Pak", "NDS Rumble Pak (need joystick with Feedback)", 0x02); return &info; } virtual void connect() { old_val_rumble = 0; if (!FeedbackON) return; FeedbackON(false); } virtual void disconnect() { FeedbackON(false); } virtual void writeWord(u8 PROCNUM, u32 addr, u16 val) { if (!FeedbackON) return; if (old_val_rumble == val) return; old_val_rumble = val; if ((addr == 0x08000000) || (addr == 0x08001000)) FeedbackON(val); } virtual u8 readByte(u8 PROCNUM, u32 addr) { return (addr & 1)?0xFF:0xFD; }; virtual u16 readWord(u8 PROCNUM, u32 addr) { return 0xFFFD; }; virtual u32 readLong(u8 PROCNUM, u32 addr) { return 0xFFFDFFFD; }; }; ISlot2Interface* construct_Slot2_RumblePak() { return new Slot2_RumblePak(); }desmume/src/utils/AsmJit/core/stringutil.cpp000664 001750 001750 00000003225 12755534123 022330 0ustar00sergiosergio000000 000000 // [AsmJit] // Complete JIT Assembler for C++ Language. // // [License] // Zlib - See COPYING file in this package. #define ASMJIT_EXPORTS // [Dependencies - AsmJit] #include "../core/assert.h" #include "../core/stringutil.h" // [Api-Begin] #include "../core/apibegin.h" namespace AsmJit { // ============================================================================ // [AsmJit::StringUtil] // ============================================================================ static const char letters[] = "0123456789ABCDEF"; char* StringUtil::copy(char* dst, const char* src, size_t len) { if (src == NULL) return dst; if (len == kInvalidSize) { while (*src) *dst++ = *src++; } else { memcpy(dst, src, len); dst += len; } return dst; } char* StringUtil::fill(char* dst, const int c, size_t len) { memset(dst, c, len); return dst + len; } char* StringUtil::hex(char* dst, const uint8_t* src, size_t len) { for (size_t i = len; i; i--, dst += 2, src += 1) { dst[0] = letters[(src[0] >> 4) & 0xF]; dst[1] = letters[(src[0] ) & 0xF]; } return dst; } // Not too efficient, but this is mainly for debugging:) char* StringUtil::utoa(char* dst, uintptr_t i, size_t base) { ASMJIT_ASSERT(base <= 16); char buf[128]; char* p = buf + 128; do { uintptr_t b = i % base; *--p = letters[b]; i /= base; } while (i); return StringUtil::copy(dst, p, (size_t)(buf + 128 - p)); } char* StringUtil::itoa(char* dst, intptr_t i, size_t base) { if (i < 0) { *dst++ = '-'; i = -i; } return StringUtil::utoa(dst, (size_t)i, base); } } // AsmJit namespace // [Api-End] #include "../core/apiend.h" desmume/src/utils/AsmJit/core/stringbuilder.cpp000664 001750 001750 00000021666 12755534123 023012 0ustar00sergiosergio000000 000000 // [AsmJit] // Complete JIT Assembler for C++ Language. // // [License] // Zlib - See COPYING file in this package. #define ASMJIT_EXPORTS // [Dependencies - AsmJit] #include "../core/defs.h" #include "../core/intutil.h" #include "../core/stringbuilder.h" // [Dependencies - C] #include // [Api-Begin] #include "../core/apibegin.h" namespace AsmJit { // Should be placed in read-only memory. static const char StringBuilder_empty[4] = { 0 }; // ============================================================================ // [AsmJit::StringBuilder - Construction / Destruction] // ============================================================================ StringBuilder::StringBuilder() : _data(const_cast(StringBuilder_empty)), _length(0), _capacity(0), _canFree(false) { } StringBuilder::~StringBuilder() { if (_canFree) ASMJIT_FREE(_data); } // ============================================================================ // [AsmJit::StringBuilder - Prepare / Reserve] // ============================================================================ char* StringBuilder::prepare(uint32_t op, size_t len) { // -------------------------------------------------------------------------- // [Set] // -------------------------------------------------------------------------- if (op == kStringBuilderOpSet) { // We don't care here, but we can't return a NULL pointer since it indicates // failure in memory allocation. if (len == 0) { if (_data != StringBuilder_empty) _data[0] = 0; _length = 0; return _data; } if (_capacity < len) { if (len >= IntUtil::maxValue() - sizeof(uintptr_t) * 2) return NULL; size_t to = IntUtil::align(len, sizeof(uintptr_t)); if (to < 256 - sizeof(uintptr_t)) to = 256 - sizeof(uintptr_t); char* newData = static_cast(ASMJIT_MALLOC(to + sizeof(uintptr_t))); if (newData == NULL) { clear(); return NULL; } if (_canFree) ASMJIT_FREE(_data); _data = newData; _capacity = to + sizeof(uintptr_t) - 1; _canFree = true; } _data[len] = 0; _length = len; ASMJIT_ASSERT(_length <= _capacity); return _data; } // -------------------------------------------------------------------------- // [Append] // -------------------------------------------------------------------------- else { // We don't care here, but we can't return a NULL pointer since it indicates // failure in memory allocation. if (len == 0) return _data + _length; // Overflow. if (IntUtil::maxValue() - sizeof(uintptr_t) * 2 - _length < len) return NULL; size_t after = _length + len; if (_capacity < after) { size_t to = _capacity; if (to < 256) to = 256; while (to < 1024 * 1024 && to < after) { to *= 2; } if (to < after) { to = after; if (to < (IntUtil::maxValue() - 1024 * 32)) to = IntUtil::align(to, 1024 * 32); } to = IntUtil::align(to, sizeof(uintptr_t)); char* newData = static_cast(ASMJIT_MALLOC(to + sizeof(uintptr_t))); if (newData == NULL) return NULL; ::memcpy(newData, _data, _length); if (_canFree) ASMJIT_FREE(_data); _data = newData; _capacity = to + sizeof(uintptr_t) - 1; _canFree = true; } char* ret = _data + _length; _data[after] = 0; _length = after; ASMJIT_ASSERT(_length <= _capacity); return ret; } } bool StringBuilder::reserve(size_t to) { if (_capacity >= to) return true; if (to >= IntUtil::maxValue() - sizeof(uintptr_t) * 2) return false; to = IntUtil::align(to, sizeof(uintptr_t)); char* newData = static_cast(ASMJIT_MALLOC(to + sizeof(uintptr_t))); if (newData == NULL) return false; ::memcpy(newData, _data, _length + 1); if (_canFree) ASMJIT_FREE(_data); _data = newData; _capacity = to + sizeof(uintptr_t) - 1; _canFree = true; return true; } // ============================================================================ // [AsmJit::StringBuilder - Clear] // ============================================================================ void StringBuilder::clear() { if (_data != StringBuilder_empty) _data[0] = 0; _length = 0; } // ============================================================================ // [AsmJit::StringBuilder - Methods] // ============================================================================ bool StringBuilder::_opString(uint32_t op, const char* str, size_t len) { if (len == kInvalidSize) len = ::strlen(str); char* p = prepare(op, len); if (p == NULL) return false; ::memcpy(p, str, len); return true; } bool StringBuilder::_opChars(uint32_t op, char c, size_t len) { char* p = prepare(op, len); if (p == NULL) return false; ::memset(p, c, len); return true; } static const char StringBuilder_numbers[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; bool StringBuilder::_opNumber(uint32_t op, uint64_t i, uint32_t base, size_t width, uint32_t flags) { if (base < 2 || base > 36) base = 10; char buf[128]; char* p = buf + ASMJIT_ARRAY_SIZE(buf); uint64_t orig = i; char sign = '\0'; // -------------------------------------------------------------------------- // [Sign] // -------------------------------------------------------------------------- if ((flags & kStringBuilderNumSigned) != 0 && static_cast(i) < 0) { i = static_cast(-static_cast(i)); sign = '-'; } else if ((flags & kStringBuilderNumShowSign) != 0) { sign = '+'; } else if ((flags & kStringBuilderNumShowSpace) != 0) { sign = ' '; } // -------------------------------------------------------------------------- // [Number] // -------------------------------------------------------------------------- do { uint64_t d = i / base; uint64_t r = i % base; *--p = StringBuilder_numbers[r]; i = d; } while (i); size_t numberLength = (size_t)(buf + ASMJIT_ARRAY_SIZE(buf) - p); // -------------------------------------------------------------------------- // [Alternate Form] // -------------------------------------------------------------------------- if ((flags & kStringBuilderNumAlternate) != 0) { if (base == 8) { if (orig != 0) *--p = '0'; } if (base == 16) { *--p = 'x'; *--p = '0'; } } // -------------------------------------------------------------------------- // [Width] // -------------------------------------------------------------------------- if (sign != 0) *--p = sign; if (width > 256) width = 256; if (width <= numberLength) width = 0; else width -= numberLength; // -------------------------------------------------------------------------- // Write] // -------------------------------------------------------------------------- size_t prefixLength = (size_t)(buf + ASMJIT_ARRAY_SIZE(buf) - p) - numberLength; char* data = prepare(op, prefixLength + width + numberLength); if (data == NULL) return false; ::memcpy(data, p, prefixLength); data += prefixLength; ::memset(data, '0', width); data += width; ::memcpy(data, p + prefixLength, numberLength); return true; } bool StringBuilder::_opHex(uint32_t op, const void* data, size_t len) { if (len >= IntUtil::maxValue() / 2) return false; char* dst = prepare(op, len); if (dst == NULL) return false; const char* src = static_cast(data); for (size_t i = 0; i < len; i++, dst += 2, src += 1) { dst[0] = StringBuilder_numbers[(src[0] >> 4) & 0xF]; dst[1] = StringBuilder_numbers[(src[0] ) & 0xF]; } return true; } bool StringBuilder::_opVFormat(uint32_t op, const char* fmt, va_list ap) { char buf[1024]; vsnprintf(buf, ASMJIT_ARRAY_SIZE(buf), fmt, ap); buf[ASMJIT_ARRAY_SIZE(buf) - 1] = '\0'; return _opString(op, buf); } bool StringBuilder::setFormat(const char* fmt, ...) { bool result; va_list ap; va_start(ap, fmt); result = _opVFormat(kStringBuilderOpSet, fmt, ap); va_end(ap); return result; } bool StringBuilder::appendFormat(const char* fmt, ...) { bool result; va_list ap; va_start(ap, fmt); result = _opVFormat(kStringBuilderOpAppend, fmt, ap); va_end(ap); return result; } bool StringBuilder::eq(const char* str, size_t len) const { const char* aData = _data; const char* bData = str; size_t aLength = _length; size_t bLength = len; if (bLength == kInvalidSize) { size_t i; for (i = 0; i < aLength; i++) { if (aData[i] != bData[i] || bData[i] == 0) return false; } return bData[i] == 0; } else { if (aLength != bLength) return false; return ::memcmp(aData, bData, aLength) == 0; } } } // AsmJit namespace // [Api-End] #include "../core/apiend.h" desmume/src/encrypt.h000664 001750 001750 00000003003 12755534123 015770 0ustar00sergiosergio000000 000000 /* Copyright (C) 2009-2013 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the this software. If not, see . */ #ifndef _ENCRYPT_H_ #define _ENCRYPT_H_ #include "types.h" #include struct _KEY1 { _KEY1(const u8 *inKeyBufPtr) { if (keyBuf) delete keyBuf; keyBuf = new u32 [0x412]; memset(keyBuf, 0x00, 0x412 * sizeof(u32)); memset(&keyCode[0], 0, sizeof(keyCode)); this->keyBufPtr = inKeyBufPtr; } ~_KEY1() { if (keyBuf) { delete keyBuf; keyBuf = NULL; } } u32 *keyBuf; u32 keyCode[3]; const u8 *keyBufPtr; void init(u32 idcode, u8 level, u8 modulo); void applyKeycode(u8 modulo); void decrypt(u32 *ptr); void encrypt(u32 *ptr); }; struct _KEY2 { private: u64 seed0; u64 seed1; u64 x; u64 y; u64 bitsReverse39(u64 key); public: _KEY2() : seed0(0x58C56DE0E8ULL), seed1(0x5C879B9B05ULL) {} void applySeed(u8 PROCNUM); u8 apply(u8 data); }; #endifdesmume/src/libretro-common/include/file/config_file.h000664 001750 001750 00000014745 12755534123 024241 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2015 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (config_file.h). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef __LIBRETRO_SDK_CONFIG_FILE_H #define __LIBRETRO_SDK_CONFIG_FILE_H #include RETRO_BEGIN_DECLS #include #include #include #include #define CONFIG_GET_BOOL_BASE(conf, base, var, key) do { \ bool tmp = false; \ if (config_get_bool(conf, key, &tmp)) \ base->var = tmp; \ } while(0) #define CONFIG_GET_INT_BASE(conf, base, var, key) do { \ int tmp = 0; \ if (config_get_int(conf, key, &tmp)) \ base->var = tmp; \ } while(0) #define CONFIG_GET_FLOAT_BASE(conf, base, var, key) do { \ float tmp = 0.0f; \ if (config_get_float(conf, key, &tmp)) \ base->var = tmp; \ } while(0) typedef struct config_file config_file_t; /* Config file format * - # are treated as comments. Rest of the line is ignored. * - Format is: key = value. There can be as many spaces as you like in-between. * - Value can be wrapped inside "" for multiword strings. (foo = "hai u") * - #include includes a config file in-place. * * Path is relative to where config file was loaded unless an absolute path is chosen. * Key/value pairs from an #include are read-only, and cannot be modified. */ /* Loads a config file. Returns NULL if file doesn't exist. * NULL path will create an empty config file. */ config_file_t *config_file_new(const char *path); /* Load a config file from a string. */ config_file_t *config_file_new_from_string(const char *from_string); /* Frees config file. */ void config_file_free(config_file_t *conf); /* Loads a new config, and appends its data to conf. * The key-value pairs of the new config file takes priority over the old. */ bool config_append_file(config_file_t *conf, const char *path); /* All extract functions return true when value is valid and exists. * Returns false otherwise. */ bool config_entry_exists(config_file_t *conf, const char *entry); struct config_entry_list; struct config_file_entry { const char *key; const char *value; /* Used intentionally. Opaque here. */ const struct config_entry_list *next; }; bool config_get_entry_list_head(config_file_t *conf, struct config_file_entry *entry); bool config_get_entry_list_next(struct config_file_entry *entry); /* Extracts a double from config file. */ bool config_get_double(config_file_t *conf, const char *entry, double *in); /* Extracts a float from config file. */ bool config_get_float(config_file_t *conf, const char *entry, float *in); /* Extracts an int from config file. */ bool config_get_int(config_file_t *conf, const char *entry, int *in); /* Extracts an uint from config file. */ bool config_get_uint(config_file_t *conf, const char *entry, unsigned *in); #if defined(__STDC_VERSION__) && __STDC_VERSION__>=199901L /* Extracts an uint64 from config file. */ bool config_get_uint64(config_file_t *conf, const char *entry, uint64_t *in); #endif /* Extracts an unsigned int from config file treating input as hex. */ bool config_get_hex(config_file_t *conf, const char *entry, unsigned *in); /* Extracts a single char. If value consists of several chars, * this is an error. */ bool config_get_char(config_file_t *conf, const char *entry, char *in); /* Extracts an allocated string in *in. This must be free()-d if * this function succeeds. */ bool config_get_string(config_file_t *conf, const char *entry, char **in); /* Extracts a string to a preallocated buffer. Avoid memory allocation. */ bool config_get_array(config_file_t *conf, const char *entry, char *s, size_t len); /* Extracts a string to a preallocated buffer. Avoid memory allocation. * Recognized magic like ~/. Similar to config_get_array() otherwise. */ bool config_get_path(config_file_t *conf, const char *entry, char *s, size_t len); /* Extracts a string to a preallocated buffer. Avoid memory allocation. */ bool config_get_config_path(config_file_t *conf, char *s, size_t len); /* Extracts a boolean from config. * Valid boolean true are "true" and "1". Valid false are "false" and "0". * Other values will be treated as an error. */ bool config_get_bool(config_file_t *conf, const char *entry, bool *in); /* Setters. Similar to the getters. * Will not write to entry if the entry was obtained from an #include. */ void config_set_double(config_file_t *conf, const char *entry, double value); void config_set_float(config_file_t *conf, const char *entry, float value); void config_set_int(config_file_t *conf, const char *entry, int val); void config_set_hex(config_file_t *conf, const char *entry, unsigned val); void config_set_uint64(config_file_t *conf, const char *entry, uint64_t val); void config_set_char(config_file_t *conf, const char *entry, char val); void config_set_string(config_file_t *conf, const char *entry, const char *val); void config_unset(config_file_t *conf, const char *key); void config_set_path(config_file_t *conf, const char *entry, const char *val); void config_set_bool(config_file_t *conf, const char *entry, bool val); /* Write the current config to a file. */ bool config_file_write(config_file_t *conf, const char *path); /* Dump the current config to an already opened file. * Does not close the file. */ void config_file_dump(config_file_t *conf, FILE *file); RETRO_END_DECLS #endif desmume/src/libretro-common/include/gfx/scaler/scaler_int.h000664 001750 001750 00000003552 12755534123 025230 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2016 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (scaler_int.h). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef __LIBRETRO_SDK_SCALER_INT_H__ #define __LIBRETRO_SDK_SCALER_INT_H__ #include void scaler_argb8888_vert(const struct scaler_ctx *ctx, void *output, int stride); void scaler_argb8888_horiz(const struct scaler_ctx *ctx, const void *input, int stride); void scaler_argb8888_point_special(const struct scaler_ctx *ctx, void *output, const void *input, int out_width, int out_height, int in_width, int in_height, int out_stride, int in_stride); #endif desmume/src/utils/AsmJit/x86/x86func.cpp000664 001750 001750 00000047446 12755534123 021137 0ustar00sergiosergio000000 000000 // [AsmJit] // Complete JIT Assembler for C++ Language. // // [License] // Zlib - See COPYING file in this package. #define ASMJIT_EXPORTS // [Dependencies - AsmJit] #include "../core/assert.h" #include "../core/intutil.h" #include "../core/stringutil.h" #include "../x86/x86defs.h" #include "../x86/x86func.h" #include "../x86/x86util.h" // [Api-Begin] #include "../core/apibegin.h" namespace AsmJit { // ============================================================================ // [AsmJit::X86FuncDecl - Accessors] // ============================================================================ uint32_t X86FuncDecl::findArgumentByRegCode(uint32_t regCode) const { uint32_t type = regCode & kRegTypeMask; uint32_t idx = regCode & kRegIndexMask; uint32_t clazz; switch (type) { case kX86RegTypeGpd: case kX86RegTypeGpq: clazz = kX86VarClassGp; break; case kX86RegTypeX87: clazz = kX86VarClassX87; break; case kX86RegTypeMm: clazz = kX86VarClassMm; break; case kX86RegTypeXmm: clazz = kX86VarClassXmm; break; default: return kInvalidValue; } for (uint32_t i = 0; i < _argumentsCount; i++) { const FuncArg& arg = _arguments[i]; if (arg.getRegIndex() == idx && (X86Util::getVarClassFromVarType(arg.getVarType()) & clazz) != 0) return i; } return kInvalidValue; } // ============================================================================ // [AsmJit::X86FuncDecl - SetPrototype - InitCallingConvention] // ============================================================================ static void X86FuncDecl_initCallingConvention(X86FuncDecl* self, uint32_t convention) { uint32_t i; // -------------------------------------------------------------------------- // [Inir] // -------------------------------------------------------------------------- self->_convention = convention; self->_calleePopsStack = false; self->_argumentsDirection = kFuncArgsRTL; for (i = 0; i < ASMJIT_ARRAY_SIZE(self->_gpList); i++) self->_gpList[i] = kRegIndexInvalid; for (i = 0; i < ASMJIT_ARRAY_SIZE(self->_xmmList); i++) self->_xmmList[i] = kRegIndexInvalid; self->_gpListMask = 0x0; self->_mmListMask = 0x0; self->_xmmListMask = 0x0; self->_gpPreservedMask = 0x0; self->_mmPreservedMask = 0x0; self->_xmmPreservedMask = 0x0; // -------------------------------------------------------------------------- // [X86 Calling Conventions] // -------------------------------------------------------------------------- #if defined(ASMJIT_X86) self->_gpPreservedMask = static_cast( IntUtil::maskFromIndex(kX86RegIndexEbx) | IntUtil::maskFromIndex(kX86RegIndexEsp) | IntUtil::maskFromIndex(kX86RegIndexEbp) | IntUtil::maskFromIndex(kX86RegIndexEsi) | IntUtil::maskFromIndex(kX86RegIndexEdi)); self->_xmmPreservedMask = 0; switch (convention) { // ------------------------------------------------------------------------ // [CDecl] // ------------------------------------------------------------------------ case kX86FuncConvCDecl: break; // ------------------------------------------------------------------------ // [StdCall] // ------------------------------------------------------------------------ case kX86FuncConvStdCall: self->_calleePopsStack = true; break; // ------------------------------------------------------------------------ // [MS-ThisCall] // ------------------------------------------------------------------------ case kX86FuncConvMsThisCall: self->_calleePopsStack = true; self->_gpList[0] = kX86RegIndexEcx; self->_gpListMask = static_cast( IntUtil::maskFromIndex(kX86RegIndexEcx)); break; // ------------------------------------------------------------------------ // [MS-FastCall] // ------------------------------------------------------------------------ case kX86FuncConvMsFastCall: self->_calleePopsStack = true; self->_gpList[0] = kX86RegIndexEcx; self->_gpList[1] = kX86RegIndexEdx; self->_gpListMask = static_cast( IntUtil::maskFromIndex(kX86RegIndexEcx) | IntUtil::maskFromIndex(kX86RegIndexEdx)); break; // ------------------------------------------------------------------------ // [Borland-FastCall] // ------------------------------------------------------------------------ case kX86FuncConvBorlandFastCall: self->_calleePopsStack = true; self->_argumentsDirection = kFuncArgsLTR; self->_gpList[0] = kX86RegIndexEax; self->_gpList[1] = kX86RegIndexEdx; self->_gpList[2] = kX86RegIndexEcx; self->_gpListMask = static_cast( IntUtil::maskFromIndex(kX86RegIndexEax) | IntUtil::maskFromIndex(kX86RegIndexEdx) | IntUtil::maskFromIndex(kX86RegIndexEcx)); break; // ------------------------------------------------------------------------ // [Gcc-FastCall] // ------------------------------------------------------------------------ case kX86FuncConvGccFastCall: self->_calleePopsStack = true; self->_gpList[0] = kX86RegIndexEcx; self->_gpList[1] = kX86RegIndexEdx; self->_gpListMask = static_cast( IntUtil::maskFromIndex(kX86RegIndexEcx) | IntUtil::maskFromIndex(kX86RegIndexEdx)); break; // ------------------------------------------------------------------------ // [Gcc-Regparm(1)] // ------------------------------------------------------------------------ case kX86FuncConvGccRegParm1: self->_calleePopsStack = false; self->_gpList[0] = kX86RegIndexEax; self->_gpListMask = static_cast( IntUtil::maskFromIndex(kX86RegIndexEax)); break; // ------------------------------------------------------------------------ // [Gcc-Regparm(2)] // ------------------------------------------------------------------------ case kX86FuncConvGccRegParm2: self->_calleePopsStack = false; self->_gpList[0] = kX86RegIndexEax; self->_gpList[1] = kX86RegIndexEdx; self->_gpListMask = static_cast( IntUtil::maskFromIndex(kX86RegIndexEax) | IntUtil::maskFromIndex(kX86RegIndexEdx)); break; // ------------------------------------------------------------------------ // [Gcc-Regparm(3)] // ------------------------------------------------------------------------ case kX86FuncConvGccRegParm3: self->_calleePopsStack = false; self->_gpList[0] = kX86RegIndexEax; self->_gpList[1] = kX86RegIndexEdx; self->_gpList[2] = kX86RegIndexEcx; self->_gpListMask = static_cast( IntUtil::maskFromIndex(kX86RegIndexEax) | IntUtil::maskFromIndex(kX86RegIndexEdx) | IntUtil::maskFromIndex(kX86RegIndexEcx)); break; // ------------------------------------------------------------------------ // [Illegal] // ------------------------------------------------------------------------ default: // Illegal calling convention. ASMJIT_ASSERT(0); } #endif // ASMJIT_X86 // -------------------------------------------------------------------------- // [X64 Calling Conventions] // -------------------------------------------------------------------------- #if defined(ASMJIT_X64) switch (convention) { // ------------------------------------------------------------------------ // [X64-Windows] // ------------------------------------------------------------------------ case kX86FuncConvX64W: self->_gpList[0] = kX86RegIndexRcx; self->_gpList[1] = kX86RegIndexRdx; self->_gpList[2] = kX86RegIndexR8; self->_gpList[3] = kX86RegIndexR9; self->_xmmList[0] = kX86RegIndexXmm0; self->_xmmList[1] = kX86RegIndexXmm1; self->_xmmList[2] = kX86RegIndexXmm2; self->_xmmList[3] = kX86RegIndexXmm3; self->_gpListMask = static_cast( IntUtil::maskFromIndex(kX86RegIndexRcx ) | IntUtil::maskFromIndex(kX86RegIndexRdx ) | IntUtil::maskFromIndex(kX86RegIndexR8 ) | IntUtil::maskFromIndex(kX86RegIndexR9 )); self->_xmmListMask = static_cast( IntUtil::maskFromIndex(kX86RegIndexXmm0 ) | IntUtil::maskFromIndex(kX86RegIndexXmm1 ) | IntUtil::maskFromIndex(kX86RegIndexXmm2 ) | IntUtil::maskFromIndex(kX86RegIndexXmm3 )); self->_gpPreservedMask = static_cast( IntUtil::maskFromIndex(kX86RegIndexRbx ) | IntUtil::maskFromIndex(kX86RegIndexRsp ) | IntUtil::maskFromIndex(kX86RegIndexRbp ) | IntUtil::maskFromIndex(kX86RegIndexRsi ) | IntUtil::maskFromIndex(kX86RegIndexRdi ) | IntUtil::maskFromIndex(kX86RegIndexR12 ) | IntUtil::maskFromIndex(kX86RegIndexR13 ) | IntUtil::maskFromIndex(kX86RegIndexR14 ) | IntUtil::maskFromIndex(kX86RegIndexR15 )); self->_xmmPreservedMask = static_cast( IntUtil::maskFromIndex(kX86RegIndexXmm6 ) | IntUtil::maskFromIndex(kX86RegIndexXmm7 ) | IntUtil::maskFromIndex(kX86RegIndexXmm8 ) | IntUtil::maskFromIndex(kX86RegIndexXmm9 ) | IntUtil::maskFromIndex(kX86RegIndexXmm10) | IntUtil::maskFromIndex(kX86RegIndexXmm11) | IntUtil::maskFromIndex(kX86RegIndexXmm12) | IntUtil::maskFromIndex(kX86RegIndexXmm13) | IntUtil::maskFromIndex(kX86RegIndexXmm14) | IntUtil::maskFromIndex(kX86RegIndexXmm15)); break; // ------------------------------------------------------------------------ // [X64-Unix] // ------------------------------------------------------------------------ case kX86FuncConvX64U: self->_gpList[0] = kX86RegIndexRdi; self->_gpList[1] = kX86RegIndexRsi; self->_gpList[2] = kX86RegIndexRdx; self->_gpList[3] = kX86RegIndexRcx; self->_gpList[4] = kX86RegIndexR8; self->_gpList[5] = kX86RegIndexR9; self->_xmmList[0] = kX86RegIndexXmm0; self->_xmmList[1] = kX86RegIndexXmm1; self->_xmmList[2] = kX86RegIndexXmm2; self->_xmmList[3] = kX86RegIndexXmm3; self->_xmmList[4] = kX86RegIndexXmm4; self->_xmmList[5] = kX86RegIndexXmm5; self->_xmmList[6] = kX86RegIndexXmm6; self->_xmmList[7] = kX86RegIndexXmm7; self->_gpListMask = static_cast( IntUtil::maskFromIndex(kX86RegIndexRdi ) | IntUtil::maskFromIndex(kX86RegIndexRsi ) | IntUtil::maskFromIndex(kX86RegIndexRdx ) | IntUtil::maskFromIndex(kX86RegIndexRcx ) | IntUtil::maskFromIndex(kX86RegIndexR8 ) | IntUtil::maskFromIndex(kX86RegIndexR9 )); self->_xmmListMask = static_cast( IntUtil::maskFromIndex(kX86RegIndexXmm0 ) | IntUtil::maskFromIndex(kX86RegIndexXmm1 ) | IntUtil::maskFromIndex(kX86RegIndexXmm2 ) | IntUtil::maskFromIndex(kX86RegIndexXmm3 ) | IntUtil::maskFromIndex(kX86RegIndexXmm4 ) | IntUtil::maskFromIndex(kX86RegIndexXmm5 ) | IntUtil::maskFromIndex(kX86RegIndexXmm6 ) | IntUtil::maskFromIndex(kX86RegIndexXmm7 )); self->_gpPreservedMask = static_cast( IntUtil::maskFromIndex(kX86RegIndexRbx ) | IntUtil::maskFromIndex(kX86RegIndexRsp ) | IntUtil::maskFromIndex(kX86RegIndexRbp ) | IntUtil::maskFromIndex(kX86RegIndexR12 ) | IntUtil::maskFromIndex(kX86RegIndexR13 ) | IntUtil::maskFromIndex(kX86RegIndexR14 ) | IntUtil::maskFromIndex(kX86RegIndexR15 )); break; // ------------------------------------------------------------------------ // [Illegal] // ------------------------------------------------------------------------ default: // Illegal calling convention. ASMJIT_ASSERT(0); } #endif // ASMJIT_X64 } // ============================================================================ // [AsmJit::X86FuncDecl - SetPrototype - InitDefinition] // ============================================================================ static void X86FuncDecl_initDefinition(X86FuncDecl* self, uint32_t returnType, const uint32_t* argumentsData, uint32_t argumentsCount) { ASMJIT_ASSERT(argumentsCount <= kFuncArgsMax); // -------------------------------------------------------------------------- // [Init] // -------------------------------------------------------------------------- int32_t i = 0; int32_t gpPos = 0; int32_t xmmPos = 0; int32_t stackOffset = 0; self->_returnType = returnType; self->_argumentsCount = static_cast(argumentsCount); while (i < static_cast(argumentsCount)) { FuncArg& arg = self->_arguments[i]; arg._varType = static_cast(argumentsData[i]); arg._regIndex = kRegIndexInvalid; arg._stackOffset = kFuncStackInvalid; i++; } while (i < kFuncArgsMax) { FuncArg& arg = self->_arguments[i]; arg.reset(); i++; } self->_argumentsStackSize = 0; self->_gpArgumentsMask = 0x0; self->_mmArgumentsMask = 0x0; self->_xmmArgumentsMask = 0x0; if (self->_argumentsCount == 0) return; // -------------------------------------------------------------------------- // [X86 Calling Conventions (32-bit)] // -------------------------------------------------------------------------- #if defined(ASMJIT_X86) // Register arguments (Integer), always left-to-right. for (i = 0; i != argumentsCount; i++) { FuncArg& arg = self->_arguments[i]; uint32_t varType = arg.getVarType(); if (X86Util::isVarTypeInt(varType) && gpPos < 16 && self->_gpList[gpPos] != kRegIndexInvalid) { arg._regIndex = self->_gpList[gpPos++]; self->_gpArgumentsMask |= static_cast(IntUtil::maskFromIndex(arg.getRegIndex())); } } // Stack arguments. int32_t iStart = static_cast(argumentsCount - 1); int32_t iEnd = -1; int32_t iStep = -1; if (self->_argumentsDirection == kFuncArgsLTR) { iStart = 0; iEnd = static_cast(argumentsCount); iStep = 1; } for (i = iStart; i != iEnd; i += iStep) { FuncArg& arg = self->_arguments[i]; uint32_t varType = arg.getVarType(); if (arg.hasRegIndex()) continue; if (X86Util::isVarTypeInt(varType)) { stackOffset -= 4; arg._stackOffset = static_cast(stackOffset); } else if (X86Util::isVarTypeFloat(varType)) { int32_t size = static_cast(x86VarInfo[varType].getSize()); stackOffset -= size; arg._stackOffset = static_cast(stackOffset); } } #endif // ASMJIT_X86 // -------------------------------------------------------------------------- // [X64 Calling Conventions (64-bit)] // -------------------------------------------------------------------------- #if defined(ASMJIT_X64) // Windows 64-bit specific. if (self->_convention == kX86FuncConvX64W) { int32_t max = argumentsCount < 4 ? argumentsCount : 4; // Register arguments (Integer / FP), always left-to-right. for (i = 0; i != max; i++) { FuncArg& arg = self->_arguments[i]; uint32_t varType = arg.getVarType(); if (X86Util::isVarTypeInt(varType)) { arg._regIndex = self->_gpList[i]; self->_gpArgumentsMask |= static_cast(IntUtil::maskFromIndex(arg.getRegIndex())); } else if (X86Util::isVarTypeFloat(varType)) { arg._regIndex = self->_xmmList[i]; self->_xmmArgumentsMask |= static_cast(IntUtil::maskFromIndex(arg.getRegIndex())); } } // Stack arguments (always right-to-left). for (i = argumentsCount - 1; i != -1; i--) { FuncArg& arg = self->_arguments[i]; uint32_t varType = arg.getVarType(); if (arg.isAssigned()) continue; if (X86Util::isVarTypeInt(varType)) { stackOffset -= 8; // Always 8 bytes. arg._stackOffset = stackOffset; } else if (X86Util::isVarTypeFloat(varType)) { int32_t size = static_cast(x86VarInfo[varType].getSize()); stackOffset -= size; arg._stackOffset = stackOffset; } } // 32 bytes shadow space (X64W calling convention specific). stackOffset -= 4 * 8; } // Linux/Unix 64-bit (AMD64 calling convention). else { // Register arguments (Integer), always left-to-right. for (i = 0; i != static_cast(argumentsCount); i++) { FuncArg& arg = self->_arguments[i]; uint32_t varType = arg.getVarType(); if (X86Util::isVarTypeInt(varType) && gpPos < 32 && self->_gpList[gpPos] != kRegIndexInvalid) { arg._regIndex = self->_gpList[gpPos++]; self->_gpArgumentsMask |= static_cast(IntUtil::maskFromIndex(arg.getRegIndex())); } } // Register arguments (FP), always left-to-right. for (i = 0; i != static_cast(argumentsCount); i++) { FuncArg& arg = self->_arguments[i]; uint32_t varType = arg.getVarType(); if (X86Util::isVarTypeFloat(varType)) { arg._regIndex = self->_xmmList[xmmPos++]; self->_xmmArgumentsMask |= static_cast(IntUtil::maskFromIndex(arg.getRegIndex())); } } // Stack arguments. for (i = argumentsCount - 1; i != -1; i--) { FuncArg& arg = self->_arguments[i]; uint32_t varType = arg.getVarType(); if (arg.isAssigned()) continue; if (X86Util::isVarTypeInt(varType)) { stackOffset -= 8; arg._stackOffset = static_cast(stackOffset); } else if (X86Util::isVarTypeFloat(varType)) { int32_t size = (int32_t)x86VarInfo[varType].getSize(); stackOffset -= size; arg._stackOffset = static_cast(stackOffset); } } } #endif // ASMJIT_X64 // Modify stack offset (all function parameters will be in positive stack // offset that is never zero). for (i = 0; i < (int32_t)argumentsCount; i++) { FuncArg& arg = self->_arguments[i]; if (!arg.hasRegIndex()) { arg._stackOffset += static_cast(static_cast(sizeof(uintptr_t)) - stackOffset); } } self->_argumentsStackSize = (uint32_t)(-stackOffset); } void X86FuncDecl::setPrototype(uint32_t convention, uint32_t returnType, const uint32_t* arguments, uint32_t argumentsCount) { // Limit maximum function arguments to kFuncArgsMax. if (argumentsCount > kFuncArgsMax) argumentsCount = kFuncArgsMax; X86FuncDecl_initCallingConvention(this, convention); X86FuncDecl_initDefinition(this, returnType, arguments, argumentsCount); } // ============================================================================ // [AsmJit::X86FuncDecl - Reset] // ============================================================================ void X86FuncDecl::reset() { uint32_t i; // -------------------------------------------------------------------------- // [Core] // -------------------------------------------------------------------------- _returnType = kVarTypeInvalid; _argumentsCount = 0; _reserved0[0] = 0; _reserved0[1] = 0; for (i = 0; i < ASMJIT_ARRAY_SIZE(_arguments); i++) _arguments[i].reset(); _argumentsStackSize = 0; _gpArgumentsMask = 0x0; _mmArgumentsMask = 0x0; _xmmArgumentsMask = 0x0; // -------------------------------------------------------------------------- // [Convention] // -------------------------------------------------------------------------- _convention = kFuncConvNone; _calleePopsStack = false; _argumentsDirection = kFuncArgsRTL; _reserved1 = 0; for (i = 0; i < ASMJIT_ARRAY_SIZE(_gpList); i++) _gpList[i] = kRegIndexInvalid; for (i = 0; i < ASMJIT_ARRAY_SIZE(_xmmList); i++) _xmmList[i] = kRegIndexInvalid; _gpListMask = 0x0; _mmListMask = 0x0; _xmmListMask = 0x0; _gpPreservedMask = 0x0; _mmPreservedMask = 0x0; _xmmPreservedMask = 0x0; } } // AsmJit namespace // [Api-Begin] #include "../core/apiend.h" desmume/src/encrypt.cpp000664 001750 001750 00000007742 12755534123 016341 0ustar00sergiosergio000000 000000 /* Copyright (C) 2009-2015 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the this software. If not, see . */ #include "encrypt.h" #include "armcpu.h" #include "MMU.h" #include "registers.h" //TODO - a lot of redundant code (maybe?) with utils/decrypt.cpp //we should try unifying all that. //TODO - endian unsafeness in here... dont like the way these take u32. maybe it makes sense and the user is genuinely supposed to present data in units of u32 //================================================================================== KEY1 #define DWNUM(i) ((i) >> 2) void _KEY1::init(u32 idcode, u8 level, u8 modulo) { memcpy(keyBuf, keyBufPtr, 0x1048); keyCode[0] = idcode; keyCode[1] = idcode >> 1; keyCode[2] = idcode << 1; if (level >= 1) // first apply (always) applyKeycode(modulo); if (level >= 2) // second apply (optional) applyKeycode(modulo); keyCode[1] <<= 1; keyCode[2] >>= 1; if (level >= 3) // third apply (optional) applyKeycode(modulo); } void _KEY1::applyKeycode(u8 modulo) { encrypt(&keyCode[1]); encrypt(&keyCode[0]); u32 scratch[2] = {0}; for (u32 i = 0; i <= 0x44; i += 4) // xor with reversed byte-order (bswap) keyBuf[DWNUM(i)] ^= bswap32(keyCode[DWNUM(i % modulo)]); for (u32 i = 0; i <= 0x1040; i += 8) { encrypt(scratch); // encrypt S (64bit) by keybuf keyBuf[DWNUM(i)] = scratch[1]; // write S to keybuf (first upper 32bit) keyBuf[DWNUM(i+4)] = scratch[0]; // write S to keybuf (then lower 32bit) } } void _KEY1::decrypt(u32 *ptr) { u32 y = ptr[0]; u32 x = ptr[1]; for (u32 i = 0x11; i >= 0x02; i--) { u32 z = keyBuf[i] ^ x; x = keyBuf[DWNUM(0x048 + (((z >> 24) & 0xFF) << 2))]; x = keyBuf[DWNUM(0x448 + (((z >> 16) & 0xFF) << 2))] + x; x = keyBuf[DWNUM(0x848 + (((z >> 8) & 0xFF) << 2))] ^ x; x = keyBuf[DWNUM(0xC48 + (((z >> 0) & 0xFF) << 2))] + x; x = y ^ x; y = z; } ptr[0] = x ^ keyBuf[DWNUM(0x04)]; ptr[1] = y ^ keyBuf[DWNUM(0x00)]; } void _KEY1::encrypt(u32 *ptr) { u32 y = ptr[0]; u32 x = ptr[1]; for (u32 i = 0x00; i <= 0x0F; i++) { u32 z = keyBuf[i] ^ x; x = keyBuf[DWNUM(0x048 + (((z >> 24) & 0xFF) << 2))]; x = keyBuf[DWNUM(0x448 + (((z >> 16) & 0xFF) << 2))] + x; x = keyBuf[DWNUM(0x848 + (((z >> 8) & 0xFF) << 2))] ^ x; x = keyBuf[DWNUM(0xC48 + (((z >> 0) & 0xFF) << 2))] + x; x = y ^ x; y = z; } ptr[0] = x ^ keyBuf[DWNUM(0x40)]; ptr[1] = y ^ keyBuf[DWNUM(0x44)]; } #undef DWNUM //================================================================================== KEY2 u64 _KEY2::bitsReverse39(u64 key) { u64 tmp = 0; for (u32 i = 0; i < 39; i++) tmp |= ((key >> i) & 1) << (38 - i); return tmp; } void _KEY2::applySeed(u8 PROCNUM) { u64 tmp = (MMU_read8(PROCNUM, REG_ENCSEED0H) & 0xFF); seed0 = MMU_read32(PROCNUM, REG_ENCSEED0L) | (tmp << 32); tmp = (MMU_read8(PROCNUM, REG_ENCSEED1H) & 0xFF); seed1 = MMU_read32(PROCNUM, REG_ENCSEED1L) | (tmp << 32); x = bitsReverse39(seed0); y = bitsReverse39(seed1); //printf("ARM%c: set KEY2 seed0 to %010llX (reverse %010llX)\n", PROCNUM?'7':'9', seed0, x); //printf("ARM%c: set KEY2 seed1 to %010llX (reverse %010llX)\n", PROCNUM?'7':'9', seed1, y); } u8 _KEY2::apply(u8 data) { x = (((x >> 5) ^ (x >> 17) ^ (x >> 18) ^ (x >> 31)) & 0xFF) + (x << 8); y = (((y >> 5) ^ (y >> 23) ^ (y >> 18) ^ (y >> 31)) & 0xFF) + (y << 8); return ((data ^ x ^ y) & 0xFF); } desmume/src/libretro-common/include/gfx/scaler/scaler.h000664 001750 001750 00000007550 12755534123 024360 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2016 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (scaler.h). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef __LIBRETRO_SDK_SCALER_H__ #define __LIBRETRO_SDK_SCALER_H__ #include #include #include #include #include RETRO_BEGIN_DECLS #define FILTER_UNITY (1 << 14) enum scaler_pix_fmt { SCALER_FMT_ARGB8888 = 0, SCALER_FMT_ABGR8888, SCALER_FMT_0RGB1555, SCALER_FMT_RGB565, SCALER_FMT_BGR24, SCALER_FMT_YUYV, SCALER_FMT_RGBA4444 }; enum scaler_type { SCALER_TYPE_UNKNOWN = 0, SCALER_TYPE_POINT, SCALER_TYPE_BILINEAR, SCALER_TYPE_SINC }; struct scaler_filter { int16_t *filter; int filter_len; int filter_stride; int *filter_pos; }; struct scaler_ctx { int in_width; int in_height; int in_stride; int out_width; int out_height; int out_stride; enum scaler_pix_fmt in_fmt; enum scaler_pix_fmt out_fmt; enum scaler_type scaler_type; void (*scaler_horiz)(const struct scaler_ctx*, const void*, int); void (*scaler_vert)(const struct scaler_ctx*, void*, int); void (*scaler_special)(const struct scaler_ctx*, void*, const void*, int, int, int, int, int, int); void (*in_pixconv)(void*, const void*, int, int, int, int); void (*out_pixconv)(void*, const void*, int, int, int, int); void (*direct_pixconv)(void*, const void*, int, int, int, int); bool unscaled; struct scaler_filter horiz, vert; struct { uint32_t *frame; int stride; } input; struct { uint64_t *frame; int width; int height; int stride; } scaled; struct { uint32_t *frame; int stride; } output; }; bool scaler_ctx_gen_filter(struct scaler_ctx *ctx); void scaler_ctx_gen_reset(struct scaler_ctx *ctx); /** * scaler_ctx_scale: * @ctx : pointer to scaler context object. * @output : pointer to output image. * @input : pointer to input image. * * Scales an input image to an output image. **/ void scaler_ctx_scale(struct scaler_ctx *ctx, void *output, const void *input); /** * scaler_alloc: * @elem_size : size of the elements to be used. * @siz : size of the image that the scaler needs to handle. * * Allocate and returns a scaler object. * * Returns: pointer to a scaler object of type 'void *' on success, * NULL in case of error. Has to be freed manually. **/ void *scaler_alloc(size_t elem_size, size_t size); /** * scaler_free: * @ptr : pointer to scaler object. * * Frees a scaler object. **/ void scaler_free(void *ptr); RETRO_END_DECLS #endif desmume/src/utils/AsmJit/000700 001750 001750 00000000000 12756420131 016444 5ustar00sergiosergio000000 000000 desmume/src/arm_jit.cpp000664 001750 001750 00000441401 12755534123 016274 0ustar00sergiosergio000000 000000 /* Copyright (C) 2006 yopyop Copyright (C) 2011 Loren Merritt Copyright (C) 2012-2015 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the this software. If not, see . */ #include "types.h" #ifdef HAVE_JIT #if !defined(HOST_32) && !defined(HOST_64) #error "ERROR: JIT compiler - unsupported target platform" #endif #ifndef _WIN32 #include #include #include #include #define HAVE_STATIC_CODE_BUFFER #endif #include "utils/bits.h" #include "armcpu.h" #include "instructions.h" #include "instruction_attributes.h" #ifdef DEBUG #include "Disassembler.h" #endif #include "MMU.h" #include "MMU_timing.h" #include "utils/AsmJit/AsmJit.h" #include "arm_jit.h" #include "bios.h" #define LOG_JIT_LEVEL 0 #define PROFILER_JIT_LEVEL 0 #if (PROFILER_JIT_LEVEL > 0) #include #endif using namespace AsmJit; #if (LOG_JIT_LEVEL > 0) #define LOG_JIT 1 #define JIT_COMMENT(...) c.comment(__VA_ARGS__) #define printJIT(buf, val) { \ JIT_COMMENT("printJIT(\""##buf"\", val);"); \ GpVar txt = c.newGpVar(kX86VarTypeGpz); \ GpVar data = c.newGpVar(kX86VarTypeGpz); \ GpVar io = c.newGpVar(kX86VarTypeGpd); \ c.lea(io, dword_ptr_abs(stdout)); \ c.lea(txt, dword_ptr_abs(&buf)); \ c.mov(data, *(GpVar*)&val); \ X86CompilerFuncCall* prn = c.call((uintptr_t)fprintf); \ prn->setPrototype(kX86FuncConvDefault, FuncBuilder3()); \ prn->setArgument(0, io); \ prn->setArgument(1, txt); \ prn->setArgument(2, data); \ X86CompilerFuncCall* prn_flush = c.call((uintptr_t)fflush); \ prn_flush->setPrototype(kX86FuncConvDefault, FuncBuilder1()); \ prn_flush->setArgument(0, io); \ } #else #define LOG_JIT 0 #define JIT_COMMENT(...) #define printJIT(buf, val) #endif u32 saveBlockSizeJIT = 0; #ifdef MAPPED_JIT_FUNCS CACHE_ALIGN JIT_struct JIT; uintptr_t *JIT_struct::JIT_MEM[2][0x4000] = {{0}}; static uintptr_t *JIT_MEM[2][32] = { //arm9 { /* 0X*/ DUP2(JIT.ARM9_ITCM), /* 1X*/ DUP2(JIT.ARM9_ITCM), // mirror /* 2X*/ DUP2(JIT.MAIN_MEM), /* 3X*/ DUP2(JIT.SWIRAM), /* 4X*/ DUP2(NULL), /* 5X*/ DUP2(NULL), /* 6X*/ NULL, JIT.ARM9_LCDC, // Plain ARM9-CPU Access (LCDC mode) (max 656KB) /* 7X*/ DUP2(NULL), /* 8X*/ DUP2(NULL), /* 9X*/ DUP2(NULL), /* AX*/ DUP2(NULL), /* BX*/ DUP2(NULL), /* CX*/ DUP2(NULL), /* DX*/ DUP2(NULL), /* EX*/ DUP2(NULL), /* FX*/ DUP2(JIT.ARM9_BIOS) }, //arm7 { /* 0X*/ DUP2(JIT.ARM7_BIOS), /* 1X*/ DUP2(NULL), /* 2X*/ DUP2(JIT.MAIN_MEM), /* 3X*/ JIT.SWIRAM, JIT.ARM7_ERAM, /* 4X*/ NULL, JIT.ARM7_WIRAM, /* 5X*/ DUP2(NULL), /* 6X*/ JIT.ARM7_WRAM, // VRAM allocated as Work RAM to ARM7 (max. 256K) NULL, /* 7X*/ DUP2(NULL), /* 8X*/ DUP2(NULL), /* 9X*/ DUP2(NULL), /* AX*/ DUP2(NULL), /* BX*/ DUP2(NULL), /* CX*/ DUP2(NULL), /* DX*/ DUP2(NULL), /* EX*/ DUP2(NULL), /* FX*/ DUP2(NULL) } }; static u32 JIT_MASK[2][32] = { //arm9 { /* 0X*/ DUP2(0x00007FFF), /* 1X*/ DUP2(0x00007FFF), /* 2X*/ DUP2(0x003FFFFF), // FIXME _MMU_MAIN_MEM_MASK /* 3X*/ DUP2(0x00007FFF), /* 4X*/ DUP2(0x00000000), /* 5X*/ DUP2(0x00000000), /* 6X*/ 0x00000000, 0x000FFFFF, /* 7X*/ DUP2(0x00000000), /* 8X*/ DUP2(0x00000000), /* 9X*/ DUP2(0x00000000), /* AX*/ DUP2(0x00000000), /* BX*/ DUP2(0x00000000), /* CX*/ DUP2(0x00000000), /* DX*/ DUP2(0x00000000), /* EX*/ DUP2(0x00000000), /* FX*/ DUP2(0x00007FFF) }, //arm7 { /* 0X*/ DUP2(0x00003FFF), /* 1X*/ DUP2(0x00000000), /* 2X*/ DUP2(0x003FFFFF), /* 3X*/ 0x00007FFF, 0x0000FFFF, /* 4X*/ 0x00000000, 0x0000FFFF, /* 5X*/ DUP2(0x00000000), /* 6X*/ 0x0003FFFF, 0x00000000, /* 7X*/ DUP2(0x00000000), /* 8X*/ DUP2(0x00000000), /* 9X*/ DUP2(0x00000000), /* AX*/ DUP2(0x00000000), /* BX*/ DUP2(0x00000000), /* CX*/ DUP2(0x00000000), /* DX*/ DUP2(0x00000000), /* EX*/ DUP2(0x00000000), /* FX*/ DUP2(0x00000000) } }; static void init_jit_mem() { static bool inited = false; if(inited) return; inited = true; for(int proc=0; proc<2; proc++) for(int i=0; i<0x4000; i++) JIT.JIT_MEM[proc][i] = JIT_MEM[proc][i>>9] + (((i<<14) & JIT_MASK[proc][i>>9]) >> 1); } #else DS_ALIGN(4096) uintptr_t compiled_funcs[1<<26] = {0}; #endif static u8 recompile_counts[(1<<26)/16]; #ifdef HAVE_STATIC_CODE_BUFFER // On x86_64, allocate jitted code from a static buffer to ensure that it's within 2GB of .text // Allows call instructions to use pcrel offsets, as opposed to slower indirect calls. // Reduces memory needed for function pointers. // FIXME win64 needs this too, x86_32 doesn't DS_ALIGN(4096) static u8 scratchpad[1<<25]; static u8 *scratchptr; struct ASMJIT_API StaticCodeGenerator : public Context { StaticCodeGenerator() { scratchptr = scratchpad; int align = (uintptr_t)scratchpad & (sysconf(_SC_PAGESIZE) - 1); int err = mprotect(scratchpad-align, sizeof(scratchpad)+align, PROT_READ|PROT_WRITE|PROT_EXEC); if(err) { fprintf(stderr, "mprotect failed: %s\n", strerror(errno)); abort(); } } uint32_t generate(void** dest, Assembler* assembler) { uintptr_t size = assembler->getCodeSize(); if(size == 0) { *dest = NULL; return kErrorNoFunction; } if(size > (uintptr_t)(scratchpad+sizeof(scratchpad)-scratchptr)) { fprintf(stderr, "Out of memory for asmjit. Clearing code cache.\n"); arm_jit_reset(1); // If arm_jit_reset didn't involve recompiling op_cmp, we could keep the current function. *dest = NULL; return kErrorOk; } void *p = scratchptr; size = assembler->relocCode(p); scratchptr += size; *dest = p; return kErrorOk; } }; static StaticCodeGenerator codegen; static X86Compiler c(&codegen); #else static X86Compiler c; #endif static void emit_branch(int cond, Label to); static void _armlog(u8 proc, u32 addr, u32 opcode); static FileLogger logger(stderr); static int PROCNUM; static int *PROCNUM_ptr = &PROCNUM; static int bb_opcodesize; static int bb_adr; static bool bb_thumb; static GpVar bb_cpu; static GpVar bb_cycles; static GpVar bb_total_cycles; static u32 bb_constant_cycles; #define cpu (&ARMPROC) #define bb_next_instruction (bb_adr + bb_opcodesize) #define bb_r15 (bb_adr + 2 * bb_opcodesize) #define cpu_ptr(x) dword_ptr(bb_cpu, offsetof(armcpu_t, x)) #define cpu_ptr_byte(x, y) byte_ptr(bb_cpu, offsetof(armcpu_t, x) + y) #define flags_ptr cpu_ptr_byte(CPSR.val, 3) #define reg_ptr(x) dword_ptr(bb_cpu, offsetof(armcpu_t, R) + 4*(x)) #define reg_pos_ptr(x) dword_ptr(bb_cpu, offsetof(armcpu_t, R) + 4*REG_POS(i,(x))) #define reg_pos_ptrL(x) word_ptr( bb_cpu, offsetof(armcpu_t, R) + 4*REG_POS(i,(x))) #define reg_pos_ptrH(x) word_ptr( bb_cpu, offsetof(armcpu_t, R) + 4*REG_POS(i,(x)) + 2) #define reg_pos_ptrB(x) byte_ptr( bb_cpu, offsetof(armcpu_t, R) + 4*REG_POS(i,(x))) #define reg_pos_thumb(x) dword_ptr(bb_cpu, offsetof(armcpu_t, R) + 4*((i>>(x))&0x7)) #define reg_pos_thumbB(x) byte_ptr(bb_cpu, offsetof(armcpu_t, R) + 4*((i>>(x))&0x7)) #define cp15_ptr(x) dword_ptr(bb_cp15, offsetof(armcp15_t, x)) #define cp15_ptr_off(x, y) dword_ptr(bb_cp15, offsetof(armcp15_t, x) + y) #define mmu_ptr(x) dword_ptr(bb_mmu, offsetof(MMU_struct, x)) #define mmu_ptr_byte(x) byte_ptr(bb_mmu, offsetof(MMU_struct, x)) #define _REG_NUM(i, n) ((i>>(n))&0x7) #ifndef ASMJIT_X64 #define r64 r32 #endif // sequencer.reschedule = true; #define changeCPSR { \ X86CompilerFuncCall* ctxCPSR = c.call((void*)NDS_Reschedule); \ ctxCPSR->setPrototype(kX86FuncConvDefault, FuncBuilder0()); \ } #if (PROFILER_JIT_LEVEL > 0) struct PROFILER_COUNTER_INFO { u64 count; char name[64]; }; struct JIT_PROFILER { JIT_PROFILER() { memset(&arm_count[0], 0, sizeof(arm_count)); memset(&thumb_count[0], 0, sizeof(thumb_count)); } u64 arm_count[4096]; u64 thumb_count[1024]; } profiler_counter[2]; static GpVar bb_profiler; #define profiler_counter_arm(opcode) qword_ptr(bb_profiler, offsetof(JIT_PROFILER, arm_count) + (INSTRUCTION_INDEX(opcode)*sizeof(u64))) #define profiler_counter_thumb(opcode) qword_ptr(bb_profiler, offsetof(JIT_PROFILER, thumb_count) + ((opcode>>6)*sizeof(u64))) #if (PROFILER_JIT_LEVEL > 1) struct PROFILER_ENTRY { u32 addr; u32 cycles; } profiler_entry[2][1<<26]; static GpVar bb_profiler_entry; #endif #endif //----------------------------------------------------------------------------- // Shifting macros //----------------------------------------------------------------------------- #define SET_NZCV(sign) { \ JIT_COMMENT("SET_NZCV"); \ GpVar x = c.newGpVar(kX86VarTypeGpd); \ GpVar y = c.newGpVar(kX86VarTypeGpd); \ c.sets(x.r8Lo()); \ c.setz(y.r8Lo()); \ c.lea(x, ptr(y.r64(), x.r64(), kScale2Times)); \ if (sign) { c.setnc(y.r8Lo()); } else { c.setc(y.r8Lo()); } \ c.lea(x, ptr(y.r64(), x.r64(), kScale2Times)); \ c.seto(y.r8Lo()); \ c.lea(x, ptr(y.r64(), x.r64(), kScale2Times)); \ c.movzx(y, flags_ptr); \ c.shl(x, 4); \ c.and_(y, 0xF); \ c.or_(x, y); \ c.mov(flags_ptr, x.r8Lo()); \ c.unuse(x); \ c.unuse(y); \ JIT_COMMENT("end SET_NZCV"); \ } #define SET_NZC { \ JIT_COMMENT("SET_NZC"); \ GpVar x = c.newGpVar(kX86VarTypeGpd); \ GpVar y = c.newGpVar(kX86VarTypeGpd); \ c.sets(x.r8Lo()); \ c.setz(y.r8Lo()); \ c.lea(x, ptr(y.r64(), x.r64(), kScale2Times)); \ if (cf_change) { c.lea(x, ptr(rcf.r64(), x.r64(), kScale2Times)); c.unuse(rcf); } \ c.movzx(y, flags_ptr); \ c.shl(x, 6 - cf_change); \ c.and_(y, cf_change?0x1F:0x3F); \ c.or_(x, y); \ c.mov(flags_ptr, x.r8Lo()); \ JIT_COMMENT("end SET_NZC"); \ } #define SET_NZC_SHIFTS_ZERO(cf) { \ JIT_COMMENT("SET_NZC_SHIFTS_ZERO"); \ c.and_(flags_ptr, 0x1F); \ if(cf) \ { \ c.shl(rcf, 5); \ c.or_(rcf, (1<<6)); \ c.or_(flags_ptr, rcf.r8Lo()); \ } \ else \ c.or_(flags_ptr, (1<<6)); \ JIT_COMMENT("end SET_NZC_SHIFTS_ZERO"); \ } #define SET_NZ(clear_cv) { \ JIT_COMMENT("SET_NZ"); \ GpVar x = c.newGpVar(kX86VarTypeGpz); \ GpVar y = c.newGpVar(kX86VarTypeGpz); \ c.sets(x.r8Lo()); \ c.setz(y.r8Lo()); \ c.lea(x, ptr(y.r64(), x.r64(), kScale2Times)); \ c.movzx(y, flags_ptr); \ c.and_(y, clear_cv?0x0F:0x3F); \ c.shl(x, 6); \ c.or_(x, y); \ c.mov(flags_ptr, x.r8Lo()); \ JIT_COMMENT("end SET_NZ"); \ } #define SET_N { \ JIT_COMMENT("SET_N"); \ GpVar x = c.newGpVar(kX86VarTypeGpz); \ GpVar y = c.newGpVar(kX86VarTypeGpz); \ c.sets(x.r8Lo()); \ c.movzx(y, flags_ptr); \ c.and_(y, 0x7F); \ c.shl(x, 7); \ c.or_(x, y); \ c.mov(flags_ptr, x.r8Lo()); \ JIT_COMMENT("end SET_N"); \ } #define SET_Z { \ JIT_COMMENT("SET_Z"); \ GpVar x = c.newGpVar(kX86VarTypeGpz); \ GpVar y = c.newGpVar(kX86VarTypeGpz); \ c.setz(x.r8Lo()); \ c.movzx(y, flags_ptr); \ c.and_(y, 0xBF); \ c.shl(x, 6); \ c.or_(x, y); \ c.mov(flags_ptr, x.r8Lo()); \ JIT_COMMENT("end SET_Z"); \ } #define SET_Q { \ JIT_COMMENT("SET_Q"); \ GpVar x = c.newGpVar(kX86VarTypeGpz); \ c.seto(x.r8Lo()); \ c.shl(x, 3); \ c.or_(flags_ptr, x.r8Lo()); \ JIT_COMMENT("end SET_Q"); \ } #define S_DST_R15 { \ JIT_COMMENT("S_DST_R15"); \ GpVar SPSR = c.newGpVar(kX86VarTypeGpd); \ GpVar tmp = c.newGpVar(kX86VarTypeGpd); \ c.mov(SPSR, cpu_ptr(SPSR.val)); \ c.mov(tmp, SPSR); \ c.and_(tmp, 0x1F); \ X86CompilerFuncCall* ctx = c.call((void*)armcpu_switchMode); \ ctx->setPrototype(kX86FuncConvDefault, FuncBuilder2()); \ ctx->setArgument(0, bb_cpu); \ ctx->setArgument(1, tmp); \ c.mov(cpu_ptr(CPSR.val), SPSR); \ c.and_(SPSR, (1<<5)); \ c.shr(SPSR, 5); \ c.lea(tmp, ptr_abs((void*)0xFFFFFFFC, SPSR.r64(), kScale2Times)); \ c.and_(tmp, reg_ptr(15)); \ c.mov(cpu_ptr(next_instruction), tmp); \ c.unuse(tmp); \ JIT_COMMENT("end S_DST_R15"); \ } // ============================================================================================= IMM #define LSL_IMM \ JIT_COMMENT("LSL_IMM"); \ bool rhs_is_imm = false; \ u32 imm = ((i>>7)&0x1F); \ GpVar rhs = c.newGpVar(kX86VarTypeGpd); \ c.mov(rhs, reg_pos_ptr(0)); \ if(imm) c.shl(rhs, imm); \ u32 rhs_first = cpu->R[REG_POS(i,0)] << imm; #define S_LSL_IMM \ JIT_COMMENT("S_LSL_IMM"); \ bool rhs_is_imm = false; \ u8 cf_change = 0; \ GpVar rcf; \ GpVar rhs = c.newGpVar(kX86VarTypeGpd); \ u32 imm = ((i>>7)&0x1F); \ c.mov(rhs, reg_pos_ptr(0)); \ if (imm) \ { \ cf_change = 1; \ c.shl(rhs, imm); \ rcf = c.newGpVar(kX86VarTypeGpd); \ c.setc(rcf.r8Lo()); \ } #define LSR_IMM \ JIT_COMMENT("LSR_IMM"); \ bool rhs_is_imm = false; \ u32 imm = ((i>>7)&0x1F); \ GpVar rhs = c.newGpVar(kX86VarTypeGpd); \ if(imm) \ { \ c.mov(rhs, reg_pos_ptr(0)); \ c.shr(rhs, imm); \ } \ else \ c.mov(rhs, 0); \ u32 rhs_first = imm ? cpu->R[REG_POS(i,0)] >> imm : 0; #define S_LSR_IMM \ JIT_COMMENT("S_LSR_IMM"); \ bool rhs_is_imm = false; \ u8 cf_change = 1; \ GpVar rcf = c.newGpVar(kX86VarTypeGpd); \ GpVar rhs = c.newGpVar(kX86VarTypeGpd); \ u32 imm = ((i>>7)&0x1F); \ c.mov(rhs, reg_pos_ptr(0)); \ if (!imm) \ { \ c.test(rhs, (1 << 31)); \ c.setnz(rcf.r8Lo()); \ c.xor_(rhs, rhs); \ } \ else \ { \ c.shr(rhs, imm); \ c.setc(rcf.r8Lo()); \ } #define ASR_IMM \ JIT_COMMENT("ASR_IMM"); \ bool rhs_is_imm = false; \ u32 imm = ((i>>7)&0x1F); \ GpVar rhs = c.newGpVar(kX86VarTypeGpd); \ c.mov(rhs, reg_pos_ptr(0)); \ if(!imm) imm = 31; \ c.sar(rhs, imm); \ u32 rhs_first = (s32)cpu->R[REG_POS(i,0)] >> imm; #define S_ASR_IMM \ JIT_COMMENT("S_ASR_IMM"); \ bool rhs_is_imm = false; \ u8 cf_change = 1; \ GpVar rcf = c.newGpVar(kX86VarTypeGpd); \ GpVar rhs = c.newGpVar(kX86VarTypeGpd); \ u32 imm = ((i>>7)&0x1F); \ c.mov(rhs, reg_pos_ptr(0)); \ if (!imm) imm = 31; \ c.sar(rhs, imm); \ imm==31?c.sets(rcf.r8Lo()):c.setc(rcf.r8Lo()); #define ROR_IMM \ JIT_COMMENT("ROR_IMM"); \ bool rhs_is_imm = false; \ u32 imm = ((i>>7)&0x1F); \ GpVar rhs = c.newGpVar(kX86VarTypeGpd); \ c.mov(rhs, reg_pos_ptr(0)); \ if (!imm) \ { \ c.bt(flags_ptr, 5); \ c.rcr(rhs, 1); \ } \ else \ c.ror(rhs, imm); \ u32 rhs_first = imm?ROR(cpu->R[REG_POS(i,0)], imm) : ((u32)cpu->CPSR.bits.C<<31)|(cpu->R[REG_POS(i,0)]>>1); #define S_ROR_IMM \ JIT_COMMENT("S_ROR_IMM"); \ bool rhs_is_imm = false; \ u8 cf_change = 1; \ GpVar rcf = c.newGpVar(kX86VarTypeGpd); \ GpVar rhs = c.newGpVar(kX86VarTypeGpd); \ u32 imm = ((i>>7)&0x1F); \ c.mov(rhs, reg_pos_ptr(0)); \ if (!imm) \ { \ c.bt(flags_ptr, 5); \ c.rcr(rhs, 1); \ } \ else \ c.ror(rhs, imm); \ c.setc(rcf.r8Lo()); #define REG_OFF \ JIT_COMMENT("REG_OFF"); \ bool rhs_is_imm = false; \ Mem rhs = reg_pos_ptr(0); \ u32 rhs_first = cpu->R[REG_POS(i,0)]; #define IMM_VAL \ JIT_COMMENT("IMM_VAL"); \ bool rhs_is_imm = true; \ u32 rhs = ROR((i&0xFF), (i>>7)&0x1E); \ u32 rhs_first = rhs; #define S_IMM_VAL \ JIT_COMMENT("S_IMM_VAL"); \ bool rhs_is_imm = true; \ u8 cf_change = 0; \ GpVar rcf; \ u32 rhs = ROR((i&0xFF), (i>>7)&0x1E); \ if ((i>>8)&0xF) \ { \ cf_change = 1; \ rcf = c.newGpVar(kX86VarTypeGpd); \ c.mov(rcf, BIT31(rhs)); \ } \ u32 rhs_first = rhs; #define IMM_OFF \ JIT_COMMENT("IMM_OFF"); \ bool rhs_is_imm = true; \ u32 rhs = ((i>>4)&0xF0)+(i&0xF); \ u32 rhs_first = rhs; #define IMM_OFF_12 \ JIT_COMMENT("IMM_OFF_12"); \ bool rhs_is_imm = true; \ u32 rhs = (i & 0xFFF); \ u32 rhs_first = rhs; // ============================================================================================= REG #define LSX_REG(name, x86inst, sign) \ JIT_COMMENT(#name); \ bool rhs_is_imm = false; \ GpVar rhs = c.newGpVar(kX86VarTypeGpd); \ GpVar imm = c.newGpVar(kX86VarTypeGpz); \ GpVar tmp = c.newGpVar(kX86VarTypeGpz); \ if(sign) c.mov(tmp, 31); \ else c.mov(tmp, 0); \ c.movzx(imm, reg_pos_ptrB(8)); \ c.mov(rhs, reg_pos_ptr(0)); \ c.cmp(imm, 31); \ if(sign) c.cmovg(imm, tmp); \ else c.cmovg(rhs, tmp); \ c.x86inst(rhs, imm); \ c.unuse(tmp); #define S_LSX_REG(name, x86inst, sign) \ JIT_COMMENT(#name); \ bool rhs_is_imm = false; \ u8 cf_change = 1; \ GpVar rcf = c.newGpVar(kX86VarTypeGpd); \ GpVar rhs = c.newGpVar(kX86VarTypeGpd); \ GpVar imm = c.newGpVar(kX86VarTypeGpz); \ Label __zero = c.newLabel(); \ Label __lt32 = c.newLabel(); \ Label __done = c.newLabel(); \ c.mov(imm, reg_pos_ptr(8)); \ c.mov(rhs, reg_pos_ptr(0)); \ c.and_(imm, 0xFF); \ c.jz(__zero); \ c.cmp(imm, 32); \ c.jl(__lt32); \ if(!sign) \ { \ Label __eq32 = c.newLabel(); \ c.je(__eq32); \ /* imm > 32 */ \ c.mov(rhs, 0); \ c.mov(rcf, 0); \ c.jmp(__done); \ /* imm == 32 */ \ c.bind(__eq32); \ } \ c.x86inst(rhs, 31); \ c.x86inst(rhs, 1); \ c.setc(rcf.r8Lo()); \ c.jmp(__done); \ /* imm == 0 */ \ c.bind(__zero); \ c.test(flags_ptr, (1 << 5)); \ c.setnz(rcf.r8Lo()); \ c.jmp(__done); \ /* imm < 32 */ \ c.bind(__lt32); \ c.x86inst(rhs, imm); \ c.setc(rcf.r8Lo()); \ /* done */ \ c.bind(__done); #define LSL_REG LSX_REG(LSL_REG, shl, 0) #define LSR_REG LSX_REG(LSR_REG, shr, 0) #define ASR_REG LSX_REG(ASR_REG, sar, 1) #define S_LSL_REG S_LSX_REG(S_LSL_REG, shl, 0) #define S_LSR_REG S_LSX_REG(S_LSR_REG, shr, 0) #define S_ASR_REG S_LSX_REG(S_ASR_REG, sar, 1) #define ROR_REG \ JIT_COMMENT("ROR_REG"); \ bool rhs_is_imm = false; \ GpVar rhs = c.newGpVar(kX86VarTypeGpd); \ GpVar imm = c.newGpVar(kX86VarTypeGpz); \ c.mov(rhs, reg_pos_ptr(0)); \ c.mov(imm, reg_pos_ptrB(8)); \ c.ror(rhs, imm.r8Lo()); #define S_ROR_REG \ JIT_COMMENT("S_ROR_REG"); \ bool rhs_is_imm = false; \ bool cf_change = 1; \ GpVar rcf = c.newGpVar(kX86VarTypeGpd); \ GpVar imm = c.newGpVar(kX86VarTypeGpz); \ GpVar rhs = c.newGpVar(kX86VarTypeGpd); \ Label __zero = c.newLabel(); \ Label __zero_1F = c.newLabel(); \ Label __done = c.newLabel(); \ c.mov(imm, reg_pos_ptr(8)); \ c.mov(rhs, reg_pos_ptr(0)); \ c.and_(imm, 0xFF); \ c.jz(__zero);\ c.and_(imm, 0x1F); \ c.jz(__zero_1F);\ /* imm&0x1F != 0 */ \ c.ror(rhs, imm); \ c.setc(rcf.r8Lo()); \ c.jmp(__done); \ /* imm&0x1F == 0 */ \ c.bind(__zero_1F); \ c.test(rhs, (1 << 31)); \ c.setnz(rcf.r8Lo()); \ c.jmp(__done); \ /* imm == 0 */ \ c.bind(__zero); \ c.test(flags_ptr, (1 << 5)); \ c.setnz(rcf.r8Lo()); \ /* done */ \ c.bind(__done); //==================================================================== common funcs static void emit_MMU_aluMemCycles(int alu_cycles, GpVar mem_cycles, int population) { if(PROCNUM==ARMCPU_ARM9) { if(population < alu_cycles) { GpVar x = c.newGpVar(kX86VarTypeGpd); c.mov(x, alu_cycles); c.cmp(mem_cycles, alu_cycles); c.cmovl(mem_cycles, x); } } else c.add(mem_cycles, alu_cycles); } //----------------------------------------------------------------------------- // OPs //----------------------------------------------------------------------------- #define OP_ARITHMETIC(arg, x86inst, symmetric, flags) \ arg; \ GpVar lhs = c.newGpVar(kX86VarTypeGpd); \ if(REG_POS(i,12) == REG_POS(i,16)) \ c.x86inst(reg_pos_ptr(12), rhs); \ else if(symmetric && !rhs_is_imm) \ { \ c.x86inst(*(GpVar*)&rhs, reg_pos_ptr(16)); \ c.mov(reg_pos_ptr(12), rhs); \ } \ else \ { \ c.mov(lhs, reg_pos_ptr(16)); \ c.x86inst(lhs, rhs); \ c.mov(reg_pos_ptr(12), lhs); \ } \ if(flags) \ { \ if(REG_POS(i,12)==15) \ { \ S_DST_R15; \ c.add(bb_total_cycles, 2); \ return 1; \ } \ SET_NZCV(!symmetric); \ } \ else \ { \ if(REG_POS(i,12)==15) \ { \ GpVar tmp = c.newGpVar(kX86VarTypeGpd); \ c.mov(tmp, reg_ptr(15)); \ c.mov(cpu_ptr(next_instruction), tmp); \ c.add(bb_total_cycles, 2); \ } \ } \ return 1; #define OP_ARITHMETIC_R(arg, x86inst, flags) \ arg; \ GpVar lhs = c.newGpVar(kX86VarTypeGpd); \ c.mov(lhs, rhs); \ c.x86inst(lhs, reg_pos_ptr(16)); \ c.mov(reg_pos_ptr(12), lhs); \ if(flags) \ { \ if(REG_POS(i,12)==15) \ { \ S_DST_R15; \ c.add(bb_total_cycles, 2); \ return 1; \ } \ SET_NZCV(1); \ } \ else \ { \ if(REG_POS(i,12)==15) \ { \ c.mov(cpu_ptr(next_instruction), lhs); \ c.add(bb_total_cycles, 2); \ } \ } \ return 1; #define OP_ARITHMETIC_S(arg, x86inst, symmetric) \ arg; \ if(REG_POS(i,12) == REG_POS(i,16)) \ c.x86inst(reg_pos_ptr(12), rhs); \ else if(symmetric && !rhs_is_imm) \ { \ c.x86inst(*(GpVar*)&rhs, reg_pos_ptr(16)); \ c.mov(reg_pos_ptr(12), rhs); \ } \ else \ { \ GpVar lhs = c.newGpVar(kX86VarTypeGpd); \ c.mov(lhs, reg_pos_ptr(16)); \ c.x86inst(lhs, rhs); \ c.mov(reg_pos_ptr(12), lhs); \ } \ if(REG_POS(i,12)==15) \ { \ S_DST_R15; \ c.add(bb_total_cycles, 2); \ return 1; \ } \ SET_NZC; \ return 1; #define GET_CARRY(invert) { \ c.bt(flags_ptr, 5); \ if (invert) c.cmc(); } static int OP_AND_LSL_IMM(const u32 i) { OP_ARITHMETIC(LSL_IMM, and_, 1, 0); } static int OP_AND_LSL_REG(const u32 i) { OP_ARITHMETIC(LSL_REG, and_, 1, 0); } static int OP_AND_LSR_IMM(const u32 i) { OP_ARITHMETIC(LSR_IMM, and_, 1, 0); } static int OP_AND_LSR_REG(const u32 i) { OP_ARITHMETIC(LSR_REG, and_, 1, 0); } static int OP_AND_ASR_IMM(const u32 i) { OP_ARITHMETIC(ASR_IMM, and_, 1, 0); } static int OP_AND_ASR_REG(const u32 i) { OP_ARITHMETIC(ASR_REG, and_, 1, 0); } static int OP_AND_ROR_IMM(const u32 i) { OP_ARITHMETIC(ROR_IMM, and_, 1, 0); } static int OP_AND_ROR_REG(const u32 i) { OP_ARITHMETIC(ROR_REG, and_, 1, 0); } static int OP_AND_IMM_VAL(const u32 i) { OP_ARITHMETIC(IMM_VAL, and_, 1, 0); } static int OP_EOR_LSL_IMM(const u32 i) { OP_ARITHMETIC(LSL_IMM, xor_, 1, 0); } static int OP_EOR_LSL_REG(const u32 i) { OP_ARITHMETIC(LSL_REG, xor_, 1, 0); } static int OP_EOR_LSR_IMM(const u32 i) { OP_ARITHMETIC(LSR_IMM, xor_, 1, 0); } static int OP_EOR_LSR_REG(const u32 i) { OP_ARITHMETIC(LSR_REG, xor_, 1, 0); } static int OP_EOR_ASR_IMM(const u32 i) { OP_ARITHMETIC(ASR_IMM, xor_, 1, 0); } static int OP_EOR_ASR_REG(const u32 i) { OP_ARITHMETIC(ASR_REG, xor_, 1, 0); } static int OP_EOR_ROR_IMM(const u32 i) { OP_ARITHMETIC(ROR_IMM, xor_, 1, 0); } static int OP_EOR_ROR_REG(const u32 i) { OP_ARITHMETIC(ROR_REG, xor_, 1, 0); } static int OP_EOR_IMM_VAL(const u32 i) { OP_ARITHMETIC(IMM_VAL, xor_, 1, 0); } static int OP_ORR_LSL_IMM(const u32 i) { OP_ARITHMETIC(LSL_IMM, or_, 1, 0); } static int OP_ORR_LSL_REG(const u32 i) { OP_ARITHMETIC(LSL_REG, or_, 1, 0); } static int OP_ORR_LSR_IMM(const u32 i) { OP_ARITHMETIC(LSR_IMM, or_, 1, 0); } static int OP_ORR_LSR_REG(const u32 i) { OP_ARITHMETIC(LSR_REG, or_, 1, 0); } static int OP_ORR_ASR_IMM(const u32 i) { OP_ARITHMETIC(ASR_IMM, or_, 1, 0); } static int OP_ORR_ASR_REG(const u32 i) { OP_ARITHMETIC(ASR_REG, or_, 1, 0); } static int OP_ORR_ROR_IMM(const u32 i) { OP_ARITHMETIC(ROR_IMM, or_, 1, 0); } static int OP_ORR_ROR_REG(const u32 i) { OP_ARITHMETIC(ROR_REG, or_, 1, 0); } static int OP_ORR_IMM_VAL(const u32 i) { OP_ARITHMETIC(IMM_VAL, or_, 1, 0); } static int OP_ADD_LSL_IMM(const u32 i) { OP_ARITHMETIC(LSL_IMM, add, 1, 0); } static int OP_ADD_LSL_REG(const u32 i) { OP_ARITHMETIC(LSL_REG, add, 1, 0); } static int OP_ADD_LSR_IMM(const u32 i) { OP_ARITHMETIC(LSR_IMM, add, 1, 0); } static int OP_ADD_LSR_REG(const u32 i) { OP_ARITHMETIC(LSR_REG, add, 1, 0); } static int OP_ADD_ASR_IMM(const u32 i) { OP_ARITHMETIC(ASR_IMM, add, 1, 0); } static int OP_ADD_ASR_REG(const u32 i) { OP_ARITHMETIC(ASR_REG, add, 1, 0); } static int OP_ADD_ROR_IMM(const u32 i) { OP_ARITHMETIC(ROR_IMM, add, 1, 0); } static int OP_ADD_ROR_REG(const u32 i) { OP_ARITHMETIC(ROR_REG, add, 1, 0); } static int OP_ADD_IMM_VAL(const u32 i) { OP_ARITHMETIC(IMM_VAL, add, 1, 0); } static int OP_SUB_LSL_IMM(const u32 i) { OP_ARITHMETIC(LSL_IMM, sub, 0, 0); } static int OP_SUB_LSL_REG(const u32 i) { OP_ARITHMETIC(LSL_REG, sub, 0, 0); } static int OP_SUB_LSR_IMM(const u32 i) { OP_ARITHMETIC(LSR_IMM, sub, 0, 0); } static int OP_SUB_LSR_REG(const u32 i) { OP_ARITHMETIC(LSR_REG, sub, 0, 0); } static int OP_SUB_ASR_IMM(const u32 i) { OP_ARITHMETIC(ASR_IMM, sub, 0, 0); } static int OP_SUB_ASR_REG(const u32 i) { OP_ARITHMETIC(ASR_REG, sub, 0, 0); } static int OP_SUB_ROR_IMM(const u32 i) { OP_ARITHMETIC(ROR_IMM, sub, 0, 0); } static int OP_SUB_ROR_REG(const u32 i) { OP_ARITHMETIC(ROR_REG, sub, 0, 0); } static int OP_SUB_IMM_VAL(const u32 i) { OP_ARITHMETIC(IMM_VAL, sub, 0, 0); } static int OP_RSB_LSL_IMM(const u32 i) { OP_ARITHMETIC_R(LSL_IMM, sub, 0); } static int OP_RSB_LSL_REG(const u32 i) { OP_ARITHMETIC_R(LSL_REG, sub, 0); } static int OP_RSB_LSR_IMM(const u32 i) { OP_ARITHMETIC_R(LSR_IMM, sub, 0); } static int OP_RSB_LSR_REG(const u32 i) { OP_ARITHMETIC_R(LSR_REG, sub, 0); } static int OP_RSB_ASR_IMM(const u32 i) { OP_ARITHMETIC_R(ASR_IMM, sub, 0); } static int OP_RSB_ASR_REG(const u32 i) { OP_ARITHMETIC_R(ASR_REG, sub, 0); } static int OP_RSB_ROR_IMM(const u32 i) { OP_ARITHMETIC_R(ROR_IMM, sub, 0); } static int OP_RSB_ROR_REG(const u32 i) { OP_ARITHMETIC_R(ROR_REG, sub, 0); } static int OP_RSB_IMM_VAL(const u32 i) { OP_ARITHMETIC_R(IMM_VAL, sub, 0); } // ================================ S instructions static int OP_AND_S_LSL_IMM(const u32 i) { OP_ARITHMETIC_S(S_LSL_IMM, and_, 1); } static int OP_AND_S_LSL_REG(const u32 i) { OP_ARITHMETIC_S(S_LSL_REG, and_, 1); } static int OP_AND_S_LSR_IMM(const u32 i) { OP_ARITHMETIC_S(S_LSR_IMM, and_, 1); } static int OP_AND_S_LSR_REG(const u32 i) { OP_ARITHMETIC_S(S_LSR_REG, and_, 1); } static int OP_AND_S_ASR_IMM(const u32 i) { OP_ARITHMETIC_S(S_ASR_IMM, and_, 1); } static int OP_AND_S_ASR_REG(const u32 i) { OP_ARITHMETIC_S(S_ASR_REG, and_, 1); } static int OP_AND_S_ROR_IMM(const u32 i) { OP_ARITHMETIC_S(S_ROR_IMM, and_, 1); } static int OP_AND_S_ROR_REG(const u32 i) { OP_ARITHMETIC_S(S_ROR_REG, and_, 1); } static int OP_AND_S_IMM_VAL(const u32 i) { OP_ARITHMETIC_S(S_IMM_VAL, and_, 1); } static int OP_EOR_S_LSL_IMM(const u32 i) { OP_ARITHMETIC_S(S_LSL_IMM, xor_, 1); } static int OP_EOR_S_LSL_REG(const u32 i) { OP_ARITHMETIC_S(S_LSL_REG, xor_, 1); } static int OP_EOR_S_LSR_IMM(const u32 i) { OP_ARITHMETIC_S(S_LSR_IMM, xor_, 1); } static int OP_EOR_S_LSR_REG(const u32 i) { OP_ARITHMETIC_S(S_LSR_REG, xor_, 1); } static int OP_EOR_S_ASR_IMM(const u32 i) { OP_ARITHMETIC_S(S_ASR_IMM, xor_, 1); } static int OP_EOR_S_ASR_REG(const u32 i) { OP_ARITHMETIC_S(S_ASR_REG, xor_, 1); } static int OP_EOR_S_ROR_IMM(const u32 i) { OP_ARITHMETIC_S(S_ROR_IMM, xor_, 1); } static int OP_EOR_S_ROR_REG(const u32 i) { OP_ARITHMETIC_S(S_ROR_REG, xor_, 1); } static int OP_EOR_S_IMM_VAL(const u32 i) { OP_ARITHMETIC_S(S_IMM_VAL, xor_, 1); } static int OP_ORR_S_LSL_IMM(const u32 i) { OP_ARITHMETIC_S(S_LSL_IMM, or_, 1); } static int OP_ORR_S_LSL_REG(const u32 i) { OP_ARITHMETIC_S(S_LSL_REG, or_, 1); } static int OP_ORR_S_LSR_IMM(const u32 i) { OP_ARITHMETIC_S(S_LSR_IMM, or_, 1); } static int OP_ORR_S_LSR_REG(const u32 i) { OP_ARITHMETIC_S(S_LSR_REG, or_, 1); } static int OP_ORR_S_ASR_IMM(const u32 i) { OP_ARITHMETIC_S(S_ASR_IMM, or_, 1); } static int OP_ORR_S_ASR_REG(const u32 i) { OP_ARITHMETIC_S(S_ASR_REG, or_, 1); } static int OP_ORR_S_ROR_IMM(const u32 i) { OP_ARITHMETIC_S(S_ROR_IMM, or_, 1); } static int OP_ORR_S_ROR_REG(const u32 i) { OP_ARITHMETIC_S(S_ROR_REG, or_, 1); } static int OP_ORR_S_IMM_VAL(const u32 i) { OP_ARITHMETIC_S(S_IMM_VAL, or_, 1); } static int OP_ADD_S_LSL_IMM(const u32 i) { OP_ARITHMETIC(LSL_IMM, add, 1, 1); } static int OP_ADD_S_LSL_REG(const u32 i) { OP_ARITHMETIC(LSL_REG, add, 1, 1); } static int OP_ADD_S_LSR_IMM(const u32 i) { OP_ARITHMETIC(LSR_IMM, add, 1, 1); } static int OP_ADD_S_LSR_REG(const u32 i) { OP_ARITHMETIC(LSR_REG, add, 1, 1); } static int OP_ADD_S_ASR_IMM(const u32 i) { OP_ARITHMETIC(ASR_IMM, add, 1, 1); } static int OP_ADD_S_ASR_REG(const u32 i) { OP_ARITHMETIC(ASR_REG, add, 1, 1); } static int OP_ADD_S_ROR_IMM(const u32 i) { OP_ARITHMETIC(ROR_IMM, add, 1, 1); } static int OP_ADD_S_ROR_REG(const u32 i) { OP_ARITHMETIC(ROR_REG, add, 1, 1); } static int OP_ADD_S_IMM_VAL(const u32 i) { OP_ARITHMETIC(IMM_VAL, add, 1, 1); } static int OP_SUB_S_LSL_IMM(const u32 i) { OP_ARITHMETIC(LSL_IMM, sub, 0, 1); } static int OP_SUB_S_LSL_REG(const u32 i) { OP_ARITHMETIC(LSL_REG, sub, 0, 1); } static int OP_SUB_S_LSR_IMM(const u32 i) { OP_ARITHMETIC(LSR_IMM, sub, 0, 1); } static int OP_SUB_S_LSR_REG(const u32 i) { OP_ARITHMETIC(LSR_REG, sub, 0, 1); } static int OP_SUB_S_ASR_IMM(const u32 i) { OP_ARITHMETIC(ASR_IMM, sub, 0, 1); } static int OP_SUB_S_ASR_REG(const u32 i) { OP_ARITHMETIC(ASR_REG, sub, 0, 1); } static int OP_SUB_S_ROR_IMM(const u32 i) { OP_ARITHMETIC(ROR_IMM, sub, 0, 1); } static int OP_SUB_S_ROR_REG(const u32 i) { OP_ARITHMETIC(ROR_REG, sub, 0, 1); } static int OP_SUB_S_IMM_VAL(const u32 i) { OP_ARITHMETIC(IMM_VAL, sub, 0, 1); } static int OP_RSB_S_LSL_IMM(const u32 i) { OP_ARITHMETIC_R(LSL_IMM, sub, 1); } static int OP_RSB_S_LSL_REG(const u32 i) { OP_ARITHMETIC_R(LSL_REG, sub, 1); } static int OP_RSB_S_LSR_IMM(const u32 i) { OP_ARITHMETIC_R(LSR_IMM, sub, 1); } static int OP_RSB_S_LSR_REG(const u32 i) { OP_ARITHMETIC_R(LSR_REG, sub, 1); } static int OP_RSB_S_ASR_IMM(const u32 i) { OP_ARITHMETIC_R(ASR_IMM, sub, 1); } static int OP_RSB_S_ASR_REG(const u32 i) { OP_ARITHMETIC_R(ASR_REG, sub, 1); } static int OP_RSB_S_ROR_IMM(const u32 i) { OP_ARITHMETIC_R(ROR_IMM, sub, 1); } static int OP_RSB_S_ROR_REG(const u32 i) { OP_ARITHMETIC_R(ROR_REG, sub, 1); } static int OP_RSB_S_IMM_VAL(const u32 i) { OP_ARITHMETIC_R(IMM_VAL, sub, 1); } static int OP_ADC_LSL_IMM(const u32 i) { OP_ARITHMETIC(LSL_IMM; GET_CARRY(0), adc, 1, 0); } static int OP_ADC_LSL_REG(const u32 i) { OP_ARITHMETIC(LSL_REG; GET_CARRY(0), adc, 1, 0); } static int OP_ADC_LSR_IMM(const u32 i) { OP_ARITHMETIC(LSR_IMM; GET_CARRY(0), adc, 1, 0); } static int OP_ADC_LSR_REG(const u32 i) { OP_ARITHMETIC(LSR_REG; GET_CARRY(0), adc, 1, 0); } static int OP_ADC_ASR_IMM(const u32 i) { OP_ARITHMETIC(ASR_IMM; GET_CARRY(0), adc, 1, 0); } static int OP_ADC_ASR_REG(const u32 i) { OP_ARITHMETIC(ASR_REG; GET_CARRY(0), adc, 1, 0); } static int OP_ADC_ROR_IMM(const u32 i) { OP_ARITHMETIC(ROR_IMM; GET_CARRY(0), adc, 1, 0); } static int OP_ADC_ROR_REG(const u32 i) { OP_ARITHMETIC(ROR_REG; GET_CARRY(0), adc, 1, 0); } static int OP_ADC_IMM_VAL(const u32 i) { OP_ARITHMETIC(IMM_VAL; GET_CARRY(0), adc, 1, 0); } static int OP_ADC_S_LSL_IMM(const u32 i) { OP_ARITHMETIC(LSL_IMM; GET_CARRY(0), adc, 1, 1); } static int OP_ADC_S_LSL_REG(const u32 i) { OP_ARITHMETIC(LSL_REG; GET_CARRY(0), adc, 1, 1); } static int OP_ADC_S_LSR_IMM(const u32 i) { OP_ARITHMETIC(LSR_IMM; GET_CARRY(0), adc, 1, 1); } static int OP_ADC_S_LSR_REG(const u32 i) { OP_ARITHMETIC(LSR_REG; GET_CARRY(0), adc, 1, 1); } static int OP_ADC_S_ASR_IMM(const u32 i) { OP_ARITHMETIC(ASR_IMM; GET_CARRY(0), adc, 1, 1); } static int OP_ADC_S_ASR_REG(const u32 i) { OP_ARITHMETIC(ASR_REG; GET_CARRY(0), adc, 1, 1); } static int OP_ADC_S_ROR_IMM(const u32 i) { OP_ARITHMETIC(ROR_IMM; GET_CARRY(0), adc, 1, 1); } static int OP_ADC_S_ROR_REG(const u32 i) { OP_ARITHMETIC(ROR_REG; GET_CARRY(0), adc, 1, 1); } static int OP_ADC_S_IMM_VAL(const u32 i) { OP_ARITHMETIC(IMM_VAL; GET_CARRY(0), adc, 1, 1); } static int OP_SBC_LSL_IMM(const u32 i) { OP_ARITHMETIC(LSL_IMM; GET_CARRY(1), sbb, 0, 0); } static int OP_SBC_LSL_REG(const u32 i) { OP_ARITHMETIC(LSL_REG; GET_CARRY(1), sbb, 0, 0); } static int OP_SBC_LSR_IMM(const u32 i) { OP_ARITHMETIC(LSR_IMM; GET_CARRY(1), sbb, 0, 0); } static int OP_SBC_LSR_REG(const u32 i) { OP_ARITHMETIC(LSR_REG; GET_CARRY(1), sbb, 0, 0); } static int OP_SBC_ASR_IMM(const u32 i) { OP_ARITHMETIC(ASR_IMM; GET_CARRY(1), sbb, 0, 0); } static int OP_SBC_ASR_REG(const u32 i) { OP_ARITHMETIC(ASR_REG; GET_CARRY(1), sbb, 0, 0); } static int OP_SBC_ROR_IMM(const u32 i) { OP_ARITHMETIC(ROR_IMM; GET_CARRY(1), sbb, 0, 0); } static int OP_SBC_ROR_REG(const u32 i) { OP_ARITHMETIC(ROR_REG; GET_CARRY(1), sbb, 0, 0); } static int OP_SBC_IMM_VAL(const u32 i) { OP_ARITHMETIC(IMM_VAL; GET_CARRY(1), sbb, 0, 0); } static int OP_SBC_S_LSL_IMM(const u32 i) { OP_ARITHMETIC(LSL_IMM; GET_CARRY(1), sbb, 0, 1); } static int OP_SBC_S_LSL_REG(const u32 i) { OP_ARITHMETIC(LSL_REG; GET_CARRY(1), sbb, 0, 1); } static int OP_SBC_S_LSR_IMM(const u32 i) { OP_ARITHMETIC(LSR_IMM; GET_CARRY(1), sbb, 0, 1); } static int OP_SBC_S_LSR_REG(const u32 i) { OP_ARITHMETIC(LSR_REG; GET_CARRY(1), sbb, 0, 1); } static int OP_SBC_S_ASR_IMM(const u32 i) { OP_ARITHMETIC(ASR_IMM; GET_CARRY(1), sbb, 0, 1); } static int OP_SBC_S_ASR_REG(const u32 i) { OP_ARITHMETIC(ASR_REG; GET_CARRY(1), sbb, 0, 1); } static int OP_SBC_S_ROR_IMM(const u32 i) { OP_ARITHMETIC(ROR_IMM; GET_CARRY(1), sbb, 0, 1); } static int OP_SBC_S_ROR_REG(const u32 i) { OP_ARITHMETIC(ROR_REG; GET_CARRY(1), sbb, 0, 1); } static int OP_SBC_S_IMM_VAL(const u32 i) { OP_ARITHMETIC(IMM_VAL; GET_CARRY(1), sbb, 0, 1); } static int OP_RSC_LSL_IMM(const u32 i) { OP_ARITHMETIC_R(LSL_IMM; GET_CARRY(1), sbb, 0); } static int OP_RSC_LSL_REG(const u32 i) { OP_ARITHMETIC_R(LSL_REG; GET_CARRY(1), sbb, 0); } static int OP_RSC_LSR_IMM(const u32 i) { OP_ARITHMETIC_R(LSR_IMM; GET_CARRY(1), sbb, 0); } static int OP_RSC_LSR_REG(const u32 i) { OP_ARITHMETIC_R(LSR_REG; GET_CARRY(1), sbb, 0); } static int OP_RSC_ASR_IMM(const u32 i) { OP_ARITHMETIC_R(ASR_IMM; GET_CARRY(1), sbb, 0); } static int OP_RSC_ASR_REG(const u32 i) { OP_ARITHMETIC_R(ASR_REG; GET_CARRY(1), sbb, 0); } static int OP_RSC_ROR_IMM(const u32 i) { OP_ARITHMETIC_R(ROR_IMM; GET_CARRY(1), sbb, 0); } static int OP_RSC_ROR_REG(const u32 i) { OP_ARITHMETIC_R(ROR_REG; GET_CARRY(1), sbb, 0); } static int OP_RSC_IMM_VAL(const u32 i) { OP_ARITHMETIC_R(IMM_VAL; GET_CARRY(1), sbb, 0); } static int OP_RSC_S_LSL_IMM(const u32 i) { OP_ARITHMETIC_R(LSL_IMM; GET_CARRY(1), sbb, 1); } static int OP_RSC_S_LSL_REG(const u32 i) { OP_ARITHMETIC_R(LSL_REG; GET_CARRY(1), sbb, 1); } static int OP_RSC_S_LSR_IMM(const u32 i) { OP_ARITHMETIC_R(LSR_IMM; GET_CARRY(1), sbb, 1); } static int OP_RSC_S_LSR_REG(const u32 i) { OP_ARITHMETIC_R(LSR_REG; GET_CARRY(1), sbb, 1); } static int OP_RSC_S_ASR_IMM(const u32 i) { OP_ARITHMETIC_R(ASR_IMM; GET_CARRY(1), sbb, 1); } static int OP_RSC_S_ASR_REG(const u32 i) { OP_ARITHMETIC_R(ASR_REG; GET_CARRY(1), sbb, 1); } static int OP_RSC_S_ROR_IMM(const u32 i) { OP_ARITHMETIC_R(ROR_IMM; GET_CARRY(1), sbb, 1); } static int OP_RSC_S_ROR_REG(const u32 i) { OP_ARITHMETIC_R(ROR_REG; GET_CARRY(1), sbb, 1); } static int OP_RSC_S_IMM_VAL(const u32 i) { OP_ARITHMETIC_R(IMM_VAL; GET_CARRY(1), sbb, 1); } static int OP_BIC_LSL_IMM(const u32 i) { OP_ARITHMETIC(LSL_IMM; c.not_(rhs), and_, 1, 0); } static int OP_BIC_LSL_REG(const u32 i) { OP_ARITHMETIC(LSL_REG; c.not_(rhs), and_, 1, 0); } static int OP_BIC_LSR_IMM(const u32 i) { OP_ARITHMETIC(LSR_IMM; c.not_(rhs), and_, 1, 0); } static int OP_BIC_LSR_REG(const u32 i) { OP_ARITHMETIC(LSR_REG; c.not_(rhs), and_, 1, 0); } static int OP_BIC_ASR_IMM(const u32 i) { OP_ARITHMETIC(ASR_IMM; c.not_(rhs), and_, 1, 0); } static int OP_BIC_ASR_REG(const u32 i) { OP_ARITHMETIC(ASR_REG; c.not_(rhs), and_, 1, 0); } static int OP_BIC_ROR_IMM(const u32 i) { OP_ARITHMETIC(ROR_IMM; c.not_(rhs), and_, 1, 0); } static int OP_BIC_ROR_REG(const u32 i) { OP_ARITHMETIC(ROR_REG; c.not_(rhs), and_, 1, 0); } static int OP_BIC_IMM_VAL(const u32 i) { OP_ARITHMETIC(IMM_VAL; rhs = ~rhs, and_, 1, 0); } static int OP_BIC_S_LSL_IMM(const u32 i) { OP_ARITHMETIC_S(S_LSL_IMM; c.not_(rhs), and_, 1); } static int OP_BIC_S_LSL_REG(const u32 i) { OP_ARITHMETIC_S(S_LSL_REG; c.not_(rhs), and_, 1); } static int OP_BIC_S_LSR_IMM(const u32 i) { OP_ARITHMETIC_S(S_LSR_IMM; c.not_(rhs), and_, 1); } static int OP_BIC_S_LSR_REG(const u32 i) { OP_ARITHMETIC_S(S_LSR_REG; c.not_(rhs), and_, 1); } static int OP_BIC_S_ASR_IMM(const u32 i) { OP_ARITHMETIC_S(S_ASR_IMM; c.not_(rhs), and_, 1); } static int OP_BIC_S_ASR_REG(const u32 i) { OP_ARITHMETIC_S(S_ASR_REG; c.not_(rhs), and_, 1); } static int OP_BIC_S_ROR_IMM(const u32 i) { OP_ARITHMETIC_S(S_ROR_IMM; c.not_(rhs), and_, 1); } static int OP_BIC_S_ROR_REG(const u32 i) { OP_ARITHMETIC_S(S_ROR_REG; c.not_(rhs), and_, 1); } static int OP_BIC_S_IMM_VAL(const u32 i) { OP_ARITHMETIC_S(S_IMM_VAL; rhs = ~rhs, and_, 1); } //----------------------------------------------------------------------------- // TST //----------------------------------------------------------------------------- #define OP_TST_(arg) \ arg; \ c.test(reg_pos_ptr(16), rhs); \ SET_NZC; \ return 1; static int OP_TST_LSL_IMM(const u32 i) { OP_TST_(S_LSL_IMM); } static int OP_TST_LSL_REG(const u32 i) { OP_TST_(S_LSL_REG); } static int OP_TST_LSR_IMM(const u32 i) { OP_TST_(S_LSR_IMM); } static int OP_TST_LSR_REG(const u32 i) { OP_TST_(S_LSR_REG); } static int OP_TST_ASR_IMM(const u32 i) { OP_TST_(S_ASR_IMM); } static int OP_TST_ASR_REG(const u32 i) { OP_TST_(S_ASR_REG); } static int OP_TST_ROR_IMM(const u32 i) { OP_TST_(S_ROR_IMM); } static int OP_TST_ROR_REG(const u32 i) { OP_TST_(S_ROR_REG); } static int OP_TST_IMM_VAL(const u32 i) { OP_TST_(S_IMM_VAL); } //----------------------------------------------------------------------------- // TEQ //----------------------------------------------------------------------------- #define OP_TEQ_(arg) \ arg; \ if (!rhs_is_imm) \ c.xor_(*(GpVar*)&rhs, reg_pos_ptr(16)); \ else \ { \ GpVar x = c.newGpVar(kX86VarTypeGpd); \ c.mov(x, rhs); \ c.xor_(x, reg_pos_ptr(16)); \ } \ SET_NZC; \ return 1; static int OP_TEQ_LSL_IMM(const u32 i) { OP_TEQ_(S_LSL_IMM); } static int OP_TEQ_LSL_REG(const u32 i) { OP_TEQ_(S_LSL_REG); } static int OP_TEQ_LSR_IMM(const u32 i) { OP_TEQ_(S_LSR_IMM); } static int OP_TEQ_LSR_REG(const u32 i) { OP_TEQ_(S_LSR_REG); } static int OP_TEQ_ASR_IMM(const u32 i) { OP_TEQ_(S_ASR_IMM); } static int OP_TEQ_ASR_REG(const u32 i) { OP_TEQ_(S_ASR_REG); } static int OP_TEQ_ROR_IMM(const u32 i) { OP_TEQ_(S_ROR_IMM); } static int OP_TEQ_ROR_REG(const u32 i) { OP_TEQ_(S_ROR_REG); } static int OP_TEQ_IMM_VAL(const u32 i) { OP_TEQ_(S_IMM_VAL); } //----------------------------------------------------------------------------- // CMP //----------------------------------------------------------------------------- #define OP_CMP(arg) \ arg; \ c.cmp(reg_pos_ptr(16), rhs); \ SET_NZCV(1); \ return 1; static int OP_CMP_LSL_IMM(const u32 i) { OP_CMP(LSL_IMM); } static int OP_CMP_LSL_REG(const u32 i) { OP_CMP(LSL_REG); } static int OP_CMP_LSR_IMM(const u32 i) { OP_CMP(LSR_IMM); } static int OP_CMP_LSR_REG(const u32 i) { OP_CMP(LSR_REG); } static int OP_CMP_ASR_IMM(const u32 i) { OP_CMP(ASR_IMM); } static int OP_CMP_ASR_REG(const u32 i) { OP_CMP(ASR_REG); } static int OP_CMP_ROR_IMM(const u32 i) { OP_CMP(ROR_IMM); } static int OP_CMP_ROR_REG(const u32 i) { OP_CMP(ROR_REG); } static int OP_CMP_IMM_VAL(const u32 i) { OP_CMP(IMM_VAL); } #undef OP_CMP //----------------------------------------------------------------------------- // CMN //----------------------------------------------------------------------------- #define OP_CMN(arg) \ arg; \ u32 rhs_imm = *(u32*)&rhs; \ int sign = rhs_is_imm && (rhs_imm != -rhs_imm); \ if(sign) \ c.cmp(reg_pos_ptr(16), -rhs_imm); \ else \ { \ GpVar lhs = c.newGpVar(kX86VarTypeGpd); \ c.mov(lhs, reg_pos_ptr(16)); \ c.add(lhs, rhs); \ } \ SET_NZCV(sign); \ return 1; static int OP_CMN_LSL_IMM(const u32 i) { OP_CMN(LSL_IMM); } static int OP_CMN_LSL_REG(const u32 i) { OP_CMN(LSL_REG); } static int OP_CMN_LSR_IMM(const u32 i) { OP_CMN(LSR_IMM); } static int OP_CMN_LSR_REG(const u32 i) { OP_CMN(LSR_REG); } static int OP_CMN_ASR_IMM(const u32 i) { OP_CMN(ASR_IMM); } static int OP_CMN_ASR_REG(const u32 i) { OP_CMN(ASR_REG); } static int OP_CMN_ROR_IMM(const u32 i) { OP_CMN(ROR_IMM); } static int OP_CMN_ROR_REG(const u32 i) { OP_CMN(ROR_REG); } static int OP_CMN_IMM_VAL(const u32 i) { OP_CMN(IMM_VAL); } #undef OP_CMN //----------------------------------------------------------------------------- // MOV //----------------------------------------------------------------------------- #define OP_MOV(arg) \ arg; \ c.mov(reg_pos_ptr(12), rhs); \ if(REG_POS(i,12)==15) \ { \ c.mov(cpu_ptr(next_instruction), rhs); \ return 1; \ } \ return 1; static int OP_MOV_LSL_IMM(const u32 i) { if (i == 0xE1A00000) { /* nop */ JIT_COMMENT("nop"); return 1; } OP_MOV(LSL_IMM); } static int OP_MOV_LSL_REG(const u32 i) { OP_MOV(LSL_REG; if (REG_POS(i,0) == 15) c.add(rhs, 4);); } static int OP_MOV_LSR_IMM(const u32 i) { OP_MOV(LSR_IMM); } static int OP_MOV_LSR_REG(const u32 i) { OP_MOV(LSR_REG; if (REG_POS(i,0) == 15) c.add(rhs, 4);); } static int OP_MOV_ASR_IMM(const u32 i) { OP_MOV(ASR_IMM); } static int OP_MOV_ASR_REG(const u32 i) { OP_MOV(ASR_REG); } static int OP_MOV_ROR_IMM(const u32 i) { OP_MOV(ROR_IMM); } static int OP_MOV_ROR_REG(const u32 i) { OP_MOV(ROR_REG); } static int OP_MOV_IMM_VAL(const u32 i) { OP_MOV(IMM_VAL); } #define OP_MOV_S(arg) \ arg; \ c.mov(reg_pos_ptr(12), rhs); \ if(REG_POS(i,12)==15) \ { \ S_DST_R15; \ c.add(bb_total_cycles, 2); \ return 1; \ } \ if(!rhs_is_imm) \ c.cmp(*(GpVar*)&rhs, 0); \ else \ c.cmp(reg_pos_ptr(12), 0); \ SET_NZC; \ return 1; static int OP_MOV_S_LSL_IMM(const u32 i) { OP_MOV_S(S_LSL_IMM); } static int OP_MOV_S_LSL_REG(const u32 i) { OP_MOV_S(S_LSL_REG; if (REG_POS(i,0) == 15) c.add(rhs, 4);); } static int OP_MOV_S_LSR_IMM(const u32 i) { OP_MOV_S(S_LSR_IMM); } static int OP_MOV_S_LSR_REG(const u32 i) { OP_MOV_S(S_LSR_REG; if (REG_POS(i,0) == 15) c.add(rhs, 4);); } static int OP_MOV_S_ASR_IMM(const u32 i) { OP_MOV_S(S_ASR_IMM); } static int OP_MOV_S_ASR_REG(const u32 i) { OP_MOV_S(S_ASR_REG); } static int OP_MOV_S_ROR_IMM(const u32 i) { OP_MOV_S(S_ROR_IMM); } static int OP_MOV_S_ROR_REG(const u32 i) { OP_MOV_S(S_ROR_REG); } static int OP_MOV_S_IMM_VAL(const u32 i) { OP_MOV_S(S_IMM_VAL); } //----------------------------------------------------------------------------- // MVN //----------------------------------------------------------------------------- static int OP_MVN_LSL_IMM(const u32 i) { OP_MOV(LSL_IMM; c.not_(rhs)); } static int OP_MVN_LSL_REG(const u32 i) { OP_MOV(LSL_REG; c.not_(rhs)); } static int OP_MVN_LSR_IMM(const u32 i) { OP_MOV(LSR_IMM; c.not_(rhs)); } static int OP_MVN_LSR_REG(const u32 i) { OP_MOV(LSR_REG; c.not_(rhs)); } static int OP_MVN_ASR_IMM(const u32 i) { OP_MOV(ASR_IMM; c.not_(rhs)); } static int OP_MVN_ASR_REG(const u32 i) { OP_MOV(ASR_REG; c.not_(rhs)); } static int OP_MVN_ROR_IMM(const u32 i) { OP_MOV(ROR_IMM; c.not_(rhs)); } static int OP_MVN_ROR_REG(const u32 i) { OP_MOV(ROR_REG; c.not_(rhs)); } static int OP_MVN_IMM_VAL(const u32 i) { OP_MOV(IMM_VAL; rhs = ~rhs); } static int OP_MVN_S_LSL_IMM(const u32 i) { OP_MOV_S(S_LSL_IMM; c.not_(rhs)); } static int OP_MVN_S_LSL_REG(const u32 i) { OP_MOV_S(S_LSL_REG; c.not_(rhs)); } static int OP_MVN_S_LSR_IMM(const u32 i) { OP_MOV_S(S_LSR_IMM; c.not_(rhs)); } static int OP_MVN_S_LSR_REG(const u32 i) { OP_MOV_S(S_LSR_REG; c.not_(rhs)); } static int OP_MVN_S_ASR_IMM(const u32 i) { OP_MOV_S(S_ASR_IMM; c.not_(rhs)); } static int OP_MVN_S_ASR_REG(const u32 i) { OP_MOV_S(S_ASR_REG; c.not_(rhs)); } static int OP_MVN_S_ROR_IMM(const u32 i) { OP_MOV_S(S_ROR_IMM; c.not_(rhs)); } static int OP_MVN_S_ROR_REG(const u32 i) { OP_MOV_S(S_ROR_REG; c.not_(rhs)); } static int OP_MVN_S_IMM_VAL(const u32 i) { OP_MOV_S(S_IMM_VAL; rhs = ~rhs); } //----------------------------------------------------------------------------- // QADD / QDADD / QSUB / QDSUB //----------------------------------------------------------------------------- // TODO static int OP_QADD(const u32 i) { printf("JIT: unimplemented OP_QADD\n"); return 0; } static int OP_QSUB(const u32 i) { printf("JIT: unimplemented OP_QSUB\n"); return 0; } static int OP_QDADD(const u32 i) { printf("JIT: unimplemented OP_QDADD\n"); return 0; } static int OP_QDSUB(const u32 i) { printf("JIT: unimplemented OP_QDSUB\n"); return 0; } //----------------------------------------------------------------------------- // MUL //----------------------------------------------------------------------------- static void MUL_Mxx_END(GpVar x, bool sign, int cycles) { if(sign) { GpVar y = c.newGpVar(kX86VarTypeGpd); c.mov(y, x); c.sar(x, 31); c.xor_(x, y); } c.or_(x, 1); c.bsr(bb_cycles, x); c.shr(bb_cycles, 3); c.add(bb_cycles, cycles+1); } #define OP_MUL_(op, width, sign, accum, flags) \ GpVar lhs = c.newGpVar(kX86VarTypeGpd); \ GpVar rhs = c.newGpVar(kX86VarTypeGpd); \ GpVar hi; \ if (width) \ { \ hi = c.newGpVar(kX86VarTypeGpd); \ c.xor_(hi, hi); \ } \ c.mov(lhs, reg_pos_ptr(0)); \ c.mov(rhs, reg_pos_ptr(8)); \ op; \ if(width && accum) \ { \ if(flags) \ { \ c.add(lhs, reg_pos_ptr(12)); \ c.adc(hi, reg_pos_ptr(16)); \ c.mov(reg_pos_ptr(12), lhs); \ c.mov(reg_pos_ptr(16), hi); \ c.or_(lhs, hi); SET_Z; \ c.and_(hi, (1 << 31)); SET_N; \ } \ else \ { \ c.add(reg_pos_ptr(12), lhs); \ c.adc(reg_pos_ptr(16), hi); \ } \ } \ else if(width) \ { \ c.mov(reg_pos_ptr(12), lhs); \ c.mov(reg_pos_ptr(16), hi); \ if(flags) { c.cmp(hi, lhs); SET_NZ(0); } \ } \ else \ { \ if(accum) c.add(lhs, reg_pos_ptr(12)); \ c.mov(reg_pos_ptr(16), lhs); \ if(flags) { c.cmp(lhs, 0); SET_NZ(0); }\ } \ MUL_Mxx_END(rhs, sign, 1+width+accum); \ return 1; static int OP_MUL(const u32 i) { OP_MUL_(c.imul(lhs,rhs), 0, 1, 0, 0); } static int OP_MLA(const u32 i) { OP_MUL_(c.imul(lhs,rhs), 0, 1, 1, 0); } static int OP_UMULL(const u32 i) { OP_MUL_(c.mul(hi,lhs,rhs), 1, 0, 0, 0); } static int OP_UMLAL(const u32 i) { OP_MUL_(c.mul(hi,lhs,rhs), 1, 0, 1, 0); } static int OP_SMULL(const u32 i) { OP_MUL_(c.imul(hi,lhs,rhs), 1, 1, 0, 0); } static int OP_SMLAL(const u32 i) { OP_MUL_(c.imul(hi,lhs,rhs), 1, 1, 1, 0); } static int OP_MUL_S(const u32 i) { OP_MUL_(c.imul(lhs,rhs), 0, 1, 0, 1); } static int OP_MLA_S(const u32 i) { OP_MUL_(c.imul(lhs,rhs), 0, 1, 1, 1); } static int OP_UMULL_S(const u32 i) { OP_MUL_(c.mul(hi,lhs,rhs), 1, 0, 0, 1); } static int OP_UMLAL_S(const u32 i) { OP_MUL_(c.mul(hi,lhs,rhs), 1, 0, 1, 1); } static int OP_SMULL_S(const u32 i) { OP_MUL_(c.imul(hi,lhs,rhs), 1, 1, 0, 1); } static int OP_SMLAL_S(const u32 i) { OP_MUL_(c.imul(hi,lhs,rhs), 1, 1, 1, 1); } #define OP_MULxy_(op, x, y, width, accum, flags) \ GpVar lhs = c.newGpVar(kX86VarTypeGpd); \ GpVar rhs = c.newGpVar(kX86VarTypeGpd); \ GpVar hi; \ c.movsx(lhs, reg_pos_ptr##x(0)); \ c.movsx(rhs, reg_pos_ptr##y(8)); \ if (width) \ { \ hi = c.newGpVar(kX86VarTypeGpd); \ } \ op; \ if(width && accum) \ { \ if(flags) \ { \ c.add(lhs, reg_pos_ptr(12)); \ c.adc(hi, reg_pos_ptr(16)); \ c.mov(reg_pos_ptr(12), lhs); \ c.mov(reg_pos_ptr(16), hi); \ SET_Q; \ } \ else \ { \ c.add(reg_pos_ptr(12), lhs); \ c.adc(reg_pos_ptr(16), hi); \ } \ } \ else \ if(width) \ { \ c.mov(reg_pos_ptr(12), lhs); \ c.mov(reg_pos_ptr(16), hi); \ if(flags) { SET_Q; }\ } \ else \ { \ if (accum) c.add(lhs, reg_pos_ptr(12)); \ c.mov(reg_pos_ptr(16), lhs); \ if(flags) { SET_Q; }\ } \ return 1; //----------------------------------------------------------------------------- // SMUL //----------------------------------------------------------------------------- static int OP_SMUL_B_B(const u32 i) { OP_MULxy_(c.imul(lhs, rhs), L, L, 0, 0, 0); } static int OP_SMUL_B_T(const u32 i) { OP_MULxy_(c.imul(lhs, rhs), L, H, 0, 0, 0); } static int OP_SMUL_T_B(const u32 i) { OP_MULxy_(c.imul(lhs, rhs), H, L, 0, 0, 0); } static int OP_SMUL_T_T(const u32 i) { OP_MULxy_(c.imul(lhs, rhs), H, H, 0, 0, 0); } //----------------------------------------------------------------------------- // SMLA //----------------------------------------------------------------------------- static int OP_SMLA_B_B(const u32 i) { OP_MULxy_(c.imul(lhs, rhs), L, L, 0, 1, 1); } static int OP_SMLA_B_T(const u32 i) { OP_MULxy_(c.imul(lhs, rhs), L, H, 0, 1, 1); } static int OP_SMLA_T_B(const u32 i) { OP_MULxy_(c.imul(lhs, rhs), H, L, 0, 1, 1); } static int OP_SMLA_T_T(const u32 i) { OP_MULxy_(c.imul(lhs, rhs), H, H, 0, 1, 1); } //----------------------------------------------------------------------------- // SMLAL //----------------------------------------------------------------------------- static int OP_SMLAL_B_B(const u32 i) { OP_MULxy_(c.imul(hi,lhs,rhs), L, L, 1, 1, 1); } static int OP_SMLAL_B_T(const u32 i) { OP_MULxy_(c.imul(hi,lhs,rhs), L, H, 1, 1, 1); } static int OP_SMLAL_T_B(const u32 i) { OP_MULxy_(c.imul(hi,lhs,rhs), H, L, 1, 1, 1); } static int OP_SMLAL_T_T(const u32 i) { OP_MULxy_(c.imul(hi,lhs,rhs), H, H, 1, 1, 1); } //----------------------------------------------------------------------------- // SMULW / SMLAW //----------------------------------------------------------------------------- #ifdef ASMJIT_X64 #define OP_SMxxW_(x, accum, flags) \ GpVar lhs = c.newGpVar(kX86VarTypeGpz); \ GpVar rhs = c.newGpVar(kX86VarTypeGpz); \ c.movsx(lhs, reg_pos_ptr##x(8)); \ c.movsxd(rhs, reg_pos_ptr(0)); \ c.imul(lhs, rhs); \ c.sar(lhs, 16); \ if (accum) c.add(lhs, reg_pos_ptr(12)); \ c.mov(reg_pos_ptr(16), lhs.r32()); \ if (flags) { SET_Q; } \ return 1; #else #define OP_SMxxW_(x, accum, flags) \ GpVar rhs = c.newGpVar(kX86VarTypeGpd); \ GpVar lhs = c.newGpVar(kX86VarTypeGpd); \ GpVar hi = c.newGpVar(kX86VarTypeGpd); \ c.xor_(hi, hi); \ c.movsx(lhs, reg_pos_ptr##x(8)); \ c.mov(rhs, reg_pos_ptr(0)); \ c.imul(hi, lhs, rhs); \ c.mov(lhs.r16(), hi.r16()); \ c.ror(lhs, 16); \ if (accum) c.add(lhs, reg_pos_ptr(12)); \ c.mov(reg_pos_ptr(16), lhs); \ if (flags) { SET_Q; } \ return 1; #endif static int OP_SMULW_B(const u32 i) { OP_SMxxW_(L, 0, 0); } static int OP_SMULW_T(const u32 i) { OP_SMxxW_(H, 0, 0); } static int OP_SMLAW_B(const u32 i) { OP_SMxxW_(L, 1, 1); } static int OP_SMLAW_T(const u32 i) { OP_SMxxW_(H, 1, 1); } //----------------------------------------------------------------------------- // MRS / MSR //----------------------------------------------------------------------------- static int OP_MRS_CPSR(const u32 i) { GpVar x = c.newGpVar(kX86VarTypeGpd); c.mov(x, cpu_ptr(CPSR)); c.mov(reg_pos_ptr(12), x); return 1; } static int OP_MRS_SPSR(const u32 i) { GpVar x = c.newGpVar(kX86VarTypeGpd); c.mov(x, cpu_ptr(SPSR)); c.mov(reg_pos_ptr(12), x); return 1; } // TODO: SPSR: if(cpu->CPSR.bits.mode == USR || cpu->CPSR.bits.mode == SYS) return 1; #define OP_MSR_(reg, args, sw) \ GpVar operand = c.newGpVar(kX86VarTypeGpd); \ args; \ c.mov(operand, rhs); \ switch (((i>>16) & 0xF)) \ { \ case 0x1: /* bit 16 */ \ { \ GpVar mode = c.newGpVar(kX86VarTypeGpd); \ Label __skip = c.newLabel(); \ c.mov(mode, cpu_ptr(CPSR)); \ c.and_(mode, 0x1F); \ c.cmp(mode, USR); \ c.je(__skip); \ if (sw) \ { \ c.mov(mode, rhs); \ c.and_(mode, 0x1F); \ X86CompilerFuncCall* ctx = c.call((void*)armcpu_switchMode); \ ctx->setPrototype(kX86FuncConvDefault, FuncBuilder2()); \ ctx->setArgument(0, bb_cpu); \ ctx->setArgument(1, mode); \ } \ Mem xPSR_memB = cpu_ptr_byte(reg, 0); \ c.mov(xPSR_memB, operand.r8Lo()); \ changeCPSR; \ c.bind(__skip); \ } \ return 1; \ case 0x2: /* bit 17 */ \ { \ GpVar mode = c.newGpVar(kX86VarTypeGpd); \ Label __skip = c.newLabel(); \ c.mov(mode, cpu_ptr(CPSR)); \ c.and_(mode, 0x1F); \ c.cmp(mode, USR); \ c.je(__skip); \ Mem xPSR_memB = cpu_ptr_byte(reg, 1); \ c.shr(operand, 8); \ c.mov(xPSR_memB, operand.r8Lo()); \ changeCPSR; \ c.bind(__skip); \ } \ return 1; \ case 0x4: /* bit 18 */ \ { \ GpVar mode = c.newGpVar(kX86VarTypeGpd); \ Label __skip = c.newLabel(); \ c.mov(mode, cpu_ptr(CPSR)); \ c.and_(mode, 0x1F); \ c.cmp(mode, USR); \ c.je(__skip); \ Mem xPSR_memB = cpu_ptr_byte(reg, 2); \ c.shr(operand, 16); \ c.mov(xPSR_memB, operand.r8Lo()); \ changeCPSR; \ c.bind(__skip); \ } \ return 1; \ case 0x8: /* bit 19 */ \ { \ Mem xPSR_memB = cpu_ptr_byte(reg, 3); \ c.shr(operand, 24); \ c.mov(xPSR_memB, operand.r8Lo()); \ changeCPSR; \ } \ return 1; \ default: \ break; \ } \ \ static u32 byte_mask = (BIT16(i)?0x000000FF:0x00000000) | \ (BIT17(i)?0x0000FF00:0x00000000) | \ (BIT18(i)?0x00FF0000:0x00000000) | \ (BIT19(i)?0xFF000000:0x00000000); \ static u32 byte_mask_USR = (BIT19(i)?0xFF000000:0x00000000); \ \ Mem xPSR_mem = cpu_ptr(reg.val); \ GpVar xPSR = c.newGpVar(kX86VarTypeGpd); \ GpVar mode = c.newGpVar(kX86VarTypeGpd); \ Label __USR = c.newLabel(); \ Label __done = c.newLabel(); \ c.mov(mode, cpu_ptr(CPSR.val)); \ c.and_(mode, 0x1F); \ c.cmp(mode, USR); \ c.je(__USR); \ /* mode != USR */ \ if (sw && BIT16(i)) \ { \ /* armcpu_switchMode */ \ c.mov(mode, rhs); \ c.and_(mode, 0x1F); \ X86CompilerFuncCall* ctx = c.call((void*)armcpu_switchMode); \ ctx->setPrototype(kX86FuncConvDefault, FuncBuilder2()); \ ctx->setArgument(0, bb_cpu); \ ctx->setArgument(1, mode); \ } \ /* cpu->CPSR.val = (cpu->CPSR.val & ~byte_mask) | (operand & byte_mask); */ \ c.mov(xPSR, xPSR_mem); \ c.and_(operand, byte_mask); \ c.and_(xPSR, ~byte_mask); \ c.or_(xPSR, operand); \ c.mov(xPSR_mem, xPSR); \ c.jmp(__done); \ /* mode == USR */ \ c.bind(__USR); \ c.mov(xPSR, xPSR_mem); \ c.and_(operand, byte_mask_USR); \ c.and_(xPSR, ~byte_mask_USR); \ c.or_(xPSR, operand); \ c.mov(xPSR_mem, xPSR); \ c.bind(__done); \ changeCPSR; \ return 1; static int OP_MSR_CPSR(const u32 i) { OP_MSR_(CPSR, REG_OFF, 1); } static int OP_MSR_SPSR(const u32 i) { OP_MSR_(SPSR, REG_OFF, 0); } static int OP_MSR_CPSR_IMM_VAL(const u32 i) { OP_MSR_(CPSR, IMM_VAL, 1); } static int OP_MSR_SPSR_IMM_VAL(const u32 i) { OP_MSR_(SPSR, IMM_VAL, 0); } //----------------------------------------------------------------------------- // LDR //----------------------------------------------------------------------------- typedef u32 (FASTCALL* OpLDR)(u32, u32*); // 98% of all memory accesses land in the same region as the first execution of // that instruction, so keep multiple copies with different fastpaths. // The copies don't need to differ in any way; the point is merely to cooperate // with x86 branch prediction. enum { MEMTYPE_GENERIC = 0, // no assumptions MEMTYPE_MAIN = 1, MEMTYPE_DTCM = 2, MEMTYPE_ERAM = 3, MEMTYPE_SWIRAM = 4, MEMTYPE_OTHER = 5, // memory that is known to not be MAIN, DTCM, ERAM, or SWIRAM }; static u32 classify_adr(u32 adr, bool store) { if(PROCNUM==ARMCPU_ARM9 && (adr & ~0x3FFF) == MMU.DTCMRegion) return MEMTYPE_DTCM; else if((adr & 0x0F000000) == 0x02000000) return MEMTYPE_MAIN; else if(PROCNUM==ARMCPU_ARM7 && !store && (adr & 0xFF800000) == 0x03800000) return MEMTYPE_ERAM; else if(PROCNUM==ARMCPU_ARM7 && !store && (adr & 0xFF800000) == 0x03000000) return MEMTYPE_SWIRAM; else return MEMTYPE_GENERIC; } template static u32 FASTCALL OP_LDR(u32 adr, u32 *dstreg) { u32 data = READ32(cpu->mem_if->data, adr); if(adr&3) data = ROR(data, 8*(adr&3)); *dstreg = data; return MMU_aluMemAccessCycles(3,adr); } template static u32 FASTCALL OP_LDRH(u32 adr, u32 *dstreg) { *dstreg = READ16(cpu->mem_if->data, adr); return MMU_aluMemAccessCycles(3,adr); } template static u32 FASTCALL OP_LDRSH(u32 adr, u32 *dstreg) { *dstreg = (s16)READ16(cpu->mem_if->data, adr); return MMU_aluMemAccessCycles(3,adr); } template static u32 FASTCALL OP_LDRB(u32 adr, u32 *dstreg) { *dstreg = READ8(cpu->mem_if->data, adr); return MMU_aluMemAccessCycles(3,adr); } template static u32 FASTCALL OP_LDRSB(u32 adr, u32 *dstreg) { *dstreg = (s8)READ8(cpu->mem_if->data, adr); return MMU_aluMemAccessCycles(3,adr); } #define T(op) op<0,0>, op<0,1>, op<0,2>, NULL, NULL, op<1,0>, op<1,1>, NULL, op<1,3>, op<1,4> static const OpLDR LDR_tab[2][5] = { T(OP_LDR) }; static const OpLDR LDRH_tab[2][5] = { T(OP_LDRH) }; static const OpLDR LDRSH_tab[2][5] = { T(OP_LDRSH) }; static const OpLDR LDRB_tab[2][5] = { T(OP_LDRB) }; static const OpLDR LDRSB_tab[2][5] = { T(OP_LDRSB) }; #undef T static u32 add(u32 lhs, u32 rhs) { return lhs + rhs; } static u32 sub(u32 lhs, u32 rhs) { return lhs - rhs; } #define OP_LDR_(mem_op, arg, sign_op, writeback) \ GpVar adr = c.newGpVar(kX86VarTypeGpd); \ GpVar dst = c.newGpVar(kX86VarTypeGpz); \ c.mov(adr, reg_pos_ptr(16)); \ c.lea(dst, reg_pos_ptr(12)); \ arg; \ if(!rhs_is_imm || *(u32*)&rhs) \ { \ if(writeback == 0) \ c.sign_op(adr, rhs); \ else if(writeback < 0) \ { \ c.sign_op(adr, rhs); \ c.mov(reg_pos_ptr(16), adr); \ } \ else if(writeback > 0) \ { \ GpVar tmp_reg = c.newGpVar(kX86VarTypeGpd); \ c.mov(tmp_reg, adr); \ c.sign_op(tmp_reg, rhs); \ c.mov(reg_pos_ptr(16), tmp_reg); \ } \ } \ u32 adr_first = sign_op(cpu->R[REG_POS(i,16)], rhs_first); \ X86CompilerFuncCall *ctx = c.call((void*)mem_op##_tab[PROCNUM][classify_adr(adr_first,0)]); \ ctx->setPrototype(ASMJIT_CALL_CONV, FuncBuilder2()); \ ctx->setArgument(0, adr); \ ctx->setArgument(1, dst); \ ctx->setReturn(bb_cycles); \ if(REG_POS(i,12)==15) \ { \ GpVar tmp = c.newGpVar(kX86VarTypeGpd); \ c.mov(tmp, reg_ptr(15)); \ if (PROCNUM == 0) \ { \ GpVar thumb = c.newGpVar(kX86VarTypeGpz); \ c.mov(thumb, tmp); \ c.and_(thumb, 1); \ c.shl(thumb, 5); \ c.or_(cpu_ptr(CPSR), thumb.r64()); \ c.and_(tmp, 0xFFFFFFFE); \ } \ else \ { \ c.and_(tmp, 0xFFFFFFFC); \ } \ c.mov(cpu_ptr(next_instruction), tmp); \ } \ return 1; // LDR static int OP_LDR_P_IMM_OFF(const u32 i) { OP_LDR_(LDR, IMM_OFF_12, add, 0); } static int OP_LDR_M_IMM_OFF(const u32 i) { OP_LDR_(LDR, IMM_OFF_12, sub, 0); } static int OP_LDR_P_LSL_IMM_OFF(const u32 i) { OP_LDR_(LDR, LSL_IMM, add, 0); } static int OP_LDR_M_LSL_IMM_OFF(const u32 i) { OP_LDR_(LDR, LSL_IMM, sub, 0); } static int OP_LDR_P_LSR_IMM_OFF(const u32 i) { OP_LDR_(LDR, LSR_IMM, add, 0); } static int OP_LDR_M_LSR_IMM_OFF(const u32 i) { OP_LDR_(LDR, LSR_IMM, sub, 0); } static int OP_LDR_P_ASR_IMM_OFF(const u32 i) { OP_LDR_(LDR, ASR_IMM, add, 0); } static int OP_LDR_M_ASR_IMM_OFF(const u32 i) { OP_LDR_(LDR, ASR_IMM, sub, 0); } static int OP_LDR_P_ROR_IMM_OFF(const u32 i) { OP_LDR_(LDR, ROR_IMM, add, 0); } static int OP_LDR_M_ROR_IMM_OFF(const u32 i) { OP_LDR_(LDR, ROR_IMM, sub, 0); } static int OP_LDR_P_IMM_OFF_PREIND(const u32 i) { OP_LDR_(LDR, IMM_OFF_12, add, -1); } static int OP_LDR_M_IMM_OFF_PREIND(const u32 i) { OP_LDR_(LDR, IMM_OFF_12, sub, -1); } static int OP_LDR_P_LSL_IMM_OFF_PREIND(const u32 i) { OP_LDR_(LDR, LSL_IMM, add, -1); } static int OP_LDR_M_LSL_IMM_OFF_PREIND(const u32 i) { OP_LDR_(LDR, LSL_IMM, sub, -1); } static int OP_LDR_P_LSR_IMM_OFF_PREIND(const u32 i) { OP_LDR_(LDR, LSR_IMM, add, -1); } static int OP_LDR_M_LSR_IMM_OFF_PREIND(const u32 i) { OP_LDR_(LDR, LSR_IMM, sub, -1); } static int OP_LDR_P_ASR_IMM_OFF_PREIND(const u32 i) { OP_LDR_(LDR, ASR_IMM, add, -1); } static int OP_LDR_M_ASR_IMM_OFF_PREIND(const u32 i) { OP_LDR_(LDR, ASR_IMM, sub, -1); } static int OP_LDR_P_ROR_IMM_OFF_PREIND(const u32 i) { OP_LDR_(LDR, ROR_IMM, add, -1); } static int OP_LDR_M_ROR_IMM_OFF_PREIND(const u32 i) { OP_LDR_(LDR, ROR_IMM, sub, -1); } static int OP_LDR_P_IMM_OFF_POSTIND(const u32 i) { OP_LDR_(LDR, IMM_OFF_12, add, 1); } static int OP_LDR_M_IMM_OFF_POSTIND(const u32 i) { OP_LDR_(LDR, IMM_OFF_12, sub, 1); } static int OP_LDR_P_LSL_IMM_OFF_POSTIND(const u32 i) { OP_LDR_(LDR, LSL_IMM, add, 1); } static int OP_LDR_M_LSL_IMM_OFF_POSTIND(const u32 i) { OP_LDR_(LDR, LSL_IMM, sub, 1); } static int OP_LDR_P_LSR_IMM_OFF_POSTIND(const u32 i) { OP_LDR_(LDR, LSR_IMM, add, 1); } static int OP_LDR_M_LSR_IMM_OFF_POSTIND(const u32 i) { OP_LDR_(LDR, LSR_IMM, sub, 1); } static int OP_LDR_P_ASR_IMM_OFF_POSTIND(const u32 i) { OP_LDR_(LDR, ASR_IMM, add, 1); } static int OP_LDR_M_ASR_IMM_OFF_POSTIND(const u32 i) { OP_LDR_(LDR, ASR_IMM, sub, 1); } static int OP_LDR_P_ROR_IMM_OFF_POSTIND(const u32 i) { OP_LDR_(LDR, ROR_IMM, add, 1); } static int OP_LDR_M_ROR_IMM_OFF_POSTIND(const u32 i) { OP_LDR_(LDR, ROR_IMM, sub, 1); } // LDRH static int OP_LDRH_P_IMM_OFF(const u32 i) { OP_LDR_(LDRH, IMM_OFF, add, 0); } static int OP_LDRH_M_IMM_OFF(const u32 i) { OP_LDR_(LDRH, IMM_OFF, sub, 0); } static int OP_LDRH_P_REG_OFF(const u32 i) { OP_LDR_(LDRH, REG_OFF, add, 0); } static int OP_LDRH_M_REG_OFF(const u32 i) { OP_LDR_(LDRH, REG_OFF, sub, 0); } static int OP_LDRH_PRE_INDE_P_IMM_OFF(const u32 i) { OP_LDR_(LDRH, IMM_OFF, add, -1); } static int OP_LDRH_PRE_INDE_M_IMM_OFF(const u32 i) { OP_LDR_(LDRH, IMM_OFF, sub, -1); } static int OP_LDRH_PRE_INDE_P_REG_OFF(const u32 i) { OP_LDR_(LDRH, REG_OFF, add, -1); } static int OP_LDRH_PRE_INDE_M_REG_OFF(const u32 i) { OP_LDR_(LDRH, REG_OFF, sub, -1); } static int OP_LDRH_POS_INDE_P_IMM_OFF(const u32 i) { OP_LDR_(LDRH, IMM_OFF, add, 1); } static int OP_LDRH_POS_INDE_M_IMM_OFF(const u32 i) { OP_LDR_(LDRH, IMM_OFF, sub, 1); } static int OP_LDRH_POS_INDE_P_REG_OFF(const u32 i) { OP_LDR_(LDRH, REG_OFF, add, 1); } static int OP_LDRH_POS_INDE_M_REG_OFF(const u32 i) { OP_LDR_(LDRH, REG_OFF, sub, 1); } // LDRSH static int OP_LDRSH_P_IMM_OFF(const u32 i) { OP_LDR_(LDRSH, IMM_OFF, add, 0); } static int OP_LDRSH_M_IMM_OFF(const u32 i) { OP_LDR_(LDRSH, IMM_OFF, sub, 0); } static int OP_LDRSH_P_REG_OFF(const u32 i) { OP_LDR_(LDRSH, REG_OFF, add, 0); } static int OP_LDRSH_M_REG_OFF(const u32 i) { OP_LDR_(LDRSH, REG_OFF, sub, 0); } static int OP_LDRSH_PRE_INDE_P_IMM_OFF(const u32 i) { OP_LDR_(LDRSH, IMM_OFF, add, -1); } static int OP_LDRSH_PRE_INDE_M_IMM_OFF(const u32 i) { OP_LDR_(LDRSH, IMM_OFF, sub, -1); } static int OP_LDRSH_PRE_INDE_P_REG_OFF(const u32 i) { OP_LDR_(LDRSH, REG_OFF, add, -1); } static int OP_LDRSH_PRE_INDE_M_REG_OFF(const u32 i) { OP_LDR_(LDRSH, REG_OFF, sub, -1); } static int OP_LDRSH_POS_INDE_P_IMM_OFF(const u32 i) { OP_LDR_(LDRSH, IMM_OFF, add, 1); } static int OP_LDRSH_POS_INDE_M_IMM_OFF(const u32 i) { OP_LDR_(LDRSH, IMM_OFF, sub, 1); } static int OP_LDRSH_POS_INDE_P_REG_OFF(const u32 i) { OP_LDR_(LDRSH, REG_OFF, add, 1); } static int OP_LDRSH_POS_INDE_M_REG_OFF(const u32 i) { OP_LDR_(LDRSH, REG_OFF, sub, 1); } // LDRB static int OP_LDRB_P_IMM_OFF(const u32 i) { OP_LDR_(LDRB, IMM_OFF_12, add, 0); } static int OP_LDRB_M_IMM_OFF(const u32 i) { OP_LDR_(LDRB, IMM_OFF_12, sub, 0); } static int OP_LDRB_P_LSL_IMM_OFF(const u32 i) { OP_LDR_(LDRB, LSL_IMM, add, 0); } static int OP_LDRB_M_LSL_IMM_OFF(const u32 i) { OP_LDR_(LDRB, LSL_IMM, sub, 0); } static int OP_LDRB_P_LSR_IMM_OFF(const u32 i) { OP_LDR_(LDRB, LSR_IMM, add, 0); } static int OP_LDRB_M_LSR_IMM_OFF(const u32 i) { OP_LDR_(LDRB, LSR_IMM, sub, 0); } static int OP_LDRB_P_ASR_IMM_OFF(const u32 i) { OP_LDR_(LDRB, ASR_IMM, add, 0); } static int OP_LDRB_M_ASR_IMM_OFF(const u32 i) { OP_LDR_(LDRB, ASR_IMM, sub, 0); } static int OP_LDRB_P_ROR_IMM_OFF(const u32 i) { OP_LDR_(LDRB, ROR_IMM, add, 0); } static int OP_LDRB_M_ROR_IMM_OFF(const u32 i) { OP_LDR_(LDRB, ROR_IMM, sub, 0); } static int OP_LDRB_P_IMM_OFF_PREIND(const u32 i) { OP_LDR_(LDRB, IMM_OFF_12, add, -1); } static int OP_LDRB_M_IMM_OFF_PREIND(const u32 i) { OP_LDR_(LDRB, IMM_OFF_12, sub, -1); } static int OP_LDRB_P_LSL_IMM_OFF_PREIND(const u32 i) { OP_LDR_(LDRB, LSL_IMM, add, -1); } static int OP_LDRB_M_LSL_IMM_OFF_PREIND(const u32 i) { OP_LDR_(LDRB, LSL_IMM, sub, -1); } static int OP_LDRB_P_LSR_IMM_OFF_PREIND(const u32 i) { OP_LDR_(LDRB, LSR_IMM, add, -1); } static int OP_LDRB_M_LSR_IMM_OFF_PREIND(const u32 i) { OP_LDR_(LDRB, LSR_IMM, sub, -1); } static int OP_LDRB_P_ASR_IMM_OFF_PREIND(const u32 i) { OP_LDR_(LDRB, ASR_IMM, add, -1); } static int OP_LDRB_M_ASR_IMM_OFF_PREIND(const u32 i) { OP_LDR_(LDRB, ASR_IMM, sub, -1); } static int OP_LDRB_P_ROR_IMM_OFF_PREIND(const u32 i) { OP_LDR_(LDRB, ROR_IMM, add, -1); } static int OP_LDRB_M_ROR_IMM_OFF_PREIND(const u32 i) { OP_LDR_(LDRB, ROR_IMM, sub, -1); } static int OP_LDRB_P_IMM_OFF_POSTIND(const u32 i) { OP_LDR_(LDRB, IMM_OFF_12, add, 1); } static int OP_LDRB_M_IMM_OFF_POSTIND(const u32 i) { OP_LDR_(LDRB, IMM_OFF_12, sub, 1); } static int OP_LDRB_P_LSL_IMM_OFF_POSTIND(const u32 i) { OP_LDR_(LDRB, LSL_IMM, add, 1); } static int OP_LDRB_M_LSL_IMM_OFF_POSTIND(const u32 i) { OP_LDR_(LDRB, LSL_IMM, sub, 1); } static int OP_LDRB_P_LSR_IMM_OFF_POSTIND(const u32 i) { OP_LDR_(LDRB, LSR_IMM, add, 1); } static int OP_LDRB_M_LSR_IMM_OFF_POSTIND(const u32 i) { OP_LDR_(LDRB, LSR_IMM, sub, 1); } static int OP_LDRB_P_ASR_IMM_OFF_POSTIND(const u32 i) { OP_LDR_(LDRB, ASR_IMM, add, 1); } static int OP_LDRB_M_ASR_IMM_OFF_POSTIND(const u32 i) { OP_LDR_(LDRB, ASR_IMM, sub, 1); } static int OP_LDRB_P_ROR_IMM_OFF_POSTIND(const u32 i) { OP_LDR_(LDRB, ROR_IMM, add, 1); } static int OP_LDRB_M_ROR_IMM_OFF_POSTIND(const u32 i) { OP_LDR_(LDRB, ROR_IMM, sub, 1); } // LDRSB static int OP_LDRSB_P_IMM_OFF(const u32 i) { OP_LDR_(LDRSB, IMM_OFF, add, 0); } static int OP_LDRSB_M_IMM_OFF(const u32 i) { OP_LDR_(LDRSB, IMM_OFF, sub, 0); } static int OP_LDRSB_P_REG_OFF(const u32 i) { OP_LDR_(LDRSB, REG_OFF, add, 0); } static int OP_LDRSB_M_REG_OFF(const u32 i) { OP_LDR_(LDRSB, REG_OFF, sub, 0); } static int OP_LDRSB_PRE_INDE_P_IMM_OFF(const u32 i) { OP_LDR_(LDRSB, IMM_OFF, add, -1); } static int OP_LDRSB_PRE_INDE_M_IMM_OFF(const u32 i) { OP_LDR_(LDRSB, IMM_OFF, sub, -1); } static int OP_LDRSB_PRE_INDE_P_REG_OFF(const u32 i) { OP_LDR_(LDRSB, REG_OFF, add, -1); } static int OP_LDRSB_PRE_INDE_M_REG_OFF(const u32 i) { OP_LDR_(LDRSB, REG_OFF, sub, -1); } static int OP_LDRSB_POS_INDE_P_IMM_OFF(const u32 i) { OP_LDR_(LDRSB, IMM_OFF, add, 1); } static int OP_LDRSB_POS_INDE_M_IMM_OFF(const u32 i) { OP_LDR_(LDRSB, IMM_OFF, sub, 1); } static int OP_LDRSB_POS_INDE_P_REG_OFF(const u32 i) { OP_LDR_(LDRSB, REG_OFF, add, 1); } static int OP_LDRSB_POS_INDE_M_REG_OFF(const u32 i) { OP_LDR_(LDRSB, REG_OFF, sub, 1); } //----------------------------------------------------------------------------- // STR //----------------------------------------------------------------------------- template static u32 FASTCALL OP_STR(u32 adr, u32 data) { WRITE32(cpu->mem_if->data, adr, data); return MMU_aluMemAccessCycles(2,adr); } template static u32 FASTCALL OP_STRH(u32 adr, u32 data) { WRITE16(cpu->mem_if->data, adr, data); return MMU_aluMemAccessCycles(2,adr); } template static u32 FASTCALL OP_STRB(u32 adr, u32 data) { WRITE8(cpu->mem_if->data, adr, data); return MMU_aluMemAccessCycles(2,adr); } typedef u32 (FASTCALL* OpSTR)(u32, u32); #define T(op) op<0,0>, op<0,1>, op<0,2>, op<1,0>, op<1,1>, NULL static const OpSTR STR_tab[2][3] = { T(OP_STR) }; static const OpSTR STRH_tab[2][3] = { T(OP_STRH) }; static const OpSTR STRB_tab[2][3] = { T(OP_STRB) }; #undef T #define OP_STR_(mem_op, arg, sign_op, writeback) \ GpVar adr = c.newGpVar(kX86VarTypeGpd); \ GpVar data = c.newGpVar(kX86VarTypeGpd); \ c.mov(adr, reg_pos_ptr(16)); \ c.mov(data, reg_pos_ptr(12)); \ arg; \ if(!rhs_is_imm || *(u32*)&rhs) \ { \ if(writeback == 0) \ c.sign_op(adr, rhs); \ else if(writeback < 0) \ { \ c.sign_op(adr, rhs); \ c.mov(reg_pos_ptr(16), adr); \ } \ else if(writeback > 0) \ { \ GpVar tmp_reg = c.newGpVar(kX86VarTypeGpd); \ c.mov(tmp_reg, adr); \ c.sign_op(tmp_reg, rhs); \ c.mov(reg_pos_ptr(16), tmp_reg); \ } \ } \ u32 adr_first = sign_op(cpu->R[REG_POS(i,16)], rhs_first); \ X86CompilerFuncCall *ctx = c.call((void*)mem_op##_tab[PROCNUM][classify_adr(adr_first,1)]); \ ctx->setPrototype(ASMJIT_CALL_CONV, FuncBuilder2()); \ ctx->setArgument(0, adr); \ ctx->setArgument(1, data); \ ctx->setReturn(bb_cycles); \ return 1; static int OP_STR_P_IMM_OFF(const u32 i) { OP_STR_(STR, IMM_OFF_12, add, 0); } static int OP_STR_M_IMM_OFF(const u32 i) { OP_STR_(STR, IMM_OFF_12, sub, 0); } static int OP_STR_P_LSL_IMM_OFF(const u32 i) { OP_STR_(STR, LSL_IMM, add, 0); } static int OP_STR_M_LSL_IMM_OFF(const u32 i) { OP_STR_(STR, LSL_IMM, sub, 0); } static int OP_STR_P_LSR_IMM_OFF(const u32 i) { OP_STR_(STR, LSR_IMM, add, 0); } static int OP_STR_M_LSR_IMM_OFF(const u32 i) { OP_STR_(STR, LSR_IMM, sub, 0); } static int OP_STR_P_ASR_IMM_OFF(const u32 i) { OP_STR_(STR, ASR_IMM, add, 0); } static int OP_STR_M_ASR_IMM_OFF(const u32 i) { OP_STR_(STR, ASR_IMM, sub, 0); } static int OP_STR_P_ROR_IMM_OFF(const u32 i) { OP_STR_(STR, ROR_IMM, add, 0); } static int OP_STR_M_ROR_IMM_OFF(const u32 i) { OP_STR_(STR, ROR_IMM, sub, 0); } static int OP_STR_P_IMM_OFF_PREIND(const u32 i) { OP_STR_(STR, IMM_OFF_12, add, -1); } static int OP_STR_M_IMM_OFF_PREIND(const u32 i) { OP_STR_(STR, IMM_OFF_12, sub, -1); } static int OP_STR_P_LSL_IMM_OFF_PREIND(const u32 i) { OP_STR_(STR, LSL_IMM, add, -1); } static int OP_STR_M_LSL_IMM_OFF_PREIND(const u32 i) { OP_STR_(STR, LSL_IMM, sub, -1); } static int OP_STR_P_LSR_IMM_OFF_PREIND(const u32 i) { OP_STR_(STR, LSR_IMM, add, -1); } static int OP_STR_M_LSR_IMM_OFF_PREIND(const u32 i) { OP_STR_(STR, LSR_IMM, sub, -1); } static int OP_STR_P_ASR_IMM_OFF_PREIND(const u32 i) { OP_STR_(STR, ASR_IMM, add, -1); } static int OP_STR_M_ASR_IMM_OFF_PREIND(const u32 i) { OP_STR_(STR, ASR_IMM, sub, -1); } static int OP_STR_P_ROR_IMM_OFF_PREIND(const u32 i) { OP_STR_(STR, ROR_IMM, add, -1); } static int OP_STR_M_ROR_IMM_OFF_PREIND(const u32 i) { OP_STR_(STR, ROR_IMM, sub, -1); } static int OP_STR_P_IMM_OFF_POSTIND(const u32 i) { OP_STR_(STR, IMM_OFF_12, add, 1); } static int OP_STR_M_IMM_OFF_POSTIND(const u32 i) { OP_STR_(STR, IMM_OFF_12, sub, 1); } static int OP_STR_P_LSL_IMM_OFF_POSTIND(const u32 i) { OP_STR_(STR, LSL_IMM, add, 1); } static int OP_STR_M_LSL_IMM_OFF_POSTIND(const u32 i) { OP_STR_(STR, LSL_IMM, sub, 1); } static int OP_STR_P_LSR_IMM_OFF_POSTIND(const u32 i) { OP_STR_(STR, LSR_IMM, add, 1); } static int OP_STR_M_LSR_IMM_OFF_POSTIND(const u32 i) { OP_STR_(STR, LSR_IMM, sub, 1); } static int OP_STR_P_ASR_IMM_OFF_POSTIND(const u32 i) { OP_STR_(STR, ASR_IMM, add, 1); } static int OP_STR_M_ASR_IMM_OFF_POSTIND(const u32 i) { OP_STR_(STR, ASR_IMM, sub, 1); } static int OP_STR_P_ROR_IMM_OFF_POSTIND(const u32 i) { OP_STR_(STR, ROR_IMM, add, 1); } static int OP_STR_M_ROR_IMM_OFF_POSTIND(const u32 i) { OP_STR_(STR, ROR_IMM, sub, 1); } static int OP_STRH_P_IMM_OFF(const u32 i) { OP_STR_(STRH, IMM_OFF, add, 0); } static int OP_STRH_M_IMM_OFF(const u32 i) { OP_STR_(STRH, IMM_OFF, sub, 0); } static int OP_STRH_P_REG_OFF(const u32 i) { OP_STR_(STRH, REG_OFF, add, 0); } static int OP_STRH_M_REG_OFF(const u32 i) { OP_STR_(STRH, REG_OFF, sub, 0); } static int OP_STRH_PRE_INDE_P_IMM_OFF(const u32 i) { OP_STR_(STRH, IMM_OFF, add, -1); } static int OP_STRH_PRE_INDE_M_IMM_OFF(const u32 i) { OP_STR_(STRH, IMM_OFF, sub, -1); } static int OP_STRH_PRE_INDE_P_REG_OFF(const u32 i) { OP_STR_(STRH, REG_OFF, add, -1); } static int OP_STRH_PRE_INDE_M_REG_OFF(const u32 i) { OP_STR_(STRH, REG_OFF, sub, -1); } static int OP_STRH_POS_INDE_P_IMM_OFF(const u32 i) { OP_STR_(STRH, IMM_OFF, add, 1); } static int OP_STRH_POS_INDE_M_IMM_OFF(const u32 i) { OP_STR_(STRH, IMM_OFF, sub, 1); } static int OP_STRH_POS_INDE_P_REG_OFF(const u32 i) { OP_STR_(STRH, REG_OFF, add, 1); } static int OP_STRH_POS_INDE_M_REG_OFF(const u32 i) { OP_STR_(STRH, REG_OFF, sub, 1); } static int OP_STRB_P_IMM_OFF(const u32 i) { OP_STR_(STRB, IMM_OFF_12, add, 0); } static int OP_STRB_M_IMM_OFF(const u32 i) { OP_STR_(STRB, IMM_OFF_12, sub, 0); } static int OP_STRB_P_LSL_IMM_OFF(const u32 i) { OP_STR_(STRB, LSL_IMM, add, 0); } static int OP_STRB_M_LSL_IMM_OFF(const u32 i) { OP_STR_(STRB, LSL_IMM, sub, 0); } static int OP_STRB_P_LSR_IMM_OFF(const u32 i) { OP_STR_(STRB, LSR_IMM, add, 0); } static int OP_STRB_M_LSR_IMM_OFF(const u32 i) { OP_STR_(STRB, LSR_IMM, sub, 0); } static int OP_STRB_P_ASR_IMM_OFF(const u32 i) { OP_STR_(STRB, ASR_IMM, add, 0); } static int OP_STRB_M_ASR_IMM_OFF(const u32 i) { OP_STR_(STRB, ASR_IMM, sub, 0); } static int OP_STRB_P_ROR_IMM_OFF(const u32 i) { OP_STR_(STRB, ROR_IMM, add, 0); } static int OP_STRB_M_ROR_IMM_OFF(const u32 i) { OP_STR_(STRB, ROR_IMM, sub, 0); } static int OP_STRB_P_IMM_OFF_PREIND(const u32 i) { OP_STR_(STRB, IMM_OFF_12, add, -1); } static int OP_STRB_M_IMM_OFF_PREIND(const u32 i) { OP_STR_(STRB, IMM_OFF_12, sub, -1); } static int OP_STRB_P_LSL_IMM_OFF_PREIND(const u32 i) { OP_STR_(STRB, LSL_IMM, add, -1); } static int OP_STRB_M_LSL_IMM_OFF_PREIND(const u32 i) { OP_STR_(STRB, LSL_IMM, sub, -1); } static int OP_STRB_P_LSR_IMM_OFF_PREIND(const u32 i) { OP_STR_(STRB, LSR_IMM, add, -1); } static int OP_STRB_M_LSR_IMM_OFF_PREIND(const u32 i) { OP_STR_(STRB, LSR_IMM, sub, -1); } static int OP_STRB_P_ASR_IMM_OFF_PREIND(const u32 i) { OP_STR_(STRB, ASR_IMM, add, -1); } static int OP_STRB_M_ASR_IMM_OFF_PREIND(const u32 i) { OP_STR_(STRB, ASR_IMM, sub, -1); } static int OP_STRB_P_ROR_IMM_OFF_PREIND(const u32 i) { OP_STR_(STRB, ROR_IMM, add, -1); } static int OP_STRB_M_ROR_IMM_OFF_PREIND(const u32 i) { OP_STR_(STRB, ROR_IMM, sub, -1); } static int OP_STRB_P_IMM_OFF_POSTIND(const u32 i) { OP_STR_(STRB, IMM_OFF_12, add, 1); } static int OP_STRB_M_IMM_OFF_POSTIND(const u32 i) { OP_STR_(STRB, IMM_OFF_12, sub, 1); } static int OP_STRB_P_LSL_IMM_OFF_POSTIND(const u32 i) { OP_STR_(STRB, LSL_IMM, add, 1); } static int OP_STRB_M_LSL_IMM_OFF_POSTIND(const u32 i) { OP_STR_(STRB, LSL_IMM, sub, 1); } static int OP_STRB_P_LSR_IMM_OFF_POSTIND(const u32 i) { OP_STR_(STRB, LSR_IMM, add, 1); } static int OP_STRB_M_LSR_IMM_OFF_POSTIND(const u32 i) { OP_STR_(STRB, LSR_IMM, sub, 1); } static int OP_STRB_P_ASR_IMM_OFF_POSTIND(const u32 i) { OP_STR_(STRB, ASR_IMM, add, 1); } static int OP_STRB_M_ASR_IMM_OFF_POSTIND(const u32 i) { OP_STR_(STRB, ASR_IMM, sub, 1); } static int OP_STRB_P_ROR_IMM_OFF_POSTIND(const u32 i) { OP_STR_(STRB, ROR_IMM, add, 1); } static int OP_STRB_M_ROR_IMM_OFF_POSTIND(const u32 i) { OP_STR_(STRB, ROR_IMM, sub, 1); } //----------------------------------------------------------------------------- // LDRD / STRD //----------------------------------------------------------------------------- typedef u32 FASTCALL (*LDRD_STRD_REG)(u32); template static u32 FASTCALL OP_LDRD_REG(u32 adr) { cpu->R[Rnum] = READ32(cpu->mem_if->data, adr); cpu->R[Rnum+1] = READ32(cpu->mem_if->data, adr+4); return (MMU_memAccessCycles(adr) + MMU_memAccessCycles(adr+4)); } template static u32 FASTCALL OP_STRD_REG(u32 adr) { WRITE32(cpu->mem_if->data, adr, cpu->R[Rnum]); WRITE32(cpu->mem_if->data, adr + 4, cpu->R[Rnum + 1]); return (MMU_memAccessCycles(adr) + MMU_memAccessCycles(adr+4)); } #define T(op, proc) op, op, op, op, op, op, op, op, op, op, op, op, op, op, op, op static const LDRD_STRD_REG op_ldrd_tab[2][16] = { {T(OP_LDRD_REG, 0)}, {T(OP_LDRD_REG, 1)} }; static const LDRD_STRD_REG op_strd_tab[2][16] = { {T(OP_STRD_REG, 0)}, {T(OP_STRD_REG, 1)} }; #undef T static int OP_LDRD_STRD_POST_INDEX(const u32 i) { u8 Rd_num = REG_POS(i, 12); if (Rd_num == 14) { printf("OP_LDRD_STRD_POST_INDEX: use R14!!!!\n"); return 0; // TODO: exception } if (Rd_num & 0x1) { printf("OP_LDRD_STRD_POST_INDEX: ERROR!!!!\n"); return 0; // TODO: exception } GpVar Rd = c.newGpVar(kX86VarTypeGpd); GpVar addr = c.newGpVar(kX86VarTypeGpd); c.mov(Rd, reg_pos_ptr(16)); c.mov(addr, reg_pos_ptr(16)); // I bit - immediate or register if (BIT22(i)) { IMM_OFF; BIT23(i)?c.add(reg_pos_ptr(16), rhs):c.sub(reg_pos_ptr(16), rhs); } else { GpVar idx = c.newGpVar(kX86VarTypeGpd); c.mov(idx, reg_pos_ptr(0)); BIT23(i)?c.add(reg_pos_ptr(16), idx):c.sub(reg_pos_ptr(16), idx); } X86CompilerFuncCall *ctx = c.call((void*)(BIT5(i) ? op_strd_tab[PROCNUM][Rd_num] : op_ldrd_tab[PROCNUM][Rd_num])); ctx->setPrototype(ASMJIT_CALL_CONV, FuncBuilder1()); ctx->setArgument(0, addr); ctx->setReturn(bb_cycles); emit_MMU_aluMemCycles(3, bb_cycles, 0); return 1; } static int OP_LDRD_STRD_OFFSET_PRE_INDEX(const u32 i) { u8 Rd_num = REG_POS(i, 12); if (Rd_num == 14) { printf("OP_LDRD_STRD_OFFSET_PRE_INDEX: use R14!!!!\n"); return 0; // TODO: exception } if (Rd_num & 0x1) { printf("OP_LDRD_STRD_OFFSET_PRE_INDEX: ERROR!!!!\n"); return 0; // TODO: exception } GpVar Rd = c.newGpVar(kX86VarTypeGpd); GpVar addr = c.newGpVar(kX86VarTypeGpd); c.mov(Rd, reg_pos_ptr(16)); c.mov(addr, reg_pos_ptr(16)); // I bit - immediate or register if (BIT22(i)) { IMM_OFF; BIT23(i)?c.add(addr, rhs):c.sub(addr, rhs); } else BIT23(i)?c.add(addr, reg_pos_ptr(0)):c.sub(addr, reg_pos_ptr(0)); if (BIT5(i)) // Store { X86CompilerFuncCall *ctx = c.call((void*)op_strd_tab[PROCNUM][Rd_num]); ctx->setPrototype(ASMJIT_CALL_CONV, FuncBuilder1()); ctx->setArgument(0, addr); ctx->setReturn(bb_cycles); if (BIT21(i)) // W bit - writeback c.mov(reg_pos_ptr(16), addr); emit_MMU_aluMemCycles(3, bb_cycles, 0); } else // Load { if (BIT21(i)) // W bit - writeback c.mov(reg_pos_ptr(16), addr); X86CompilerFuncCall *ctx = c.call((void*)op_ldrd_tab[PROCNUM][Rd_num]); ctx->setPrototype(ASMJIT_CALL_CONV, FuncBuilder1()); ctx->setArgument(0, addr); ctx->setReturn(bb_cycles); emit_MMU_aluMemCycles(3, bb_cycles, 0); } return 1; } //----------------------------------------------------------------------------- // SWP/SWPB //----------------------------------------------------------------------------- template static u32 FASTCALL op_swp(u32 adr, u32 *Rd, u32 Rs) { u32 tmp = ROR(READ32(cpu->mem_if->data, adr), (adr & 3)<<3); WRITE32(cpu->mem_if->data, adr, Rs); *Rd = tmp; return (MMU_memAccessCycles(adr) + MMU_memAccessCycles(adr)); } template static u32 FASTCALL op_swpb(u32 adr, u32 *Rd, u32 Rs) { u32 tmp = READ8(cpu->mem_if->data, adr); WRITE8(cpu->mem_if->data, adr, Rs); *Rd = tmp; return (MMU_memAccessCycles(adr) + MMU_memAccessCycles(adr)); } typedef u32 FASTCALL (*OP_SWP_SWPB)(u32, u32*, u32); static const OP_SWP_SWPB op_swp_tab[2][2] = {{ op_swp<0>, op_swp<1> }, { op_swpb<0>, op_swpb<1> }}; static int op_swp_(const u32 i, int b) { GpVar addr = c.newGpVar(kX86VarTypeGpd); GpVar Rd = c.newGpVar(kX86VarTypeGpz); GpVar Rs = c.newGpVar(kX86VarTypeGpd); c.mov(addr, reg_pos_ptr(16)); c.lea(Rd, reg_pos_ptr(12)); if(b) c.movzx(Rs, reg_pos_ptrB(0)); else c.mov(Rs, reg_pos_ptr(0)); X86CompilerFuncCall *ctx = c.call((void*)op_swp_tab[b][PROCNUM]); ctx->setPrototype(ASMJIT_CALL_CONV, FuncBuilder3()); ctx->setArgument(0, addr); ctx->setArgument(1, Rd); ctx->setArgument(2, Rs); ctx->setReturn(bb_cycles); emit_MMU_aluMemCycles(4, bb_cycles, 0); return 1; } static int OP_SWP(const u32 i) { return op_swp_(i, 0); } static int OP_SWPB(const u32 i) { return op_swp_(i, 1); } //----------------------------------------------------------------------------- // LDMIA / LDMIB / LDMDA / LDMDB / STMIA / STMIB / STMDA / STMDB //----------------------------------------------------------------------------- static u32 popregcount(u32 x) { uint32_t pop = 0; for(; x; x>>=1) pop += x&1; return pop; } static u64 get_reg_list(u32 reg_mask, int dir) { u64 regs = 0; for(int j=0; j<16; j++) { int k = dir<0 ? j : 15-j; if(BIT_N(reg_mask,k)) regs = (regs << 4) | k; } return regs; } #ifdef ASMJIT_X64 // generic needs to spill regs and main doesn't; if it's inlined gcc isn't smart enough to keep the spills out of the common case. #define LDM_INLINE NOINLINE #else // spills either way, and we might as well save codesize by not having separate functions #define LDM_INLINE INLINE #endif template static LDM_INLINE FASTCALL u32 OP_LDM_STM_generic(u32 adr, u64 regs, int n) { u32 cycles = 0; adr &= ~3; do { if(store) _MMU_write32(adr, cpu->R[regs&0xF]); else cpu->R[regs&0xF] = _MMU_read32(adr); cycles += MMU_memAccessCycles(adr); adr += 4*dir; regs >>= 4; } while(--n > 0); return cycles; } #ifdef ENABLE_ADVANCED_TIMING #define ADV_CYCLES cycles += MMU_memAccessCycles(adr); #else #define ADV_CYCLES #endif template static LDM_INLINE FASTCALL u32 OP_LDM_STM_other(u32 adr, u64 regs, int n) { u32 cycles = 0; adr &= ~3; #ifndef ENABLE_ADVANCED_TIMING cycles = n * MMU_memAccessCycles(adr); #endif do { if(PROCNUM==ARMCPU_ARM9) if(store) _MMU_ARM9_write32(adr, cpu->R[regs&0xF]); else cpu->R[regs&0xF] = _MMU_ARM9_read32(adr); else if(store) _MMU_ARM7_write32(adr, cpu->R[regs&0xF]); else cpu->R[regs&0xF] = _MMU_ARM7_read32(adr); ADV_CYCLES; adr += 4*dir; regs >>= 4; } while(--n > 0); return cycles; } template static FORCEINLINE FASTCALL u32 OP_LDM_STM_main(u32 adr, u64 regs, int n, u8 *ptr, u32 cycles) { #ifdef ENABLE_ADVANCED_TIMING cycles = 0; #endif uintptr_t *func = (uintptr_t *)&JIT_COMPILED_FUNC(adr, PROCNUM); #define OP(j) { \ /* no need to zero functions in DTCM, since we can't execute from it */ \ if(null_compiled && store) \ { \ *func = 0; \ *(func+1) = 0; \ } \ int Rd = ((uintptr_t)regs >> (j*4)) & 0xF; \ if(store) *(u32*)ptr = cpu->R[Rd]; \ else cpu->R[Rd] = *(u32*)ptr; \ ADV_CYCLES; \ func += 2*dir; \ adr += 4*dir; \ ptr += 4*dir; } do { OP(0); if(n == 1) break; OP(1); if(n == 2) break; OP(2); if(n == 3) break; OP(3); regs >>= 16; n -= 4; } while(n > 0); return cycles; #undef OP #undef ADV_CYCLES } template static u32 FASTCALL OP_LDM_STM(u32 adr, u64 regs, int n) { // TODO use classify_adr? u32 cycles; u8 *ptr; if((adr ^ (adr + (dir>0 ? (n-1)*4 : -15*4))) & ~0x3FFF) // a little conservative, but we don't want to run too many comparisons { // the memory region spans a page boundary, so we can't factor the address translation out of the loop return OP_LDM_STM_generic(adr, regs, n); } else if(PROCNUM==ARMCPU_ARM9 && (adr & ~0x3FFF) == MMU.DTCMRegion) { // don't special-case DTCM cycles, even though that would be both faster and more accurate, // because that wouldn't match the non-jitted version with !ACCOUNT_FOR_DATA_TCM_SPEED ptr = MMU.ARM9_DTCM + (adr & 0x3FFC); cycles = n * MMU_memAccessCycles(adr); if(store) return OP_LDM_STM_main(adr, regs, n, ptr, cycles); } else if((adr & 0x0F000000) == 0x02000000) { ptr = MMU.MAIN_MEM + (adr & _MMU_MAIN_MEM_MASK32); cycles = n * ((PROCNUM==ARMCPU_ARM9) ? 4 : 2); } else if(PROCNUM==ARMCPU_ARM7 && !store && (adr & 0xFF800000) == 0x03800000) { ptr = MMU.ARM7_ERAM + (adr & 0xFFFC); cycles = n; } else if(PROCNUM==ARMCPU_ARM7 && !store && (adr & 0xFF800000) == 0x03000000) { ptr = MMU.SWIRAM + (adr & 0x7FFC); cycles = n; } else return OP_LDM_STM_other(adr, regs, n); return OP_LDM_STM_main(adr, regs, n, ptr, cycles); } typedef u32 FASTCALL (*LDMOpFunc)(u32,u64,int); static const LDMOpFunc op_ldm_stm_tab[2][2][2] = {{ { OP_LDM_STM<0,0,-1>, OP_LDM_STM<0,0,+1> }, { OP_LDM_STM<0,1,-1>, OP_LDM_STM<0,1,+1> }, },{ { OP_LDM_STM<1,0,-1>, OP_LDM_STM<1,0,+1> }, { OP_LDM_STM<1,1,-1>, OP_LDM_STM<1,1,+1> }, }}; static void call_ldm_stm(GpVar adr, u32 bitmask, bool store, int dir) { if(bitmask) { GpVar n = c.newGpVar(kX86VarTypeGpd); c.mov(n, popregcount(bitmask)); #ifdef ASMJIT_X64 GpVar regs = c.newGpVar(kX86VarTypeGpz); c.mov(regs, get_reg_list(bitmask, dir)); X86CompilerFuncCall *ctx = c.call((void*)op_ldm_stm_tab[PROCNUM][store][dir>0]); ctx->setPrototype(ASMJIT_CALL_CONV, FuncBuilder3()); ctx->setArgument(0, adr); ctx->setArgument(1, regs); ctx->setArgument(2, n); #else // same prototype, but we have to handle splitting of a u64 arg manually GpVar regs_lo = c.newGpVar(kX86VarTypeGpd); GpVar regs_hi = c.newGpVar(kX86VarTypeGpd); c.mov(regs_lo, (u32)get_reg_list(bitmask, dir)); c.mov(regs_hi, get_reg_list(bitmask, dir) >> 32); X86CompilerFuncCall *ctx = c.call((void*)op_ldm_stm_tab[PROCNUM][store][dir>0]); ctx->setPrototype(ASMJIT_CALL_CONV, FuncBuilder4()); ctx->setArgument(0, adr); ctx->setArgument(1, regs_lo); ctx->setArgument(2, regs_hi); ctx->setArgument(3, n); #endif ctx->setReturn(bb_cycles); } else bb_constant_cycles++; } static int op_bx(Mem srcreg, bool blx, bool test_thumb); static int op_bx_thumb(Mem srcreg, bool blx, bool test_thumb); static int op_ldm_stm(u32 i, bool store, int dir, bool before, bool writeback) { u32 bitmask = i & 0xFFFF; u32 pop = popregcount(bitmask); GpVar adr = c.newGpVar(kX86VarTypeGpd); c.mov(adr, reg_pos_ptr(16)); if(before) c.add(adr, 4*dir); call_ldm_stm(adr, bitmask, store, dir); if(BIT15(i) && !store) { op_bx(reg_ptr(15), 0, PROCNUM == ARMCPU_ARM9); } if(writeback) { if(store || !(i & (1 << REG_POS(i,16)))) { JIT_COMMENT("--- writeback"); c.add(reg_pos_ptr(16), 4*dir*pop); } else { u32 bitlist = (~((2 << REG_POS(i,16))-1)) & 0xFFFF; if(i & bitlist) { JIT_COMMENT("--- writeback"); c.add(adr, 4*dir*(pop-before)); c.mov(reg_pos_ptr(16), adr); } } } emit_MMU_aluMemCycles(store ? 1 : 2, bb_cycles, pop); return 1; } static int OP_LDMIA(const u32 i) { return op_ldm_stm(i, 0, +1, 0, 0); } static int OP_LDMIB(const u32 i) { return op_ldm_stm(i, 0, +1, 1, 0); } static int OP_LDMDA(const u32 i) { return op_ldm_stm(i, 0, -1, 0, 0); } static int OP_LDMDB(const u32 i) { return op_ldm_stm(i, 0, -1, 1, 0); } static int OP_LDMIA_W(const u32 i) { return op_ldm_stm(i, 0, +1, 0, 1); } static int OP_LDMIB_W(const u32 i) { return op_ldm_stm(i, 0, +1, 1, 1); } static int OP_LDMDA_W(const u32 i) { return op_ldm_stm(i, 0, -1, 0, 1); } static int OP_LDMDB_W(const u32 i) { return op_ldm_stm(i, 0, -1, 1, 1); } static int OP_STMIA(const u32 i) { return op_ldm_stm(i, 1, +1, 0, 0); } static int OP_STMIB(const u32 i) { return op_ldm_stm(i, 1, +1, 1, 0); } static int OP_STMDA(const u32 i) { return op_ldm_stm(i, 1, -1, 0, 0); } static int OP_STMDB(const u32 i) { return op_ldm_stm(i, 1, -1, 1, 0); } static int OP_STMIA_W(const u32 i) { return op_ldm_stm(i, 1, +1, 0, 1); } static int OP_STMIB_W(const u32 i) { return op_ldm_stm(i, 1, +1, 1, 1); } static int OP_STMDA_W(const u32 i) { return op_ldm_stm(i, 1, -1, 0, 1); } static int OP_STMDB_W(const u32 i) { return op_ldm_stm(i, 1, -1, 1, 1); } static int op_ldm_stm2(u32 i, bool store, int dir, bool before, bool writeback) { u32 bitmask = i & 0xFFFF; u32 pop = popregcount(bitmask); bool bit15 = BIT15(i); //printf("ARM%c: %s R%d:%08X, bitmask %02X\n", PROCNUM?'7':'9', (store?"STM":"LDM"), REG_POS(i, 16), cpu->R[REG_POS(i, 16)], bitmask); u32 adr_first = cpu->R[REG_POS(i, 16)]; GpVar adr = c.newGpVar(kX86VarTypeGpd); GpVar oldmode = c.newGpVar(kX86VarTypeGpd); c.mov(adr, reg_pos_ptr(16)); if(before) c.add(adr, 4*dir); if (!bit15 || store) { //if((cpu->CPSR.bits.mode==USR)||(cpu->CPSR.bits.mode==SYS)) { printf("ERROR1\n"); return 1; } //oldmode = armcpu_switchMode(cpu, SYS); c.mov(oldmode, SYS); X86CompilerFuncCall *ctx = c.call((void*)armcpu_switchMode); ctx->setPrototype(kX86FuncConvDefault, FuncBuilder2()); ctx->setArgument(0, bb_cpu); ctx->setArgument(1, oldmode); ctx->setReturn(oldmode); } call_ldm_stm(adr, bitmask, store, dir); if(!bit15 || store) { //armcpu_switchMode(cpu, oldmode); X86CompilerFuncCall *ctx = c.call((void*)armcpu_switchMode); ctx->setPrototype(kX86FuncConvDefault, FuncBuilder2()); ctx->setArgument(0, bb_cpu); ctx->setArgument(1, oldmode); } else { S_DST_R15; } // FIXME if(writeback) { if(store || !(i & (1 << REG_POS(i,16)))) c.add(reg_pos_ptr(16), 4*dir*pop); else { u32 bitlist = (~((2 << REG_POS(i,16))-1)) & 0xFFFF; if(i & bitlist) { c.add(adr, 4*dir*(pop-before)); c.mov(reg_pos_ptr(16), adr); } } } emit_MMU_aluMemCycles(store ? 1 : 2, bb_cycles, pop); return 1; } static int OP_LDMIA2(const u32 i) { return op_ldm_stm2(i, 0, +1, 0, 0); } static int OP_LDMIB2(const u32 i) { return op_ldm_stm2(i, 0, +1, 1, 0); } static int OP_LDMDA2(const u32 i) { return op_ldm_stm2(i, 0, -1, 0, 0); } static int OP_LDMDB2(const u32 i) { return op_ldm_stm2(i, 0, -1, 1, 0); } static int OP_LDMIA2_W(const u32 i) { return op_ldm_stm2(i, 0, +1, 0, 1); } static int OP_LDMIB2_W(const u32 i) { return op_ldm_stm2(i, 0, +1, 1, 1); } static int OP_LDMDA2_W(const u32 i) { return op_ldm_stm2(i, 0, -1, 0, 1); } static int OP_LDMDB2_W(const u32 i) { return op_ldm_stm2(i, 0, -1, 1, 1); } static int OP_STMIA2(const u32 i) { return op_ldm_stm2(i, 1, +1, 0, 0); } static int OP_STMIB2(const u32 i) { return op_ldm_stm2(i, 1, +1, 1, 0); } static int OP_STMDA2(const u32 i) { return op_ldm_stm2(i, 1, -1, 0, 0); } static int OP_STMDB2(const u32 i) { return op_ldm_stm2(i, 1, -1, 1, 0); } static int OP_STMIA2_W(const u32 i) { return op_ldm_stm2(i, 1, +1, 0, 1); } static int OP_STMIB2_W(const u32 i) { return op_ldm_stm2(i, 1, +1, 1, 1); } static int OP_STMDA2_W(const u32 i) { return op_ldm_stm2(i, 1, -1, 0, 1); } static int OP_STMDB2_W(const u32 i) { return op_ldm_stm2(i, 1, -1, 1, 1); } //----------------------------------------------------------------------------- // Branch //----------------------------------------------------------------------------- #define SIGNEXTEND_11(i) (((s32)i<<21)>>21) #define SIGNEXTEND_24(i) (((s32)i<<8)>>8) static int op_b(u32 i, bool bl) { u32 dst = bb_r15 + (SIGNEXTEND_24(i) << 2); if(CONDITION(i)==0xF) { if(bl) dst += 2; c.or_(cpu_ptr_byte(CPSR, 0), 1<<5); } if(bl || CONDITION(i)==0xF) c.mov(reg_ptr(14), bb_next_instruction); c.mov(cpu_ptr(instruct_adr), dst); return 1; } static int OP_B(const u32 i) { return op_b(i, 0); } static int OP_BL(const u32 i) { return op_b(i, 1); } static int op_bx(Mem srcreg, bool blx, bool test_thumb) { GpVar dst = c.newGpVar(kX86VarTypeGpd); c.mov(dst, srcreg); if(test_thumb) { GpVar mask = c.newGpVar(kX86VarTypeGpd); GpVar thumb = dst; dst = c.newGpVar(kX86VarTypeGpd); c.mov(dst, thumb); c.and_(thumb, 1); c.lea(mask, ptr_abs((void*)0xFFFFFFFC, thumb.r64(), kScale2Times)); c.shl(thumb, 5); c.or_(cpu_ptr_byte(CPSR, 0), thumb.r8Lo()); c.and_(dst, mask); } else c.and_(dst, 0xFFFFFFFC); if(blx) c.mov(reg_ptr(14), bb_next_instruction); c.mov(cpu_ptr(instruct_adr), dst); return 1; } static int OP_BX(const u32 i) { return op_bx(reg_pos_ptr(0), 0, 1); } static int OP_BLX_REG(const u32 i) { return op_bx(reg_pos_ptr(0), 1, 1); } //----------------------------------------------------------------------------- // CLZ //----------------------------------------------------------------------------- static int OP_CLZ(const u32 i) { GpVar res = c.newGpVar(kX86VarTypeGpd); c.mov(res, 0x3F); c.bsr(res, reg_pos_ptr(0)); c.xor_(res, 0x1F); c.mov(reg_pos_ptr(12), res); return 1; } //----------------------------------------------------------------------------- // MCR / MRC //----------------------------------------------------------------------------- // precalculate region masks/sets from cp15 register ----- JIT // TODO: rewrite to asm static void maskPrecalc(u32 _num) { #define precalc(num) { \ u32 mask = 0, set = 0xFFFFFFFF ; /* (x & 0) == 0xFF..FF is allways false (disabled) */ \ if (BIT_N(cp15.protectBaseSize[num],0)) /* if region is enabled */ \ { /* reason for this define: naming includes var */ \ mask = CP15_MASKFROMREG(cp15.protectBaseSize[num]) ; \ set = CP15_SETFROMREG(cp15.protectBaseSize[num]) ; \ if (CP15_SIZEIDENTIFIER(cp15.protectBaseSize[num])==0x1F) \ { /* for the 4GB region, u32 suffers wraparound */ \ mask = 0 ; set = 0 ; /* (x & 0) == 0 is allways true (enabled) */ \ } \ } \ cp15.setSingleRegionAccess(num, mask, set) ; \ } switch(_num) { case 0: precalc(0); break; case 1: precalc(1); break; case 2: precalc(2); break; case 3: precalc(3); break; case 4: precalc(4); break; case 5: precalc(5); break; case 6: precalc(6); break; case 7: precalc(7); break; case 0xFF: precalc(0); precalc(1); precalc(2); precalc(3); precalc(4); precalc(5); precalc(6); precalc(7); break; } #undef precalc } #define _maskPrecalc(num) \ { \ GpVar _num = c.newGpVar(kX86VarTypeGpd); \ X86CompilerFuncCall* ctxM = c.call((uintptr_t)maskPrecalc); \ c.mov(_num, num); \ ctxM->setPrototype(kX86FuncConvDefault, FuncBuilder1()); \ ctxM->setArgument(0, _num); \ } static int OP_MCR(const u32 i) { if (PROCNUM == ARMCPU_ARM7) return 0; u32 cpnum = REG_POS(i, 8); if(cpnum != 15) { // TODO - exception? printf("JIT: MCR P%i, 0, R%i, C%i, C%i, %i, %i (don't allocated coprocessor)\n", cpnum, REG_POS(i, 12), REG_POS(i, 16), REG_POS(i, 0), (i>>21)&0x7, (i>>5)&0x7); return 2; } if (REG_POS(i, 12) == 15) { printf("JIT: MCR Rd=R15\n"); return 2; } u8 CRn = REG_POS(i, 16); // Cn u8 CRm = REG_POS(i, 0); // Cm u8 opcode1 = ((i>>21)&0x7); // opcode1 u8 opcode2 = ((i>>5)&0x7); // opcode2 GpVar bb_cp15 = c.newGpVar(kX86VarTypeGpz); GpVar data = c.newGpVar(kX86VarTypeGpd); c.mov(data, reg_pos_ptr(12)); c.mov(bb_cp15, (uintptr_t)&cp15); bool bUnknown = false; switch(CRn) { case 1: if((opcode1==0) && (opcode2==0) && (CRm==0)) { GpVar tmp = c.newGpVar(kX86VarTypeGpd); // On the NDS bit0,2,7,12..19 are R/W, Bit3..6 are always set, all other bits are always zero. //MMU.ARM9_RW_MODE = BIT7(val); GpVar bb_mmu = c.newGpVar(kX86VarTypeGpz); c.mov(bb_mmu, (uintptr_t)&MMU); Mem rwmode = mmu_ptr_byte(ARM9_RW_MODE); Mem ldtbit = cpu_ptr_byte(LDTBit, 0); c.test(data, (1<<7)); c.setnz(rwmode); //cpu->intVector = 0xFFFF0000 * (BIT13(val)); GpVar vec = c.newGpVar(kX86VarTypeGpd); c.mov(tmp, 0xFFFF0000); c.xor_(vec, vec); c.test(data, (1 << 13)); c.cmovnz(vec, tmp); c.mov(cpu_ptr(intVector), vec); //cpu->LDTBit = !BIT15(val); //TBit c.test(data, (1 << 15)); c.setz(ldtbit); //ctrl = (val & 0x000FF085) | 0x00000078; c.and_(data, 0x000FF085); c.or_(data, 0x00000078); c.mov(cp15_ptr(ctrl), data); break; } bUnknown = true; break; case 2: if((opcode1==0) && (CRm==0)) { switch(opcode2) { case 0: // DCConfig = val; c.mov(cp15_ptr(DCConfig), data); break; case 1: // ICConfig = val; c.mov(cp15_ptr(ICConfig), data); break; default: bUnknown = true; break; } break; } bUnknown = true; break; case 3: if((opcode1==0) && (opcode2==0) && (CRm==0)) { //writeBuffCtrl = val; c.mov(cp15_ptr(writeBuffCtrl), data); break; } bUnknown = true; break; case 5: if((opcode1==0) && (CRm==0)) { switch(opcode2) { case 2: //DaccessPerm = val; c.mov(cp15_ptr(DaccessPerm), data); _maskPrecalc(0xFF); break; case 3: //IaccessPerm = val; c.mov(cp15_ptr(IaccessPerm), data); _maskPrecalc(0xFF); break; default: bUnknown = true; break; } } bUnknown = true; break; case 6: if((opcode1==0) && (opcode2==0)) { if (CRm < 8) { //protectBaseSize[CRm] = val; c.mov(cp15_ptr_off(protectBaseSize, (CRm * sizeof(u32))), data); _maskPrecalc(CRm); break; } } bUnknown = true; break; case 7: if((CRm==0)&&(opcode1==0)&&((opcode2==4))) { //CP15wait4IRQ; c.mov(cpu_ptr(waitIRQ), true); c.mov(cpu_ptr(halt_IE_and_IF), true); //IME set deliberately omitted: only SWI sets IME to 1 break; } bUnknown = true; break; case 9: if((opcode1==0)) { switch(CRm) { case 0: switch(opcode2) { case 0: //DcacheLock = val; c.mov(cp15_ptr(DcacheLock), data); break; case 1: //IcacheLock = val; c.mov(cp15_ptr(IcacheLock), data); break; default: bUnknown = true; break; } case 1: switch(opcode2) { case 0: { //MMU.DTCMRegion = DTCMRegion = val & 0x0FFFF000; c.and_(data, 0x0FFFF000); GpVar bb_mmu = c.newGpVar(kX86VarTypeGpz); c.mov(bb_mmu, (uintptr_t)&MMU); c.mov(mmu_ptr(DTCMRegion), data); c.mov(cp15_ptr(DTCMRegion), data); } break; case 1: { //ITCMRegion = val; //ITCM base is not writeable! GpVar bb_mmu = c.newGpVar(kX86VarTypeGpz); c.mov(bb_mmu, (uintptr_t)&MMU); c.mov(mmu_ptr(ITCMRegion), 0); c.mov(cp15_ptr(ITCMRegion), data); } break; default: bUnknown = true; break; } } break; } bUnknown = true; break; case 13: bUnknown = true; break; case 15: bUnknown = true; break; default: bUnknown = true; break; } if (bUnknown) { //printf("Unknown MCR command: MRC P15, 0, R%i, C%i, C%i, %i, %i\n", REG_POS(i, 12), CRn, CRm, opcode1, opcode2); return 1; } return 1; } static int OP_MRC(const u32 i) { if (PROCNUM == ARMCPU_ARM7) return 0; u32 cpnum = REG_POS(i, 8); if(cpnum != 15) { printf("MRC P%i, 0, R%i, C%i, C%i, %i, %i (don't allocated coprocessor)\n", cpnum, REG_POS(i, 12), REG_POS(i, 16), REG_POS(i, 0), (i>>21)&0x7, (i>>5)&0x7); return 2; } u8 CRn = REG_POS(i, 16); // Cn u8 CRm = REG_POS(i, 0); // Cm u8 opcode1 = ((i>>21)&0x7); // opcode1 u8 opcode2 = ((i>>5)&0x7); // opcode2 GpVar bb_cp15 = c.newGpVar(kX86VarTypeGpz); GpVar data = c.newGpVar(kX86VarTypeGpd); c.mov(bb_cp15, (uintptr_t)&cp15); bool bUnknown = false; switch(CRn) { case 0: if((opcode1 == 0)&&(CRm==0)) { switch(opcode2) { case 1: // *R = cacheType; c.mov(data, cp15_ptr(cacheType)); break; case 2: // *R = TCMSize; c.mov(data, cp15_ptr(TCMSize)); break; default: // FIXME // *R = IDCode; c.mov(data, cp15_ptr(IDCode)); break; } break; } bUnknown = true; break; case 1: if((opcode1==0) && (opcode2==0) && (CRm==0)) { // *R = ctrl; c.mov(data, cp15_ptr(ctrl)); break; } bUnknown = true; break; case 2: if((opcode1==0) && (CRm==0)) { switch(opcode2) { case 0: // *R = DCConfig; c.mov(data, cp15_ptr(DCConfig)); break; case 1: // *R = ICConfig; c.mov(data, cp15_ptr(ICConfig)); break; default: bUnknown = true; break; } break; } bUnknown = true; break; case 3: if((opcode1==0) && (opcode2==0) && (CRm==0)) { // *R = writeBuffCtrl; c.mov(data, cp15_ptr(writeBuffCtrl)); break; } bUnknown = true; break; case 5: if((opcode1==0) && (CRm==0)) { switch(opcode2) { case 2: // *R = DaccessPerm; c.mov(data, cp15_ptr(DaccessPerm)); break; case 3: // *R = IaccessPerm; c.mov(data, cp15_ptr(IaccessPerm)); break; default: bUnknown = true; break; } break; } bUnknown = true; break; case 6: if((opcode1==0) && (opcode2==0)) { if (CRm < 8) { // *R = protectBaseSize[CRm]; c.mov(data, cp15_ptr_off(protectBaseSize, (CRm * sizeof(u32)))); break; } } bUnknown = true; break; case 7: bUnknown = true; break; case 9: if(opcode1 == 0) { switch(CRm) { case 0: switch(opcode2) { case 0: //*R = DcacheLock; c.mov(data, cp15_ptr(DcacheLock)); break; case 1: //*R = IcacheLock; c.mov(data, cp15_ptr(IcacheLock)); break; default: bUnknown = true; break; } case 1: switch(opcode2) { case 0: //*R = DTCMRegion; c.mov(data, cp15_ptr(DTCMRegion)); break; case 1: //*R = ITCMRegion; c.mov(data, cp15_ptr(ITCMRegion)); break; default: bUnknown = true; break; } } // break; } bUnknown = true; break; case 13: bUnknown = true; break; case 15: bUnknown = true; break; default: bUnknown = true; break; } if (bUnknown) { //printf("Unknown MRC command: MRC P15, 0, R%i, C%i, C%i, %i, %i\n", REG_POS(i, 12), CRn, CRm, opcode1, opcode2); return 1; } if (REG_POS(i, 12) == 15) // set NZCV { //CPSR.bits.N = BIT31(data); //CPSR.bits.Z = BIT30(data); //CPSR.bits.C = BIT29(data); //CPSR.bits.V = BIT28(data); c.and_(data, 0xF0000000); c.and_(cpu_ptr(CPSR), 0x0FFFFFFF); c.or_(cpu_ptr(CPSR), data); } else c.mov(reg_pos_ptr(12), data); return 1; } u32 op_swi(u8 swinum) { if(cpu->swi_tab) { #if defined(_M_X64) || defined(__x86_64__) // TODO: return 0; #else X86CompilerFuncCall *ctx = c.call((void*)ARM_swi_tab[PROCNUM][swinum]); ctx->setPrototype(kX86FuncConvDefault, FuncBuilder0()); ctx->setReturn(bb_cycles); c.add(bb_cycles, 3); return 1; #endif } GpVar oldCPSR = c.newGpVar(kX86VarTypeGpd); GpVar mode = c.newGpVar(kX86VarTypeGpd); Mem CPSR = cpu_ptr(CPSR.val); JIT_COMMENT("store CPSR to x86 stack"); c.mov(oldCPSR, CPSR); JIT_COMMENT("enter SVC mode"); c.mov(mode, imm(SVC)); X86CompilerFuncCall* ctx = c.call((void*)armcpu_switchMode); ctx->setPrototype(kX86FuncConvDefault, FuncBuilder2()); ctx->setArgument(0, bb_cpu); ctx->setArgument(1, mode); c.unuse(mode); JIT_COMMENT("store next instruction address to R14"); c.mov(reg_ptr(14), bb_next_instruction); JIT_COMMENT("save old CPSR as new SPSR"); c.mov(cpu_ptr(SPSR.val), oldCPSR); JIT_COMMENT("CPSR: clear T, set I"); GpVar _cpsr = c.newGpVar(kX86VarTypeGpd); c.mov(_cpsr, CPSR); c.and_(_cpsr, ~(1 << 5)); /* clear T */ c.or_(_cpsr, (1 << 7)); /* set I */ c.mov(CPSR, _cpsr); c.unuse(_cpsr); JIT_COMMENT("set next instruction"); c.mov(cpu_ptr(next_instruction), imm(cpu->intVector+0x08)); return 1; } static int OP_SWI(const u32 i) { return op_swi((i >> 16) & 0x1F); } //----------------------------------------------------------------------------- // BKPT //----------------------------------------------------------------------------- static int OP_BKPT(const u32 i) { printf("JIT: unimplemented OP_BKPT\n"); return 0; } //----------------------------------------------------------------------------- // THUMB //----------------------------------------------------------------------------- #define OP_SHIFTS_IMM(x86inst) \ GpVar rcf = c.newGpVar(kX86VarTypeGpd); \ u8 cf_change = 1; \ const u32 rhs = ((i>>6) & 0x1F); \ if (_REG_NUM(i, 0) == _REG_NUM(i, 3)) \ c.x86inst(reg_pos_thumb(0), rhs); \ else \ { \ GpVar lhs = c.newGpVar(kX86VarTypeGpd); \ c.mov(lhs, reg_pos_thumb(3)); \ c.x86inst(lhs, rhs); \ c.mov(reg_pos_thumb(0), lhs); \ c.unuse(lhs); \ } \ c.setc(rcf.r8Lo()); \ SET_NZC; \ return 1; #define OP_SHIFTS_REG(x86inst, bit) \ u8 cf_change = 1; \ GpVar imm = c.newGpVar(kX86VarTypeGpz); \ GpVar rcf = c.newGpVar(kX86VarTypeGpd); \ Label __eq32 = c.newLabel(); \ Label __ls32 = c.newLabel(); \ Label __zero = c.newLabel(); \ Label __done = c.newLabel(); \ \ c.mov(imm, reg_pos_thumb(3)); \ c.and_(imm, 0xFF); \ c.jz(__zero); \ c.cmp(imm, 32); \ c.jl(__ls32); \ c.je(__eq32); \ /* imm > 32 */ \ c.mov(reg_pos_thumb(0), 0); \ SET_NZC_SHIFTS_ZERO(0); \ c.jmp(__done); \ /* imm == 32 */ \ c.bind(__eq32); \ c.test(reg_pos_thumb(0), (1 << bit)); \ c.setnz(rcf.r8Lo()); \ c.mov(reg_pos_thumb(0), 0); \ SET_NZC_SHIFTS_ZERO(1); \ c.jmp(__done); \ /* imm == 0 */ \ c.bind(__zero); \ c.cmp(reg_pos_thumb(0), 0); \ SET_NZ(0); \ c.jmp(__done); \ /* imm < 32 */ \ c.bind(__ls32); \ c.x86inst(reg_pos_thumb(0), imm); \ c.setc(rcf.r8Lo()); \ SET_NZC; \ c.bind(__done); \ return 1; #define OP_LOGIC(x86inst, _conv) \ GpVar rhs = c.newGpVar(kX86VarTypeGpd); \ c.mov(rhs, reg_pos_thumb(3)); \ if (_conv==1) c.not_(rhs); \ c.x86inst(reg_pos_thumb(0), rhs); \ SET_NZ(0); \ return 1; //----------------------------------------------------------------------------- // LSL / LSR / ASR / ROR //----------------------------------------------------------------------------- static int OP_LSL_0(const u32 i) { if (_REG_NUM(i, 0) == _REG_NUM(i, 3)) c.cmp(reg_pos_thumb(0), 0); else { GpVar rhs = c.newGpVar(kX86VarTypeGpd); c.mov(rhs, reg_pos_thumb(3)); c.mov(reg_pos_thumb(0), rhs); c.cmp(rhs, 0); } SET_NZ(0); return 1; } static int OP_LSL(const u32 i) { OP_SHIFTS_IMM(shl); } static int OP_LSL_REG(const u32 i) { OP_SHIFTS_REG(shl, 0); } static int OP_LSR_0(const u32 i) { GpVar rcf = c.newGpVar(kX86VarTypeGpd); c.test(reg_pos_thumb(3), (1 << 31)); c.setnz(rcf.r8Lo()); SET_NZC_SHIFTS_ZERO(1); c.mov(reg_pos_thumb(0), 0); return 1; } static int OP_LSR(const u32 i) { OP_SHIFTS_IMM(shr); } static int OP_LSR_REG(const u32 i) { OP_SHIFTS_REG(shr, 31); } static int OP_ASR_0(const u32 i) { u8 cf_change = 1; GpVar rcf = c.newGpVar(kX86VarTypeGpd); GpVar rhs = c.newGpVar(kX86VarTypeGpd); if (_REG_NUM(i, 0) == _REG_NUM(i, 3)) c.sar(reg_pos_thumb(0), 31); else { c.mov(rhs, reg_pos_thumb(3)); c.sar(rhs, 31); c.mov(reg_pos_thumb(0), rhs); } c.sets(rcf.r8Lo()); SET_NZC; return 1; } static int OP_ASR(const u32 i) { OP_SHIFTS_IMM(sar); } static int OP_ASR_REG(const u32 i) { u8 cf_change = 1; Label __gr0 = c.newLabel(); Label __lt32 = c.newLabel(); Label __done = c.newLabel(); Label __setFlags = c.newLabel(); GpVar imm = c.newGpVar(kX86VarTypeGpz); GpVar rcf = c.newGpVar(kX86VarTypeGpd); c.mov(imm, reg_pos_thumb(3)); c.and_(imm, 0xFF); c.jnz(__gr0); /* imm == 0 */ c.cmp(reg_pos_thumb(0), 0); SET_NZ(0); c.jmp(__done); /* imm > 0 */ c.bind(__gr0); c.cmp(imm, 32); c.jl(__lt32); /* imm > 31 */ c.sar(reg_pos_thumb(0), 31); c.sets(rcf.r8Lo()); c.jmp(__setFlags); /* imm < 32 */ c.bind(__lt32); c.sar(reg_pos_thumb(0), imm); c.setc(rcf.r8Lo()); c.bind(__setFlags); SET_NZC; c.bind(__done); return 1; } //----------------------------------------------------------------------------- // ROR //----------------------------------------------------------------------------- static int OP_ROR_REG(const u32 i) { u8 cf_change = 1; GpVar imm = c.newGpVar(kX86VarTypeGpz); GpVar rcf = c.newGpVar(kX86VarTypeGpd); Label __zero = c.newLabel(); Label __zero_1F = c.newLabel(); Label __done = c.newLabel(); c.mov(imm, reg_pos_thumb(3)); c.and_(imm, 0xFF); c.jz(__zero); c.and_(imm, 0x1F); c.jz(__zero_1F); c.ror(reg_pos_thumb(0), imm); c.setc(rcf.r8Lo()); SET_NZC; c.jmp(__done); /* imm & 0x1F == 0 */ c.bind(__zero_1F); c.cmp(reg_pos_thumb(0), 0); c.sets(rcf.r8Lo()); SET_NZC; c.jmp(__done); /* imm == 0 */ c.bind(__zero); c.cmp(reg_pos_thumb(0), 0); SET_NZ(0); c.bind(__done); return 1; } //----------------------------------------------------------------------------- // AND / ORR / EOR / BIC //----------------------------------------------------------------------------- static int OP_AND(const u32 i) { OP_LOGIC(and_, 0); } static int OP_ORR(const u32 i) { OP_LOGIC(or_, 0); } static int OP_EOR(const u32 i) { OP_LOGIC(xor_, 0); } static int OP_BIC(const u32 i) { OP_LOGIC(and_, 1); } //----------------------------------------------------------------------------- // NEG //----------------------------------------------------------------------------- static int OP_NEG(const u32 i) { if (_REG_NUM(i, 0) == _REG_NUM(i, 3)) c.neg(reg_pos_thumb(0)); else { GpVar tmp = c.newGpVar(kX86VarTypeGpd); c.mov(tmp, reg_pos_thumb(3)); c.neg(tmp); c.mov(reg_pos_thumb(0), tmp); } SET_NZCV(1); return 1; } //----------------------------------------------------------------------------- // ADD //----------------------------------------------------------------------------- static int OP_ADD_IMM3(const u32 i) { u32 imm3 = (i >> 6) & 0x07; if (imm3 == 0) // mov 2 { GpVar tmp = c.newGpVar(kX86VarTypeGpd); c.mov(tmp, reg_pos_thumb(3)); c.mov(reg_pos_thumb(0), tmp); c.cmp(tmp, 0); SET_NZ(1); return 1; } if (_REG_NUM(i, 0) == _REG_NUM(i, 3)) { c.add(reg_pos_thumb(0), imm3); } else { GpVar tmp = c.newGpVar(kX86VarTypeGpd); c.mov(tmp, reg_pos_thumb(3)); c.add(tmp, imm3); c.mov(reg_pos_thumb(0), tmp); } SET_NZCV(0); return 1; } static int OP_ADD_IMM8(const u32 i) { c.add(reg_pos_thumb(8), (i & 0xFF)); SET_NZCV(0); return 1; } static int OP_ADD_REG(const u32 i) { //cpu->R[REG_NUM(i, 0)] = cpu->R[REG_NUM(i, 3)] + cpu->R[REG_NUM(i, 6)]; if (_REG_NUM(i, 0) == _REG_NUM(i, 3)) { GpVar tmp = c.newGpVar(kX86VarTypeGpd); c.mov(tmp, reg_pos_thumb(6)); c.add(reg_pos_thumb(0), tmp); } else if (_REG_NUM(i, 0) == _REG_NUM(i, 6)) { GpVar tmp = c.newGpVar(kX86VarTypeGpd); c.mov(tmp, reg_pos_thumb(3)); c.add(reg_pos_thumb(0), tmp); } else { GpVar tmp = c.newGpVar(kX86VarTypeGpd); c.mov(tmp, reg_pos_thumb(3)); c.add(tmp, reg_pos_thumb(6)); c.mov(reg_pos_thumb(0), tmp); } SET_NZCV(0); return 1; } static int OP_ADD_SPE(const u32 i) { u32 Rd = _REG_NUM(i, 0) | ((i>>4)&8); //cpu->R[Rd] += cpu->R[REG_POS(i, 3)]; GpVar tmp = c.newGpVar(kX86VarTypeGpd); c.mov(tmp, reg_ptr(Rd)); c.add(tmp, reg_pos_ptr(3)); c.mov(reg_ptr(Rd), tmp); if(Rd==15) c.mov(cpu_ptr(next_instruction), tmp); return 1; } static int OP_ADD_2PC(const u32 i) { u32 imm = ((i&0xFF)<<2); c.mov(reg_pos_thumb(8), (bb_r15 & 0xFFFFFFFC) + imm); return 1; } static int OP_ADD_2SP(const u32 i) { u32 imm = ((i&0xFF)<<2); //cpu->R[REG_NUM(i, 8)] = cpu->R[13] + ((i&0xFF)<<2); GpVar tmp = c.newGpVar(kX86VarTypeGpd); c.mov(tmp, reg_ptr(13)); if (imm) c.add(tmp, imm); c.mov(reg_pos_thumb(8), tmp); return 1; } //----------------------------------------------------------------------------- // SUB //----------------------------------------------------------------------------- static int OP_SUB_IMM3(const u32 i) { u32 imm3 = (i >> 6) & 0x07; // cpu->R[REG_NUM(i, 0)] = cpu->R[REG_NUM(i, 3)] - imm3; if (_REG_NUM(i, 0) == _REG_NUM(i, 3)) { c.sub(reg_pos_thumb(0), imm3); } else { GpVar tmp = c.newGpVar(kX86VarTypeGpd); c.mov(tmp, reg_pos_thumb(3)); c.sub(tmp, imm3); c.mov(reg_pos_thumb(0), tmp); } SET_NZCV(1); return 1; } static int OP_SUB_IMM8(const u32 i) { //cpu->R[REG_NUM(i, 8)] -= imm8; c.sub(reg_pos_thumb(8), (i & 0xFF)); SET_NZCV(1); return 1; } static int OP_SUB_REG(const u32 i) { // cpu->R[REG_NUM(i, 0)] = cpu->R[REG_NUM(i, 3)] - cpu->R[REG_NUM(i, 6)]; if (_REG_NUM(i, 0) == _REG_NUM(i, 3)) { GpVar tmp = c.newGpVar(kX86VarTypeGpd); c.mov(tmp, reg_pos_thumb(6)); c.sub(reg_pos_thumb(0), tmp); } else { GpVar tmp = c.newGpVar(kX86VarTypeGpd); c.mov(tmp, reg_pos_thumb(3)); c.sub(tmp, reg_pos_thumb(6)); c.mov(reg_pos_thumb(0), tmp); } SET_NZCV(1); return 1; } //----------------------------------------------------------------------------- // ADC //----------------------------------------------------------------------------- static int OP_ADC_REG(const u32 i) { GpVar tmp = c.newGpVar(kX86VarTypeGpd); c.mov(tmp, reg_pos_thumb(3)); GET_CARRY(0); c.adc(reg_pos_thumb(0), tmp); SET_NZCV(0); return 1; } //----------------------------------------------------------------------------- // SBC //----------------------------------------------------------------------------- static int OP_SBC_REG(const u32 i) { GpVar tmp = c.newGpVar(kX86VarTypeGpd); c.mov(tmp, reg_pos_thumb(3)); GET_CARRY(1); c.sbb(reg_pos_thumb(0), tmp); SET_NZCV(1); return 1; } //----------------------------------------------------------------------------- // MOV / MVN //----------------------------------------------------------------------------- static int OP_MOV_IMM8(const u32 i) { c.mov(reg_pos_thumb(8), (i & 0xFF)); c.cmp(reg_pos_thumb(8), 0); SET_NZ(0); return 1; } static int OP_MOV_SPE(const u32 i) { u32 Rd = _REG_NUM(i, 0) | ((i>>4)&8); //cpu->R[Rd] = cpu->R[REG_POS(i, 3)]; GpVar tmp = c.newGpVar(kX86VarTypeGpd); c.mov(tmp, reg_pos_ptr(3)); c.mov(reg_ptr(Rd), tmp); if(Rd == 15) { c.mov(cpu_ptr(next_instruction), tmp); bb_constant_cycles += 2; } return 1; } static int OP_MVN(const u32 i) { GpVar tmp = c.newGpVar(kX86VarTypeGpd); c.mov(tmp, reg_pos_thumb(3)); c.not_(tmp); c.cmp(tmp, 0); c.mov(reg_pos_thumb(0), tmp); SET_NZ(0); return 1; } //----------------------------------------------------------------------------- // MUL //----------------------------------------------------------------------------- static int OP_MUL_REG(const u32 i) { GpVar lhs = c.newGpVar(kX86VarTypeGpd); c.mov(lhs, reg_pos_thumb(0)); c.imul(lhs, reg_pos_thumb(3)); c.cmp(lhs, 0); c.mov(reg_pos_thumb(0), lhs); SET_NZ(0); if (PROCNUM == ARMCPU_ARM7) c.mov(bb_cycles, 4); else MUL_Mxx_END(lhs, 0, 1); return 1; } //----------------------------------------------------------------------------- // CMP / CMN //----------------------------------------------------------------------------- static int OP_CMP_IMM8(const u32 i) { c.cmp(reg_pos_thumb(8), (i & 0xFF)); SET_NZCV(1); return 1; } static int OP_CMP(const u32 i) { GpVar tmp = c.newGpVar(kX86VarTypeGpd); c.mov(tmp, reg_pos_thumb(3)); c.cmp(reg_pos_thumb(0), tmp); SET_NZCV(1); return 1; } static int OP_CMP_SPE(const u32 i) { u32 Rn = (i&7) | ((i>>4)&8); GpVar tmp = c.newGpVar(kX86VarTypeGpd); c.mov(tmp, reg_pos_ptr(3)); c.cmp(reg_ptr(Rn), tmp); SET_NZCV(1); return 1; } static int OP_CMN(const u32 i) { GpVar tmp = c.newGpVar(kX86VarTypeGpd); c.mov(tmp, reg_pos_thumb(0)); c.add(tmp, reg_pos_thumb(3)); SET_NZCV(0); return 1; } //----------------------------------------------------------------------------- // TST //----------------------------------------------------------------------------- static int OP_TST(const u32 i) { GpVar tmp = c.newGpVar(kX86VarTypeGpd); c.mov(tmp, reg_pos_thumb(3)); c.test(reg_pos_thumb(0), tmp); SET_NZ(0); return 1; } //----------------------------------------------------------------------------- // STR / LDR / STRB / LDRB //----------------------------------------------------------------------------- #define STR_THUMB(mem_op, offset) \ GpVar addr = c.newGpVar(kX86VarTypeGpd); \ GpVar data = c.newGpVar(kX86VarTypeGpd); \ u32 adr_first = cpu->R[_REG_NUM(i, 3)]; \ \ c.mov(addr, reg_pos_thumb(3)); \ if ((offset) != -1) \ { \ if ((offset) != 0) \ { \ c.add(addr, (u32)(offset)); \ adr_first += (u32)(offset); \ } \ } \ else \ { \ c.add(addr, reg_pos_thumb(6)); \ adr_first += cpu->R[_REG_NUM(i, 6)]; \ } \ c.mov(data, reg_pos_thumb(0)); \ X86CompilerFuncCall *ctx = c.call((void*)mem_op##_tab[PROCNUM][classify_adr(adr_first,1)]); \ ctx->setPrototype(ASMJIT_CALL_CONV, FuncBuilder2()); \ ctx->setArgument(0, addr); \ ctx->setArgument(1, data); \ ctx->setReturn(bb_cycles); \ return 1; #define LDR_THUMB(mem_op, offset) \ GpVar addr = c.newGpVar(kX86VarTypeGpd); \ GpVar data = c.newGpVar(kX86VarTypeGpz); \ u32 adr_first = cpu->R[_REG_NUM(i, 3)]; \ \ c.mov(addr, reg_pos_thumb(3)); \ if ((offset) != -1) \ { \ if ((offset) != 0) \ { \ c.add(addr, (u32)(offset)); \ adr_first += (u32)(offset); \ } \ } \ else \ { \ c.add(addr, reg_pos_thumb(6)); \ adr_first += cpu->R[_REG_NUM(i, 6)]; \ } \ c.lea(data, reg_pos_thumb(0)); \ X86CompilerFuncCall *ctx = c.call((void*)mem_op##_tab[PROCNUM][classify_adr(adr_first,0)]); \ ctx->setPrototype(ASMJIT_CALL_CONV, FuncBuilder2()); \ ctx->setArgument(0, addr); \ ctx->setArgument(1, data); \ ctx->setReturn(bb_cycles); \ return 1; static int OP_STRB_IMM_OFF(const u32 i) { STR_THUMB(STRB, ((i>>6)&0x1F)); } static int OP_LDRB_IMM_OFF(const u32 i) { LDR_THUMB(LDRB, ((i>>6)&0x1F)); } static int OP_STRB_REG_OFF(const u32 i) { STR_THUMB(STRB, -1); } static int OP_LDRB_REG_OFF(const u32 i) { LDR_THUMB(LDRB, -1); } static int OP_LDRSB_REG_OFF(const u32 i) { LDR_THUMB(LDRSB, -1); } static int OP_STRH_IMM_OFF(const u32 i) { STR_THUMB(STRH, ((i>>5)&0x3E)); } static int OP_LDRH_IMM_OFF(const u32 i) { LDR_THUMB(LDRH, ((i>>5)&0x3E)); } static int OP_STRH_REG_OFF(const u32 i) { STR_THUMB(STRH, -1); } static int OP_LDRH_REG_OFF(const u32 i) { LDR_THUMB(LDRH, -1); } static int OP_LDRSH_REG_OFF(const u32 i) { LDR_THUMB(LDRSH, -1); } static int OP_STR_IMM_OFF(const u32 i) { STR_THUMB(STR, ((i>>4)&0x7C)); } static int OP_LDR_IMM_OFF(const u32 i) { LDR_THUMB(LDR, ((i>>4)&0x7C)); } // FIXME: tempValue = (tempValue>>adr) | (tempValue<<(32-adr)); static int OP_STR_REG_OFF(const u32 i) { STR_THUMB(STR, -1); } static int OP_LDR_REG_OFF(const u32 i) { LDR_THUMB(LDR, -1); } static int OP_STR_SPREL(const u32 i) { u32 imm = ((i&0xFF)<<2); u32 adr_first = cpu->R[13] + imm; GpVar addr = c.newGpVar(kX86VarTypeGpd); c.mov(addr, reg_ptr(13)); if (imm) c.add(addr, imm); GpVar data = c.newGpVar(kX86VarTypeGpd); c.mov(data, reg_pos_thumb(8)); X86CompilerFuncCall *ctx = c.call((void*)STR_tab[PROCNUM][classify_adr(adr_first,1)]); ctx->setPrototype(ASMJIT_CALL_CONV, FuncBuilder2()); ctx->setArgument(0, addr); ctx->setArgument(1, data); ctx->setReturn(bb_cycles); return 1; } static int OP_LDR_SPREL(const u32 i) { u32 imm = ((i&0xFF)<<2); u32 adr_first = cpu->R[13] + imm; GpVar addr = c.newGpVar(kX86VarTypeGpd); c.mov(addr, reg_ptr(13)); if (imm) c.add(addr, imm); GpVar data = c.newGpVar(kX86VarTypeGpz); c.lea(data, reg_pos_thumb(8)); X86CompilerFuncCall *ctx = c.call((void*)LDR_tab[PROCNUM][classify_adr(adr_first,0)]); ctx->setPrototype(ASMJIT_CALL_CONV, FuncBuilder2()); ctx->setArgument(0, addr); ctx->setArgument(1, data); ctx->setReturn(bb_cycles); return 1; } static int OP_LDR_PCREL(const u32 i) { u32 imm = ((i&0xFF)<<2); u32 adr_first = (bb_r15 & 0xFFFFFFFC) + imm; GpVar addr = c.newGpVar(kX86VarTypeGpd); GpVar data = c.newGpVar(kX86VarTypeGpz); c.mov(addr, adr_first); c.lea(data, reg_pos_thumb(8)); X86CompilerFuncCall *ctx = c.call((void*)LDR_tab[PROCNUM][classify_adr(adr_first,0)]); ctx->setPrototype(ASMJIT_CALL_CONV, FuncBuilder2()); ctx->setArgument(0, addr); ctx->setArgument(1, data); ctx->setReturn(bb_cycles); return 1; } //----------------------------------------------------------------------------- // STMIA / LDMIA //----------------------------------------------------------------------------- static int op_ldm_stm_thumb(u32 i, bool store) { u32 bitmask = i & 0xFF; u32 pop = popregcount(bitmask); //if (BIT_N(i, _REG_NUM(i, 8))) // printf("WARNING - %sIA with Rb in Rlist (THUMB)\n", store?"STM":"LDM"); GpVar adr = c.newGpVar(kX86VarTypeGpd); c.mov(adr, reg_pos_thumb(8)); call_ldm_stm(adr, bitmask, store, 1); // ARM_REF: THUMB: Causes base register write-back, and is not optional // ARM_REF: If the base register is specified in , the final value of is the loaded value // (not the written-back value). if (store) c.add(reg_pos_thumb(8), 4*pop); else { if (!BIT_N(i, _REG_NUM(i, 8))) c.add(reg_pos_thumb(8), 4*pop); } emit_MMU_aluMemCycles(store ? 2 : 3, bb_cycles, pop); return 1; } static int OP_LDMIA_THUMB(const u32 i) { return op_ldm_stm_thumb(i, 0); } static int OP_STMIA_THUMB(const u32 i) { return op_ldm_stm_thumb(i, 1); } //----------------------------------------------------------------------------- // Adjust SP //----------------------------------------------------------------------------- static int OP_ADJUST_P_SP(const u32 i) { c.add(reg_ptr(13), ((i&0x7F)<<2)); return 1; } static int OP_ADJUST_M_SP(const u32 i) { c.sub(reg_ptr(13), ((i&0x7F)<<2)); return 1; } //----------------------------------------------------------------------------- // PUSH / POP //----------------------------------------------------------------------------- static int op_push_pop(u32 i, bool store, bool pc_lr) { u32 bitmask = (i & 0xFF); bitmask |= pc_lr << (store ? 14 : 15); u32 pop = popregcount(bitmask); int dir = store ? -1 : 1; GpVar adr = c.newGpVar(kX86VarTypeGpd); c.mov(adr, reg_ptr(13)); if(store) c.sub(adr, 4); call_ldm_stm(adr, bitmask, store, dir); if(pc_lr && !store) op_bx_thumb(reg_ptr(15), 0, PROCNUM == ARMCPU_ARM9); c.add(reg_ptr(13), 4*dir*pop); emit_MMU_aluMemCycles(store ? (pc_lr?4:3) : (pc_lr?5:2), bb_cycles, pop); return 1; } static int OP_PUSH(const u32 i) { return op_push_pop(i, 1, 0); } static int OP_PUSH_LR(const u32 i) { return op_push_pop(i, 1, 1); } static int OP_POP(const u32 i) { return op_push_pop(i, 0, 0); } static int OP_POP_PC(const u32 i) { return op_push_pop(i, 0, 1); } //----------------------------------------------------------------------------- // Branch //----------------------------------------------------------------------------- static int OP_B_COND(const u32 i) { Label skip = c.newLabel(); u32 dst = bb_r15 + ((u32)((s8)(i&0xFF))<<1); c.mov(cpu_ptr(instruct_adr), bb_next_instruction); emit_branch((i>>8)&0xF, skip); c.mov(cpu_ptr(instruct_adr), dst); c.add(bb_total_cycles, 2); c.bind(skip); return 1; } static int OP_B_UNCOND(const u32 i) { u32 dst = bb_r15 + (SIGNEXTEND_11(i)<<1); c.mov(cpu_ptr(instruct_adr), dst); return 1; } static int OP_BLX(const u32 i) { GpVar dst = c.newGpVar(kX86VarTypeGpd); c.mov(dst, reg_ptr(14)); c.add(dst, (i&0x7FF) << 1); c.and_(dst, 0xFFFFFFFC); c.mov(cpu_ptr(instruct_adr), dst); c.mov(reg_ptr(14), bb_next_instruction | 1); // reset T bit c.and_(cpu_ptr_byte(CPSR, 0), ~(1<<5)); return 1; } static int OP_BL_10(const u32 i) { u32 dst = bb_r15 + (SIGNEXTEND_11(i)<<12); c.mov(reg_ptr(14), dst); return 1; } static int OP_BL_11(const u32 i) { GpVar dst = c.newGpVar(kX86VarTypeGpd); c.mov(dst, reg_ptr(14)); c.add(dst, (i&0x7FF) << 1); c.mov(cpu_ptr(instruct_adr), dst); c.mov(reg_ptr(14), bb_next_instruction | 1); return 1; } static int op_bx_thumb(Mem srcreg, bool blx, bool test_thumb) { GpVar dst = c.newGpVar(kX86VarTypeGpd); GpVar thumb = c.newGpVar(kX86VarTypeGpd); c.mov(dst, srcreg); c.mov(thumb, dst); // * cpu->CPSR.bits.T = BIT0(Rm); c.and_(thumb, 1); // * if (blx) c.mov(reg_ptr(14), bb_next_instruction | 1); if(test_thumb) { GpVar mask = c.newGpVar(kX86VarTypeGpd); c.lea(mask, ptr_abs((void*)0xFFFFFFFC, thumb.r64(), kScale2Times)); c.and_(dst, mask); } else c.and_(dst, 0xFFFFFFFE); GpVar tmp = c.newGpVar(kX86VarTypeGpd); // * c.mov(tmp, cpu_ptr_byte(CPSR, 0)); // * c.and_(tmp, ~(1<< 5)); // * c.shl(thumb, 5); // * c.or_(tmp, thumb); // * c.mov(cpu_ptr_byte(CPSR, 0), tmp.r8Lo()); // ****************************** c.mov(cpu_ptr(instruct_adr), dst); return 1; } static int op_bx_thumbR15() { const u32 r15 = (bb_r15 & 0xFFFFFFFC); c.mov(cpu_ptr(instruct_adr), Imm(r15)); c.mov(reg_ptr(15), Imm(r15)); c.and_(cpu_ptr(CPSR), (u32)~(1<< 5)); return 1; } static int OP_BX_THUMB(const u32 i) { if (REG_POS(i, 3) == 15) return op_bx_thumbR15(); return op_bx_thumb(reg_pos_ptr(3), 0, 0); } static int OP_BLX_THUMB(const u32 i) { return op_bx_thumb(reg_pos_ptr(3), 1, 1); } static int OP_SWI_THUMB(const u32 i) { return op_swi(i & 0x1F); } //----------------------------------------------------------------------------- // Unimplemented; fall back to the C versions //----------------------------------------------------------------------------- #define OP_UND NULL #define OP_LDREX NULL #define OP_STREX NULL #define OP_LDC_P_IMM_OFF NULL #define OP_LDC_M_IMM_OFF NULL #define OP_LDC_P_PREIND NULL #define OP_LDC_M_PREIND NULL #define OP_LDC_P_POSTIND NULL #define OP_LDC_M_POSTIND NULL #define OP_LDC_OPTION NULL #define OP_STC_P_IMM_OFF NULL #define OP_STC_M_IMM_OFF NULL #define OP_STC_P_PREIND NULL #define OP_STC_M_PREIND NULL #define OP_STC_P_POSTIND NULL #define OP_STC_M_POSTIND NULL #define OP_STC_OPTION NULL #define OP_CDP NULL #define OP_UND_THUMB NULL #define OP_BKPT_THUMB NULL //----------------------------------------------------------------------------- // Dispatch table //----------------------------------------------------------------------------- typedef int (*ArmOpCompiler)(u32); static const ArmOpCompiler arm_instruction_compilers[4096] = { #define TABDECL(x) x #include "instruction_tabdef.inc" #undef TABDECL }; static const ArmOpCompiler thumb_instruction_compilers[1024] = { #define TABDECL(x) x #include "thumb_tabdef.inc" #undef TABDECL }; //----------------------------------------------------------------------------- // Generic instruction wrapper //----------------------------------------------------------------------------- template static u32 FASTCALL OP_DECODE() { u32 cycles; u32 adr = cpu->instruct_adr; if(thumb) { cpu->next_instruction = adr + 2; cpu->R[15] = adr + 4; u32 opcode = _MMU_read16(adr); _armlog(PROCNUM, adr, opcode); cycles = thumb_instructions_set[PROCNUM][opcode>>6](opcode); } else { cpu->next_instruction = adr + 4; cpu->R[15] = adr + 8; u32 opcode = _MMU_read32(adr); _armlog(PROCNUM, adr, opcode); if(CONDITION(opcode) == 0xE || TEST_COND(CONDITION(opcode), CODE(opcode), cpu->CPSR)) cycles = arm_instructions_set[PROCNUM][INSTRUCTION_INDEX(opcode)](opcode); else cycles = 1; } cpu->instruct_adr = cpu->next_instruction; return cycles; } static const ArmOpCompiled op_decode[2][2] = { OP_DECODE<0,0>, OP_DECODE<0,1>, OP_DECODE<1,0>, OP_DECODE<1,1> }; //----------------------------------------------------------------------------- // Compiler //----------------------------------------------------------------------------- static u32 instr_attributes(u32 opcode) { return bb_thumb ? thumb_attributes[opcode>>6] : instruction_attributes[INSTRUCTION_INDEX(opcode)]; } static bool instr_is_branch(u32 opcode) { u32 x = instr_attributes(opcode); if(bb_thumb) { // merge OP_BL_10+OP_BL_11 if (x & MERGE_NEXT) return false; return (x & BRANCH_ALWAYS) || ((x & BRANCH_POS0) && ((opcode&7) | ((opcode>>4)&8)) == 15) || (x & BRANCH_SWI) || (x & JIT_BYPASS); } else return (x & BRANCH_ALWAYS) || ((x & BRANCH_POS12) && REG_POS(opcode,12) == 15) || ((x & BRANCH_LDM) && BIT15(opcode)) || (x & BRANCH_SWI) || (x & JIT_BYPASS); } static bool instr_uses_r15(u32 opcode) { u32 x = instr_attributes(opcode); if(bb_thumb) return ((x & SRCREG_POS0) && ((opcode&7) | ((opcode>>4)&8)) == 15) || ((x & SRCREG_POS3) && REG_POS(opcode,3) == 15) || (x & JIT_BYPASS); else return ((x & SRCREG_POS0) && REG_POS(opcode,0) == 15) || ((x & SRCREG_POS8) && REG_POS(opcode,8) == 15) || ((x & SRCREG_POS12) && REG_POS(opcode,12) == 15) || ((x & SRCREG_POS16) && REG_POS(opcode,16) == 15) || ((x & SRCREG_STM) && BIT15(opcode)) || (x & JIT_BYPASS); } static bool instr_is_conditional(u32 opcode) { if(bb_thumb) return false; return !(CONDITION(opcode) == 0xE || (CONDITION(opcode) == 0xF && CODE(opcode) == 5)); } static int instr_cycles(u32 opcode) { u32 x = instr_attributes(opcode); u32 c = (x & INSTR_CYCLES_MASK); if(c == INSTR_CYCLES_VARIABLE) { if ((x & BRANCH_SWI) && !cpu->swi_tab) return 3; return 0; } if(instr_is_branch(opcode) && !(instr_attributes(opcode) & (BRANCH_ALWAYS|BRANCH_LDM))) c += 2; return c; } static bool instr_does_prefetch(u32 opcode) { u32 x = instr_attributes(opcode); if(bb_thumb) return thumb_instruction_compilers[opcode>>6] && (x & BRANCH_ALWAYS); else return instr_is_branch(opcode) && arm_instruction_compilers[INSTRUCTION_INDEX(opcode)] && ((x & BRANCH_ALWAYS) || (x & BRANCH_LDM)); } static const char *disassemble(u32 opcode) { if(bb_thumb) return thumb_instruction_names[opcode>>6]; static char str[100]; strcpy(str, arm_instruction_names[INSTRUCTION_INDEX(opcode)]); static const char *conds[16] = {"EQ","NE","CS","CC","MI","PL","VS","VC","HI","LS","GE","LT","GT","LE","AL","NV"}; if(instr_is_conditional(opcode)) { strcat(str, "."); strcat(str, conds[CONDITION(opcode)]); } return str; } static void sync_r15(u32 opcode, bool is_last, bool force) { if(instr_does_prefetch(opcode)) { if(force) { //assert(!instr_uses_r15(opcode)); JIT_COMMENT("sync_r15: force instruct_adr %08Xh (PREFETCH)", bb_adr); c.mov(cpu_ptr(instruct_adr), bb_next_instruction); } } else { if(force || (instr_attributes(opcode) & JIT_BYPASS) || (instr_attributes(opcode) & BRANCH_SWI) || (is_last && !instr_is_branch(opcode))) { JIT_COMMENT("sync_r15: next_instruction %08Xh - %s%s%s%s", bb_next_instruction, force?" FORCE":"", (instr_attributes(opcode) & JIT_BYPASS)?" BYPASS":"", (instr_attributes(opcode) & BRANCH_SWI)?" SWI":"", (is_last && !instr_is_branch(opcode))?" LAST":"" ); c.mov(cpu_ptr(next_instruction), bb_next_instruction); } if(instr_uses_r15(opcode)) { JIT_COMMENT("sync_r15: R15 %08Xh (USES R15)", bb_r15); c.mov(reg_ptr(15), bb_r15); } if(instr_attributes(opcode) & JIT_BYPASS) { JIT_COMMENT("sync_r15: instruct_adr %08Xh (JIT_BYPASS)", bb_adr); c.mov(cpu_ptr(instruct_adr), bb_adr); } } } static void emit_branch(int cond, Label to) { JIT_COMMENT("emit_branch cond %02X", cond); static const u8 cond_bit[] = {0x40, 0x40, 0x20, 0x20, 0x80, 0x80, 0x10, 0x10}; if(cond < 8) { c.test(flags_ptr, cond_bit[cond]); (cond & 1)?c.jnz(to):c.jz(to); } else { GpVar x = c.newGpVar(kX86VarTypeGpz); c.movzx(x, flags_ptr); c.and_(x, 0xF0); #if defined(_M_X64) || defined(__x86_64__) c.add(x, offsetof(armcpu_t,cond_table) + cond); c.test(byte_ptr(bb_cpu, x), 1); #else c.test(byte_ptr_abs((void*)(arm_cond_table + cond), x, kScaleNone), 1); #endif c.unuse(x); c.jz(to); } } static void emit_armop_call(u32 opcode) { ArmOpCompiler fc = bb_thumb? thumb_instruction_compilers[opcode>>6]: arm_instruction_compilers[INSTRUCTION_INDEX(opcode)]; if (fc && fc(opcode)) return; JIT_COMMENT("call interpreter"); GpVar arg = c.newGpVar(kX86VarTypeGpd); c.mov(arg, opcode); OpFunc f = bb_thumb ? thumb_instructions_set[PROCNUM][opcode>>6] : arm_instructions_set[PROCNUM][INSTRUCTION_INDEX(opcode)]; X86CompilerFuncCall* ctx = c.call((void*)f); ctx->setPrototype(ASMJIT_CALL_CONV, FuncBuilder1()); ctx->setArgument(0, arg); ctx->setReturn(bb_cycles); } static void _armlog(u8 proc, u32 addr, u32 opcode) { #if 0 #if 0 fprintf(stderr, "\t\t;R0:%08X R1:%08X R2:%08X R3:%08X R4:%08X R5:%08X R6:%08X R7:%08X R8:%08X R9:%08X\n\t\t;R10:%08X R11:%08X R12:%08X R13:%08X R14:%08X R15:%08X| next %08X, N:%i Z:%i C:%i V:%i\n", cpu->R[0], cpu->R[1], cpu->R[2], cpu->R[3], cpu->R[4], cpu->R[5], cpu->R[6], cpu->R[7], cpu->R[8], cpu->R[9], cpu->R[10], cpu->R[11], cpu->R[12], cpu->R[13], cpu->R[14], cpu->R[15], cpu->next_instruction, cpu->CPSR.bits.N, cpu->CPSR.bits.Z, cpu->CPSR.bits.C, cpu->CPSR.bits.V); #endif #define INDEX22(i) ((((i)>>16)&0xFF0)|(((i)>>4)&0xF)) char dasmbuf[4096]; if(cpu->CPSR.bits.T) des_thumb_instructions_set[((opcode)>>6)&1023](addr, opcode, dasmbuf); else des_arm_instructions_set[INDEX22(opcode)](addr, opcode, dasmbuf); #undef INDEX22 fprintf(stderr, "%s%c %08X\t%08X \t%s\n", cpu->CPSR.bits.T?"THUMB":"ARM", proc?'7':'9', addr, opcode, dasmbuf); #else return; #endif } template static u32 compile_basicblock() { #if LOG_JIT bool has_variable_cycles = FALSE; #endif u32 interpreted_cycles = 0; u32 start_adr = cpu->instruct_adr; u32 opcode = 0; bb_thumb = cpu->CPSR.bits.T; bb_opcodesize = bb_thumb ? 2 : 4; if (!JIT_MAPPED(start_adr & 0x0FFFFFFF, PROCNUM)) { printf("JIT: use unmapped memory address %08X\n", start_adr); execute = false; return 1; } #if LOG_JIT fprintf(stderr, "adr %08Xh %s%c\n", start_adr, ARMPROC.CPSR.bits.T ? "THUMB":"ARM", PROCNUM?'7':'9'); #endif c.clear(); c.newFunc(ASMJIT_CALL_CONV, FuncBuilder0()); c.getFunc()->setHint(kFuncHintNaked, true); c.getFunc()->setHint(kX86FuncHintPushPop, true); JIT_COMMENT("CPU ptr"); bb_cpu = c.newGpVar(kX86VarTypeGpz); c.mov(bb_cpu, (uintptr_t)&ARMPROC); JIT_COMMENT("reset bb_total_cycles"); bb_total_cycles = c.newGpVar(kX86VarTypeGpz); c.mov(bb_total_cycles, 0); #if (PROFILER_JIT_LEVEL > 0) JIT_COMMENT("Profiler ptr"); bb_profiler = c.newGpVar(kX86VarTypeGpz); c.mov(bb_profiler, (uintptr_t)&profiler_counter[PROCNUM]); #endif bb_constant_cycles = 0; for(u32 i=0, bEndBlock = 0; bEndBlock == 0; i++) { bb_adr = start_adr + (i * bb_opcodesize); if(bb_thumb) opcode = _MMU_read16(bb_adr); else opcode = _MMU_read32(bb_adr); #if LOG_JIT char dasmbuf[1024] = {0}; if(bb_thumb) des_thumb_instructions_set[opcode>>6](bb_adr, opcode, dasmbuf); else des_arm_instructions_set[INSTRUCTION_INDEX(opcode)](bb_adr, opcode, dasmbuf); fprintf(stderr, "%08X\t%s\t\t; %s \n", bb_adr, dasmbuf, disassemble(opcode)); #endif u32 cycles = instr_cycles(opcode); bEndBlock = instr_is_branch(opcode) || (i >= (CommonSettings.jit_max_block_size - 1)); #if LOG_JIT if (instr_is_conditional(opcode) && (cycles > 1) || (cycles == 0)) has_variable_cycles = TRUE; #endif bb_cycles = c.newGpVar(kX86VarTypeGpz); bb_constant_cycles += instr_is_conditional(opcode) ? 1 : cycles; JIT_COMMENT("%s (PC:%08X)", disassemble(opcode), bb_adr); #if (PROFILER_JIT_LEVEL > 0) JIT_COMMENT("*** profiler - counter"); if (bb_thumb) c.add(profiler_counter_thumb(opcode), 1); else c.add(profiler_counter_arm(opcode), 1); #endif if(instr_is_conditional(opcode)) { // 25% of conditional instructions are immediately followed by // another with the same condition, but merging them into a // single branch has negligible effect on speed. if(bEndBlock) sync_r15(opcode, 1, 1); Label skip = c.newLabel(); emit_branch(CONDITION(opcode), skip); if(!bEndBlock) sync_r15(opcode, 0, 0); emit_armop_call(opcode); if(cycles == 0) { JIT_COMMENT("variable cycles"); c.lea(bb_total_cycles, ptr(bb_total_cycles.r64(), bb_cycles.r64(), kScaleNone, -1)); } else if (cycles > 1) { JIT_COMMENT("cycles (%d)", cycles); c.lea(bb_total_cycles, ptr(bb_total_cycles.r64(), -1)); } c.bind(skip); } else { sync_r15(opcode, bEndBlock, 0); emit_armop_call(opcode); if(cycles == 0) { JIT_COMMENT("variable cycles"); c.lea(bb_total_cycles, ptr(bb_total_cycles.r64(), bb_cycles.r64(), kScaleNone)); } } interpreted_cycles += op_decode[PROCNUM][bb_thumb](); } if(!instr_does_prefetch(opcode)) { JIT_COMMENT("!instr_does_prefetch: copy next_instruction (%08X) to instruct_adr (%08X)", cpu->next_instruction, cpu->instruct_adr); GpVar x = c.newGpVar(kX86VarTypeGpd); c.mov(x, cpu_ptr(next_instruction)); c.mov(cpu_ptr(instruct_adr), x); c.unuse(x); //c.mov(cpu_ptr(instruct_adr), bb_adr); //c.mov(cpu_ptr(instruct_adr), bb_next_instruction); } JIT_COMMENT("total cycles (block)"); if (bb_constant_cycles > 0) c.add(bb_total_cycles, bb_constant_cycles); #if (PROFILER_JIT_LEVEL > 1) JIT_COMMENT("*** profiler - cycles"); u32 padr = ((start_adr & 0x07FFFFFE) >> 1); bb_profiler_entry = c.newGpVar(kX86VarTypeGpz); c.mov(bb_profiler_entry, (uintptr_t)&profiler_entry[PROCNUM][padr]); c.add(dword_ptr(bb_profiler_entry, offsetof(PROFILER_ENTRY, cycles)), bb_total_cycles); profiler_entry[PROCNUM][padr].addr = start_adr; #endif c.ret(bb_total_cycles); #if LOG_JIT fprintf(stderr, "cycles %d%s\n", bb_constant_cycles, has_variable_cycles ? " + variable" : ""); #endif c.endFunc(); ArmOpCompiled f = (ArmOpCompiled)c.make(); if(c.getError()) { fprintf(stderr, "JIT error at %s%c-%08X: %s\n", bb_thumb?"THUMB":"ARM", PROCNUM?'7':'9', start_adr, getErrorString(c.getError())); f = op_decode[PROCNUM][bb_thumb]; } #if LOG_JIT uintptr_t baddr = (uintptr_t)f; fprintf(stderr, "Block address %08lX\n\n", baddr); fflush(stderr); #endif JIT_COMPILED_FUNC(start_adr, PROCNUM) = (uintptr_t)f; return interpreted_cycles; } template u32 arm_jit_compile() { *PROCNUM_ptr = PROCNUM; // prevent endless recompilation of self-modifying code, which would be a memleak since we only free code all at once. // also allows us to clear compiled_funcs[] while leaving it sparsely allocated, if the OS does memory overcommit. u32 adr = cpu->instruct_adr; u32 mask_adr = (adr & 0x07FFFFFE) >> 4; if(((recompile_counts[mask_adr >> 1] >> 4*(mask_adr & 1)) & 0xF) > 8) { ArmOpCompiled f = op_decode[PROCNUM][cpu->CPSR.bits.T]; JIT_COMPILED_FUNC(adr, PROCNUM) = (uintptr_t)f; return f(); } recompile_counts[mask_adr >> 1] += 1 << 4*(mask_adr & 1); return compile_basicblock(); } template u32 arm_jit_compile<0>(); template u32 arm_jit_compile<1>(); void arm_jit_reset(bool enable, bool suppress_msg) { #if LOG_JIT c.setLogger(&logger); freopen("desmume_jit.log", "w", stderr); #endif #ifdef HAVE_STATIC_CODE_BUFFER scratchptr = scratchpad; #endif if (!suppress_msg) printf("CPU mode: %s\n", enable?"JIT":"Interpreter"); saveBlockSizeJIT = CommonSettings.jit_max_block_size; if (enable) { printf("JIT: max block size %d instruction(s)\n", CommonSettings.jit_max_block_size); #ifdef MAPPED_JIT_FUNCS //these pointers are allocated by asmjit and need freeing #define JITFREE(x) for(int iii=0;iiifree((void*)x[iii]); memset(x,0,sizeof(x)); JITFREE(JIT.MAIN_MEM); JITFREE(JIT.SWIRAM); JITFREE(JIT.ARM9_ITCM); JITFREE(JIT.ARM9_LCDC); JITFREE(JIT.ARM9_BIOS); JITFREE(JIT.ARM7_BIOS); JITFREE(JIT.ARM7_ERAM); JITFREE(JIT.ARM7_WIRAM); JITFREE(JIT.ARM7_WRAM); #undef JITFREE memset(recompile_counts, 0, sizeof(recompile_counts)); init_jit_mem(); #else for(int i=0; i 0) reconstruct(&profiler_counter[0]); reconstruct(&profiler_counter[1]); #if (PROFILER_JIT_LEVEL > 1) for (u8 t = 0; t < 2; t++) { for (u32 i = 0; i < (1<<26); i++) memset(&profiler_entry[t][i], 0, sizeof(PROFILER_ENTRY)); } #endif #endif } #if (PROFILER_JIT_LEVEL > 0) static int pcmp(PROFILER_COUNTER_INFO *info1, PROFILER_COUNTER_INFO *info2) { return (int)(info2->count - info1->count); } #if (PROFILER_JIT_LEVEL > 1) static int pcmp_entry(PROFILER_ENTRY *info1, PROFILER_ENTRY *info2) { return (int)(info1->cycles - info2->cycles); } #endif #endif void arm_jit_close() { #if (PROFILER_JIT_LEVEL > 0) printf("Generating profile report..."); for (u8 proc = 0; proc < 2; proc++) { extern GameInfo gameInfo; u16 last[2] = {0}; PROFILER_COUNTER_INFO *arm_info = NULL; PROFILER_COUNTER_INFO *thumb_info = NULL; arm_info = new PROFILER_COUNTER_INFO[4096]; thumb_info = new PROFILER_COUNTER_INFO[1024]; memset(arm_info, 0, sizeof(PROFILER_COUNTER_INFO) * 4096); memset(thumb_info, 0, sizeof(PROFILER_COUNTER_INFO) * 1024); // ARM last[0] = 0; for (u16 i=0; i < 4096; i++) { u16 t = 0; if (profiler_counter[proc].arm_count[i] == 0) continue; for (t = 0; t < last[0]; t++) { if (strcmp(arm_instruction_names[i], arm_info[t].name) == 0) { arm_info[t].count += profiler_counter[proc].arm_count[i]; break; } } if (t == last[0]) { strcpy(arm_info[last[0]++].name, arm_instruction_names[i]); arm_info[t].count = profiler_counter[proc].arm_count[i]; } } // THUMB last[1] = 0; for (u16 i=0; i < 1024; i++) { u16 t = 0; if (profiler_counter[proc].thumb_count[i] == 0) continue; for (t = 0; t < last[1]; t++) { if (strcmp(thumb_instruction_names[i], thumb_info[t].name) == 0) { thumb_info[t].count += profiler_counter[proc].thumb_count[i]; break; } } if (t == last[1]) { strcpy(thumb_info[last[1]++].name, thumb_instruction_names[i]); thumb_info[t].count = profiler_counter[proc].thumb_count[i]; } } std::qsort(arm_info, last[0], sizeof(PROFILER_COUNTER_INFO), (int (*)(const void *, const void *))pcmp); std::qsort(thumb_info, last[1], sizeof(PROFILER_COUNTER_INFO), (int (*)(const void *, const void *))pcmp); char buf[MAX_PATH] = {0}; sprintf(buf, "desmume_jit%c_counter.profiler", proc==0?'9':'7'); FILE *fp = fopen(buf, "w"); if (fp) { if (!gameInfo.isHomebrew()) { fprintf(fp, "Name: %s\n", gameInfo.ROMname); fprintf(fp, "Serial: %s\n", gameInfo.ROMserial); } else fprintf(fp, "Homebrew\n"); fprintf(fp, "CPU: ARM%c\n\n", proc==0?'9':'7'); if (last[0]) { fprintf(fp, "========================================== ARM ==========================================\n"); for (int i=0; i < last[0]; i++) fprintf(fp, "%30s: %20ld\n", arm_info[i].name, arm_info[i].count); fprintf(fp, "\n"); } if (last[1]) { fprintf(fp, "========================================== THUMB ==========================================\n"); for (int i=0; i < last[1]; i++) fprintf(fp, "%30s: %20ld\n", thumb_info[i].name, thumb_info[i].count); fprintf(fp, "\n"); } fclose(fp); } delete [] arm_info; arm_info = NULL; delete [] thumb_info; thumb_info = NULL; #if (PROFILER_JIT_LEVEL > 1) sprintf(buf, "desmume_jit%c_entry.profiler", proc==0?'9':'7'); fp = fopen(buf, "w"); if (fp) { u32 count = 0; PROFILER_ENTRY *tmp = NULL; fprintf(fp, "Entrypoints (cycles):\n"); tmp = new PROFILER_ENTRY[1<<26]; memset(tmp, 0, sizeof(PROFILER_ENTRY) * (1<<26)); for (u32 i = 0; i < (1<<26); i++) { if (profiler_entry[proc][i].cycles == 0) continue; memcpy(&tmp[count++], &profiler_entry[proc][i], sizeof(PROFILER_ENTRY)); } std::qsort(tmp, count, sizeof(PROFILER_ENTRY), (int (*)(const void *, const void *))pcmp_entry); if (!gameInfo.isHomebrew()) { fprintf(fp, "Name: %s\n", gameInfo.ROMname); fprintf(fp, "Serial: %s\n", gameInfo.ROMserial); } else fprintf(fp, "Homebrew\n"); fprintf(fp, "CPU: ARM%c\n\n", proc==0?'9':'7'); while ((count--) > 0) fprintf(fp, "%08X: %20ld\n", tmp[count].addr, tmp[count].cycles); delete [] tmp; tmp = NULL; fclose(fp); } #endif } printf(" done.\n"); #endif } #endif // HAVE_JIT desmume/src/libretro-common/include/string/stdstring.h000664 001750 001750 00000004245 12755534123 024377 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2015 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (stdstring.h). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef __LIBRETRO_SDK_STDSTRING_H #define __LIBRETRO_SDK_STDSTRING_H #include #include #include #include #include RETRO_BEGIN_DECLS bool string_is_empty(const char *data); bool string_is_equal(const char *a, const char *b); bool string_is_equal_noncase(const char *a, const char *b); char *string_to_upper(char *s); char *string_to_lower(char *s); char *string_ucwords(char* s); char *string_replace_substring(const char *in, const char *pattern, const char *by); /* Remove leading whitespaces */ char *string_trim_whitespace_left(char *const s); /* Remove trailing whitespaces */ char *string_trim_whitespace_right(char *const s); /* Remove leading and trailing whitespaces */ char *string_trim_whitespace(char *const s); RETRO_END_DECLS #endif desmume/src/libretro-common/include/math/complex.h000664 001750 001750 00000004373 12755534123 023452 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2016 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (complex.h). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef __LIBRETRO_SDK_MATH_COMPLEX_H__ #define __LIBRETRO_SDK_MATH_COMPLEX_H__ #include #include typedef struct { float real; float imag; } fft_complex_t; static INLINE fft_complex_t fft_complex_mul(fft_complex_t a, fft_complex_t b) { fft_complex_t out = { a.real * b.real - a.imag * b.imag, a.imag * b.real + a.real * b.imag, }; return out; } static INLINE fft_complex_t fft_complex_add(fft_complex_t a, fft_complex_t b) { fft_complex_t out = { a.real + b.real, a.imag + b.imag, }; return out; } static INLINE fft_complex_t fft_complex_sub(fft_complex_t a, fft_complex_t b) { fft_complex_t out = { a.real - b.real, a.imag - b.imag, }; return out; } static INLINE fft_complex_t fft_complex_conj(fft_complex_t a) { fft_complex_t out = { a.real, -a.imag, }; return out; } #endif desmume/src/path.cpp000664 001750 001750 00000012057 12755534123 015604 0ustar00sergiosergio000000 000000 /* Copyright (C) 2009-2011 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the this software. If not, see . */ #include "types.h" #include "path.h" #include //----------------------------------- //This is taken from mono Path.cs static const char InvalidPathChars[] = { '\x22', '\x3C', '\x3E', '\x7C', '\x00', '\x01', '\x02', '\x03', '\x04', '\x05', '\x06', '\x07', '\x08', '\x09', '\x0A', '\x0B', '\x0C', '\x0D', '\x0E', '\x0F', '\x10', '\x11', '\x12', '\x13', '\x14', '\x15', '\x16', '\x17', '\x18', '\x19', '\x1A', '\x1B', '\x1C', '\x1D', '\x1E', '\x1F' //but I added this #ifdef HOST_WINDOWS ,'\x2F' #endif }; //but it is sort of windows-specific. Does it work in linux? Maybe we'll have to make it smarter static const char VolumeSeparatorChar = ':'; static const char AltDirectorySeparatorChar = '/'; static bool dirEqualsVolume = (DIRECTORY_DELIMITER_CHAR == VolumeSeparatorChar); bool Path::IsPathRooted (const std::string &path) { if (path.empty()) return false; if (path.find_first_of(InvalidPathChars) != std::string::npos) return false; char c = path[0]; return (c == DIRECTORY_DELIMITER_CHAR || c == AltDirectorySeparatorChar || (!dirEqualsVolume && path.size() > 1 && path[1] == VolumeSeparatorChar)); } std::string Path::GetFileDirectoryPath(std::string filePath) { if( filePath.empty() ) return ""; #if !defined(HOST_WINDOWS) size_t i = filePath.find_last_of(ALL_DIRECTORY_DELIMITER_STRING); if(i == std::string::npos) return filePath; return filePath.substr(0, i); #else char path[MAX_PATH] = {0}; strncpy( path, filePath.c_str(), sizeof(path) ); if( filePath.length() >= MAX_PATH ) path[MAX_PATH - 1] = '\0'; PathRemoveFileSpec(path); return std::string(path); #endif } std::string Path::GetFileNameFromPath(std::string filePath) { if( filePath.empty() ) return ""; #if !defined(HOST_WINDOWS) size_t i = filePath.find_last_of(ALL_DIRECTORY_DELIMITER_STRING); if(i == std::string::npos) return filePath; return filePath.substr(i + 1); #else char path[MAX_PATH] = {0}; strncpy( path, filePath.c_str(), sizeof(path) ); if( filePath.length() >= MAX_PATH ) path[MAX_PATH - 1] = '\0'; PathStripPath(path); return std::string(path); #endif } std::string Path::GetFileNameWithoutExt(std::string fileName) { if (fileName.empty()) return ""; #if !defined(HOST_WINDOWS) size_t i = fileName.find_last_of(FILE_EXT_DELIMITER_CHAR); if (i == std::string::npos) return fileName; return fileName.substr(0, i); #else char path[MAX_PATH] = {0}; strncpy( path, fileName.c_str(), sizeof(path) ); if( fileName.length() >= MAX_PATH ) path[MAX_PATH - 1] = '\0'; PathRemoveExtension(path); return std::string(path); #endif } std::string Path::ScrubInvalid(std::string str) { #if !defined(HOST_WINDOWS) for (std::string::iterator it(str.begin()); it != str.end(); ++it) { bool ok = true; for(int i=0;i= 1024) buffer[1024 - 1] = '\0'; for(i = 0; i < length; i += size) { c = buffer + i; if(*c == '\0') break; size = _mbclen( (unsigned char *)c ); // •¶Žš‚̃oƒCƒg”‚ðŽæ“¾ if(size <= 0) break; if(size != 1) continue; for( j = 0; j < ARRAY_SIZE(InvalidPathChars); ++j ) { if( InvalidPathChars[j] != *c ) continue; *c = '*'; break; } } return (std::string)buffer; #endif } std::string Path::GetFileNameFromPathWithoutExt(std::string filePath) { if (filePath.empty()) return ""; std::string fileName = GetFileNameFromPath(filePath); return GetFileNameWithoutExt(fileName); } std::string Path::GetFileExt(std::string fileName) { if (fileName.empty()) return ""; #if !defined(HOST_WINDOWS) size_t i = fileName.find_last_of(FILE_EXT_DELIMITER_CHAR); if (i == std::string::npos) return fileName; return fileName.substr(i + 1); #else char path[MAX_PATH] = {0}; char *extension; strncpy( path, fileName.c_str(), sizeof(path) ); if( fileName.length() >= MAX_PATH ) path[MAX_PATH - 1] = '\0'; extension = PathFindExtension(path); return std::string(extension); #endif } desmume/src/OGLRender.h000664 001750 001750 00000045056 12755534123 016103 0ustar00sergiosergio000000 000000 /* Copyright (C) 2006 yopyop Copyright (C) 2006-2007 shash Copyright (C) 2008-2016 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the this software. If not, see . */ #ifndef OGLRENDER_H #define OGLRENDER_H #include #include #include #include "render3D.h" #include "types.h" #define OGLRENDER_MAX_MULTISAMPLES 16 #define OGLRENDER_VERT_INDEX_BUFFER_COUNT (POLYLIST_SIZE * 6) enum OGLVertexAttributeID { OGLVertexAttributeID_Position = 0, OGLVertexAttributeID_TexCoord0 = 8, OGLVertexAttributeID_Color = 3, }; enum OGLTextureUnitID { // Main textures will always be on texture unit 0. OGLTextureUnitID_FinalColor = 1, OGLTextureUnitID_ToonTable, OGLTextureUnitID_GColor, OGLTextureUnitID_GDepth, OGLTextureUnitID_GPolyID, OGLTextureUnitID_FogAttr, OGLTextureUnitID_PolyStates }; enum OGLBindingPointID { OGLBindingPointID_RenderStates = 0 }; enum OGLErrorCode { OGLERROR_NOERR = RENDER3DERROR_NOERR, OGLERROR_BEGINGL_FAILED, OGLERROR_FEATURE_UNSUPPORTED, OGLERROR_VBO_UNSUPPORTED, OGLERROR_PBO_UNSUPPORTED, OGLERROR_SHADER_UNSUPPORTED, OGLERROR_VAO_UNSUPPORTED, OGLERROR_FBO_UNSUPPORTED, OGLERROR_MULTISAMPLED_FBO_UNSUPPORTED, OGLERROR_VERTEX_SHADER_PROGRAM_LOAD_ERROR, OGLERROR_FRAGMENT_SHADER_PROGRAM_LOAD_ERROR, OGLERROR_SHADER_CREATE_ERROR, OGLERROR_FBO_CREATE_ERROR }; union GLvec2 { struct { GLfloat x, y; }; GLfloat v[2]; }; union GLvec3 { struct { GLfloat r, g, b; }; struct { GLfloat x, y, z; }; GLfloat v[3]; }; union GLvec4 { struct { GLfloat r, g, b, a; }; struct { GLfloat x, y, z, w; }; GLfloat v[4]; }; struct OGLVertex { GLvec4 position; GLvec2 texCoord; GLvec3 color; }; struct OGLRenderStates { GLvec2 framebufferSize; GLint toonShadingMode; GLuint enableAlphaTest; GLuint enableAntialiasing; GLuint enableEdgeMarking; GLuint enableFogAlphaOnly; GLuint useWDepth; GLfloat alphaTestRef; GLfloat fogOffset; GLfloat fogStep; GLfloat pad_0; // This needs to be here to preserve alignment GLvec4 fogColor; GLvec4 fogDensity[32]; // Array of floats need to be padded as vec4 GLvec4 edgeColor[8]; GLvec4 toonColor[32]; }; struct OGLPolyStates { union { struct { GLubyte enableTexture, enableFog, enableDepthWrite, setNewDepthForTranslucent; }; GLubyte flags[4]; }; union { struct { GLubyte polyAlpha, polyMode, polyID, valuesPad[1]; }; GLubyte values[4]; }; union { struct { GLubyte texSizeS, texSizeT, texParamPad[2]; }; GLubyte texParam[4]; }; }; struct OGLRenderRef { // OpenGL Feature Support GLint stateTexMirroredRepeat; // VBO GLuint vboGeometryVtxID; GLuint iboGeometryIndexID; GLuint vboPostprocessVtxID; GLuint iboPostprocessIndexID; // PBO GLuint pboRenderDataID; // UBO / TBO GLuint uboRenderStatesID; GLuint tboPolyStatesID; GLuint texPolyStatesID; // FBO GLuint texCIColorID; GLuint texCIDepthID; GLuint texCIFogAttrID; GLuint texCIPolyID; GLuint texCIDepthStencilID; GLuint texGColorID; GLuint texGDepthID; GLuint texGFogAttrID; GLuint texGPolyID; GLuint texGDepthStencilID; GLuint texPostprocessFogID; GLuint texFinalColorID; GLuint rboMSGColorID; GLuint rboMSGDepthID; GLuint rboMSGPolyID; GLuint rboMSGFogAttrID; GLuint rboMSGDepthStencilID; GLuint rboFramebufferRGBA6665ID; GLuint fboClearImageID; GLuint fboRenderID; GLuint fboPostprocessID; GLuint fboMSIntermediateRenderID; GLuint selectedRenderingFBO; // Shader states GLuint vertexGeometryShaderID; GLuint fragmentGeometryShaderID; GLuint programGeometryID; GLuint vertexEdgeMarkShaderID; GLuint vertexFogShaderID; GLuint vertexFramebufferOutputShaderID; GLuint fragmentEdgeMarkShaderID; GLuint fragmentFogShaderID; GLuint fragmentFramebufferRGBA6665OutputShaderID; GLuint fragmentFramebufferRGBA8888OutputShaderID; GLuint programEdgeMarkID; GLuint programFogID; GLuint programFramebufferRGBA6665OutputID; GLuint programFramebufferRGBA8888OutputID; GLint uniformFramebufferSize; GLint uniformStateToonShadingMode; GLint uniformStateEnableAlphaTest; GLint uniformStateEnableAntialiasing; GLint uniformStateEnableEdgeMarking; GLint uniformStateEnableFogAlphaOnly; GLint uniformStateUseWDepth; GLint uniformStateAlphaTestRef; GLint uniformStateEdgeColor; GLint uniformStateFogColor; GLint uniformStateFogDensity; GLint uniformStateFogOffset; GLint uniformStateFogStep; GLint uniformPolyTexScale; GLint uniformPolyMode; GLint uniformPolyEnableDepthWrite; GLint uniformPolySetNewDepthForTranslucent; GLint uniformPolyAlpha; GLint uniformPolyID; GLint uniformPolyEnableTexture; GLint uniformPolyEnableFog; GLint uniformPolyStateIndex; GLuint texToonTableID; // VAO GLuint vaoGeometryStatesID; GLuint vaoPostprocessStatesID; // Textures std::queue freeTextureIDs; // Client-side Buffers GLfloat *color4fBuffer; GLushort *vertIndexBuffer; CACHE_ALIGN GLuint workingCIDepthBuffer[GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT]; CACHE_ALIGN GLuint workingCIDepthStencilBuffer[GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT]; CACHE_ALIGN GLuint workingCIFogAttributesBuffer[GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT]; CACHE_ALIGN GLuint workingCIPolyIDBuffer[GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT]; // Vertex Attributes Pointers GLvoid *vtxPtrPosition; GLvoid *vtxPtrTexCoord; GLvoid *vtxPtrColor; }; struct GFX3D_State; struct VERTLIST; struct POLYLIST; struct INDEXLIST; struct POLY; class TexCacheItem; class OpenGLRenderer; extern GPU3DInterface gpu3Dgl; extern GPU3DInterface gpu3DglOld; extern GPU3DInterface gpu3Dgl_3_2; extern const GLenum RenderDrawList[4]; extern CACHE_ALIGN const GLfloat divide5bitBy31_LUT[32]; extern const GLfloat PostprocessVtxBuffer[16]; extern const GLubyte PostprocessElementBuffer[6]; extern void texDeleteCallback(TexCacheItem *texItem, void *param1, void *param2); //This is called by OGLRender whenever it initializes. //Platforms, please be sure to set this up. //return true if you successfully init. extern bool (*oglrender_init)(); //This is called by OGLRender before it uses opengl. //return true if youre OK with using opengl extern bool (*oglrender_beginOpenGL)(); //This is called by OGLRender after it is done using opengl. extern void (*oglrender_endOpenGL)(); //This is called by OGLRender whenever the framebuffer is resized. extern bool (*oglrender_framebufferDidResizeCallback)(size_t w, size_t h); // Helper functions for calling the above function pointers at the // beginning and ending of OpenGL commands. bool BEGINGL(); void ENDGL(); // These functions need to be assigned by ports that support using an // OpenGL 3.2 Core Profile context. The OGLRender_3_2.cpp file includes // the corresponding functions to assign to each function pointer. // // If any of these functions are unassigned, then one of the legacy OpenGL // renderers will be used instead. extern void (*OGLLoadEntryPoints_3_2_Func)(); extern void (*OGLCreateRenderer_3_2_Func)(OpenGLRenderer **rendererPtr); FORCEINLINE u32 BGRA8888_32_To_RGBA6665_32(const u32 srcPix); FORCEINLINE u32 BGRA8888_32Rev_To_RGBA6665_32Rev(const u32 srcPix); bool IsVersionSupported(unsigned int checkVersionMajor, unsigned int checkVersionMinor, unsigned int checkVersionRevision); #if defined(ENABLE_SSSE3) class OpenGLRenderer : public Render3D_SSSE3 #elif defined(ENABLE_SSE2) class OpenGLRenderer : public Render3D_SSE2 #else class OpenGLRenderer : public Render3D #endif { private: // Driver's OpenGL Version unsigned int versionMajor; unsigned int versionMinor; unsigned int versionRevision; private: Render3DError _FlushFramebufferConvertOnCPU(const FragmentColor *__restrict srcFramebuffer, FragmentColor *__restrict dstFramebuffer, u16 *__restrict dstRGBA5551); protected: // OpenGL-specific References OGLRenderRef *ref; // OpenGL Feature Support bool isVBOSupported; bool isPBOSupported; bool isFBOSupported; bool isMultisampledFBOSupported; bool isShaderSupported; bool isVAOSupported; bool willFlipFramebufferOnGPU; bool willConvertFramebufferOnGPU; // Textures TexCacheItem *currTexture; FragmentColor *_mappedFramebuffer; bool _pixelReadNeedsFinish; size_t _currentPolyIndex; std::vector _shadowPolyID; Render3DError FlushFramebuffer(const FragmentColor *__restrict srcFramebuffer, FragmentColor *__restrict dstFramebuffer, u16 *__restrict dstRGBA5551); // OpenGL-specific methods virtual Render3DError CreateVBOs() = 0; virtual void DestroyVBOs() = 0; virtual Render3DError CreatePBOs() = 0; virtual void DestroyPBOs() = 0; virtual Render3DError CreateFBOs() = 0; virtual void DestroyFBOs() = 0; virtual Render3DError CreateMultisampledFBO() = 0; virtual void DestroyMultisampledFBO() = 0; virtual Render3DError InitGeometryProgram(const std::string &vertexShaderProgram, const std::string &fragmentShaderProgram) = 0; virtual void DestroyGeometryProgram() = 0; virtual Render3DError CreateVAOs() = 0; virtual void DestroyVAOs() = 0; virtual Render3DError InitTextures() = 0; virtual Render3DError InitFinalRenderStates(const std::set *oglExtensionSet) = 0; virtual Render3DError InitTables() = 0; virtual Render3DError InitPostprocessingPrograms(const std::string &edgeMarkVtxShader, const std::string &edgeMarkFragShader, const std::string &fogVtxShader, const std::string &fogFragShader, const std::string &framebufferOutputVtxShader, const std::string &framebufferOutputRGBA6665FragShader, const std::string &framebufferOutputRGBA8888FragShader) = 0; virtual Render3DError DestroyPostprocessingPrograms() = 0; virtual Render3DError InitEdgeMarkProgramBindings() = 0; virtual Render3DError InitEdgeMarkProgramShaderLocations() = 0; virtual Render3DError InitFogProgramBindings() = 0; virtual Render3DError InitFogProgramShaderLocations() = 0; virtual Render3DError InitFramebufferOutputProgramBindings() = 0; virtual Render3DError InitFramebufferOutputShaderLocations() = 0; virtual Render3DError LoadGeometryShaders(std::string &outVertexShaderProgram, std::string &outFragmentShaderProgram) = 0; virtual Render3DError InitGeometryProgramBindings() = 0; virtual Render3DError InitGeometryProgramShaderLocations() = 0; virtual Render3DError CreateToonTable() = 0; virtual Render3DError DestroyToonTable() = 0; virtual Render3DError UploadClearImage(const u16 *__restrict colorBuffer, const u32 *__restrict depthBuffer, const u8 *__restrict fogBuffer, const u8 *__restrict polyIDBuffer) = 0; virtual void GetExtensionSet(std::set *oglExtensionSet) = 0; virtual Render3DError ExpandFreeTextures() = 0; virtual Render3DError EnableVertexAttributes() = 0; virtual Render3DError DisableVertexAttributes() = 0; virtual Render3DError DownsampleFBO() = 0; virtual Render3DError ReadBackPixels() = 0; virtual void SetPolygonIndex(const size_t index) = 0; public: OpenGLRenderer(); virtual ~OpenGLRenderer(); virtual Render3DError InitExtensions() = 0; virtual Render3DError DeleteTexture(const TexCacheItem *item) = 0; bool IsExtensionPresent(const std::set *oglExtensionSet, const std::string extensionName) const; bool ValidateShaderCompile(GLuint theShader) const; bool ValidateShaderProgramLink(GLuint theProgram) const; void GetVersion(unsigned int *major, unsigned int *minor, unsigned int *revision) const; void SetVersion(unsigned int major, unsigned int minor, unsigned int revision); virtual FragmentColor* GetFramebuffer(); }; class OpenGLRenderer_1_2 : public OpenGLRenderer { protected: // OpenGL-specific methods virtual Render3DError CreateVBOs(); virtual void DestroyVBOs(); virtual Render3DError CreatePBOs(); virtual void DestroyPBOs(); virtual Render3DError CreateFBOs(); virtual void DestroyFBOs(); virtual Render3DError CreateMultisampledFBO(); virtual void DestroyMultisampledFBO(); virtual Render3DError CreateVAOs(); virtual void DestroyVAOs(); virtual Render3DError InitTextures(); virtual Render3DError InitFinalRenderStates(const std::set *oglExtensionSet); virtual Render3DError InitTables(); virtual Render3DError InitGeometryProgram(const std::string &vertexShaderProgram, const std::string &fragmentShaderProgram); virtual Render3DError LoadGeometryShaders(std::string &outVertexShaderProgram, std::string &outFragmentShaderProgram); virtual Render3DError InitGeometryProgramBindings(); virtual Render3DError InitGeometryProgramShaderLocations(); virtual void DestroyGeometryProgram(); virtual Render3DError InitPostprocessingPrograms(const std::string &edgeMarkVtxShader, const std::string &edgeMarkFragShader, const std::string &fogVtxShader, const std::string &fogFragShader, const std::string &framebufferOutputVtxShader, const std::string &framebufferOutputRGBA6665FragShader, const std::string &framebufferOutputRGBA8888FragShader); virtual Render3DError DestroyPostprocessingPrograms(); virtual Render3DError InitEdgeMarkProgramBindings(); virtual Render3DError InitEdgeMarkProgramShaderLocations(); virtual Render3DError InitFogProgramBindings(); virtual Render3DError InitFogProgramShaderLocations(); virtual Render3DError InitFramebufferOutputProgramBindings(); virtual Render3DError InitFramebufferOutputShaderLocations(); virtual Render3DError CreateToonTable(); virtual Render3DError DestroyToonTable(); virtual Render3DError UploadClearImage(const u16 *__restrict colorBuffer, const u32 *__restrict depthBuffer, const u8 *__restrict fogBuffer, const u8 *__restrict polyIDBuffer); virtual void GetExtensionSet(std::set *oglExtensionSet); virtual Render3DError ExpandFreeTextures(); virtual Render3DError EnableVertexAttributes(); virtual Render3DError DisableVertexAttributes(); virtual Render3DError DownsampleFBO(); virtual Render3DError ReadBackPixels(); // Base rendering methods virtual Render3DError BeginRender(const GFX3D &engine); virtual Render3DError RenderGeometry(const GFX3D_State &renderState, const POLYLIST *polyList, const INDEXLIST *indexList); virtual Render3DError EndRender(const u64 frameCount); virtual Render3DError ClearUsingImage(const u16 *__restrict colorBuffer, const u32 *__restrict depthBuffer, const u8 *__restrict fogBuffer, const u8 *__restrict polyIDBuffer); virtual Render3DError ClearUsingValues(const FragmentColor &clearColor, const FragmentAttributes &clearAttributes) const; virtual void SetPolygonIndex(const size_t index); virtual Render3DError SetupPolygon(const POLY &thePoly); virtual Render3DError SetupTexture(const POLY &thePoly, bool enableTexturing); virtual Render3DError SetupViewport(const u32 viewportValue); public: ~OpenGLRenderer_1_2(); virtual Render3DError InitExtensions(); virtual Render3DError UpdateToonTable(const u16 *toonTableBuffer); virtual Render3DError Reset(); virtual Render3DError RenderFinish(); virtual Render3DError SetFramebufferSize(size_t w, size_t h); virtual Render3DError DeleteTexture(const TexCacheItem *item); }; class OpenGLRenderer_1_3 : public OpenGLRenderer_1_2 { protected: virtual Render3DError CreateToonTable(); virtual Render3DError UploadClearImage(const u16 *__restrict colorBuffer, const u32 *__restrict depthBuffer, const u8 *__restrict fogBuffer, const u8 *__restrict polyIDBuffer); public: virtual Render3DError UpdateToonTable(const u16 *toonTableBuffer); virtual Render3DError SetFramebufferSize(size_t w, size_t h); }; class OpenGLRenderer_1_4 : public OpenGLRenderer_1_3 { protected: virtual Render3DError InitFinalRenderStates(const std::set *oglExtensionSet); }; class OpenGLRenderer_1_5 : public OpenGLRenderer_1_4 { protected: virtual Render3DError CreateVBOs(); virtual void DestroyVBOs(); virtual Render3DError CreateVAOs(); virtual Render3DError EnableVertexAttributes(); virtual Render3DError DisableVertexAttributes(); virtual Render3DError BeginRender(const GFX3D &engine); public: ~OpenGLRenderer_1_5(); }; class OpenGLRenderer_2_0 : public OpenGLRenderer_1_5 { protected: virtual Render3DError InitExtensions(); virtual Render3DError InitFinalRenderStates(const std::set *oglExtensionSet); virtual Render3DError InitPostprocessingPrograms(const std::string &edgeMarkVtxShader, const std::string &edgeMarkFragShader, const std::string &fogVtxShader, const std::string &fogFragShader, const std::string &framebufferOutputVtxShader, const std::string &framebufferOutputRGBA6665FragShader, const std::string &framebufferOutputRGBA8888FragShader); virtual Render3DError DestroyPostprocessingPrograms(); virtual Render3DError InitEdgeMarkProgramBindings(); virtual Render3DError InitEdgeMarkProgramShaderLocations(); virtual Render3DError InitFogProgramBindings(); virtual Render3DError InitFogProgramShaderLocations(); virtual Render3DError InitFramebufferOutputProgramBindings(); virtual Render3DError InitFramebufferOutputShaderLocations(); virtual Render3DError EnableVertexAttributes(); virtual Render3DError DisableVertexAttributes(); virtual Render3DError BeginRender(const GFX3D &engine); virtual Render3DError RenderEdgeMarking(const u16 *colorTable, const bool useAntialias); virtual Render3DError RenderFog(const u8 *densityTable, const u32 color, const u32 offset, const u8 shift, const bool alphaOnly); virtual Render3DError SetupPolygon(const POLY &thePoly); virtual Render3DError SetupTexture(const POLY &thePoly, bool enableTexturing); }; class OpenGLRenderer_2_1 : public OpenGLRenderer_2_0 { protected: virtual Render3DError ReadBackPixels(); public: virtual Render3DError RenderFinish(); }; #endif desmume/src/libretro-common/include/formats/rbmp.h000664 001750 001750 00000004135 12755534123 023461 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2015 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (rbmp.h). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef __LIBRETRO_SDK_FORMAT_RBMP_H__ #define __LIBRETRO_SDK_FORMAT_RBMP_H__ #include #include RETRO_BEGIN_DECLS enum rbmp_source_type { RBMP_SOURCE_TYPE_DONT_CARE, RBMP_SOURCE_TYPE_BGR24, RBMP_SOURCE_TYPE_XRGB888, RBMP_SOURCE_TYPE_RGB565, RBMP_SOURCE_TYPE_ARGB8888 }; typedef struct rbmp rbmp_t; bool rbmp_save_image( const char *filename, const void *frame, unsigned width, unsigned height, unsigned pitch, enum rbmp_source_type type); int rbmp_process_image(rbmp_t *rbmp, void **buf, size_t size, unsigned *width, unsigned *height); bool rbmp_set_buf_ptr(rbmp_t *rbmp, void *data); void rbmp_free(rbmp_t *rbmp); rbmp_t *rbmp_alloc(void); RETRO_END_DECLS #endif desmume/src/path.h000664 001750 001750 00000024431 12755534123 015250 0ustar00sergiosergio000000 000000 /* Copyright (C) 2009-2015 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the this software. If not, see . */ #include #include "types.h" #include "libretro.h" extern retro_log_printf_t log_cb; extern retro_environment_t environ_cb; #include "time.h" #include "utils/xstring.h" #ifdef _WIN32 #define FILE_EXT_DELIMITER_CHAR '.' #define DIRECTORY_DELIMITER_CHAR '\\' #define ALL_DIRECTORY_DELIMITER_STRING "/\\" #else #define FILE_EXT_DELIMITER_CHAR '.' #define DIRECTORY_DELIMITER_CHAR '/' #define ALL_DIRECTORY_DELIMITER_STRING "/" #endif class Path { public: static bool IsPathRooted (const std::string &path); static std::string GetFileDirectoryPath(std::string filePath); static std::string GetFileNameFromPath(std::string filePath); static std::string ScrubInvalid(std::string str); static std::string GetFileNameWithoutExt(std::string fileName); static std::string GetFileNameFromPathWithoutExt(std::string filePath); static std::string GetFileExt(std::string fileName); }; class PathInfo { public: std::string path; std::string RomName; std::string RomDirectory; #define MAX_FORMAT 20 #define SECTION "PathSettings" #define ROMKEY "Roms" #define BATTERYKEY "Battery" #define STATEKEY "States" #define SCREENSHOTKEY "Screenshots" #define AVIKEY "AviFiles" #define CHEATKEY "Cheats" #define R4FORMATKEY "R4format" #define SOUNDKEY "SoundSamples" #define FIRMWAREKEY "Firmware" #define FORMATKEY "format" #define DEFAULTFORMATKEY "defaultFormat" #define NEEDSSAVINGKEY "needsSaving" #define LASTVISITKEY "lastVisit" #define LUAKEY "Lua" #define SLOT1DKEY "Slot1D" char screenshotFormat[MAX_FORMAT]; bool savelastromvisit; enum KnownPath { FIRSTKNOWNPATH = 0, ROMS = 0, BATTERY, STATES, SCREENSHOTS, AVI_FILES, CHEATS, SOUNDS, FIRMWARE, MODULE, SLOT1D, MAXKNOWNPATH = MODULE }; char pathToRoms[PATH_MAX_LENGTH]; char pathToBattery[PATH_MAX_LENGTH]; char pathToStates[PATH_MAX_LENGTH]; char pathToScreenshots[PATH_MAX_LENGTH]; char pathToAviFiles[PATH_MAX_LENGTH]; char pathToCheats[PATH_MAX_LENGTH]; char pathToSounds[PATH_MAX_LENGTH]; char pathToFirmware[PATH_MAX_LENGTH]; char pathToModule[PATH_MAX_LENGTH]; char pathToLua[PATH_MAX_LENGTH]; char pathToSlot1D[PATH_MAX_LENGTH]; void init(const char *filename) { path = std::string(filename); //extract the internal part of the logical rom name std::vector parts = tokenize_str(filename,"|"); SetRomName(parts[parts.size()-1].c_str()); LoadModulePath(); #if !defined(WIN32) && !defined(DESMUME_COCOA) ReadPathSettings(); #endif } void LoadModulePath() { const char* saveDir = 0; environ_cb(RETRO_ENVIRONMENT_GET_SAVE_DIRECTORY, &saveDir); strncpy(pathToModule, saveDir ? saveDir : ".", PATH_MAX_LENGTH); if(saveDir == 0 && log_cb) { log_cb(RETRO_LOG_WARN, "Save directory is not defined. Fallback on using SYSTEM directory ...\n"); const char* systemDir = 0; environ_cb(RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY, &systemDir); strncpy(pathToModule, systemDir ? systemDir : ".", PATH_MAX_LENGTH); if(systemDir == 0 && log_cb) log_cb(RETRO_LOG_WARN, "System directory is not defined. Fallback to ROM dir\n"); } } enum Action { GET, SET }; void GetDefaultPath(char *pathToDefault, const char *key, int maxCount) { #ifdef HOST_WINDOWS std::string temp = (std::string)"." + DIRECTORY_DELIMITER_CHAR + pathToDefault; strncpy(pathToDefault, temp.c_str(), maxCount); #else strncpy(pathToDefault, pathToModule, maxCount); #endif } void ReadKey(char *pathToRead, const char *key) { #ifdef HOST_WINDOWS GetPrivateProfileString(SECTION, key, key, pathToRead, PATH_MAX_LENGTH, IniName); //since the variables are all intialized in this file they all use PATH_MAX_LENGTH if(strcmp(pathToRead, key) == 0) GetDefaultPath(pathToRead, key, PATH_MAX_LENGTH); #else //since the variables are all intialized in this file they all use PATH_MAX_LENGTH GetDefaultPath(pathToRead, key, PATH_MAX_LENGTH); #endif } void ReadPathSettings() { if( ( strcmp(pathToModule, "") == 0) || !pathToModule) LoadModulePath(); ReadKey(pathToRoms, ROMKEY); ReadKey(pathToBattery, BATTERYKEY); ReadKey(pathToStates, STATEKEY); ReadKey(pathToScreenshots, SCREENSHOTKEY); ReadKey(pathToAviFiles, AVIKEY); ReadKey(pathToCheats, CHEATKEY); ReadKey(pathToSounds, SOUNDKEY); ReadKey(pathToFirmware, FIRMWAREKEY); ReadKey(pathToLua, LUAKEY); ReadKey(pathToSlot1D, SLOT1DKEY); #ifdef HOST_WINDOWS GetPrivateProfileString(SECTION, FORMATKEY, "%f_%s_%r", screenshotFormat, MAX_FORMAT, IniName); savelastromvisit = GetPrivateProfileBool(SECTION, LASTVISITKEY, true, IniName); currentimageformat = (ImageFormat)GetPrivateProfileInt(SECTION, DEFAULTFORMATKEY, PNG, IniName); r4Format = (R4Format)GetPrivateProfileInt(SECTION, R4FORMATKEY, R4_CHEAT_DAT, IniName); if ((r4Format != R4_CHEAT_DAT) && (r4Format != R4_USRCHEAT_DAT)) { r4Format = R4_USRCHEAT_DAT; WritePrivateProfileInt(SECTION, R4FORMATKEY, r4Format, IniName); } #endif /* needsSaving = GetPrivateProfileInt(SECTION, NEEDSSAVINGKEY, TRUE, IniName); if(needsSaving) { needsSaving = FALSE; WritePathSettings(); }*/ } void SwitchPath(Action action, KnownPath path, char *buffer) { char *pathToCopy = 0; switch(path) { case ROMS: pathToCopy = pathToRoms; break; case BATTERY: pathToCopy = pathToBattery; break; case STATES: pathToCopy = pathToStates; break; case SCREENSHOTS: pathToCopy = pathToScreenshots; break; case AVI_FILES: pathToCopy = pathToAviFiles; break; case CHEATS: pathToCopy = pathToCheats; break; case SOUNDS: pathToCopy = pathToSounds; break; case FIRMWARE: pathToCopy = pathToFirmware; break; case MODULE: pathToCopy = pathToModule; break; case SLOT1D: pathToCopy = pathToSlot1D; break; } if(action == GET) { std::string thePath = pathToCopy; std::string relativePath = (std::string)"." + DIRECTORY_DELIMITER_CHAR; int len = (int)thePath.size()-1; if(len == -1) thePath = relativePath; else if(thePath[len] != DIRECTORY_DELIMITER_CHAR) thePath += DIRECTORY_DELIMITER_CHAR; if(!Path::IsPathRooted(thePath)) { thePath = (std::string)pathToModule + thePath; } strncpy(buffer, thePath.c_str(), PATH_MAX_LENGTH); } else if(action == SET) { int len = strlen(buffer)-1; if(buffer[len] == DIRECTORY_DELIMITER_CHAR) buffer[len] = '\0'; strncpy(pathToCopy, buffer, PATH_MAX_LENGTH); } } std::string getpath(KnownPath path) { char temp[PATH_MAX_LENGTH]; SwitchPath(GET, path, temp); return temp; } void getpath(KnownPath path, char *buffer) { SwitchPath(GET, path, buffer); } void setpath(KnownPath path, char *buffer) { SwitchPath(SET, path, buffer); } void getfilename(char *buffer, int maxCount) { strcpy(buffer,noextension().c_str()); } void getpathnoext(KnownPath path, char *buffer) { getpath(path, buffer); strcat(buffer, GetRomNameWithoutExtension().c_str()); } std::string extension() { return Path::GetFileExt(path); } std::string noextension() { std::string romNameWithPath = Path::GetFileDirectoryPath(path) + DIRECTORY_DELIMITER_CHAR + Path::GetFileNameWithoutExt(RomName); return romNameWithPath; } void formatname(char *output) { // Except 't' for tick and 'r' for random. const char* strftimeArgs = "AbBcCdDeFgGhHIjmMnpRStTuUVwWxXyYzZ%"; std::string file; time_t now = time(NULL); tm *time_struct = localtime(&now); srand((unsigned)now); for (char* p = screenshotFormat, *end = p + sizeof(screenshotFormat); p < end; p++) { if (*p != '%') { file.append(1, *p); } else { p++; if (*p == 'f') { file.append(GetRomNameWithoutExtension()); } else if (*p == 'r') { file.append(stditoa(rand())); } else if (*p == 't') { file.append(stditoa(clock() >> 5)); } else if (strchr(strftimeArgs, *p)) { char tmp[PATH_MAX_LENGTH]; char format[] = { '%', *p, '\0' }; strftime(tmp, PATH_MAX_LENGTH, format, time_struct); file.append(tmp); } } } #ifdef WIN32 // Replace invalid file name character. { const char* invalids = "\\/:*?\"<>|"; size_t pos = 0; while ((pos = file.find_first_of(invalids, pos)) != std::string::npos) { file[pos] = '-'; } } #endif strncpy(output, file.c_str(), PATH_MAX_LENGTH); } enum R4Format { R4_CHEAT_DAT = 0, R4_USRCHEAT_DAT = 1 }; R4Format r4Format; enum ImageFormat { PNG = 0, BMP = 1 }; ImageFormat currentimageformat; ImageFormat imageformat() { return currentimageformat; } void SetRomName(const char *filename) { std::string romPath = filename; RomName = Path::GetFileNameFromPath(romPath); RomName = Path::ScrubInvalid(RomName); RomDirectory = Path::GetFileDirectoryPath(romPath); } const char *GetRomName() { return RomName.c_str(); } std::string GetRomNameWithoutExtension() { if (RomName.c_str() == NULL) return ""; return Path::GetFileNameWithoutExt(RomName); } bool isdsgba(std::string fileName) { size_t i = fileName.find_last_of(FILE_EXT_DELIMITER_CHAR); if (i != std::string::npos) fileName = fileName.substr(i - 2); if(fileName == "ds.gba") return true; return false; } }; extern PathInfo path; desmume/src/libretro-common/crt/include/000700 001750 001750 00000000000 12756420131 021440 5ustar00sergiosergio000000 000000 desmume/src/libretro-common/file/000700 001750 001750 00000000000 12756420131 020144 5ustar00sergiosergio000000 000000 desmume/src/libretro-common/include/dynamic/000700 001750 001750 00000000000 12756420131 022274 5ustar00sergiosergio000000 000000 desmume/src/PACKED_END.h000664 001750 001750 00000000052 12755534123 015722 0ustar00sergiosergio000000 000000 #ifndef __GNUC__ #pragma pack(pop) #endif desmume/src/utils/arm_arm/arm_gen.cpp000664 001750 001750 00000014573 12755534123 021043 0ustar00sergiosergio000000 000000 #include #include #include #include #include #include #include "arm_gen.h" #ifdef _3DS # include # include "3ds/memory.h" #elif defined(VITA) # include # define RW_INIT sceKernelOpenVMDomain # define RW_END sceKernelCloseVMDomain #else # include #endif // __clear_cache(start, end) #ifdef __BLACKBERRY_QNX__ #undef __clear_cache #define __clear_cache(start,end) msync(start, (size_t)((void*)end - (void*)start), MS_SYNC | MS_CACHE_ONLY | MS_INVALIDATE_ICACHE); #elif defined(__MACH__) #include #define __clear_cache mach_clear_cache static void __clear_cache(void *start, void *end) { size_t len = (char *)end - (char *)start; sys_dcache_flush(start, len); sys_icache_invalidate(start, len); } #elif defined(_3DS) #undef __clear_cache #define __clear_cache(start,end)FlushInvalidateCache(); #elif defined(VITA) #undef __clear_cache #define __clear_cache(start,end)sceKernelSyncVMDomain(block, start, (char *)end - (char *)start) #endif namespace arm_gen { #ifdef _3DS uint32_t* _instructions = 0; #endif code_pool::code_pool(uint32_t icount) : instruction_count(icount), instructions(0), next_instruction(0), flush_start(0) { printf("\n\ncode_pool icount: %i\n\n", icount); literal_count = 0; memset(labels, 0, sizeof(labels)); memset(branches, 0, sizeof(branches)); #if defined(_3DS) if(!_instructions) { _instructions = (uint32_t*)memalign(4096, instruction_count * 4); if (!_instructions) { fprintf(stderr, "memalign failed\n"); abort(); } ReprotectMemory((unsigned int*)_instructions, (instruction_count * 4) / 4096, 7); } instructions = _instructions; #elif defined(VITA) block = sceKernelAllocMemBlockForVM("desmume_rwx_block", instruction_count * 4); if (block < 0) { fprintf(stderr, "sceKernelAllocMemBlockForVM failed\n"); abort(); } if (sceKernelGetMemBlockBase(block, (void **)&instructions) < 0) { fprintf(stderr, "sceKernelGetMemBlockBase failed\n"); abort(); } #elif defined(USE_POSIX_MEMALIGN) if (posix_memalign((void**)&instructions, 4096, instruction_count * 4)) { fprintf(stderr, "posix_memalign failed\n"); abort(); } if (mprotect(instructions, instruction_count * 4, PROT_READ | PROT_WRITE | PROT_EXEC)) { fprintf(stderr, "mprotect failed\n"); abort(); } #else instructions = (uint32_t*)memalign(4096, instruction_count * 4); if (!instructions) { fprintf(stderr, "memalign failed\n"); abort(); } if (mprotect(instructions, instruction_count * 4, PROT_READ | PROT_WRITE | PROT_EXEC)) { fprintf(stderr, "mprotect failed\n"); abort(); } #endif } code_pool::~code_pool() { #ifdef _3DS //ReprotectMemory((unsigned int*)instructions, (instruction_count * 4) / 4096, 3); #elif defined(VITA) sceKernelFreeMemBlock(block); #else mprotect(instructions, instruction_count * 4, PROT_READ | PROT_WRITE); free(instructions); #endif } void* code_pool::fn_pointer() { void* result = &instructions[flush_start]; __clear_cache(&instructions[flush_start], &instructions[next_instruction]); flush_start = next_instruction; return result; } void code_pool::set_label(const char* name) { for (int i = 0; i < TARGET_COUNT; i ++) { if (labels[i].name == name) { fprintf(stderr, "Duplicate label\n"); abort(); } } for (int i = 0; i < TARGET_COUNT; i ++) { if (labels[i].name == 0) { labels[i].name = name; labels[i].position = next_instruction; return; } } fprintf(stderr, "Label overflow\n"); abort(); } void code_pool::resolve_label(const char* name) { #ifdef VITA RW_INIT(); #endif for (int i = 0; i < TARGET_COUNT; i ++) { if (labels[i].name != name) { continue; } for (int j = 0; j < TARGET_COUNT; j ++) { if (branches[j].name != name) { continue; } const uint32_t source = branches[j].position; const uint32_t target = labels[i].position; instructions[source] |= ((target - source) - 2) & 0xFFFFFF; branches[j].name = 0; } labels[i].name = 0; break; } #ifdef VITA RW_END(); #endif } // Code Gen: Generic void code_pool::insert_instruction(uint32_t op, AG_COND cond) { assert(cond < CONDINVALID); insert_raw_instruction((op & 0x0FFFFFFF) | (cond << 28)); } void code_pool::insert_raw_instruction(uint32_t op) { if (next_instruction >= instruction_count) { fprintf(stderr, "code_pool overflow\n"); abort(); } #ifdef VITA RW_INIT(); #endif instructions[next_instruction ++] = op; #ifdef VITA RW_END(); #endif } void code_pool::alu_op(AG_ALU_OP op, reg_t rd, reg_t rn, const alu2& arg, AG_COND cond) { assert(op < OPINVALID); insert_instruction( (op << 20) | (rn << 16) | (rd << 12) | arg.encoding, cond ); } void code_pool::mem_op(AG_MEM_OP op, reg_t rd, reg_t rn, const mem2& arg, AG_MEM_FLAGS flags, AG_COND cond) { uint32_t instruction = 0x04000000; instruction |= (op & 1) ? 1 << 20 : 0; instruction |= (op & 2) ? 1 << 22 : 0; instruction |= arg.encoding; instruction |= rd << 12; instruction |= rn << 16; instruction |= flags ^ 0x1800000; insert_instruction( instruction, cond ); } void code_pool::b(const char* target, AG_COND cond) { assert(target); for (int i = 0; i < TARGET_COUNT; i ++) { if (branches[i].name == 0) { branches[i].name = target; branches[i].position = next_instruction; insert_instruction( 0x0A000000, cond ); return; } } assert(false); } void code_pool::load_constant(reg_t target_reg, uint32_t constant, AG_COND cond) { // TODO: Support another method for ARM procs that don't have movw|movt uint32_t instructions[2] = { 0x03000000, 0x03400000 }; for (int i = 0; i < 2; i ++, constant >>= 16) { // If the upper 16-bits are zero the movt op is not needed if (i == 1 && constant == 0) break; instructions[i] |= target_reg << 12; instructions[i] |= constant & 0xFFF; instructions[i] |= (constant & 0xF000) << 4; insert_instruction( instructions[i], cond ); } } } // namespace arm_gen desmume/src/libretro-common/streams/file_stream.c000664 001750 001750 00000032316 12755534123 023370 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2016 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (file_stream.c). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include #include #include #include #if defined(_WIN32) # ifdef _MSC_VER # define setmode _setmode # endif # ifdef _XBOX # include # define INVALID_FILE_ATTRIBUTES -1 # else # include # include # include # include # endif #else # if defined(PSP) # include # endif # include # include # if !defined(VITA) # include # endif # include #endif #ifdef __CELLOS_LV2__ #include #define O_RDONLY CELL_FS_O_RDONLY #define O_WRONLY CELL_FS_O_WRONLY #define O_CREAT CELL_FS_O_CREAT #define O_TRUNC CELL_FS_O_TRUNC #define O_RDWR CELL_FS_O_RDWR #else #include #endif #include #include struct RFILE { unsigned hints; #if defined(PSP) SceUID fd; #else #define HAVE_BUFFERED_IO 1 #if defined(HAVE_BUFFERED_IO) FILE *fp; #endif #if defined(HAVE_MMAP) uint8_t *mapped; uint64_t mappos; uint64_t mapsize; #endif int fd; #endif }; int filestream_get_fd(RFILE *stream) { if (!stream) return -1; #if defined(HAVE_BUFFERED_IO) if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0) return fileno(stream->fp); #endif return stream->fd; } RFILE *filestream_open(const char *path, unsigned mode, ssize_t len) { int flags = 0; int mode_int = 0; #if defined(HAVE_BUFFERED_IO) const char *mode_str = NULL; #endif RFILE *stream = (RFILE*)calloc(1, sizeof(*stream)); if (!stream) return NULL; (void)mode_int; (void)flags; stream->hints = mode; #ifdef HAVE_MMAP if (stream->hints & RFILE_HINT_MMAP && (stream->hints & 0xff) == RFILE_MODE_READ) stream->hints |= RFILE_HINT_UNBUFFERED; else #endif stream->hints &= ~RFILE_HINT_MMAP; switch (mode & 0xff) { case RFILE_MODE_READ_TEXT: #if defined(PSP) mode_int = 0666; flags = PSP_O_RDONLY; #else #if defined(HAVE_BUFFERED_IO) if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0) mode_str = "r"; #endif /* No "else" here */ flags = O_RDONLY; #endif break; case RFILE_MODE_READ: #if defined(PSP) mode_int = 0666; flags = PSP_O_RDONLY; #else #if defined(HAVE_BUFFERED_IO) if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0) mode_str = "rb"; #endif /* No "else" here */ flags = O_RDONLY; #endif break; case RFILE_MODE_WRITE: #if defined(PSP) mode_int = 0666; flags = PSP_O_CREAT | PSP_O_WRONLY | PSP_O_TRUNC; #else #if defined(HAVE_BUFFERED_IO) if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0) mode_str = "wb"; #endif else { flags = O_WRONLY | O_CREAT | O_TRUNC; #ifndef _WIN32 flags |= S_IRUSR | S_IWUSR; #endif } #endif break; case RFILE_MODE_READ_WRITE: #if defined(PSP) mode_int = 0666; flags = PSP_O_RDWR; #else #if defined(HAVE_BUFFERED_IO) if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0) mode_str = "w+"; #endif else { flags = O_RDWR; #ifdef _WIN32 flags |= O_BINARY; #endif } #endif break; } #if defined(PSP) stream->fd = sceIoOpen(path, flags, mode_int); #else #if defined(HAVE_BUFFERED_IO) if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0) { stream->fp = fopen(path, mode_str); if (!stream->fp) goto error; } else #endif { stream->fd = open(path, flags); if (stream->fd == -1) goto error; #ifdef HAVE_MMAP if (stream->hints & RFILE_HINT_MMAP) { stream->mappos = 0; stream->mapped = NULL; stream->mapsize = filestream_seek(stream, 0, SEEK_END); if (stream->mapsize == (uint64_t)-1) goto error; filestream_rewind(stream); stream->mapped = (uint8_t*)mmap((void*)0, stream->mapsize, PROT_READ, MAP_SHARED, stream->fd, 0); if (stream->mapped == MAP_FAILED) stream->hints &= ~RFILE_HINT_MMAP; } #endif } #endif #if defined(PSP) if (stream->fd == -1) goto error; #endif return stream; error: filestream_close(stream); return NULL; } char *filestream_getline(RFILE *stream) { char* newline = (char*)malloc(9); char* newline_tmp = NULL; size_t cur_size = 8; size_t idx = 0; int in = filestream_getc(stream); if (!newline) return NULL; while (in != EOF && in != '\n') { if (idx == cur_size) { cur_size *= 2; newline_tmp = (char*)realloc(newline, cur_size + 1); if (!newline_tmp) { free(newline); return NULL; } newline = newline_tmp; } newline[idx++] = in; in = filestream_getc(stream); } newline[idx] = '\0'; return newline; } char *filestream_gets(RFILE *stream, char *s, size_t len) { if (!stream) return NULL; #if defined(HAVE_BUFFERED_IO) return fgets(s, len, stream->fp); #elif defined(PSP) if(filestream_read(stream,s,len)==len) return s; return NULL; #else return gets(s); #endif } int filestream_getc(RFILE *stream) { char c = 0; (void)c; if (!stream) return 0; #if defined(HAVE_BUFFERED_IO) return fgetc(stream->fp); #elif defined(PSP) if(filestream_read(stream, &c, 1) == 1) return (int)c; return EOF; #else return getc(stream->fd); #endif } ssize_t filestream_seek(RFILE *stream, ssize_t offset, int whence) { if (!stream) goto error; #if defined(PSP) if (sceIoLseek(stream->fd, (SceOff)offset, whence) == -1) goto error; #else #if defined(HAVE_BUFFERED_IO) if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0) return fseek(stream->fp, (long)offset, whence); #endif #ifdef HAVE_MMAP /* Need to check stream->mapped because this function is * called in filestream_open() */ if (stream->mapped && stream->hints & RFILE_HINT_MMAP) { /* fseek() returns error on under/overflow but allows cursor > EOF for read-only file descriptors. */ switch (whence) { case SEEK_SET: if (offset < 0) goto error; stream->mappos = offset; break; case SEEK_CUR: if ((offset < 0 && stream->mappos + offset > stream->mappos) || (offset > 0 && stream->mappos + offset < stream->mappos)) goto error; stream->mappos += offset; break; case SEEK_END: if (stream->mapsize + offset < stream->mapsize) goto error; stream->mappos = stream->mapsize + offset; break; } return stream->mappos; } #endif if (lseek(stream->fd, offset, whence) < 0) goto error; #endif return 0; error: return -1; } int filestream_eof(RFILE *stream) { size_t current_position = filestream_tell(stream); size_t end_position = filestream_seek(stream, 0, SEEK_END); filestream_seek(stream, current_position, SEEK_SET); if (current_position >= end_position) return 1; return 0; } ssize_t filestream_tell(RFILE *stream) { if (!stream) goto error; #if defined(PSP) if (sceIoLseek(stream->fd, 0, SEEK_CUR) < 0) goto error; #else #if defined(HAVE_BUFFERED_IO) if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0) return ftell(stream->fp); #endif #ifdef HAVE_MMAP /* Need to check stream->mapped because this function * is called in filestream_open() */ if (stream->mapped && stream->hints & RFILE_HINT_MMAP) return stream->mappos; #endif if (lseek(stream->fd, 0, SEEK_CUR) < 0) goto error; #endif return 0; error: return -1; } void filestream_rewind(RFILE *stream) { filestream_seek(stream, 0L, SEEK_SET); } ssize_t filestream_read(RFILE *stream, void *s, size_t len) { if (!stream || !s) goto error; #if defined(PSP) return sceIoRead(stream->fd, s, len); #else #if defined(HAVE_BUFFERED_IO) if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0) return fread(s, 1, len, stream->fp); #endif #ifdef HAVE_MMAP if (stream->hints & RFILE_HINT_MMAP) { if (stream->mappos > stream->mapsize) goto error; if (stream->mappos + len > stream->mapsize) len = stream->mapsize - stream->mappos; memcpy(s, &stream->mapped[stream->mappos], len); stream->mappos += len; return len; } #endif return read(stream->fd, s, len); #endif error: return -1; } ssize_t filestream_write(RFILE *stream, const void *s, size_t len) { if (!stream) goto error; #if defined(PSP) return sceIoWrite(stream->fd, s, len); #else #if defined(HAVE_BUFFERED_IO) if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0) return fwrite(s, 1, len, stream->fp); #endif #ifdef HAVE_MMAP if (stream->hints & RFILE_HINT_MMAP) goto error; #endif return write(stream->fd, s, len); #endif error: return -1; } int filestream_putc(RFILE *stream, int c) { if (!stream) return EOF; #if defined(HAVE_BUFFERED_IO) return fputc(c, stream->fp); #else /* unimplemented */ return EOF; #endif } int filestream_close(RFILE *stream) { if (!stream) goto error; #if defined(PSP) if (stream->fd > 0) sceIoClose(stream->fd); #else #if defined(HAVE_BUFFERED_IO) if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0) { if (stream->fp) fclose(stream->fp); } else #endif #ifdef HAVE_MMAP if (stream->hints & RFILE_HINT_MMAP) munmap(stream->mapped, stream->mapsize); #endif if (stream->fd > 0) close(stream->fd); #endif free(stream); return 0; error: return -1; } /** * filestream_read_file: * @path : path to file. * @buf : buffer to allocate and read the contents of the * file into. Needs to be freed manually. * * Read the contents of a file into @buf. * * Returns: number of items read, -1 on error. */ int filestream_read_file(const char *path, void **buf, ssize_t *len) { ssize_t ret = 0; ssize_t content_buf_size = 0; void *content_buf = NULL; RFILE *file = filestream_open(path, RFILE_MODE_READ, -1); if (!file) { fprintf(stderr, "Failed to open %s: %s\n", path, strerror(errno)); goto error; } if (filestream_seek(file, 0, SEEK_END) != 0) goto error; content_buf_size = filestream_tell(file); if (content_buf_size < 0) goto error; filestream_rewind(file); content_buf = malloc(content_buf_size + 1); if (!content_buf) goto error; ret = filestream_read(file, content_buf, content_buf_size); if (ret < 0) { fprintf(stderr, "Failed to read %s: %s\n", path, strerror(errno)); goto error; } filestream_close(file); *buf = content_buf; /* Allow for easy reading of strings to be safe. * Will only work with sane character formatting (Unix). */ ((char*)content_buf)[content_buf_size] = '\0'; if (len) *len = ret; return 1; error: if (file) filestream_close(file); if (content_buf) free(content_buf); if (len) *len = -1; *buf = NULL; return 0; } /** * filestream_write_file: * @path : path to file. * @data : contents to write to the file. * @size : size of the contents. * * Writes data to a file. * * Returns: true (1) on success, false (0) otherwise. */ bool filestream_write_file(const char *path, const void *data, ssize_t size) { ssize_t ret = 0; RFILE *file = filestream_open(path, RFILE_MODE_WRITE, -1); if (!file) return false; ret = filestream_write(file, data, size); filestream_close(file); if (ret != size) return false; return true; } desmume/src/addons/slot2_piano.cpp000664 001750 001750 00000005461 12755534123 020352 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2013 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the this software. If not, see . */ #include "../slot2.h" static u16 pianoKeyStatus = 0; class Slot2_EasyPiano : public ISlot2Interface { public: virtual Slot2Info const* info() { static Slot2InfoSimple info("Piano", "Piano for EasyPiano", 0x06); return &info; } virtual void connect() { pianoKeyStatus = 0; } virtual u8 readByte(u8 PROCNUM, u32 addr) { //printf("piano: read 08 at 0x%08X\n", adr); //the actual keyboard output //byte:bit //0x09FFFFFE:0 = C //0x09FFFFFE:1 = C# //0x09FFFFFE:2 = D //0x09FFFFFE:3 = D# //0x09FFFFFE:4 = E //0x09FFFFFE:5 = F //0x09FFFFFE:6 = F# //0x09FFFFFE:7 = G //0x09FFFFFF:0 = G# //0x09FFFFFF:1 = A //0x09FFFFFF:2 = A# //0x09FFFFFF:3 = ? //0x09FFFFFF:4 = ? //0x09FFFFFF:5 = B //0x09FFFFFF:6 = hiC //0x09FFFFFF:7 = ? //deassert bit if key is pressed //LOG("PIANO: %04X\n",pianoKeyStatus); if(addr == 0x09FFFFFE) return (~(pianoKeyStatus&0xFF)); if(addr == 0x09FFFFFF) return (~((pianoKeyStatus>>8)&0xFF))&~(0x18); return (addr & 1)?0xE7:0xFF; } virtual u16 readWord(u8 PROCNUM, u32 addr) { if (addr != 0x09FFFFFE) return 0xE7FF; return readByte(PROCNUM, 0x09FFFFFE) | (readByte(PROCNUM,0x09FFFFFF) << 8); } virtual u32 readLong(u8 PROCNUM, u32 addr) { return 0xE7FFE7FF; } }; ISlot2Interface* construct_Slot2_EasyPiano() { return new Slot2_EasyPiano(); } void piano_setKey(bool c, bool cs, bool d, bool ds, bool e, bool f, bool fs, bool g, bool gs, bool a, bool as, bool b, bool hic) { //0x09FFFFFE:0 = C //0x09FFFFFE:1 = C# //0x09FFFFFE:2 = D //0x09FFFFFE:3 = D# //0x09FFFFFE:4 = E //0x09FFFFFE:5 = F //0x09FFFFFE:6 = F# //0x09FFFFFE:7 = G //0x09FFFFFE:0 = G# //0x09FFFFFE:1 = A //0x09FFFFFF:2 = A# //0x09FFFFFF:3 = ? //0x09FFFFFF:4 = ? //0x09FFFFFF:5 = B //0x09FFFFFF:6 = hiC //0x09FFFFFF:7 = ? #define BIT_P(N,v) ((v)?(1<<(N)):0) pianoKeyStatus = BIT_P(0,c) | BIT_P(1,cs) | BIT_P(2,d) | BIT_P(3,ds) | BIT_P(4,e) | BIT_P(5,f) | BIT_P(6,fs) | BIT_P(7,g) | BIT_P(8,gs) | BIT_P(9,a) | BIT_P(10,as) | BIT_P(13,b) | BIT_P(14,hic) ; } desmume/src/libretro-common/string/000700 001750 001750 00000000000 12756420131 020533 5ustar00sergiosergio000000 000000 desmume/src/addons/slot2_none.cpp000664 001750 001750 00000001715 12755534123 020201 0ustar00sergiosergio000000 000000 /* Copyright (C) 2009 CrazyMax Copyright (C) 2009-2013 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the this software. If not, see . */ #include "../slot2.h" class Slot2_None : public ISlot2Interface { public: virtual Slot2Info const* info() { static Slot2InfoSimple info("None", "Slot2 no-device emulation", 0xFF); return &info; } }; ISlot2Interface* construct_Slot2_None() { return new Slot2_None(); } desmume/src/libretro-common/file/nbio/test/000700 001750 001750 00000000000 12756420131 022052 5ustar00sergiosergio000000 000000 desmume/src/libretro-common/include/filters.h000664 001750 001750 00000005532 12755534123 022520 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2016 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (filters.h). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef _LIBRETRO_SDK_FILTERS_H #define _LIBRETRO_SDK_FILTERS_H /* for MSVC; should be benign under any circumstances */ #define _USE_MATH_DEFINES #include #include #include #include static INLINE double sinc(double val) { if (fabs(val) < 0.00001) return 1.0; return sin(val) / val; } /* Paeth prediction filter. */ static INLINE int paeth(int a, int b, int c) { int p = a + b - c; int pa = abs(p - a); int pb = abs(p - b); int pc = abs(p - c); if (pa <= pb && pa <= pc) return a; else if (pb <= pc) return b; return c; } /* Modified Bessel function of first order. * Check Wiki for mathematical definition ... */ static INLINE double besseli0(double x) { unsigned i; double sum = 0.0; double factorial = 1.0; double factorial_mult = 0.0; double x_pow = 1.0; double two_div_pow = 1.0; double x_sqr = x * x; /* Approximate. This is an infinite sum. * Luckily, it converges rather fast. */ for (i = 0; i < 18; i++) { sum += x_pow * two_div_pow / (factorial * factorial); factorial_mult += 1.0; x_pow *= x_sqr; two_div_pow *= 0.25; factorial *= factorial_mult; } return sum; } static INLINE double kaiser_window_function(double index, double beta) { return besseli0(beta * sqrtf(1 - index * index)); } static INLINE double lanzcos_window_function(double index) { return sinc(M_PI * index); } #endif desmume/src/libretro-common/include/formats/rpng.h000664 001750 001750 00000004260 12755534123 023466 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2015 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (rpng.h). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef __LIBRETRO_SDK_FORMAT_RPNG_H__ #define __LIBRETRO_SDK_FORMAT_RPNG_H__ #include #include #include #include RETRO_BEGIN_DECLS typedef struct rpng rpng_t; rpng_t *rpng_init(const char *path); bool rpng_is_valid(rpng_t *rpng); bool rpng_set_buf_ptr(rpng_t *rpng, void *data); rpng_t *rpng_alloc(void); void rpng_free(rpng_t *rpng); bool rpng_iterate_image(rpng_t *rpng); int rpng_process_image(rpng_t *rpng, void **data, size_t size, unsigned *width, unsigned *height); bool rpng_start(rpng_t *rpng); bool rpng_save_image_argb(const char *path, const uint32_t *data, unsigned width, unsigned height, unsigned pitch); bool rpng_save_image_bgr24(const char *path, const uint8_t *data, unsigned width, unsigned height, unsigned pitch); RETRO_END_DECLS #endif desmume/src/utils/task.h000664 001750 001750 00000002333 12755534123 016413 0ustar00sergiosergio000000 000000 /* Copyright (C) 2009 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the this software. If not, see . */ #ifndef _TASK_H_ #define _TASK_H_ #include //Sort of like a single-thread thread pool. //You hand it a worker function and then call finish() to synch with its completion class Task { public: Task(); ~Task(); typedef void * (*TWork)(void *); // initialize task runner void start(void); //execute some work void execute(const TWork &work, void* param); //wait for the work to complete void* finish(); // does the opposite of start void shutdown(); class Impl; Impl *impl; }; #endif desmume/src/utils/AsmJit/core/virtualmemory.cpp000664 001750 001750 00000007171 12755534123 023047 0ustar00sergiosergio000000 000000 // [AsmJit] // Complete JIT Assembler for C++ Language. // // [License] // Zlib - See COPYING file in this package. #define ASMJIT_EXPORTS // [Dependencies - AsmJit] #include "../core/intutil.h" #include "../core/virtualmemory.h" // [Dependencies - Windows] #if defined(ASMJIT_WINDOWS) # include #endif // ASMJIT_WINDOWS // [Dependencies - Posix] #if defined(ASMJIT_POSIX) # include # include # include #endif // ASMJIT_POSIX // [Api-Begin] #include "../core/apibegin.h" namespace AsmJit { // ============================================================================ // [AsmJit::VirtualMemory - Windows] // ============================================================================ #if defined(ASMJIT_WINDOWS) struct VirtualMemoryLocal { VirtualMemoryLocal() { SYSTEM_INFO info; GetSystemInfo(&info); alignment = info.dwAllocationGranularity; pageSize = IntUtil::roundUpToPowerOf2(info.dwPageSize); } size_t alignment; size_t pageSize; }; static VirtualMemoryLocal& vm() { static VirtualMemoryLocal vm; return vm; }; void* VirtualMemory::alloc(size_t length, size_t* allocated, bool canExecute) { return allocProcessMemory(GetCurrentProcess(), length, allocated, canExecute); } void VirtualMemory::free(void* addr, size_t length) { return freeProcessMemory(GetCurrentProcess(), addr, length); } void* VirtualMemory::allocProcessMemory(HANDLE hProcess, size_t length, size_t* allocated, bool canExecute) { // VirtualAlloc rounds allocated size to page size automatically. size_t msize = IntUtil::roundUp(length, vm().pageSize); // Windows XP SP2 / Vista allow Data Excution Prevention (DEP). WORD protect = canExecute ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE; LPVOID mbase = VirtualAllocEx(hProcess, NULL, msize, MEM_COMMIT | MEM_RESERVE, protect); if (mbase == NULL) return NULL; ASMJIT_ASSERT(IntUtil::isAligned(reinterpret_cast(mbase), vm().alignment)); if (allocated != NULL) *allocated = msize; return mbase; } void VirtualMemory::freeProcessMemory(HANDLE hProcess, void* addr, size_t /* length */) { VirtualFreeEx(hProcess, addr, 0, MEM_RELEASE); } size_t VirtualMemory::getAlignment() { return vm().alignment; } size_t VirtualMemory::getPageSize() { return vm().pageSize; } #endif // ASMJIT_WINDOWS // ============================================================================ // [AsmJit::VirtualMemory - Posix] // ============================================================================ #if defined(ASMJIT_POSIX) // MacOS uses MAP_ANON instead of MAP_ANONYMOUS. #if !defined(MAP_ANONYMOUS) # define MAP_ANONYMOUS MAP_ANON #endif // MAP_ANONYMOUS struct VirtualMemoryLocal { VirtualMemoryLocal() { alignment = pageSize = ::getpagesize(); } size_t alignment; size_t pageSize; }; static VirtualMemoryLocal& vm() { static VirtualMemoryLocal vm; return vm; } void* VirtualMemory::alloc(size_t length, size_t* allocated, bool canExecute) { size_t msize = IntUtil::roundUp(length, vm().pageSize); int protection = PROT_READ | PROT_WRITE | (canExecute ? PROT_EXEC : 0); void* mbase = ::mmap(NULL, msize, protection, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); if (mbase == MAP_FAILED) return NULL; if (allocated != NULL) *allocated = msize; return mbase; } void VirtualMemory::free(void* addr, size_t length) { munmap(addr, length); } size_t VirtualMemory::getAlignment() { return vm().alignment; } size_t VirtualMemory::getPageSize() { return vm().pageSize; } #endif // ASMJIT_POSIX } // AsmJit namespace // [Api-End] #include "../core/apiend.h" desmume/src/libretro-common/include/glsym/glsym_es2.h000664 001750 001750 00000143520 12755534123 024107 0ustar00sergiosergio000000 000000 #ifndef RGLGEN_DECL_H__ #define RGLGEN_DECL_H__ #ifdef __cplusplus extern "C" { #endif #ifdef GL_APIENTRY typedef void (GL_APIENTRY *RGLGENGLDEBUGPROC)(GLenum, GLenum, GLuint, GLenum, GLsizei, const GLchar*, GLvoid*); typedef void (GL_APIENTRY *RGLGENGLDEBUGPROCKHR)(GLenum, GLenum, GLuint, GLenum, GLsizei, const GLchar*, GLvoid*); #else #ifndef APIENTRY #define APIENTRY #endif #ifndef APIENTRYP #define APIENTRYP APIENTRY * #endif typedef void (APIENTRY *RGLGENGLDEBUGPROCARB)(GLenum, GLenum, GLuint, GLenum, GLsizei, const GLchar*, GLvoid*); typedef void (APIENTRY *RGLGENGLDEBUGPROC)(GLenum, GLenum, GLuint, GLenum, GLsizei, const GLchar*, GLvoid*); #endif #ifndef GL_OES_EGL_image typedef void *GLeglImageOES; #endif #if !defined(GL_OES_fixed_point) && !defined(HAVE_OPENGLES2) typedef GLint GLfixed; #endif #if defined(OSX) && !defined(MAC_OS_X_VERSION_10_7) typedef long long int GLint64; typedef unsigned long long int GLuint64; typedef unsigned long long int GLuint64EXT; typedef struct __GLsync *GLsync; #endif typedef void (GL_APIENTRYP RGLSYMGLBLENDBARRIERKHRPROC) (void); typedef void (GL_APIENTRYP RGLSYMGLDEBUGMESSAGECONTROLKHRPROC) (GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled); typedef void (GL_APIENTRYP RGLSYMGLDEBUGMESSAGEINSERTKHRPROC) (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *buf); typedef void (GL_APIENTRYP RGLSYMGLDEBUGMESSAGECALLBACKKHRPROC) (RGLGENGLDEBUGPROCKHR callback, const void *userParam); typedef GLuint (GL_APIENTRYP RGLSYMGLGETDEBUGMESSAGELOGKHRPROC) (GLuint count, GLsizei bufSize, GLenum *sources, GLenum *types, GLuint *ids, GLenum *severities, GLsizei *lengths, GLchar *messageLog); typedef void (GL_APIENTRYP RGLSYMGLPUSHDEBUGGROUPKHRPROC) (GLenum source, GLuint id, GLsizei length, const GLchar *message); typedef void (GL_APIENTRYP RGLSYMGLPOPDEBUGGROUPKHRPROC) (void); typedef void (GL_APIENTRYP RGLSYMGLOBJECTLABELKHRPROC) (GLenum identifier, GLuint name, GLsizei length, const GLchar *label); typedef void (GL_APIENTRYP RGLSYMGLGETOBJECTLABELKHRPROC) (GLenum identifier, GLuint name, GLsizei bufSize, GLsizei *length, GLchar *label); typedef void (GL_APIENTRYP RGLSYMGLOBJECTPTRLABELKHRPROC) (const void *ptr, GLsizei length, const GLchar *label); typedef void (GL_APIENTRYP RGLSYMGLGETOBJECTPTRLABELKHRPROC) (const void *ptr, GLsizei bufSize, GLsizei *length, GLchar *label); typedef void (GL_APIENTRYP RGLSYMGLGETPOINTERVKHRPROC) (GLenum pname, void **params); typedef GLenum (GL_APIENTRYP RGLSYMGLGETGRAPHICSRESETSTATUSKHRPROC) (void); typedef void (GL_APIENTRYP RGLSYMGLREADNPIXELSKHRPROC) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void *data); typedef void (GL_APIENTRYP RGLSYMGLGETNUNIFORMFVKHRPROC) (GLuint program, GLint location, GLsizei bufSize, GLfloat *params); typedef void (GL_APIENTRYP RGLSYMGLGETNUNIFORMIVKHRPROC) (GLuint program, GLint location, GLsizei bufSize, GLint *params); typedef void (GL_APIENTRYP RGLSYMGLGETNUNIFORMUIVKHRPROC) (GLuint program, GLint location, GLsizei bufSize, GLuint *params); typedef void (GL_APIENTRYP RGLSYMGLEGLIMAGETARGETTEXTURE2DOESPROC) (GLenum target, GLeglImageOES image); typedef void (GL_APIENTRYP RGLSYMGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC) (GLenum target, GLeglImageOES image); typedef void (GL_APIENTRYP RGLSYMGLCOPYIMAGESUBDATAOESPROC) (GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth); typedef void (GL_APIENTRYP RGLSYMGLENABLEIOESPROC) (GLenum target, GLuint index); typedef void (GL_APIENTRYP RGLSYMGLDISABLEIOESPROC) (GLenum target, GLuint index); typedef void (GL_APIENTRYP RGLSYMGLBLENDEQUATIONIOESPROC) (GLuint buf, GLenum mode); typedef void (GL_APIENTRYP RGLSYMGLBLENDEQUATIONSEPARATEIOESPROC) (GLuint buf, GLenum modeRGB, GLenum modeAlpha); typedef void (GL_APIENTRYP RGLSYMGLBLENDFUNCIOESPROC) (GLuint buf, GLenum src, GLenum dst); typedef void (GL_APIENTRYP RGLSYMGLBLENDFUNCSEPARATEIOESPROC) (GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha); typedef void (GL_APIENTRYP RGLSYMGLCOLORMASKIOESPROC) (GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a); typedef GLboolean (GL_APIENTRYP RGLSYMGLISENABLEDIOESPROC) (GLenum target, GLuint index); typedef void (GL_APIENTRYP RGLSYMGLDRAWELEMENTSBASEVERTEXOESPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLint basevertex); typedef void (GL_APIENTRYP RGLSYMGLDRAWRANGEELEMENTSBASEVERTEXOESPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices, GLint basevertex); typedef void (GL_APIENTRYP RGLSYMGLDRAWELEMENTSINSTANCEDBASEVERTEXOESPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex); typedef void (GL_APIENTRYP RGLSYMGLMULTIDRAWELEMENTSBASEVERTEXOESPROC) (GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei primcount, const GLint *basevertex); typedef void (GL_APIENTRYP RGLSYMGLFRAMEBUFFERTEXTUREOESPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level); typedef void (GL_APIENTRYP RGLSYMGLGETPROGRAMBINARYOESPROC) (GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, void *binary); typedef void (GL_APIENTRYP RGLSYMGLPROGRAMBINARYOESPROC) (GLuint program, GLenum binaryFormat, const void *binary, GLint length); typedef void *(GL_APIENTRYP RGLSYMGLMAPBUFFEROESPROC) (GLenum target, GLenum access); typedef GLboolean (GL_APIENTRYP RGLSYMGLUNMAPBUFFEROESPROC) (GLenum target); typedef void (GL_APIENTRYP RGLSYMGLGETBUFFERPOINTERVOESPROC) (GLenum target, GLenum pname, void **params); typedef void (GL_APIENTRYP RGLSYMGLPRIMITIVEBOUNDINGBOXOESPROC) (GLfloat minX, GLfloat minY, GLfloat minZ, GLfloat minW, GLfloat maxX, GLfloat maxY, GLfloat maxZ, GLfloat maxW); typedef void (GL_APIENTRYP RGLSYMGLMINSAMPLESHADINGOESPROC) (GLfloat value); typedef void (GL_APIENTRYP RGLSYMGLPATCHPARAMETERIOESPROC) (GLenum pname, GLint value); typedef void (GL_APIENTRYP RGLSYMGLTEXIMAGE3DOESPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels); typedef void (GL_APIENTRYP RGLSYMGLTEXSUBIMAGE3DOESPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels); typedef void (GL_APIENTRYP RGLSYMGLCOPYTEXSUBIMAGE3DOESPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); typedef void (GL_APIENTRYP RGLSYMGLCOMPRESSEDTEXIMAGE3DOESPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data); typedef void (GL_APIENTRYP RGLSYMGLCOMPRESSEDTEXSUBIMAGE3DOESPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data); typedef void (GL_APIENTRYP RGLSYMGLFRAMEBUFFERTEXTURE3DOESPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset); typedef void (GL_APIENTRYP RGLSYMGLTEXPARAMETERIIVOESPROC) (GLenum target, GLenum pname, const GLint *params); typedef void (GL_APIENTRYP RGLSYMGLTEXPARAMETERIUIVOESPROC) (GLenum target, GLenum pname, const GLuint *params); typedef void (GL_APIENTRYP RGLSYMGLGETTEXPARAMETERIIVOESPROC) (GLenum target, GLenum pname, GLint *params); typedef void (GL_APIENTRYP RGLSYMGLGETTEXPARAMETERIUIVOESPROC) (GLenum target, GLenum pname, GLuint *params); typedef void (GL_APIENTRYP RGLSYMGLSAMPLERPARAMETERIIVOESPROC) (GLuint sampler, GLenum pname, const GLint *param); typedef void (GL_APIENTRYP RGLSYMGLSAMPLERPARAMETERIUIVOESPROC) (GLuint sampler, GLenum pname, const GLuint *param); typedef void (GL_APIENTRYP RGLSYMGLGETSAMPLERPARAMETERIIVOESPROC) (GLuint sampler, GLenum pname, GLint *params); typedef void (GL_APIENTRYP RGLSYMGLGETSAMPLERPARAMETERIUIVOESPROC) (GLuint sampler, GLenum pname, GLuint *params); typedef void (GL_APIENTRYP RGLSYMGLTEXBUFFEROESPROC) (GLenum target, GLenum internalformat, GLuint buffer); typedef void (GL_APIENTRYP RGLSYMGLTEXBUFFERRANGEOESPROC) (GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size); typedef void (GL_APIENTRYP RGLSYMGLTEXSTORAGE3DMULTISAMPLEOESPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations); typedef void (GL_APIENTRYP RGLSYMGLTEXTUREVIEWOESPROC) (GLuint texture, GLenum target, GLuint origtexture, GLenum internalformat, GLuint minlevel, GLuint numlevels, GLuint minlayer, GLuint numlayers); typedef void (GL_APIENTRYP RGLSYMGLBINDVERTEXARRAYOESPROC) (GLuint array); typedef void (GL_APIENTRYP RGLSYMGLDELETEVERTEXARRAYSOESPROC) (GLsizei n, const GLuint *arrays); typedef void (GL_APIENTRYP RGLSYMGLGENVERTEXARRAYSOESPROC) (GLsizei n, GLuint *arrays); typedef GLboolean (GL_APIENTRYP RGLSYMGLISVERTEXARRAYOESPROC) (GLuint array); typedef void (GL_APIENTRYP RGLSYMGLDRAWARRAYSINSTANCEDBASEINSTANCEEXTPROC) (GLenum mode, GLint first, GLsizei count, GLsizei instancecount, GLuint baseinstance); typedef void (GL_APIENTRYP RGLSYMGLDRAWELEMENTSINSTANCEDBASEINSTANCEEXTPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLuint baseinstance); typedef void (GL_APIENTRYP RGLSYMGLDRAWELEMENTSINSTANCEDBASEVERTEXBASEINSTANCEEXTPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex, GLuint baseinstance); typedef void (GL_APIENTRYP RGLSYMGLBINDFRAGDATALOCATIONINDEXEDEXTPROC) (GLuint program, GLuint colorNumber, GLuint index, const GLchar *name); typedef void (GL_APIENTRYP RGLSYMGLBINDFRAGDATALOCATIONEXTPROC) (GLuint program, GLuint color, const GLchar *name); typedef GLint (GL_APIENTRYP RGLSYMGLGETPROGRAMRESOURCELOCATIONINDEXEXTPROC) (GLuint program, GLenum programInterface, const GLchar *name); typedef GLint (GL_APIENTRYP RGLSYMGLGETFRAGDATAINDEXEXTPROC) (GLuint program, const GLchar *name); typedef void (GL_APIENTRYP RGLSYMGLBUFFERSTORAGEEXTPROC) (GLenum target, GLsizeiptr size, const void *data, GLbitfield flags); typedef void (GL_APIENTRYP RGLSYMGLCOPYIMAGESUBDATAEXTPROC) (GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth); typedef void (GL_APIENTRYP RGLSYMGLLABELOBJECTEXTPROC) (GLenum type, GLuint object, GLsizei length, const GLchar *label); typedef void (GL_APIENTRYP RGLSYMGLGETOBJECTLABELEXTPROC) (GLenum type, GLuint object, GLsizei bufSize, GLsizei *length, GLchar *label); typedef void (GL_APIENTRYP RGLSYMGLINSERTEVENTMARKEREXTPROC) (GLsizei length, const GLchar *marker); typedef void (GL_APIENTRYP RGLSYMGLPUSHGROUPMARKEREXTPROC) (GLsizei length, const GLchar *marker); typedef void (GL_APIENTRYP RGLSYMGLPOPGROUPMARKEREXTPROC) (void); typedef void (GL_APIENTRYP RGLSYMGLDISCARDFRAMEBUFFEREXTPROC) (GLenum target, GLsizei numAttachments, const GLenum *attachments); typedef void (GL_APIENTRYP RGLSYMGLGENQUERIESEXTPROC) (GLsizei n, GLuint *ids); typedef void (GL_APIENTRYP RGLSYMGLDELETEQUERIESEXTPROC) (GLsizei n, const GLuint *ids); typedef GLboolean (GL_APIENTRYP RGLSYMGLISQUERYEXTPROC) (GLuint id); typedef void (GL_APIENTRYP RGLSYMGLBEGINQUERYEXTPROC) (GLenum target, GLuint id); typedef void (GL_APIENTRYP RGLSYMGLENDQUERYEXTPROC) (GLenum target); typedef void (GL_APIENTRYP RGLSYMGLQUERYCOUNTEREXTPROC) (GLuint id, GLenum target); typedef void (GL_APIENTRYP RGLSYMGLGETQUERYIVEXTPROC) (GLenum target, GLenum pname, GLint *params); typedef void (GL_APIENTRYP RGLSYMGLGETQUERYOBJECTIVEXTPROC) (GLuint id, GLenum pname, GLint *params); typedef void (GL_APIENTRYP RGLSYMGLGETQUERYOBJECTUIVEXTPROC) (GLuint id, GLenum pname, GLuint *params); typedef void (GL_APIENTRYP RGLSYMGLDRAWBUFFERSEXTPROC) (GLsizei n, const GLenum *bufs); typedef void (GL_APIENTRYP RGLSYMGLENABLEIEXTPROC) (GLenum target, GLuint index); typedef void (GL_APIENTRYP RGLSYMGLDISABLEIEXTPROC) (GLenum target, GLuint index); typedef void (GL_APIENTRYP RGLSYMGLBLENDEQUATIONIEXTPROC) (GLuint buf, GLenum mode); typedef void (GL_APIENTRYP RGLSYMGLBLENDEQUATIONSEPARATEIEXTPROC) (GLuint buf, GLenum modeRGB, GLenum modeAlpha); typedef void (GL_APIENTRYP RGLSYMGLBLENDFUNCIEXTPROC) (GLuint buf, GLenum src, GLenum dst); typedef void (GL_APIENTRYP RGLSYMGLBLENDFUNCSEPARATEIEXTPROC) (GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha); typedef void (GL_APIENTRYP RGLSYMGLCOLORMASKIEXTPROC) (GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a); typedef GLboolean (GL_APIENTRYP RGLSYMGLISENABLEDIEXTPROC) (GLenum target, GLuint index); typedef void (GL_APIENTRYP RGLSYMGLDRAWELEMENTSBASEVERTEXEXTPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLint basevertex); typedef void (GL_APIENTRYP RGLSYMGLDRAWRANGEELEMENTSBASEVERTEXEXTPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices, GLint basevertex); typedef void (GL_APIENTRYP RGLSYMGLDRAWELEMENTSINSTANCEDBASEVERTEXEXTPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex); typedef void (GL_APIENTRYP RGLSYMGLMULTIDRAWELEMENTSBASEVERTEXEXTPROC) (GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei primcount, const GLint *basevertex); typedef void (GL_APIENTRYP RGLSYMGLDRAWARRAYSINSTANCEDEXTPROC) (GLenum mode, GLint start, GLsizei count, GLsizei primcount); typedef void (GL_APIENTRYP RGLSYMGLDRAWELEMENTSINSTANCEDEXTPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount); typedef void (GL_APIENTRYP RGLSYMGLFRAMEBUFFERTEXTUREEXTPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level); typedef void (GL_APIENTRYP RGLSYMGLVERTEXATTRIBDIVISOREXTPROC) (GLuint index, GLuint divisor); typedef void *(GL_APIENTRYP RGLSYMGLMAPBUFFERRANGEEXTPROC) (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access); typedef void (GL_APIENTRYP RGLSYMGLFLUSHMAPPEDBUFFERRANGEEXTPROC) (GLenum target, GLintptr offset, GLsizeiptr length); typedef void (GL_APIENTRYP RGLSYMGLMULTIDRAWARRAYSEXTPROC) (GLenum mode, const GLint *first, const GLsizei *count, GLsizei primcount); typedef void (GL_APIENTRYP RGLSYMGLMULTIDRAWELEMENTSEXTPROC) (GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei primcount); typedef void (GL_APIENTRYP RGLSYMGLMULTIDRAWARRAYSINDIRECTEXTPROC) (GLenum mode, const void *indirect, GLsizei drawcount, GLsizei stride); typedef void (GL_APIENTRYP RGLSYMGLMULTIDRAWELEMENTSINDIRECTEXTPROC) (GLenum mode, GLenum type, const void *indirect, GLsizei drawcount, GLsizei stride); typedef void (GL_APIENTRYP RGLSYMGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); typedef void (GL_APIENTRYP RGLSYMGLFRAMEBUFFERTEXTURE2DMULTISAMPLEEXTPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLsizei samples); typedef void (GL_APIENTRYP RGLSYMGLREADBUFFERINDEXEDEXTPROC) (GLenum src, GLint index); typedef void (GL_APIENTRYP RGLSYMGLDRAWBUFFERSINDEXEDEXTPROC) (GLint n, const GLenum *location, const GLint *indices); typedef void (GL_APIENTRYP RGLSYMGLGETINTEGERI_VEXTPROC) (GLenum target, GLuint index, GLint *data); typedef void (GL_APIENTRYP RGLSYMGLPRIMITIVEBOUNDINGBOXEXTPROC) (GLfloat minX, GLfloat minY, GLfloat minZ, GLfloat minW, GLfloat maxX, GLfloat maxY, GLfloat maxZ, GLfloat maxW); typedef void (GL_APIENTRYP RGLSYMGLRASTERSAMPLESEXTPROC) (GLuint samples, GLboolean fixedsamplelocations); typedef GLenum (GL_APIENTRYP RGLSYMGLGETGRAPHICSRESETSTATUSEXTPROC) (void); typedef void (GL_APIENTRYP RGLSYMGLREADNPIXELSEXTPROC) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void *data); typedef void (GL_APIENTRYP RGLSYMGLGETNUNIFORMFVEXTPROC) (GLuint program, GLint location, GLsizei bufSize, GLfloat *params); typedef void (GL_APIENTRYP RGLSYMGLGETNUNIFORMIVEXTPROC) (GLuint program, GLint location, GLsizei bufSize, GLint *params); typedef void (GL_APIENTRYP RGLSYMGLACTIVESHADERPROGRAMEXTPROC) (GLuint pipeline, GLuint program); typedef void (GL_APIENTRYP RGLSYMGLBINDPROGRAMPIPELINEEXTPROC) (GLuint pipeline); typedef GLuint (GL_APIENTRYP RGLSYMGLCREATESHADERPROGRAMVEXTPROC) (GLenum type, GLsizei count, const GLchar **strings); typedef void (GL_APIENTRYP RGLSYMGLDELETEPROGRAMPIPELINESEXTPROC) (GLsizei n, const GLuint *pipelines); typedef void (GL_APIENTRYP RGLSYMGLGENPROGRAMPIPELINESEXTPROC) (GLsizei n, GLuint *pipelines); typedef void (GL_APIENTRYP RGLSYMGLGETPROGRAMPIPELINEINFOLOGEXTPROC) (GLuint pipeline, GLsizei bufSize, GLsizei *length, GLchar *infoLog); typedef void (GL_APIENTRYP RGLSYMGLGETPROGRAMPIPELINEIVEXTPROC) (GLuint pipeline, GLenum pname, GLint *params); typedef GLboolean (GL_APIENTRYP RGLSYMGLISPROGRAMPIPELINEEXTPROC) (GLuint pipeline); typedef void (GL_APIENTRYP RGLSYMGLPROGRAMPARAMETERIEXTPROC) (GLuint program, GLenum pname, GLint value); typedef void (GL_APIENTRYP RGLSYMGLPROGRAMUNIFORM1FEXTPROC) (GLuint program, GLint location, GLfloat v0); typedef void (GL_APIENTRYP RGLSYMGLPROGRAMUNIFORM1FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value); typedef void (GL_APIENTRYP RGLSYMGLPROGRAMUNIFORM1IEXTPROC) (GLuint program, GLint location, GLint v0); typedef void (GL_APIENTRYP RGLSYMGLPROGRAMUNIFORM1IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint *value); typedef void (GL_APIENTRYP RGLSYMGLPROGRAMUNIFORM2FEXTPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1); typedef void (GL_APIENTRYP RGLSYMGLPROGRAMUNIFORM2FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value); typedef void (GL_APIENTRYP RGLSYMGLPROGRAMUNIFORM2IEXTPROC) (GLuint program, GLint location, GLint v0, GLint v1); typedef void (GL_APIENTRYP RGLSYMGLPROGRAMUNIFORM2IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint *value); typedef void (GL_APIENTRYP RGLSYMGLPROGRAMUNIFORM3FEXTPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2); typedef void (GL_APIENTRYP RGLSYMGLPROGRAMUNIFORM3FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value); typedef void (GL_APIENTRYP RGLSYMGLPROGRAMUNIFORM3IEXTPROC) (GLuint program, GLint location, GLint v0, GLint v1, GLint v2); typedef void (GL_APIENTRYP RGLSYMGLPROGRAMUNIFORM3IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint *value); typedef void (GL_APIENTRYP RGLSYMGLPROGRAMUNIFORM4FEXTPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); typedef void (GL_APIENTRYP RGLSYMGLPROGRAMUNIFORM4FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value); typedef void (GL_APIENTRYP RGLSYMGLPROGRAMUNIFORM4IEXTPROC) (GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3); typedef void (GL_APIENTRYP RGLSYMGLPROGRAMUNIFORM4IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint *value); typedef void (GL_APIENTRYP RGLSYMGLPROGRAMUNIFORMMATRIX2FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); typedef void (GL_APIENTRYP RGLSYMGLPROGRAMUNIFORMMATRIX3FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); typedef void (GL_APIENTRYP RGLSYMGLPROGRAMUNIFORMMATRIX4FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); typedef void (GL_APIENTRYP RGLSYMGLUSEPROGRAMSTAGESEXTPROC) (GLuint pipeline, GLbitfield stages, GLuint program); typedef void (GL_APIENTRYP RGLSYMGLVALIDATEPROGRAMPIPELINEEXTPROC) (GLuint pipeline); typedef void (GL_APIENTRYP RGLSYMGLPROGRAMUNIFORM1UIEXTPROC) (GLuint program, GLint location, GLuint v0); typedef void (GL_APIENTRYP RGLSYMGLPROGRAMUNIFORM2UIEXTPROC) (GLuint program, GLint location, GLuint v0, GLuint v1); typedef void (GL_APIENTRYP RGLSYMGLPROGRAMUNIFORM3UIEXTPROC) (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2); typedef void (GL_APIENTRYP RGLSYMGLPROGRAMUNIFORM4UIEXTPROC) (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3); typedef void (GL_APIENTRYP RGLSYMGLPROGRAMUNIFORM1UIVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value); typedef void (GL_APIENTRYP RGLSYMGLPROGRAMUNIFORM2UIVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value); typedef void (GL_APIENTRYP RGLSYMGLPROGRAMUNIFORM3UIVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value); typedef void (GL_APIENTRYP RGLSYMGLPROGRAMUNIFORM4UIVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value); typedef void (GL_APIENTRYP RGLSYMGLPROGRAMUNIFORMMATRIX2X3FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); typedef void (GL_APIENTRYP RGLSYMGLPROGRAMUNIFORMMATRIX3X2FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); typedef void (GL_APIENTRYP RGLSYMGLPROGRAMUNIFORMMATRIX2X4FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); typedef void (GL_APIENTRYP RGLSYMGLPROGRAMUNIFORMMATRIX4X2FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); typedef void (GL_APIENTRYP RGLSYMGLPROGRAMUNIFORMMATRIX3X4FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); typedef void (GL_APIENTRYP RGLSYMGLPROGRAMUNIFORMMATRIX4X3FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); typedef void (GL_APIENTRYP RGLSYMGLTEXPAGECOMMITMENTEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLboolean commit); typedef void (GL_APIENTRYP RGLSYMGLPATCHPARAMETERIEXTPROC) (GLenum pname, GLint value); typedef void (GL_APIENTRYP RGLSYMGLTEXPARAMETERIIVEXTPROC) (GLenum target, GLenum pname, const GLint *params); typedef void (GL_APIENTRYP RGLSYMGLTEXPARAMETERIUIVEXTPROC) (GLenum target, GLenum pname, const GLuint *params); typedef void (GL_APIENTRYP RGLSYMGLGETTEXPARAMETERIIVEXTPROC) (GLenum target, GLenum pname, GLint *params); typedef void (GL_APIENTRYP RGLSYMGLGETTEXPARAMETERIUIVEXTPROC) (GLenum target, GLenum pname, GLuint *params); typedef void (GL_APIENTRYP RGLSYMGLSAMPLERPARAMETERIIVEXTPROC) (GLuint sampler, GLenum pname, const GLint *param); typedef void (GL_APIENTRYP RGLSYMGLSAMPLERPARAMETERIUIVEXTPROC) (GLuint sampler, GLenum pname, const GLuint *param); typedef void (GL_APIENTRYP RGLSYMGLGETSAMPLERPARAMETERIIVEXTPROC) (GLuint sampler, GLenum pname, GLint *params); typedef void (GL_APIENTRYP RGLSYMGLGETSAMPLERPARAMETERIUIVEXTPROC) (GLuint sampler, GLenum pname, GLuint *params); typedef void (GL_APIENTRYP RGLSYMGLTEXBUFFEREXTPROC) (GLenum target, GLenum internalformat, GLuint buffer); typedef void (GL_APIENTRYP RGLSYMGLTEXBUFFERRANGEEXTPROC) (GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size); typedef void (GL_APIENTRYP RGLSYMGLTEXSTORAGE1DEXTPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width); typedef void (GL_APIENTRYP RGLSYMGLTEXSTORAGE2DEXTPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height); typedef void (GL_APIENTRYP RGLSYMGLTEXSTORAGE3DEXTPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); typedef void (GL_APIENTRYP RGLSYMGLTEXTURESTORAGE1DEXTPROC) (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width); typedef void (GL_APIENTRYP RGLSYMGLTEXTURESTORAGE2DEXTPROC) (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height); typedef void (GL_APIENTRYP RGLSYMGLTEXTURESTORAGE3DEXTPROC) (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); typedef void (GL_APIENTRYP RGLSYMGLTEXTUREVIEWEXTPROC) (GLuint texture, GLenum target, GLuint origtexture, GLenum internalformat, GLuint minlevel, GLuint numlevels, GLuint minlayer, GLuint numlayers); typedef void (GL_APIENTRYP RGLSYMGLFRAMEBUFFERTEXTUREMULTIVIEWOVRPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint baseViewIndex, GLsizei numViews); typedef void (GL_APIENTRYP RGLSYMGLFRAMEBUFFERTEXTUREMULTISAMPLEMULTIVIEWOVRPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLsizei samples, GLint baseViewIndex, GLsizei numViews); #define glBlendBarrierKHR __rglgen_glBlendBarrierKHR #define glDebugMessageControlKHR __rglgen_glDebugMessageControlKHR #define glDebugMessageInsertKHR __rglgen_glDebugMessageInsertKHR #define glDebugMessageCallbackKHR __rglgen_glDebugMessageCallbackKHR #define glGetDebugMessageLogKHR __rglgen_glGetDebugMessageLogKHR #define glPushDebugGroupKHR __rglgen_glPushDebugGroupKHR #define glPopDebugGroupKHR __rglgen_glPopDebugGroupKHR #define glObjectLabelKHR __rglgen_glObjectLabelKHR #define glGetObjectLabelKHR __rglgen_glGetObjectLabelKHR #define glObjectPtrLabelKHR __rglgen_glObjectPtrLabelKHR #define glGetObjectPtrLabelKHR __rglgen_glGetObjectPtrLabelKHR #define glGetPointervKHR __rglgen_glGetPointervKHR #define glGetGraphicsResetStatusKHR __rglgen_glGetGraphicsResetStatusKHR #define glReadnPixelsKHR __rglgen_glReadnPixelsKHR #define glGetnUniformfvKHR __rglgen_glGetnUniformfvKHR #define glGetnUniformivKHR __rglgen_glGetnUniformivKHR #define glGetnUniformuivKHR __rglgen_glGetnUniformuivKHR #define glEGLImageTargetTexture2DOES __rglgen_glEGLImageTargetTexture2DOES #define glEGLImageTargetRenderbufferStorageOES __rglgen_glEGLImageTargetRenderbufferStorageOES #define glCopyImageSubDataOES __rglgen_glCopyImageSubDataOES #define glEnableiOES __rglgen_glEnableiOES #define glDisableiOES __rglgen_glDisableiOES #define glBlendEquationiOES __rglgen_glBlendEquationiOES #define glBlendEquationSeparateiOES __rglgen_glBlendEquationSeparateiOES #define glBlendFunciOES __rglgen_glBlendFunciOES #define glBlendFuncSeparateiOES __rglgen_glBlendFuncSeparateiOES #define glColorMaskiOES __rglgen_glColorMaskiOES #define glIsEnablediOES __rglgen_glIsEnablediOES #define glDrawElementsBaseVertexOES __rglgen_glDrawElementsBaseVertexOES #define glDrawRangeElementsBaseVertexOES __rglgen_glDrawRangeElementsBaseVertexOES #define glDrawElementsInstancedBaseVertexOES __rglgen_glDrawElementsInstancedBaseVertexOES #define glMultiDrawElementsBaseVertexOES __rglgen_glMultiDrawElementsBaseVertexOES #define glFramebufferTextureOES __rglgen_glFramebufferTextureOES #define glGetProgramBinaryOES __rglgen_glGetProgramBinaryOES #define glProgramBinaryOES __rglgen_glProgramBinaryOES #define glMapBufferOES __rglgen_glMapBufferOES #define glUnmapBufferOES __rglgen_glUnmapBufferOES #define glGetBufferPointervOES __rglgen_glGetBufferPointervOES #define glPrimitiveBoundingBoxOES __rglgen_glPrimitiveBoundingBoxOES #define glMinSampleShadingOES __rglgen_glMinSampleShadingOES #define glPatchParameteriOES __rglgen_glPatchParameteriOES #define glTexImage3DOES __rglgen_glTexImage3DOES #define glTexSubImage3DOES __rglgen_glTexSubImage3DOES #define glCopyTexSubImage3DOES __rglgen_glCopyTexSubImage3DOES #define glCompressedTexImage3DOES __rglgen_glCompressedTexImage3DOES #define glCompressedTexSubImage3DOES __rglgen_glCompressedTexSubImage3DOES #define glFramebufferTexture3DOES __rglgen_glFramebufferTexture3DOES #define glTexParameterIivOES __rglgen_glTexParameterIivOES #define glTexParameterIuivOES __rglgen_glTexParameterIuivOES #define glGetTexParameterIivOES __rglgen_glGetTexParameterIivOES #define glGetTexParameterIuivOES __rglgen_glGetTexParameterIuivOES #define glSamplerParameterIivOES __rglgen_glSamplerParameterIivOES #define glSamplerParameterIuivOES __rglgen_glSamplerParameterIuivOES #define glGetSamplerParameterIivOES __rglgen_glGetSamplerParameterIivOES #define glGetSamplerParameterIuivOES __rglgen_glGetSamplerParameterIuivOES #define glTexBufferOES __rglgen_glTexBufferOES #define glTexBufferRangeOES __rglgen_glTexBufferRangeOES #define glTexStorage3DMultisampleOES __rglgen_glTexStorage3DMultisampleOES #define glTextureViewOES __rglgen_glTextureViewOES #define glBindVertexArrayOES __rglgen_glBindVertexArrayOES #define glDeleteVertexArraysOES __rglgen_glDeleteVertexArraysOES #define glGenVertexArraysOES __rglgen_glGenVertexArraysOES #define glIsVertexArrayOES __rglgen_glIsVertexArrayOES #define glDrawArraysInstancedBaseInstanceEXT __rglgen_glDrawArraysInstancedBaseInstanceEXT #define glDrawElementsInstancedBaseInstanceEXT __rglgen_glDrawElementsInstancedBaseInstanceEXT #define glDrawElementsInstancedBaseVertexBaseInstanceEXT __rglgen_glDrawElementsInstancedBaseVertexBaseInstanceEXT #define glBindFragDataLocationIndexedEXT __rglgen_glBindFragDataLocationIndexedEXT #define glBindFragDataLocationEXT __rglgen_glBindFragDataLocationEXT #define glGetProgramResourceLocationIndexEXT __rglgen_glGetProgramResourceLocationIndexEXT #define glGetFragDataIndexEXT __rglgen_glGetFragDataIndexEXT #define glBufferStorageEXT __rglgen_glBufferStorageEXT #define glCopyImageSubDataEXT __rglgen_glCopyImageSubDataEXT #define glLabelObjectEXT __rglgen_glLabelObjectEXT #define glGetObjectLabelEXT __rglgen_glGetObjectLabelEXT #define glInsertEventMarkerEXT __rglgen_glInsertEventMarkerEXT #define glPushGroupMarkerEXT __rglgen_glPushGroupMarkerEXT #define glPopGroupMarkerEXT __rglgen_glPopGroupMarkerEXT #define glDiscardFramebufferEXT __rglgen_glDiscardFramebufferEXT #define glGenQueriesEXT __rglgen_glGenQueriesEXT #define glDeleteQueriesEXT __rglgen_glDeleteQueriesEXT #define glIsQueryEXT __rglgen_glIsQueryEXT #define glBeginQueryEXT __rglgen_glBeginQueryEXT #define glEndQueryEXT __rglgen_glEndQueryEXT #define glQueryCounterEXT __rglgen_glQueryCounterEXT #define glGetQueryivEXT __rglgen_glGetQueryivEXT #define glGetQueryObjectivEXT __rglgen_glGetQueryObjectivEXT #define glGetQueryObjectuivEXT __rglgen_glGetQueryObjectuivEXT #define glDrawBuffersEXT __rglgen_glDrawBuffersEXT #define glEnableiEXT __rglgen_glEnableiEXT #define glDisableiEXT __rglgen_glDisableiEXT #define glBlendEquationiEXT __rglgen_glBlendEquationiEXT #define glBlendEquationSeparateiEXT __rglgen_glBlendEquationSeparateiEXT #define glBlendFunciEXT __rglgen_glBlendFunciEXT #define glBlendFuncSeparateiEXT __rglgen_glBlendFuncSeparateiEXT #define glColorMaskiEXT __rglgen_glColorMaskiEXT #define glIsEnablediEXT __rglgen_glIsEnablediEXT #define glDrawElementsBaseVertexEXT __rglgen_glDrawElementsBaseVertexEXT #define glDrawRangeElementsBaseVertexEXT __rglgen_glDrawRangeElementsBaseVertexEXT #define glDrawElementsInstancedBaseVertexEXT __rglgen_glDrawElementsInstancedBaseVertexEXT #define glMultiDrawElementsBaseVertexEXT __rglgen_glMultiDrawElementsBaseVertexEXT #define glDrawArraysInstancedEXT __rglgen_glDrawArraysInstancedEXT #define glDrawElementsInstancedEXT __rglgen_glDrawElementsInstancedEXT #define glFramebufferTextureEXT __rglgen_glFramebufferTextureEXT #define glVertexAttribDivisorEXT __rglgen_glVertexAttribDivisorEXT #define glMapBufferRangeEXT __rglgen_glMapBufferRangeEXT #define glFlushMappedBufferRangeEXT __rglgen_glFlushMappedBufferRangeEXT #define glMultiDrawArraysEXT __rglgen_glMultiDrawArraysEXT #define glMultiDrawElementsEXT __rglgen_glMultiDrawElementsEXT #define glMultiDrawArraysIndirectEXT __rglgen_glMultiDrawArraysIndirectEXT #define glMultiDrawElementsIndirectEXT __rglgen_glMultiDrawElementsIndirectEXT #define glRenderbufferStorageMultisampleEXT __rglgen_glRenderbufferStorageMultisampleEXT #define glFramebufferTexture2DMultisampleEXT __rglgen_glFramebufferTexture2DMultisampleEXT #define glReadBufferIndexedEXT __rglgen_glReadBufferIndexedEXT #define glDrawBuffersIndexedEXT __rglgen_glDrawBuffersIndexedEXT #define glGetIntegeri_vEXT __rglgen_glGetIntegeri_vEXT #define glPrimitiveBoundingBoxEXT __rglgen_glPrimitiveBoundingBoxEXT #define glRasterSamplesEXT __rglgen_glRasterSamplesEXT #define glGetGraphicsResetStatusEXT __rglgen_glGetGraphicsResetStatusEXT #define glReadnPixelsEXT __rglgen_glReadnPixelsEXT #define glGetnUniformfvEXT __rglgen_glGetnUniformfvEXT #define glGetnUniformivEXT __rglgen_glGetnUniformivEXT #define glActiveShaderProgramEXT __rglgen_glActiveShaderProgramEXT #define glBindProgramPipelineEXT __rglgen_glBindProgramPipelineEXT #define glCreateShaderProgramvEXT __rglgen_glCreateShaderProgramvEXT #define glDeleteProgramPipelinesEXT __rglgen_glDeleteProgramPipelinesEXT #define glGenProgramPipelinesEXT __rglgen_glGenProgramPipelinesEXT #define glGetProgramPipelineInfoLogEXT __rglgen_glGetProgramPipelineInfoLogEXT #define glGetProgramPipelineivEXT __rglgen_glGetProgramPipelineivEXT #define glIsProgramPipelineEXT __rglgen_glIsProgramPipelineEXT #define glProgramParameteriEXT __rglgen_glProgramParameteriEXT #define glProgramUniform1fEXT __rglgen_glProgramUniform1fEXT #define glProgramUniform1fvEXT __rglgen_glProgramUniform1fvEXT #define glProgramUniform1iEXT __rglgen_glProgramUniform1iEXT #define glProgramUniform1ivEXT __rglgen_glProgramUniform1ivEXT #define glProgramUniform2fEXT __rglgen_glProgramUniform2fEXT #define glProgramUniform2fvEXT __rglgen_glProgramUniform2fvEXT #define glProgramUniform2iEXT __rglgen_glProgramUniform2iEXT #define glProgramUniform2ivEXT __rglgen_glProgramUniform2ivEXT #define glProgramUniform3fEXT __rglgen_glProgramUniform3fEXT #define glProgramUniform3fvEXT __rglgen_glProgramUniform3fvEXT #define glProgramUniform3iEXT __rglgen_glProgramUniform3iEXT #define glProgramUniform3ivEXT __rglgen_glProgramUniform3ivEXT #define glProgramUniform4fEXT __rglgen_glProgramUniform4fEXT #define glProgramUniform4fvEXT __rglgen_glProgramUniform4fvEXT #define glProgramUniform4iEXT __rglgen_glProgramUniform4iEXT #define glProgramUniform4ivEXT __rglgen_glProgramUniform4ivEXT #define glProgramUniformMatrix2fvEXT __rglgen_glProgramUniformMatrix2fvEXT #define glProgramUniformMatrix3fvEXT __rglgen_glProgramUniformMatrix3fvEXT #define glProgramUniformMatrix4fvEXT __rglgen_glProgramUniformMatrix4fvEXT #define glUseProgramStagesEXT __rglgen_glUseProgramStagesEXT #define glValidateProgramPipelineEXT __rglgen_glValidateProgramPipelineEXT #define glProgramUniform1uiEXT __rglgen_glProgramUniform1uiEXT #define glProgramUniform2uiEXT __rglgen_glProgramUniform2uiEXT #define glProgramUniform3uiEXT __rglgen_glProgramUniform3uiEXT #define glProgramUniform4uiEXT __rglgen_glProgramUniform4uiEXT #define glProgramUniform1uivEXT __rglgen_glProgramUniform1uivEXT #define glProgramUniform2uivEXT __rglgen_glProgramUniform2uivEXT #define glProgramUniform3uivEXT __rglgen_glProgramUniform3uivEXT #define glProgramUniform4uivEXT __rglgen_glProgramUniform4uivEXT #define glProgramUniformMatrix2x3fvEXT __rglgen_glProgramUniformMatrix2x3fvEXT #define glProgramUniformMatrix3x2fvEXT __rglgen_glProgramUniformMatrix3x2fvEXT #define glProgramUniformMatrix2x4fvEXT __rglgen_glProgramUniformMatrix2x4fvEXT #define glProgramUniformMatrix4x2fvEXT __rglgen_glProgramUniformMatrix4x2fvEXT #define glProgramUniformMatrix3x4fvEXT __rglgen_glProgramUniformMatrix3x4fvEXT #define glProgramUniformMatrix4x3fvEXT __rglgen_glProgramUniformMatrix4x3fvEXT #define glTexPageCommitmentEXT __rglgen_glTexPageCommitmentEXT #define glPatchParameteriEXT __rglgen_glPatchParameteriEXT #define glTexParameterIivEXT __rglgen_glTexParameterIivEXT #define glTexParameterIuivEXT __rglgen_glTexParameterIuivEXT #define glGetTexParameterIivEXT __rglgen_glGetTexParameterIivEXT #define glGetTexParameterIuivEXT __rglgen_glGetTexParameterIuivEXT #define glSamplerParameterIivEXT __rglgen_glSamplerParameterIivEXT #define glSamplerParameterIuivEXT __rglgen_glSamplerParameterIuivEXT #define glGetSamplerParameterIivEXT __rglgen_glGetSamplerParameterIivEXT #define glGetSamplerParameterIuivEXT __rglgen_glGetSamplerParameterIuivEXT #define glTexBufferEXT __rglgen_glTexBufferEXT #define glTexBufferRangeEXT __rglgen_glTexBufferRangeEXT #define glTexStorage1DEXT __rglgen_glTexStorage1DEXT #define glTexStorage2DEXT __rglgen_glTexStorage2DEXT #define glTexStorage3DEXT __rglgen_glTexStorage3DEXT #define glTextureStorage1DEXT __rglgen_glTextureStorage1DEXT #define glTextureStorage2DEXT __rglgen_glTextureStorage2DEXT #define glTextureStorage3DEXT __rglgen_glTextureStorage3DEXT #define glTextureViewEXT __rglgen_glTextureViewEXT #define glFramebufferTextureMultiviewOVR __rglgen_glFramebufferTextureMultiviewOVR #define glFramebufferTextureMultisampleMultiviewOVR __rglgen_glFramebufferTextureMultisampleMultiviewOVR extern RGLSYMGLBLENDBARRIERKHRPROC __rglgen_glBlendBarrierKHR; extern RGLSYMGLDEBUGMESSAGECONTROLKHRPROC __rglgen_glDebugMessageControlKHR; extern RGLSYMGLDEBUGMESSAGEINSERTKHRPROC __rglgen_glDebugMessageInsertKHR; extern RGLSYMGLDEBUGMESSAGECALLBACKKHRPROC __rglgen_glDebugMessageCallbackKHR; extern RGLSYMGLGETDEBUGMESSAGELOGKHRPROC __rglgen_glGetDebugMessageLogKHR; extern RGLSYMGLPUSHDEBUGGROUPKHRPROC __rglgen_glPushDebugGroupKHR; extern RGLSYMGLPOPDEBUGGROUPKHRPROC __rglgen_glPopDebugGroupKHR; extern RGLSYMGLOBJECTLABELKHRPROC __rglgen_glObjectLabelKHR; extern RGLSYMGLGETOBJECTLABELKHRPROC __rglgen_glGetObjectLabelKHR; extern RGLSYMGLOBJECTPTRLABELKHRPROC __rglgen_glObjectPtrLabelKHR; extern RGLSYMGLGETOBJECTPTRLABELKHRPROC __rglgen_glGetObjectPtrLabelKHR; extern RGLSYMGLGETPOINTERVKHRPROC __rglgen_glGetPointervKHR; extern RGLSYMGLGETGRAPHICSRESETSTATUSKHRPROC __rglgen_glGetGraphicsResetStatusKHR; extern RGLSYMGLREADNPIXELSKHRPROC __rglgen_glReadnPixelsKHR; extern RGLSYMGLGETNUNIFORMFVKHRPROC __rglgen_glGetnUniformfvKHR; extern RGLSYMGLGETNUNIFORMIVKHRPROC __rglgen_glGetnUniformivKHR; extern RGLSYMGLGETNUNIFORMUIVKHRPROC __rglgen_glGetnUniformuivKHR; extern RGLSYMGLEGLIMAGETARGETTEXTURE2DOESPROC __rglgen_glEGLImageTargetTexture2DOES; extern RGLSYMGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC __rglgen_glEGLImageTargetRenderbufferStorageOES; extern RGLSYMGLCOPYIMAGESUBDATAOESPROC __rglgen_glCopyImageSubDataOES; extern RGLSYMGLENABLEIOESPROC __rglgen_glEnableiOES; extern RGLSYMGLDISABLEIOESPROC __rglgen_glDisableiOES; extern RGLSYMGLBLENDEQUATIONIOESPROC __rglgen_glBlendEquationiOES; extern RGLSYMGLBLENDEQUATIONSEPARATEIOESPROC __rglgen_glBlendEquationSeparateiOES; extern RGLSYMGLBLENDFUNCIOESPROC __rglgen_glBlendFunciOES; extern RGLSYMGLBLENDFUNCSEPARATEIOESPROC __rglgen_glBlendFuncSeparateiOES; extern RGLSYMGLCOLORMASKIOESPROC __rglgen_glColorMaskiOES; extern RGLSYMGLISENABLEDIOESPROC __rglgen_glIsEnablediOES; extern RGLSYMGLDRAWELEMENTSBASEVERTEXOESPROC __rglgen_glDrawElementsBaseVertexOES; extern RGLSYMGLDRAWRANGEELEMENTSBASEVERTEXOESPROC __rglgen_glDrawRangeElementsBaseVertexOES; extern RGLSYMGLDRAWELEMENTSINSTANCEDBASEVERTEXOESPROC __rglgen_glDrawElementsInstancedBaseVertexOES; extern RGLSYMGLMULTIDRAWELEMENTSBASEVERTEXOESPROC __rglgen_glMultiDrawElementsBaseVertexOES; extern RGLSYMGLFRAMEBUFFERTEXTUREOESPROC __rglgen_glFramebufferTextureOES; extern RGLSYMGLGETPROGRAMBINARYOESPROC __rglgen_glGetProgramBinaryOES; extern RGLSYMGLPROGRAMBINARYOESPROC __rglgen_glProgramBinaryOES; extern RGLSYMGLMAPBUFFEROESPROC __rglgen_glMapBufferOES; extern RGLSYMGLUNMAPBUFFEROESPROC __rglgen_glUnmapBufferOES; extern RGLSYMGLGETBUFFERPOINTERVOESPROC __rglgen_glGetBufferPointervOES; extern RGLSYMGLPRIMITIVEBOUNDINGBOXOESPROC __rglgen_glPrimitiveBoundingBoxOES; extern RGLSYMGLMINSAMPLESHADINGOESPROC __rglgen_glMinSampleShadingOES; extern RGLSYMGLPATCHPARAMETERIOESPROC __rglgen_glPatchParameteriOES; extern RGLSYMGLTEXIMAGE3DOESPROC __rglgen_glTexImage3DOES; extern RGLSYMGLTEXSUBIMAGE3DOESPROC __rglgen_glTexSubImage3DOES; extern RGLSYMGLCOPYTEXSUBIMAGE3DOESPROC __rglgen_glCopyTexSubImage3DOES; extern RGLSYMGLCOMPRESSEDTEXIMAGE3DOESPROC __rglgen_glCompressedTexImage3DOES; extern RGLSYMGLCOMPRESSEDTEXSUBIMAGE3DOESPROC __rglgen_glCompressedTexSubImage3DOES; extern RGLSYMGLFRAMEBUFFERTEXTURE3DOESPROC __rglgen_glFramebufferTexture3DOES; extern RGLSYMGLTEXPARAMETERIIVOESPROC __rglgen_glTexParameterIivOES; extern RGLSYMGLTEXPARAMETERIUIVOESPROC __rglgen_glTexParameterIuivOES; extern RGLSYMGLGETTEXPARAMETERIIVOESPROC __rglgen_glGetTexParameterIivOES; extern RGLSYMGLGETTEXPARAMETERIUIVOESPROC __rglgen_glGetTexParameterIuivOES; extern RGLSYMGLSAMPLERPARAMETERIIVOESPROC __rglgen_glSamplerParameterIivOES; extern RGLSYMGLSAMPLERPARAMETERIUIVOESPROC __rglgen_glSamplerParameterIuivOES; extern RGLSYMGLGETSAMPLERPARAMETERIIVOESPROC __rglgen_glGetSamplerParameterIivOES; extern RGLSYMGLGETSAMPLERPARAMETERIUIVOESPROC __rglgen_glGetSamplerParameterIuivOES; extern RGLSYMGLTEXBUFFEROESPROC __rglgen_glTexBufferOES; extern RGLSYMGLTEXBUFFERRANGEOESPROC __rglgen_glTexBufferRangeOES; extern RGLSYMGLTEXSTORAGE3DMULTISAMPLEOESPROC __rglgen_glTexStorage3DMultisampleOES; extern RGLSYMGLTEXTUREVIEWOESPROC __rglgen_glTextureViewOES; extern RGLSYMGLBINDVERTEXARRAYOESPROC __rglgen_glBindVertexArrayOES; extern RGLSYMGLDELETEVERTEXARRAYSOESPROC __rglgen_glDeleteVertexArraysOES; extern RGLSYMGLGENVERTEXARRAYSOESPROC __rglgen_glGenVertexArraysOES; extern RGLSYMGLISVERTEXARRAYOESPROC __rglgen_glIsVertexArrayOES; extern RGLSYMGLDRAWARRAYSINSTANCEDBASEINSTANCEEXTPROC __rglgen_glDrawArraysInstancedBaseInstanceEXT; extern RGLSYMGLDRAWELEMENTSINSTANCEDBASEINSTANCEEXTPROC __rglgen_glDrawElementsInstancedBaseInstanceEXT; extern RGLSYMGLDRAWELEMENTSINSTANCEDBASEVERTEXBASEINSTANCEEXTPROC __rglgen_glDrawElementsInstancedBaseVertexBaseInstanceEXT; extern RGLSYMGLBINDFRAGDATALOCATIONINDEXEDEXTPROC __rglgen_glBindFragDataLocationIndexedEXT; extern RGLSYMGLBINDFRAGDATALOCATIONEXTPROC __rglgen_glBindFragDataLocationEXT; extern RGLSYMGLGETPROGRAMRESOURCELOCATIONINDEXEXTPROC __rglgen_glGetProgramResourceLocationIndexEXT; extern RGLSYMGLGETFRAGDATAINDEXEXTPROC __rglgen_glGetFragDataIndexEXT; extern RGLSYMGLBUFFERSTORAGEEXTPROC __rglgen_glBufferStorageEXT; extern RGLSYMGLCOPYIMAGESUBDATAEXTPROC __rglgen_glCopyImageSubDataEXT; extern RGLSYMGLLABELOBJECTEXTPROC __rglgen_glLabelObjectEXT; extern RGLSYMGLGETOBJECTLABELEXTPROC __rglgen_glGetObjectLabelEXT; extern RGLSYMGLINSERTEVENTMARKEREXTPROC __rglgen_glInsertEventMarkerEXT; extern RGLSYMGLPUSHGROUPMARKEREXTPROC __rglgen_glPushGroupMarkerEXT; extern RGLSYMGLPOPGROUPMARKEREXTPROC __rglgen_glPopGroupMarkerEXT; extern RGLSYMGLDISCARDFRAMEBUFFEREXTPROC __rglgen_glDiscardFramebufferEXT; extern RGLSYMGLGENQUERIESEXTPROC __rglgen_glGenQueriesEXT; extern RGLSYMGLDELETEQUERIESEXTPROC __rglgen_glDeleteQueriesEXT; extern RGLSYMGLISQUERYEXTPROC __rglgen_glIsQueryEXT; extern RGLSYMGLBEGINQUERYEXTPROC __rglgen_glBeginQueryEXT; extern RGLSYMGLENDQUERYEXTPROC __rglgen_glEndQueryEXT; extern RGLSYMGLQUERYCOUNTEREXTPROC __rglgen_glQueryCounterEXT; extern RGLSYMGLGETQUERYIVEXTPROC __rglgen_glGetQueryivEXT; extern RGLSYMGLGETQUERYOBJECTIVEXTPROC __rglgen_glGetQueryObjectivEXT; extern RGLSYMGLGETQUERYOBJECTUIVEXTPROC __rglgen_glGetQueryObjectuivEXT; extern RGLSYMGLDRAWBUFFERSEXTPROC __rglgen_glDrawBuffersEXT; extern RGLSYMGLENABLEIEXTPROC __rglgen_glEnableiEXT; extern RGLSYMGLDISABLEIEXTPROC __rglgen_glDisableiEXT; extern RGLSYMGLBLENDEQUATIONIEXTPROC __rglgen_glBlendEquationiEXT; extern RGLSYMGLBLENDEQUATIONSEPARATEIEXTPROC __rglgen_glBlendEquationSeparateiEXT; extern RGLSYMGLBLENDFUNCIEXTPROC __rglgen_glBlendFunciEXT; extern RGLSYMGLBLENDFUNCSEPARATEIEXTPROC __rglgen_glBlendFuncSeparateiEXT; extern RGLSYMGLCOLORMASKIEXTPROC __rglgen_glColorMaskiEXT; extern RGLSYMGLISENABLEDIEXTPROC __rglgen_glIsEnablediEXT; extern RGLSYMGLDRAWELEMENTSBASEVERTEXEXTPROC __rglgen_glDrawElementsBaseVertexEXT; extern RGLSYMGLDRAWRANGEELEMENTSBASEVERTEXEXTPROC __rglgen_glDrawRangeElementsBaseVertexEXT; extern RGLSYMGLDRAWELEMENTSINSTANCEDBASEVERTEXEXTPROC __rglgen_glDrawElementsInstancedBaseVertexEXT; extern RGLSYMGLMULTIDRAWELEMENTSBASEVERTEXEXTPROC __rglgen_glMultiDrawElementsBaseVertexEXT; extern RGLSYMGLDRAWARRAYSINSTANCEDEXTPROC __rglgen_glDrawArraysInstancedEXT; extern RGLSYMGLDRAWELEMENTSINSTANCEDEXTPROC __rglgen_glDrawElementsInstancedEXT; extern RGLSYMGLFRAMEBUFFERTEXTUREEXTPROC __rglgen_glFramebufferTextureEXT; extern RGLSYMGLVERTEXATTRIBDIVISOREXTPROC __rglgen_glVertexAttribDivisorEXT; extern RGLSYMGLMAPBUFFERRANGEEXTPROC __rglgen_glMapBufferRangeEXT; extern RGLSYMGLFLUSHMAPPEDBUFFERRANGEEXTPROC __rglgen_glFlushMappedBufferRangeEXT; extern RGLSYMGLMULTIDRAWARRAYSEXTPROC __rglgen_glMultiDrawArraysEXT; extern RGLSYMGLMULTIDRAWELEMENTSEXTPROC __rglgen_glMultiDrawElementsEXT; extern RGLSYMGLMULTIDRAWARRAYSINDIRECTEXTPROC __rglgen_glMultiDrawArraysIndirectEXT; extern RGLSYMGLMULTIDRAWELEMENTSINDIRECTEXTPROC __rglgen_glMultiDrawElementsIndirectEXT; extern RGLSYMGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC __rglgen_glRenderbufferStorageMultisampleEXT; extern RGLSYMGLFRAMEBUFFERTEXTURE2DMULTISAMPLEEXTPROC __rglgen_glFramebufferTexture2DMultisampleEXT; extern RGLSYMGLREADBUFFERINDEXEDEXTPROC __rglgen_glReadBufferIndexedEXT; extern RGLSYMGLDRAWBUFFERSINDEXEDEXTPROC __rglgen_glDrawBuffersIndexedEXT; extern RGLSYMGLGETINTEGERI_VEXTPROC __rglgen_glGetIntegeri_vEXT; extern RGLSYMGLPRIMITIVEBOUNDINGBOXEXTPROC __rglgen_glPrimitiveBoundingBoxEXT; extern RGLSYMGLRASTERSAMPLESEXTPROC __rglgen_glRasterSamplesEXT; extern RGLSYMGLGETGRAPHICSRESETSTATUSEXTPROC __rglgen_glGetGraphicsResetStatusEXT; extern RGLSYMGLREADNPIXELSEXTPROC __rglgen_glReadnPixelsEXT; extern RGLSYMGLGETNUNIFORMFVEXTPROC __rglgen_glGetnUniformfvEXT; extern RGLSYMGLGETNUNIFORMIVEXTPROC __rglgen_glGetnUniformivEXT; extern RGLSYMGLACTIVESHADERPROGRAMEXTPROC __rglgen_glActiveShaderProgramEXT; extern RGLSYMGLBINDPROGRAMPIPELINEEXTPROC __rglgen_glBindProgramPipelineEXT; extern RGLSYMGLCREATESHADERPROGRAMVEXTPROC __rglgen_glCreateShaderProgramvEXT; extern RGLSYMGLDELETEPROGRAMPIPELINESEXTPROC __rglgen_glDeleteProgramPipelinesEXT; extern RGLSYMGLGENPROGRAMPIPELINESEXTPROC __rglgen_glGenProgramPipelinesEXT; extern RGLSYMGLGETPROGRAMPIPELINEINFOLOGEXTPROC __rglgen_glGetProgramPipelineInfoLogEXT; extern RGLSYMGLGETPROGRAMPIPELINEIVEXTPROC __rglgen_glGetProgramPipelineivEXT; extern RGLSYMGLISPROGRAMPIPELINEEXTPROC __rglgen_glIsProgramPipelineEXT; extern RGLSYMGLPROGRAMPARAMETERIEXTPROC __rglgen_glProgramParameteriEXT; extern RGLSYMGLPROGRAMUNIFORM1FEXTPROC __rglgen_glProgramUniform1fEXT; extern RGLSYMGLPROGRAMUNIFORM1FVEXTPROC __rglgen_glProgramUniform1fvEXT; extern RGLSYMGLPROGRAMUNIFORM1IEXTPROC __rglgen_glProgramUniform1iEXT; extern RGLSYMGLPROGRAMUNIFORM1IVEXTPROC __rglgen_glProgramUniform1ivEXT; extern RGLSYMGLPROGRAMUNIFORM2FEXTPROC __rglgen_glProgramUniform2fEXT; extern RGLSYMGLPROGRAMUNIFORM2FVEXTPROC __rglgen_glProgramUniform2fvEXT; extern RGLSYMGLPROGRAMUNIFORM2IEXTPROC __rglgen_glProgramUniform2iEXT; extern RGLSYMGLPROGRAMUNIFORM2IVEXTPROC __rglgen_glProgramUniform2ivEXT; extern RGLSYMGLPROGRAMUNIFORM3FEXTPROC __rglgen_glProgramUniform3fEXT; extern RGLSYMGLPROGRAMUNIFORM3FVEXTPROC __rglgen_glProgramUniform3fvEXT; extern RGLSYMGLPROGRAMUNIFORM3IEXTPROC __rglgen_glProgramUniform3iEXT; extern RGLSYMGLPROGRAMUNIFORM3IVEXTPROC __rglgen_glProgramUniform3ivEXT; extern RGLSYMGLPROGRAMUNIFORM4FEXTPROC __rglgen_glProgramUniform4fEXT; extern RGLSYMGLPROGRAMUNIFORM4FVEXTPROC __rglgen_glProgramUniform4fvEXT; extern RGLSYMGLPROGRAMUNIFORM4IEXTPROC __rglgen_glProgramUniform4iEXT; extern RGLSYMGLPROGRAMUNIFORM4IVEXTPROC __rglgen_glProgramUniform4ivEXT; extern RGLSYMGLPROGRAMUNIFORMMATRIX2FVEXTPROC __rglgen_glProgramUniformMatrix2fvEXT; extern RGLSYMGLPROGRAMUNIFORMMATRIX3FVEXTPROC __rglgen_glProgramUniformMatrix3fvEXT; extern RGLSYMGLPROGRAMUNIFORMMATRIX4FVEXTPROC __rglgen_glProgramUniformMatrix4fvEXT; extern RGLSYMGLUSEPROGRAMSTAGESEXTPROC __rglgen_glUseProgramStagesEXT; extern RGLSYMGLVALIDATEPROGRAMPIPELINEEXTPROC __rglgen_glValidateProgramPipelineEXT; extern RGLSYMGLPROGRAMUNIFORM1UIEXTPROC __rglgen_glProgramUniform1uiEXT; extern RGLSYMGLPROGRAMUNIFORM2UIEXTPROC __rglgen_glProgramUniform2uiEXT; extern RGLSYMGLPROGRAMUNIFORM3UIEXTPROC __rglgen_glProgramUniform3uiEXT; extern RGLSYMGLPROGRAMUNIFORM4UIEXTPROC __rglgen_glProgramUniform4uiEXT; extern RGLSYMGLPROGRAMUNIFORM1UIVEXTPROC __rglgen_glProgramUniform1uivEXT; extern RGLSYMGLPROGRAMUNIFORM2UIVEXTPROC __rglgen_glProgramUniform2uivEXT; extern RGLSYMGLPROGRAMUNIFORM3UIVEXTPROC __rglgen_glProgramUniform3uivEXT; extern RGLSYMGLPROGRAMUNIFORM4UIVEXTPROC __rglgen_glProgramUniform4uivEXT; extern RGLSYMGLPROGRAMUNIFORMMATRIX2X3FVEXTPROC __rglgen_glProgramUniformMatrix2x3fvEXT; extern RGLSYMGLPROGRAMUNIFORMMATRIX3X2FVEXTPROC __rglgen_glProgramUniformMatrix3x2fvEXT; extern RGLSYMGLPROGRAMUNIFORMMATRIX2X4FVEXTPROC __rglgen_glProgramUniformMatrix2x4fvEXT; extern RGLSYMGLPROGRAMUNIFORMMATRIX4X2FVEXTPROC __rglgen_glProgramUniformMatrix4x2fvEXT; extern RGLSYMGLPROGRAMUNIFORMMATRIX3X4FVEXTPROC __rglgen_glProgramUniformMatrix3x4fvEXT; extern RGLSYMGLPROGRAMUNIFORMMATRIX4X3FVEXTPROC __rglgen_glProgramUniformMatrix4x3fvEXT; extern RGLSYMGLTEXPAGECOMMITMENTEXTPROC __rglgen_glTexPageCommitmentEXT; extern RGLSYMGLPATCHPARAMETERIEXTPROC __rglgen_glPatchParameteriEXT; extern RGLSYMGLTEXPARAMETERIIVEXTPROC __rglgen_glTexParameterIivEXT; extern RGLSYMGLTEXPARAMETERIUIVEXTPROC __rglgen_glTexParameterIuivEXT; extern RGLSYMGLGETTEXPARAMETERIIVEXTPROC __rglgen_glGetTexParameterIivEXT; extern RGLSYMGLGETTEXPARAMETERIUIVEXTPROC __rglgen_glGetTexParameterIuivEXT; extern RGLSYMGLSAMPLERPARAMETERIIVEXTPROC __rglgen_glSamplerParameterIivEXT; extern RGLSYMGLSAMPLERPARAMETERIUIVEXTPROC __rglgen_glSamplerParameterIuivEXT; extern RGLSYMGLGETSAMPLERPARAMETERIIVEXTPROC __rglgen_glGetSamplerParameterIivEXT; extern RGLSYMGLGETSAMPLERPARAMETERIUIVEXTPROC __rglgen_glGetSamplerParameterIuivEXT; extern RGLSYMGLTEXBUFFEREXTPROC __rglgen_glTexBufferEXT; extern RGLSYMGLTEXBUFFERRANGEEXTPROC __rglgen_glTexBufferRangeEXT; extern RGLSYMGLTEXSTORAGE1DEXTPROC __rglgen_glTexStorage1DEXT; extern RGLSYMGLTEXSTORAGE2DEXTPROC __rglgen_glTexStorage2DEXT; extern RGLSYMGLTEXSTORAGE3DEXTPROC __rglgen_glTexStorage3DEXT; extern RGLSYMGLTEXTURESTORAGE1DEXTPROC __rglgen_glTextureStorage1DEXT; extern RGLSYMGLTEXTURESTORAGE2DEXTPROC __rglgen_glTextureStorage2DEXT; extern RGLSYMGLTEXTURESTORAGE3DEXTPROC __rglgen_glTextureStorage3DEXT; extern RGLSYMGLTEXTUREVIEWEXTPROC __rglgen_glTextureViewEXT; extern RGLSYMGLFRAMEBUFFERTEXTUREMULTIVIEWOVRPROC __rglgen_glFramebufferTextureMultiviewOVR; extern RGLSYMGLFRAMEBUFFERTEXTUREMULTISAMPLEMULTIVIEWOVRPROC __rglgen_glFramebufferTextureMultisampleMultiviewOVR; struct rglgen_sym_map { const char *sym; void *ptr; }; extern const struct rglgen_sym_map rglgen_symbol_map[]; #ifdef __cplusplus } #endif #endif desmume/src/utils/AsmJit/x86/x86compiler.h000664 001750 001750 00000763010 12755534123 021453 0ustar00sergiosergio000000 000000 // [AsmJit] // Complete JIT Assembler for C++ Language. // // [License] // Zlib - See COPYING file in this package. // [Guard] #ifndef _ASMJIT_X86_X86COMPILER_H #define _ASMJIT_X86_X86COMPILER_H // [Dependencies - AsmJit] #include "../core/build.h" #include "../core/compiler.h" #include "../core/compilercontext.h" #include "../core/compilerfunc.h" #include "../core/compileritem.h" #include "../x86/x86assembler.h" #include "../x86/x86defs.h" #include "../x86/x86func.h" #include "../x86/x86util.h" // [Api-Begin] #include "../core/apibegin.h" //! @internal //! //! @brief Mark methods not supported by @ref Compiler. These methods are //! usually used only in function prologs/epilogs or to manage stack. #define ASMJIT_NOT_SUPPORTED_BY_COMPILER 0 namespace AsmJit { //! @addtogroup AsmJit_X86 //! @{ // ============================================================================ // [Forward Declarations] // ============================================================================ struct X86Compiler; struct X86CompilerAlign; struct X86CompilerContext; struct X86CompilerFuncCall; struct X86CompilerFuncDecl; struct X86CompilerFuncEnd; struct X86CompilerInst; struct X86CompilerJmpInst; struct X86CompilerState; struct X86CompilerTarget; struct X86CompilerVar; // ============================================================================ // [AsmJit::X86CompilerVar] // ============================================================================ //! @brief @ref X86Compiler variable. struct X86CompilerVar : public CompilerVar { // -------------------------------------------------------------------------- // [AsVar] // -------------------------------------------------------------------------- inline GpVar asGpVar() const { GpVar var; var._var.id = _id; var._var.size = _size; var._var.regCode = x86VarInfo[_type].getCode(); var._var.varType = _type; return var; } inline MmVar asMmVar() const { MmVar var; var._var.id = _id; var._var.size = _size; var._var.regCode = x86VarInfo[_type].getCode(); var._var.varType = _type; return var; } inline XmmVar asXmmVar() const { XmmVar var; var._var.id = _id; var._var.size = _size; var._var.regCode = x86VarInfo[_type].getCode(); var._var.varType = _type; return var; } // -------------------------------------------------------------------------- // [Members - Scope] // -------------------------------------------------------------------------- //! @brief The first item where the variable is accessed. //! @note If this member is @c NULL then variable isn't used. CompilerItem* firstItem; //! @brief The last item where the variable is accessed. CompilerItem* lastItem; //! @brief Scope (NULL if variable is global). X86CompilerFuncDecl* funcScope; //! @brief The first call which is after the @c firstItem. X86CompilerFuncCall* funcCall; // -------------------------------------------------------------------------- // [Members - Home] // -------------------------------------------------------------------------- //! @brief Home register index or @c kRegIndexInvalid (used by register allocator). uint32_t homeRegisterIndex; //! @brief Preferred registers mask. uint32_t prefRegisterMask; //! @brief Home memory address offset. int32_t homeMemoryOffset; //! @brief Used by @c CompilerContext, do not touch (initially NULL). void* homeMemoryData; // -------------------------------------------------------------------------- // [Members - Actual] // -------------------------------------------------------------------------- //! @brief Actual register index (connected with actual @c X86CompilerState). uint32_t regIndex; //! @brief Actual working offset. This member is set before register allocator //! is called. If workOffset is same as CompilerContext::_currentOffset then //! this variable is probably used in next instruction and can't be spilled. uint32_t workOffset; //! @brief Next active variable in circular double-linked list. X86CompilerVar* nextActive; //! @brief Previous active variable in circular double-linked list. X86CompilerVar* prevActive; // -------------------------------------------------------------------------- // [Members - Flags] // -------------------------------------------------------------------------- //! @brief Variable state (connected with actual @c X86CompilerState). uint8_t state; //! @brief Whether variable was changed (connected with actual @c X86CompilerState). uint8_t changed; //! @brief Save on unuse (at end of the variable scope). uint8_t saveOnUnuse; // -------------------------------------------------------------------------- // [Members - Statistics] // -------------------------------------------------------------------------- //! @brief Register read access statistics. uint32_t regReadCount; //! @brief Register write access statistics. uint32_t regWriteCount; //! @brief Register read/write access statistics (related to a single instruction). uint32_t regRwCount; //! @brief Register GpbLo access statistics. uint32_t regGpbLoCount; //! @brief Register GpbHi access statistics. uint32_t regGpbHiCount; //! @brief Memory read statistics. uint32_t memReadCount; //! @brief Memory write statistics. uint32_t memWriteCount; //! @brief Memory read+write statistics. uint32_t memRwCount; // -------------------------------------------------------------------------- // [Members - Temporary] // -------------------------------------------------------------------------- //! @brief Temporary data that can be used in prepare/translate stage. //! //! Initial value is NULL and it's expected that after use it's set back to //! NULL. //! //! The temporary data is designed to be used by algorithms that need to //! set some state into variables, do something and then clean-up. See //! state switch and function call for details. union { void* tPtr; intptr_t tInt; }; }; // ============================================================================ // [AsmJit::X86CompilerState] // ============================================================================ //! @brief @ref X86Compiler state. struct X86CompilerState : CompilerState { enum { //! @brief Base for Gp registers. kStateRegGpBase = 0, //! @brief Base for Mm registers. kStateRegMmBase = 16, //! @brief Base for Xmm registers. kStateRegXmmBase = 24, //! @brief Count of all registers in @ref X86CompilerState. kStateRegCount = 16 + 8 + 16 }; // -------------------------------------------------------------------------- // [Clear] // -------------------------------------------------------------------------- inline void clear() { memset(this, 0, sizeof(*this)); } // -------------------------------------------------------------------------- // [Members] // -------------------------------------------------------------------------- union { //! @brief All allocated variables in one array. X86CompilerVar* regs[kStateRegCount]; struct { //! @brief Allocated GP registers. X86CompilerVar* gp[16]; //! @brief Allocated MM registers. X86CompilerVar* mm[8]; //! @brief Allocated XMM registers. X86CompilerVar* xmm[16]; }; }; //! @brief Used GP registers bit-mask. uint32_t usedGP; //! @brief Used MM registers bit-mask. uint32_t usedMM; //! @brief Used XMM registers bit-mask. uint32_t usedXMM; //! @brief Changed GP registers bit-mask. uint32_t changedGP; //! @brief Changed MM registers bit-mask. uint32_t changedMM; //! @brief Changed XMM registers bit-mask. uint32_t changedXMM; //! @brief Count of variables in @c memVarsData. uint32_t memVarsCount; //! @brief Variables stored in memory (@c kVarStateMem). //! //! When saving / restoring state it's important to keep registers which are //! still in memory. Register is always unused when it is going out-of-scope. //! All variables which are not here are unused (@c kVarStateUnused). X86CompilerVar* memVarsData[1]; }; // ============================================================================ // [AsmJit::VarMemBlock] // ============================================================================ struct VarMemBlock { int32_t offset; uint32_t size; VarMemBlock* nextUsed; VarMemBlock* nextFree; }; // ============================================================================ // [AsmJit::VarAllocRecord] // ============================================================================ //! @brief Variable alloc record (for each instruction that uses variables). //! //! Variable record contains pointer to variable data and register allocation //! flags. These flags are important to determine the best alloc instruction. struct VarAllocRecord { //! @brief Variable data (the structure owned by @c Compiler). X86CompilerVar* vdata; //! @brief Variable alloc flags, see @c kVarAllocFlags. uint32_t vflags; //! @brief Register mask (default is 0). uint32_t regMask; }; // ============================================================================ // [AsmJit::VarCallRecord] // ============================================================================ //! @brief Variable call-fn record (for each callable that uses variables). //! //! This record contains variables that are used to call a function (using //! @c X86CompilerFuncCall item). Each variable contains the registers where //! it must be and registers where the value will be returned. struct VarCallRecord { //! @brief Variable data (the structure owned by @c Compiler). X86CompilerVar* vdata; uint32_t flags; uint8_t inCount; uint8_t inDone; uint8_t outCount; uint8_t outDone; enum FLAGS { kFlagInGp = 0x0001, kFlagInMm = 0x0002, kFlagInXmm = 0x0004, kFlagInStack = 0x0008, kFlagOutEax = 0x0010, kFlagOutEdx = 0x0020, kFlagOutSt0 = 0x0040, kFlagOutSt1 = 0x0080, kFlagOutMm0 = 0x0100, kFlagOutXmm0 = 0x0400, kFlagOutXmm1 = 0x0800, kFlagInMemPtr = 0x1000, kFlagCallReg = 0x2000, kFlagCallMem = 0x4000, kFlagUnuseAfterUse = 0x8000 }; }; // ============================================================================ // [AsmJit::VarHintRecord] // ============================================================================ struct VarHintRecord { X86CompilerVar* vdata; uint32_t hint; }; // ============================================================================ // [AsmJit::ForwardJumpData] // ============================================================================ struct ForwardJumpData { X86CompilerJmpInst* inst; X86CompilerState* state; ForwardJumpData* next; }; // ============================================================================ // [AsmJit::CompilerUtil] // ============================================================================ //! @brief Static class that contains utility methods. struct CompilerUtil { ASMJIT_API static bool isStack16ByteAligned(); }; // ============================================================================ // [AsmJit::X86Compiler] // ============================================================================ //! @brief Compiler - high level code generation. //! //! This class is used to store instruction stream and allows to modify //! it on the fly. It uses different concept than @c AsmJit::Assembler class //! and in fact @c AsmJit::Assembler is only used as a backend. Compiler never //! emits machine code and each instruction you use is stored to instruction //! array instead. This allows to modify instruction stream later and for //! example to reorder instructions to make better performance. //! //! Using @c AsmJit::Compiler moves code generation to higher level. Higher //! level constructs allows to write more abstract and extensible code that //! is not possible with pure @c AsmJit::Assembler class. Because //! @c AsmJit::Compiler needs to create many objects and lifetime of these //! objects is small (same as @c AsmJit::Compiler lifetime itself) it uses //! very fast memory management model. This model allows to create object //! instances in nearly zero time (compared to @c malloc() or @c new() //! operators) so overhead by creating machine code by @c AsmJit::Compiler //! is minimized. //! //! @section AsmJit_Compiler_TheStory The Story //! //! Before telling you how Compiler works I'd like to write a story. I'd like //! to cover reasons why this class was created and why I'm recommending to use //! it. When I released the first version of AsmJit (0.1) it was a toy. The //! first function I wrote was function which is still available as testjit and //! which simply returns 1024. The reason why function works for both 32-bit/ //! 64-bit mode and for Windows/Unix specific calling conventions is luck, no //! arguments usage and no registers usage except returning value in EAX/RAX. //! //! Then I started a project called BlitJit which was targetted to generating //! JIT code for computer graphics. After writing some lines I decided that I //! can't join pieces of code together without abstraction, should be //! pixels source pointer in ESI/RSI or EDI/RDI or it's completelly //! irrellevant? What about destination pointer and SSE2 register for reading //! input pixels? The simple answer might be "just pick some one and use it". //! //! Another reason for abstraction is function calling-conventions. It's really //! not easy to write assembler code for 32-bit and 64-bit platform supporting //! three calling conventions (32-bit is similar between Windows and Unix, but //! 64-bit calling conventions are different). //! //! At this time I realized that I can't write code which uses named registers, //! I need to abstract it. In most cases you don't need specific register, you //! need to emit instruction that does something with 'virtual' register(s), //! memory, immediate or label. //! //! The first version of AsmJit with Compiler was 0.5 (or 0.6?, can't remember). //! There was support for 32-bit and 64-bit mode, function calling conventions, //! but when emitting instructions the developer needed to decide which //! registers are changed, which are only read or completely overwritten. This //! model helped a lot when generating code, especially when joining more //! code-sections together, but there was also small possibility for mistakes. //! Simply the first version of Compiler was great improvement over low-level //! Assembler class, but the API design wasn't perfect. //! //! The second version of Compiler, completelly rewritten and based on //! different goals, is part of AsmJit starting at version 1.0. This version //! was designed after the first one and it contains serious improvements over //! the old one. The first improvement is that you just use instructions with //! virtual registers - called variables. When using compiler there is no way //! to use native registers, there are variables instead. AsmJit is smarter //! than before and it knows which register is needed only for read (r), //! read/write (w) or overwrite (x). Supported are also instructions which //! are using some registers in implicit way (these registers are not part of //! instruction definition in string form). For example to use CPUID instruction //! you must give it four variables which will be automatically allocated to //! input/output registers (EAX, EBX, ECX, EDX). //! //! Another improvement is algorithm used by a register allocator. In first //! version the registers were allocated when creating instruction stream. In //! new version registers are allocated after calling @c Compiler::make(). This //! means that register allocator has information about scope of all variables //! and their usage statistics. The algorithm to allocate registers is very //! simple and it's always called as a 'linear scan register allocator'. When //! you get out of registers the all possible variables are scored and the worst //! is spilled. Of course algorithm ignores the variables used for current //! instruction. //! //! In addition, because registers are allocated after the code stream is //! generated, the state switches between jumps are handled by Compiler too. //! You don't need to worry about jumps, compiler always do this dirty work //! for you. //! //! The nearly last thing I'd like to present is calling other functions from //! the generated code. AsmJit uses a @c FunctionPrototype class to hold //! the function parameters, their position in stack (or register index) and //! function return value. This class is used internally, but it can be //! used to create your own function calling-convention. All standard function //! calling conventions are implemented. //! //! Please enjoy the new version of Compiler, it was created for writing a //! low-level code using high-level API, leaving developer to concentrate to //! real problems and not to solving a register puzzle. //! //! @section AsmJit_Compiler_CodeGeneration Code Generation //! //! First that is needed to know about compiler is that compiler never emits //! machine code. It's used as a middleware between @c AsmJit::Assembler and //! your code. There is also convenience method @c make() that allows to //! generate machine code directly without creating @c AsmJit::Assembler //! instance. //! //! Comparison of generating machine code through @c Assembler and directly //! by @c Compiler: //! //! @code //! // Assembler instance is low level code generation class that emits //! // machine code. //! X86Assembler a; //! //! // Compiler instance is high level code generation class that stores all //! // instructions in internal representation. //! X86Compiler c; //! //! // ... put your code here ... //! //! // Final step - generate code. AsmJit::Compiler::serialize() will serialize //! // all instructions into Assembler and this ensures generating real machine //! // code. //! c.serialize(a); //! //! // Your function //! void* fn = a.make(); //! @endcode //! //! Example how to generate machine code using only @c Compiler (preferred): //! //! @code //! // Compiler instance is enough. //! X86Compiler c; //! //! // ... put your code here ... //! //! // Your function //! void* fn = c.make(); //! @endcode //! //! You can see that there is @c AsmJit::Compiler::serialize() function that //! emits instructions into @c AsmJit::Assembler(). This layered architecture //! means that each class is used for something different and there is no code //! duplication. For convenience there is also @c AsmJit::Compiler::make() //! method that can create your function using @c AsmJit::Assembler, but //! internally (this is preffered bahavior when using @c AsmJit::Compiler). //! //! The @c make() method allocates memory using @c Context instance passed //! into the @c X86Compiler constructor. If code generator is used to create JIT //! function then virtual memory allocated by @c MemoryManager is used. To get //! global memory manager use @c MemoryManager::getGlobal(). //! //! @code //! // Compiler instance is enough. //! X86Compiler c; //! //! // ... put your code using Compiler instance ... //! //! // Your function //! void* fn = c.make(); //! //! // Free it if you don't want it anymore //! // (using global memory manager instance) //! MemoryManager::getGlobal()->free(fn); //! @endcode //! //! @section AsmJit_Compiler_Functions Functions //! //! To build functions with @c Compiler, see @c AsmJit::Compiler::newFunc() //! method. //! //! @section AsmJit_Compiler_Variables Variables //! //! Compiler is able to manage variables and function arguments. Internally //! there is no difference between function argument and variable declared //! inside. To get function argument you use @c getGpArg() method and to declare //! variable use @c newGpVar(), @c newMmVar() and @c newXmmVar() methods. The @c newXXX() //! methods accept also parameter describing the variable type. For example //! the @c newGpVar() method always creates variable which size matches the target //! architecture size (for 32-bit target the 32-bit variable is created, for //! 64-bit target the variable size is 64-bit). To override this behavior the //! variable type must be specified. //! //! @code //! // Compiler and function declaration - void f(int*); //! X86Compiler c; //! c.newFunc(kX86FuncConvDefault, BuildFunction1()); //! //! // Get argument variable (it's pointer). //! GpVar a1(c.getGpArg(0)); //! //! // Create your variables. //! GpVar x1(c.newGpVar(kX86VarTypeGpd)); //! GpVar x2(c.newGpVar(kX86VarTypeGpd)); //! //! // Init your variables. //! c.mov(x1, 1); //! c.mov(x2, 2); //! //! // ... your code ... //! c.add(x1, x2); //! // ... your code ... //! //! // Store result to a given pointer in first argument //! c.mov(dword_ptr(a1), x1); //! //! // End of function body. //! c.endFunc(); //! //! // Make the function. //! typedef void (*MyFn)(int*); //! MyFn fn = asmjit_cast(c.make()); //! @endcode //! //! This code snipped needs to be explained. You can see that there are more //! variable types that can be used by @c Compiler. Most useful variables can //! be allocated using general purpose registers (@c GpVar), MMX registers //! (@c MmVar) or SSE registers (@c XmmVar). //! //! X86/X64 variable types: //! //! - @c kX86VarTypeGpd - 32-bit general purpose register (EAX, EBX, ...). //! - @c kX86VarTypeGpq - 64-bit general purpose register (RAX, RBX, ...). //! - @c kX86VarTypeGpz - 32-bit or 64-bit general purpose register, depends //! to target architecture. Mapped to @c kX86VarTypeGpd or @c kX86VarTypeGpq. //! //! - @c kX86VarTypeX87 - 80-bit floating point stack register st(0 to 7). //! - @c kX86VarTypeX87SS - 32-bit floating point stack register st(0 to 7). //! - @c kX86VarTypeX87SD - 64-bit floating point stack register st(0 to 7). //! //! - @c VARIALBE_TYPE_MM - 64-bit MMX register. //! //! - @c kX86VarTypeXmm - 128-bit SSE register. //! - @c kX86VarTypeXmmSS - 128-bit SSE register which contains //! scalar 32-bit single precision floating point. //! - @c kX86VarTypeXmmSD - 128-bit SSE register which contains //! scalar 64-bit double precision floating point. //! - @c kX86VarTypeXmmPS - 128-bit SSE register which contains //! 4 packed 32-bit single precision floating points. //! - @c kX86VarTypeXmmPD - 128-bit SSE register which contains //! 2 packed 64-bit double precision floating points. //! //! Unified variable types: //! //! - @c kX86VarTypeInt32 - 32-bit general purpose register. //! - @c kX86VarTypeInt64 - 64-bit general purpose register. //! - @c kX86VarTypeIntPtr - 32-bit or 64-bit general purpose register / pointer. //! //! - @c kX86VarTypeFloat - 32-bit single precision floating point. //! - @c kX86VarTypeDouble - 64-bit double precision floating point. //! //! Variable states: //! //! - @c kVarStateUnused - State that is assigned to newly created //! variables or to not used variables (dereferenced to zero). //! - @c kVarStateReg - State that means that variable is currently //! allocated in register. //! - @c kVarStateMem - State that means that variable is currently //! only in memory location. //! //! When you create new variable, initial state is always @c kVarStateUnused, //! allocating it to register or spilling to memory changes this state to //! @c kVarStateReg or @c kVarStateMem, respectively. //! During variable lifetime it's usual that its state is changed multiple //! times. To generate better code, you can control allocating and spilling //! by using up to four types of methods that allows it (see next list). //! //! Explicit variable allocating / spilling methods: //! //! - @c Compiler::alloc() - Explicit method to alloc variable into //! register. You can use this before loops or code blocks. //! //! - @c Compiler::spill() - Explicit method to spill variable. If variable //! is in register and you call this method, it's moved to its home memory //! location. If variable is not in register no operation is performed. //! //! - @c Compiler::unuse() - Unuse variable (you can use this to end the //! variable scope or sub-scope). //! //! Please see AsmJit tutorials (testcompiler.cpp and testvariables.cpp) for //! more complete examples. //! //! @section AsmJit_Compiler_MemoryManagement Memory Management //! //! @c Compiler Memory management follows these rules: //! - Everything created by @c Compiler is always freed by @c Compiler. //! - To get decent performance, compiler always uses larger memory buffer //! for objects to allocate and when compiler instance is destroyed, this //! buffer is freed. Destructors of active objects are called when //! destroying compiler instance. Destructors of abadonded compiler //! objects are called immediately after abadonding them. //! - This type of memory management is called 'zone memory management'. //! //! This means that you can't use any @c Compiler object after destructing it, //! it also means that each object like @c Label, @c Var and others are created //! and managed by @c Compiler itself. These objects contain ID which is used //! internally by Compiler to store additional information about these objects. //! //! @section AsmJit_Compiler_StateManagement Control-Flow and State Management. //! //! The @c Compiler automatically manages state of the variables when using //! control flow instructions like jumps, conditional jumps and calls. There //! is minimal heuristics for choosing the method how state is saved or restored. //! //! Generally the state can be changed only when using jump or conditional jump //! instruction. When using non-conditional jump then state change is embedded //! into the instruction stream before the jump. When using conditional jump //! the @c Compiler decides whether to restore state before the jump or whether //! to use another block where state is restored. The last case is that no-code //! have to be emitted and there is no state change (this is of course ideal). //! //! Choosing whether to embed 'restore-state' section before conditional jump //! is quite simple. If jump is likely to be 'taken' then code is embedded, if //! jump is unlikely to be taken then the small code section for state-switch //! will be generated instead. //! //! Next example is the situation where the extended code block is used to //! do state-change: //! //! @code //! X86Compiler c; //! //! c.newFunc(kX86FuncConvDefault, FuncBuilder0()); //! c.getFunc()->setHint(kFuncHintNaked, true); //! //! // Labels. //! Label L0 = c.newLabel(); //! //! // Variables. //! GpVar var0 = c.newGpVar(); //! GpVar var1 = c.newGpVar(); //! //! // Cleanup. After these two lines, the var0 and var1 will be always stored //! // in registers. Our example is very small, but in larger code the var0 can //! // be spilled by xor(var1, var1). //! c.xor_(var0, var0); //! c.xor_(var1, var1); //! c.cmp(var0, var1); //! // State: //! // var0 - register. //! // var1 - register. //! //! // We manually spill these variables. //! c.spill(var0); //! c.spill(var1); //! // State: //! // var0 - memory. //! // var1 - memory. //! //! // Conditional jump to L0. It will be always taken, but compiler thinks that //! // it is unlikely taken so it will embed state change code somewhere. //! c.je(L0); //! //! // Do something. The variables var0 and var1 will be allocated again. //! c.add(var0, 1); //! c.add(var1, 2); //! // State: //! // var0 - register. //! // var1 - register. //! //! // Bind label here, the state is not changed. //! c.bind(L0); //! // State: //! // var0 - register. //! // var1 - register. //! //! // We need to use var0 and var1, because if compiler detects that variables //! // are out of scope then it optimizes the state-change. //! c.sub(var0, var1); //! // State: //! // var0 - register. //! // var1 - register. //! //! c.endFunc(); //! @endcode //! //! The output: //! //! @verbatim //! xor eax, eax ; xor var_0, var_0 //! xor ecx, ecx ; xor var_1, var_1 //! cmp eax, ecx ; cmp var_0, var_1 //! mov [esp - 24], eax ; spill var_0 //! mov [esp - 28], ecx ; spill var_1 //! je L0_Switch //! mov eax, [esp - 24] ; alloc var_0 //! add eax, 1 ; add var_0, 1 //! mov ecx, [esp - 28] ; alloc var_1 //! add ecx, 2 ; add var_1, 2 //! L0: //! sub eax, ecx ; sub var_0, var_1 //! ret //! //! ; state-switch begin //! L0_Switch0: //! mov eax, [esp - 24] ; alloc var_0 //! mov ecx, [esp - 28] ; alloc var_1 //! jmp short L0 //! ; state-switch end //! @endverbatim //! //! You can see that the state-switch section was generated (see L0_Switch0). //! The compiler is unable to restore state immediately when emitting the //! forward jump (the code is generated from first to last instruction and //! the target state is simply not known at this time). //! //! To tell @c Compiler that you want to embed state-switch code before jump //! it's needed to create backward jump (where also processor expects that it //! will be taken). To demonstrate the possibility to embed state-switch before //! jump we use slightly modified code: //! //! @code //! X86Compiler c; //! //! c.newFunc(kX86FuncConvDefault, FuncBuilder0()); //! c.getFunc()->setHint(kFuncHintNaked, true); //! //! // Labels. //! Label L0 = c.newLabel(); //! //! // Variables. //! GpVar var0 = c.newGpVar(); //! GpVar var1 = c.newGpVar(); //! //! // Cleanup. After these two lines, the var0 and var1 will be always stored //! // in registers. Our example is very small, but in larger code the var0 can //! // be spilled by xor(var1, var1). //! c.xor_(var0, var0); //! c.xor_(var1, var1); //! // State: //! // var0 - register. //! // var1 - register. //! //! // We manually spill these variables. //! c.spill(var0); //! c.spill(var1); //! // State: //! // var0 - memory. //! // var1 - memory. //! //! // Bind our label here. //! c.bind(L0); //! //! // Do something, the variables will be allocated again. //! c.add(var0, 1); //! c.add(var1, 2); //! // State: //! // var0 - register. //! // var1 - register. //! //! // Backward conditional jump to L0. The default behavior is that it is taken //! // so state-change code will be embedded here. //! c.je(L0); //! //! c.endFunc(); //! @endcode //! //! The output: //! //! @verbatim //! xor ecx, ecx ; xor var_0, var_0 //! xor edx, edx ; xor var_1, var_1 //! mov [esp - 24], ecx ; spill var_0 //! mov [esp - 28], edx ; spill var_1 //! L.2: //! mov ecx, [esp - 24] ; alloc var_0 //! add ecx, 1 ; add var_0, 1 //! mov edx, [esp - 28] ; alloc var_1 //! add edx, 2 ; add var_1, 2 //! //! ; state-switch begin //! mov [esp - 24], ecx ; spill var_0 //! mov [esp - 28], edx ; spill var_1 //! ; state-switch end //! //! je short L.2 //! ret //! @endverbatim //! //! Please notice where the state-switch section is located. The @c Compiler //! decided that jump is likely to be taken so the state change is embedded //! before the conditional jump. To change this behavior into the previous //! case it's needed to add a hint (@c kCondHintLikely or @c kCondHintUnlikely). //! //! Replacing the c.je(L0) by c.je(L0, kCondHintUnlikely) //! will generate code like this: //! //! @verbatim //! xor ecx, ecx ; xor var_0, var_0 //! xor edx, edx ; xor var_1, var_1 //! mov [esp - 24], ecx ; spill var_0 //! mov [esp - 28], edx ; spill var_1 //! L0: //! mov ecx, [esp - 24] ; alloc var_0 //! add ecx, 1 ; add var_0, a //! mov edx, [esp - 28] ; alloc var_1 //! add edx, 2 ; add var_1, 2 //! je L0_Switch, 2 //! ret //! //! ; state-switch begin //! L0_Switch: //! mov [esp - 24], ecx ; spill var_0 //! mov [esp - 28], edx ; spill var_1 //! jmp short L0 //! ; state-switch end //! @endverbatim //! //! This section provided information about how state-change works. The //! behavior is deterministic and it can be overridden. //! //! @section AsmJit_Compiler_AdvancedCodeGeneration Advanced Code Generation //! //! This section describes advanced method of code generation available to //! @c Compiler (but also to @c Assembler). When emitting code to instruction //! stream the methods like @c mov(), @c add(), @c sub() can be called directly //! (advantage is static-type control performed also by C++ compiler) or //! indirectly using @c emit() method. The @c emit() method needs only //! instruction code and operands. //! //! Example of code generating by standard type-safe API: //! //! @code //! X86Compiler c; //! GpVar var0 = c.newGpVar(); //! GpVar var1 = c.newGpVar(); //! //! ... //! //! c.mov(var0, imm(0)); //! c.add(var0, var1); //! c.sub(var0, var1); //! @endcode //! //! The code above can be rewritten as: //! //! @code //! X86Compiler c; //! GpVar var0 = c.newGpVar(); //! GpVar var1 = c.newGpVar(); //! //! ... //! //! c.emit(kX86InstMov, var0, imm(0)); //! c.emit(kX86InstAdd, var0, var1); //! c.emit(kX86InstSub, var0, var1); //! @endcode //! //! The advantage of first snippet is very friendly API and type-safe control //! that is controlled by the C++ compiler. The advantage of second snippet is //! availability to replace or generate instruction code in different places. //! See the next example how the @c emit() method can be used to generate //! abstract code. //! //! Use case: //! //! @code //! bool emitArithmetic(Compiler& c, XmmVar& var0, XmmVar& var1, const char* op) //! { //! uint code = kInstNone; //! //! if (strcmp(op, "ADD") == 0) //! code = kX86InstAddSS; //! else if (strcmp(op, "SUBTRACT") == 0) //! code = kX86InstSubSS; //! else if (strcmp(op, "MULTIPLY") == 0) //! code = kX86InstMulSS; //! else if (strcmp(op, "DIVIDE") == 0) //! code = kX86InstDivSS; //! else //! // Invalid parameter? //! return false; //! //! c.emit(code, var0, var1); //! } //! @endcode //! //! Other use cases are waiting for you! Be sure that instruction you are //! emitting is correct and encodable, because if not, Assembler will set //! error code to @c kErrorUnknownInstruction. //! //! @section AsmJit_Compiler_CompilerDetails Compiler Details //! //! This section is here for people interested in the compiling process. There //! are few steps that must be done for each compiled function (or your code). //! //! When your @c Compiler instance is ready, you can create function and add //! compiler-items using intrinsics or higher level methods implemented by the //! @c AsmJit::Compiler. When you are done (all instructions serialized) you //! should call @c AsmJit::Compiler::make() method which will analyze your code, //! allocate registers and memory for local variables and serialize all items //! to @c AsmJit::Assembler instance. Next steps shows what's done internally //! before code is serialized into @c AsmJit::Assembler //! (implemented in @c AsmJit::Compiler::serialize() method). //! //! 1. Compiler try to match function and end-function items (these items //! define function body and blocks). //! //! 2. For all items inside the function-body the virtual functions //! are called in this order: //! - CompilerItem::prepare() //! - CompilerItem::translate() //! - CompilerItem::emit() //! - CompilerItem::post() //! //! There is some extra work when emitting function prolog / epilog and //! register allocator. //! //! 3. Emit jump tables data. //! //! When everything here ends, @c AsmJit::Assembler contains binary stream //! that needs only relocation to be callable by C/C++ code. //! //! @section AsmJit_Compiler_Differences Summary of Differences between @c Assembler and @c Compiler //! //! - Instructions are not translated to machine code immediately, they are //! stored as emmitables, see @c AsmJit::CompilerItem. //! - Contains function builder and ability to call other functions. //! - Contains register allocator and variable management. //! - Contains a lot of helper methods to simplify the code generation not //! available/possible in @c AsmJit::Assembler. //! - Ability to pre-process or post-process the code which is being generated. struct X86Compiler : public Compiler { // Special X86 instructions: // - cpuid, // - cbw, cwd, cwde, cdq, cdqe, cqo // - cmpxchg // - cmpxchg8b, cmpxchg16b, // - daa, das, // - imul, mul, idiv, div, // - mov_ptr // - lahf, sahf // - maskmovq, maskmovdqu // - enter, leave // - ret // - monitor, mwait // - pop, popad, popfd, popfq, // - push, pushad, pushfd, pushfq // - rcl, rcr, rol, ror, sal, sar, shl, shr // - shld, shrd // - rdtsc. rdtscp // - lodsb, lodsd, lodsq, lodsw // - movsb, movsd, movsq, movsw // - stosb, stosd, stosq, stosw // - cmpsb, cmpsd, cmpsq, cmpsw // - scasb, scasd, scasq, scasw // // Special X87 instructions: // - fisttp // -------------------------------------------------------------------------- // [Construction / Destruction] // -------------------------------------------------------------------------- //! @brief Create a @ref X86Compiler instance. ASMJIT_API X86Compiler(Context* context = JitContext::getGlobal()); //! @brief Destroy the @ref X86Compiler instance. ASMJIT_API ~X86Compiler(); // -------------------------------------------------------------------------- // [Accessors] // -------------------------------------------------------------------------- //! @brief Get current function as @ref X86CompilerFuncDecl. //! //! This method can be called within @c newFunc() and @c endFunc() //! block to get current function you are working with. It's recommended //! to store @c AsmJit::Function pointer returned by @c newFunc<> method, //! because this allows you in future implement function sections outside of //! function itself (yeah, this is possible!). inline X86CompilerFuncDecl* getFunc() const { return reinterpret_cast(_func); } // -------------------------------------------------------------------------- // [Function Builder] // -------------------------------------------------------------------------- //! @brief Create a new function. //! //! @param cconv Calling convention to use (see @c kX86FuncConv enum) //! @param params Function arguments prototype. //! //! This method is usually used as a first step when generating functions //! by @c Compiler. First parameter @a cconv specifies function calling //! convention to use. Second parameter @a params specifies function //! arguments. To create function arguments are used templates //! @c BuildFunction0<>, @c BuildFunction1<...>, @c BuildFunction2<...>, //! etc... //! //! Templates with BuildFunction prefix are used to generate argument IDs //! based on real C++ types. See next example how to generate function with //! two 32-bit integer arguments. //! //! @code //! // Building function using AsmJit::Compiler example. //! //! // Compiler instance //! X86Compiler c; //! //! // Begin of function (also emits function @c Prolog) //! c.newFunc( //! // Default calling convention (32-bit cdecl or 64-bit for host OS) //! kX86FuncConvDefault, //! // Using function builder to generate arguments list //! BuildFunction2()); //! //! // End of function (also emits function @c Epilog) //! c.endFunc(); //! @endcode //! //! You can see that building functions is really easy. Previous code snipped //! will generate code for function with two 32-bit integer arguments. You //! can access arguments by @c AsmJit::Function::argument() method. Arguments //! are indexed from 0 (like everything in C). //! //! @code //! // Accessing function arguments through AsmJit::Function example. //! //! // Compiler instance //! X86Compiler c; //! //! // Begin of function (also emits function @c Prolog) //! c.newFunc( //! // Default calling convention (32-bit cdecl or 64-bit for host OS) //! kX86FuncConvDefault, //! // Using function builder to generate arguments list //! BuildFunction2()); //! //! // Arguments are like other variables, you need to reference them by //! // variable operands: //! GpVar a0 = c.getGpArg(0); //! GpVar a1 = c.getGpArg(1); //! //! // Use them. //! c.add(a0, a1); //! //! // End of function (emits function epilog and return) //! c.endFunc(); //! @endcode //! //! Arguments are like variables. How to manipulate with variables is //! documented in @c AsmJit::Compiler, variables section. //! //! @note To get current function use @c currentFunction() method or save //! pointer to @c AsmJit::Function returned by @c AsmJit::Compiler::newFunc<> //! method. Recommended is to save the pointer. //! //! @sa @c BuildFunction0, @c BuildFunction1, @c BuildFunction2, ... inline X86CompilerFuncDecl* newFunc(uint32_t convention, const FuncPrototype& func) { return newFunc_(convention, func.getReturnType(), func.getArguments(), func.getArgumentsCount()); } //! @brief Create a new function (low level version). //! //! @param cconv Function calling convention (see @c AsmJit::kX86FuncConv). //! @param args Function arguments (see @c AsmJit::kX86VarType). //! @param count Arguments count. //! //! This method is internally called from @c newFunc() method and //! contains arguments thats used internally by @c AsmJit::Compiler. //! //! @note To get current function use @c currentFunction() method. ASMJIT_API X86CompilerFuncDecl* newFunc_(uint32_t convenion, uint32_t returnType, const uint32_t* arguments, uint32_t argumentsCount); //! @brief End of current function scope and all variables. ASMJIT_API X86CompilerFuncDecl* endFunc(); // -------------------------------------------------------------------------- // [Emit] // -------------------------------------------------------------------------- //! @brief Emit instruction with no operand. ASMJIT_API void _emitInstruction(uint32_t code); //! @brief Emit instruction with one operand. ASMJIT_API void _emitInstruction(uint32_t code, const Operand* o0); //! @brief Emit instruction with two operands. ASMJIT_API void _emitInstruction(uint32_t code, const Operand* o0, const Operand* o1); //! @brief Emit instruction with three operands. ASMJIT_API void _emitInstruction(uint32_t code, const Operand* o0, const Operand* o1, const Operand* o2); //! @brief Emit instruction with four operands (Special instructions). ASMJIT_API void _emitInstruction(uint32_t code, const Operand* o0, const Operand* o1, const Operand* o2, const Operand* o3); //! @brief Emit instruction with five operands (Special instructions). ASMJIT_API void _emitInstruction(uint32_t code, const Operand* o0, const Operand* o1, const Operand* o2, const Operand* o3, const Operand* o4); //! @brief Private method for emitting jcc. ASMJIT_API void _emitJcc(uint32_t code, const Label* label, uint32_t hint); //! @brief Private method for emitting function call. ASMJIT_API X86CompilerFuncCall* _emitCall(const Operand* o0); //! @brief Private method for returning a value from the function. ASMJIT_API void _emitReturn(const Operand* first, const Operand* second); // -------------------------------------------------------------------------- // [Align] // -------------------------------------------------------------------------- //! @brief Align target buffer to @a m bytes. //! //! Typical usage of this is to align labels at start of the inner loops. //! //! Inserts @c nop() instructions or CPU optimized NOPs. ASMJIT_API void align(uint32_t m); // -------------------------------------------------------------------------- // [Label] // -------------------------------------------------------------------------- //! @brief Create and return new label. ASMJIT_API Label newLabel(); //! @brief Bind label to the current offset. //! //! @note Label can be bound only once! ASMJIT_API void bind(const Label& label); // -------------------------------------------------------------------------- // [Variables] // -------------------------------------------------------------------------- //! @brief Get compiler variable at @a id. inline X86CompilerVar* _getVar(uint32_t id) const { ASMJIT_ASSERT(id != kInvalidValue); return reinterpret_cast(_vars[id & kOperandIdValueMask]); } //! @internal //! //! @brief Create a new variable data. ASMJIT_API X86CompilerVar* _newVar(const char* name, uint32_t type, uint32_t size); //! @brief Create a new general-purpose variable. ASMJIT_API GpVar newGpVar(uint32_t varType = kX86VarTypeGpz, const char* name = NULL); //! @brief Get argument as general-purpose variable. ASMJIT_API GpVar getGpArg(uint32_t argIndex); //! @brief Create a new MM variable. ASMJIT_API MmVar newMmVar(uint32_t varType = kX86VarTypeMm, const char* name = NULL); //! @brief Get argument as MM variable. ASMJIT_API MmVar getMmArg(uint32_t argIndex); //! @brief Create a new XMM variable. ASMJIT_API XmmVar newXmmVar(uint32_t varType = kX86VarTypeXmm, const char* name = NULL); //! @brief Get argument as XMM variable. ASMJIT_API XmmVar getXmmArg(uint32_t argIndex); //! @internal //! //! @brief Serialize variable hint. ASMJIT_API void _vhint(Var& var, uint32_t hintId, uint32_t hintValue); //! @brief Alloc variable @a var. ASMJIT_API void alloc(Var& var); //! @brief Alloc variable @a var using @a regIndex as a register index. ASMJIT_API void alloc(Var& var, uint32_t regIndex); //! @brief Alloc variable @a var using @a reg as a demanded register. ASMJIT_API void alloc(Var& var, const Reg& reg); //! @brief Spill variable @a var. ASMJIT_API void spill(Var& var); //! @brief Save variable @a var if modified. ASMJIT_API void save(Var& var); //! @brief Unuse variable @a var. ASMJIT_API void unuse(Var& var); //! @brief Get memory home of variable @a var. ASMJIT_API void getMemoryHome(Var& var, GpVar* home, int* displacement = NULL); //! @brief Set memory home of variable @a var. //! //! Default memory home location is on stack (ESP/RSP), but when needed the //! bebahior can be changed by this method. //! //! It is an error to chaining memory home locations. For example the given //! code is invalid: //! //! @code //! X86Compiler c; //! //! ... //! GpVar v0 = c.newGpVar(); //! GpVar v1 = c.newGpVar(); //! GpVar v2 = c.newGpVar(); //! GpVar v3 = c.newGpVar(); //! //! c.setMemoryHome(v1, v0, 0); // Allowed, [v0] is memory home for v1. //! c.setMemoryHome(v2, v0, 4); // Allowed, [v0+4] is memory home for v2. //! c.setMemoryHome(v3, v2); // CHAINING, NOT ALLOWED! //! @endcode ASMJIT_API void setMemoryHome(Var& var, const GpVar& home, int displacement = 0); //! @brief Get priority of variable @a var. ASMJIT_API uint32_t getPriority(Var& var) const; //! @brief Set priority of variable @a var to @a priority. ASMJIT_API void setPriority(Var& var, uint32_t priority); //! @brief Get save-on-unuse @a var property. ASMJIT_API bool getSaveOnUnuse(Var& var) const; //! @brief Set save-on-unuse @a var property to @a value. ASMJIT_API void setSaveOnUnuse(Var& var, bool value); //! @brief Rename variable @a var to @a name. //! //! @note Only new name will appear in the logger. ASMJIT_API void rename(Var& var, const char* name); // -------------------------------------------------------------------------- // [State] // -------------------------------------------------------------------------- //! @internal //! //! @brief Create a new @ref X86CompilerState. ASMJIT_API X86CompilerState* _newState(uint32_t memVarsCount); // -------------------------------------------------------------------------- // [Make] // -------------------------------------------------------------------------- //! @brief Make is convenience method to make currently serialized code and //! return pointer to generated function. //! //! What you need is only to cast this pointer to your function type and call //! it. Note that if there was an error and calling @c getError() method doesn't //! return @c kErrorOk (zero) then this function always returns @c NULL and //! error value remains the same. ASMJIT_API virtual void* make(); //! @brief Method that will emit everything to @c Assembler instance @a a. ASMJIT_API virtual void serialize(Assembler& a); // -------------------------------------------------------------------------- // [Data] // -------------------------------------------------------------------------- //! @brief Get target from label @a id. inline X86CompilerTarget* _getTarget(uint32_t id) { ASMJIT_ASSERT((id & kOperandIdTypeMask) == kOperandIdTypeLabel); return reinterpret_cast(_targets[id & kOperandIdValueMask]); } // -------------------------------------------------------------------------- // [Embed] // -------------------------------------------------------------------------- //! @brief Add 8-bit integer data to the instuction stream. inline void db(uint8_t x) { embed(&x, 1); } //! @brief Add 16-bit integer data to the instuction stream. inline void dw(uint16_t x) { embed(&x, 2); } //! @brief Add 32-bit integer data to the instuction stream. inline void dd(uint32_t x) { embed(&x, 4); } //! @brief Add 64-bit integer data to the instuction stream. inline void dq(uint64_t x) { embed(&x, 8); } //! @brief Add 8-bit integer data to the instuction stream. inline void dint8(int8_t x) { embed(&x, sizeof(int8_t)); } //! @brief Add 8-bit integer data to the instuction stream. inline void duint8(uint8_t x) { embed(&x, sizeof(uint8_t)); } //! @brief Add 16-bit integer data to the instuction stream. inline void dint16(int16_t x) { embed(&x, sizeof(int16_t)); } //! @brief Add 16-bit integer data to the instuction stream. inline void duint16(uint16_t x) { embed(&x, sizeof(uint16_t)); } //! @brief Add 32-bit integer data to the instuction stream. inline void dint32(int32_t x) { embed(&x, sizeof(int32_t)); } //! @brief Add 32-bit integer data to the instuction stream. inline void duint32(uint32_t x) { embed(&x, sizeof(uint32_t)); } //! @brief Add 64-bit integer data to the instuction stream. inline void dint64(int64_t x) { embed(&x, sizeof(int64_t)); } //! @brief Add 64-bit integer data to the instuction stream. inline void duint64(uint64_t x) { embed(&x, sizeof(uint64_t)); } //! @brief Add system-integer data to the instuction stream. inline void dintptr(intptr_t x) { embed(&x, sizeof(intptr_t)); } //! @brief Add system-integer data to the instuction stream. inline void duintptr(uintptr_t x) { embed(&x, sizeof(uintptr_t)); } //! @brief Add float data to the instuction stream. inline void dfloat(float x) { embed(&x, sizeof(float)); } //! @brief Add double data to the instuction stream. inline void ddouble(double x) { embed(&x, sizeof(double)); } //! @brief Add pointer data to the instuction stream. inline void dptr(void* x) { embed(&x, sizeof(void*)); } //! @brief Add MM data to the instuction stream. inline void dmm(const MmData& x) { embed(&x, sizeof(MmData)); } //! @brief Add XMM data to the instuction stream. inline void dxmm(const XmmData& x) { embed(&x, sizeof(XmmData)); } //! @brief Add data to the instuction stream. inline void data(const void* data, size_t size) { embed(data, size); } //! @brief Add data in a given structure instance to the instuction stream. template inline void dstruct(const T& x) { embed(&x, sizeof(T)); } // -------------------------------------------------------------------------- // [Custom Instructions] // -------------------------------------------------------------------------- // These emitters are used by custom compiler code (register alloc / spill, // prolog / epilog generator, ...). inline void emit(uint32_t code) { _emitInstruction(code); } inline void emit(uint32_t code, const Operand& o0) { _emitInstruction(code, &o0); } inline void emit(uint32_t code, const Operand& o0, const Operand& o1) { _emitInstruction(code, &o0, &o1); } inline void emit(uint32_t code, const Operand& o0, const Operand& o1, const Operand& o2) { _emitInstruction(code, &o0, &o1, &o2); } // -------------------------------------------------------------------------- // [X86 Instructions] // -------------------------------------------------------------------------- //! @brief Add with Carry. inline void adc(const GpVar& dst, const GpVar& src) { _emitInstruction(kX86InstAdc, &dst, &src); } //! @brief Add with Carry. inline void adc(const GpVar& dst, const Mem& src) { _emitInstruction(kX86InstAdc, &dst, &src); } //! @brief Add with Carry. inline void adc(const GpVar& dst, const Imm& src) { _emitInstruction(kX86InstAdc, &dst, &src); } //! @brief Add with Carry. inline void adc(const Mem& dst, const GpVar& src) { _emitInstruction(kX86InstAdc, &dst, &src); } //! @brief Add with Carry. inline void adc(const Mem& dst, const Imm& src) { _emitInstruction(kX86InstAdc, &dst, &src); } //! @brief Add. inline void add(const GpVar& dst, const GpVar& src) { _emitInstruction(kX86InstAdd, &dst, &src); } //! @brief Add. inline void add(const GpVar& dst, const Mem& src) { _emitInstruction(kX86InstAdd, &dst, &src); } //! @brief Add. inline void add(const GpVar& dst, const Imm& src) { _emitInstruction(kX86InstAdd, &dst, &src); } //! @brief Add. inline void add(const Mem& dst, const GpVar& src) { _emitInstruction(kX86InstAdd, &dst, &src); } //! @brief Add. inline void add(const Mem& dst, const Imm& src) { _emitInstruction(kX86InstAdd, &dst, &src); } //! @brief Logical And. inline void and_(const GpVar& dst, const GpVar& src) { _emitInstruction(kX86InstAnd, &dst, &src); } //! @brief Logical And. inline void and_(const GpVar& dst, const Mem& src) { _emitInstruction(kX86InstAnd, &dst, &src); } //! @brief Logical And. inline void and_(const GpVar& dst, const Imm& src) { _emitInstruction(kX86InstAnd, &dst, &src); } //! @brief Logical And. inline void and_(const Mem& dst, const GpVar& src) { _emitInstruction(kX86InstAnd, &dst, &src); } //! @brief Logical And. inline void and_(const Mem& dst, const Imm& src) { _emitInstruction(kX86InstAnd, &dst, &src); } //! @brief Bit Scan Forward. inline void bsf(const GpVar& dst, const GpVar& src) { ASMJIT_ASSERT(!dst.isGpb()); _emitInstruction(kX86InstBsf, &dst, &src); } //! @brief Bit Scan Forward. inline void bsf(const GpVar& dst, const Mem& src) { ASMJIT_ASSERT(!dst.isGpb()); _emitInstruction(kX86InstBsf, &dst, &src); } //! @brief Bit Scan Reverse. inline void bsr(const GpVar& dst, const GpVar& src) { ASMJIT_ASSERT(!dst.isGpb()); _emitInstruction(kX86InstBsr, &dst, &src); } //! @brief Bit Scan Reverse. inline void bsr(const GpVar& dst, const Mem& src) { ASMJIT_ASSERT(!dst.isGpb()); _emitInstruction(kX86InstBsr, &dst, &src); } //! @brief Byte swap (32-bit or 64-bit registers only) (i486). inline void bswap(const GpVar& dst) { // ASMJIT_ASSERT(dst.getRegType() == kX86RegGPD || dst.getRegType() == kX86RegGPQ); _emitInstruction(kX86InstBSwap, &dst); } //! @brief Bit test. inline void bt(const GpVar& dst, const GpVar& src) { _emitInstruction(kX86InstBt, &dst, &src); } //! @brief Bit test. inline void bt(const GpVar& dst, const Imm& src) { _emitInstruction(kX86InstBt, &dst, &src); } //! @brief Bit test. inline void bt(const Mem& dst, const GpVar& src) { _emitInstruction(kX86InstBt, &dst, &src); } //! @brief Bit test. inline void bt(const Mem& dst, const Imm& src) { _emitInstruction(kX86InstBt, &dst, &src); } //! @brief Bit test and complement. inline void btc(const GpVar& dst, const GpVar& src) { _emitInstruction(kX86InstBtc, &dst, &src); } //! @brief Bit test and complement. inline void btc(const GpVar& dst, const Imm& src) { _emitInstruction(kX86InstBtc, &dst, &src); } //! @brief Bit test and complement. inline void btc(const Mem& dst, const GpVar& src) { _emitInstruction(kX86InstBtc, &dst, &src); } //! @brief Bit test and complement. inline void btc(const Mem& dst, const Imm& src) { _emitInstruction(kX86InstBtc, &dst, &src); } //! @brief Bit test and reset. inline void btr(const GpVar& dst, const GpVar& src) { _emitInstruction(kX86InstBtr, &dst, &src); } //! @brief Bit test and reset. inline void btr(const GpVar& dst, const Imm& src) { _emitInstruction(kX86InstBtr, &dst, &src); } //! @brief Bit test and reset. inline void btr(const Mem& dst, const GpVar& src) { _emitInstruction(kX86InstBtr, &dst, &src); } //! @brief Bit test and reset. inline void btr(const Mem& dst, const Imm& src) { _emitInstruction(kX86InstBtr, &dst, &src); } //! @brief Bit test and set. inline void bts(const GpVar& dst, const GpVar& src) { _emitInstruction(kX86InstBts, &dst, &src); } //! @brief Bit test and set. inline void bts(const GpVar& dst, const Imm& src) { _emitInstruction(kX86InstBts, &dst, &src); } //! @brief Bit test and set. inline void bts(const Mem& dst, const GpVar& src) { _emitInstruction(kX86InstBts, &dst, &src); } //! @brief Bit test and set. inline void bts(const Mem& dst, const Imm& src) { _emitInstruction(kX86InstBts, &dst, &src); } //! @brief Call Procedure. inline X86CompilerFuncCall* call(const GpVar& dst) { return _emitCall(&dst); } //! @brief Call Procedure. inline X86CompilerFuncCall* call(const Mem& dst) { return _emitCall(&dst); } //! @brief Call Procedure. inline X86CompilerFuncCall* call(const Imm& dst) { return _emitCall(&dst); } //! @brief Call Procedure. //! @overload inline X86CompilerFuncCall* call(void* dst) { Imm imm((sysint_t)dst); return _emitCall(&imm); } //! @brief Call Procedure. inline X86CompilerFuncCall* call(const Label& label) { return _emitCall(&label); } //! @brief Convert Byte to Word (Sign Extend). inline void cbw(const GpVar& dst) { _emitInstruction(kX86InstCbw, &dst); } //! @brief Convert Word to DWord (Sign Extend). inline void cwd(const GpVar& dst, const GpVar& src) { _emitInstruction(kX86InstCwd, &dst, &src); } //! @brief Convert Word to DWord (Sign Extend). inline void cwde(const GpVar& dst) { _emitInstruction(kX86InstCwde, &dst); } //! @brief Convert Word to DWord (Sign Extend). inline void cdq(const GpVar& dst, const GpVar& src) { _emitInstruction(kX86InstCdq, &dst, &src); } #if defined(ASMJIT_X64) //! @brief Convert DWord to QWord (Sign Extend). inline void cdqe(const GpVar& dst) { _emitInstruction(kX86InstCdqe, &dst); } #endif // ASMJIT_X64 #if defined(ASMJIT_X64) //! @brief Convert QWord to DQWord (Sign Extend). inline void cqo(const GpVar& dst, const GpVar& src) { _emitInstruction(kX86InstCqo, &dst, &src); } #endif // ASMJIT_X64 //! @brief Clear Carry flag //! //! This instruction clears the CF flag in the EFLAGS register. inline void clc() { _emitInstruction(kX86InstClc); } //! @brief Clear Direction flag //! //! This instruction clears the DF flag in the EFLAGS register. inline void cld() { _emitInstruction(kX86InstCld); } //! @brief Complement Carry Flag. //! //! This instruction complements the CF flag in the EFLAGS register. //! (CF = NOT CF) inline void cmc() { _emitInstruction(kX86InstCmc); } //! @brief Conditional Move. inline void cmov(kX86Cond cc, const GpVar& dst, const GpVar& src) { _emitInstruction(X86Util::getCMovccInstFromCond(cc), &dst, &src); } //! @brief Conditional Move. inline void cmov(kX86Cond cc, const GpVar& dst, const Mem& src) { _emitInstruction(X86Util::getCMovccInstFromCond(cc), &dst, &src); } //! @brief Conditional Move. inline void cmova (const GpVar& dst, const GpVar& src) { _emitInstruction(kX86InstCMovA , &dst, &src); } //! @brief Conditional Move. inline void cmova (const GpVar& dst, const Mem& src) { _emitInstruction(kX86InstCMovA , &dst, &src); } //! @brief Conditional Move. inline void cmovae (const GpVar& dst, const GpVar& src) { _emitInstruction(kX86InstCMovAE , &dst, &src); } //! @brief Conditional Move. inline void cmovae (const GpVar& dst, const Mem& src) { _emitInstruction(kX86InstCMovAE , &dst, &src); } //! @brief Conditional Move. inline void cmovb (const GpVar& dst, const GpVar& src) { _emitInstruction(kX86InstCMovB , &dst, &src); } //! @brief Conditional Move. inline void cmovb (const GpVar& dst, const Mem& src) { _emitInstruction(kX86InstCMovB , &dst, &src); } //! @brief Conditional Move. inline void cmovbe (const GpVar& dst, const GpVar& src) { _emitInstruction(kX86InstCMovBE , &dst, &src); } //! @brief Conditional Move. inline void cmovbe (const GpVar& dst, const Mem& src) { _emitInstruction(kX86InstCMovBE , &dst, &src); } //! @brief Conditional Move. inline void cmovc (const GpVar& dst, const GpVar& src) { _emitInstruction(kX86InstCMovC , &dst, &src); } //! @brief Conditional Move. inline void cmovc (const GpVar& dst, const Mem& src) { _emitInstruction(kX86InstCMovC , &dst, &src); } //! @brief Conditional Move. inline void cmove (const GpVar& dst, const GpVar& src) { _emitInstruction(kX86InstCMovE , &dst, &src); } //! @brief Conditional Move. inline void cmove (const GpVar& dst, const Mem& src) { _emitInstruction(kX86InstCMovE , &dst, &src); } //! @brief Conditional Move. inline void cmovg (const GpVar& dst, const GpVar& src) { _emitInstruction(kX86InstCMovG , &dst, &src); } //! @brief Conditional Move. inline void cmovg (const GpVar& dst, const Mem& src) { _emitInstruction(kX86InstCMovG , &dst, &src); } //! @brief Conditional Move. inline void cmovge (const GpVar& dst, const GpVar& src) { _emitInstruction(kX86InstCMovGE , &dst, &src); } //! @brief Conditional Move. inline void cmovge (const GpVar& dst, const Mem& src) { _emitInstruction(kX86InstCMovGE , &dst, &src); } //! @brief Conditional Move. inline void cmovl (const GpVar& dst, const GpVar& src) { _emitInstruction(kX86InstCMovL , &dst, &src); } //! @brief Conditional Move. inline void cmovl (const GpVar& dst, const Mem& src) { _emitInstruction(kX86InstCMovL , &dst, &src); } //! @brief Conditional Move. inline void cmovle (const GpVar& dst, const GpVar& src) { _emitInstruction(kX86InstCMovLE , &dst, &src); } //! @brief Conditional Move. inline void cmovle (const GpVar& dst, const Mem& src) { _emitInstruction(kX86InstCMovLE , &dst, &src); } //! @brief Conditional Move. inline void cmovna (const GpVar& dst, const GpVar& src) { _emitInstruction(kX86InstCMovNA , &dst, &src); } //! @brief Conditional Move. inline void cmovna (const GpVar& dst, const Mem& src) { _emitInstruction(kX86InstCMovNA , &dst, &src); } //! @brief Conditional Move. inline void cmovnae(const GpVar& dst, const GpVar& src) { _emitInstruction(kX86InstCMovNAE, &dst, &src); } //! @brief Conditional Move. inline void cmovnae(const GpVar& dst, const Mem& src) { _emitInstruction(kX86InstCMovNAE, &dst, &src); } //! @brief Conditional Move. inline void cmovnb (const GpVar& dst, const GpVar& src) { _emitInstruction(kX86InstCMovNB , &dst, &src); } //! @brief Conditional Move. inline void cmovnb (const GpVar& dst, const Mem& src) { _emitInstruction(kX86InstCMovNB , &dst, &src); } //! @brief Conditional Move. inline void cmovnbe(const GpVar& dst, const GpVar& src) { _emitInstruction(kX86InstCMovNBE, &dst, &src); } //! @brief Conditional Move. inline void cmovnbe(const GpVar& dst, const Mem& src) { _emitInstruction(kX86InstCMovNBE, &dst, &src); } //! @brief Conditional Move. inline void cmovnc (const GpVar& dst, const GpVar& src) { _emitInstruction(kX86InstCMovNC , &dst, &src); } //! @brief Conditional Move. inline void cmovnc (const GpVar& dst, const Mem& src) { _emitInstruction(kX86InstCMovNC , &dst, &src); } //! @brief Conditional Move. inline void cmovne (const GpVar& dst, const GpVar& src) { _emitInstruction(kX86InstCMovNE , &dst, &src); } //! @brief Conditional Move. inline void cmovne (const GpVar& dst, const Mem& src) { _emitInstruction(kX86InstCMovNE , &dst, &src); } //! @brief Conditional Move. inline void cmovng (const GpVar& dst, const GpVar& src) { _emitInstruction(kX86InstCMovNG , &dst, &src); } //! @brief Conditional Move. inline void cmovng (const GpVar& dst, const Mem& src) { _emitInstruction(kX86InstCMovNG , &dst, &src); } //! @brief Conditional Move. inline void cmovnge(const GpVar& dst, const GpVar& src) { _emitInstruction(kX86InstCMovNGE, &dst, &src); } //! @brief Conditional Move. inline void cmovnge(const GpVar& dst, const Mem& src) { _emitInstruction(kX86InstCMovNGE, &dst, &src); } //! @brief Conditional Move. inline void cmovnl (const GpVar& dst, const GpVar& src) { _emitInstruction(kX86InstCMovNL , &dst, &src); } //! @brief Conditional Move. inline void cmovnl (const GpVar& dst, const Mem& src) { _emitInstruction(kX86InstCMovNL , &dst, &src); } //! @brief Conditional Move. inline void cmovnle(const GpVar& dst, const GpVar& src) { _emitInstruction(kX86InstCMovNLE, &dst, &src); } //! @brief Conditional Move. inline void cmovnle(const GpVar& dst, const Mem& src) { _emitInstruction(kX86InstCMovNLE, &dst, &src); } //! @brief Conditional Move. inline void cmovno (const GpVar& dst, const GpVar& src) { _emitInstruction(kX86InstCMovNO , &dst, &src); } //! @brief Conditional Move. inline void cmovno (const GpVar& dst, const Mem& src) { _emitInstruction(kX86InstCMovNO , &dst, &src); } //! @brief Conditional Move. inline void cmovnp (const GpVar& dst, const GpVar& src) { _emitInstruction(kX86InstCMovNP , &dst, &src); } //! @brief Conditional Move. inline void cmovnp (const GpVar& dst, const Mem& src) { _emitInstruction(kX86InstCMovNP , &dst, &src); } //! @brief Conditional Move. inline void cmovns (const GpVar& dst, const GpVar& src) { _emitInstruction(kX86InstCMovNS , &dst, &src); } //! @brief Conditional Move. inline void cmovns (const GpVar& dst, const Mem& src) { _emitInstruction(kX86InstCMovNS , &dst, &src); } //! @brief Conditional Move. inline void cmovnz (const GpVar& dst, const GpVar& src) { _emitInstruction(kX86InstCMovNZ , &dst, &src); } //! @brief Conditional Move. inline void cmovnz (const GpVar& dst, const Mem& src) { _emitInstruction(kX86InstCMovNZ , &dst, &src); } //! @brief Conditional Move. inline void cmovo (const GpVar& dst, const GpVar& src) { _emitInstruction(kX86InstCMovO , &dst, &src); } //! @brief Conditional Move. inline void cmovo (const GpVar& dst, const Mem& src) { _emitInstruction(kX86InstCMovO , &dst, &src); } //! @brief Conditional Move. inline void cmovp (const GpVar& dst, const GpVar& src) { _emitInstruction(kX86InstCMovP , &dst, &src); } //! @brief Conditional Move. inline void cmovp (const GpVar& dst, const Mem& src) { _emitInstruction(kX86InstCMovP , &dst, &src); } //! @brief Conditional Move. inline void cmovpe (const GpVar& dst, const GpVar& src) { _emitInstruction(kX86InstCMovPE , &dst, &src); } //! @brief Conditional Move. inline void cmovpe (const GpVar& dst, const Mem& src) { _emitInstruction(kX86InstCMovPE , &dst, &src); } //! @brief Conditional Move. inline void cmovpo (const GpVar& dst, const GpVar& src) { _emitInstruction(kX86InstCMovPO , &dst, &src); } //! @brief Conditional Move. inline void cmovpo (const GpVar& dst, const Mem& src) { _emitInstruction(kX86InstCMovPO , &dst, &src); } //! @brief Conditional Move. inline void cmovs (const GpVar& dst, const GpVar& src) { _emitInstruction(kX86InstCMovS , &dst, &src); } //! @brief Conditional Move. inline void cmovs (const GpVar& dst, const Mem& src) { _emitInstruction(kX86InstCMovS , &dst, &src); } //! @brief Conditional Move. inline void cmovz (const GpVar& dst, const GpVar& src) { _emitInstruction(kX86InstCMovZ , &dst, &src); } //! @brief Conditional Move. inline void cmovz (const GpVar& dst, const Mem& src) { _emitInstruction(kX86InstCMovZ , &dst, &src); } //! @brief Compare Two Operands. inline void cmp(const GpVar& dst, const GpVar& src) { _emitInstruction(kX86InstCmp, &dst, &src); } //! @brief Compare Two Operands. inline void cmp(const GpVar& dst, const Mem& src) { _emitInstruction(kX86InstCmp, &dst, &src); } //! @brief Compare Two Operands. inline void cmp(const GpVar& dst, const Imm& src) { _emitInstruction(kX86InstCmp, &dst, &src); } //! @brief Compare Two Operands. inline void cmp(const Mem& dst, const GpVar& src) { _emitInstruction(kX86InstCmp, &dst, &src); } //! @brief Compare Two Operands. inline void cmp(const Mem& dst, const Imm& src) { _emitInstruction(kX86InstCmp, &dst, &src); } //! @brief Compare and Exchange (i486). inline void cmpxchg(const GpVar cmp_1_eax, const GpVar& cmp_2, const GpVar& src) { ASMJIT_ASSERT(cmp_1_eax.getId() != src.getId()); _emitInstruction(kX86InstCmpXCHG, &cmp_1_eax, &cmp_2, &src); } //! @brief Compare and Exchange (i486). inline void cmpxchg(const GpVar cmp_1_eax, const Mem& cmp_2, const GpVar& src) { ASMJIT_ASSERT(cmp_1_eax.getId() != src.getId()); _emitInstruction(kX86InstCmpXCHG, &cmp_1_eax, &cmp_2, &src); } //! @brief Compares the 64-bit value in EDX:EAX with the memory operand (Pentium). //! //! If the values are equal, then this instruction stores the 64-bit value //! in ECX:EBX into the memory operand and sets the zero flag. Otherwise, //! this instruction copies the 64-bit memory operand into the EDX:EAX //! registers and clears the zero flag. inline void cmpxchg8b( const GpVar& cmp_edx, const GpVar& cmp_eax, const GpVar& cmp_ecx, const GpVar& cmp_ebx, const Mem& dst) { ASMJIT_ASSERT(cmp_edx.getId() != cmp_eax.getId() && cmp_eax.getId() != cmp_ecx.getId() && cmp_ecx.getId() != cmp_ebx.getId()); _emitInstruction(kX86InstCmpXCHG8B, &cmp_edx, &cmp_eax, &cmp_ecx, &cmp_ebx, &dst); } #if defined(ASMJIT_X64) //! @brief Compares the 128-bit value in RDX:RAX with the memory operand (X64). //! //! If the values are equal, then this instruction stores the 128-bit value //! in RCX:RBX into the memory operand and sets the zero flag. Otherwise, //! this instruction copies the 128-bit memory operand into the RDX:RAX //! registers and clears the zero flag. inline void cmpxchg16b( const GpVar& cmp_edx, const GpVar& cmp_eax, const GpVar& cmp_ecx, const GpVar& cmp_ebx, const Mem& dst) { ASMJIT_ASSERT(cmp_edx.getId() != cmp_eax.getId() && cmp_eax.getId() != cmp_ecx.getId() && cmp_ecx.getId() != cmp_ebx.getId()); _emitInstruction(kX86InstCmpXCHG16B, &cmp_edx, &cmp_eax, &cmp_ecx, &cmp_ebx, &dst); } #endif // ASMJIT_X64 //! @brief CPU Identification (i486). inline void cpuid( const GpVar& inout_eax, const GpVar& out_ebx, const GpVar& out_ecx, const GpVar& out_edx) { // Destination variables must be different. ASMJIT_ASSERT(inout_eax.getId() != out_ebx.getId() && out_ebx.getId() != out_ecx.getId() && out_ecx.getId() != out_edx.getId()); _emitInstruction(kX86InstCpuId, &inout_eax, &out_ebx, &out_ecx, &out_edx); } #if defined(ASMJIT_X86) inline void daa(const GpVar& dst) { _emitInstruction(kX86InstDaa, &dst); } #endif // ASMJIT_X86 #if defined(ASMJIT_X86) inline void das(const GpVar& dst) { _emitInstruction(kX86InstDas, &dst); } #endif // ASMJIT_X86 //! @brief Decrement by 1. //! @note This instruction can be slower than sub(dst, 1) inline void dec(const GpVar& dst) { _emitInstruction(kX86InstDec, &dst); } //! @brief Decrement by 1. //! @note This instruction can be slower than sub(dst, 1) inline void dec(const Mem& dst) { _emitInstruction(kX86InstDec, &dst); } //! @brief Unsigned divide. //! //! This instruction divides (unsigned) the value in the AL, AX, or EAX //! register by the source operand and stores the result in the AX, //! DX:AX, or EDX:EAX registers. inline void div(const GpVar& dst_rem, const GpVar& dst_quot, const GpVar& src) { // Destination variables must be different. ASMJIT_ASSERT(dst_rem.getId() != dst_quot.getId()); _emitInstruction(kX86InstDiv, &dst_rem, &dst_quot, &src); } //! @brief Unsigned divide. //! @overload inline void div(const GpVar& dst_rem, const GpVar& dst_quot, const Mem& src) { // Destination variables must be different. ASMJIT_ASSERT(dst_rem.getId() != dst_quot.getId()); _emitInstruction(kX86InstDiv, &dst_rem, &dst_quot, &src); } #if ASMJIT_NOT_SUPPORTED_BY_COMPILER //! @brief Make Stack Frame for Procedure Parameters. inline void enter(const Imm& imm16, const Imm& imm8) { _emitInstruction(kX86InstEnter, &imm16, &imm8); } #endif // ASMJIT_NOT_SUPPORTED_BY_COMPILER //! @brief Signed divide. //! //! This instruction divides (signed) the value in the AL, AX, or EAX //! register by the source operand and stores the result in the AX, //! DX:AX, or EDX:EAX registers. inline void idiv(const GpVar& dst_rem, const GpVar& dst_quot, const GpVar& src) { // Destination variables must be different. ASMJIT_ASSERT(dst_rem.getId() != dst_quot.getId()); _emitInstruction(kX86InstIDiv, &dst_rem, &dst_quot, &src); } //! @brief Signed divide. //! @overload inline void idiv(const GpVar& dst_rem, const GpVar& dst_quot, const Mem& src) { // Destination variables must be different. ASMJIT_ASSERT(dst_rem.getId() != dst_quot.getId()); _emitInstruction(kX86InstIDiv, &dst_rem, &dst_quot, &src); } //! @brief Signed multiply. //! //! [dst_lo:dst_hi] = dst_hi * src. inline void imul(const GpVar& dst_hi, const GpVar& dst_lo, const GpVar& src) { // Destination variables must be different. ASMJIT_ASSERT(dst_hi.getId() != dst_lo.getId()); _emitInstruction(kX86InstIMul, &dst_hi, &dst_lo, &src); } //! @overload inline void imul(const GpVar& dst_hi, const GpVar& dst_lo, const Mem& src) { // Destination variables must be different. ASMJIT_ASSERT(dst_hi.getId() != dst_lo.getId()); _emitInstruction(kX86InstIMul, &dst_hi, &dst_lo, &src); } //! @brief Signed multiply. //! //! Destination operand (the first operand) is multiplied by the source //! operand (second operand). The destination operand is a general-purpose //! register and the source operand is an immediate value, a general-purpose //! register, or a memory location. The product is then stored in the //! destination operand location. inline void imul(const GpVar& dst, const GpVar& src) { _emitInstruction(kX86InstIMul, &dst, &src); } //! @brief Signed multiply. //! @overload inline void imul(const GpVar& dst, const Mem& src) { _emitInstruction(kX86InstIMul, &dst, &src); } //! @brief Signed multiply. //! @overload inline void imul(const GpVar& dst, const Imm& src) { _emitInstruction(kX86InstIMul, &dst, &src); } //! @brief Signed multiply. //! //! source operand (which can be a general-purpose register or a memory //! location) is multiplied by the second source operand (an immediate //! value). The product is then stored in the destination operand //! (a general-purpose register). inline void imul(const GpVar& dst, const GpVar& src, const Imm& imm) { _emitInstruction(kX86InstIMul, &dst, &src, &imm); } //! @overload inline void imul(const GpVar& dst, const Mem& src, const Imm& imm) { _emitInstruction(kX86InstIMul, &dst, &src, &imm); } //! @brief Increment by 1. //! @note This instruction can be slower than add(dst, 1) inline void inc(const GpVar& dst) { _emitInstruction(kX86InstInc, &dst); } //! @brief Increment by 1. //! @note This instruction can be slower than add(dst, 1) inline void inc(const Mem& dst) { _emitInstruction(kX86InstInc, &dst); } //! @brief Interrupt 3 - trap to debugger. inline void int3() { _emitInstruction(kX86InstInt3); } //! @brief Jump to label @a label if condition @a cc is met. //! //! This instruction checks the state of one or more of the status flags in //! the EFLAGS register (CF, OF, PF, SF, and ZF) and, if the flags are in the //! specified state (condition), performs a jump to the target instruction //! specified by the destination operand. A condition code (cc) is associated //! with each instruction to indicate the condition being tested for. If the //! condition is not satisfied, the jump is not performed and execution //! continues with the instruction following the Jcc instruction. inline void j(kX86Cond cc, const Label& label, uint32_t hint = kCondHintNone) { _emitJcc(X86Util::getJccInstFromCond(cc), &label, hint); } //! @brief Jump to label @a label if condition is met. inline void ja (const Label& label, uint32_t hint = kCondHintNone) { _emitJcc(kX86InstJA , &label, hint); } //! @brief Jump to label @a label if condition is met. inline void jae (const Label& label, uint32_t hint = kCondHintNone) { _emitJcc(kX86InstJAE , &label, hint); } //! @brief Jump to label @a label if condition is met. inline void jb (const Label& label, uint32_t hint = kCondHintNone) { _emitJcc(kX86InstJB , &label, hint); } //! @brief Jump to label @a label if condition is met. inline void jbe (const Label& label, uint32_t hint = kCondHintNone) { _emitJcc(kX86InstJBE , &label, hint); } //! @brief Jump to label @a label if condition is met. inline void jc (const Label& label, uint32_t hint = kCondHintNone) { _emitJcc(kX86InstJC , &label, hint); } //! @brief Jump to label @a label if condition is met. inline void je (const Label& label, uint32_t hint = kCondHintNone) { _emitJcc(kX86InstJE , &label, hint); } //! @brief Jump to label @a label if condition is met. inline void jg (const Label& label, uint32_t hint = kCondHintNone) { _emitJcc(kX86InstJG , &label, hint); } //! @brief Jump to label @a label if condition is met. inline void jge (const Label& label, uint32_t hint = kCondHintNone) { _emitJcc(kX86InstJGE , &label, hint); } //! @brief Jump to label @a label if condition is met. inline void jl (const Label& label, uint32_t hint = kCondHintNone) { _emitJcc(kX86InstJL , &label, hint); } //! @brief Jump to label @a label if condition is met. inline void jle (const Label& label, uint32_t hint = kCondHintNone) { _emitJcc(kX86InstJLE , &label, hint); } //! @brief Jump to label @a label if condition is met. inline void jna (const Label& label, uint32_t hint = kCondHintNone) { _emitJcc(kX86InstJNA , &label, hint); } //! @brief Jump to label @a label if condition is met. inline void jnae(const Label& label, uint32_t hint = kCondHintNone) { _emitJcc(kX86InstJNAE, &label, hint); } //! @brief Jump to label @a label if condition is met. inline void jnb (const Label& label, uint32_t hint = kCondHintNone) { _emitJcc(kX86InstJNB , &label, hint); } //! @brief Jump to label @a label if condition is met. inline void jnbe(const Label& label, uint32_t hint = kCondHintNone) { _emitJcc(kX86InstJNBE, &label, hint); } //! @brief Jump to label @a label if condition is met. inline void jnc (const Label& label, uint32_t hint = kCondHintNone) { _emitJcc(kX86InstJNC , &label, hint); } //! @brief Jump to label @a label if condition is met. inline void jne (const Label& label, uint32_t hint = kCondHintNone) { _emitJcc(kX86InstJNE , &label, hint); } //! @brief Jump to label @a label if condition is met. inline void jng (const Label& label, uint32_t hint = kCondHintNone) { _emitJcc(kX86InstJNG , &label, hint); } //! @brief Jump to label @a label if condition is met. inline void jnge(const Label& label, uint32_t hint = kCondHintNone) { _emitJcc(kX86InstJNGE, &label, hint); } //! @brief Jump to label @a label if condition is met. inline void jnl (const Label& label, uint32_t hint = kCondHintNone) { _emitJcc(kX86InstJNL , &label, hint); } //! @brief Jump to label @a label if condition is met. inline void jnle(const Label& label, uint32_t hint = kCondHintNone) { _emitJcc(kX86InstJNLE, &label, hint); } //! @brief Jump to label @a label if condition is met. inline void jno (const Label& label, uint32_t hint = kCondHintNone) { _emitJcc(kX86InstJNO , &label, hint); } //! @brief Jump to label @a label if condition is met. inline void jnp (const Label& label, uint32_t hint = kCondHintNone) { _emitJcc(kX86InstJNP , &label, hint); } //! @brief Jump to label @a label if condition is met. inline void jns (const Label& label, uint32_t hint = kCondHintNone) { _emitJcc(kX86InstJNS , &label, hint); } //! @brief Jump to label @a label if condition is met. inline void jnz (const Label& label, uint32_t hint = kCondHintNone) { _emitJcc(kX86InstJNZ , &label, hint); } //! @brief Jump to label @a label if condition is met. inline void jo (const Label& label, uint32_t hint = kCondHintNone) { _emitJcc(kX86InstJO , &label, hint); } //! @brief Jump to label @a label if condition is met. inline void jp (const Label& label, uint32_t hint = kCondHintNone) { _emitJcc(kX86InstJP , &label, hint); } //! @brief Jump to label @a label if condition is met. inline void jpe (const Label& label, uint32_t hint = kCondHintNone) { _emitJcc(kX86InstJPE , &label, hint); } //! @brief Jump to label @a label if condition is met. inline void jpo (const Label& label, uint32_t hint = kCondHintNone) { _emitJcc(kX86InstJPO , &label, hint); } //! @brief Jump to label @a label if condition is met. inline void js (const Label& label, uint32_t hint = kCondHintNone) { _emitJcc(kX86InstJS , &label, hint); } //! @brief Jump to label @a label if condition is met. inline void jz (const Label& label, uint32_t hint = kCondHintNone) { _emitJcc(kX86InstJZ , &label, hint); } //! @brief Jump. //! @overload inline void jmp(const GpVar& dst) { _emitInstruction(kX86InstJmp, &dst); } //! @brief Jump. //! @overload inline void jmp(const Mem& dst) { _emitInstruction(kX86InstJmp, &dst); } //! @brief Jump. //! @overload inline void jmp(const Imm& dst) { _emitInstruction(kX86InstJmp, &dst); } //! @brief Jump. //! @overload inline void jmp(void* dst) { Imm imm((sysint_t)dst); _emitInstruction(kX86InstJmp, &imm); } //! @brief Jump. //! //! This instruction transfers program control to a different point //! in the instruction stream without recording return information. //! The destination (target) operand specifies the label of the //! instruction being jumped to. inline void jmp(const Label& label) { _emitInstruction(kX86InstJmp, &label); } //! @brief Load Effective Address //! //! This instruction computes the effective address of the second //! operand (the source operand) and stores it in the first operand //! (destination operand). The source operand is a memory address //! (offset part) specified with one of the processors addressing modes. //! The destination operand is a general-purpose register. inline void lea(const GpVar& dst, const Mem& src) { _emitInstruction(kX86InstLea, &dst, &src); } #if ASMJIT_NOT_SUPPORTED_BY_COMPILER //! @brief High Level Procedure Exit. inline void leave() { _emitInstruction(kX86InstLeave); } #endif // ASMJIT_NOT_SUPPORTED_BY_COMPILER //! @brief Move. //! //! This instruction copies the second operand (source operand) to the first //! operand (destination operand). The source operand can be an immediate //! value, general-purpose register, segment register, or memory location. //! The destination register can be a general-purpose register, segment //! register, or memory location. Both operands must be the same size, which //! can be a byte, a word, or a DWORD. //! //! @note To move MMX or SSE registers to/from GP registers or memory, use //! corresponding functions: @c movd(), @c movq(), etc. Passing MMX or SSE //! registers to @c mov() is illegal. inline void mov(const GpVar& dst, const GpVar& src) { _emitInstruction(kX86InstMov, &dst, &src); } //! @brief Move. //! @overload inline void mov(const GpVar& dst, const Mem& src) { _emitInstruction(kX86InstMov, &dst, &src); } //! @brief Move. //! @overload inline void mov(const GpVar& dst, const Imm& src) { _emitInstruction(kX86InstMov, &dst, &src); } //! @brief Move. //! @overload inline void mov(const Mem& dst, const GpVar& src) { _emitInstruction(kX86InstMov, &dst, &src); } //! @brief Move. //! @overload inline void mov(const Mem& dst, const Imm& src) { _emitInstruction(kX86InstMov, &dst, &src); } //! @brief Move from segment register. //! @overload. inline void mov(const GpVar& dst, const SegmentReg& src) { _emitInstruction(kX86InstMov, &dst, &src); } //! @brief Move from segment register. //! @overload. inline void mov(const Mem& dst, const SegmentReg& src) { _emitInstruction(kX86InstMov, &dst, &src); } //! @brief Move to segment register. //! @overload. inline void mov(const SegmentReg& dst, const GpVar& src) { _emitInstruction(kX86InstMov, &dst, &src); } //! @brief Move to segment register. //! @overload. inline void mov(const SegmentReg& dst, const Mem& src) { _emitInstruction(kX86InstMov, &dst, &src); } //! @brief Move byte, word, dword or qword from absolute address @a src to //! AL, AX, EAX or RAX register. inline void mov_ptr(const GpVar& dst, void* src) { Imm imm((sysint_t)src); _emitInstruction(kX86InstMovPtr, &dst, &imm); } //! @brief Move byte, word, dword or qword from AL, AX, EAX or RAX register //! to absolute address @a dst. inline void mov_ptr(void* dst, const GpVar& src) { Imm imm((sysint_t)dst); _emitInstruction(kX86InstMovPtr, &imm, &src); } //! @brief Move with Sign-Extension. //! //! This instruction copies the contents of the source operand (register //! or memory location) to the destination operand (register) and sign //! extends the value to 16, 32 or 64-bits. //! //! @sa movsxd(). void movsx(const GpVar& dst, const GpVar& src) { _emitInstruction(kX86InstMovSX, &dst, &src); } //! @brief Move with Sign-Extension. //! @overload void movsx(const GpVar& dst, const Mem& src) { _emitInstruction(kX86InstMovSX, &dst, &src); } #if defined(ASMJIT_X64) //! @brief Move DWord to QWord with sign-extension. inline void movsxd(const GpVar& dst, const GpVar& src) { _emitInstruction(kX86InstMovSXD, &dst, &src); } //! @brief Move DWord to QWord with sign-extension. //! @overload inline void movsxd(const GpVar& dst, const Mem& src) { _emitInstruction(kX86InstMovSXD, &dst, &src); } #endif // ASMJIT_X64 //! @brief Move with Zero-Extend. //! //! This instruction copies the contents of the source operand (register //! or memory location) to the destination operand (register) and zero //! extends the value to 16 or 32-bits. The size of the converted value //! depends on the operand-size attribute. inline void movzx(const GpVar& dst, const GpVar& src) { _emitInstruction(kX86InstMovZX, &dst, &src); } //! @brief Move with Zero-Extend. //! @brief Overload inline void movzx(const GpVar& dst, const Mem& src) { _emitInstruction(kX86InstMovZX, &dst, &src); } //! @brief Unsigned multiply. //! //! Source operand (in a general-purpose register or memory location) //! is multiplied by the value in the AL, AX, or EAX register (depending //! on the operand size) and the product is stored in the AX, DX:AX, or //! EDX:EAX registers, respectively. inline void mul(const GpVar& dst_hi, const GpVar& dst_lo, const GpVar& src) { // Destination variables must be different. ASMJIT_ASSERT(dst_hi.getId() != dst_lo.getId()); _emitInstruction(kX86InstMul, &dst_hi, &dst_lo, &src); } //! @brief Unsigned multiply. //! @overload inline void mul(const GpVar& dst_hi, const GpVar& dst_lo, const Mem& src) { // Destination variables must be different. ASMJIT_ASSERT(dst_hi.getId() != dst_lo.getId()); _emitInstruction(kX86InstMul, &dst_hi, &dst_lo, &src); } //! @brief Two's Complement Negation. inline void neg(const GpVar& dst) { _emitInstruction(kX86InstNeg, &dst); } //! @brief Two's Complement Negation. inline void neg(const Mem& dst) { _emitInstruction(kX86InstNeg, &dst); } //! @brief No Operation. //! //! This instruction performs no operation. This instruction is a one-byte //! instruction that takes up space in the instruction stream but does not //! affect the machine context, except the EIP register. The NOP instruction //! is an alias mnemonic for the XCHG (E)AX, (E)AX instruction. inline void nop() { _emitInstruction(kX86InstNop); } //! @brief One's Complement Negation. inline void not_(const GpVar& dst) { _emitInstruction(kX86InstNot, &dst); } //! @brief One's Complement Negation. inline void not_(const Mem& dst) { _emitInstruction(kX86InstNot, &dst); } //! @brief Logical Inclusive OR. inline void or_(const GpVar& dst, const GpVar& src) { _emitInstruction(kX86InstOr, &dst, &src); } //! @brief Logical Inclusive OR. inline void or_(const GpVar& dst, const Mem& src) { _emitInstruction(kX86InstOr, &dst, &src); } //! @brief Logical Inclusive OR. inline void or_(const GpVar& dst, const Imm& src) { _emitInstruction(kX86InstOr, &dst, &src); } //! @brief Logical Inclusive OR. inline void or_(const Mem& dst, const GpVar& src) { _emitInstruction(kX86InstOr, &dst, &src); } //! @brief Logical Inclusive OR. inline void or_(const Mem& dst, const Imm& src) { _emitInstruction(kX86InstOr, &dst, &src); } //! @brief Pop a Value from the Stack. //! //! This instruction loads the value from the top of the stack to the location //! specified with the destination operand and then increments the stack pointer. //! The destination operand can be a general purpose register, memory location, //! or segment register. inline void pop(const GpVar& dst) { _emitInstruction(kX86InstPop, &dst); } inline void pop(const Mem& dst) { ASMJIT_ASSERT(dst.getSize() == 2 || dst.getSize() == sizeof(sysint_t)); _emitInstruction(kX86InstPop, &dst); } #if defined(ASMJIT_X86) //! @brief Pop All General-Purpose Registers. //! //! Pop EDI, ESI, EBP, EBX, EDX, ECX, and EAX. inline void popad() { _emitInstruction(kX86InstPopAD); } #endif // ASMJIT_X86 //! @brief Pop Stack into EFLAGS Register (32-bit or 64-bit). inline void popf() { #if defined(ASMJIT_X86) popfd(); #else popfq(); #endif } #if defined(ASMJIT_X86) //! @brief Pop Stack into EFLAGS Register (32-bit). inline void popfd() { _emitInstruction(kX86InstPopFD); } #else //! @brief Pop Stack into EFLAGS Register (64-bit). inline void popfq() { _emitInstruction(kX86InstPopFQ); } #endif //! @brief Push WORD/DWORD/QWORD Onto the Stack. //! //! @note 32-bit architecture pushed DWORD while 64-bit //! pushes QWORD. 64-bit mode not provides instruction to //! push 32-bit register/memory. inline void push(const GpVar& src) { _emitInstruction(kX86InstPush, &src); } //! @brief Push WORD/DWORD/QWORD Onto the Stack. inline void push(const Mem& src) { ASMJIT_ASSERT(src.getSize() == 2 || src.getSize() == sizeof(sysint_t)); _emitInstruction(kX86InstPush, &src); } //! @brief Push WORD/DWORD/QWORD Onto the Stack. inline void push(const Imm& src) { _emitInstruction(kX86InstPush, &src); } #if defined(ASMJIT_X86) //! @brief Push All General-Purpose Registers. //! //! Push EAX, ECX, EDX, EBX, original ESP, EBP, ESI, and EDI. inline void pushad() { _emitInstruction(kX86InstPushAD); } #endif // ASMJIT_X86 //! @brief Push EFLAGS Register (32-bit or 64-bit) onto the Stack. inline void pushf() { #if defined(ASMJIT_X86) pushfd(); #else pushfq(); #endif } #if defined(ASMJIT_X86) //! @brief Push EFLAGS Register (32-bit) onto the Stack. inline void pushfd() { _emitInstruction(kX86InstPushFD); } #else //! @brief Push EFLAGS Register (64-bit) onto the Stack. inline void pushfq() { _emitInstruction(kX86InstPushFQ); } #endif // ASMJIT_X86 //! @brief Rotate Bits Left. //! @note @a src register can be only @c cl. inline void rcl(const GpVar& dst, const GpVar& src) { _emitInstruction(kX86InstRcl, &dst, &src); } //! @brief Rotate Bits Left. inline void rcl(const GpVar& dst, const Imm& src) { _emitInstruction(kX86InstRcl, &dst, &src); } //! @brief Rotate Bits Left. //! @note @a src register can be only @c cl. inline void rcl(const Mem& dst, const GpVar& src) { _emitInstruction(kX86InstRcl, &dst, &src); } //! @brief Rotate Bits Left. inline void rcl(const Mem& dst, const Imm& src) { _emitInstruction(kX86InstRcl, &dst, &src); } //! @brief Rotate Bits Right. //! @note @a src register can be only @c cl. inline void rcr(const GpVar& dst, const GpVar& src) { _emitInstruction(kX86InstRcr, &dst, &src); } //! @brief Rotate Bits Right. inline void rcr(const GpVar& dst, const Imm& src) { _emitInstruction(kX86InstRcr, &dst, &src); } //! @brief Rotate Bits Right. //! @note @a src register can be only @c cl. inline void rcr(const Mem& dst, const GpVar& src) { _emitInstruction(kX86InstRcr, &dst, &src); } //! @brief Rotate Bits Right. inline void rcr(const Mem& dst, const Imm& src) { _emitInstruction(kX86InstRcr, &dst, &src); } //! @brief Read Time-Stamp Counter (Pentium). inline void rdtsc(const GpVar& dst_edx, const GpVar& dst_eax) { // Destination registers must be different. ASMJIT_ASSERT(dst_edx.getId() != dst_eax.getId()); _emitInstruction(kX86InstRdtsc, &dst_edx, &dst_eax); } //! @brief Read Time-Stamp Counter and Processor ID (New). inline void rdtscp(const GpVar& dst_edx, const GpVar& dst_eax, const GpVar& dst_ecx) { // Destination registers must be different. ASMJIT_ASSERT(dst_edx.getId() != dst_eax.getId() && dst_eax.getId() != dst_ecx.getId()); _emitInstruction(kX86InstRdtscP, &dst_edx, &dst_eax, &dst_ecx); } //! @brief Load ECX/RCX BYTEs from DS:[ESI/RSI] to AL. inline void rep_lodsb(const GpVar& dst_val, const GpVar& src_addr, const GpVar& cnt_ecx) { // All registers must be unique, they will be reallocated to dst=EAX,RAX, src=DS:ESI/RSI, cnt=ECX/RCX. ASMJIT_ASSERT(dst_val.getId() != src_addr.getId() && src_addr.getId() != cnt_ecx.getId()); _emitInstruction(kX86InstRepLodSB, &dst_val, &src_addr, &cnt_ecx); } //! @brief Load ECX/RCX DWORDs from DS:[ESI/RSI] to EAX. inline void rep_lodsd(const GpVar& dst_val, const GpVar& src_addr, const GpVar& cnt_ecx) { // All registers must be unique, they will be reallocated to dst=EAX,RAX, src=DS:ESI/RSI, cnt=ECX/RCX. ASMJIT_ASSERT(dst_val.getId() != src_addr.getId() && src_addr.getId() != cnt_ecx.getId()); _emitInstruction(kX86InstRepLodSD, &dst_val, &src_addr, &cnt_ecx); } #if defined(ASMJIT_X64) //! @brief Load ECX/RCX QWORDs from DS:[ESI/RSI] to RAX. inline void rep_lodsq(const GpVar& dst_val, const GpVar& src_addr, const GpVar& cnt_ecx) { // All registers must be unique, they will be reallocated to dst=EAX,RAX, src=DS:ESI/RSI, cnt=ECX/RCX. ASMJIT_ASSERT(dst_val.getId() != src_addr.getId() && src_addr.getId() != cnt_ecx.getId()); _emitInstruction(kX86InstRepLodSQ, &dst_val, &src_addr, &cnt_ecx); } #endif // ASMJIT_X64 //! @brief Load ECX/RCX WORDs from DS:[ESI/RSI] to AX. inline void rep_lodsw(const GpVar& dst_val, const GpVar& src_addr, const GpVar& cnt_ecx) { // All registers must be unique, they will be reallocated to dst=EAX,RAX, src=DS:ESI/RSI, cnt=ECX/RCX. ASMJIT_ASSERT(dst_val.getId() != src_addr.getId() && src_addr.getId() != cnt_ecx.getId()); _emitInstruction(kX86InstRepLodSW, &dst_val, &src_addr, &cnt_ecx); } //! @brief Move ECX/RCX BYTEs from DS:[ESI/RSI] to ES:[EDI/RDI]. inline void rep_movsb(const GpVar& dst_addr, const GpVar& src_addr, const GpVar& cnt_ecx) { // All registers must be unique, they will be reallocated to dst=ES:EDI,RDI, src=DS:ESI/RSI, cnt=ECX/RCX. ASMJIT_ASSERT(dst_addr.getId() != src_addr.getId() && src_addr.getId() != cnt_ecx.getId()); _emitInstruction(kX86InstRepMovSB, &dst_addr, &src_addr, &cnt_ecx); } //! @brief Move ECX/RCX DWORDs from DS:[ESI/RSI] to ES:[EDI/RDI]. inline void rep_movsd(const GpVar& dst_addr, const GpVar& src_addr, const GpVar& cnt_ecx) { // All registers must be unique, they will be reallocated to dst=ES:EDI,RDI, src=DS:ESI/RSI, cnt=ECX/RCX. ASMJIT_ASSERT(dst_addr.getId() != src_addr.getId() && src_addr.getId() != cnt_ecx.getId()); _emitInstruction(kX86InstRepMovSD, &dst_addr, &src_addr, &cnt_ecx); } #if defined(ASMJIT_X64) //! @brief Move ECX/RCX QWORDs from DS:[ESI/RSI] to ES:[EDI/RDI]. inline void rep_movsq(const GpVar& dst_addr, const GpVar& src_addr, const GpVar& cnt_ecx) { // All registers must be unique, they will be reallocated to dst=ES:EDI,RDI, src=DS:ESI/RSI, cnt=ECX/RCX. ASMJIT_ASSERT(dst_addr.getId() != src_addr.getId() && src_addr.getId() != cnt_ecx.getId()); _emitInstruction(kX86InstRepMovSQ, &dst_addr, &src_addr, &cnt_ecx); } #endif // ASMJIT_X64 //! @brief Move ECX/RCX WORDs from DS:[ESI/RSI] to ES:[EDI/RDI]. inline void rep_movsw(const GpVar& dst_addr, const GpVar& src_addr, const GpVar& cnt_ecx) { // All registers must be unique, they will be reallocated to dst=ES:EDI,RDI, src=DS:ESI/RSI, cnt=ECX/RCX. ASMJIT_ASSERT(dst_addr.getId() != src_addr.getId() && src_addr.getId() != cnt_ecx.getId()); _emitInstruction(kX86InstRepMovSW, &dst_addr, &src_addr, &cnt_ecx); } //! @brief Fill ECX/RCX BYTEs at ES:[EDI/RDI] with AL. inline void rep_stosb(const GpVar& dst_addr, const GpVar& src_val, const GpVar& cnt_ecx) { // All registers must be unique, they will be reallocated to dst=ES:EDI,RDI, src=EAX/RAX, cnt=ECX/RCX. ASMJIT_ASSERT(dst_addr.getId() != src_val.getId() && src_val.getId() != cnt_ecx.getId()); _emitInstruction(kX86InstRepStoSB, &dst_addr, &src_val, &cnt_ecx); } //! @brief Fill ECX/RCX DWORDs at ES:[EDI/RDI] with EAX. inline void rep_stosd(const GpVar& dst_addr, const GpVar& src_val, const GpVar& cnt_ecx) { // All registers must be unique, they will be reallocated to dst=ES:EDI,RDI, src=EAX/RAX, cnt=ECX/RCX. ASMJIT_ASSERT(dst_addr.getId() != src_val.getId() && src_val.getId() != cnt_ecx.getId()); _emitInstruction(kX86InstRepStoSD, &dst_addr, &src_val, &cnt_ecx); } #if defined(ASMJIT_X64) //! @brief Fill ECX/RCX QWORDs at ES:[EDI/RDI] with RAX. inline void rep_stosq(const GpVar& dst_addr, const GpVar& src_val, const GpVar& cnt_ecx) { // All registers must be unique, they will be reallocated to dst=ES:EDI,RDI, src=EAX/RAX, cnt=ECX/RCX. ASMJIT_ASSERT(dst_addr.getId() != src_val.getId() && src_val.getId() != cnt_ecx.getId()); _emitInstruction(kX86InstRepStoSQ, &dst_addr, &src_val, &cnt_ecx); } #endif // ASMJIT_X64 //! @brief Fill ECX/RCX WORDs at ES:[EDI/RDI] with AX. inline void rep_stosw(const GpVar& dst_addr, const GpVar& src_val, const GpVar& cnt_ecx) { // All registers must be unique, they will be reallocated to dst=ES:EDI,RDI, src=EAX/RAX, cnt=ECX/RCX. ASMJIT_ASSERT(dst_addr.getId() != src_val.getId() && src_val.getId() != cnt_ecx.getId()); _emitInstruction(kX86InstRepStoSW, &dst_addr, &src_val, &cnt_ecx); } //! @brief Repeated find nonmatching BYTEs in ES:[EDI/RDI] and DS:[ESI/RDI]. inline void repe_cmpsb(const GpVar& cmp1_addr, const GpVar& cmp2_addr, const GpVar& cnt_ecx) { // All registers must be unique, they will be reallocated to cmp1=ES:EDI,RDI, cmp2=ES:[EDI/RDI], cnt=ECX/RCX. ASMJIT_ASSERT(cmp1_addr.getId() != cmp2_addr.getId() && cmp2_addr.getId() != cnt_ecx.getId()); _emitInstruction(kX86InstRepECmpSB, &cmp1_addr, &cmp2_addr, &cnt_ecx); } //! @brief Repeated find nonmatching DWORDs in ES:[EDI/RDI] and DS:[ESI/RDI]. inline void repe_cmpsd(const GpVar& cmp1_addr, const GpVar& cmp2_addr, const GpVar& cnt_ecx) { // All registers must be unique, they will be reallocated to cmp1=ES:EDI,RDI, cmp2=ES:[EDI/RDI], cnt=ECX/RCX. ASMJIT_ASSERT(cmp1_addr.getId() != cmp2_addr.getId() && cmp2_addr.getId() != cnt_ecx.getId()); _emitInstruction(kX86InstRepECmpSD, &cmp1_addr, &cmp2_addr, &cnt_ecx); } #if defined(ASMJIT_X64) //! @brief Repeated find nonmatching QWORDs in ES:[EDI/RDI] and DS:[ESI/RDI]. inline void repe_cmpsq(const GpVar& cmp1_addr, const GpVar& cmp2_addr, const GpVar& cnt_ecx) { // All registers must be unique, they will be reallocated to cmp1=ES:EDI,RDI, cmp2=ES:[EDI/RDI], cnt=ECX/RCX. ASMJIT_ASSERT(cmp1_addr.getId() != cmp2_addr.getId() && cmp2_addr.getId() != cnt_ecx.getId()); _emitInstruction(kX86InstRepECmpSQ, &cmp1_addr, &cmp2_addr, &cnt_ecx); } #endif // ASMJIT_X64 //! @brief Repeated find nonmatching WORDs in ES:[EDI/RDI] and DS:[ESI/RDI]. inline void repe_cmpsw(const GpVar& cmp1_addr, const GpVar& cmp2_addr, const GpVar& cnt_ecx) { // All registers must be unique, they will be reallocated to cmp1=ES:EDI,RDI, cmp2=ES:[EDI/RDI], cnt=ECX/RCX. ASMJIT_ASSERT(cmp1_addr.getId() != cmp2_addr.getId() && cmp2_addr.getId() != cnt_ecx.getId()); _emitInstruction(kX86InstRepECmpSW, &cmp1_addr, &cmp2_addr, &cnt_ecx); } //! @brief Find non-AL BYTE starting at ES:[EDI/RDI]. inline void repe_scasb(const GpVar& cmp1_addr, const GpVar& cmp2_val, const GpVar& cnt_ecx) { // All registers must be unique, they will be reallocated to cmp1=ES:EDI,RDI, src=AL, cnt=ECX/RCX. ASMJIT_ASSERT(cmp1_addr.getId() != cmp2_val.getId() && cmp2_val.getId() != cnt_ecx.getId()); _emitInstruction(kX86InstRepEScaSB, &cmp1_addr, &cmp2_val, &cnt_ecx); } //! @brief Find non-EAX DWORD starting at ES:[EDI/RDI]. inline void repe_scasd(const GpVar& cmp1_addr, const GpVar& cmp2_val, const GpVar& cnt_ecx) { // All registers must be unique, they will be reallocated to cmp1=ES:EDI,RDI, src=EAX, cnt=ECX/RCX. ASMJIT_ASSERT(cmp1_addr.getId() != cmp2_val.getId() && cmp2_val.getId() != cnt_ecx.getId()); _emitInstruction(kX86InstRepEScaSD, &cmp1_addr, &cmp2_val, &cnt_ecx); } #if defined(ASMJIT_X64) //! @brief Find non-RAX QWORD starting at ES:[EDI/RDI]. inline void repe_scasq(const GpVar& cmp1_addr, const GpVar& cmp2_val, const GpVar& cnt_ecx) { // All registers must be unique, they will be reallocated to cmp1=ES:EDI,RDI, src=RAX, cnt=ECX/RCX. ASMJIT_ASSERT(cmp1_addr.getId() != cmp2_val.getId() && cmp2_val.getId() != cnt_ecx.getId()); _emitInstruction(kX86InstRepEScaSQ, &cmp1_addr, &cmp2_val, &cnt_ecx); } #endif // ASMJIT_X64 //! @brief Find non-AX WORD starting at ES:[EDI/RDI]. inline void repe_scasw(const GpVar& cmp1_addr, const GpVar& cmp2_val, const GpVar& cnt_ecx) { // All registers must be unique, they will be reallocated to cmp1=ES:EDI,RDI, src=AX, cnt=ECX/RCX. ASMJIT_ASSERT(cmp1_addr.getId() != cmp2_val.getId() && cmp2_val.getId() != cnt_ecx.getId()); _emitInstruction(kX86InstRepEScaSW, &cmp1_addr, &cmp2_val, &cnt_ecx); } //! @brief Find matching BYTEs in [RDI] and [RSI]. inline void repne_cmpsb(const GpVar& cmp1_addr, const GpVar& cmp2_addr, const GpVar& cnt_ecx) { // All registers must be unique, they will be reallocated to cmp1=ES:EDI,RDI, cmp2=ES:[EDI/RDI], cnt=ECX/RCX. ASMJIT_ASSERT(cmp1_addr.getId() != cmp2_addr.getId() && cmp2_addr.getId() != cnt_ecx.getId()); _emitInstruction(kX86InstRepNECmpSB, &cmp1_addr, &cmp2_addr, &cnt_ecx); } //! @brief Find matching DWORDs in [RDI] and [RSI]. inline void repne_cmpsd(const GpVar& cmp1_addr, const GpVar& cmp2_addr, const GpVar& cnt_ecx) { // All registers must be unique, they will be reallocated to cmp1=ES:EDI,RDI, cmp2=ES:[EDI/RDI], cnt=ECX/RCX. ASMJIT_ASSERT(cmp1_addr.getId() != cmp2_addr.getId() && cmp2_addr.getId() != cnt_ecx.getId()); _emitInstruction(kX86InstRepNECmpSD, &cmp1_addr, &cmp2_addr, &cnt_ecx); } #if defined(ASMJIT_X64) //! @brief Find matching QWORDs in [RDI] and [RSI]. inline void repne_cmpsq(const GpVar& cmp1_addr, const GpVar& cmp2_addr, const GpVar& cnt_ecx) { // All registers must be unique, they will be reallocated to cmp1=ES:EDI,RDI, cmp2=ES:[EDI/RDI], cnt=ECX/RCX. ASMJIT_ASSERT(cmp1_addr.getId() != cmp2_addr.getId() && cmp2_addr.getId() != cnt_ecx.getId()); _emitInstruction(kX86InstRepNECmpSQ, &cmp1_addr, &cmp2_addr, &cnt_ecx); } #endif // ASMJIT_X64 //! @brief Find matching WORDs in [RDI] and [RSI]. inline void repne_cmpsw(const GpVar& cmp1_addr, const GpVar& cmp2_addr, const GpVar& cnt_ecx) { // All registers must be unique, they will be reallocated to cmp1=ES:EDI,RDI, cmp2=ES:[EDI/RDI], cnt=ECX/RCX. ASMJIT_ASSERT(cmp1_addr.getId() != cmp2_addr.getId() && cmp2_addr.getId() != cnt_ecx.getId()); _emitInstruction(kX86InstRepNECmpSW, &cmp1_addr, &cmp2_addr, &cnt_ecx); } //! @brief Find AL, starting at ES:[EDI/RDI]. inline void repne_scasb(const GpVar& cmp1_addr, const GpVar& cmp2_val, const GpVar& cnt_ecx) { // All registers must be unique, they will be reallocated to cmp1=ES:EDI,RDI, src=AL, cnt=ECX/RCX. ASMJIT_ASSERT(cmp1_addr.getId() != cmp2_val.getId() && cmp2_val.getId() != cnt_ecx.getId()); _emitInstruction(kX86InstRepNEScaSB, &cmp1_addr, &cmp2_val, &cnt_ecx); } //! @brief Find EAX, starting at ES:[EDI/RDI]. inline void repne_scasd(const GpVar& cmp1_addr, const GpVar& cmp2_val, const GpVar& cnt_ecx) { // All registers must be unique, they will be reallocated to cmp1=ES:EDI,RDI, src=EAX, cnt=ECX/RCX. ASMJIT_ASSERT(cmp1_addr.getId() != cmp2_val.getId() && cmp2_val.getId() != cnt_ecx.getId()); _emitInstruction(kX86InstRepNEScaSD, &cmp1_addr, &cmp2_val, &cnt_ecx); } #if defined(ASMJIT_X64) //! @brief Find RAX, starting at ES:[EDI/RDI]. inline void repne_scasq(const GpVar& cmp1_addr, const GpVar& cmp2_val, const GpVar& cnt_ecx) { // All registers must be unique, they will be reallocated to cmp1=ES:EDI,RDI, src=RAX, cnt=ECX/RCX. ASMJIT_ASSERT(cmp1_addr.getId() != cmp2_val.getId() && cmp2_val.getId() != cnt_ecx.getId()); _emitInstruction(kX86InstRepNEScaSQ, &cmp1_addr, &cmp2_val, &cnt_ecx); } #endif // ASMJIT_X64 //! @brief Find AX, starting at ES:[EDI/RDI]. inline void repne_scasw(const GpVar& cmp1_addr, const GpVar& cmp2_val, const GpVar& cnt_ecx) { // All registers must be unique, they will be reallocated to cmp1=ES:EDI,RDI, src=AX, cnt=ECX/RCX. ASMJIT_ASSERT(cmp1_addr.getId() != cmp2_val.getId() && cmp2_val.getId() != cnt_ecx.getId()); _emitInstruction(kX86InstRepNEScaSW, &cmp1_addr, &cmp2_val, &cnt_ecx); } //! @brief Return from Procedure. inline void ret() { _emitReturn(NULL, NULL); } //! @brief Return from Procedure. inline void ret(const GpVar& first) { _emitReturn(&first, NULL); } //! @brief Return from Procedure. inline void ret(const GpVar& first, const GpVar& second) { _emitReturn(&first, &second); } //! @brief Return from Procedure. inline void ret(const XmmVar& first) { _emitReturn(&first, NULL); } //! @brief Return from Procedure. inline void ret(const XmmVar& first, const XmmVar& second) { _emitReturn(&first, &second); } //! @brief Rotate Bits Left. //! @note @a src register can be only @c cl. inline void rol(const GpVar& dst, const GpVar& src) { _emitInstruction(kX86InstRol, &dst, &src); } //! @brief Rotate Bits Left. inline void rol(const GpVar& dst, const Imm& src) { _emitInstruction(kX86InstRol, &dst, &src); } //! @brief Rotate Bits Left. //! @note @a src register can be only @c cl. inline void rol(const Mem& dst, const GpVar& src) { _emitInstruction(kX86InstRol, &dst, &src); } //! @brief Rotate Bits Left. inline void rol(const Mem& dst, const Imm& src) { _emitInstruction(kX86InstRol, &dst, &src); } //! @brief Rotate Bits Right. //! @note @a src register can be only @c cl. inline void ror(const GpVar& dst, const GpVar& src) { _emitInstruction(kX86InstRor, &dst, &src); } //! @brief Rotate Bits Right. inline void ror(const GpVar& dst, const Imm& src) { _emitInstruction(kX86InstRor, &dst, &src); } //! @brief Rotate Bits Right. //! @note @a src register can be only @c cl. inline void ror(const Mem& dst, const GpVar& src) { _emitInstruction(kX86InstRor, &dst, &src); } //! @brief Rotate Bits Right. inline void ror(const Mem& dst, const Imm& src) { _emitInstruction(kX86InstRor, &dst, &src); } #if defined(ASMJIT_X86) //! @brief Store @a var (allocated to AH/AX/EAX/RAX) into Flags. inline void sahf(const GpVar& var) { _emitInstruction(kX86InstSahf, &var); } #endif // ASMJIT_X86 //! @brief Integer subtraction with borrow. inline void sbb(const GpVar& dst, const GpVar& src) { _emitInstruction(kX86InstSbb, &dst, &src); } //! @brief Integer subtraction with borrow. inline void sbb(const GpVar& dst, const Mem& src) { _emitInstruction(kX86InstSbb, &dst, &src); } //! @brief Integer subtraction with borrow. inline void sbb(const GpVar& dst, const Imm& src) { _emitInstruction(kX86InstSbb, &dst, &src); } //! @brief Integer subtraction with borrow. inline void sbb(const Mem& dst, const GpVar& src) { _emitInstruction(kX86InstSbb, &dst, &src); } //! @brief Integer subtraction with borrow. inline void sbb(const Mem& dst, const Imm& src) { _emitInstruction(kX86InstSbb, &dst, &src); } //! @brief Shift Bits Left. //! @note @a src register can be only @c cl. inline void sal(const GpVar& dst, const GpVar& src) { _emitInstruction(kX86InstSal, &dst, &src); } //! @brief Shift Bits Left. inline void sal(const GpVar& dst, const Imm& src) { _emitInstruction(kX86InstSal, &dst, &src); } //! @brief Shift Bits Left. //! @note @a src register can be only @c cl. inline void sal(const Mem& dst, const GpVar& src) { _emitInstruction(kX86InstSal, &dst, &src); } //! @brief Shift Bits Left. inline void sal(const Mem& dst, const Imm& src) { _emitInstruction(kX86InstSal, &dst, &src); } //! @brief Shift Bits Right. //! @note @a src register can be only @c cl. inline void sar(const GpVar& dst, const GpVar& src) { _emitInstruction(kX86InstSar, &dst, &src); } //! @brief Shift Bits Right. inline void sar(const GpVar& dst, const Imm& src) { _emitInstruction(kX86InstSar, &dst, &src); } //! @brief Shift Bits Right. //! @note @a src register can be only @c cl. inline void sar(const Mem& dst, const GpVar& src) { _emitInstruction(kX86InstSar, &dst, &src); } //! @brief Shift Bits Right. inline void sar(const Mem& dst, const Imm& src) { _emitInstruction(kX86InstSar, &dst, &src); } //! @brief Set Byte on Condition. inline void set(kX86Cond cc, const GpVar& dst) { ASMJIT_ASSERT(dst.getSize() == 1); _emitInstruction(X86Util::getSetccInstFromCond(cc), &dst); } //! @brief Set Byte on Condition. inline void set(kX86Cond cc, const Mem& dst) { ASMJIT_ASSERT(dst.getSize() <= 1); _emitInstruction(X86Util::getSetccInstFromCond(cc), &dst); } //! @brief Set Byte on Condition. inline void seta (const GpVar& dst) { ASMJIT_ASSERT(dst.getSize() == 1); _emitInstruction(kX86InstSetA , &dst); } //! @brief Set Byte on Condition. inline void seta (const Mem& dst) { ASMJIT_ASSERT(dst.getSize() <= 1); _emitInstruction(kX86InstSetA , &dst); } //! @brief Set Byte on Condition. inline void setae (const GpVar& dst) { ASMJIT_ASSERT(dst.getSize() == 1); _emitInstruction(kX86InstSetAE , &dst); } //! @brief Set Byte on Condition. inline void setae (const Mem& dst) { ASMJIT_ASSERT(dst.getSize() <= 1); _emitInstruction(kX86InstSetAE , &dst); } //! @brief Set Byte on Condition. inline void setb (const GpVar& dst) { ASMJIT_ASSERT(dst.getSize() == 1); _emitInstruction(kX86InstSetB , &dst); } //! @brief Set Byte on Condition. inline void setb (const Mem& dst) { ASMJIT_ASSERT(dst.getSize() <= 1); _emitInstruction(kX86InstSetB , &dst); } //! @brief Set Byte on Condition. inline void setbe (const GpVar& dst) { ASMJIT_ASSERT(dst.getSize() == 1); _emitInstruction(kX86InstSetBE , &dst); } //! @brief Set Byte on Condition. inline void setbe (const Mem& dst) { ASMJIT_ASSERT(dst.getSize() <= 1); _emitInstruction(kX86InstSetBE , &dst); } //! @brief Set Byte on Condition. inline void setc (const GpVar& dst) { ASMJIT_ASSERT(dst.getSize() == 1); _emitInstruction(kX86InstSetC , &dst); } //! @brief Set Byte on Condition. inline void setc (const Mem& dst) { ASMJIT_ASSERT(dst.getSize() <= 1); _emitInstruction(kX86InstSetC , &dst); } //! @brief Set Byte on Condition. inline void sete (const GpVar& dst) { ASMJIT_ASSERT(dst.getSize() == 1); _emitInstruction(kX86InstSetE , &dst); } //! @brief Set Byte on Condition. inline void sete (const Mem& dst) { ASMJIT_ASSERT(dst.getSize() <= 1); _emitInstruction(kX86InstSetE , &dst); } //! @brief Set Byte on Condition. inline void setg (const GpVar& dst) { ASMJIT_ASSERT(dst.getSize() == 1); _emitInstruction(kX86InstSetG , &dst); } //! @brief Set Byte on Condition. inline void setg (const Mem& dst) { ASMJIT_ASSERT(dst.getSize() <= 1); _emitInstruction(kX86InstSetG , &dst); } //! @brief Set Byte on Condition. inline void setge (const GpVar& dst) { ASMJIT_ASSERT(dst.getSize() == 1); _emitInstruction(kX86InstSetGE , &dst); } //! @brief Set Byte on Condition. inline void setge (const Mem& dst) { ASMJIT_ASSERT(dst.getSize() <= 1); _emitInstruction(kX86InstSetGE , &dst); } //! @brief Set Byte on Condition. inline void setl (const GpVar& dst) { ASMJIT_ASSERT(dst.getSize() == 1); _emitInstruction(kX86InstSetL , &dst); } //! @brief Set Byte on Condition. inline void setl (const Mem& dst) { ASMJIT_ASSERT(dst.getSize() <= 1); _emitInstruction(kX86InstSetL , &dst); } //! @brief Set Byte on Condition. inline void setle (const GpVar& dst) { ASMJIT_ASSERT(dst.getSize() == 1); _emitInstruction(kX86InstSetLE , &dst); } //! @brief Set Byte on Condition. inline void setle (const Mem& dst) { ASMJIT_ASSERT(dst.getSize() <= 1); _emitInstruction(kX86InstSetLE , &dst); } //! @brief Set Byte on Condition. inline void setna (const GpVar& dst) { ASMJIT_ASSERT(dst.getSize() == 1); _emitInstruction(kX86InstSetNA , &dst); } //! @brief Set Byte on Condition. inline void setna (const Mem& dst) { ASMJIT_ASSERT(dst.getSize() <= 1); _emitInstruction(kX86InstSetNA , &dst); } //! @brief Set Byte on Condition. inline void setnae(const GpVar& dst) { ASMJIT_ASSERT(dst.getSize() == 1); _emitInstruction(kX86InstSetNAE, &dst); } //! @brief Set Byte on Condition. inline void setnae(const Mem& dst) { ASMJIT_ASSERT(dst.getSize() <= 1); _emitInstruction(kX86InstSetNAE, &dst); } //! @brief Set Byte on Condition. inline void setnb (const GpVar& dst) { ASMJIT_ASSERT(dst.getSize() == 1); _emitInstruction(kX86InstSetNB , &dst); } //! @brief Set Byte on Condition. inline void setnb (const Mem& dst) { ASMJIT_ASSERT(dst.getSize() <= 1); _emitInstruction(kX86InstSetNB , &dst); } //! @brief Set Byte on Condition. inline void setnbe(const GpVar& dst) { ASMJIT_ASSERT(dst.getSize() == 1); _emitInstruction(kX86InstSetNBE, &dst); } //! @brief Set Byte on Condition. inline void setnbe(const Mem& dst) { ASMJIT_ASSERT(dst.getSize() <= 1); _emitInstruction(kX86InstSetNBE, &dst); } //! @brief Set Byte on Condition. inline void setnc (const GpVar& dst) { ASMJIT_ASSERT(dst.getSize() == 1); _emitInstruction(kX86InstSetNC , &dst); } //! @brief Set Byte on Condition. inline void setnc (const Mem& dst) { ASMJIT_ASSERT(dst.getSize() <= 1); _emitInstruction(kX86InstSetNC , &dst); } //! @brief Set Byte on Condition. inline void setne (const GpVar& dst) { ASMJIT_ASSERT(dst.getSize() == 1); _emitInstruction(kX86InstSetNE , &dst); } //! @brief Set Byte on Condition. inline void setne (const Mem& dst) { ASMJIT_ASSERT(dst.getSize() <= 1); _emitInstruction(kX86InstSetNE , &dst); } //! @brief Set Byte on Condition. inline void setng (const GpVar& dst) { ASMJIT_ASSERT(dst.getSize() == 1); _emitInstruction(kX86InstSetNG , &dst); } //! @brief Set Byte on Condition. inline void setng (const Mem& dst) { ASMJIT_ASSERT(dst.getSize() <= 1); _emitInstruction(kX86InstSetNG , &dst); } //! @brief Set Byte on Condition. inline void setnge(const GpVar& dst) { ASMJIT_ASSERT(dst.getSize() == 1); _emitInstruction(kX86InstSetNGE, &dst); } //! @brief Set Byte on Condition. inline void setnge(const Mem& dst) { ASMJIT_ASSERT(dst.getSize() <= 1); _emitInstruction(kX86InstSetNGE, &dst); } //! @brief Set Byte on Condition. inline void setnl (const GpVar& dst) { ASMJIT_ASSERT(dst.getSize() == 1); _emitInstruction(kX86InstSetNL , &dst); } //! @brief Set Byte on Condition. inline void setnl (const Mem& dst) { ASMJIT_ASSERT(dst.getSize() <= 1); _emitInstruction(kX86InstSetNL , &dst); } //! @brief Set Byte on Condition. inline void setnle(const GpVar& dst) { ASMJIT_ASSERT(dst.getSize() == 1); _emitInstruction(kX86InstSetNLE, &dst); } //! @brief Set Byte on Condition. inline void setnle(const Mem& dst) { ASMJIT_ASSERT(dst.getSize() <= 1); _emitInstruction(kX86InstSetNLE, &dst); } //! @brief Set Byte on Condition. inline void setno (const GpVar& dst) { ASMJIT_ASSERT(dst.getSize() == 1); _emitInstruction(kX86InstSetNO , &dst); } //! @brief Set Byte on Condition. inline void setno (const Mem& dst) { ASMJIT_ASSERT(dst.getSize() <= 1); _emitInstruction(kX86InstSetNO , &dst); } //! @brief Set Byte on Condition. inline void setnp (const GpVar& dst) { ASMJIT_ASSERT(dst.getSize() == 1); _emitInstruction(kX86InstSetNP , &dst); } //! @brief Set Byte on Condition. inline void setnp (const Mem& dst) { ASMJIT_ASSERT(dst.getSize() <= 1); _emitInstruction(kX86InstSetNP , &dst); } //! @brief Set Byte on Condition. inline void setns (const GpVar& dst) { ASMJIT_ASSERT(dst.getSize() == 1); _emitInstruction(kX86InstSetNS , &dst); } //! @brief Set Byte on Condition. inline void setns (const Mem& dst) { ASMJIT_ASSERT(dst.getSize() <= 1); _emitInstruction(kX86InstSetNS , &dst); } //! @brief Set Byte on Condition. inline void setnz (const GpVar& dst) { ASMJIT_ASSERT(dst.getSize() == 1); _emitInstruction(kX86InstSetNZ , &dst); } //! @brief Set Byte on Condition. inline void setnz (const Mem& dst) { ASMJIT_ASSERT(dst.getSize() <= 1); _emitInstruction(kX86InstSetNZ , &dst); } //! @brief Set Byte on Condition. inline void seto (const GpVar& dst) { ASMJIT_ASSERT(dst.getSize() == 1); _emitInstruction(kX86InstSetO , &dst); } //! @brief Set Byte on Condition. inline void seto (const Mem& dst) { ASMJIT_ASSERT(dst.getSize() <= 1); _emitInstruction(kX86InstSetO , &dst); } //! @brief Set Byte on Condition. inline void setp (const GpVar& dst) { ASMJIT_ASSERT(dst.getSize() == 1); _emitInstruction(kX86InstSetP , &dst); } //! @brief Set Byte on Condition. inline void setp (const Mem& dst) { ASMJIT_ASSERT(dst.getSize() <= 1); _emitInstruction(kX86InstSetP , &dst); } //! @brief Set Byte on Condition. inline void setpe (const GpVar& dst) { ASMJIT_ASSERT(dst.getSize() == 1); _emitInstruction(kX86InstSetPE , &dst); } //! @brief Set Byte on Condition. inline void setpe (const Mem& dst) { ASMJIT_ASSERT(dst.getSize() <= 1); _emitInstruction(kX86InstSetPE , &dst); } //! @brief Set Byte on Condition. inline void setpo (const GpVar& dst) { ASMJIT_ASSERT(dst.getSize() == 1); _emitInstruction(kX86InstSetPO , &dst); } //! @brief Set Byte on Condition. inline void setpo (const Mem& dst) { ASMJIT_ASSERT(dst.getSize() <= 1); _emitInstruction(kX86InstSetPO , &dst); } //! @brief Set Byte on Condition. inline void sets (const GpVar& dst) { ASMJIT_ASSERT(dst.getSize() == 1); _emitInstruction(kX86InstSetS , &dst); } //! @brief Set Byte on Condition. inline void sets (const Mem& dst) { ASMJIT_ASSERT(dst.getSize() <= 1); _emitInstruction(kX86InstSetS , &dst); } //! @brief Set Byte on Condition. inline void setz (const GpVar& dst) { ASMJIT_ASSERT(dst.getSize() == 1); _emitInstruction(kX86InstSetZ , &dst); } //! @brief Set Byte on Condition. inline void setz (const Mem& dst) { ASMJIT_ASSERT(dst.getSize() <= 1); _emitInstruction(kX86InstSetZ , &dst); } //! @brief Shift Bits Left. //! @note @a src register can be only @c cl. inline void shl(const GpVar& dst, const GpVar& src) { _emitInstruction(kX86InstShl, &dst, &src); } //! @brief Shift Bits Left. inline void shl(const GpVar& dst, const Imm& src) { _emitInstruction(kX86InstShl, &dst, &src); } //! @brief Shift Bits Left. //! @note @a src register can be only @c cl. inline void shl(const Mem& dst, const GpVar& src) { _emitInstruction(kX86InstShl, &dst, &src); } //! @brief Shift Bits Left. inline void shl(const Mem& dst, const Imm& src) { _emitInstruction(kX86InstShl, &dst, &src); } //! @brief Shift Bits Right. //! @note @a src register can be only @c cl. inline void shr(const GpVar& dst, const GpVar& src) { _emitInstruction(kX86InstShr, &dst, &src); } //! @brief Shift Bits Right. inline void shr(const GpVar& dst, const Imm& src) { _emitInstruction(kX86InstShr, &dst, &src); } //! @brief Shift Bits Right. //! @note @a src register can be only @c cl. inline void shr(const Mem& dst, const GpVar& src) { _emitInstruction(kX86InstShr, &dst, &src); } //! @brief Shift Bits Right. inline void shr(const Mem& dst, const Imm& src) { _emitInstruction(kX86InstShr, &dst, &src); } //! @brief Double Precision Shift Left. //! @note src2 register can be only @c cl register. inline void shld(const GpVar& dst, const GpVar& src1, const GpVar& src2) { _emitInstruction(kX86InstShld, &dst, &src1, &src2); } //! @brief Double Precision Shift Left. inline void shld(const GpVar& dst, const GpVar& src1, const Imm& src2) { _emitInstruction(kX86InstShld, &dst, &src1, &src2); } //! @brief Double Precision Shift Left. //! @note src2 register can be only @c cl register. inline void shld(const Mem& dst, const GpVar& src1, const GpVar& src2) { _emitInstruction(kX86InstShld, &dst, &src1, &src2); } //! @brief Double Precision Shift Left. inline void shld(const Mem& dst, const GpVar& src1, const Imm& src2) { _emitInstruction(kX86InstShld, &dst, &src1, &src2); } //! @brief Double Precision Shift Right. //! @note src2 register can be only @c cl register. inline void shrd(const GpVar& dst, const GpVar& src1, const GpVar& src2) { _emitInstruction(kX86InstShrd, &dst, &src1, &src2); } //! @brief Double Precision Shift Right. inline void shrd(const GpVar& dst, const GpVar& src1, const Imm& src2) { _emitInstruction(kX86InstShrd, &dst, &src1, &src2); } //! @brief Double Precision Shift Right. //! @note src2 register can be only @c cl register. inline void shrd(const Mem& dst, const GpVar& src1, const GpVar& src2) { _emitInstruction(kX86InstShrd, &dst, &src1, &src2); } //! @brief Double Precision Shift Right. inline void shrd(const Mem& dst, const GpVar& src1, const Imm& src2) { _emitInstruction(kX86InstShrd, &dst, &src1, &src2); } //! @brief Set Carry Flag to 1. inline void stc() { _emitInstruction(kX86InstStc); } //! @brief Set Direction Flag to 1. inline void std() { _emitInstruction(kX86InstStd); } //! @brief Subtract. inline void sub(const GpVar& dst, const GpVar& src) { _emitInstruction(kX86InstSub, &dst, &src); } //! @brief Subtract. inline void sub(const GpVar& dst, const Mem& src) { _emitInstruction(kX86InstSub, &dst, &src); } //! @brief Subtract. inline void sub(const GpVar& dst, const Imm& src) { _emitInstruction(kX86InstSub, &dst, &src); } //! @brief Subtract. inline void sub(const Mem& dst, const GpVar& src) { _emitInstruction(kX86InstSub, &dst, &src); } //! @brief Subtract. inline void sub(const Mem& dst, const Imm& src) { _emitInstruction(kX86InstSub, &dst, &src); } //! @brief Logical Compare. inline void test(const GpVar& op1, const GpVar& op2) { _emitInstruction(kX86InstTest, &op1, &op2); } //! @brief Logical Compare. inline void test(const GpVar& op1, const Imm& op2) { _emitInstruction(kX86InstTest, &op1, &op2); } //! @brief Logical Compare. inline void test(const Mem& op1, const GpVar& op2) { _emitInstruction(kX86InstTest, &op1, &op2); } //! @brief Logical Compare. inline void test(const Mem& op1, const Imm& op2) { _emitInstruction(kX86InstTest, &op1, &op2); } //! @brief Undefined instruction - Raise invalid opcode exception. inline void ud2() { _emitInstruction(kX86InstUd2); } //! @brief Exchange and Add. inline void xadd(const GpVar& dst, const GpVar& src) { _emitInstruction(kX86InstXadd, &dst, &src); } //! @brief Exchange and Add. inline void xadd(const Mem& dst, const GpVar& src) { _emitInstruction(kX86InstXadd, &dst, &src); } //! @brief Exchange Register/Memory with Register. inline void xchg(const GpVar& dst, const GpVar& src) { _emitInstruction(kX86InstXchg, &dst, &src); } //! @brief Exchange Register/Memory with Register. inline void xchg(const Mem& dst, const GpVar& src) { _emitInstruction(kX86InstXchg, &dst, &src); } //! @brief Exchange Register/Memory with Register. inline void xchg(const GpVar& dst, const Mem& src) { _emitInstruction(kX86InstXchg, &src, &dst); } //! @brief Exchange Register/Memory with Register. inline void xor_(const GpVar& dst, const GpVar& src) { _emitInstruction(kX86InstXor, &dst, &src); } //! @brief Exchange Register/Memory with Register. inline void xor_(const GpVar& dst, const Mem& src) { _emitInstruction(kX86InstXor, &dst, &src); } //! @brief Exchange Register/Memory with Register. inline void xor_(const GpVar& dst, const Imm& src) { _emitInstruction(kX86InstXor, &dst, &src); } //! @brief Exchange Register/Memory with Register. inline void xor_(const Mem& dst, const GpVar& src) { _emitInstruction(kX86InstXor, &dst, &src); } //! @brief Exchange Register/Memory with Register. inline void xor_(const Mem& dst, const Imm& src) { _emitInstruction(kX86InstXor, &dst, &src); } // -------------------------------------------------------------------------- // [MMX] // -------------------------------------------------------------------------- //! @brief Empty MMX state. inline void emms() { _emitInstruction(kX86InstEmms); } //! @brief Move DWord (MMX). inline void movd(const Mem& dst, const MmVar& src) { _emitInstruction(kX86InstMovD, &dst, &src); } //! @brief Move DWord (MMX). inline void movd(const GpVar& dst, const MmVar& src) { _emitInstruction(kX86InstMovD, &dst, &src); } //! @brief Move DWord (MMX). inline void movd(const MmVar& dst, const Mem& src) { _emitInstruction(kX86InstMovD, &dst, &src); } //! @brief Move DWord (MMX). inline void movd(const MmVar& dst, const GpVar& src) { _emitInstruction(kX86InstMovD, &dst, &src); } //! @brief Move QWord (MMX). inline void movq(const MmVar& dst, const MmVar& src) { _emitInstruction(kX86InstMovQ, &dst, &src); } //! @brief Move QWord (MMX). inline void movq(const Mem& dst, const MmVar& src) { _emitInstruction(kX86InstMovQ, &dst, &src); } #if defined(ASMJIT_X64) //! @brief Move QWord (MMX). inline void movq(const GpVar& dst, const MmVar& src) { _emitInstruction(kX86InstMovQ, &dst, &src); } #endif //! @brief Move QWord (MMX). inline void movq(const MmVar& dst, const Mem& src) { _emitInstruction(kX86InstMovQ, &dst, &src); } #if defined(ASMJIT_X64) //! @brief Move QWord (MMX). inline void movq(const MmVar& dst, const GpVar& src) { _emitInstruction(kX86InstMovQ, &dst, &src); } #endif //! @brief Pack with Signed Saturation (MMX). inline void packsswb(const MmVar& dst, const MmVar& src) { _emitInstruction(kX86InstPackSSWB, &dst, &src); } //! @brief Pack with Signed Saturation (MMX). inline void packsswb(const MmVar& dst, const Mem& src) { _emitInstruction(kX86InstPackSSWB, &dst, &src); } //! @brief Pack with Signed Saturation (MMX). inline void packssdw(const MmVar& dst, const MmVar& src) { _emitInstruction(kX86InstPackSSDW, &dst, &src); } //! @brief Pack with Signed Saturation (MMX). inline void packssdw(const MmVar& dst, const Mem& src) { _emitInstruction(kX86InstPackSSDW, &dst, &src); } //! @brief Pack with Unsigned Saturation (MMX). inline void packuswb(const MmVar& dst, const MmVar& src) { _emitInstruction(kX86InstPackUSWB, &dst, &src); } //! @brief Pack with Unsigned Saturation (MMX). inline void packuswb(const MmVar& dst, const Mem& src) { _emitInstruction(kX86InstPackUSWB, &dst, &src); } //! @brief Packed BYTE Add (MMX). inline void paddb(const MmVar& dst, const MmVar& src) { _emitInstruction(kX86InstPAddB, &dst, &src); } //! @brief Packed BYTE Add (MMX). inline void paddb(const MmVar& dst, const Mem& src) { _emitInstruction(kX86InstPAddB, &dst, &src); } //! @brief Packed WORD Add (MMX). inline void paddw(const MmVar& dst, const MmVar& src) { _emitInstruction(kX86InstPAddW, &dst, &src); } //! @brief Packed WORD Add (MMX). inline void paddw(const MmVar& dst, const Mem& src) { _emitInstruction(kX86InstPAddW, &dst, &src); } //! @brief Packed DWORD Add (MMX). inline void paddd(const MmVar& dst, const MmVar& src) { _emitInstruction(kX86InstPAddD, &dst, &src); } //! @brief Packed DWORD Add (MMX). inline void paddd(const MmVar& dst, const Mem& src) { _emitInstruction(kX86InstPAddD, &dst, &src); } //! @brief Packed Add with Saturation (MMX). inline void paddsb(const MmVar& dst, const MmVar& src) { _emitInstruction(kX86InstPAddSB, &dst, &src); } //! @brief Packed Add with Saturation (MMX). inline void paddsb(const MmVar& dst, const Mem& src) { _emitInstruction(kX86InstPAddSB, &dst, &src); } //! @brief Packed Add with Saturation (MMX). inline void paddsw(const MmVar& dst, const MmVar& src) { _emitInstruction(kX86InstPAddSW, &dst, &src); } //! @brief Packed Add with Saturation (MMX). inline void paddsw(const MmVar& dst, const Mem& src) { _emitInstruction(kX86InstPAddSW, &dst, &src); } //! @brief Packed Add Unsigned with Saturation (MMX). inline void paddusb(const MmVar& dst, const MmVar& src) { _emitInstruction(kX86InstPAddUSB, &dst, &src); } //! @brief Packed Add Unsigned with Saturation (MMX). inline void paddusb(const MmVar& dst, const Mem& src) { _emitInstruction(kX86InstPAddUSB, &dst, &src); } //! @brief Packed Add Unsigned with Saturation (MMX). inline void paddusw(const MmVar& dst, const MmVar& src) { _emitInstruction(kX86InstPAddUSW, &dst, &src); } //! @brief Packed Add Unsigned with Saturation (MMX). inline void paddusw(const MmVar& dst, const Mem& src) { _emitInstruction(kX86InstPAddUSW, &dst, &src); } //! @brief Logical AND (MMX). inline void pand(const MmVar& dst, const MmVar& src) { _emitInstruction(kX86InstPAnd, &dst, &src); } //! @brief Logical AND (MMX). inline void pand(const MmVar& dst, const Mem& src) { _emitInstruction(kX86InstPAnd, &dst, &src); } //! @brief Logical AND Not (MMX). inline void pandn(const MmVar& dst, const MmVar& src) { _emitInstruction(kX86InstPAndN, &dst, &src); } //! @brief Logical AND Not (MMX). inline void pandn(const MmVar& dst, const Mem& src) { _emitInstruction(kX86InstPAndN, &dst, &src); } //! @brief Packed Compare for Equal (BYTES) (MMX). inline void pcmpeqb(const MmVar& dst, const MmVar& src) { _emitInstruction(kX86InstPCmpEqB, &dst, &src); } //! @brief Packed Compare for Equal (BYTES) (MMX). inline void pcmpeqb(const MmVar& dst, const Mem& src) { _emitInstruction(kX86InstPCmpEqB, &dst, &src); } //! @brief Packed Compare for Equal (WORDS) (MMX). inline void pcmpeqw(const MmVar& dst, const MmVar& src) { _emitInstruction(kX86InstPCmpEqW, &dst, &src); } //! @brief Packed Compare for Equal (WORDS) (MMX). inline void pcmpeqw(const MmVar& dst, const Mem& src) { _emitInstruction(kX86InstPCmpEqW, &dst, &src); } //! @brief Packed Compare for Equal (DWORDS) (MMX). inline void pcmpeqd(const MmVar& dst, const MmVar& src) { _emitInstruction(kX86InstPCmpEqD, &dst, &src); } //! @brief Packed Compare for Equal (DWORDS) (MMX). inline void pcmpeqd(const MmVar& dst, const Mem& src) { _emitInstruction(kX86InstPCmpEqD, &dst, &src); } //! @brief Packed Compare for Greater Than (BYTES) (MMX). inline void pcmpgtb(const MmVar& dst, const MmVar& src) { _emitInstruction(kX86InstPCmpGtB, &dst, &src); } //! @brief Packed Compare for Greater Than (BYTES) (MMX). inline void pcmpgtb(const MmVar& dst, const Mem& src) { _emitInstruction(kX86InstPCmpGtB, &dst, &src); } //! @brief Packed Compare for Greater Than (WORDS) (MMX). inline void pcmpgtw(const MmVar& dst, const MmVar& src) { _emitInstruction(kX86InstPCmpGtW, &dst, &src); } //! @brief Packed Compare for Greater Than (WORDS) (MMX). inline void pcmpgtw(const MmVar& dst, const Mem& src) { _emitInstruction(kX86InstPCmpGtW, &dst, &src); } //! @brief Packed Compare for Greater Than (DWORDS) (MMX). inline void pcmpgtd(const MmVar& dst, const MmVar& src) { _emitInstruction(kX86InstPCmpGtD, &dst, &src); } //! @brief Packed Compare for Greater Than (DWORDS) (MMX). inline void pcmpgtd(const MmVar& dst, const Mem& src) { _emitInstruction(kX86InstPCmpGtD, &dst, &src); } //! @brief Packed Multiply High (MMX). inline void pmulhw(const MmVar& dst, const MmVar& src) { _emitInstruction(kX86InstPMulHW, &dst, &src); } //! @brief Packed Multiply High (MMX). inline void pmulhw(const MmVar& dst, const Mem& src) { _emitInstruction(kX86InstPMulHW, &dst, &src); } //! @brief Packed Multiply Low (MMX). inline void pmullw(const MmVar& dst, const MmVar& src) { _emitInstruction(kX86InstPMulLW, &dst, &src); } //! @brief Packed Multiply Low (MMX). inline void pmullw(const MmVar& dst, const Mem& src) { _emitInstruction(kX86InstPMulLW, &dst, &src); } //! @brief Bitwise Logical OR (MMX). inline void por(const MmVar& dst, const MmVar& src) { _emitInstruction(kX86InstPOr, &dst, &src); } //! @brief Bitwise Logical OR (MMX). inline void por(const MmVar& dst, const Mem& src) { _emitInstruction(kX86InstPOr, &dst, &src); } //! @brief Packed Multiply and Add (MMX). inline void pmaddwd(const MmVar& dst, const MmVar& src) { _emitInstruction(kX86InstPMAddWD, &dst, &src); } //! @brief Packed Multiply and Add (MMX). inline void pmaddwd(const MmVar& dst, const Mem& src) { _emitInstruction(kX86InstPMAddWD, &dst, &src); } //! @brief Packed Shift Left Logical (MMX). inline void pslld(const MmVar& dst, const MmVar& src) { _emitInstruction(kX86InstPSllD, &dst, &src); } //! @brief Packed Shift Left Logical (MMX). inline void pslld(const MmVar& dst, const Mem& src) { _emitInstruction(kX86InstPSllD, &dst, &src); } //! @brief Packed Shift Left Logical (MMX). inline void pslld(const MmVar& dst, const Imm& src) { _emitInstruction(kX86InstPSllD, &dst, &src); } //! @brief Packed Shift Left Logical (MMX). inline void psllq(const MmVar& dst, const MmVar& src) { _emitInstruction(kX86InstPSllQ, &dst, &src); } //! @brief Packed Shift Left Logical (MMX). inline void psllq(const MmVar& dst, const Mem& src) { _emitInstruction(kX86InstPSllQ, &dst, &src); } //! @brief Packed Shift Left Logical (MMX). inline void psllq(const MmVar& dst, const Imm& src) { _emitInstruction(kX86InstPSllQ, &dst, &src); } //! @brief Packed Shift Left Logical (MMX). inline void psllw(const MmVar& dst, const MmVar& src) { _emitInstruction(kX86InstPSllW, &dst, &src); } //! @brief Packed Shift Left Logical (MMX). inline void psllw(const MmVar& dst, const Mem& src) { _emitInstruction(kX86InstPSllW, &dst, &src); } //! @brief Packed Shift Left Logical (MMX). inline void psllw(const MmVar& dst, const Imm& src) { _emitInstruction(kX86InstPSllW, &dst, &src); } //! @brief Packed Shift Right Arithmetic (MMX). inline void psrad(const MmVar& dst, const MmVar& src) { _emitInstruction(kX86InstPSraD, &dst, &src); } //! @brief Packed Shift Right Arithmetic (MMX). inline void psrad(const MmVar& dst, const Mem& src) { _emitInstruction(kX86InstPSraD, &dst, &src);} //! @brief Packed Shift Right Arithmetic (MMX). inline void psrad(const MmVar& dst, const Imm& src) { _emitInstruction(kX86InstPSraD, &dst, &src); } //! @brief Packed Shift Right Arithmetic (MMX). inline void psraw(const MmVar& dst, const MmVar& src) { _emitInstruction(kX86InstPSraW, &dst, &src); } //! @brief Packed Shift Right Arithmetic (MMX). inline void psraw(const MmVar& dst, const Mem& src) { _emitInstruction(kX86InstPSraW, &dst, &src); } //! @brief Packed Shift Right Arithmetic (MMX). inline void psraw(const MmVar& dst, const Imm& src) { _emitInstruction(kX86InstPSraW, &dst, &src); } //! @brief Packed Shift Right Logical (MMX). inline void psrld(const MmVar& dst, const MmVar& src) { _emitInstruction(kX86InstPSrlD, &dst, &src); } //! @brief Packed Shift Right Logical (MMX). inline void psrld(const MmVar& dst, const Mem& src) { _emitInstruction(kX86InstPSrlD, &dst, &src); } //! @brief Packed Shift Right Logical (MMX). inline void psrld(const MmVar& dst, const Imm& src) { _emitInstruction(kX86InstPSrlD, &dst, &src); } //! @brief Packed Shift Right Logical (MMX). inline void psrlq(const MmVar& dst, const MmVar& src) { _emitInstruction(kX86InstPSrlQ, &dst, &src); } //! @brief Packed Shift Right Logical (MMX). inline void psrlq(const MmVar& dst, const Mem& src) { _emitInstruction(kX86InstPSrlQ, &dst, &src); } //! @brief Packed Shift Right Logical (MMX). inline void psrlq(const MmVar& dst, const Imm& src) { _emitInstruction(kX86InstPSrlQ, &dst, &src); } //! @brief Packed Shift Right Logical (MMX). inline void psrlw(const MmVar& dst, const MmVar& src) { _emitInstruction(kX86InstPSrlW, &dst, &src); } //! @brief Packed Shift Right Logical (MMX). inline void psrlw(const MmVar& dst, const Mem& src) { _emitInstruction(kX86InstPSrlW, &dst, &src); } //! @brief Packed Shift Right Logical (MMX). inline void psrlw(const MmVar& dst, const Imm& src) { _emitInstruction(kX86InstPSrlW, &dst, &src); } //! @brief Packed Subtract (MMX). inline void psubb(const MmVar& dst, const MmVar& src) { _emitInstruction(kX86InstPSubB, &dst, &src); } //! @brief Packed Subtract (MMX). inline void psubb(const MmVar& dst, const Mem& src) { _emitInstruction(kX86InstPSubB, &dst, &src); } //! @brief Packed Subtract (MMX). inline void psubw(const MmVar& dst, const MmVar& src) { _emitInstruction(kX86InstPSubW, &dst, &src); } //! @brief Packed Subtract (MMX). inline void psubw(const MmVar& dst, const Mem& src) { _emitInstruction(kX86InstPSubW, &dst, &src); } //! @brief Packed Subtract (MMX). inline void psubd(const MmVar& dst, const MmVar& src) { _emitInstruction(kX86InstPSubD, &dst, &src); } //! @brief Packed Subtract (MMX). inline void psubd(const MmVar& dst, const Mem& src) { _emitInstruction(kX86InstPSubD, &dst, &src); } //! @brief Packed Subtract with Saturation (MMX). inline void psubsb(const MmVar& dst, const MmVar& src) { _emitInstruction(kX86InstPSubSB, &dst, &src); } //! @brief Packed Subtract with Saturation (MMX). inline void psubsb(const MmVar& dst, const Mem& src) { _emitInstruction(kX86InstPSubSB, &dst, &src); } //! @brief Packed Subtract with Saturation (MMX). inline void psubsw(const MmVar& dst, const MmVar& src) { _emitInstruction(kX86InstPSubSW, &dst, &src); } //! @brief Packed Subtract with Saturation (MMX). inline void psubsw(const MmVar& dst, const Mem& src) { _emitInstruction(kX86InstPSubSW, &dst, &src); } //! @brief Packed Subtract with Unsigned Saturation (MMX). inline void psubusb(const MmVar& dst, const MmVar& src) { _emitInstruction(kX86InstPSubUSB, &dst, &src); } //! @brief Packed Subtract with Unsigned Saturation (MMX). inline void psubusb(const MmVar& dst, const Mem& src) { _emitInstruction(kX86InstPSubUSB, &dst, &src); } //! @brief Packed Subtract with Unsigned Saturation (MMX). inline void psubusw(const MmVar& dst, const MmVar& src) { _emitInstruction(kX86InstPSubUSW, &dst, &src); } //! @brief Packed Subtract with Unsigned Saturation (MMX). inline void psubusw(const MmVar& dst, const Mem& src) { _emitInstruction(kX86InstPSubUSW, &dst, &src); } //! @brief Unpack High Packed Data (MMX). inline void punpckhbw(const MmVar& dst, const MmVar& src) { _emitInstruction(kX86InstPunpckHBW, &dst, &src); } //! @brief Unpack High Packed Data (MMX). inline void punpckhbw(const MmVar& dst, const Mem& src) { _emitInstruction(kX86InstPunpckHBW, &dst, &src); } //! @brief Unpack High Packed Data (MMX). inline void punpckhwd(const MmVar& dst, const MmVar& src) { _emitInstruction(kX86InstPunpckHWD, &dst, &src); } //! @brief Unpack High Packed Data (MMX). inline void punpckhwd(const MmVar& dst, const Mem& src) { _emitInstruction(kX86InstPunpckHWD, &dst, &src); } //! @brief Unpack High Packed Data (MMX). inline void punpckhdq(const MmVar& dst, const MmVar& src) { _emitInstruction(kX86InstPunpckHDQ, &dst, &src); } //! @brief Unpack High Packed Data (MMX). inline void punpckhdq(const MmVar& dst, const Mem& src) { _emitInstruction(kX86InstPunpckHDQ, &dst, &src); } //! @brief Unpack High Packed Data (MMX). inline void punpcklbw(const MmVar& dst, const MmVar& src) { _emitInstruction(kX86InstPunpckLBW, &dst, &src); } //! @brief Unpack High Packed Data (MMX). inline void punpcklbw(const MmVar& dst, const Mem& src) { _emitInstruction(kX86InstPunpckLBW, &dst, &src); } //! @brief Unpack High Packed Data (MMX). inline void punpcklwd(const MmVar& dst, const MmVar& src) { _emitInstruction(kX86InstPunpckLWD, &dst, &src); } //! @brief Unpack High Packed Data (MMX). inline void punpcklwd(const MmVar& dst, const Mem& src) { _emitInstruction(kX86InstPunpckLWD, &dst, &src); } //! @brief Unpack High Packed Data (MMX). inline void punpckldq(const MmVar& dst, const MmVar& src) { _emitInstruction(kX86InstPunpckLDQ, &dst, &src); } //! @brief Unpack High Packed Data (MMX). inline void punpckldq(const MmVar& dst, const Mem& src) { _emitInstruction(kX86InstPunpckLDQ, &dst, &src); } //! @brief Bitwise Exclusive OR (MMX). inline void pxor(const MmVar& dst, const MmVar& src) { _emitInstruction(kX86InstPXor, &dst, &src); } //! @brief Bitwise Exclusive OR (MMX). inline void pxor(const MmVar& dst, const Mem& src) { _emitInstruction(kX86InstPXor, &dst, &src); } // -------------------------------------------------------------------------- // [3dNow] // -------------------------------------------------------------------------- //! @brief Faster EMMS (3dNow!). //! //! @note Use only for early AMD processors where is only 3dNow! or SSE. If //! CPU contains SSE2, it's better to use @c emms() ( @c femms() is mapped //! to @c emms() ). inline void femms() { _emitInstruction(kX86InstFEmms); } //! @brief Packed SP-FP to Integer Convert (3dNow!). inline void pf2id(const MmVar& dst, const MmVar& src) { _emitInstruction(kX86InstPF2ID, &dst, &src); } //! @brief Packed SP-FP to Integer Convert (3dNow!). inline void pf2id(const MmVar& dst, const Mem& src) { _emitInstruction(kX86InstPF2ID, &dst, &src); } //! @brief Packed SP-FP to Integer Word Convert (3dNow!). inline void pf2iw(const MmVar& dst, const MmVar& src) { _emitInstruction(kX86InstPF2IW, &dst, &src); } //! @brief Packed SP-FP to Integer Word Convert (3dNow!). inline void pf2iw(const MmVar& dst, const Mem& src) { _emitInstruction(kX86InstPF2IW, &dst, &src); } //! @brief Packed SP-FP Accumulate (3dNow!). inline void pfacc(const MmVar& dst, const MmVar& src) { _emitInstruction(kX86InstPFAcc, &dst, &src); } //! @brief Packed SP-FP Accumulate (3dNow!). inline void pfacc(const MmVar& dst, const Mem& src) { _emitInstruction(kX86InstPFAcc, &dst, &src); } //! @brief Packed SP-FP Addition (3dNow!). inline void pfadd(const MmVar& dst, const MmVar& src) { _emitInstruction(kX86InstPFAdd, &dst, &src); } //! @brief Packed SP-FP Addition (3dNow!). inline void pfadd(const MmVar& dst, const Mem& src) { _emitInstruction(kX86InstPFAdd, &dst, &src); } //! @brief Packed SP-FP Compare - dst == src (3dNow!). inline void pfcmpeq(const MmVar& dst, const MmVar& src) { _emitInstruction(kX86InstPFCmpEQ, &dst, &src); } //! @brief Packed SP-FP Compare - dst == src (3dNow!). inline void pfcmpeq(const MmVar& dst, const Mem& src) { _emitInstruction(kX86InstPFCmpEQ, &dst, &src); } //! @brief Packed SP-FP Compare - dst >= src (3dNow!). inline void pfcmpge(const MmVar& dst, const MmVar& src) { _emitInstruction(kX86InstPFCmpGE, &dst, &src); } //! @brief Packed SP-FP Compare - dst >= src (3dNow!). inline void pfcmpge(const MmVar& dst, const Mem& src) { _emitInstruction(kX86InstPFCmpGE, &dst, &src); } //! @brief Packed SP-FP Compare - dst > src (3dNow!). inline void pfcmpgt(const MmVar& dst, const MmVar& src) { _emitInstruction(kX86InstPFCmpGT, &dst, &src); } //! @brief Packed SP-FP Compare - dst > src (3dNow!). inline void pfcmpgt(const MmVar& dst, const Mem& src) { _emitInstruction(kX86InstPFCmpGT, &dst, &src); } //! @brief Packed SP-FP Maximum (3dNow!). inline void pfmax(const MmVar& dst, const MmVar& src) { _emitInstruction(kX86InstPFMax, &dst, &src); } //! @brief Packed SP-FP Maximum (3dNow!). inline void pfmax(const MmVar& dst, const Mem& src) { _emitInstruction(kX86InstPFMax, &dst, &src); } //! @brief Packed SP-FP Minimum (3dNow!). inline void pfmin(const MmVar& dst, const MmVar& src) { _emitInstruction(kX86InstPFMin, &dst, &src); } //! @brief Packed SP-FP Minimum (3dNow!). inline void pfmin(const MmVar& dst, const Mem& src) { _emitInstruction(kX86InstPFMin, &dst, &src); } //! @brief Packed SP-FP Multiply (3dNow!). inline void pfmul(const MmVar& dst, const MmVar& src) { _emitInstruction(kX86InstPFMul, &dst, &src); } //! @brief Packed SP-FP Multiply (3dNow!). inline void pfmul(const MmVar& dst, const Mem& src) { _emitInstruction(kX86InstPFMul, &dst, &src); } //! @brief Packed SP-FP Negative Accumulate (3dNow!). inline void pfnacc(const MmVar& dst, const MmVar& src) { _emitInstruction(kX86InstPFNAcc, &dst, &src); } //! @brief Packed SP-FP Negative Accumulate (3dNow!). inline void pfnacc(const MmVar& dst, const Mem& src) { _emitInstruction(kX86InstPFNAcc, &dst, &src); } //! @brief Packed SP-FP Mixed Accumulate (3dNow!). inline void pfpnacc(const MmVar& dst, const MmVar& src) { _emitInstruction(kX86InstPFPNAcc, &dst, &src); } //! @brief Packed SP-FP Mixed Accumulate (3dNow!). inline void pfpnacc(const MmVar& dst, const Mem& src) { _emitInstruction(kX86InstPFPNAcc, &dst, &src); } //! @brief Packed SP-FP Reciprocal Approximation (3dNow!). inline void pfrcp(const MmVar& dst, const MmVar& src) { _emitInstruction(kX86InstPFRcp, &dst, &src); } //! @brief Packed SP-FP Reciprocal Approximation (3dNow!). inline void pfrcp(const MmVar& dst, const Mem& src) { _emitInstruction(kX86InstPFRcp, &dst, &src); } //! @brief Packed SP-FP Reciprocal, First Iteration Step (3dNow!). inline void pfrcpit1(const MmVar& dst, const MmVar& src) { _emitInstruction(kX86InstPFRcpIt1, &dst, &src); } //! @brief Packed SP-FP Reciprocal, First Iteration Step (3dNow!). inline void pfrcpit1(const MmVar& dst, const Mem& src) { _emitInstruction(kX86InstPFRcpIt1, &dst, &src); } //! @brief Packed SP-FP Reciprocal, Second Iteration Step (3dNow!). inline void pfrcpit2(const MmVar& dst, const MmVar& src) { _emitInstruction(kX86InstPFRcpIt2, &dst, &src); } //! @brief Packed SP-FP Reciprocal, Second Iteration Step (3dNow!). inline void pfrcpit2(const MmVar& dst, const Mem& src) { _emitInstruction(kX86InstPFRcpIt2, &dst, &src); } //! @brief Packed SP-FP Reciprocal Square Root, First Iteration Step (3dNow!). inline void pfrsqit1(const MmVar& dst, const MmVar& src) { _emitInstruction(kX86InstPFRSqIt1, &dst, &src); } //! @brief Packed SP-FP Reciprocal Square Root, First Iteration Step (3dNow!). inline void pfrsqit1(const MmVar& dst, const Mem& src) { _emitInstruction(kX86InstPFRSqIt1, &dst, &src); } //! @brief Packed SP-FP Reciprocal Square Root Approximation (3dNow!). inline void pfrsqrt(const MmVar& dst, const MmVar& src) { _emitInstruction(kX86InstPFRSqrt, &dst, &src); } //! @brief Packed SP-FP Reciprocal Square Root Approximation (3dNow!). inline void pfrsqrt(const MmVar& dst, const Mem& src) { _emitInstruction(kX86InstPFRSqrt, &dst, &src); } //! @brief Packed SP-FP Subtract (3dNow!). inline void pfsub(const MmVar& dst, const MmVar& src) { _emitInstruction(kX86InstPFSub, &dst, &src); } //! @brief Packed SP-FP Subtract (3dNow!). inline void pfsub(const MmVar& dst, const Mem& src) { _emitInstruction(kX86InstPFSub, &dst, &src); } //! @brief Packed SP-FP Reverse Subtract (3dNow!). inline void pfsubr(const MmVar& dst, const MmVar& src) { _emitInstruction(kX86InstPFSubR, &dst, &src); } //! @brief Packed SP-FP Reverse Subtract (3dNow!). inline void pfsubr(const MmVar& dst, const Mem& src) { _emitInstruction(kX86InstPFSubR, &dst, &src); } //! @brief Packed DWords to SP-FP (3dNow!). inline void pi2fd(const MmVar& dst, const MmVar& src) { _emitInstruction(kX86InstPI2FD, &dst, &src); } //! @brief Packed DWords to SP-FP (3dNow!). inline void pi2fd(const MmVar& dst, const Mem& src) { _emitInstruction(kX86InstPI2FD, &dst, &src); } //! @brief Packed Words to SP-FP (3dNow!). inline void pi2fw(const MmVar& dst, const MmVar& src) { _emitInstruction(kX86InstPI2FW, &dst, &src); } //! @brief Packed Words to SP-FP (3dNow!). inline void pi2fw(const MmVar& dst, const Mem& src) { _emitInstruction(kX86InstPI2FW, &dst, &src); } //! @brief Packed swap DWord (3dNow!) inline void pswapd(const MmVar& dst, const MmVar& src) { _emitInstruction(kX86InstPSwapD, &dst, &src); } //! @brief Packed swap DWord (3dNow!) inline void pswapd(const MmVar& dst, const Mem& src) { _emitInstruction(kX86InstPSwapD, &dst, &src); } // -------------------------------------------------------------------------- // [SSE] // -------------------------------------------------------------------------- //! @brief Packed SP-FP Add (SSE). inline void addps(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstAddPS, &dst, &src); } //! @brief Packed SP-FP Add (SSE). inline void addps(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstAddPS, &dst, &src); } //! @brief Scalar SP-FP Add (SSE). inline void addss(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstAddSS, &dst, &src); } //! @brief Scalar SP-FP Add (SSE). inline void addss(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstAddSS, &dst, &src); } //! @brief Bit-wise Logical And Not For SP-FP (SSE). inline void andnps(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstAndnPS, &dst, &src); } //! @brief Bit-wise Logical And Not For SP-FP (SSE). inline void andnps(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstAndnPS, &dst, &src); } //! @brief Bit-wise Logical And For SP-FP (SSE). inline void andps(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstAndPS, &dst, &src); } //! @brief Bit-wise Logical And For SP-FP (SSE). inline void andps(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstAndPS, &dst, &src); } //! @brief Packed SP-FP Compare (SSE). inline void cmpps(const XmmVar& dst, const XmmVar& src, const Imm& imm8) { _emitInstruction(kX86InstCmpPS, &dst, &src, &imm8); } //! @brief Packed SP-FP Compare (SSE). inline void cmpps(const XmmVar& dst, const Mem& src, const Imm& imm8) { _emitInstruction(kX86InstCmpPS, &dst, &src, &imm8); } //! @brief Compare Scalar SP-FP Values (SSE). inline void cmpss(const XmmVar& dst, const XmmVar& src, const Imm& imm8) { _emitInstruction(kX86InstCmpSS, &dst, &src, &imm8); } //! @brief Compare Scalar SP-FP Values (SSE). inline void cmpss(const XmmVar& dst, const Mem& src, const Imm& imm8) { _emitInstruction(kX86InstCmpSS, &dst, &src, &imm8); } //! @brief Scalar Ordered SP-FP Compare and Set EFLAGS (SSE). inline void comiss(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstComISS, &dst, &src); } //! @brief Scalar Ordered SP-FP Compare and Set EFLAGS (SSE). inline void comiss(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstComISS, &dst, &src); } //! @brief Packed Signed INT32 to Packed SP-FP Conversion (SSE). inline void cvtpi2ps(const XmmVar& dst, const MmVar& src) { _emitInstruction(kX86InstCvtPI2PS, &dst, &src); } //! @brief Packed Signed INT32 to Packed SP-FP Conversion (SSE). inline void cvtpi2ps(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstCvtPI2PS, &dst, &src); } //! @brief Packed SP-FP to Packed INT32 Conversion (SSE). inline void cvtps2pi(const MmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstCvtPS2PI, &dst, &src); } //! @brief Packed SP-FP to Packed INT32 Conversion (SSE). inline void cvtps2pi(const MmVar& dst, const Mem& src) { _emitInstruction(kX86InstCvtPS2PI, &dst, &src); } //! @brief Scalar Signed INT32 to SP-FP Conversion (SSE). inline void cvtsi2ss(const XmmVar& dst, const GpVar& src) { _emitInstruction(kX86InstCvtSI2SS, &dst, &src); } //! @brief Scalar Signed INT32 to SP-FP Conversion (SSE). inline void cvtsi2ss(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstCvtSI2SS, &dst, &src); } //! @brief Scalar SP-FP to Signed INT32 Conversion (SSE). inline void cvtss2si(const GpVar& dst, const XmmVar& src) { _emitInstruction(kX86InstCvtSS2SI, &dst, &src); } //! @brief Scalar SP-FP to Signed INT32 Conversion (SSE). inline void cvtss2si(const GpVar& dst, const Mem& src) { _emitInstruction(kX86InstCvtSS2SI, &dst, &src); } //! @brief Packed SP-FP to Packed INT32 Conversion (truncate) (SSE). inline void cvttps2pi(const MmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstCvttPS2PI, &dst, &src); } //! @brief Packed SP-FP to Packed INT32 Conversion (truncate) (SSE). inline void cvttps2pi(const MmVar& dst, const Mem& src) { _emitInstruction(kX86InstCvttPS2PI, &dst, &src); } //! @brief Scalar SP-FP to Signed INT32 Conversion (truncate) (SSE). inline void cvttss2si(const GpVar& dst, const XmmVar& src) { _emitInstruction(kX86InstCvttSS2SI, &dst, &src); } //! @brief Scalar SP-FP to Signed INT32 Conversion (truncate) (SSE). inline void cvttss2si(const GpVar& dst, const Mem& src) { _emitInstruction(kX86InstCvttSS2SI, &dst, &src); } //! @brief Packed SP-FP Divide (SSE). inline void divps(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstDivPS, &dst, &src); } //! @brief Packed SP-FP Divide (SSE). inline void divps(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstDivPS, &dst, &src); } //! @brief Scalar SP-FP Divide (SSE). inline void divss(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstDivSS, &dst, &src); } //! @brief Scalar SP-FP Divide (SSE). inline void divss(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstDivSS, &dst, &src); } //! @brief Load Streaming SIMD Extension Control/Status (SSE). inline void ldmxcsr(const Mem& src) { _emitInstruction(kX86InstLdMXCSR, &src); } //! @brief Byte Mask Write (SSE). //! //! @note The default memory location is specified by DS:EDI. inline void maskmovq(const GpVar& dst_ptr, const MmVar& data, const MmVar& mask) { _emitInstruction(kX86InstMaskMovQ, &dst_ptr, &data, &mask); } //! @brief Packed SP-FP Maximum (SSE). inline void maxps(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstMaxPS, &dst, &src); } //! @brief Packed SP-FP Maximum (SSE). inline void maxps(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstMaxPS, &dst, &src); } //! @brief Scalar SP-FP Maximum (SSE). inline void maxss(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstMaxSS, &dst, &src); } //! @brief Scalar SP-FP Maximum (SSE). inline void maxss(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstMaxSS, &dst, &src); } //! @brief Packed SP-FP Minimum (SSE). inline void minps(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstMinPS, &dst, &src); } //! @brief Packed SP-FP Minimum (SSE). inline void minps(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstMinPS, &dst, &src); } //! @brief Scalar SP-FP Minimum (SSE). inline void minss(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstMinSS, &dst, &src); } //! @brief Scalar SP-FP Minimum (SSE). inline void minss(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstMinSS, &dst, &src); } //! @brief Move Aligned Packed SP-FP Values (SSE). inline void movaps(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstMovAPS, &dst, &src); } //! @brief Move Aligned Packed SP-FP Values (SSE). inline void movaps(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstMovAPS, &dst, &src); } //! @brief Move Aligned Packed SP-FP Values (SSE). inline void movaps(const Mem& dst, const XmmVar& src) { _emitInstruction(kX86InstMovAPS, &dst, &src); } //! @brief Move DWord. inline void movd(const Mem& dst, const XmmVar& src) { _emitInstruction(kX86InstMovD, &dst, &src); } //! @brief Move DWord. inline void movd(const GpVar& dst, const XmmVar& src) { _emitInstruction(kX86InstMovD, &dst, &src); } //! @brief Move DWord. inline void movd(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstMovD, &dst, &src); } //! @brief Move DWord. inline void movd(const XmmVar& dst, const GpVar& src) { _emitInstruction(kX86InstMovD, &dst, &src); } //! @brief Move QWord (SSE). inline void movq(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstMovQ, &dst, &src); } //! @brief Move QWord (SSE). inline void movq(const Mem& dst, const XmmVar& src) { _emitInstruction(kX86InstMovQ, &dst, &src); } #if defined(ASMJIT_X64) //! @brief Move QWord (SSE). inline void movq(const GpVar& dst, const XmmVar& src) { _emitInstruction(kX86InstMovQ, &dst, &src); } #endif // ASMJIT_X64 //! @brief Move QWord (SSE). inline void movq(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstMovQ, &dst, &src); } #if defined(ASMJIT_X64) //! @brief Move QWord (SSE). inline void movq(const XmmVar& dst, const GpVar& src) { _emitInstruction(kX86InstMovQ, &dst, &src); } #endif // ASMJIT_X64 //! @brief Move 64 Bits Non Temporal (SSE). inline void movntq(const Mem& dst, const MmVar& src) { _emitInstruction(kX86InstMovNTQ, &dst, &src); } //! @brief High to Low Packed SP-FP (SSE). inline void movhlps(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstMovHLPS, &dst, &src); } //! @brief Move High Packed SP-FP (SSE). inline void movhps(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstMovHPS, &dst, &src); } //! @brief Move High Packed SP-FP (SSE). inline void movhps(const Mem& dst, const XmmVar& src) { _emitInstruction(kX86InstMovHPS, &dst, &src); } //! @brief Move Low to High Packed SP-FP (SSE). inline void movlhps(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstMovLHPS, &dst, &src); } //! @brief Move Low Packed SP-FP (SSE). inline void movlps(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstMovLPS, &dst, &src); } //! @brief Move Low Packed SP-FP (SSE). inline void movlps(const Mem& dst, const XmmVar& src) { _emitInstruction(kX86InstMovLPS, &dst, &src); } //! @brief Move Aligned Four Packed SP-FP Non Temporal (SSE). inline void movntps(const Mem& dst, const XmmVar& src) { _emitInstruction(kX86InstMovNTPS, &dst, &src); } //! @brief Move Scalar SP-FP (SSE). inline void movss(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstMovSS, &dst, &src); } //! @brief Move Scalar SP-FP (SSE). inline void movss(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstMovSS, &dst, &src); } //! @brief Move Scalar SP-FP (SSE). inline void movss(const Mem& dst, const XmmVar& src) { _emitInstruction(kX86InstMovSS, &dst, &src); } //! @brief Move Unaligned Packed SP-FP Values (SSE). inline void movups(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstMovUPS, &dst, &src); } //! @brief Move Unaligned Packed SP-FP Values (SSE). inline void movups(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstMovUPS, &dst, &src); } //! @brief Move Unaligned Packed SP-FP Values (SSE). inline void movups(const Mem& dst, const XmmVar& src) { _emitInstruction(kX86InstMovUPS, &dst, &src); } //! @brief Packed SP-FP Multiply (SSE). inline void mulps(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstMulPS, &dst, &src); } //! @brief Packed SP-FP Multiply (SSE). inline void mulps(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstMulPS, &dst, &src); } //! @brief Scalar SP-FP Multiply (SSE). inline void mulss(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstMulSS, &dst, &src); } //! @brief Scalar SP-FP Multiply (SSE). inline void mulss(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstMulSS, &dst, &src); } //! @brief Bit-wise Logical OR for SP-FP Data (SSE). inline void orps(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstOrPS, &dst, &src); } //! @brief Bit-wise Logical OR for SP-FP Data (SSE). inline void orps(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstOrPS, &dst, &src); } //! @brief Packed Average (SSE). inline void pavgb(const MmVar& dst, const MmVar& src) { _emitInstruction(kX86InstPAvgB, &dst, &src); } //! @brief Packed Average (SSE). inline void pavgb(const MmVar& dst, const Mem& src) { _emitInstruction(kX86InstPAvgB, &dst, &src); } //! @brief Packed Average (SSE). inline void pavgw(const MmVar& dst, const MmVar& src) { _emitInstruction(kX86InstPAvgW, &dst, &src); } //! @brief Packed Average (SSE). inline void pavgw(const MmVar& dst, const Mem& src) { _emitInstruction(kX86InstPAvgW, &dst, &src); } //! @brief Extract Word (SSE). inline void pextrw(const GpVar& dst, const MmVar& src, const Imm& imm8) { _emitInstruction(kX86InstPExtrW, &dst, &src, &imm8); } //! @brief Insert Word (SSE). inline void pinsrw(const MmVar& dst, const GpVar& src, const Imm& imm8) { _emitInstruction(kX86InstPInsRW, &dst, &src, &imm8); } //! @brief Insert Word (SSE). inline void pinsrw(const MmVar& dst, const Mem& src, const Imm& imm8) { _emitInstruction(kX86InstPInsRW, &dst, &src, &imm8); } //! @brief Packed Signed Integer Word Maximum (SSE). inline void pmaxsw(const MmVar& dst, const MmVar& src) { _emitInstruction(kX86InstPMaxSW, &dst, &src); } //! @brief Packed Signed Integer Word Maximum (SSE). inline void pmaxsw(const MmVar& dst, const Mem& src) { _emitInstruction(kX86InstPMaxSW, &dst, &src); } //! @brief Packed Unsigned Integer Byte Maximum (SSE). inline void pmaxub(const MmVar& dst, const MmVar& src) { _emitInstruction(kX86InstPMaxUB, &dst, &src); } //! @brief Packed Unsigned Integer Byte Maximum (SSE). inline void pmaxub(const MmVar& dst, const Mem& src) { _emitInstruction(kX86InstPMaxUB, &dst, &src); } //! @brief Packed Signed Integer Word Minimum (SSE). inline void pminsw(const MmVar& dst, const MmVar& src) { _emitInstruction(kX86InstPMinSW, &dst, &src); } //! @brief Packed Signed Integer Word Minimum (SSE). inline void pminsw(const MmVar& dst, const Mem& src) { _emitInstruction(kX86InstPMinSW, &dst, &src); } //! @brief Packed Unsigned Integer Byte Minimum (SSE). inline void pminub(const MmVar& dst, const MmVar& src) { _emitInstruction(kX86InstPMinUB, &dst, &src); } //! @brief Packed Unsigned Integer Byte Minimum (SSE). inline void pminub(const MmVar& dst, const Mem& src) { _emitInstruction(kX86InstPMinUB, &dst, &src); } //! @brief Move Byte Mask To Integer (SSE). inline void pmovmskb(const GpVar& dst, const MmVar& src) { _emitInstruction(kX86InstPMovMskB, &dst, &src); } //! @brief Packed Multiply High Unsigned (SSE). inline void pmulhuw(const MmVar& dst, const MmVar& src) { _emitInstruction(kX86InstPMulHUW, &dst, &src); } //! @brief Packed Multiply High Unsigned (SSE). inline void pmulhuw(const MmVar& dst, const Mem& src) { _emitInstruction(kX86InstPMulHUW, &dst, &src); } //! @brief Packed Sum of Absolute Differences (SSE). inline void psadbw(const MmVar& dst, const MmVar& src) { _emitInstruction(kX86InstPSADBW, &dst, &src); } //! @brief Packed Sum of Absolute Differences (SSE). inline void psadbw(const MmVar& dst, const Mem& src) { _emitInstruction(kX86InstPSADBW, &dst, &src); } //! @brief Packed Shuffle word (SSE). inline void pshufw(const MmVar& dst, const MmVar& src, const Imm& imm8) { _emitInstruction(kX86InstPShufW, &dst, &src, &imm8); } //! @brief Packed Shuffle word (SSE). inline void pshufw(const MmVar& dst, const Mem& src, const Imm& imm8) { _emitInstruction(kX86InstPShufW, &dst, &src, &imm8); } //! @brief Packed SP-FP Reciprocal (SSE). inline void rcpps(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstRcpPS, &dst, &src); } //! @brief Packed SP-FP Reciprocal (SSE). inline void rcpps(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstRcpPS, &dst, &src); } //! @brief Scalar SP-FP Reciprocal (SSE). inline void rcpss(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstRcpSS, &dst, &src); } //! @brief Scalar SP-FP Reciprocal (SSE). inline void rcpss(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstRcpSS, &dst, &src); } //! @brief Prefetch (SSE). inline void prefetch(const Mem& mem, const Imm& hint) { _emitInstruction(kX86InstPrefetch, &mem, &hint); } //! @brief Compute Sum of Absolute Differences (SSE). inline void psadbw(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstPSADBW, &dst, &src); } //! @brief Compute Sum of Absolute Differences (SSE). inline void psadbw(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstPSADBW, &dst, &src); } //! @brief Packed SP-FP Square Root Reciprocal (SSE). inline void rsqrtps(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstSqrtPS, &dst, &src); } //! @brief Packed SP-FP Square Root Reciprocal (SSE). inline void rsqrtps(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstSqrtPS, &dst, &src); } //! @brief Scalar SP-FP Square Root Reciprocal (SSE). inline void rsqrtss(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstSqrtSS, &dst, &src); } //! @brief Scalar SP-FP Square Root Reciprocal (SSE). inline void rsqrtss(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstSqrtSS, &dst, &src); } //! @brief Store fence (SSE). inline void sfence() { _emitInstruction(kX86InstSFence); } //! @brief Shuffle SP-FP (SSE). inline void shufps(const XmmVar& dst, const XmmVar& src, const Imm& imm8) { _emitInstruction(kX86InstShufPS, &dst, &src, &imm8); } //! @brief Shuffle SP-FP (SSE). inline void shufps(const XmmVar& dst, const Mem& src, const Imm& imm8) { _emitInstruction(kX86InstShufPS, &dst, &src, &imm8); } //! @brief Packed SP-FP Square Root (SSE). inline void sqrtps(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstSqrtPS, &dst, &src); } //! @brief Packed SP-FP Square Root (SSE). inline void sqrtps(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstSqrtPS, &dst, &src); } //! @brief Scalar SP-FP Square Root (SSE). inline void sqrtss(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstSqrtSS, &dst, &src); } //! @brief Scalar SP-FP Square Root (SSE). inline void sqrtss(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstSqrtSS, &dst, &src); } //! @brief Store Streaming SIMD Extension Control/Status (SSE). inline void stmxcsr(const Mem& dst) { _emitInstruction(kX86InstStMXCSR, &dst); } //! @brief Packed SP-FP Subtract (SSE). inline void subps(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstSubPS, &dst, &src); } //! @brief Packed SP-FP Subtract (SSE). inline void subps(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstSubPS, &dst, &src); } //! @brief Scalar SP-FP Subtract (SSE). inline void subss(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstSubSS, &dst, &src); } //! @brief Scalar SP-FP Subtract (SSE). inline void subss(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstSubSS, &dst, &src); } //! @brief Unordered Scalar SP-FP compare and set EFLAGS (SSE). inline void ucomiss(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstUComISS, &dst, &src); } //! @brief Unordered Scalar SP-FP compare and set EFLAGS (SSE). inline void ucomiss(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstUComISS, &dst, &src); } //! @brief Unpack High Packed SP-FP Data (SSE). inline void unpckhps(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstUnpckHPS, &dst, &src); } //! @brief Unpack High Packed SP-FP Data (SSE). inline void unpckhps(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstUnpckHPS, &dst, &src); } //! @brief Unpack Low Packed SP-FP Data (SSE). inline void unpcklps(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstUnpckLPS, &dst, &src); } //! @brief Unpack Low Packed SP-FP Data (SSE). inline void unpcklps(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstUnpckLPS, &dst, &src); } //! @brief Bit-wise Logical Xor for SP-FP Data (SSE). inline void xorps(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstXorPS, &dst, &src); } //! @brief Bit-wise Logical Xor for SP-FP Data (SSE). inline void xorps(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstXorPS, &dst, &src); } // -------------------------------------------------------------------------- // [SSE2] // -------------------------------------------------------------------------- //! @brief Packed DP-FP Add (SSE2). inline void addpd(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstAddPD, &dst, &src); } //! @brief Packed DP-FP Add (SSE2). inline void addpd(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstAddPD, &dst, &src); } //! @brief Scalar DP-FP Add (SSE2). inline void addsd(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstAddSD, &dst, &src); } //! @brief Scalar DP-FP Add (SSE2). inline void addsd(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstAddSD, &dst, &src); } //! @brief Bit-wise Logical And Not For DP-FP (SSE2). inline void andnpd(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstAndnPD, &dst, &src); } //! @brief Bit-wise Logical And Not For DP-FP (SSE2). inline void andnpd(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstAndnPD, &dst, &src); } //! @brief Bit-wise Logical And For DP-FP (SSE2). inline void andpd(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstAndPD, &dst, &src); } //! @brief Bit-wise Logical And For DP-FP (SSE2). inline void andpd(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstAndPD, &dst, &src); } //! @brief Flush Cache Line (SSE2). inline void clflush(const Mem& mem) { _emitInstruction(kX86InstClFlush, &mem); } //! @brief Packed DP-FP Compare (SSE2). inline void cmppd(const XmmVar& dst, const XmmVar& src, const Imm& imm8) { _emitInstruction(kX86InstCmpPD, &dst, &src, &imm8); } //! @brief Packed DP-FP Compare (SSE2). inline void cmppd(const XmmVar& dst, const Mem& src, const Imm& imm8) { _emitInstruction(kX86InstCmpPD, &dst, &src, &imm8); } //! @brief Compare Scalar SP-FP Values (SSE2). inline void cmpsd(const XmmVar& dst, const XmmVar& src, const Imm& imm8) { _emitInstruction(kX86InstCmpSD, &dst, &src, &imm8); } //! @brief Compare Scalar SP-FP Values (SSE2). inline void cmpsd(const XmmVar& dst, const Mem& src, const Imm& imm8) { _emitInstruction(kX86InstCmpSD, &dst, &src, &imm8); } //! @brief Scalar Ordered DP-FP Compare and Set EFLAGS (SSE2). inline void comisd(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstComISD, &dst, &src); } //! @brief Scalar Ordered DP-FP Compare and Set EFLAGS (SSE2). inline void comisd(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstComISD, &dst, &src); } //! @brief Convert Packed Dword Integers to Packed DP-FP Values (SSE2). inline void cvtdq2pd(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstCvtDQ2PD, &dst, &src); } //! @brief Convert Packed Dword Integers to Packed DP-FP Values (SSE2). inline void cvtdq2pd(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstCvtDQ2PD, &dst, &src); } //! @brief Convert Packed Dword Integers to Packed SP-FP Values (SSE2). inline void cvtdq2ps(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstCvtDQ2PS, &dst, &src); } //! @brief Convert Packed Dword Integers to Packed SP-FP Values (SSE2). inline void cvtdq2ps(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstCvtDQ2PS, &dst, &src); } //! @brief Convert Packed DP-FP Values to Packed Dword Integers (SSE2). inline void cvtpd2dq(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstCvtPD2DQ, &dst, &src); } //! @brief Convert Packed DP-FP Values to Packed Dword Integers (SSE2). inline void cvtpd2dq(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstCvtPD2DQ, &dst, &src); } //! @brief Convert Packed DP-FP Values to Packed Dword Integers (SSE2). inline void cvtpd2pi(const MmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstCvtPD2PI, &dst, &src); } //! @brief Convert Packed DP-FP Values to Packed Dword Integers (SSE2). inline void cvtpd2pi(const MmVar& dst, const Mem& src) { _emitInstruction(kX86InstCvtPD2PI, &dst, &src); } //! @brief Convert Packed DP-FP Values to Packed SP-FP Values (SSE2). inline void cvtpd2ps(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstCvtPD2PS, &dst, &src); } //! @brief Convert Packed DP-FP Values to Packed SP-FP Values (SSE2). inline void cvtpd2ps(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstCvtPD2PS, &dst, &src); } //! @brief Convert Packed Dword Integers to Packed DP-FP Values (SSE2). inline void cvtpi2pd(const XmmVar& dst, const MmVar& src) { _emitInstruction(kX86InstCvtPI2PD, &dst, &src); } //! @brief Convert Packed Dword Integers to Packed DP-FP Values (SSE2). inline void cvtpi2pd(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstCvtPI2PD, &dst, &src); } //! @brief Convert Packed SP-FP Values to Packed Dword Integers (SSE2). inline void cvtps2dq(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstCvtPS2DQ, &dst, &src); } //! @brief Convert Packed SP-FP Values to Packed Dword Integers (SSE2). inline void cvtps2dq(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstCvtPS2DQ, &dst, &src); } //! @brief Convert Packed SP-FP Values to Packed DP-FP Values (SSE2). inline void cvtps2pd(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstCvtPS2PD, &dst, &src); } //! @brief Convert Packed SP-FP Values to Packed DP-FP Values (SSE2). inline void cvtps2pd(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstCvtPS2PD, &dst, &src); } //! @brief Convert Scalar DP-FP Value to Dword Integer (SSE2). inline void cvtsd2si(const GpVar& dst, const XmmVar& src) { _emitInstruction(kX86InstCvtSD2SI, &dst, &src); } //! @brief Convert Scalar DP-FP Value to Dword Integer (SSE2). inline void cvtsd2si(const GpVar& dst, const Mem& src) { _emitInstruction(kX86InstCvtSD2SI, &dst, &src); } //! @brief Convert Scalar DP-FP Value to Scalar SP-FP Value (SSE2). inline void cvtsd2ss(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstCvtSD2SS, &dst, &src); } //! @brief Convert Scalar DP-FP Value to Scalar SP-FP Value (SSE2). inline void cvtsd2ss(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstCvtSD2SS, &dst, &src); } //! @brief Convert Dword Integer to Scalar DP-FP Value (SSE2). inline void cvtsi2sd(const XmmVar& dst, const GpVar& src) { _emitInstruction(kX86InstCvtSI2SD, &dst, &src); } //! @brief Convert Dword Integer to Scalar DP-FP Value (SSE2). inline void cvtsi2sd(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstCvtSI2SD, &dst, &src); } //! @brief Convert Scalar SP-FP Value to Scalar DP-FP Value (SSE2). inline void cvtss2sd(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstCvtSS2SD, &dst, &src); } //! @brief Convert Scalar SP-FP Value to Scalar DP-FP Value (SSE2). inline void cvtss2sd(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstCvtSS2SD, &dst, &src); } //! @brief Convert with Truncation Packed DP-FP Values to Packed Dword Integers (SSE2). inline void cvttpd2pi(const MmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstCvttPD2PI, &dst, &src); } //! @brief Convert with Truncation Packed DP-FP Values to Packed Dword Integers (SSE2). inline void cvttpd2pi(const MmVar& dst, const Mem& src) { _emitInstruction(kX86InstCvttPD2PI, &dst, &src); } //! @brief Convert with Truncation Packed DP-FP Values to Packed Dword Integers (SSE2). inline void cvttpd2dq(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstCvttPD2DQ, &dst, &src); } //! @brief Convert with Truncation Packed DP-FP Values to Packed Dword Integers (SSE2). inline void cvttpd2dq(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstCvttPD2DQ, &dst, &src); } //! @brief Convert with Truncation Packed SP-FP Values to Packed Dword Integers (SSE2). inline void cvttps2dq(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstCvttPS2DQ, &dst, &src); } //! @brief Convert with Truncation Packed SP-FP Values to Packed Dword Integers (SSE2). inline void cvttps2dq(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstCvttPS2DQ, &dst, &src); } //! @brief Convert with Truncation Scalar DP-FP Value to Signed Dword Integer (SSE2). inline void cvttsd2si(const GpVar& dst, const XmmVar& src) { _emitInstruction(kX86InstCvttSD2SI, &dst, &src); } //! @brief Convert with Truncation Scalar DP-FP Value to Signed Dword Integer (SSE2). inline void cvttsd2si(const GpVar& dst, const Mem& src) { _emitInstruction(kX86InstCvttSD2SI, &dst, &src); } //! @brief Packed DP-FP Divide (SSE2). inline void divpd(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstDivPD, &dst, &src); } //! @brief Packed DP-FP Divide (SSE2). inline void divpd(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstDivPD, &dst, &src); } //! @brief Scalar DP-FP Divide (SSE2). inline void divsd(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstDivSD, &dst, &src); } //! @brief Scalar DP-FP Divide (SSE2). inline void divsd(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstDivSD, &dst, &src); } //! @brief Load Fence (SSE2). inline void lfence() { _emitInstruction(kX86InstLFence); } //! @brief Store Selected Bytes of Double Quadword (SSE2). //! //! @note Target is DS:EDI. inline void maskmovdqu(const GpVar& dst_ptr, const XmmVar& src, const XmmVar& mask) { _emitInstruction(kX86InstMaskMovDQU, &dst_ptr, &src, &mask); } //! @brief Return Maximum Packed Double-Precision FP Values (SSE2). inline void maxpd(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstMaxPD, &dst, &src); } //! @brief Return Maximum Packed Double-Precision FP Values (SSE2). inline void maxpd(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstMaxPD, &dst, &src); } //! @brief Return Maximum Scalar Double-Precision FP Value (SSE2). inline void maxsd(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstMaxSD, &dst, &src); } //! @brief Return Maximum Scalar Double-Precision FP Value (SSE2). inline void maxsd(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstMaxSD, &dst, &src); } //! @brief Memory Fence (SSE2). inline void mfence() { _emitInstruction(kX86InstMFence); } //! @brief Return Minimum Packed DP-FP Values (SSE2). inline void minpd(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstMinPD, &dst, &src); } //! @brief Return Minimum Packed DP-FP Values (SSE2). inline void minpd(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstMinPD, &dst, &src); } //! @brief Return Minimum Scalar DP-FP Value (SSE2). inline void minsd(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstMinSD, &dst, &src); } //! @brief Return Minimum Scalar DP-FP Value (SSE2). inline void minsd(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstMinSD, &dst, &src); } //! @brief Move Aligned DQWord (SSE2). inline void movdqa(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstMovDQA, &dst, &src); } //! @brief Move Aligned DQWord (SSE2). inline void movdqa(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstMovDQA, &dst, &src); } //! @brief Move Aligned DQWord (SSE2). inline void movdqa(const Mem& dst, const XmmVar& src) { _emitInstruction(kX86InstMovDQA, &dst, &src); } //! @brief Move Unaligned Double Quadword (SSE2). inline void movdqu(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstMovDQU, &dst, &src); } //! @brief Move Unaligned Double Quadword (SSE2). inline void movdqu(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstMovDQU, &dst, &src); } //! @brief Move Unaligned Double Quadword (SSE2). inline void movdqu(const Mem& dst, const XmmVar& src) { _emitInstruction(kX86InstMovDQU, &dst, &src); } //! @brief Extract Packed SP-FP Sign Mask (SSE2). inline void movmskps(const GpVar& dst, const XmmVar& src) { _emitInstruction(kX86InstMovMskPS, &dst, &src); } //! @brief Extract Packed DP-FP Sign Mask (SSE2). inline void movmskpd(const GpVar& dst, const XmmVar& src) { _emitInstruction(kX86InstMovMskPD, &dst, &src); } //! @brief Move Scalar Double-Precision FP Value (SSE2). inline void movsd(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstMovSD, &dst, &src); } //! @brief Move Scalar Double-Precision FP Value (SSE2). inline void movsd(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstMovSD, &dst, &src); } //! @brief Move Scalar Double-Precision FP Value (SSE2). inline void movsd(const Mem& dst, const XmmVar& src) { _emitInstruction(kX86InstMovSD, &dst, &src); } //! @brief Move Aligned Packed Double-Precision FP Values (SSE2). inline void movapd(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstMovAPD, &dst, &src); } //! @brief Move Aligned Packed Double-Precision FP Values (SSE2). inline void movapd(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstMovAPD, &dst, &src); } //! @brief Move Aligned Packed Double-Precision FP Values (SSE2). inline void movapd(const Mem& dst, const XmmVar& src) { _emitInstruction(kX86InstMovAPD, &dst, &src); } //! @brief Move Quadword from XMM to MMX Technology Register (SSE2). inline void movdq2q(const MmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstMovDQ2Q, &dst, &src); } //! @brief Move Quadword from MMX Technology to XMM Register (SSE2). inline void movq2dq(const XmmVar& dst, const MmVar& src) { _emitInstruction(kX86InstMovQ2DQ, &dst, &src); } //! @brief Move High Packed Double-Precision FP Value (SSE2). inline void movhpd(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstMovHPD, &dst, &src); } //! @brief Move High Packed Double-Precision FP Value (SSE2). inline void movhpd(const Mem& dst, const XmmVar& src) { _emitInstruction(kX86InstMovHPD, &dst, &src); } //! @brief Move Low Packed Double-Precision FP Value (SSE2). inline void movlpd(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstMovLPD, &dst, &src); } //! @brief Move Low Packed Double-Precision FP Value (SSE2). inline void movlpd(const Mem& dst, const XmmVar& src) { _emitInstruction(kX86InstMovLPD, &dst, &src); } //! @brief Store Double Quadword Using Non-Temporal Hint (SSE2). inline void movntdq(const Mem& dst, const XmmVar& src) { _emitInstruction(kX86InstMovNTDQ, &dst, &src); } //! @brief Store Store DWORD Using Non-Temporal Hint (SSE2). inline void movnti(const Mem& dst, const GpVar& src) { _emitInstruction(kX86InstMovNTI, &dst, &src); } //! @brief Store Packed Double-Precision FP Values Using Non-Temporal Hint (SSE2). inline void movntpd(const Mem& dst, const XmmVar& src) { _emitInstruction(kX86InstMovNTPD, &dst, &src); } //! @brief Move Unaligned Packed Double-Precision FP Values (SSE2). inline void movupd(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstMovUPD, &dst, &src); } //! @brief Move Unaligned Packed Double-Precision FP Values (SSE2). inline void movupd(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstMovUPD, &dst, &src); } //! @brief Move Unaligned Packed Double-Precision FP Values (SSE2). inline void movupd(const Mem& dst, const XmmVar& src) { _emitInstruction(kX86InstMovUPD, &dst, &src); } //! @brief Packed DP-FP Multiply (SSE2). inline void mulpd(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstMulPD, &dst, &src); } //! @brief Packed DP-FP Multiply (SSE2). inline void mulpd(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstMulPD, &dst, &src); } //! @brief Scalar DP-FP Multiply (SSE2). inline void mulsd(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstMulSD, &dst, &src); } //! @brief Scalar DP-FP Multiply (SSE2). inline void mulsd(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstMulSD, &dst, &src); } //! @brief Bit-wise Logical OR for DP-FP Data (SSE2). inline void orpd(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstOrPD, &dst, &src); } //! @brief Bit-wise Logical OR for DP-FP Data (SSE2). inline void orpd(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstOrPD, &dst, &src); } //! @brief Pack with Signed Saturation (SSE2). inline void packsswb(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstPackSSWB, &dst, &src); } //! @brief Pack with Signed Saturation (SSE2). inline void packsswb(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstPackSSWB, &dst, &src); } //! @brief Pack with Signed Saturation (SSE2). inline void packssdw(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstPackSSDW, &dst, &src); } //! @brief Pack with Signed Saturation (SSE2). inline void packssdw(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstPackSSDW, &dst, &src); } //! @brief Pack with Unsigned Saturation (SSE2). inline void packuswb(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstPackUSWB, &dst, &src); } //! @brief Pack with Unsigned Saturation (SSE2). inline void packuswb(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstPackUSWB, &dst, &src); } //! @brief Packed BYTE Add (SSE2). inline void paddb(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstPAddB, &dst, &src); } //! @brief Packed BYTE Add (SSE2). inline void paddb(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstPAddB, &dst, &src); } //! @brief Packed WORD Add (SSE2). inline void paddw(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstPAddW, &dst, &src); } //! @brief Packed WORD Add (SSE2). inline void paddw(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstPAddW, &dst, &src); } //! @brief Packed DWORD Add (SSE2). inline void paddd(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstPAddD, &dst, &src); } //! @brief Packed DWORD Add (SSE2). inline void paddd(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstPAddD, &dst, &src); } //! @brief Packed QWORD Add (SSE2). inline void paddq(const MmVar& dst, const MmVar& src) { _emitInstruction(kX86InstPAddQ, &dst, &src); } //! @brief Packed QWORD Add (SSE2). inline void paddq(const MmVar& dst, const Mem& src) { _emitInstruction(kX86InstPAddQ, &dst, &src); } //! @brief Packed QWORD Add (SSE2). inline void paddq(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstPAddQ, &dst, &src); } //! @brief Packed QWORD Add (SSE2). inline void paddq(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstPAddQ, &dst, &src); } //! @brief Packed Add with Saturation (SSE2). inline void paddsb(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstPAddSB, &dst, &src); } //! @brief Packed Add with Saturation (SSE2). inline void paddsb(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstPAddSB, &dst, &src); } //! @brief Packed Add with Saturation (SSE2). inline void paddsw(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstPAddSW, &dst, &src); } //! @brief Packed Add with Saturation (SSE2). inline void paddsw(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstPAddSW, &dst, &src); } //! @brief Packed Add Unsigned with Saturation (SSE2). inline void paddusb(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstPAddUSB, &dst, &src); } //! @brief Packed Add Unsigned with Saturation (SSE2). inline void paddusb(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstPAddUSB, &dst, &src); } //! @brief Packed Add Unsigned with Saturation (SSE2). inline void paddusw(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstPAddUSW, &dst, &src); } //! @brief Packed Add Unsigned with Saturation (SSE2). inline void paddusw(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstPAddUSW, &dst, &src); } //! @brief Logical AND (SSE2). inline void pand(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstPAnd, &dst, &src); } //! @brief Logical AND (SSE2). inline void pand(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstPAnd, &dst, &src); } //! @brief Logical AND Not (SSE2). inline void pandn(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstPAndN, &dst, &src); } //! @brief Logical AND Not (SSE2). inline void pandn(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstPAndN, &dst, &src); } //! @brief Spin Loop Hint (SSE2). inline void pause() { _emitInstruction(kX86InstPause); } //! @brief Packed Average (SSE2). inline void pavgb(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstPAvgB, &dst, &src); } //! @brief Packed Average (SSE2). inline void pavgb(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstPAvgB, &dst, &src); } //! @brief Packed Average (SSE2). inline void pavgw(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstPAvgW, &dst, &src); } //! @brief Packed Average (SSE2). inline void pavgw(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstPAvgW, &dst, &src); } //! @brief Packed Compare for Equal (BYTES) (SSE2). inline void pcmpeqb(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstPCmpEqB, &dst, &src); } //! @brief Packed Compare for Equal (BYTES) (SSE2). inline void pcmpeqb(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstPCmpEqB, &dst, &src); } //! @brief Packed Compare for Equal (WORDS) (SSE2). inline void pcmpeqw(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstPCmpEqW, &dst, &src); } //! @brief Packed Compare for Equal (WORDS) (SSE2). inline void pcmpeqw(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstPCmpEqW, &dst, &src); } //! @brief Packed Compare for Equal (DWORDS) (SSE2). inline void pcmpeqd(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstPCmpEqD, &dst, &src); } //! @brief Packed Compare for Equal (DWORDS) (SSE2). inline void pcmpeqd(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstPCmpEqD, &dst, &src); } //! @brief Packed Compare for Greater Than (BYTES) (SSE2). inline void pcmpgtb(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstPCmpGtB, &dst, &src); } //! @brief Packed Compare for Greater Than (BYTES) (SSE2). inline void pcmpgtb(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstPCmpGtB, &dst, &src); } //! @brief Packed Compare for Greater Than (WORDS) (SSE2). inline void pcmpgtw(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstPCmpGtW, &dst, &src); } //! @brief Packed Compare for Greater Than (WORDS) (SSE2). inline void pcmpgtw(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstPCmpGtW, &dst, &src); } //! @brief Packed Compare for Greater Than (DWORDS) (SSE2). inline void pcmpgtd(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstPCmpGtD, &dst, &src); } //! @brief Packed Compare for Greater Than (DWORDS) (SSE2). inline void pcmpgtd(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstPCmpGtD, &dst, &src); } //! @brief Extract Word (SSE2). inline void pextrw(const GpVar& dst, const XmmVar& src, const Imm& imm8) { _emitInstruction(kX86InstPExtrW, &dst, &src, &imm8); } //! @brief Extract Word (SSE2). inline void pextrw(const Mem& dst, const XmmVar& src, const Imm& imm8) { _emitInstruction(kX86InstPExtrW, &dst, &src, &imm8); } //! @brief Packed Signed Integer Word Maximum (SSE2). inline void pmaxsw(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstPMaxSW, &dst, &src); } //! @brief Packed Signed Integer Word Maximum (SSE2). inline void pmaxsw(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstPMaxSW, &dst, &src); } //! @brief Packed Unsigned Integer Byte Maximum (SSE2). inline void pmaxub(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstPMaxUB, &dst, &src); } //! @brief Packed Unsigned Integer Byte Maximum (SSE2). inline void pmaxub(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstPMaxUB, &dst, &src); } //! @brief Packed Signed Integer Word Minimum (SSE2). inline void pminsw(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstPMinSW, &dst, &src); } //! @brief Packed Signed Integer Word Minimum (SSE2). inline void pminsw(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstPMinSW, &dst, &src); } //! @brief Packed Unsigned Integer Byte Minimum (SSE2). inline void pminub(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstPMinUB, &dst, &src); } //! @brief Packed Unsigned Integer Byte Minimum (SSE2). inline void pminub(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstPMinUB, &dst, &src); } //! @brief Move Byte Mask (SSE2). inline void pmovmskb(const GpVar& dst, const XmmVar& src) { _emitInstruction(kX86InstPMovMskB, &dst, &src); } //! @brief Packed Multiply High (SSE2). inline void pmulhw(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstPMulHW, &dst, &src); } //! @brief Packed Multiply High (SSE2). inline void pmulhw(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstPMulHW, &dst, &src); } //! @brief Packed Multiply High Unsigned (SSE2). inline void pmulhuw(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstPMulHUW, &dst, &src); } //! @brief Packed Multiply High Unsigned (SSE2). inline void pmulhuw(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstPMulHUW, &dst, &src); } //! @brief Packed Multiply Low (SSE2). inline void pmullw(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstPMulLW, &dst, &src); } //! @brief Packed Multiply Low (SSE2). inline void pmullw(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstPMulLW, &dst, &src); } //! @brief Packed Multiply to QWORD (SSE2). inline void pmuludq(const MmVar& dst, const MmVar& src) { _emitInstruction(kX86InstPMulUDQ, &dst, &src); } //! @brief Packed Multiply to QWORD (SSE2). inline void pmuludq(const MmVar& dst, const Mem& src) { _emitInstruction(kX86InstPMulUDQ, &dst, &src); } //! @brief Packed Multiply to QWORD (SSE2). inline void pmuludq(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstPMulUDQ, &dst, &src); } //! @brief Packed Multiply to QWORD (SSE2). inline void pmuludq(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstPMulUDQ, &dst, &src); } //! @brief Bitwise Logical OR (SSE2). inline void por(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstPOr, &dst, &src); } //! @brief Bitwise Logical OR (SSE2). inline void por(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstPOr, &dst, &src); } //! @brief Packed Shift Left Logical (SSE2). inline void pslld(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstPSllD, &dst, &src); } //! @brief Packed Shift Left Logical (SSE2). inline void pslld(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstPSllD, &dst, &src); } //! @brief Packed Shift Left Logical (SSE2). inline void pslld(const XmmVar& dst, const Imm& src) { _emitInstruction(kX86InstPSllD, &dst, &src); } //! @brief Packed Shift Left Logical (SSE2). inline void psllq(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstPSllQ, &dst, &src); } //! @brief Packed Shift Left Logical (SSE2). inline void psllq(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstPSllQ, &dst, &src); } //! @brief Packed Shift Left Logical (SSE2). inline void psllq(const XmmVar& dst, const Imm& src) { _emitInstruction(kX86InstPSllQ, &dst, &src); } //! @brief Packed Shift Left Logical (SSE2). inline void psllw(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstPSllW, &dst, &src); } //! @brief Packed Shift Left Logical (SSE2). inline void psllw(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstPSllW, &dst, &src); } //! @brief Packed Shift Left Logical (SSE2). inline void psllw(const XmmVar& dst, const Imm& src) { _emitInstruction(kX86InstPSllW, &dst, &src); } //! @brief Packed Shift Left Logical (SSE2). inline void pslldq(const XmmVar& dst, const Imm& src) { _emitInstruction(kX86InstPSllDQ, &dst, &src); } //! @brief Packed Shift Right Arithmetic (SSE2). inline void psrad(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstPSraD, &dst, &src); } //! @brief Packed Shift Right Arithmetic (SSE2). inline void psrad(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstPSraD, &dst, &src); } //! @brief Packed Shift Right Arithmetic (SSE2). inline void psrad(const XmmVar& dst, const Imm& src) { _emitInstruction(kX86InstPSraD, &dst, &src); } //! @brief Packed Shift Right Arithmetic (SSE2). inline void psraw(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstPSraW, &dst, &src); } //! @brief Packed Shift Right Arithmetic (SSE2). inline void psraw(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstPSraW, &dst, &src); } //! @brief Packed Shift Right Arithmetic (SSE2). inline void psraw(const XmmVar& dst, const Imm& src) { _emitInstruction(kX86InstPSraW, &dst, &src); } //! @brief Packed Subtract (SSE2). inline void psubb(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstPSubB, &dst, &src); } //! @brief Packed Subtract (SSE2). inline void psubb(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstPSubB, &dst, &src); } //! @brief Packed Subtract (SSE2). inline void psubw(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstPSubW, &dst, &src); } //! @brief Packed Subtract (SSE2). inline void psubw(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstPSubW, &dst, &src); } //! @brief Packed Subtract (SSE2). inline void psubd(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstPSubD, &dst, &src); } //! @brief Packed Subtract (SSE2). inline void psubd(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstPSubD, &dst, &src); } //! @brief Packed Subtract (SSE2). inline void psubq(const MmVar& dst, const MmVar& src) { _emitInstruction(kX86InstPSubQ, &dst, &src); } //! @brief Packed Subtract (SSE2). inline void psubq(const MmVar& dst, const Mem& src) { _emitInstruction(kX86InstPSubQ, &dst, &src); } //! @brief Packed Subtract (SSE2). inline void psubq(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstPSubQ, &dst, &src); } //! @brief Packed Subtract (SSE2). inline void psubq(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstPSubQ, &dst, &src); } //! @brief Packed Multiply and Add (SSE2). inline void pmaddwd(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstPMAddWD, &dst, &src); } //! @brief Packed Multiply and Add (SSE2). inline void pmaddwd(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstPMAddWD, &dst, &src); } //! @brief Shuffle Packed DWORDs (SSE2). inline void pshufd(const XmmVar& dst, const XmmVar& src, const Imm& imm8) { _emitInstruction(kX86InstPShufD, &dst, &src, &imm8); } //! @brief Shuffle Packed DWORDs (SSE2). inline void pshufd(const XmmVar& dst, const Mem& src, const Imm& imm8) { _emitInstruction(kX86InstPShufD, &dst, &src, &imm8); } //! @brief Shuffle Packed High Words (SSE2). inline void pshufhw(const XmmVar& dst, const XmmVar& src, const Imm& imm8) { _emitInstruction(kX86InstPShufHW, &dst, &src, &imm8); } //! @brief Shuffle Packed High Words (SSE2). inline void pshufhw(const XmmVar& dst, const Mem& src, const Imm& imm8) { _emitInstruction(kX86InstPShufHW, &dst, &src, &imm8); } //! @brief Shuffle Packed Low Words (SSE2). inline void pshuflw(const XmmVar& dst, const XmmVar& src, const Imm& imm8) { _emitInstruction(kX86InstPShufLW, &dst, &src, &imm8); } //! @brief Shuffle Packed Low Words (SSE2). inline void pshuflw(const XmmVar& dst, const Mem& src, const Imm& imm8) { _emitInstruction(kX86InstPShufLW, &dst, &src, &imm8); } //! @brief Packed Shift Right Logical (SSE2). inline void psrld(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstPSrlD, &dst, &src); } //! @brief Packed Shift Right Logical (SSE2). inline void psrld(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstPSrlD, &dst, &src); } //! @brief Packed Shift Right Logical (SSE2). inline void psrld(const XmmVar& dst, const Imm& src) { _emitInstruction(kX86InstPSrlD, &dst, &src); } //! @brief Packed Shift Right Logical (SSE2). inline void psrlq(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstPSrlQ, &dst, &src); } //! @brief Packed Shift Right Logical (SSE2). inline void psrlq(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstPSrlQ, &dst, &src); } //! @brief Packed Shift Right Logical (SSE2). inline void psrlq(const XmmVar& dst, const Imm& src) { _emitInstruction(kX86InstPSrlQ, &dst, &src); } //! @brief DQWord Shift Right Logical (MMX). inline void psrldq(const XmmVar& dst, const Imm& src) { _emitInstruction(kX86InstPSrlDQ, &dst, &src); } //! @brief Packed Shift Right Logical (SSE2). inline void psrlw(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstPSrlW, &dst, &src); } //! @brief Packed Shift Right Logical (SSE2). inline void psrlw(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstPSrlW, &dst, &src); } //! @brief Packed Shift Right Logical (SSE2). inline void psrlw(const XmmVar& dst, const Imm& src) { _emitInstruction(kX86InstPSrlW, &dst, &src); } //! @brief Packed Subtract with Saturation (SSE2). inline void psubsb(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstPSubSB, &dst, &src); } //! @brief Packed Subtract with Saturation (SSE2). inline void psubsb(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstPSubSB, &dst, &src); } //! @brief Packed Subtract with Saturation (SSE2). inline void psubsw(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstPSubSW, &dst, &src); } //! @brief Packed Subtract with Saturation (SSE2). inline void psubsw(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstPSubSW, &dst, &src); } //! @brief Packed Subtract with Unsigned Saturation (SSE2). inline void psubusb(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstPSubUSB, &dst, &src); } //! @brief Packed Subtract with Unsigned Saturation (SSE2). inline void psubusb(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstPSubUSB, &dst, &src); } //! @brief Packed Subtract with Unsigned Saturation (SSE2). inline void psubusw(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstPSubUSW, &dst, &src); } //! @brief Packed Subtract with Unsigned Saturation (SSE2). inline void psubusw(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstPSubUSW, &dst, &src); } //! @brief Unpack High Data (SSE2). inline void punpckhbw(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstPunpckHBW, &dst, &src); } //! @brief Unpack High Data (SSE2). inline void punpckhbw(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstPunpckHBW, &dst, &src); } //! @brief Unpack High Data (SSE2). inline void punpckhwd(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstPunpckHWD, &dst, &src); } //! @brief Unpack High Data (SSE2). inline void punpckhwd(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstPunpckHWD, &dst, &src); } //! @brief Unpack High Data (SSE2). inline void punpckhdq(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstPunpckHDQ, &dst, &src); } //! @brief Unpack High Data (SSE2). inline void punpckhdq(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstPunpckHDQ, &dst, &src); } //! @brief Unpack High Data (SSE2). inline void punpckhqdq(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstPunpckHQDQ, &dst, &src); } //! @brief Unpack High Data (SSE2). inline void punpckhqdq(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstPunpckHQDQ, &dst, &src); } //! @brief Unpack Low Data (SSE2). inline void punpcklbw(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstPunpckLBW, &dst, &src); } //! @brief Unpack Low Data (SSE2). inline void punpcklbw(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstPunpckLBW, &dst, &src); } //! @brief Unpack Low Data (SSE2). inline void punpcklwd(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstPunpckLWD, &dst, &src); } //! @brief Unpack Low Data (SSE2). inline void punpcklwd(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstPunpckLWD, &dst, &src); } //! @brief Unpack Low Data (SSE2). inline void punpckldq(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstPunpckLDQ, &dst, &src); } //! @brief Unpack Low Data (SSE2). inline void punpckldq(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstPunpckLDQ, &dst, &src); } //! @brief Unpack Low Data (SSE2). inline void punpcklqdq(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstPunpckLQDQ, &dst, &src); } //! @brief Unpack Low Data (SSE2). inline void punpcklqdq(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstPunpckLQDQ, &dst, &src); } //! @brief Bitwise Exclusive OR (SSE2). inline void pxor(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstPXor, &dst, &src); } //! @brief Bitwise Exclusive OR (SSE2). inline void pxor(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstPXor, &dst, &src); } //! @brief Shuffle DP-FP (SSE2). inline void shufpd(const XmmVar& dst, const XmmVar& src, const Imm& imm8) { _emitInstruction(kX86InstShufPD, &dst, &src, &imm8); } //! @brief Shuffle DP-FP (SSE2). inline void shufpd(const XmmVar& dst, const Mem& src, const Imm& imm8) { _emitInstruction(kX86InstShufPD, &dst, &src, &imm8); } //! @brief Compute Square Roots of Packed DP-FP Values (SSE2). inline void sqrtpd(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstSqrtPD, &dst, &src); } //! @brief Compute Square Roots of Packed DP-FP Values (SSE2). inline void sqrtpd(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstSqrtPD, &dst, &src); } //! @brief Compute Square Root of Scalar DP-FP Value (SSE2). inline void sqrtsd(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstSqrtSD, &dst, &src); } //! @brief Compute Square Root of Scalar DP-FP Value (SSE2). inline void sqrtsd(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstSqrtSD, &dst, &src); } //! @brief Packed DP-FP Subtract (SSE2). inline void subpd(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstSubPD, &dst, &src); } //! @brief Packed DP-FP Subtract (SSE2). inline void subpd(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstSubPD, &dst, &src); } //! @brief Scalar DP-FP Subtract (SSE2). inline void subsd(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstSubSD, &dst, &src); } //! @brief Scalar DP-FP Subtract (SSE2). inline void subsd(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstSubSD, &dst, &src); } //! @brief Scalar Unordered DP-FP Compare and Set EFLAGS (SSE2). inline void ucomisd(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstUComISD, &dst, &src); } //! @brief Scalar Unordered DP-FP Compare and Set EFLAGS (SSE2). inline void ucomisd(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstUComISD, &dst, &src); } //! @brief Unpack and Interleave High Packed Double-Precision FP Values (SSE2). inline void unpckhpd(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstUnpckHPD, &dst, &src); } //! @brief Unpack and Interleave High Packed Double-Precision FP Values (SSE2). inline void unpckhpd(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstUnpckHPD, &dst, &src); } //! @brief Unpack and Interleave Low Packed Double-Precision FP Values (SSE2). inline void unpcklpd(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstUnpckLPD, &dst, &src); } //! @brief Unpack and Interleave Low Packed Double-Precision FP Values (SSE2). inline void unpcklpd(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstUnpckLPD, &dst, &src); } //! @brief Bit-wise Logical OR for DP-FP Data (SSE2). inline void xorpd(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstXorPD, &dst, &src); } //! @brief Bit-wise Logical OR for DP-FP Data (SSE2). inline void xorpd(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstXorPD, &dst, &src); } // -------------------------------------------------------------------------- // [SSE3] // -------------------------------------------------------------------------- //! @brief Packed DP-FP Add/Subtract (SSE3). inline void addsubpd(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstAddSubPD, &dst, &src); } //! @brief Packed DP-FP Add/Subtract (SSE3). inline void addsubpd(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstAddSubPD, &dst, &src); } //! @brief Packed SP-FP Add/Subtract (SSE3). inline void addsubps(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstAddSubPS, &dst, &src); } //! @brief Packed SP-FP Add/Subtract (SSE3). inline void addsubps(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstAddSubPS, &dst, &src); } #if ASMJIT_NOT_SUPPORTED_BY_COMPILER // TODO: NOT IMPLEMENTED BY THE COMPILER. //! @brief Store Integer with Truncation (SSE3). inline void fisttp(const Mem& dst) { _emitInstruction(kX86InstFISttP, &dst); } #endif // ASMJIT_NOT_SUPPORTED_BY_COMPILER //! @brief Packed DP-FP Horizontal Add (SSE3). inline void haddpd(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstHAddPD, &dst, &src); } //! @brief Packed DP-FP Horizontal Add (SSE3). inline void haddpd(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstHAddPD, &dst, &src); } //! @brief Packed SP-FP Horizontal Add (SSE3). inline void haddps(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstHAddPS, &dst, &src); } //! @brief Packed SP-FP Horizontal Add (SSE3). inline void haddps(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstHAddPS, &dst, &src); } //! @brief Packed DP-FP Horizontal Subtract (SSE3). inline void hsubpd(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstHSubPD, &dst, &src); } //! @brief Packed DP-FP Horizontal Subtract (SSE3). inline void hsubpd(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstHSubPD, &dst, &src); } //! @brief Packed SP-FP Horizontal Subtract (SSE3). inline void hsubps(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstHSubPS, &dst, &src); } //! @brief Packed SP-FP Horizontal Subtract (SSE3). inline void hsubps(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstHSubPS, &dst, &src); } //! @brief Load Unaligned Integer 128 Bits (SSE3). inline void lddqu(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstLdDQU, &dst, &src); } #if ASMJIT_NOT_SUPPORTED_BY_COMPILER //! @brief Set Up Monitor Address (SSE3). inline void monitor() { _emitInstruction(kX86InstMonitor); } #endif // ASMJIT_NOT_SUPPORTED_BY_COMPILER //! @brief Move One DP-FP and Duplicate (SSE3). inline void movddup(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstMovDDup, &dst, &src); } //! @brief Move One DP-FP and Duplicate (SSE3). inline void movddup(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstMovDDup, &dst, &src); } //! @brief Move Packed SP-FP High and Duplicate (SSE3). inline void movshdup(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstMovSHDup, &dst, &src); } //! @brief Move Packed SP-FP High and Duplicate (SSE3). inline void movshdup(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstMovSHDup, &dst, &src); } //! @brief Move Packed SP-FP Low and Duplicate (SSE3). inline void movsldup(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstMovSLDup, &dst, &src); } //! @brief Move Packed SP-FP Low and Duplicate (SSE3). inline void movsldup(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstMovSLDup, &dst, &src); } #if ASMJIT_NOT_SUPPORTED_BY_COMPILER //! @brief Monitor Wait (SSE3). inline void mwait() { _emitInstruction(kX86InstMWait); } #endif // ASMJIT_NOT_SUPPORTED_BY_COMPILER // -------------------------------------------------------------------------- // [SSSE3] // -------------------------------------------------------------------------- //! @brief Packed SIGN (SSSE3). inline void psignb(const MmVar& dst, const MmVar& src) { _emitInstruction(kX86InstPSignB, &dst, &src); } //! @brief Packed SIGN (SSSE3). inline void psignb(const MmVar& dst, const Mem& src) { _emitInstruction(kX86InstPSignB, &dst, &src); } //! @brief Packed SIGN (SSSE3). inline void psignb(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstPSignB, &dst, &src); } //! @brief Packed SIGN (SSSE3). inline void psignb(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstPSignB, &dst, &src); } //! @brief Packed SIGN (SSSE3). inline void psignw(const MmVar& dst, const MmVar& src) { _emitInstruction(kX86InstPSignW, &dst, &src); } //! @brief Packed SIGN (SSSE3). inline void psignw(const MmVar& dst, const Mem& src) { _emitInstruction(kX86InstPSignW, &dst, &src); } //! @brief Packed SIGN (SSSE3). inline void psignw(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstPSignW, &dst, &src); } //! @brief Packed SIGN (SSSE3). inline void psignw(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstPSignW, &dst, &src); } //! @brief Packed SIGN (SSSE3). inline void psignd(const MmVar& dst, const MmVar& src) { _emitInstruction(kX86InstPSignD, &dst, &src); } //! @brief Packed SIGN (SSSE3). inline void psignd(const MmVar& dst, const Mem& src) { _emitInstruction(kX86InstPSignD, &dst, &src); } //! @brief Packed SIGN (SSSE3). inline void psignd(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstPSignD, &dst, &src); } //! @brief Packed SIGN (SSSE3). inline void psignd(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstPSignD, &dst, &src); } //! @brief Packed Horizontal Add (SSSE3). inline void phaddw(const MmVar& dst, const MmVar& src) { _emitInstruction(kX86InstPHAddW, &dst, &src); } //! @brief Packed Horizontal Add (SSSE3). inline void phaddw(const MmVar& dst, const Mem& src) { _emitInstruction(kX86InstPHAddW, &dst, &src); } //! @brief Packed Horizontal Add (SSSE3). inline void phaddw(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstPHAddW, &dst, &src); } //! @brief Packed Horizontal Add (SSSE3). inline void phaddw(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstPHAddW, &dst, &src); } //! @brief Packed Horizontal Add (SSSE3). inline void phaddd(const MmVar& dst, const MmVar& src) { _emitInstruction(kX86InstPHAddD, &dst, &src); } //! @brief Packed Horizontal Add (SSSE3). inline void phaddd(const MmVar& dst, const Mem& src) { _emitInstruction(kX86InstPHAddD, &dst, &src); } //! @brief Packed Horizontal Add (SSSE3). inline void phaddd(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstPHAddD, &dst, &src); } //! @brief Packed Horizontal Add (SSSE3). inline void phaddd(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstPHAddD, &dst, &src); } //! @brief Packed Horizontal Add and Saturate (SSSE3). inline void phaddsw(const MmVar& dst, const MmVar& src) { _emitInstruction(kX86InstPHAddSW, &dst, &src); } //! @brief Packed Horizontal Add and Saturate (SSSE3). inline void phaddsw(const MmVar& dst, const Mem& src) { _emitInstruction(kX86InstPHAddSW, &dst, &src); } //! @brief Packed Horizontal Add and Saturate (SSSE3). inline void phaddsw(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstPHAddSW, &dst, &src); } //! @brief Packed Horizontal Add and Saturate (SSSE3). inline void phaddsw(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstPHAddSW, &dst, &src); } //! @brief Packed Horizontal Subtract (SSSE3). inline void phsubw(const MmVar& dst, const MmVar& src) { _emitInstruction(kX86InstPHSubW, &dst, &src); } //! @brief Packed Horizontal Subtract (SSSE3). inline void phsubw(const MmVar& dst, const Mem& src) { _emitInstruction(kX86InstPHSubW, &dst, &src); } //! @brief Packed Horizontal Subtract (SSSE3). inline void phsubw(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstPHSubW, &dst, &src); } //! @brief Packed Horizontal Subtract (SSSE3). inline void phsubw(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstPHSubW, &dst, &src); } //! @brief Packed Horizontal Subtract (SSSE3). inline void phsubd(const MmVar& dst, const MmVar& src) { _emitInstruction(kX86InstPHSubD, &dst, &src); } //! @brief Packed Horizontal Subtract (SSSE3). inline void phsubd(const MmVar& dst, const Mem& src) { _emitInstruction(kX86InstPHSubD, &dst, &src); } //! @brief Packed Horizontal Subtract (SSSE3). inline void phsubd(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstPHSubD, &dst, &src); } //! @brief Packed Horizontal Subtract (SSSE3). inline void phsubd(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstPHSubD, &dst, &src); } //! @brief Packed Horizontal Subtract and Saturate (SSSE3). inline void phsubsw(const MmVar& dst, const MmVar& src) { _emitInstruction(kX86InstPHSubSW, &dst, &src); } //! @brief Packed Horizontal Subtract and Saturate (SSSE3). inline void phsubsw(const MmVar& dst, const Mem& src) { _emitInstruction(kX86InstPHSubSW, &dst, &src); } //! @brief Packed Horizontal Subtract and Saturate (SSSE3). inline void phsubsw(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstPHSubSW, &dst, &src); } //! @brief Packed Horizontal Subtract and Saturate (SSSE3). inline void phsubsw(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstPHSubSW, &dst, &src); } //! @brief Multiply and Add Packed Signed and Unsigned Bytes (SSSE3). inline void pmaddubsw(const MmVar& dst, const MmVar& src) { _emitInstruction(kX86InstPMAddUBSW, &dst, &src); } //! @brief Multiply and Add Packed Signed and Unsigned Bytes (SSSE3). inline void pmaddubsw(const MmVar& dst, const Mem& src) { _emitInstruction(kX86InstPMAddUBSW, &dst, &src); } //! @brief Multiply and Add Packed Signed and Unsigned Bytes (SSSE3). inline void pmaddubsw(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstPMAddUBSW, &dst, &src); } //! @brief Multiply and Add Packed Signed and Unsigned Bytes (SSSE3). inline void pmaddubsw(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstPMAddUBSW, &dst, &src); } //! @brief Packed Absolute Value (SSSE3). inline void pabsb(const MmVar& dst, const MmVar& src) { _emitInstruction(kX86InstPAbsB, &dst, &src); } //! @brief Packed Absolute Value (SSSE3). inline void pabsb(const MmVar& dst, const Mem& src) { _emitInstruction(kX86InstPAbsB, &dst, &src); } //! @brief Packed Absolute Value (SSSE3). inline void pabsb(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstPAbsB, &dst, &src); } //! @brief Packed Absolute Value (SSSE3). inline void pabsb(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstPAbsB, &dst, &src); } //! @brief Packed Absolute Value (SSSE3). inline void pabsw(const MmVar& dst, const MmVar& src) { _emitInstruction(kX86InstPAbsW, &dst, &src); } //! @brief Packed Absolute Value (SSSE3). inline void pabsw(const MmVar& dst, const Mem& src) { _emitInstruction(kX86InstPAbsW, &dst, &src); } //! @brief Packed Absolute Value (SSSE3). inline void pabsw(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstPAbsW, &dst, &src); } //! @brief Packed Absolute Value (SSSE3). inline void pabsw(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstPAbsW, &dst, &src); } //! @brief Packed Absolute Value (SSSE3). inline void pabsd(const MmVar& dst, const MmVar& src) { _emitInstruction(kX86InstPAbsD, &dst, &src); } //! @brief Packed Absolute Value (SSSE3). inline void pabsd(const MmVar& dst, const Mem& src) { _emitInstruction(kX86InstPAbsD, &dst, &src); } //! @brief Packed Absolute Value (SSSE3). inline void pabsd(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstPAbsD, &dst, &src); } //! @brief Packed Absolute Value (SSSE3). inline void pabsd(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstPAbsD, &dst, &src); } //! @brief Packed Multiply High with Round and Scale (SSSE3). inline void pmulhrsw(const MmVar& dst, const MmVar& src) { _emitInstruction(kX86InstPMulHRSW, &dst, &src); } //! @brief Packed Multiply High with Round and Scale (SSSE3). inline void pmulhrsw(const MmVar& dst, const Mem& src) { _emitInstruction(kX86InstPMulHRSW, &dst, &src); } //! @brief Packed Multiply High with Round and Scale (SSSE3). inline void pmulhrsw(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstPMulHRSW, &dst, &src); } //! @brief Packed Multiply High with Round and Scale (SSSE3). inline void pmulhrsw(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstPMulHRSW, &dst, &src); } //! @brief Packed Shuffle Bytes (SSSE3). inline void pshufb(const MmVar& dst, const MmVar& src) { _emitInstruction(kX86InstPShufB, &dst, &src); } //! @brief Packed Shuffle Bytes (SSSE3). inline void pshufb(const MmVar& dst, const Mem& src) { _emitInstruction(kX86InstPShufB, &dst, &src); } //! @brief Packed Shuffle Bytes (SSSE3). inline void pshufb(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstPShufB, &dst, &src); } //! @brief Packed Shuffle Bytes (SSSE3). inline void pshufb(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstPShufB, &dst, &src); } //! @brief Packed Shuffle Bytes (SSSE3). inline void palignr(const MmVar& dst, const MmVar& src, const Imm& imm8) { _emitInstruction(kX86InstPAlignR, &dst, &src, &imm8); } //! @brief Packed Shuffle Bytes (SSSE3). inline void palignr(const MmVar& dst, const Mem& src, const Imm& imm8) { _emitInstruction(kX86InstPAlignR, &dst, &src, &imm8); } //! @brief Packed Shuffle Bytes (SSSE3). inline void palignr(const XmmVar& dst, const XmmVar& src, const Imm& imm8) { _emitInstruction(kX86InstPAlignR, &dst, &src, &imm8); } //! @brief Packed Shuffle Bytes (SSSE3). inline void palignr(const XmmVar& dst, const Mem& src, const Imm& imm8) { _emitInstruction(kX86InstPAlignR, &dst, &src, &imm8); } // -------------------------------------------------------------------------- // [SSE4.1] // -------------------------------------------------------------------------- //! @brief Blend Packed DP-FP Values (SSE4.1). inline void blendpd(const XmmVar& dst, const XmmVar& src, const Imm& imm8) { _emitInstruction(kX86InstBlendPD, &dst, &src, &imm8); } //! @brief Blend Packed DP-FP Values (SSE4.1). inline void blendpd(const XmmVar& dst, const Mem& src, const Imm& imm8) { _emitInstruction(kX86InstBlendPD, &dst, &src, &imm8); } //! @brief Blend Packed SP-FP Values (SSE4.1). inline void blendps(const XmmVar& dst, const XmmVar& src, const Imm& imm8) { _emitInstruction(kX86InstBlendPS, &dst, &src, &imm8); } //! @brief Blend Packed SP-FP Values (SSE4.1). inline void blendps(const XmmVar& dst, const Mem& src, const Imm& imm8) { _emitInstruction(kX86InstBlendPS, &dst, &src, &imm8); } //! @brief Variable Blend Packed DP-FP Values (SSE4.1). inline void blendvpd(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstBlendVPD, &dst, &src); } //! @brief Variable Blend Packed DP-FP Values (SSE4.1). inline void blendvpd(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstBlendVPD, &dst, &src); } //! @brief Variable Blend Packed SP-FP Values (SSE4.1). inline void blendvps(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstBlendVPS, &dst, &src); } //! @brief Variable Blend Packed SP-FP Values (SSE4.1). inline void blendvps(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstBlendVPS, &dst, &src); } //! @brief Dot Product of Packed DP-FP Values (SSE4.1). inline void dppd(const XmmVar& dst, const XmmVar& src, const Imm& imm8) { _emitInstruction(kX86InstDpPD, &dst, &src, &imm8); } //! @brief Dot Product of Packed DP-FP Values (SSE4.1). inline void dppd(const XmmVar& dst, const Mem& src, const Imm& imm8) { _emitInstruction(kX86InstDpPD, &dst, &src, &imm8); } //! @brief Dot Product of Packed SP-FP Values (SSE4.1). inline void dpps(const XmmVar& dst, const XmmVar& src, const Imm& imm8) { _emitInstruction(kX86InstDpPS, &dst, &src, &imm8); } //! @brief Dot Product of Packed SP-FP Values (SSE4.1). inline void dpps(const XmmVar& dst, const Mem& src, const Imm& imm8) { _emitInstruction(kX86InstDpPS, &dst, &src, &imm8); } //! @brief Extract Packed SP-FP Value (SSE4.1). inline void extractps(const XmmVar& dst, const XmmVar& src, const Imm& imm8) { _emitInstruction(kX86InstExtractPS, &dst, &src, &imm8); } //! @brief Extract Packed SP-FP Value (SSE4.1). inline void extractps(const XmmVar& dst, const Mem& src, const Imm& imm8) { _emitInstruction(kX86InstExtractPS, &dst, &src, &imm8); } //! @brief Load Double Quadword Non-Temporal Aligned Hint (SSE4.1). inline void movntdqa(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstMovNTDQA, &dst, &src); } //! @brief Compute Multiple Packed Sums of Absolute Difference (SSE4.1). inline void mpsadbw(const XmmVar& dst, const XmmVar& src, const Imm& imm8) { _emitInstruction(kX86InstMPSADBW, &dst, &src, &imm8); } //! @brief Compute Multiple Packed Sums of Absolute Difference (SSE4.1). inline void mpsadbw(const XmmVar& dst, const Mem& src, const Imm& imm8) { _emitInstruction(kX86InstMPSADBW, &dst, &src, &imm8); } //! @brief Pack with Unsigned Saturation (SSE4.1). inline void packusdw(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstPackUSDW, &dst, &src); } //! @brief Pack with Unsigned Saturation (SSE4.1). inline void packusdw(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstPackUSDW, &dst, &src); } //! @brief Variable Blend Packed Bytes (SSE4.1). inline void pblendvb(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstPBlendVB, &dst, &src); } //! @brief Variable Blend Packed Bytes (SSE4.1). inline void pblendvb(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstPBlendVB, &dst, &src); } //! @brief Blend Packed Words (SSE4.1). inline void pblendw(const XmmVar& dst, const XmmVar& src, const Imm& imm8) { _emitInstruction(kX86InstPBlendW, &dst, &src, &imm8); } //! @brief Blend Packed Words (SSE4.1). inline void pblendw(const XmmVar& dst, const Mem& src, const Imm& imm8) { _emitInstruction(kX86InstPBlendW, &dst, &src, &imm8); } //! @brief Compare Packed Qword Data for Equal (SSE4.1). inline void pcmpeqq(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstPCmpEqQ, &dst, &src); } //! @brief Compare Packed Qword Data for Equal (SSE4.1). inline void pcmpeqq(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstPCmpEqQ, &dst, &src); } //! @brief Extract Byte (SSE4.1). inline void pextrb(const GpVar& dst, const XmmVar& src, const Imm& imm8) { _emitInstruction(kX86InstPExtrB, &dst, &src, &imm8); } //! @brief Extract Byte (SSE4.1). inline void pextrb(const Mem& dst, const XmmVar& src, const Imm& imm8) { _emitInstruction(kX86InstPExtrB, &dst, &src, &imm8); } //! @brief Extract Dword (SSE4.1). inline void pextrd(const GpVar& dst, const XmmVar& src, const Imm& imm8) { _emitInstruction(kX86InstPExtrD, &dst, &src, &imm8); } //! @brief Extract Dword (SSE4.1). inline void pextrd(const Mem& dst, const XmmVar& src, const Imm& imm8) { _emitInstruction(kX86InstPExtrD, &dst, &src, &imm8); } //! @brief Extract Dword (SSE4.1). inline void pextrq(const GpVar& dst, const XmmVar& src, const Imm& imm8) { _emitInstruction(kX86InstPExtrQ, &dst, &src, &imm8); } //! @brief Extract Dword (SSE4.1). inline void pextrq(const Mem& dst, const XmmVar& src, const Imm& imm8) { _emitInstruction(kX86InstPExtrQ, &dst, &src, &imm8); } //! @brief Packed Horizontal Word Minimum (SSE4.1). inline void phminposuw(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstPHMinPOSUW, &dst, &src); } //! @brief Packed Horizontal Word Minimum (SSE4.1). inline void phminposuw(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstPHMinPOSUW, &dst, &src); } //! @brief Insert Byte (SSE4.1). inline void pinsrb(const XmmVar& dst, const GpVar& src, const Imm& imm8) { _emitInstruction(kX86InstPInsRB, &dst, &src, &imm8); } //! @brief Insert Byte (SSE4.1). inline void pinsrb(const XmmVar& dst, const Mem& src, const Imm& imm8) { _emitInstruction(kX86InstPInsRB, &dst, &src, &imm8); } //! @brief Insert Dword (SSE4.1). inline void pinsrd(const XmmVar& dst, const GpVar& src, const Imm& imm8) { _emitInstruction(kX86InstPInsRD, &dst, &src, &imm8); } //! @brief Insert Dword (SSE4.1). inline void pinsrd(const XmmVar& dst, const Mem& src, const Imm& imm8) { _emitInstruction(kX86InstPInsRD, &dst, &src, &imm8); } //! @brief Insert Dword (SSE4.1). inline void pinsrq(const XmmVar& dst, const GpVar& src, const Imm& imm8) { _emitInstruction(kX86InstPInsRQ, &dst, &src, &imm8); } //! @brief Insert Dword (SSE4.1). inline void pinsrq(const XmmVar& dst, const Mem& src, const Imm& imm8) { _emitInstruction(kX86InstPInsRQ, &dst, &src, &imm8); } //! @brief Insert Word (SSE2). inline void pinsrw(const XmmVar& dst, const GpVar& src, const Imm& imm8) { _emitInstruction(kX86InstPInsRW, &dst, &src, &imm8); } //! @brief Insert Word (SSE2). inline void pinsrw(const XmmVar& dst, const Mem& src, const Imm& imm8) { _emitInstruction(kX86InstPInsRW, &dst, &src, &imm8); } //! @brief Maximum of Packed Word Integers (SSE4.1). inline void pmaxuw(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstPMaxUW, &dst, &src); } //! @brief Maximum of Packed Word Integers (SSE4.1). inline void pmaxuw(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstPMaxUW, &dst, &src); } //! @brief Maximum of Packed Signed Byte Integers (SSE4.1). inline void pmaxsb(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstPMaxSB, &dst, &src); } //! @brief Maximum of Packed Signed Byte Integers (SSE4.1). inline void pmaxsb(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstPMaxSB, &dst, &src); } //! @brief Maximum of Packed Signed Dword Integers (SSE4.1). inline void pmaxsd(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstPMaxSD, &dst, &src); } //! @brief Maximum of Packed Signed Dword Integers (SSE4.1). inline void pmaxsd(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstPMaxSD, &dst, &src); } //! @brief Maximum of Packed Unsigned Dword Integers (SSE4.1). inline void pmaxud(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstPMaxUD, &dst, &src); } //! @brief Maximum of Packed Unsigned Dword Integers (SSE4.1). inline void pmaxud(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstPMaxUD, &dst, &src); } //! @brief Minimum of Packed Signed Byte Integers (SSE4.1). inline void pminsb(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstPMinSB, &dst, &src); } //! @brief Minimum of Packed Signed Byte Integers (SSE4.1). inline void pminsb(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstPMinSB, &dst, &src); } //! @brief Minimum of Packed Word Integers (SSE4.1). inline void pminuw(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstPMinUW, &dst, &src); } //! @brief Minimum of Packed Word Integers (SSE4.1). inline void pminuw(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstPMinUW, &dst, &src); } //! @brief Minimum of Packed Dword Integers (SSE4.1). inline void pminud(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstPMinUD, &dst, &src); } //! @brief Minimum of Packed Dword Integers (SSE4.1). inline void pminud(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstPMinUD, &dst, &src); } //! @brief Minimum of Packed Dword Integers (SSE4.1). inline void pminsd(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstPMinSD, &dst, &src); } //! @brief Minimum of Packed Dword Integers (SSE4.1). inline void pminsd(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstPMinSD, &dst, &src); } //! @brief Packed Move with Sign Extend (SSE4.1). inline void pmovsxbw(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstPMovSXBW, &dst, &src); } //! @brief Packed Move with Sign Extend (SSE4.1). inline void pmovsxbw(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstPMovSXBW, &dst, &src); } //! @brief Packed Move with Sign Extend (SSE4.1). inline void pmovsxbd(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstPMovSXBD, &dst, &src); } //! @brief Packed Move with Sign Extend (SSE4.1). inline void pmovsxbd(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstPMovSXBD, &dst, &src); } //! @brief Packed Move with Sign Extend (SSE4.1). inline void pmovsxbq(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstPMovSXBQ, &dst, &src); } //! @brief Packed Move with Sign Extend (SSE4.1). inline void pmovsxbq(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstPMovSXBQ, &dst, &src); } //! @brief Packed Move with Sign Extend (SSE4.1). inline void pmovsxwd(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstPMovSXWD, &dst, &src); } //! @brief Packed Move with Sign Extend (SSE4.1). inline void pmovsxwd(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstPMovSXWD, &dst, &src); } //! @brief (SSE4.1). inline void pmovsxwq(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstPMovSXWQ, &dst, &src); } //! @brief (SSE4.1). inline void pmovsxwq(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstPMovSXWQ, &dst, &src); } //! @brief (SSE4.1). inline void pmovsxdq(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstPMovSXDQ, &dst, &src); } //! @brief (SSE4.1). inline void pmovsxdq(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstPMovSXDQ, &dst, &src); } //! @brief Packed Move with Zero Extend (SSE4.1). inline void pmovzxbw(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstPMovZXBW, &dst, &src); } //! @brief Packed Move with Zero Extend (SSE4.1). inline void pmovzxbw(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstPMovZXBW, &dst, &src); } //! @brief Packed Move with Zero Extend (SSE4.1). inline void pmovzxbd(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstPMovZXBD, &dst, &src); } //! @brief Packed Move with Zero Extend (SSE4.1). inline void pmovzxbd(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstPMovZXBD, &dst, &src); } //! @brief Packed Move with Zero Extend (SSE4.1). inline void pmovzxbq(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstPMovZXBQ, &dst, &src); } //! @brief Packed Move with Zero Extend (SSE4.1). inline void pmovzxbq(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstPMovZXBQ, &dst, &src); } //! @brief Packed Move with Zero Extend (SSE4.1). inline void pmovzxwd(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstPMovZXWD, &dst, &src); } //! @brief Packed Move with Zero Extend (SSE4.1). inline void pmovzxwd(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstPMovZXWD, &dst, &src); } //! @brief (SSE4.1). inline void pmovzxwq(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstPMovZXWQ, &dst, &src); } //! @brief (SSE4.1). inline void pmovzxwq(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstPMovZXWQ, &dst, &src); } //! @brief (SSE4.1). inline void pmovzxdq(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstPMovZXDQ, &dst, &src); } //! @brief (SSE4.1). inline void pmovzxdq(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstPMovZXDQ, &dst, &src); } //! @brief Multiply Packed Signed Dword Integers (SSE4.1). inline void pmuldq(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstPMulDQ, &dst, &src); } //! @brief Multiply Packed Signed Dword Integers (SSE4.1). inline void pmuldq(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstPMulDQ, &dst, &src); } //! @brief Multiply Packed Signed Integers and Store Low Result (SSE4.1). inline void pmulld(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstPMulLD, &dst, &src); } //! @brief Multiply Packed Signed Integers and Store Low Result (SSE4.1). inline void pmulld(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstPMulLD, &dst, &src); } //! @brief Logical Compare (SSE4.1). inline void ptest(const XmmVar& op1, const XmmVar& op2) { _emitInstruction(kX86InstPTest, &op1, &op2); } //! @brief Logical Compare (SSE4.1). inline void ptest(const XmmVar& op1, const Mem& op2) { _emitInstruction(kX86InstPTest, &op1, &op2); } //! Round Packed SP-FP Values @brief (SSE4.1). inline void roundps(const XmmVar& dst, const XmmVar& src, const Imm& imm8) { _emitInstruction(kX86InstRoundPS, &dst, &src, &imm8); } //! Round Packed SP-FP Values @brief (SSE4.1). inline void roundps(const XmmVar& dst, const Mem& src, const Imm& imm8) { _emitInstruction(kX86InstRoundPS, &dst, &src, &imm8); } //! @brief Round Scalar SP-FP Values (SSE4.1). inline void roundss(const XmmVar& dst, const XmmVar& src, const Imm& imm8) { _emitInstruction(kX86InstRoundSS, &dst, &src, &imm8); } //! @brief Round Scalar SP-FP Values (SSE4.1). inline void roundss(const XmmVar& dst, const Mem& src, const Imm& imm8) { _emitInstruction(kX86InstRoundSS, &dst, &src, &imm8); } //! @brief Round Packed DP-FP Values (SSE4.1). inline void roundpd(const XmmVar& dst, const XmmVar& src, const Imm& imm8) { _emitInstruction(kX86InstRoundPD, &dst, &src, &imm8); } //! @brief Round Packed DP-FP Values (SSE4.1). inline void roundpd(const XmmVar& dst, const Mem& src, const Imm& imm8) { _emitInstruction(kX86InstRoundPD, &dst, &src, &imm8); } //! @brief Round Scalar DP-FP Values (SSE4.1). inline void roundsd(const XmmVar& dst, const XmmVar& src, const Imm& imm8) { _emitInstruction(kX86InstRoundSD, &dst, &src, &imm8); } //! @brief Round Scalar DP-FP Values (SSE4.1). inline void roundsd(const XmmVar& dst, const Mem& src, const Imm& imm8) { _emitInstruction(kX86InstRoundSD, &dst, &src, &imm8); } // -------------------------------------------------------------------------- // [SSE4.2] // -------------------------------------------------------------------------- //! @brief Accumulate CRC32 Value (polynomial 0x11EDC6F41) (SSE4.2). inline void crc32(const GpVar& dst, const GpVar& src) { _emitInstruction(kX86InstCrc32, &dst, &src); } //! @brief Accumulate CRC32 Value (polynomial 0x11EDC6F41) (SSE4.2). inline void crc32(const GpVar& dst, const Mem& src) { _emitInstruction(kX86InstCrc32, &dst, &src); } //! @brief Packed Compare Explicit Length Strings, Return Index (SSE4.2). inline void pcmpestri(const XmmVar& dst, const XmmVar& src, const Imm& imm8) { _emitInstruction(kX86InstPCmpEStrI, &dst, &src, &imm8); } //! @brief Packed Compare Explicit Length Strings, Return Index (SSE4.2). inline void pcmpestri(const XmmVar& dst, const Mem& src, const Imm& imm8) { _emitInstruction(kX86InstPCmpEStrI, &dst, &src, &imm8); } //! @brief Packed Compare Explicit Length Strings, Return Mask (SSE4.2). inline void pcmpestrm(const XmmVar& dst, const XmmVar& src, const Imm& imm8) { _emitInstruction(kX86InstPCmpEStrM, &dst, &src, &imm8); } //! @brief Packed Compare Explicit Length Strings, Return Mask (SSE4.2). inline void pcmpestrm(const XmmVar& dst, const Mem& src, const Imm& imm8) { _emitInstruction(kX86InstPCmpEStrM, &dst, &src, &imm8); } //! @brief Packed Compare Implicit Length Strings, Return Index (SSE4.2). inline void pcmpistri(const XmmVar& dst, const XmmVar& src, const Imm& imm8) { _emitInstruction(kX86InstPCmpIStrI, &dst, &src, &imm8); } //! @brief Packed Compare Implicit Length Strings, Return Index (SSE4.2). inline void pcmpistri(const XmmVar& dst, const Mem& src, const Imm& imm8) { _emitInstruction(kX86InstPCmpIStrI, &dst, &src, &imm8); } //! @brief Packed Compare Implicit Length Strings, Return Mask (SSE4.2). inline void pcmpistrm(const XmmVar& dst, const XmmVar& src, const Imm& imm8) { _emitInstruction(kX86InstPCmpIStrM, &dst, &src, &imm8); } //! @brief Packed Compare Implicit Length Strings, Return Mask (SSE4.2). inline void pcmpistrm(const XmmVar& dst, const Mem& src, const Imm& imm8) { _emitInstruction(kX86InstPCmpIStrM, &dst, &src, &imm8); } //! @brief Compare Packed Data for Greater Than (SSE4.2). inline void pcmpgtq(const XmmVar& dst, const XmmVar& src) { _emitInstruction(kX86InstPCmpGtQ, &dst, &src); } //! @brief Compare Packed Data for Greater Than (SSE4.2). inline void pcmpgtq(const XmmVar& dst, const Mem& src) { _emitInstruction(kX86InstPCmpGtQ, &dst, &src); } //! @brief Return the Count of Number of Bits Set to 1 (SSE4.2). inline void popcnt(const GpVar& dst, const GpVar& src) { _emitInstruction(kX86InstPopCnt, &dst, &src); } //! @brief Return the Count of Number of Bits Set to 1 (SSE4.2). inline void popcnt(const GpVar& dst, const Mem& src) { _emitInstruction(kX86InstPopCnt, &dst, &src); } // -------------------------------------------------------------------------- // [AMD only] // -------------------------------------------------------------------------- //! @brief Prefetch (3dNow - Amd). //! //! Loads the entire 64-byte aligned memory sequence containing the //! specified memory address into the L1 data cache. The position of //! the specified memory address within the 64-byte cache line is //! irrelevant. If a cache hit occurs, or if a memory fault is detected, //! no bus cycle is initiated and the instruction is treated as a NOP. inline void amd_prefetch(const Mem& mem) { _emitInstruction(kX86InstAmdPrefetch, &mem); } //! @brief Prefetch and set cache to modified (3dNow - Amd). //! //! The PREFETCHW instruction loads the prefetched line and sets the //! cache-line state to Modified, in anticipation of subsequent data //! writes to the line. The PREFETCH instruction, by contrast, typically //! sets the cache-line state to Exclusive (depending on the hardware //! implementation). inline void amd_prefetchw(const Mem& mem) { _emitInstruction(kX86InstAmdPrefetchW, &mem); } // -------------------------------------------------------------------------- // [Intel only] // -------------------------------------------------------------------------- //! @brief Move Data After Swapping Bytes (SSE3 - Intel Atom). inline void movbe(const GpVar& dst, const Mem& src) { ASMJIT_ASSERT(!dst.isGpb()); _emitInstruction(kX86InstMovBE, &dst, &src); } //! @brief Move Data After Swapping Bytes (SSE3 - Intel Atom). inline void movbe(const Mem& dst, const GpVar& src) { ASMJIT_ASSERT(!src.isGpb()); _emitInstruction(kX86InstMovBE, &dst, &src); } // ------------------------------------------------------------------------- // [Emit Options] // ------------------------------------------------------------------------- //! @brief Assert LOCK# Signal Prefix. //! //! This instruction causes the processor's LOCK# signal to be asserted //! during execution of the accompanying instruction (turns the //! instruction into an atomic instruction). In a multiprocessor environment, //! the LOCK# signal insures that the processor has exclusive use of any shared //! memory while the signal is asserted. //! //! The LOCK prefix can be prepended only to the following instructions and //! to those forms of the instructions that use a memory operand: ADD, ADC, //! AND, BTC, BTR, BTS, CMPXCHG, DEC, INC, NEG, NOT, OR, SBB, SUB, XOR, XADD, //! and XCHG. An undefined opcode exception will be generated if the LOCK //! prefix is used with any other instruction. The XCHG instruction always //! asserts the LOCK# signal regardless of the presence or absence of the LOCK //! prefix. inline void lock() { _emitOptions |= kX86EmitOptionLock; } //! @brief Force REX prefix to be emitted. //! //! This option should be used carefully, because there are unencodable //! combinations. If you want to access ah, bh, ch or dh registers then you //! can't emit REX prefix and it will cause an illegal instruction error. //! //! @note REX prefix is only valid for X64/AMD64 platform. //! //! @sa @c kX86EmitOptionRex. inline void rex() { _emitOptions |= kX86EmitOptionRex; } }; //! @} } // AsmJit namespace #undef ASMJIT_NOT_SUPPORTED_BY_COMPILER // [Api-End] #include "../core/apiend.h" // [Guard] #endif // _ASMJIT_X86_X86COMPILER_H desmume/src/libretro-common/libco/ppc.c000664 001750 001750 00000027343 12755534123 021276 0ustar00sergiosergio000000 000000 /* libco.ppc (2010-10-17) author: blargg license: public domain */ /* PowerPC 32/64 using embedded or external asm, with optional floating-point and AltiVec save/restore */ #define LIBCO_C #include #include #include #include #define LIBCO_MPROTECT (__unix__ && !LIBCO_PPC_ASM) #if LIBCO_MPROTECT #include #include #endif /* State format (offsets in 32-bit words) +0 Pointer to swap code Rest of function descriptor for entry function +8 PC +10 SP Special regs GPRs FPRs VRs stack */ enum { state_size = 1024 }; enum { above_stack = 2048 }; enum { stack_align = 256 }; static thread_local cothread_t co_active_handle = 0; /**** Determine environment ****/ #define LIBCO_PPC64 (_ARCH_PPC64 || __PPC64__ || __ppc64__ || __powerpc64__) /* Whether function calls are indirect through a descriptor, or are directly to function */ #ifndef LIBCO_PPCDESC #if !_CALL_SYSV && (_CALL_AIX || _CALL_AIXDESC || LIBCO_PPC64) #define LIBCO_PPCDESC 1 #endif #endif #ifdef LIBCO_PPC_ASM #ifdef __cplusplus extern "C" #endif /* Swap code is in ppc.S */ void co_swap_asm( cothread_t, cothread_t ); #define CO_SWAP_ASM( x, y ) co_swap_asm( x, y ) #else /* Swap code is here in array. Please leave dieassembly comments, as they make it easy to see what it does, and reorder instructions if one wants to see whether that improves performance. */ static const uint32_t libco_ppc_code [] = { #if LIBCO_PPC64 0x7d000026, /* mfcr r8 */ 0xf8240028, /* std r1,40(r4) */ 0x7d2802a6, /* mflr r9 */ 0xf9c40048, /* std r14,72(r4) */ 0xf9e40050, /* std r15,80(r4) */ 0xfa040058, /* std r16,88(r4) */ 0xfa240060, /* std r17,96(r4) */ 0xfa440068, /* std r18,104(r4) */ 0xfa640070, /* std r19,112(r4) */ 0xfa840078, /* std r20,120(r4) */ 0xfaa40080, /* std r21,128(r4) */ 0xfac40088, /* std r22,136(r4) */ 0xfae40090, /* std r23,144(r4) */ 0xfb040098, /* std r24,152(r4) */ 0xfb2400a0, /* std r25,160(r4) */ 0xfb4400a8, /* std r26,168(r4) */ 0xfb6400b0, /* std r27,176(r4) */ 0xfb8400b8, /* std r28,184(r4) */ 0xfba400c0, /* std r29,192(r4) */ 0xfbc400c8, /* std r30,200(r4) */ 0xfbe400d0, /* std r31,208(r4) */ 0xf9240020, /* std r9,32(r4) */ 0xe8e30020, /* ld r7,32(r3) */ 0xe8230028, /* ld r1,40(r3) */ 0x48000009, /* bl 1 */ 0x7fe00008, /* trap */ 0x91040030,/*1:stw r8,48(r4) */ 0x80c30030, /* lwz r6,48(r3) */ 0x7ce903a6, /* mtctr r7 */ 0xe9c30048, /* ld r14,72(r3) */ 0xe9e30050, /* ld r15,80(r3) */ 0xea030058, /* ld r16,88(r3) */ 0xea230060, /* ld r17,96(r3) */ 0xea430068, /* ld r18,104(r3) */ 0xea630070, /* ld r19,112(r3) */ 0xea830078, /* ld r20,120(r3) */ 0xeaa30080, /* ld r21,128(r3) */ 0xeac30088, /* ld r22,136(r3) */ 0xeae30090, /* ld r23,144(r3) */ 0xeb030098, /* ld r24,152(r3) */ 0xeb2300a0, /* ld r25,160(r3) */ 0xeb4300a8, /* ld r26,168(r3) */ 0xeb6300b0, /* ld r27,176(r3) */ 0xeb8300b8, /* ld r28,184(r3) */ 0xeba300c0, /* ld r29,192(r3) */ 0xebc300c8, /* ld r30,200(r3) */ 0xebe300d0, /* ld r31,208(r3) */ 0x7ccff120, /* mtcr r6 */ #else 0x7d000026, /* mfcr r8 */ 0x90240028, /* stw r1,40(r4) */ 0x7d2802a6, /* mflr r9 */ 0x91a4003c, /* stw r13,60(r4) */ 0x91c40040, /* stw r14,64(r4) */ 0x91e40044, /* stw r15,68(r4) */ 0x92040048, /* stw r16,72(r4) */ 0x9224004c, /* stw r17,76(r4) */ 0x92440050, /* stw r18,80(r4) */ 0x92640054, /* stw r19,84(r4) */ 0x92840058, /* stw r20,88(r4) */ 0x92a4005c, /* stw r21,92(r4) */ 0x92c40060, /* stw r22,96(r4) */ 0x92e40064, /* stw r23,100(r4) */ 0x93040068, /* stw r24,104(r4) */ 0x9324006c, /* stw r25,108(r4) */ 0x93440070, /* stw r26,112(r4) */ 0x93640074, /* stw r27,116(r4) */ 0x93840078, /* stw r28,120(r4) */ 0x93a4007c, /* stw r29,124(r4) */ 0x93c40080, /* stw r30,128(r4) */ 0x93e40084, /* stw r31,132(r4) */ 0x91240020, /* stw r9,32(r4) */ 0x80e30020, /* lwz r7,32(r3) */ 0x80230028, /* lwz r1,40(r3) */ 0x48000009, /* bl 1 */ 0x7fe00008, /* trap */ 0x91040030,/*1:stw r8,48(r4) */ 0x80c30030, /* lwz r6,48(r3) */ 0x7ce903a6, /* mtctr r7 */ 0x81a3003c, /* lwz r13,60(r3) */ 0x81c30040, /* lwz r14,64(r3) */ 0x81e30044, /* lwz r15,68(r3) */ 0x82030048, /* lwz r16,72(r3) */ 0x8223004c, /* lwz r17,76(r3) */ 0x82430050, /* lwz r18,80(r3) */ 0x82630054, /* lwz r19,84(r3) */ 0x82830058, /* lwz r20,88(r3) */ 0x82a3005c, /* lwz r21,92(r3) */ 0x82c30060, /* lwz r22,96(r3) */ 0x82e30064, /* lwz r23,100(r3) */ 0x83030068, /* lwz r24,104(r3) */ 0x8323006c, /* lwz r25,108(r3) */ 0x83430070, /* lwz r26,112(r3) */ 0x83630074, /* lwz r27,116(r3) */ 0x83830078, /* lwz r28,120(r3) */ 0x83a3007c, /* lwz r29,124(r3) */ 0x83c30080, /* lwz r30,128(r3) */ 0x83e30084, /* lwz r31,132(r3) */ 0x7ccff120, /* mtcr r6 */ #endif #ifndef LIBCO_PPC_NOFP 0xd9c400e0, /* stfd f14,224(r4) */ 0xd9e400e8, /* stfd f15,232(r4) */ 0xda0400f0, /* stfd f16,240(r4) */ 0xda2400f8, /* stfd f17,248(r4) */ 0xda440100, /* stfd f18,256(r4) */ 0xda640108, /* stfd f19,264(r4) */ 0xda840110, /* stfd f20,272(r4) */ 0xdaa40118, /* stfd f21,280(r4) */ 0xdac40120, /* stfd f22,288(r4) */ 0xdae40128, /* stfd f23,296(r4) */ 0xdb040130, /* stfd f24,304(r4) */ 0xdb240138, /* stfd f25,312(r4) */ 0xdb440140, /* stfd f26,320(r4) */ 0xdb640148, /* stfd f27,328(r4) */ 0xdb840150, /* stfd f28,336(r4) */ 0xdba40158, /* stfd f29,344(r4) */ 0xdbc40160, /* stfd f30,352(r4) */ 0xdbe40168, /* stfd f31,360(r4) */ 0xc9c300e0, /* lfd f14,224(r3) */ 0xc9e300e8, /* lfd f15,232(r3) */ 0xca0300f0, /* lfd f16,240(r3) */ 0xca2300f8, /* lfd f17,248(r3) */ 0xca430100, /* lfd f18,256(r3) */ 0xca630108, /* lfd f19,264(r3) */ 0xca830110, /* lfd f20,272(r3) */ 0xcaa30118, /* lfd f21,280(r3) */ 0xcac30120, /* lfd f22,288(r3) */ 0xcae30128, /* lfd f23,296(r3) */ 0xcb030130, /* lfd f24,304(r3) */ 0xcb230138, /* lfd f25,312(r3) */ 0xcb430140, /* lfd f26,320(r3) */ 0xcb630148, /* lfd f27,328(r3) */ 0xcb830150, /* lfd f28,336(r3) */ 0xcba30158, /* lfd f29,344(r3) */ 0xcbc30160, /* lfd f30,352(r3) */ 0xcbe30168, /* lfd f31,360(r3) */ #endif #ifdef __ALTIVEC__ 0x7ca042a6, /* mfvrsave r5 */ 0x39040180, /* addi r8,r4,384 */ 0x39240190, /* addi r9,r4,400 */ 0x70a00fff, /* andi. r0,r5,4095 */ 0x90a40034, /* stw r5,52(r4) */ 0x4182005c, /* beq- 2 */ 0x7e8041ce, /* stvx v20,r0,r8 */ 0x39080020, /* addi r8,r8,32 */ 0x7ea049ce, /* stvx v21,r0,r9 */ 0x39290020, /* addi r9,r9,32 */ 0x7ec041ce, /* stvx v22,r0,r8 */ 0x39080020, /* addi r8,r8,32 */ 0x7ee049ce, /* stvx v23,r0,r9 */ 0x39290020, /* addi r9,r9,32 */ 0x7f0041ce, /* stvx v24,r0,r8 */ 0x39080020, /* addi r8,r8,32 */ 0x7f2049ce, /* stvx v25,r0,r9 */ 0x39290020, /* addi r9,r9,32 */ 0x7f4041ce, /* stvx v26,r0,r8 */ 0x39080020, /* addi r8,r8,32 */ 0x7f6049ce, /* stvx v27,r0,r9 */ 0x39290020, /* addi r9,r9,32 */ 0x7f8041ce, /* stvx v28,r0,r8 */ 0x39080020, /* addi r8,r8,32 */ 0x7fa049ce, /* stvx v29,r0,r9 */ 0x39290020, /* addi r9,r9,32 */ 0x7fc041ce, /* stvx v30,r0,r8 */ 0x7fe049ce, /* stvx v31,r0,r9 */ 0x80a30034,/*2:lwz r5,52(r3) */ 0x39030180, /* addi r8,r3,384 */ 0x39230190, /* addi r9,r3,400 */ 0x70a00fff, /* andi. r0,r5,4095 */ 0x7ca043a6, /* mtvrsave r5 */ 0x4d820420, /* beqctr */ 0x7e8040ce, /* lvx v20,r0,r8 */ 0x39080020, /* addi r8,r8,32 */ 0x7ea048ce, /* lvx v21,r0,r9 */ 0x39290020, /* addi r9,r9,32 */ 0x7ec040ce, /* lvx v22,r0,r8 */ 0x39080020, /* addi r8,r8,32 */ 0x7ee048ce, /* lvx v23,r0,r9 */ 0x39290020, /* addi r9,r9,32 */ 0x7f0040ce, /* lvx v24,r0,r8 */ 0x39080020, /* addi r8,r8,32 */ 0x7f2048ce, /* lvx v25,r0,r9 */ 0x39290020, /* addi r9,r9,32 */ 0x7f4040ce, /* lvx v26,r0,r8 */ 0x39080020, /* addi r8,r8,32 */ 0x7f6048ce, /* lvx v27,r0,r9 */ 0x39290020, /* addi r9,r9,32 */ 0x7f8040ce, /* lvx v28,r0,r8 */ 0x39080020, /* addi r8,r8,32 */ 0x7fa048ce, /* lvx v29,r0,r9 */ 0x39290020, /* addi r9,r9,32 */ 0x7fc040ce, /* lvx v30,r0,r8 */ 0x7fe048ce, /* lvx v31,r0,r9 */ #endif 0x4e800420, /* bctr */ }; #if LIBCO_PPCDESC /* Function call goes through indirect descriptor */ #define CO_SWAP_ASM( x, y ) \ ((void (*)( cothread_t, cothread_t )) (uintptr_t) x)( x, y ) #else /* Function call goes directly to code */ #define CO_SWAP_ASM( x, y ) \ ((void (*)( cothread_t, cothread_t )) (uintptr_t) libco_ppc_code)( x, y ) #endif #endif static uint32_t* co_create_( unsigned size, uintptr_t entry ) { uint32_t* t = (uint32_t*) malloc( size ); (void) entry; #if LIBCO_PPCDESC if ( t ) { /* Copy entry's descriptor */ memcpy( t, (void*) entry, sizeof (void*) * 3 ); /* Set function pointer to swap routine */ #ifdef LIBCO_PPC_ASM *(const void**) t = *(void**) &co_swap_asm; #else *(const void**) t = libco_ppc_code; #endif } #endif return t; } cothread_t co_create( unsigned int size, void (*entry_)( void ) ) { uintptr_t entry = (uintptr_t) entry_; uint32_t* t = NULL; /* Be sure main thread was successfully allocated */ if ( co_active() ) { size += state_size + above_stack + stack_align; t = co_create_( size, entry ); } if ( t ) { uintptr_t sp; int shift; /* Save current registers into new thread, so that any special ones will have proper values when thread is begun */ CO_SWAP_ASM( t, t ); #if LIBCO_PPCDESC /* Get real address */ entry = (uintptr_t) *(void**) entry; #endif /* Put stack near end of block, and align */ sp = (uintptr_t) t + size - above_stack; sp -= sp % stack_align; /* On PPC32, we save and restore GPRs as 32 bits. For PPC64, we save and restore them as 64 bits, regardless of the size the ABI uses. So, we manually write pointers at the proper size. We always save and restore at the same address, and since PPC is big-endian, we must put the low byte first on PPC32. */ /* If uintptr_t is 32 bits, >>32 is undefined behavior, so we do two shifts and don't have to care how many bits uintptr_t is. */ #if LIBCO_PPC64 shift = 16; #else shift = 0; #endif /* Set up so entry will be called on next swap */ t [8] = (uint32_t) (entry >> shift >> shift); t [9] = (uint32_t) entry; t [10] = (uint32_t) (sp >> shift >> shift); t [11] = (uint32_t) sp; } return t; } void co_delete( cothread_t t ) { free(t); } static void co_init_( void ) { #if LIBCO_MPROTECT /* TODO: pre- and post-pad PPC code so that this doesn't make other data executable and writable */ long page_size = sysconf( _SC_PAGESIZE ); if ( page_size > 0 ) { uintptr_t align = page_size; uintptr_t begin = (uintptr_t) libco_ppc_code; uintptr_t end = begin + sizeof libco_ppc_code; /* Align beginning and end */ end += align - 1; end -= end % align; begin -= begin % align; mprotect( (void*) begin, end - begin, PROT_READ | PROT_WRITE | PROT_EXEC ); } #endif co_active_handle = co_create_( state_size, (uintptr_t) &co_switch ); } cothread_t co_active(void) { if (!co_active_handle) co_init_(); return co_active_handle; } void co_switch(cothread_t t) { cothread_t old = co_active_handle; co_active_handle = t; CO_SWAP_ASM( t, old ); } desmume/src/libretro-common/include/gfx/math/matrix_4x4.h000664 001750 001750 00000005060 12755534123 024564 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2016 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (matrix.h). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef __LIBRETRO_SDK_GFX_MATH_MATRIX_4X4_H__ #define __LIBRETRO_SDK_GFX_MATH_MATRIX_4X4_H__ /* Column-major matrix (OpenGL-style). * Reimplements functionality from FF OpenGL pipeline to be able * to work on GLES 2.0 and modern GL variants. */ typedef struct math_matrix_4x4 { float data[16]; } math_matrix_4x4; #define MAT_ELEM_4X4(mat, r, c) ((mat).data[4 * (c) + (r)]) void matrix_4x4_copy(math_matrix_4x4 *dst, const math_matrix_4x4 *src); void matrix_4x4_identity(math_matrix_4x4 *mat); void matrix_4x4_transpose(math_matrix_4x4 *out, const math_matrix_4x4 *in); void matrix_4x4_rotate_x(math_matrix_4x4 *mat, float rad); void matrix_4x4_rotate_y(math_matrix_4x4 *mat, float rad); void matrix_4x4_rotate_z(math_matrix_4x4 *mat, float rad); void matrix_4x4_ortho(math_matrix_4x4 *mat, float left, float right, float bottom, float top, float znear, float zfar); void matrix_4x4_multiply(math_matrix_4x4 *out, const math_matrix_4x4 *a, const math_matrix_4x4 *b); void matrix_4x4_scale(math_matrix_4x4 *out, float x, float y, float z); void matrix_4x4_translate(math_matrix_4x4 *out, float x, float y, float z); void matrix_4x4_projection(math_matrix_4x4 *out, float znear, float zfar); #endif desmume/src/utils/AsmJit/core/buffer.h000664 001750 001750 00000022205 12755534123 021041 0ustar00sergiosergio000000 000000 // [AsmJit] // Complete JIT Assembler for C++ Language. // // [License] // Zlib - See COPYING file in this package. // [Guard] #ifndef _ASMJIT_CORE_BUFFER_H #define _ASMJIT_CORE_BUFFER_H // [Dependencies - AsmJit] #include "../core/assert.h" #include "../core/build.h" // [Api-Begin] #include "../core/apibegin.h" namespace AsmJit { //! @addtogroup AsmJit_Core //! @{ // ============================================================================ // [Forward Declarations] // ============================================================================ struct Buffer; // ============================================================================ // [AsmJit::Buffer] // ============================================================================ //! @brief Buffer used to store instruction stream in AsmJit. //! //! This class can be dangerous, if you don't know how it works. Assembler //! instruction stream is usually constructed by multiple calls of emit //! functions that emits bytes, words, dwords or qwords. But to decrease //! AsmJit library size and improve performance, we are not checking for //! buffer overflow for each emit operation, but only once in highler level //! emit instruction. //! //! So, if you want to use this class, you need to do buffer checking yourself //! by using @c ensureSpace() method. It's designed to grow buffer if needed. //! Threshold for growing is named @c growThreshold() and it means count of //! bytes for emitting single operation. Default size is set to 16 bytes, //! because x86 and x64 instruction can't be larger (so it's space to hold 1 //! instruction). //! //! Example using Buffer: //! //! @code //! // Buffer instance, growThreshold == 16 //! // (no memory allocated in constructor). //! AsmJit::Buffer buf(16); //! //! // Begin of emit stream, ensure space can fail on out of memory error. //! if (buf.ensureSpace()) //! { //! // here, you can emit up to 16 (growThreshold) bytes //! buf.emitByte(0x00); //! buf.emitByte(0x01); //! buf.emitByte(0x02); //! buf.emitByte(0x03); //! ... //! } //! @endcode struct Buffer { // -------------------------------------------------------------------------- // [Construction / Destruction] // -------------------------------------------------------------------------- inline Buffer() : _data(NULL), _cur(NULL), _max(NULL), _capacity(0) { } inline ~Buffer() { if (_data) ASMJIT_FREE(_data); } //! @brief Get start of buffer. inline uint8_t* getData() const { return _data; } //! @brief Get current pointer in code buffer. inline uint8_t* getCur() const { return _cur; } //! @brief Get maximum pointer in code buffer for growing. inline uint8_t* getMax() const { return _max; } //! @brief Get current offset in buffer. inline size_t getOffset() const { return (size_t)(_cur - _data); } //! @brief Get capacity of buffer. inline size_t getCapacity() const { return _capacity; } //! @brief Ensure space for next instruction inline bool ensureSpace() { return (_cur >= _max) ? grow() : true; } //! @brief Sets offset to @a o and returns previous offset. //! //! This method can be used to truncate buffer or it's used to //! overwrite specific position in buffer by Assembler. inline size_t toOffset(size_t offset) { ASMJIT_ASSERT(offset < _capacity); size_t prev = (size_t)(_cur - _data); _cur = _data + offset; return prev; } //! @brief Reallocate buffer. //! //! It's only used for growing, buffer is never reallocated to smaller //! number than current capacity() is. ASMJIT_API bool realloc(size_t to); //! @brief Used to grow the buffer. //! //! It will typically realloc to twice size of capacity(), but if capacity() //! is large, it will use smaller steps. ASMJIT_API bool grow(); //! @brief Clear everything, but not deallocate buffer. inline void clear() { _cur = _data; } //! @brief Free buffer and NULL all pointers. ASMJIT_API void reset(); //! @brief Take ownership of the buffer data and purge @c Buffer instance. ASMJIT_API uint8_t* take(); // -------------------------------------------------------------------------- // [Emit] // -------------------------------------------------------------------------- //! @brief Emit Byte. inline void emitByte(uint8_t x) { ASMJIT_ASSERT(getOffset() + 1 <= _capacity); *_cur++ = x; } //! @brief Emit Word (2 bytes). inline void emitWord(uint16_t x) { ASMJIT_ASSERT(getOffset() + 2 <= _capacity); *(uint16_t *)_cur = x; _cur += 2; } //! @brief Emit DWord (4 bytes). inline void emitDWord(uint32_t x) { ASMJIT_ASSERT(getOffset() + 4 <= _capacity); *(uint32_t *)_cur = x; _cur += 4; } //! @brief Emit QWord (8 bytes). inline void emitQWord(uint64_t x) { ASMJIT_ASSERT(getOffset() + 8 <= _capacity); *(uint64_t *)_cur = x; _cur += 8; } //! @brief Emit intptr_t (4 or 8 bytes). inline void emitIntPtrT(intptr_t x) { ASMJIT_ASSERT(getOffset() + sizeof(intptr_t) <= _capacity); *(intptr_t *)_cur = x; _cur += sizeof(intptr_t); } //! @brief Emit uintptr_t (4 or 8 bytes). inline void emitUIntPtrT(uintptr_t x) { ASMJIT_ASSERT(getOffset() + sizeof(uintptr_t) <= _capacity); *(uintptr_t *)_cur = x; _cur += sizeof(uintptr_t); } //! @brief Emit size_t (4 or 8 bytes). inline void emitSizeT(size_t x) { ASMJIT_ASSERT(getOffset() + sizeof(size_t) <= _capacity); *(size_t *)_cur = x; _cur += sizeof(size_t); } //! @brief Emit custom data. ASMJIT_API void emitData(const void* ptr, size_t len); // -------------------------------------------------------------------------- // [Get / Set] // -------------------------------------------------------------------------- //! @brief Set byte at position @a pos. inline uint8_t getByteAt(size_t pos) const { ASMJIT_ASSERT(pos + 1 <= _capacity); return *reinterpret_cast(_data + pos); } //! @brief Set word at position @a pos. inline uint16_t getWordAt(size_t pos) const { ASMJIT_ASSERT(pos + 2 <= _capacity); return *reinterpret_cast(_data + pos); } //! @brief Set dword at position @a pos. inline uint32_t getDWordAt(size_t pos) const { ASMJIT_ASSERT(pos + 4 <= _capacity); return *reinterpret_cast(_data + pos); } //! @brief Set qword at position @a pos. inline uint64_t getQWordAt(size_t pos) const { ASMJIT_ASSERT(pos + 8 <= _capacity); return *reinterpret_cast(_data + pos); } //! @brief Set intptr_t at position @a pos. inline intptr_t getIntPtrTAt(size_t pos) const { ASMJIT_ASSERT(pos + sizeof(intptr_t) <= _capacity); return *reinterpret_cast(_data + pos); } //! @brief Set uintptr_t at position @a pos. inline uintptr_t getUIntPtrTAt(size_t pos) const { ASMJIT_ASSERT(pos + sizeof(uintptr_t) <= _capacity); return *reinterpret_cast(_data + pos); } //! @brief Set size_t at position @a pos. inline uintptr_t getSizeTAt(size_t pos) const { ASMJIT_ASSERT(pos + sizeof(size_t) <= _capacity); return *reinterpret_cast(_data + pos); } //! @brief Set byte at position @a pos. inline void setByteAt(size_t pos, uint8_t x) { ASMJIT_ASSERT(pos + 1 <= _capacity); *reinterpret_cast(_data + pos) = x; } //! @brief Set word at position @a pos. inline void setWordAt(size_t pos, uint16_t x) { ASMJIT_ASSERT(pos + 2 <= _capacity); *reinterpret_cast(_data + pos) = x; } //! @brief Set dword at position @a pos. inline void setDWordAt(size_t pos, uint32_t x) { ASMJIT_ASSERT(pos + 4 <= _capacity); *reinterpret_cast(_data + pos) = x; } //! @brief Set qword at position @a pos. inline void setQWordAt(size_t pos, uint64_t x) { ASMJIT_ASSERT(pos + 8 <= _capacity); *reinterpret_cast(_data + pos) = x; } //! @brief Set intptr_t at position @a pos. inline void setIntPtrTAt(size_t pos, intptr_t x) { ASMJIT_ASSERT(pos + sizeof(intptr_t) <= _capacity); *reinterpret_cast(_data + pos) = x; } //! @brief Set uintptr_t at position @a pos. inline void setUIntPtrTAt(size_t pos, uintptr_t x) { ASMJIT_ASSERT(pos + sizeof(uintptr_t) <= _capacity); *reinterpret_cast(_data + pos) = x; } //! @brief Set size_t at position @a pos. inline void setSizeTAt(size_t pos, size_t x) { ASMJIT_ASSERT(pos + sizeof(size_t) <= _capacity); *reinterpret_cast(_data + pos) = x; } // -------------------------------------------------------------------------- // [Members] // -------------------------------------------------------------------------- // All members are public, because they can be accessed and modified by // Assembler/Compiler directly. //! @brief Beginning position of buffer. uint8_t* _data; //! @brief Current position in buffer. uint8_t* _cur; //! @brief Maximum position in buffer for realloc. uint8_t* _max; //! @brief Buffer capacity (in bytes). size_t _capacity; }; //! @} } // AsmJit namespace // [Api-End] #include "../core/apiend.h" #endif // _ASMJIT_CORE_BUFFER_H desmume/src/OGLRender.cpp000664 001750 001750 00000511334 12755534123 016433 0ustar00sergiosergio000000 000000 /* Copyright (C) 2006 yopyop Copyright (C) 2006-2007 shash Copyright (C) 2008-2016 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the this software. If not, see . */ #include "OGLRender.h" #include #include #include #include #include "common.h" #include "debug.h" #include "gfx3d.h" #include "NDSSystem.h" #include "texcache.h" #ifdef ENABLE_SSE2 #include #endif #ifdef ENABLE_SSSE3 #include #endif typedef struct { unsigned int major; unsigned int minor; unsigned int revision; } OGLVersion; static OGLVersion _OGLDriverVersion = {0, 0, 0}; // Lookup Tables static CACHE_ALIGN GLfloat material_8bit_to_float[256] = {0}; CACHE_ALIGN const GLfloat divide5bitBy31_LUT[32] = {0.0, 0.03225806451613, 0.06451612903226, 0.09677419354839, 0.1290322580645, 0.1612903225806, 0.1935483870968, 0.2258064516129, 0.2580645161290, 0.2903225806452, 0.3225806451613, 0.3548387096774, 0.3870967741935, 0.4193548387097, 0.4516129032258, 0.4838709677419, 0.5161290322581, 0.5483870967742, 0.5806451612903, 0.6129032258065, 0.6451612903226, 0.6774193548387, 0.7096774193548, 0.7419354838710, 0.7741935483871, 0.8064516129032, 0.8387096774194, 0.8709677419355, 0.9032258064516, 0.9354838709677, 0.9677419354839, 1.0}; const GLfloat PostprocessVtxBuffer[16] = {-1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f}; const GLubyte PostprocessElementBuffer[6] = {0, 1, 2, 2, 3, 0}; const GLenum RenderDrawList[4] = {GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_COLOR_ATTACHMENT2_EXT, GL_COLOR_ATTACHMENT3_EXT}; bool BEGINGL() { if(oglrender_beginOpenGL) return oglrender_beginOpenGL(); else return true; } void ENDGL() { if(oglrender_endOpenGL) oglrender_endOpenGL(); } // Function Pointers bool (*oglrender_init)() = NULL; bool (*oglrender_beginOpenGL)() = NULL; void (*oglrender_endOpenGL)() = NULL; bool (*oglrender_framebufferDidResizeCallback)(size_t w, size_t h) = NULL; void (*OGLLoadEntryPoints_3_2_Func)() = NULL; void (*OGLCreateRenderer_3_2_Func)(OpenGLRenderer **rendererPtr) = NULL; static void OGLLoadEntryPoints_Legacy() { } // Vertex Shader GLSL 1.00 static const char *vertexShader_100 = {"\ attribute vec4 inPosition; \n\ attribute vec2 inTexCoord0; \n\ attribute vec3 inColor; \n\ \n\ uniform float polyAlpha; \n\ uniform vec2 polyTexScale; \n\ \n\ varying vec4 vtxPosition; \n\ varying vec2 vtxTexCoord; \n\ varying vec4 vtxColor; \n\ \n\ void main() \n\ { \n\ mat2 texScaleMtx = mat2( vec2(polyTexScale.x, 0.0), \n\ vec2( 0.0, polyTexScale.y)); \n\ \n\ vtxPosition = inPosition; \n\ vtxTexCoord = texScaleMtx * inTexCoord0; \n\ vtxColor = vec4(inColor * 4.0, polyAlpha); \n\ \n\ gl_Position = vtxPosition; \n\ } \n\ "}; // Fragment Shader GLSL 1.00 static const char *fragmentShader_100 = {"\ varying vec4 vtxPosition; \n\ varying vec2 vtxTexCoord; \n\ varying vec4 vtxColor; \n\ \n\ uniform sampler2D texRenderObject; \n\ uniform sampler1D texToonTable; \n\ \n\ uniform int stateToonShadingMode; \n\ uniform bool stateEnableAlphaTest; \n\ uniform bool stateEnableAntialiasing;\n\ uniform bool stateEnableEdgeMarking;\n\ uniform bool stateUseWDepth; \n\ uniform float stateAlphaTestRef; \n\ \n\ uniform int polyMode; \n\ uniform bool polyEnableDepthWrite;\n\ uniform bool polySetNewDepthForTranslucent;\n\ uniform int polyID; \n\ \n\ uniform bool polyEnableTexture; \n\ uniform bool polyEnableFog;\n\ \n\ vec3 packVec3FromFloat(const float value)\n\ {\n\ float expandedValue = value * 16777215.0;\n\ vec3 packedValue = vec3( fract(expandedValue/256.0), fract(((expandedValue/256.0) - fract(expandedValue/256.0)) / 256.0), fract(((expandedValue/65536.0) - fract(expandedValue/65536.0)) / 256.0) );\n\ return packedValue;\n\ }\n\ \n\ void main() \n\ { \n\ vec4 mainTexColor = (polyEnableTexture) ? texture2D(texRenderObject, vtxTexCoord) : vec4(1.0, 1.0, 1.0, 1.0); \n\ vec4 newFragColor = mainTexColor * vtxColor; \n\ \n\ if(polyMode == 1) \n\ { \n\ newFragColor.rgb = (polyEnableTexture) ? mix(vtxColor.rgb, mainTexColor.rgb, mainTexColor.a) : vtxColor.rgb; \n\ newFragColor.a = vtxColor.a; \n\ } \n\ else if(polyMode == 2) \n\ { \n\ vec3 toonColor = vec3(texture1D(texToonTable, vtxColor.r).rgb); \n\ newFragColor.rgb = (stateToonShadingMode == 0) ? mainTexColor.rgb * toonColor.rgb : min((mainTexColor.rgb * vtxColor.r) + toonColor.rgb, 1.0); \n\ } \n\ else if(polyMode == 3) \n\ { \n\ if (polyID != 0) \n\ { \n\ newFragColor = vtxColor; \n\ } \n\ } \n\ \n\ if (newFragColor.a == 0.0 || (stateEnableAlphaTest && newFragColor.a < stateAlphaTestRef)) \n\ { \n\ discard; \n\ } \n\ \n\ float vertW = (vtxPosition.w == 0.0) ? 0.00000001 : vtxPosition.w; \n\ // hack: when using z-depth, drop some LSBs so that the overworld map in Dragon Quest IV shows up correctly\n\ float newFragDepth = (stateUseWDepth) ? vtxPosition.w/4096.0 : clamp( (floor((((vtxPosition.z/vertW) * 0.5 + 0.5) * 16777215.0) / 4.0) * 4.0) / 16777215.0, 0.0, 1.0); \n\ \n\ gl_FragData[0] = newFragColor;\n\ gl_FragData[1] = vec4( packVec3FromFloat(newFragDepth), float(polyEnableDepthWrite && (newFragColor.a > 0.999 || polySetNewDepthForTranslucent)));\n\ gl_FragData[2] = vec4(float(polyID)/63.0, 0.0, 0.0, float(newFragColor.a > 0.999));\n\ gl_FragData[3] = vec4( float(polyEnableFog), 0.0, 0.0, float(newFragColor.a > 0.999 || !polyEnableFog));\n\ gl_FragDepth = newFragDepth;\n\ } \n\ "}; // Vertex shader for applying edge marking, GLSL 1.00 static const char *EdgeMarkVtxShader_100 = {"\ attribute vec2 inPosition;\n\ attribute vec2 inTexCoord0;\n\ uniform vec2 framebufferSize;\n\ varying vec2 texCoord[5];\n\ \n\ void main()\n\ {\n\ vec2 texInvScale = vec2(1.0/framebufferSize.x, 1.0/framebufferSize.y);\n\ \n\ texCoord[0] = inTexCoord0; // Center\n\ texCoord[1] = inTexCoord0 + (vec2( 1.0, 0.0) * texInvScale); // Right\n\ texCoord[2] = inTexCoord0 + (vec2( 0.0, 1.0) * texInvScale); // Down\n\ texCoord[3] = inTexCoord0 + (vec2(-1.0, 0.0) * texInvScale); // Left\n\ texCoord[4] = inTexCoord0 + (vec2( 0.0,-1.0) * texInvScale); // Up\n\ \n\ gl_Position = vec4(inPosition, 0.0, 1.0);\n\ }\n\ "}; // Fragment shader for applying edge marking, GLSL 1.00 static const char *EdgeMarkFragShader_100 = {"\ varying vec2 texCoord[5];\n\ \n\ uniform sampler2D texInFragDepth;\n\ uniform sampler2D texInPolyID;\n\ uniform vec4 stateEdgeColor[8];\n\ \n\ float unpackFloatFromVec3(const vec3 value)\n\ {\n\ const vec3 unpackRatio = vec3(256.0, 65536.0, 16777216.0);\n\ return (dot(value, unpackRatio) / 16777215.0);\n\ }\n\ \n\ void main()\n\ {\n\ int polyID[5];\n\ polyID[0] = int((texture2D(texInPolyID, texCoord[0]).r * 63.0) + 0.5);\n\ polyID[1] = int((texture2D(texInPolyID, texCoord[1]).r * 63.0) + 0.5);\n\ polyID[2] = int((texture2D(texInPolyID, texCoord[2]).r * 63.0) + 0.5);\n\ polyID[3] = int((texture2D(texInPolyID, texCoord[3]).r * 63.0) + 0.5);\n\ polyID[4] = int((texture2D(texInPolyID, texCoord[4]).r * 63.0) + 0.5);\n\ \n\ float depth[5];\n\ depth[0] = unpackFloatFromVec3(texture2D(texInFragDepth, texCoord[0]).rgb);\n\ depth[1] = unpackFloatFromVec3(texture2D(texInFragDepth, texCoord[1]).rgb);\n\ depth[2] = unpackFloatFromVec3(texture2D(texInFragDepth, texCoord[2]).rgb);\n\ depth[3] = unpackFloatFromVec3(texture2D(texInFragDepth, texCoord[3]).rgb);\n\ depth[4] = unpackFloatFromVec3(texture2D(texInFragDepth, texCoord[4]).rgb);\n\ \n\ vec4 edgeColor = vec4(0.0, 0.0, 0.0, 0.0);\n\ \n\ for (int i = 1; i < 5; i++)\n\ {\n\ if (polyID[0] != polyID[i] && depth[0] >= depth[i])\n\ {\n\ edgeColor = stateEdgeColor[polyID[i]/8];\n\ break;\n\ }\n\ }\n\ \n\ gl_FragData[0] = edgeColor;\n\ }\n\ "}; // Vertex shader for applying fog, GLSL 1.00 static const char *FogVtxShader_100 = {"\ attribute vec2 inPosition;\n\ attribute vec2 inTexCoord0;\n\ varying vec2 texCoord;\n\ \n\ void main() \n\ { \n\ texCoord = inTexCoord0; \n\ gl_Position = vec4(inPosition, 0.0, 1.0);\n\ }\n\ "}; // Fragment shader for applying fog, GLSL 1.00 static const char *FogFragShader_100 = {"\ varying vec2 texCoord;\n\ \n\ uniform sampler2D texInFragColor;\n\ uniform sampler2D texInFragDepth;\n\ uniform sampler2D texInFogAttributes;\n\ uniform bool stateEnableFogAlphaOnly;\n\ uniform vec4 stateFogColor;\n\ uniform float stateFogDensity[32];\n\ uniform float stateFogOffset;\n\ uniform float stateFogStep;\n\ \n\ float unpackFloatFromVec3(const vec3 value)\n\ {\n\ const vec3 unpackRatio = vec3(256.0, 65536.0, 16777216.0);\n\ return (dot(value, unpackRatio) / 16777215.0);\n\ }\n\ \n\ void main()\n\ {\n\ vec4 inFragColor = texture2D(texInFragColor, texCoord);\n\ vec4 inFogAttributes = texture2D(texInFogAttributes, texCoord);\n\ bool polyEnableFog = bool(inFogAttributes.r);\n\ vec4 newFoggedColor = inFragColor;\n\ \n\ if (polyEnableFog)\n\ {\n\ float inFragDepth = unpackFloatFromVec3(texture2D(texInFragDepth, texCoord).rgb);\n\ float fogMixWeight = 0.0;\n\ \n\ if (inFragDepth <= min(stateFogOffset + stateFogStep, 1.0))\n\ {\n\ fogMixWeight = stateFogDensity[0];\n\ }\n\ else if (inFragDepth >= min(stateFogOffset + (stateFogStep*32.0), 1.0))\n\ {\n\ fogMixWeight = stateFogDensity[31];\n\ }\n\ else\n\ {\n\ for (int i = 1; i < 32; i++)\n\ {\n\ float currentFogStep = min(stateFogOffset + (stateFogStep * float(i+1)), 1.0);\n\ if (inFragDepth <= currentFogStep)\n\ {\n\ float previousFogStep = min(stateFogOffset + (stateFogStep * float(i)), 1.0);\n\ fogMixWeight = mix(stateFogDensity[i-1], stateFogDensity[i], (inFragDepth - previousFogStep) / (currentFogStep - previousFogStep));\n\ break;\n\ }\n\ }\n\ }\n\ \n\ newFoggedColor = mix(inFragColor, (stateEnableFogAlphaOnly) ? vec4(inFragColor.rgb, stateFogColor.a) : stateFogColor, fogMixWeight);\n\ }\n\ \n\ gl_FragData[0] = newFoggedColor;\n\ }\n\ "}; // Vertex shader for the final framebuffer, GLSL 1.00 static const char *FramebufferOutputVtxShader_100 = {"\ attribute vec2 inPosition;\n\ attribute vec2 inTexCoord0;\n\ varying vec2 texCoord;\n\ \n\ void main()\n\ {\n\ texCoord = inTexCoord0;\n\ gl_Position = vec4(inPosition, 0.0, 1.0);\n\ }\n\ "}; // Fragment shader for the final RGBA6665 formatted framebuffer, GLSL 1.00 static const char *FramebufferOutputRGBA6665FragShader_100 = {"\ varying vec2 texCoord;\n\ \n\ uniform sampler2D texInFragColor;\n\ \n\ void main()\n\ {\n\ // Note that we swap B and R since pixel readbacks are done in BGRA format for fastest\n\ // performance. The final color is still in RGBA format.\n\ vec4 colorRGBA6665 = texture2D(texInFragColor, texCoord).bgra;\n\ colorRGBA6665 = floor((colorRGBA6665 * 255.0) + 0.5);\n\ colorRGBA6665.rgb = floor(colorRGBA6665.rgb / 4.0);\n\ colorRGBA6665.a = floor(colorRGBA6665.a / 8.0);\n\ \n\ gl_FragData[0] = (colorRGBA6665 / 255.0);\n\ }\n\ "}; // Fragment shader for the final RGBA8888 formatted framebuffer, GLSL 1.00 static const char *FramebufferOutputRGBA8888FragShader_100 = {"\ varying vec2 texCoord;\n\ \n\ uniform sampler2D texInFragColor;\n\ \n\ void main()\n\ {\n\ gl_FragData[0] = texture2D(texInFragColor, texCoord).bgra;\n\ }\n\ "}; FORCEINLINE u32 BGRA8888_32_To_RGBA6665_32(const u32 srcPix) { const u32 dstPix = (srcPix >> 2); return (dstPix & 0x00003F00) << 16 | // R (dstPix & 0x003F0000) | // G (dstPix & 0x3F000000) >> 16 | // B ((dstPix >> 1) & 0x0000001F); // A } FORCEINLINE u32 BGRA8888_32Rev_To_RGBA6665_32Rev(const u32 srcPix) { const u32 dstPix = (srcPix >> 2); return (dstPix & 0x003F0000) >> 16 | // R (dstPix & 0x00003F00) | // G (dstPix & 0x0000003F) << 16 | // B ((dstPix >> 1) & 0x1F000000); // A } FORCEINLINE FragmentColor BGRA8888_32_To_RGBA6665_32(const FragmentColor src) { FragmentColor dst = src; dst.r = src.b >> 2; dst.g = src.g >> 2; dst.b = src.r >> 2; dst.a = src.a >> 3; return dst; } FORCEINLINE FragmentColor BGRA8888_32Rev_To_RGBA6665_32Rev(const FragmentColor src) { FragmentColor dst = src; dst.r = src.b >> 2; dst.g = src.g >> 2; dst.b = src.r >> 2; dst.a = src.a >> 3; return dst; } FORCEINLINE u16 BGRA8888_32_To_RGBA5551_16(const FragmentColor src) { return R5G5B5TORGB15( (src.b >> 3), (src.g >> 3), (src.r >> 3)) | ((src.a == 0) ? 0x0000 : 0x8000); } FORCEINLINE u16 BGRA8888_32Rev_To_RGBA5551_16Rev(const FragmentColor src) { return R5G5B5TORGB15( (src.b >> 3), (src.g >> 3), (src.r >> 3)) | ((src.a == 0) ? 0x0000 : 0x8000); } #ifdef ENABLE_SSSE3 FORCEINLINE __m128i BGRA8888_32Rev_To_RGBA6665_32Rev(const __m128i src) { const __m128i rgb = _mm_srli_epi32(_mm_and_si128(src, _mm_set1_epi32(0x00FCFCFC)), 2); const __m128i a = _mm_srli_epi32(_mm_and_si128(src, _mm_set1_epi32(0xF8000000)), 3); return _mm_shuffle_epi8(_mm_or_si128(rgb, a), _mm_set_epi8(15, 12, 13, 14, 11, 8, 9, 10, 7, 4, 5, 6, 3, 0, 1, 2)); // Swizzle RGBA to BGRA } FORCEINLINE __m128i BGRA8888_32Rev_To_RGBA5551_16Rev(const __m128i src) { __m128i b = _mm_and_si128(src, _mm_set1_epi32(0x000000F8)); // Read from R b = _mm_slli_epi32(b, 7); // Shift to B __m128i g = _mm_and_si128(src, _mm_set1_epi32(0x0000F800)); // Read from G g = _mm_srli_epi32(g, 6); // Shift in G __m128i r = _mm_and_si128(src, _mm_set1_epi32(0x00F80000)); // Read from B r = _mm_srli_epi32(r, 19); // Shift to R __m128i a = _mm_and_si128(src, _mm_set1_epi32(0xFF000000)); // Read from A a = _mm_cmpeq_epi32(a, _mm_setzero_si128()); // Determine A a = _mm_andnot_si128(a, _mm_set1_epi32(0x00008000)); // Mask to A // All the colors are currently placed on 32 bit boundaries, so we need to swizzle them // to the lower 64 bits of our vector before we store them back to memory. // Note: Do not attempt to use packssdw here since packing with the 0x8000 bit set will // result in values of 0x7FFF, which are incorrect values in this case. return _mm_shuffle_epi8(_mm_or_si128(_mm_or_si128(_mm_or_si128(b, g), r), a), _mm_set_epi8(15, 14, 11, 10, 7, 6, 3, 2, 13, 12, 9, 8, 5, 4, 1, 0)); } #endif bool IsVersionSupported(unsigned int checkVersionMajor, unsigned int checkVersionMinor, unsigned int checkVersionRevision) { bool result = false; if ( (_OGLDriverVersion.major > checkVersionMajor) || (_OGLDriverVersion.major >= checkVersionMajor && _OGLDriverVersion.minor > checkVersionMinor) || (_OGLDriverVersion.major >= checkVersionMajor && _OGLDriverVersion.minor >= checkVersionMinor && _OGLDriverVersion.revision >= checkVersionRevision) ) { result = true; } return result; } static void OGLGetDriverVersion(const char *oglVersionString, unsigned int *versionMajor, unsigned int *versionMinor, unsigned int *versionRevision) { size_t versionStringLength = 0; if (oglVersionString == NULL) return; // First, check for the dot in the revision string. There should be at // least one present. const char *versionStrEnd = strstr(oglVersionString, "."); if (versionStrEnd == NULL) return; // Next, check for the space before the vendor-specific info (if present). versionStrEnd = strstr(oglVersionString, " "); if (versionStrEnd == NULL) { // If a space was not found, then the vendor-specific info is not present, // and therefore the entire string must be the version number. versionStringLength = strlen(oglVersionString); } else { // If a space was found, then the vendor-specific info is present, // and therefore the version number is everything before the space. versionStringLength = versionStrEnd - oglVersionString; } // Copy the version substring and parse it. char *versionSubstring = (char *)malloc(versionStringLength * sizeof(char)); strncpy(versionSubstring, oglVersionString, versionStringLength); unsigned int major = 0; unsigned int minor = 0; unsigned int revision = 0; sscanf(versionSubstring, "%u.%u.%u", &major, &minor, &revision); free(versionSubstring); versionSubstring = NULL; if (versionMajor != NULL) *versionMajor = major; if (versionMinor != NULL) *versionMinor = minor; if (versionRevision != NULL) *versionRevision = revision; } void texDeleteCallback(TexCacheItem *texItem, void *param1, void *param2) { OpenGLRenderer *oglRenderer = (OpenGLRenderer *)param1; oglRenderer->DeleteTexture(texItem); } template static Render3D* OpenGLRendererCreate() { OpenGLRenderer *newRenderer = NULL; Render3DError error = OGLERROR_NOERR; if (oglrender_init == NULL) return NULL; if (!oglrender_init()) return NULL; if (!BEGINGL()) { INFO("OpenGL<%s,%s>: Could not initialize -- BEGINGL() failed.\n",require_profile?"force":"auto",enable_3_2?"3_2":"old"); return NULL; } // Get OpenGL info const char *oglVersionString = (const char *)glGetString(GL_VERSION); const char *oglVendorString = (const char *)glGetString(GL_VENDOR); const char *oglRendererString = (const char *)glGetString(GL_RENDERER); // Writing to gl_FragDepth causes the driver to fail miserably on systems equipped // with a Intel G965 graphic card. Warn the user and fail gracefully. // http://forums.desmume.org/viewtopic.php?id=9286 if(!strcmp(oglVendorString,"Intel") && strstr(oglRendererString,"965")) { INFO("OpenGL: Incompatible graphic card detected. Disabling OpenGL support.\n"); ENDGL(); return newRenderer; } // Check the driver's OpenGL version OGLGetDriverVersion(oglVersionString, &_OGLDriverVersion.major, &_OGLDriverVersion.minor, &_OGLDriverVersion.revision); if (!IsVersionSupported(OGLRENDER_MINIMUM_DRIVER_VERSION_REQUIRED_MAJOR, OGLRENDER_MINIMUM_DRIVER_VERSION_REQUIRED_MINOR, OGLRENDER_MINIMUM_DRIVER_VERSION_REQUIRED_REVISION)) { INFO("OpenGL: Driver does not support OpenGL v%u.%u.%u or later. Disabling 3D renderer.\n[ Driver Info -\n Version: %s\n Vendor: %s\n Renderer: %s ]\n", OGLRENDER_MINIMUM_DRIVER_VERSION_REQUIRED_MAJOR, OGLRENDER_MINIMUM_DRIVER_VERSION_REQUIRED_MINOR, OGLRENDER_MINIMUM_DRIVER_VERSION_REQUIRED_REVISION, oglVersionString, oglVendorString, oglRendererString); ENDGL(); return newRenderer; } // Create new OpenGL rendering object if (enable_3_2) { if (OGLLoadEntryPoints_3_2_Func != NULL && OGLCreateRenderer_3_2_Func != NULL) { OGLLoadEntryPoints_3_2_Func(); OGLLoadEntryPoints_Legacy(); //zero 04-feb-2013 - this seems to be necessary as well OGLCreateRenderer_3_2_Func(&newRenderer); } else { if(require_profile) { ENDGL(); return newRenderer; } } } // If the renderer doesn't initialize with OpenGL v3.2 or higher, fall back // to one of the lower versions. if (newRenderer == NULL) { OGLLoadEntryPoints_Legacy(); if (IsVersionSupported(2, 1, 0)) { newRenderer = new OpenGLRenderer_2_1; newRenderer->SetVersion(2, 1, 0); } else if (IsVersionSupported(2, 0, 0)) { newRenderer = new OpenGLRenderer_2_0; newRenderer->SetVersion(2, 0, 0); } else if (IsVersionSupported(1, 5, 0)) { newRenderer = new OpenGLRenderer_1_5; newRenderer->SetVersion(1, 5, 0); } else if (IsVersionSupported(1, 4, 0)) { newRenderer = new OpenGLRenderer_1_4; newRenderer->SetVersion(1, 4, 0); } else if (IsVersionSupported(1, 3, 0)) { newRenderer = new OpenGLRenderer_1_3; newRenderer->SetVersion(1, 3, 0); } else if (IsVersionSupported(1, 2, 0)) { newRenderer = new OpenGLRenderer_1_2; newRenderer->SetVersion(1, 2, 0); } } if (newRenderer == NULL) { INFO("OpenGL: Renderer did not initialize. Disabling 3D renderer.\n[ Driver Info -\n Version: %s\n Vendor: %s\n Renderer: %s ]\n", oglVersionString, oglVendorString, oglRendererString); ENDGL(); return newRenderer; } // Initialize OpenGL extensions error = newRenderer->InitExtensions(); if (error != OGLERROR_NOERR) { if ( IsVersionSupported(2, 0, 0) && (error == OGLERROR_SHADER_CREATE_ERROR || error == OGLERROR_VERTEX_SHADER_PROGRAM_LOAD_ERROR || error == OGLERROR_FRAGMENT_SHADER_PROGRAM_LOAD_ERROR) ) { INFO("OpenGL: Shaders are not working, even though they should be. Disabling 3D renderer.\n"); delete newRenderer; newRenderer = NULL; ENDGL(); return newRenderer; } else if (IsVersionSupported(3, 0, 0) && error == OGLERROR_FBO_CREATE_ERROR && OGLLoadEntryPoints_3_2_Func != NULL) { INFO("OpenGL: FBOs are not working, even though they should be. Disabling 3D renderer.\n"); delete newRenderer; newRenderer = NULL; ENDGL(); return newRenderer; } } ENDGL(); // Initialization finished -- reset the renderer newRenderer->Reset(); unsigned int major = 0; unsigned int minor = 0; unsigned int revision = 0; newRenderer->GetVersion(&major, &minor, &revision); INFO("OpenGL: Renderer initialized successfully (v%u.%u.%u).\n[ Driver Info -\n Version: %s\n Vendor: %s\n Renderer: %s ]\n", major, minor, revision, oglVersionString, oglVendorString, oglRendererString); return newRenderer; } static void OpenGLRendererDestroy() { if(!BEGINGL()) return; if (CurrentRenderer != BaseRenderer) { OpenGLRenderer *oldRenderer = (OpenGLRenderer *)CurrentRenderer; CurrentRenderer = BaseRenderer; delete oldRenderer; } ENDGL(); } //automatically select 3.2 or old profile depending on whether 3.2 is available GPU3DInterface gpu3Dgl = { "OpenGL", OpenGLRendererCreate, OpenGLRendererDestroy }; //forcibly use old profile GPU3DInterface gpu3DglOld = { "OpenGL Old", OpenGLRendererCreate, OpenGLRendererDestroy }; //forcibly use new profile GPU3DInterface gpu3Dgl_3_2 = { "OpenGL 3.2", OpenGLRendererCreate, OpenGLRendererDestroy }; OpenGLRenderer::OpenGLRenderer() { _renderID = RENDERID_OPENGL_AUTO; _renderName = "OpenGL"; _internalRenderingFormat = NDSColorFormat_BGR888_Rev; versionMajor = 0; versionMinor = 0; versionRevision = 0; isVBOSupported = false; isPBOSupported = false; isFBOSupported = false; isMultisampledFBOSupported = false; isShaderSupported = false; isVAOSupported = false; willFlipFramebufferOnGPU = false; willConvertFramebufferOnGPU = false; // Init OpenGL rendering states ref = new OGLRenderRef; ref->fboRenderID = 0; ref->fboMSIntermediateRenderID = 0; ref->fboPostprocessID = 0; ref->selectedRenderingFBO = 0; currTexture = NULL; _mappedFramebuffer = NULL; _pixelReadNeedsFinish = false; _currentPolyIndex = 0; _shadowPolyID.reserve(POLYLIST_SIZE); } OpenGLRenderer::~OpenGLRenderer() { free_aligned(_framebufferColor); // Destroy OpenGL rendering states delete ref; ref = NULL; } bool OpenGLRenderer::IsExtensionPresent(const std::set *oglExtensionSet, const std::string extensionName) const { if (oglExtensionSet == NULL || oglExtensionSet->size() == 0) return false; return (oglExtensionSet->find(extensionName) != oglExtensionSet->end()); } bool OpenGLRenderer::ValidateShaderCompile(GLuint theShader) const { bool isCompileValid = false; GLint status = GL_FALSE; glGetShaderiv(theShader, GL_COMPILE_STATUS, &status); if(status == GL_TRUE) { isCompileValid = true; } else { GLint logSize; GLchar *log = NULL; glGetShaderiv(theShader, GL_INFO_LOG_LENGTH, &logSize); log = new GLchar[logSize]; glGetShaderInfoLog(theShader, logSize, &logSize, log); INFO("OpenGL: SEVERE - FAILED TO COMPILE SHADER : %s\n", log); delete[] log; } return isCompileValid; } bool OpenGLRenderer::ValidateShaderProgramLink(GLuint theProgram) const { bool isLinkValid = false; GLint status = GL_FALSE; glGetProgramiv(theProgram, GL_LINK_STATUS, &status); if(status == GL_TRUE) { isLinkValid = true; } else { GLint logSize; GLchar *log = NULL; glGetProgramiv(theProgram, GL_INFO_LOG_LENGTH, &logSize); log = new GLchar[logSize]; glGetProgramInfoLog(theProgram, logSize, &logSize, log); INFO("OpenGL: SEVERE - FAILED TO LINK SHADER PROGRAM : %s\n", log); delete[] log; } return isLinkValid; } void OpenGLRenderer::GetVersion(unsigned int *major, unsigned int *minor, unsigned int *revision) const { *major = this->versionMajor; *minor = this->versionMinor; *revision = this->versionRevision; } void OpenGLRenderer::SetVersion(unsigned int major, unsigned int minor, unsigned int revision) { this->versionMajor = major; this->versionMinor = minor; this->versionRevision = revision; } Render3DError OpenGLRenderer::_FlushFramebufferConvertOnCPU(const FragmentColor *__restrict srcFramebuffer, FragmentColor *__restrict dstFramebuffer, u16 *__restrict dstRGBA5551) { if ( ((dstFramebuffer == NULL) && (dstRGBA5551 == NULL)) || (srcFramebuffer == NULL) ) return RENDER3DERROR_NOERR; // Convert from 32-bit BGRA8888 format to 32-bit RGBA6665 reversed format. OpenGL // stores pixels using a flipped Y-coordinate, so this needs to be flipped back // to the DS Y-coordinate. size_t i = 0; const size_t pixCount = this->_framebufferWidth; #ifdef ENABLE_SSSE3 const size_t ssePixCount = pixCount - (pixCount % 4); #endif if (this->willFlipFramebufferOnGPU) { if (this->_outputFormat == NDSColorFormat_BGR666_Rev) { if ( (dstFramebuffer != NULL) && (dstRGBA5551 != NULL) ) { #ifdef ENABLE_SSSE3 for (; i < ssePixCount; i += 4) { const __m128i srcColor = _mm_load_si128((__m128i *)(srcFramebuffer + i)); const __m128i color6665 = BGRA8888_32Rev_To_RGBA6665_32Rev(srcColor); const __m128i color5551 = BGRA8888_32Rev_To_RGBA5551_16Rev(srcColor); _mm_store_si128((__m128i *)(dstFramebuffer + i), color6665); _mm_storel_epi64((__m128i *)(dstRGBA5551 + i), color5551); } #endif for (; i < pixCount; i++) { #ifdef MSB_FIRST dstFramebuffer[i] = BGRA8888_32_To_RGBA6665_32(srcFramebuffer[i]); dstRGBA5551[i] = BGRA8888_32_To_RGBA5551_16(srcFramebuffer[i]); #else dstFramebuffer[i] = BGRA8888_32Rev_To_RGBA6665_32Rev(srcFramebuffer[i]); dstRGBA5551[i] = BGRA8888_32Rev_To_RGBA5551_16Rev(srcFramebuffer[i]); #endif } } else if (dstFramebuffer != NULL) { #ifdef ENABLE_SSSE3 for (; i < ssePixCount; i += 4) { const __m128i srcColor = _mm_load_si128((__m128i *)(srcFramebuffer + i)); const __m128i color6665 = BGRA8888_32Rev_To_RGBA6665_32Rev(srcColor); _mm_store_si128((__m128i *)(dstFramebuffer + i), color6665); } #endif for (; i < pixCount; i++) { #ifdef MSB_FIRST dstFramebuffer[i] = BGRA8888_32_To_RGBA6665_32(srcFramebuffer[i]); #else dstFramebuffer[i] = BGRA8888_32Rev_To_RGBA6665_32Rev(srcFramebuffer[i]); #endif } } else { #ifdef ENABLE_SSSE3 for (; i < ssePixCount; i += 4) { const __m128i srcColor = _mm_load_si128((__m128i *)(srcFramebuffer + i)); const __m128i color5551 = BGRA8888_32Rev_To_RGBA5551_16Rev(srcColor); _mm_storel_epi64((__m128i *)(dstRGBA5551 + i), color5551); } #endif for (; i < pixCount; i++) { #ifdef MSB_FIRST dstRGBA5551[i] = BGRA8888_32_To_RGBA5551_16(srcFramebuffer[i]); #else dstRGBA5551[i] = BGRA8888_32Rev_To_RGBA5551_16Rev(srcFramebuffer[i]); #endif } } } else if (this->_outputFormat == NDSColorFormat_BGR888_Rev) { if ( (dstFramebuffer != NULL) && (dstRGBA5551 != NULL) ) { #ifdef ENABLE_SSSE3 for (; i < ssePixCount; i += 4) { const __m128i srcColor = _mm_load_si128((__m128i *)(srcFramebuffer + i)); const __m128i color5551 = BGRA8888_32Rev_To_RGBA5551_16Rev(srcColor); _mm_store_si128((__m128i *)(dstFramebuffer + i), srcColor); _mm_storel_epi64((__m128i *)(dstRGBA5551 + i), color5551); } #endif for (; i < pixCount; i++) { dstFramebuffer[i] = srcFramebuffer[i]; #ifdef MSB_FIRST dstRGBA5551[i] = BGRA8888_32_To_RGBA5551_16(srcFramebuffer[i]); #else dstRGBA5551[i] = BGRA8888_32Rev_To_RGBA5551_16Rev(srcFramebuffer[i]); #endif } } else if (dstFramebuffer != NULL) { memcpy(dstFramebuffer, srcFramebuffer, this->_framebufferWidth * this->_framebufferHeight * sizeof(FragmentColor)); } else { #ifdef ENABLE_SSSE3 for (; i < ssePixCount; i += 4) { const __m128i srcColor = _mm_load_si128((__m128i *)(srcFramebuffer + i)); const __m128i color5551 = BGRA8888_32Rev_To_RGBA5551_16Rev(srcColor); _mm_storel_epi64((__m128i *)(dstRGBA5551 + i), color5551); } #endif for (; i < pixCount; i++) { #ifdef MSB_FIRST dstRGBA5551[i] = BGRA8888_32_To_RGBA5551_16(srcFramebuffer[i]); #else dstRGBA5551[i] = BGRA8888_32Rev_To_RGBA5551_16Rev(srcFramebuffer[i]); #endif } } } } else // In the case where OpenGL couldn't flip the framebuffer on the GPU, we'll instead need to flip the framebuffer during conversion. { if (this->_outputFormat == NDSColorFormat_BGR666_Rev) { if ( (dstFramebuffer != NULL) && (dstRGBA5551 != NULL) ) { for (size_t y = 0, ir = 0, iw = ((this->_framebufferHeight - 1) * this->_framebufferWidth); y < this->_framebufferHeight; y++, iw -= (this->_framebufferWidth * 2)) { size_t x = 0; #ifdef ENABLE_SSSE3 for (; x < ssePixCount; x += 4, ir += 4, iw += 4) { const __m128i srcColor = _mm_load_si128((__m128i *)(srcFramebuffer + ir)); const __m128i color6665 = BGRA8888_32Rev_To_RGBA6665_32Rev(srcColor); const __m128i color5551 = BGRA8888_32Rev_To_RGBA5551_16Rev(srcColor); _mm_store_si128((__m128i *)(dstFramebuffer + iw), color6665); _mm_storel_epi64((__m128i *)(dstFramebuffer + iw), color5551); } #endif for (; x < pixCount; x++, ir++, iw++) { #ifdef MSB_FIRST dstFramebuffer[iw] = BGRA8888_32_To_RGBA6665_32(srcFramebuffer[ir]); dstRGBA5551[iw] = BGRA8888_32_To_RGBA5551_16(srcFramebuffer[ir]); #else dstFramebuffer[iw] = BGRA8888_32Rev_To_RGBA6665_32Rev(srcFramebuffer[ir]); dstRGBA5551[iw] = BGRA8888_32Rev_To_RGBA5551_16Rev(srcFramebuffer[ir]); #endif } } } else if (dstFramebuffer != NULL) { for (size_t y = 0, ir = 0, iw = ((this->_framebufferHeight - 1) * this->_framebufferWidth); y < this->_framebufferHeight; y++, iw -= (this->_framebufferWidth * 2)) { size_t x = 0; #ifdef ENABLE_SSSE3 for (; x < ssePixCount; x += 4, ir += 4, iw += 4) { const __m128i srcColor = _mm_load_si128((__m128i *)(srcFramebuffer + ir)); const __m128i color6665 = BGRA8888_32Rev_To_RGBA6665_32Rev(srcColor); _mm_store_si128((__m128i *)(dstFramebuffer + iw), color6665); } #endif for (; x < pixCount; x++, ir++, iw++) { #ifdef MSB_FIRST dstFramebuffer[iw] = BGRA8888_32_To_RGBA6665_32(srcFramebuffer[ir]); #else dstFramebuffer[iw] = BGRA8888_32Rev_To_RGBA6665_32Rev(srcFramebuffer[ir]); #endif } } } else { for (size_t y = 0, ir = 0, iw = ((this->_framebufferHeight - 1) * this->_framebufferWidth); y < this->_framebufferHeight; y++, iw -= (this->_framebufferWidth * 2)) { size_t x = 0; #ifdef ENABLE_SSSE3 for (; x < ssePixCount; x += 4, ir += 4, iw += 4) { const __m128i srcColor = _mm_load_si128((__m128i *)(srcFramebuffer + ir)); const __m128i color5551 = BGRA8888_32Rev_To_RGBA5551_16Rev(srcColor); _mm_storel_epi64((__m128i *)(dstFramebuffer + iw), color5551); } #endif for (; x < pixCount; x++, ir++, iw++) { #ifdef MSB_FIRST dstRGBA5551[iw] = BGRA8888_32_To_RGBA5551_16(srcFramebuffer[ir]); #else dstRGBA5551[iw] = BGRA8888_32Rev_To_RGBA5551_16Rev(srcFramebuffer[ir]); #endif } } } } else if (this->_outputFormat == NDSColorFormat_BGR888_Rev) { if ( (dstFramebuffer != NULL) && (dstRGBA5551 != NULL) ) { for (size_t y = 0, ir = 0, iw = ((this->_framebufferHeight - 1) * this->_framebufferWidth); y < this->_framebufferHeight; y++, iw -= (this->_framebufferWidth * 2)) { size_t x = 0; #ifdef ENABLE_SSSE3 for (; x < ssePixCount; x += 4, ir += 4, iw += 4) { const __m128i srcColor = _mm_load_si128((__m128i *)(srcFramebuffer + ir)); const __m128i color5551 = BGRA8888_32Rev_To_RGBA5551_16Rev(srcColor); _mm_store_si128((__m128i *)(dstFramebuffer + iw), srcColor); _mm_storel_epi64((__m128i *)(dstFramebuffer + iw), color5551); } #endif for (; x < pixCount; x++, ir++, iw++) { dstFramebuffer[iw] = srcFramebuffer[ir]; #ifdef MSB_FIRST dstRGBA5551[iw] = BGRA8888_32_To_RGBA5551_16(srcFramebuffer[ir]); #else dstRGBA5551[iw] = BGRA8888_32Rev_To_RGBA5551_16Rev(srcFramebuffer[ir]); #endif } } } else if (dstFramebuffer != NULL) { const size_t lineBytes = this->_framebufferWidth * sizeof(FragmentColor); const FragmentColor *__restrict srcPtr = srcFramebuffer; FragmentColor *__restrict dstPtr = dstFramebuffer + ((this->_framebufferHeight - 1) * this->_framebufferWidth); for (size_t y = 0; y < this->_framebufferHeight; y++) { memcpy(dstPtr, srcPtr, lineBytes); srcPtr += this->_framebufferWidth; dstPtr -= this->_framebufferWidth; } } else { for (size_t y = 0, ir = 0, iw = ((this->_framebufferHeight - 1) * this->_framebufferWidth); y < this->_framebufferHeight; y++, iw -= (this->_framebufferWidth * 2)) { size_t x = 0; #ifdef ENABLE_SSSE3 for (; x < ssePixCount; x += 4, ir += 4, iw += 4) { const __m128i srcColor = _mm_load_si128((__m128i *)(srcFramebuffer + ir)); const __m128i color5551 = BGRA8888_32Rev_To_RGBA5551_16Rev(srcColor); _mm_storel_epi64((__m128i *)(dstFramebuffer + iw), color5551); } #endif for (; x < pixCount; x++, ir++, iw++) { #ifdef MSB_FIRST dstRGBA5551[iw] = BGRA8888_32_To_RGBA5551_16(srcFramebuffer[ir]); #else dstRGBA5551[iw] = BGRA8888_32Rev_To_RGBA5551_16Rev(srcFramebuffer[ir]); #endif } } } } } return RENDER3DERROR_NOERR; } Render3DError OpenGLRenderer::FlushFramebuffer(const FragmentColor *__restrict srcFramebuffer, FragmentColor *__restrict dstFramebuffer, u16 *__restrict dstRGBA5551) { if (this->willConvertFramebufferOnGPU) { #ifdef ENABLE_SSE2 return Render3D_SSE2::FlushFramebuffer(srcFramebuffer, NULL, dstRGBA5551); #else return Render3D::FlushFramebuffer(srcFramebuffer, NULL, dstRGBA5551); #endif } return this->_FlushFramebufferConvertOnCPU(srcFramebuffer, dstFramebuffer, dstRGBA5551); } FragmentColor* OpenGLRenderer::GetFramebuffer() { return (this->willConvertFramebufferOnGPU) ? this->_mappedFramebuffer : GPU->GetEngineMain()->Get3DFramebufferRGBA6665(); } OpenGLRenderer_1_2::~OpenGLRenderer_1_2() { glFinish(); _pixelReadNeedsFinish = false; delete[] ref->color4fBuffer; ref->color4fBuffer = NULL; delete[] ref->vertIndexBuffer; ref->vertIndexBuffer = NULL; DestroyGeometryProgram(); DestroyPostprocessingPrograms(); DestroyVAOs(); DestroyVBOs(); DestroyPBOs(); DestroyFBOs(); DestroyMultisampledFBO(); // Kill the texture cache now before all of our texture IDs disappear. TexCache_Reset(); while(!ref->freeTextureIDs.empty()) { GLuint temp = ref->freeTextureIDs.front(); ref->freeTextureIDs.pop(); glDeleteTextures(1, &temp); } glFinish(); } Render3DError OpenGLRenderer_1_2::InitExtensions() { Render3DError error = OGLERROR_NOERR; // Get OpenGL extensions std::set oglExtensionSet; this->GetExtensionSet(&oglExtensionSet); // Initialize OpenGL this->InitTables(); this->isShaderSupported = this->IsExtensionPresent(&oglExtensionSet, "GL_ARB_shader_objects") && this->IsExtensionPresent(&oglExtensionSet, "GL_ARB_vertex_shader") && this->IsExtensionPresent(&oglExtensionSet, "GL_ARB_fragment_shader") && this->IsExtensionPresent(&oglExtensionSet, "GL_ARB_vertex_program"); if (this->isShaderSupported) { std::string vertexShaderProgram; std::string fragmentShaderProgram; error = this->LoadGeometryShaders(vertexShaderProgram, fragmentShaderProgram); if (error == OGLERROR_NOERR) { error = this->InitGeometryProgram(vertexShaderProgram, fragmentShaderProgram); if (error == OGLERROR_NOERR) { std::string edgeMarkVtxShaderString = std::string(EdgeMarkVtxShader_100); std::string edgeMarkFragShaderString = std::string(EdgeMarkFragShader_100); std::string fogVtxShaderString = std::string(FogVtxShader_100); std::string fogFragShaderString = std::string(FogFragShader_100); std::string framebufferOutputVtxShaderString = std::string(FramebufferOutputVtxShader_100); std::string framebufferOutputRGBA6665FragShaderString = std::string(FramebufferOutputRGBA6665FragShader_100); std::string framebufferOutputRGBA8888FragShaderString = std::string(FramebufferOutputRGBA8888FragShader_100); error = this->InitPostprocessingPrograms(edgeMarkVtxShaderString, edgeMarkFragShaderString, fogVtxShaderString, fogFragShaderString, framebufferOutputVtxShaderString, framebufferOutputRGBA6665FragShaderString, framebufferOutputRGBA8888FragShaderString); if (error != OGLERROR_NOERR) { INFO("OpenGL: Edge mark and fog require OpenGL v2.0 or later. These features will be disabled.\n"); } } else { this->isShaderSupported = false; } } else { this->isShaderSupported = false; } } else { INFO("OpenGL: Shaders are unsupported. Disabling shaders and using fixed-function pipeline. Some emulation features will be disabled.\n"); } this->isVBOSupported = this->IsExtensionPresent(&oglExtensionSet, "GL_ARB_vertex_buffer_object"); if (this->isVBOSupported) { this->CreateVBOs(); } this->isPBOSupported = this->isVBOSupported && (this->IsExtensionPresent(&oglExtensionSet, "GL_ARB_pixel_buffer_object") || this->IsExtensionPresent(&oglExtensionSet, "GL_EXT_pixel_buffer_object")); if (this->isPBOSupported) { this->CreatePBOs(); } this->isVAOSupported = this->isShaderSupported && this->isVBOSupported && (this->IsExtensionPresent(&oglExtensionSet, "GL_ARB_vertex_array_object") || this->IsExtensionPresent(&oglExtensionSet, "GL_APPLE_vertex_array_object")); if (this->isVAOSupported) { this->CreateVAOs(); } // Don't use ARB versions since we're using the EXT versions for backwards compatibility. this->isFBOSupported = this->IsExtensionPresent(&oglExtensionSet, "GL_EXT_framebuffer_object") && this->IsExtensionPresent(&oglExtensionSet, "GL_EXT_framebuffer_blit") && this->IsExtensionPresent(&oglExtensionSet, "GL_EXT_packed_depth_stencil"); if (this->isFBOSupported) { this->willFlipFramebufferOnGPU = true; this->willConvertFramebufferOnGPU = (this->isShaderSupported && this->isVAOSupported && this->isPBOSupported && this->isFBOSupported); error = this->CreateFBOs(); if (error != OGLERROR_NOERR) { this->isFBOSupported = false; } } else { INFO("OpenGL: FBOs are unsupported. Some emulation features will be disabled.\n"); } // Set these again after FBO creation just in case FBO creation fails. this->willFlipFramebufferOnGPU = this->isFBOSupported; this->willConvertFramebufferOnGPU = (this->isShaderSupported && this->isVAOSupported && this->isPBOSupported && this->isFBOSupported); // Don't use ARB versions since we're using the EXT versions for backwards compatibility. this->isMultisampledFBOSupported = this->isFBOSupported && this->IsExtensionPresent(&oglExtensionSet, "GL_EXT_framebuffer_multisample"); if (this->isMultisampledFBOSupported) { error = this->CreateMultisampledFBO(); if (error != OGLERROR_NOERR) { this->isMultisampledFBOSupported = false; } } else { INFO("OpenGL: Multisampled FBOs are unsupported. Multisample antialiasing will be disabled.\n"); } this->InitTextures(); this->InitFinalRenderStates(&oglExtensionSet); // This must be done last return OGLERROR_NOERR; } Render3DError OpenGLRenderer_1_2::CreateVBOs() { OGLRenderRef &OGLRef = *this->ref; glGenBuffersARB(1, &OGLRef.vboGeometryVtxID); glGenBuffersARB(1, &OGLRef.iboGeometryIndexID); glGenBuffersARB(1, &OGLRef.vboPostprocessVtxID); glGenBuffersARB(1, &OGLRef.iboPostprocessIndexID); glBindBufferARB(GL_ARRAY_BUFFER_ARB, OGLRef.vboGeometryVtxID); glBufferDataARB(GL_ARRAY_BUFFER_ARB, VERTLIST_SIZE * sizeof(VERT), NULL, GL_STREAM_DRAW_ARB); glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, OGLRef.iboGeometryIndexID); glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, OGLRENDER_VERT_INDEX_BUFFER_COUNT * sizeof(GLushort), NULL, GL_STREAM_DRAW_ARB); glBindBufferARB(GL_ARRAY_BUFFER_ARB, OGLRef.vboPostprocessVtxID); glBufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(PostprocessVtxBuffer), PostprocessVtxBuffer, GL_STATIC_DRAW_ARB); glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, OGLRef.iboPostprocessIndexID); glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, sizeof(PostprocessElementBuffer), PostprocessElementBuffer, GL_STATIC_DRAW_ARB); glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0); return OGLERROR_NOERR; } void OpenGLRenderer_1_2::DestroyVBOs() { if (!this->isVBOSupported) return; OGLRenderRef &OGLRef = *this->ref; glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0); glDeleteBuffersARB(1, &OGLRef.vboGeometryVtxID); glDeleteBuffersARB(1, &OGLRef.iboGeometryIndexID); glDeleteBuffersARB(1, &OGLRef.vboPostprocessVtxID); glDeleteBuffersARB(1, &OGLRef.iboPostprocessIndexID); this->isVBOSupported = false; } Render3DError OpenGLRenderer_1_2::CreatePBOs() { OGLRenderRef &OGLRef = *this->ref; glGenBuffersARB(1, &OGLRef.pboRenderDataID); glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, OGLRef.pboRenderDataID); glBufferDataARB(GL_PIXEL_PACK_BUFFER_ARB, this->_framebufferColorSizeBytes, NULL, GL_STREAM_READ_ARB); return OGLERROR_NOERR; } void OpenGLRenderer_1_2::DestroyPBOs() { if (!this->isPBOSupported) { return; } glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0); glDeleteBuffersARB(1, &this->ref->pboRenderDataID); this->isPBOSupported = false; } Render3DError OpenGLRenderer_1_2::LoadGeometryShaders(std::string &outVertexShaderProgram, std::string &outFragmentShaderProgram) { outVertexShaderProgram.clear(); outFragmentShaderProgram.clear(); outVertexShaderProgram += std::string(vertexShader_100); outFragmentShaderProgram += std::string(fragmentShader_100); return OGLERROR_NOERR; } Render3DError OpenGLRenderer_1_2::InitGeometryProgramBindings() { OGLRenderRef &OGLRef = *this->ref; glBindAttribLocation(OGLRef.programGeometryID, OGLVertexAttributeID_Position, "inPosition"); glBindAttribLocation(OGLRef.programGeometryID, OGLVertexAttributeID_TexCoord0, "inTexCoord0"); glBindAttribLocation(OGLRef.programGeometryID, OGLVertexAttributeID_Color, "inColor"); return OGLERROR_NOERR; } Render3DError OpenGLRenderer_1_2::InitGeometryProgramShaderLocations() { OGLRenderRef &OGLRef = *this->ref; glUseProgram(OGLRef.programGeometryID); const GLint uniformTexRenderObject = glGetUniformLocation(OGLRef.programGeometryID, "texRenderObject"); const GLint uniformTexToonTable = glGetUniformLocation(OGLRef.programGeometryID, "texToonTable"); glUniform1i(uniformTexRenderObject, 0); glUniform1i(uniformTexToonTable, OGLTextureUnitID_ToonTable); OGLRef.uniformStateToonShadingMode = glGetUniformLocation(OGLRef.programGeometryID, "stateToonShadingMode"); OGLRef.uniformStateEnableAlphaTest = glGetUniformLocation(OGLRef.programGeometryID, "stateEnableAlphaTest"); OGLRef.uniformStateEnableAntialiasing = glGetUniformLocation(OGLRef.programGeometryID, "stateEnableAntialiasing"); OGLRef.uniformStateEnableEdgeMarking = glGetUniformLocation(OGLRef.programGeometryID, "stateEnableEdgeMarking"); OGLRef.uniformStateUseWDepth = glGetUniformLocation(OGLRef.programGeometryID, "stateUseWDepth"); OGLRef.uniformStateAlphaTestRef = glGetUniformLocation(OGLRef.programGeometryID, "stateAlphaTestRef"); OGLRef.uniformPolyTexScale = glGetUniformLocation(OGLRef.programGeometryID, "polyTexScale"); OGLRef.uniformPolyMode = glGetUniformLocation(OGLRef.programGeometryID, "polyMode"); OGLRef.uniformPolyEnableDepthWrite = glGetUniformLocation(OGLRef.programGeometryID, "polyEnableDepthWrite"); OGLRef.uniformPolySetNewDepthForTranslucent = glGetUniformLocation(OGLRef.programGeometryID, "polySetNewDepthForTranslucent"); OGLRef.uniformPolyAlpha = glGetUniformLocation(OGLRef.programGeometryID, "polyAlpha"); OGLRef.uniformPolyID = glGetUniformLocation(OGLRef.programGeometryID, "polyID"); OGLRef.uniformPolyEnableTexture = glGetUniformLocation(OGLRef.programGeometryID, "polyEnableTexture"); OGLRef.uniformPolyEnableFog = glGetUniformLocation(OGLRef.programGeometryID, "polyEnableFog"); return OGLERROR_NOERR; } Render3DError OpenGLRenderer_1_2::InitGeometryProgram(const std::string &vertexShaderProgram, const std::string &fragmentShaderProgram) { OGLRenderRef &OGLRef = *this->ref; OGLRef.vertexGeometryShaderID = glCreateShader(GL_VERTEX_SHADER); if(!OGLRef.vertexGeometryShaderID) { INFO("OpenGL: Failed to create the vertex shader. Disabling shaders and using fixed-function pipeline. Some emulation features will be disabled.\n"); return OGLERROR_SHADER_CREATE_ERROR; } const char *vertexShaderProgramChar = vertexShaderProgram.c_str(); glShaderSource(OGLRef.vertexGeometryShaderID, 1, (const GLchar **)&vertexShaderProgramChar, NULL); glCompileShader(OGLRef.vertexGeometryShaderID); if (!this->ValidateShaderCompile(OGLRef.vertexGeometryShaderID)) { glDeleteShader(OGLRef.vertexGeometryShaderID); INFO("OpenGL: Failed to compile the vertex shader. Disabling shaders and using fixed-function pipeline. Some emulation features will be disabled.\n"); return OGLERROR_SHADER_CREATE_ERROR; } OGLRef.fragmentGeometryShaderID = glCreateShader(GL_FRAGMENT_SHADER); if(!OGLRef.fragmentGeometryShaderID) { glDeleteShader(OGLRef.vertexGeometryShaderID); INFO("OpenGL: Failed to create the fragment shader. Disabling shaders and using fixed-function pipeline. Some emulation features will be disabled.\n"); return OGLERROR_SHADER_CREATE_ERROR; } const char *fragmentShaderProgramChar = fragmentShaderProgram.c_str(); glShaderSource(OGLRef.fragmentGeometryShaderID, 1, (const GLchar **)&fragmentShaderProgramChar, NULL); glCompileShader(OGLRef.fragmentGeometryShaderID); if (!this->ValidateShaderCompile(OGLRef.fragmentGeometryShaderID)) { glDeleteShader(OGLRef.vertexGeometryShaderID); glDeleteShader(OGLRef.fragmentGeometryShaderID); INFO("OpenGL: Failed to compile the fragment shader. Disabling shaders and using fixed-function pipeline. Some emulation features will be disabled.\n"); return OGLERROR_SHADER_CREATE_ERROR; } OGLRef.programGeometryID = glCreateProgram(); if(!OGLRef.programGeometryID) { glDeleteShader(OGLRef.vertexGeometryShaderID); glDeleteShader(OGLRef.fragmentGeometryShaderID); INFO("OpenGL: Failed to create the shader program. Disabling shaders and using fixed-function pipeline. Some emulation features will be disabled.\n"); return OGLERROR_SHADER_CREATE_ERROR; } glAttachShader(OGLRef.programGeometryID, OGLRef.vertexGeometryShaderID); glAttachShader(OGLRef.programGeometryID, OGLRef.fragmentGeometryShaderID); this->InitGeometryProgramBindings(); glLinkProgram(OGLRef.programGeometryID); if (!this->ValidateShaderProgramLink(OGLRef.programGeometryID)) { glDetachShader(OGLRef.programGeometryID, OGLRef.vertexGeometryShaderID); glDetachShader(OGLRef.programGeometryID, OGLRef.fragmentGeometryShaderID); glDeleteProgram(OGLRef.programGeometryID); glDeleteShader(OGLRef.vertexGeometryShaderID); glDeleteShader(OGLRef.fragmentGeometryShaderID); INFO("OpenGL: Failed to link the shader program. Disabling shaders and using fixed-function pipeline. Some emulation features will be disabled.\n"); return OGLERROR_SHADER_CREATE_ERROR; } glValidateProgram(OGLRef.programGeometryID); this->InitGeometryProgramShaderLocations(); INFO("OpenGL: Successfully created shaders.\n"); this->CreateToonTable(); return OGLERROR_NOERR; } void OpenGLRenderer_1_2::DestroyGeometryProgram() { if(!this->isShaderSupported) { return; } OGLRenderRef &OGLRef = *this->ref; glUseProgram(0); glDetachShader(OGLRef.programGeometryID, OGLRef.vertexGeometryShaderID); glDetachShader(OGLRef.programGeometryID, OGLRef.fragmentGeometryShaderID); glDeleteProgram(OGLRef.programGeometryID); glDeleteShader(OGLRef.vertexGeometryShaderID); glDeleteShader(OGLRef.fragmentGeometryShaderID); this->DestroyToonTable(); this->isShaderSupported = false; } Render3DError OpenGLRenderer_1_2::CreateVAOs() { OGLRenderRef &OGLRef = *this->ref; glGenVertexArrays(1, &OGLRef.vaoGeometryStatesID); glGenVertexArrays(1, &OGLRef.vaoPostprocessStatesID); glBindVertexArray(OGLRef.vaoGeometryStatesID); glBindBufferARB(GL_ARRAY_BUFFER_ARB, OGLRef.vboGeometryVtxID); glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, OGLRef.iboGeometryIndexID); glEnableVertexAttribArray(OGLVertexAttributeID_Position); glEnableVertexAttribArray(OGLVertexAttributeID_TexCoord0); glEnableVertexAttribArray(OGLVertexAttributeID_Color); glVertexAttribPointer(OGLVertexAttributeID_Position, 4, GL_FLOAT, GL_FALSE, sizeof(VERT), (const GLvoid *)offsetof(VERT, coord)); glVertexAttribPointer(OGLVertexAttributeID_TexCoord0, 2, GL_FLOAT, GL_FALSE, sizeof(VERT), (const GLvoid *)offsetof(VERT, texcoord)); glVertexAttribPointer(OGLVertexAttributeID_Color, 3, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(VERT), (const GLvoid *)offsetof(VERT, color)); glBindVertexArray(0); glBindVertexArray(OGLRef.vaoPostprocessStatesID); glBindBufferARB(GL_ARRAY_BUFFER_ARB, OGLRef.vboPostprocessVtxID); glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, OGLRef.iboPostprocessIndexID); glEnableVertexAttribArray(OGLVertexAttributeID_Position); glEnableVertexAttribArray(OGLVertexAttributeID_TexCoord0); glVertexAttribPointer(OGLVertexAttributeID_Position, 2, GL_FLOAT, GL_FALSE, 0, 0); glVertexAttribPointer(OGLVertexAttributeID_TexCoord0, 2, GL_FLOAT, GL_FALSE, 0, (const GLvoid *)(sizeof(GLfloat) * 8)); glBindVertexArray(0); return OGLERROR_NOERR; } void OpenGLRenderer_1_2::DestroyVAOs() { OGLRenderRef &OGLRef = *this->ref; if (!this->isVAOSupported) { return; } glBindVertexArray(0); glDeleteVertexArrays(1, &OGLRef.vaoGeometryStatesID); glDeleteVertexArrays(1, &OGLRef.vaoPostprocessStatesID); this->isVAOSupported = false; } Render3DError OpenGLRenderer_1_2::CreateFBOs() { OGLRenderRef &OGLRef = *this->ref; // Set up FBO render targets glGenTextures(1, &OGLRef.texCIColorID); glGenTextures(1, &OGLRef.texCIDepthID); glGenTextures(1, &OGLRef.texCIFogAttrID); glGenTextures(1, &OGLRef.texCIPolyID); glGenTextures(1, &OGLRef.texCIDepthStencilID); glGenTextures(1, &OGLRef.texFinalColorID); glGenTextures(1, &OGLRef.texGColorID); glGenTextures(1, &OGLRef.texGDepthID); glGenTextures(1, &OGLRef.texGFogAttrID); glGenTextures(1, &OGLRef.texGPolyID); glGenTextures(1, &OGLRef.texGDepthStencilID); glGenTextures(1, &OGLRef.texPostprocessFogID); if (this->willFlipFramebufferOnGPU) { glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_FinalColor); glBindTexture(GL_TEXTURE_2D, OGLRef.texFinalColorID); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, this->_framebufferWidth, this->_framebufferHeight, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL); } glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_GColor); glBindTexture(GL_TEXTURE_2D, OGLRef.texGDepthStencilID); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE); glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8_EXT, this->_framebufferWidth, this->_framebufferHeight, 0, GL_DEPTH_STENCIL_EXT, GL_UNSIGNED_INT_24_8_EXT, NULL); glBindTexture(GL_TEXTURE_2D, OGLRef.texGColorID); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, this->_framebufferWidth, this->_framebufferHeight, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL); glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_GDepth); glBindTexture(GL_TEXTURE_2D, OGLRef.texGDepthID); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, this->_framebufferWidth, this->_framebufferHeight, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL); glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_GPolyID); glBindTexture(GL_TEXTURE_2D, OGLRef.texGPolyID); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, this->_framebufferWidth, this->_framebufferHeight, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL); glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_FogAttr); glBindTexture(GL_TEXTURE_2D, OGLRef.texGFogAttrID); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, this->_framebufferWidth, this->_framebufferHeight, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, OGLRef.texPostprocessFogID); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, this->_framebufferWidth, this->_framebufferHeight, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL); glBindTexture(GL_TEXTURE_2D, OGLRef.texCIColorID); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, GPU_FRAMEBUFFER_NATIVE_WIDTH, GPU_FRAMEBUFFER_NATIVE_HEIGHT, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL); glBindTexture(GL_TEXTURE_2D, OGLRef.texCIDepthStencilID); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE); glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8_EXT, GPU_FRAMEBUFFER_NATIVE_WIDTH, GPU_FRAMEBUFFER_NATIVE_HEIGHT, 0, GL_DEPTH_STENCIL_EXT, GL_UNSIGNED_INT_24_8_EXT, NULL); glBindTexture(GL_TEXTURE_2D, OGLRef.texCIDepthID); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, GPU_FRAMEBUFFER_NATIVE_WIDTH, GPU_FRAMEBUFFER_NATIVE_HEIGHT, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL); glBindTexture(GL_TEXTURE_2D, OGLRef.texCIPolyID); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, GPU_FRAMEBUFFER_NATIVE_WIDTH, GPU_FRAMEBUFFER_NATIVE_HEIGHT, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL); glBindTexture(GL_TEXTURE_2D, OGLRef.texCIFogAttrID); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, GPU_FRAMEBUFFER_NATIVE_WIDTH, GPU_FRAMEBUFFER_NATIVE_HEIGHT, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL); glBindTexture(GL_TEXTURE_2D, 0); // Set up RBOs if (this->willConvertFramebufferOnGPU) { glGenRenderbuffersEXT(1, &OGLRef.rboFramebufferRGBA6665ID); glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, OGLRef.rboFramebufferRGBA6665ID); glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGBA, this->_framebufferWidth, this->_framebufferHeight); } // Set up FBOs glGenFramebuffersEXT(1, &OGLRef.fboClearImageID); glGenFramebuffersEXT(1, &OGLRef.fboRenderID); glGenFramebuffersEXT(1, &OGLRef.fboPostprocessID); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.fboClearImageID); glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, OGLRef.texCIColorID, 0); glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_TEXTURE_2D, OGLRef.texCIDepthID, 0); glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT2_EXT, GL_TEXTURE_2D, OGLRef.texCIPolyID, 0); glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT3_EXT, GL_TEXTURE_2D, OGLRef.texCIFogAttrID, 0); glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, OGLRef.texCIDepthStencilID, 0); glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_TEXTURE_2D, OGLRef.texCIDepthStencilID, 0); if (glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) != GL_FRAMEBUFFER_COMPLETE_EXT) { INFO("OpenGL: Failed to created FBOs. Some emulation features will be disabled.\n"); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); glDeleteFramebuffersEXT(1, &OGLRef.fboClearImageID); glDeleteFramebuffersEXT(1, &OGLRef.fboRenderID); glDeleteFramebuffersEXT(1, &OGLRef.fboPostprocessID); glDeleteTextures(1, &OGLRef.texCIColorID); glDeleteTextures(1, &OGLRef.texCIDepthID); glDeleteTextures(1, &OGLRef.texCIFogAttrID); glDeleteTextures(1, &OGLRef.texCIPolyID); glDeleteTextures(1, &OGLRef.texCIDepthStencilID); glDeleteTextures(1, &OGLRef.texGColorID); glDeleteTextures(1, &OGLRef.texGDepthID); glDeleteTextures(1, &OGLRef.texGPolyID); glDeleteTextures(1, &OGLRef.texGFogAttrID); glDeleteTextures(1, &OGLRef.texGDepthStencilID); glDeleteTextures(1, &OGLRef.texPostprocessFogID); glDeleteTextures(1, &OGLRef.texFinalColorID); glDeleteRenderbuffersEXT(1, &OGLRef.rboFramebufferRGBA6665ID); OGLRef.fboClearImageID = 0; OGLRef.fboRenderID = 0; OGLRef.fboPostprocessID = 0; this->isFBOSupported = false; return OGLERROR_FBO_CREATE_ERROR; } glDrawBuffers(4, RenderDrawList); glReadBuffer(GL_COLOR_ATTACHMENT0_EXT); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.fboRenderID); glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, OGLRef.texGColorID, 0); glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_TEXTURE_2D, OGLRef.texGDepthID, 0); glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT2_EXT, GL_TEXTURE_2D, OGLRef.texGPolyID, 0); glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT3_EXT, GL_TEXTURE_2D, OGLRef.texGFogAttrID, 0); glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, OGLRef.texGDepthStencilID, 0); glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_TEXTURE_2D, OGLRef.texGDepthStencilID, 0); if (glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) != GL_FRAMEBUFFER_COMPLETE_EXT) { INFO("OpenGL: Failed to created FBOs. Some emulation features will be disabled.\n"); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); glDeleteFramebuffersEXT(1, &OGLRef.fboClearImageID); glDeleteFramebuffersEXT(1, &OGLRef.fboRenderID); glDeleteFramebuffersEXT(1, &OGLRef.fboPostprocessID); glDeleteTextures(1, &OGLRef.texCIColorID); glDeleteTextures(1, &OGLRef.texCIDepthID); glDeleteTextures(1, &OGLRef.texCIFogAttrID); glDeleteTextures(1, &OGLRef.texCIPolyID); glDeleteTextures(1, &OGLRef.texCIDepthStencilID); glDeleteTextures(1, &OGLRef.texGColorID); glDeleteTextures(1, &OGLRef.texGDepthID); glDeleteTextures(1, &OGLRef.texGPolyID); glDeleteTextures(1, &OGLRef.texGFogAttrID); glDeleteTextures(1, &OGLRef.texGDepthStencilID); glDeleteTextures(1, &OGLRef.texPostprocessFogID); glDeleteTextures(1, &OGLRef.texFinalColorID); glDeleteRenderbuffersEXT(1, &OGLRef.rboFramebufferRGBA6665ID); OGLRef.fboClearImageID = 0; OGLRef.fboRenderID = 0; OGLRef.fboPostprocessID = 0; this->isFBOSupported = false; return OGLERROR_FBO_CREATE_ERROR; } glDrawBuffers(4, RenderDrawList); glReadBuffer(GL_COLOR_ATTACHMENT0_EXT); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.fboPostprocessID); glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, OGLRef.texPostprocessFogID, 0); if (this->willFlipFramebufferOnGPU) { glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_TEXTURE_2D, OGLRef.texFinalColorID, 0); } if (this->willConvertFramebufferOnGPU) { glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT2_EXT, GL_RENDERBUFFER_EXT, OGLRef.rboFramebufferRGBA6665ID); } if (glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) != GL_FRAMEBUFFER_COMPLETE_EXT) { INFO("OpenGL: Failed to created FBOs. Some emulation features will be disabled.\n"); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); glDeleteFramebuffersEXT(1, &OGLRef.fboClearImageID); glDeleteFramebuffersEXT(1, &OGLRef.fboRenderID); glDeleteFramebuffersEXT(1, &OGLRef.fboPostprocessID); glDeleteTextures(1, &OGLRef.texCIColorID); glDeleteTextures(1, &OGLRef.texCIDepthID); glDeleteTextures(1, &OGLRef.texCIFogAttrID); glDeleteTextures(1, &OGLRef.texCIPolyID); glDeleteTextures(1, &OGLRef.texCIDepthStencilID); glDeleteTextures(1, &OGLRef.texGColorID); glDeleteTextures(1, &OGLRef.texGDepthID); glDeleteTextures(1, &OGLRef.texGPolyID); glDeleteTextures(1, &OGLRef.texGFogAttrID); glDeleteTextures(1, &OGLRef.texGDepthStencilID); glDeleteTextures(1, &OGLRef.texPostprocessFogID); glDeleteTextures(1, &OGLRef.texFinalColorID); glDeleteRenderbuffersEXT(1, &OGLRef.rboFramebufferRGBA6665ID); OGLRef.fboClearImageID = 0; OGLRef.fboRenderID = 0; OGLRef.fboPostprocessID = 0; this->isFBOSupported = false; return OGLERROR_FBO_CREATE_ERROR; } glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); glReadBuffer(GL_COLOR_ATTACHMENT0_EXT); OGLRef.selectedRenderingFBO = OGLRef.fboRenderID; glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.selectedRenderingFBO); INFO("OpenGL: Successfully created FBOs.\n"); return OGLERROR_NOERR; } void OpenGLRenderer_1_2::DestroyFBOs() { if (!this->isFBOSupported) { return; } OGLRenderRef &OGLRef = *this->ref; glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); glDeleteFramebuffersEXT(1, &OGLRef.fboClearImageID); glDeleteFramebuffersEXT(1, &OGLRef.fboRenderID); glDeleteFramebuffersEXT(1, &OGLRef.fboPostprocessID); glDeleteTextures(1, &OGLRef.texCIColorID); glDeleteTextures(1, &OGLRef.texCIDepthID); glDeleteTextures(1, &OGLRef.texCIFogAttrID); glDeleteTextures(1, &OGLRef.texCIPolyID); glDeleteTextures(1, &OGLRef.texCIDepthStencilID); glDeleteTextures(1, &OGLRef.texGColorID); glDeleteTextures(1, &OGLRef.texGDepthID); glDeleteTextures(1, &OGLRef.texGPolyID); glDeleteTextures(1, &OGLRef.texGFogAttrID); glDeleteTextures(1, &OGLRef.texGDepthStencilID); glDeleteTextures(1, &OGLRef.texPostprocessFogID); glDeleteTextures(1, &OGLRef.texFinalColorID); glDeleteRenderbuffersEXT(1, &OGLRef.rboFramebufferRGBA6665ID); OGLRef.fboClearImageID = 0; OGLRef.fboRenderID = 0; OGLRef.fboPostprocessID = 0; this->isFBOSupported = false; } Render3DError OpenGLRenderer_1_2::CreateMultisampledFBO() { // Check the maximum number of samples that the driver supports and use that. // Since our target resolution is only 256x192 pixels, using the most samples // possible is the best thing to do. GLint maxSamples = 0; glGetIntegerv(GL_MAX_SAMPLES_EXT, &maxSamples); if (maxSamples < 2) { INFO("OpenGL: Driver does not support at least 2x multisampled FBOs. Multisample antialiasing will be disabled.\n"); return OGLERROR_FEATURE_UNSUPPORTED; } else if (maxSamples > OGLRENDER_MAX_MULTISAMPLES) { maxSamples = OGLRENDER_MAX_MULTISAMPLES; } OGLRenderRef &OGLRef = *this->ref; // Set up FBO render targets glGenRenderbuffersEXT(1, &OGLRef.rboMSGColorID); glGenRenderbuffersEXT(1, &OGLRef.rboMSGDepthID); glGenRenderbuffersEXT(1, &OGLRef.rboMSGPolyID); glGenRenderbuffersEXT(1, &OGLRef.rboMSGFogAttrID); glGenRenderbuffersEXT(1, &OGLRef.rboMSGDepthStencilID); glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, OGLRef.rboMSGColorID); glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, maxSamples, GL_RGBA, this->_framebufferWidth, this->_framebufferHeight); glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, OGLRef.rboMSGDepthID); glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, maxSamples, GL_RGBA, this->_framebufferWidth, this->_framebufferHeight); glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, OGLRef.rboMSGPolyID); glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, maxSamples, GL_RGBA, this->_framebufferWidth, this->_framebufferHeight); glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, OGLRef.rboMSGFogAttrID); glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, maxSamples, GL_RGBA, this->_framebufferWidth, this->_framebufferHeight); glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, OGLRef.rboMSGDepthStencilID); glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, maxSamples, GL_DEPTH24_STENCIL8_EXT, this->_framebufferWidth, this->_framebufferHeight); // Set up multisampled rendering FBO glGenFramebuffersEXT(1, &OGLRef.fboMSIntermediateRenderID); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.fboMSIntermediateRenderID); glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, OGLRef.rboMSGColorID); glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_RENDERBUFFER_EXT, OGLRef.rboMSGDepthID); glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT2_EXT, GL_RENDERBUFFER_EXT, OGLRef.rboMSGPolyID); glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT3_EXT, GL_RENDERBUFFER_EXT, OGLRef.rboMSGFogAttrID); glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, OGLRef.rboMSGDepthStencilID); glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, OGLRef.rboMSGDepthStencilID); if (glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) != GL_FRAMEBUFFER_COMPLETE_EXT) { INFO("OpenGL: Failed to create multisampled FBO. Multisample antialiasing will be disabled.\n"); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); glDeleteFramebuffersEXT(1, &OGLRef.fboMSIntermediateRenderID); glDeleteRenderbuffersEXT(1, &OGLRef.rboMSGColorID); glDeleteRenderbuffersEXT(1, &OGLRef.rboMSGDepthID); glDeleteRenderbuffersEXT(1, &OGLRef.rboMSGPolyID); glDeleteRenderbuffersEXT(1, &OGLRef.rboMSGFogAttrID); glDeleteRenderbuffersEXT(1, &OGLRef.rboMSGDepthStencilID); return OGLERROR_FBO_CREATE_ERROR; } glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.fboRenderID); INFO("OpenGL: Successfully created multisampled FBO.\n"); return OGLERROR_NOERR; } void OpenGLRenderer_1_2::DestroyMultisampledFBO() { if (!this->isMultisampledFBOSupported) { return; } OGLRenderRef &OGLRef = *this->ref; glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); glDeleteFramebuffersEXT(1, &OGLRef.fboMSIntermediateRenderID); glDeleteRenderbuffersEXT(1, &OGLRef.rboMSGColorID); glDeleteRenderbuffersEXT(1, &OGLRef.rboMSGDepthID); glDeleteRenderbuffersEXT(1, &OGLRef.rboMSGPolyID); glDeleteRenderbuffersEXT(1, &OGLRef.rboMSGFogAttrID); glDeleteRenderbuffersEXT(1, &OGLRef.rboMSGDepthStencilID); this->isMultisampledFBOSupported = false; } Render3DError OpenGLRenderer_1_2::InitFinalRenderStates(const std::set *oglExtensionSet) { OGLRenderRef &OGLRef = *this->ref; bool isTexMirroredRepeatSupported = this->IsExtensionPresent(oglExtensionSet, "GL_ARB_texture_mirrored_repeat"); bool isBlendFuncSeparateSupported = this->IsExtensionPresent(oglExtensionSet, "GL_EXT_blend_func_separate"); bool isBlendEquationSeparateSupported = this->IsExtensionPresent(oglExtensionSet, "GL_EXT_blend_equation_separate"); // Blending Support if (isBlendFuncSeparateSupported) { if (isBlendEquationSeparateSupported) { // we want to use alpha destination blending so we can track the last-rendered alpha value // test: new super mario brothers renders the stormclouds at the beginning glBlendFuncSeparateEXT(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA, GL_DST_ALPHA); glBlendEquationSeparateEXT(GL_FUNC_ADD, GL_MAX); } else { glBlendFuncSeparateEXT(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_DST_ALPHA); } } else { glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } // Mirrored Repeat Mode Support OGLRef.stateTexMirroredRepeat = isTexMirroredRepeatSupported ? GL_MIRRORED_REPEAT : GL_REPEAT; // Map the vertex list's colors with 4 floats per color. This is being done // because OpenGL needs 4-colors per vertex to support translucency. (The DS // uses 3-colors per vertex, and adds alpha through the poly, so we can't // simply reference the colors+alpha from just the vertices by themselves.) OGLRef.color4fBuffer = (this->isShaderSupported) ? NULL : new GLfloat[VERTLIST_SIZE * 4]; // If VBOs aren't supported, then we need to create the index buffer on the // client side so that we have a buffer to update. OGLRef.vertIndexBuffer = (this->isVBOSupported) ? NULL : new GLushort[OGLRENDER_VERT_INDEX_BUFFER_COUNT]; return OGLERROR_NOERR; } Render3DError OpenGLRenderer_1_2::InitTextures() { this->ExpandFreeTextures(); return OGLERROR_NOERR; } Render3DError OpenGLRenderer_1_2::InitTables() { static bool needTableInit = true; if (needTableInit) { for (size_t i = 0; i < 256; i++) material_8bit_to_float[i] = (GLfloat)(i * 4) / 255.0f; needTableInit = false; } return OGLERROR_NOERR; } Render3DError OpenGLRenderer_1_2::InitPostprocessingPrograms(const std::string &edgeMarkVtxShader, const std::string &edgeMarkFragShader, const std::string &fogVtxShader, const std::string &fogFragShader, const std::string &framebufferOutputVtxShader, const std::string &framebufferOutputRGBA6665FragShader, const std::string &framebufferOutputRGBA8888FragShader) { return OGLERROR_FEATURE_UNSUPPORTED; } Render3DError OpenGLRenderer_1_2::DestroyPostprocessingPrograms() { return OGLERROR_FEATURE_UNSUPPORTED; } Render3DError OpenGLRenderer_1_2::InitEdgeMarkProgramBindings() { return OGLERROR_FEATURE_UNSUPPORTED; } Render3DError OpenGLRenderer_1_2::InitEdgeMarkProgramShaderLocations() { return OGLERROR_FEATURE_UNSUPPORTED; } Render3DError OpenGLRenderer_1_2::InitFogProgramBindings() { return OGLERROR_FEATURE_UNSUPPORTED; } Render3DError OpenGLRenderer_1_2::InitFogProgramShaderLocations() { return OGLERROR_FEATURE_UNSUPPORTED; } Render3DError OpenGLRenderer_1_2::InitFramebufferOutputProgramBindings() { return OGLERROR_FEATURE_UNSUPPORTED; } Render3DError OpenGLRenderer_1_2::InitFramebufferOutputShaderLocations() { return OGLERROR_FEATURE_UNSUPPORTED; } Render3DError OpenGLRenderer_1_2::CreateToonTable() { OGLRenderRef &OGLRef = *this->ref; u16 tempToonTable[32]; memset(tempToonTable, 0, sizeof(tempToonTable)); // The toon table is a special 1D texture where each pixel corresponds // to a specific color in the toon table. glGenTextures(1, &OGLRef.texToonTableID); glActiveTextureARB(GL_TEXTURE0_ARB + OGLTextureUnitID_ToonTable); glBindTexture(GL_TEXTURE_1D, OGLRef.texToonTableID); glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexImage1D(GL_TEXTURE_1D, 0, GL_RGB, 32, 0, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, tempToonTable); glActiveTextureARB(GL_TEXTURE0_ARB); return OGLERROR_NOERR; } Render3DError OpenGLRenderer_1_2::DestroyToonTable() { glDeleteTextures(1, &this->ref->texToonTableID); return OGLERROR_NOERR; } Render3DError OpenGLRenderer_1_2::UploadClearImage(const u16 *__restrict colorBuffer, const u32 *__restrict depthBuffer, const u8 *__restrict fogBuffer, const u8 *__restrict polyIDBuffer) { OGLRenderRef &OGLRef = *this->ref; if (this->isShaderSupported) { for (size_t i = 0; i < GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT; i++) { OGLRef.workingCIDepthStencilBuffer[i] = (depthBuffer[i] << 8) | polyIDBuffer[i]; OGLRef.workingCIDepthBuffer[i] = depthBuffer[i] | 0xFF000000; OGLRef.workingCIFogAttributesBuffer[i] = (fogBuffer[i]) ? 0xFF0000FF : 0xFF000000; OGLRef.workingCIPolyIDBuffer[i] = (GLuint)polyIDBuffer[i] | 0xFF000000; } } else { for (size_t i = 0; i < GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT; i++) { OGLRef.workingCIDepthStencilBuffer[i] = (depthBuffer[i] << 8) | polyIDBuffer[i]; } } glActiveTextureARB(GL_TEXTURE0_ARB); glBindTexture(GL_TEXTURE_2D, OGLRef.texCIColorID); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, GPU_FRAMEBUFFER_NATIVE_WIDTH, GPU_FRAMEBUFFER_NATIVE_HEIGHT, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, colorBuffer); glBindTexture(GL_TEXTURE_2D, OGLRef.texCIDepthStencilID); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, GPU_FRAMEBUFFER_NATIVE_WIDTH, GPU_FRAMEBUFFER_NATIVE_HEIGHT, GL_DEPTH_STENCIL_EXT, GL_UNSIGNED_INT_24_8_EXT, OGLRef.workingCIDepthStencilBuffer); if (this->isShaderSupported) { glBindTexture(GL_TEXTURE_2D, OGLRef.texCIDepthID); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, GPU_FRAMEBUFFER_NATIVE_WIDTH, GPU_FRAMEBUFFER_NATIVE_HEIGHT, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, OGLRef.workingCIDepthBuffer); glBindTexture(GL_TEXTURE_2D, OGLRef.texCIFogAttrID); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, GPU_FRAMEBUFFER_NATIVE_WIDTH, GPU_FRAMEBUFFER_NATIVE_HEIGHT, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, OGLRef.workingCIFogAttributesBuffer); glBindTexture(GL_TEXTURE_2D, OGLRef.texCIPolyID); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, GPU_FRAMEBUFFER_NATIVE_WIDTH, GPU_FRAMEBUFFER_NATIVE_HEIGHT, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, OGLRef.workingCIPolyIDBuffer); } glBindTexture(GL_TEXTURE_2D, 0); return OGLERROR_NOERR; } void OpenGLRenderer_1_2::GetExtensionSet(std::set *oglExtensionSet) { std::string oglExtensionString = std::string((const char *)glGetString(GL_EXTENSIONS)); size_t extStringStartLoc = 0; size_t delimiterLoc = oglExtensionString.find_first_of(' ', extStringStartLoc); while (delimiterLoc != std::string::npos) { std::string extensionName = oglExtensionString.substr(extStringStartLoc, delimiterLoc - extStringStartLoc); oglExtensionSet->insert(extensionName); extStringStartLoc = delimiterLoc + 1; delimiterLoc = oglExtensionString.find_first_of(' ', extStringStartLoc); } if (extStringStartLoc - oglExtensionString.length() > 0) { std::string extensionName = oglExtensionString.substr(extStringStartLoc, oglExtensionString.length() - extStringStartLoc); oglExtensionSet->insert(extensionName); } } Render3DError OpenGLRenderer_1_2::ExpandFreeTextures() { static const GLsizei kInitTextures = 128; GLuint oglTempTextureID[kInitTextures]; glGenTextures(kInitTextures, oglTempTextureID); for(GLsizei i = 0; i < kInitTextures; i++) { this->ref->freeTextureIDs.push(oglTempTextureID[i]); } return OGLERROR_NOERR; } Render3DError OpenGLRenderer_1_2::EnableVertexAttributes() { OGLRenderRef &OGLRef = *this->ref; if (this->isVAOSupported) { glBindVertexArray(OGLRef.vaoGeometryStatesID); } else { if (this->isShaderSupported) { glEnableVertexAttribArray(OGLVertexAttributeID_Position); glEnableVertexAttribArray(OGLVertexAttributeID_TexCoord0); glEnableVertexAttribArray(OGLVertexAttributeID_Color); glVertexAttribPointer(OGLVertexAttributeID_Position, 4, GL_FLOAT, GL_FALSE, sizeof(VERT), OGLRef.vtxPtrPosition); glVertexAttribPointer(OGLVertexAttributeID_TexCoord0, 2, GL_FLOAT, GL_FALSE, sizeof(VERT), OGLRef.vtxPtrTexCoord); glVertexAttribPointer(OGLVertexAttributeID_Color, 3, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(VERT), OGLRef.vtxPtrColor); } else { glEnableClientState(GL_TEXTURE_COORD_ARRAY); glEnableClientState(GL_COLOR_ARRAY); glEnableClientState(GL_VERTEX_ARRAY); if (this->isVBOSupported) { glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); glColorPointer(4, GL_FLOAT, 0, OGLRef.vtxPtrColor); glBindBufferARB(GL_ARRAY_BUFFER_ARB, OGLRef.vboGeometryVtxID); } else { glColorPointer(4, GL_FLOAT, 0, OGLRef.vtxPtrColor); } glVertexPointer(4, GL_FLOAT, sizeof(VERT), OGLRef.vtxPtrPosition); glTexCoordPointer(2, GL_FLOAT, sizeof(VERT), OGLRef.vtxPtrTexCoord); } } glActiveTextureARB(GL_TEXTURE0_ARB); return OGLERROR_NOERR; } Render3DError OpenGLRenderer_1_2::DisableVertexAttributes() { if (this->isVAOSupported) { glBindVertexArray(0); } else { if (this->isShaderSupported) { glDisableVertexAttribArray(OGLVertexAttributeID_Position); glDisableVertexAttribArray(OGLVertexAttributeID_TexCoord0); glDisableVertexAttribArray(OGLVertexAttributeID_Color); } else { glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_COLOR_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY); } } return OGLERROR_NOERR; } Render3DError OpenGLRenderer_1_2::DownsampleFBO() { OGLRenderRef &OGLRef = *this->ref; if (this->isMultisampledFBOSupported && OGLRef.selectedRenderingFBO == OGLRef.fboMSIntermediateRenderID) { glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, OGLRef.fboMSIntermediateRenderID); glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, OGLRef.fboRenderID); // Blit the color buffer glReadBuffer(GL_COLOR_ATTACHMENT0_EXT); glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); glBlitFramebufferEXT(0, 0, this->_framebufferWidth, this->_framebufferHeight, 0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST); // Blit the working depth buffer glReadBuffer(GL_COLOR_ATTACHMENT1_EXT); glDrawBuffer(GL_COLOR_ATTACHMENT1_EXT); glBlitFramebufferEXT(0, 0, this->_framebufferWidth, this->_framebufferHeight, 0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST); // Blit the polygon ID buffer glReadBuffer(GL_COLOR_ATTACHMENT2_EXT); glDrawBuffer(GL_COLOR_ATTACHMENT2_EXT); glBlitFramebufferEXT(0, 0, this->_framebufferWidth, this->_framebufferHeight, 0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST); // Blit the fog buffer glReadBuffer(GL_COLOR_ATTACHMENT3_EXT); glDrawBuffer(GL_COLOR_ATTACHMENT3_EXT); glBlitFramebufferEXT(0, 0, this->_framebufferWidth, this->_framebufferHeight, 0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST); // Reset framebuffer targets glReadBuffer(GL_COLOR_ATTACHMENT0_EXT); glDrawBuffers(4, RenderDrawList); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.fboRenderID); } return OGLERROR_NOERR; } Render3DError OpenGLRenderer_1_2::ReadBackPixels() { OGLRenderRef &OGLRef = *this->ref; if (!this->isPBOSupported) { this->_pixelReadNeedsFinish = true; return OGLERROR_NOERR; } if (this->_mappedFramebuffer != NULL) { glUnmapBufferARB(GL_PIXEL_PACK_BUFFER_ARB); this->_mappedFramebuffer = NULL; } // Flip the framebuffer in Y to match the coordinates of OpenGL and the NDS hardware. if (this->willFlipFramebufferOnGPU) { glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, OGLRef.fboPostprocessID); glDrawBuffer(GL_COLOR_ATTACHMENT1_EXT); glBlitFramebufferEXT(0, this->_framebufferHeight, this->_framebufferWidth, 0, 0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.fboPostprocessID); glReadBuffer(GL_COLOR_ATTACHMENT1_EXT); } if (this->willConvertFramebufferOnGPU) { // Perform the color space conversion while we're still on the GPU so // that we can avoid having to do it on the CPU. const GLuint convertProgramID = (this->_outputFormat == NDSColorFormat_BGR666_Rev) ? OGLRef.programFramebufferRGBA6665OutputID : OGLRef.programFramebufferRGBA8888OutputID; glDrawBuffer(GL_COLOR_ATTACHMENT2_EXT); glUseProgram(convertProgramID); glViewport(0, 0, this->_framebufferWidth, this->_framebufferHeight); glDisable(GL_DEPTH_TEST); glDisable(GL_STENCIL_TEST); glDisable(GL_BLEND); glDisable(GL_CULL_FACE); glBindBuffer(GL_ARRAY_BUFFER, OGLRef.vboPostprocessVtxID); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, OGLRef.iboPostprocessIndexID); glBindVertexArray(OGLRef.vaoPostprocessStatesID); glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, 0); glBindVertexArray(0); // Read back the pixels. glReadBuffer(GL_COLOR_ATTACHMENT2_EXT); } // Read back the pixels in BGRA format, since legacy OpenGL devices may experience a performance // penalty if the readback is in any other format. glReadPixels(0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_BGRA, GL_UNSIGNED_BYTE, 0); // Set the read and draw target buffers back to color attachment 0, which is always the default. if (this->willFlipFramebufferOnGPU || this->willConvertFramebufferOnGPU) { glReadBuffer(GL_COLOR_ATTACHMENT0_EXT); glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); } this->_pixelReadNeedsFinish = true; return OGLERROR_NOERR; } Render3DError OpenGLRenderer_1_2::DeleteTexture(const TexCacheItem *item) { this->ref->freeTextureIDs.push((GLuint)item->texid); if(this->currTexture == item) { this->currTexture = NULL; } return OGLERROR_NOERR; } Render3DError OpenGLRenderer_1_2::BeginRender(const GFX3D &engine) { OGLRenderRef &OGLRef = *this->ref; if(!BEGINGL()) { return OGLERROR_BEGINGL_FAILED; } if (this->isShaderSupported) { glUseProgram(OGLRef.programGeometryID); glUniform1i(OGLRef.uniformStateToonShadingMode, engine.renderState.shading); glUniform1i(OGLRef.uniformStateEnableAlphaTest, (engine.renderState.enableAlphaTest) ? GL_TRUE : GL_FALSE); glUniform1i(OGLRef.uniformStateEnableAntialiasing, (engine.renderState.enableAntialiasing) ? GL_TRUE : GL_FALSE); glUniform1i(OGLRef.uniformStateEnableEdgeMarking, (engine.renderState.enableEdgeMarking) ? GL_TRUE : GL_FALSE); glUniform1i(OGLRef.uniformStateUseWDepth, (engine.renderState.wbuffer) ? GL_TRUE : GL_FALSE); glUniform1f(OGLRef.uniformStateAlphaTestRef, divide5bitBy31_LUT[engine.renderState.alphaTestRef]); } else { if(engine.renderState.enableAlphaTest && (engine.renderState.alphaTestRef > 0)) { glAlphaFunc(GL_GEQUAL, divide5bitBy31_LUT[engine.renderState.alphaTestRef]); } else { glAlphaFunc(GL_GREATER, 0); } glMatrixMode(GL_PROJECTION); glLoadIdentity(); } GLushort *indexPtr = NULL; if (this->isVBOSupported) { glBindBufferARB(GL_ARRAY_BUFFER_ARB, OGLRef.vboGeometryVtxID); glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, OGLRef.iboGeometryIndexID); indexPtr = (GLushort *)glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB); } else { // If VBOs aren't supported, we need to use the client-side buffers here. OGLRef.vtxPtrPosition = &engine.vertlist->list[0].coord; OGLRef.vtxPtrTexCoord = &engine.vertlist->list[0].texcoord; OGLRef.vtxPtrColor = (this->isShaderSupported) ? (GLvoid *)&engine.vertlist->list[0].color : OGLRef.color4fBuffer; indexPtr = OGLRef.vertIndexBuffer; } size_t vertIndexCount = 0; for (size_t i = 0; i < engine.polylist->count; i++) { const POLY *thePoly = &engine.polylist->list[engine.indexlist.list[i]]; const size_t polyType = thePoly->type; if (this->isShaderSupported) { for (size_t j = 0; j < polyType; j++) { const GLushort vertIndex = thePoly->vertIndexes[j]; // While we're looping through our vertices, add each vertex index to // a buffer. For GFX3D_QUADS and GFX3D_QUAD_STRIP, we also add additional // vertices here to convert them to GL_TRIANGLES, which are much easier // to work with and won't be deprecated in future OpenGL versions. indexPtr[vertIndexCount++] = vertIndex; if (thePoly->vtxFormat == GFX3D_QUADS || thePoly->vtxFormat == GFX3D_QUAD_STRIP) { if (j == 2) { indexPtr[vertIndexCount++] = vertIndex; } else if (j == 3) { indexPtr[vertIndexCount++] = thePoly->vertIndexes[0]; } } } } else { const GLfloat thePolyAlpha = (!thePoly->isWireframe() && thePoly->isTranslucent()) ? divide5bitBy31_LUT[thePoly->getAttributeAlpha()] : 1.0f; for (size_t j = 0; j < polyType; j++) { const GLushort vertIndex = thePoly->vertIndexes[j]; const size_t colorIndex = vertIndex * 4; // Consolidate the vertex color and the poly alpha to our internal color buffer // so that OpenGL can use it. const VERT *vert = &engine.vertlist->list[vertIndex]; OGLRef.color4fBuffer[colorIndex+0] = material_8bit_to_float[vert->color[0]]; OGLRef.color4fBuffer[colorIndex+1] = material_8bit_to_float[vert->color[1]]; OGLRef.color4fBuffer[colorIndex+2] = material_8bit_to_float[vert->color[2]]; OGLRef.color4fBuffer[colorIndex+3] = thePolyAlpha; // While we're looping through our vertices, add each vertex index to a // buffer. For GFX3D_QUADS and GFX3D_QUAD_STRIP, we also add additional // vertices here to convert them to GL_TRIANGLES, which are much easier // to work with and won't be deprecated in future OpenGL versions. indexPtr[vertIndexCount++] = vertIndex; if (thePoly->vtxFormat == GFX3D_QUADS || thePoly->vtxFormat == GFX3D_QUAD_STRIP) { if (j == 2) { indexPtr[vertIndexCount++] = vertIndex; } else if (j == 3) { indexPtr[vertIndexCount++] = thePoly->vertIndexes[0]; } } } } } if (this->isVBOSupported) { glUnmapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB); glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, sizeof(VERT) * engine.vertlist->count, engine.vertlist); } return OGLERROR_NOERR; } Render3DError OpenGLRenderer_1_2::RenderGeometry(const GFX3D_State &renderState, const POLYLIST *polyList, const INDEXLIST *indexList) { OGLRenderRef &OGLRef = *this->ref; const size_t polyCount = polyList->count; // Map GFX3D_QUADS and GFX3D_QUAD_STRIP to GL_TRIANGLES since we will convert them. // // Also map GFX3D_TRIANGLE_STRIP to GL_TRIANGLES. This is okay since this is actually // how the POLY struct stores triangle strip vertices, which is in sets of 3 vertices // each. This redefinition is necessary since uploading more than 3 indices at a time // will cause glDrawElements() to draw the triangle strip incorrectly. static const GLenum oglPrimitiveType[] = {GL_TRIANGLES, GL_TRIANGLES, GL_TRIANGLES, GL_TRIANGLES, GL_LINE_LOOP, GL_LINE_LOOP, GL_LINE_STRIP, GL_LINE_STRIP}; static const GLsizei indexIncrementLUT[] = {3, 6, 3, 6, 3, 4, 3, 4}; if (polyCount > 0) { glEnable(GL_DEPTH_TEST); if(renderState.enableAlphaBlending) { glEnable(GL_BLEND); } else { glDisable(GL_BLEND); } this->EnableVertexAttributes(); this->_shadowPolyID.clear(); for (size_t i = 0; i < polyCount; i++) { const POLY &thePoly = polyList->list[i]; if (thePoly.getAttributePolygonMode() != POLYGON_MODE_SHADOW) { continue; } const u8 polyID = thePoly.getAttributePolygonID(); if ( (polyID == 0) || (std::find(this->_shadowPolyID.begin(), this->_shadowPolyID.end(), polyID) != this->_shadowPolyID.end()) ) { continue; } this->_shadowPolyID.push_back(polyID); } const POLY &firstPoly = polyList->list[indexList->list[0]]; u32 lastPolyAttr = firstPoly.polyAttr; u32 lastTexParams = firstPoly.texParam; u32 lastTexPalette = firstPoly.texPalette; u32 lastViewport = firstPoly.viewport; this->SetupPolygon(firstPoly); this->SetupTexture(firstPoly, renderState.enableTexturing); this->SetupViewport(lastViewport); GLsizei vertIndexCount = 0; GLushort *indexBufferPtr = OGLRef.vertIndexBuffer; // Enumerate through all polygons and render for (size_t i = 0; i < polyCount; i++) { const POLY &thePoly = polyList->list[indexList->list[i]]; // Set up the polygon if it changed if (lastPolyAttr != thePoly.polyAttr) { lastPolyAttr = thePoly.polyAttr; this->SetupPolygon(thePoly); } // Set up the texture if it changed if (lastTexParams != thePoly.texParam || lastTexPalette != thePoly.texPalette) { lastTexParams = thePoly.texParam; lastTexPalette = thePoly.texPalette; this->SetupTexture(thePoly, renderState.enableTexturing); } // Set up the viewport if it changed if (lastViewport != thePoly.viewport) { lastViewport = thePoly.viewport; this->SetupViewport(thePoly.viewport); } // In wireframe mode, redefine all primitives as GL_LINE_LOOP rather than // setting the polygon mode to GL_LINE though glPolygonMode(). Not only is // drawing more accurate this way, but it also allows GFX3D_QUADS and // GFX3D_QUAD_STRIP primitives to properly draw as wireframe without the // extra diagonal line. const GLenum polyPrimitive = (!thePoly.isWireframe()) ? oglPrimitiveType[thePoly.vtxFormat] : GL_LINE_LOOP; // Increment the vertex count vertIndexCount += indexIncrementLUT[thePoly.vtxFormat]; // Look ahead to the next polygon to see if we can simply buffer the indices // instead of uploading them now. We can buffer if all polygon states remain // the same and we're not drawing a line loop or line strip. if (i+1 < polyCount) { const POLY *nextPoly = &polyList->list[indexList->list[i+1]]; if (lastPolyAttr == nextPoly->polyAttr && lastTexParams == nextPoly->texParam && lastTexPalette == nextPoly->texPalette && lastViewport == nextPoly->viewport && polyPrimitive == oglPrimitiveType[nextPoly->vtxFormat] && polyPrimitive != GL_LINE_LOOP && polyPrimitive != GL_LINE_STRIP && oglPrimitiveType[nextPoly->vtxFormat] != GL_LINE_LOOP && oglPrimitiveType[nextPoly->vtxFormat] != GL_LINE_STRIP) { continue; } } // Render the polygons this->SetPolygonIndex(i); glDrawElements(polyPrimitive, vertIndexCount, GL_UNSIGNED_SHORT, indexBufferPtr); indexBufferPtr += vertIndexCount; vertIndexCount = 0; } this->DisableVertexAttributes(); } this->DownsampleFBO(); return OGLERROR_NOERR; } Render3DError OpenGLRenderer_1_2::EndRender(const u64 frameCount) { //needs to happen before endgl because it could free some textureids for expired cache items TexCache_EvictFrame(); this->ReadBackPixels(); ENDGL(); return OGLERROR_NOERR; } Render3DError OpenGLRenderer_1_2::UpdateToonTable(const u16 *toonTableBuffer) { glActiveTextureARB(GL_TEXTURE0_ARB + OGLTextureUnitID_ToonTable); glTexSubImage1D(GL_TEXTURE_1D, 0, 0, 32, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, toonTableBuffer); return OGLERROR_NOERR; } Render3DError OpenGLRenderer_1_2::ClearUsingImage(const u16 *__restrict colorBuffer, const u32 *__restrict depthBuffer, const u8 *__restrict fogBuffer, const u8 *__restrict polyIDBuffer) { if (!this->isFBOSupported) { return OGLERROR_FEATURE_UNSUPPORTED; } OGLRenderRef &OGLRef = *this->ref; this->UploadClearImage(colorBuffer, depthBuffer, fogBuffer, polyIDBuffer); glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, OGLRef.fboClearImageID); glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, OGLRef.fboRenderID); // It might seem wasteful to be doing a separate glClear(GL_STENCIL_BUFFER_BIT) instead // of simply blitting the stencil buffer with everything else. // // We do this because glBlitFramebufferEXT() for GL_STENCIL_BUFFER_BIT has been tested // to be unsupported on ATI/AMD GPUs running in compatibility mode. So we do the separate // glClear() for GL_STENCIL_BUFFER_BIT to keep these GPUs working. glClearStencil(polyIDBuffer[0]); glClear(GL_STENCIL_BUFFER_BIT); // Blit the working depth buffer glReadBuffer(GL_COLOR_ATTACHMENT1_EXT); glDrawBuffer(GL_COLOR_ATTACHMENT1_EXT); glBlitFramebufferEXT(0, GPU_FRAMEBUFFER_NATIVE_HEIGHT, GPU_FRAMEBUFFER_NATIVE_WIDTH, 0, 0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST); // Blit the polygon ID buffer glReadBuffer(GL_COLOR_ATTACHMENT2_EXT); glDrawBuffer(GL_COLOR_ATTACHMENT2_EXT); glBlitFramebufferEXT(0, GPU_FRAMEBUFFER_NATIVE_HEIGHT, GPU_FRAMEBUFFER_NATIVE_WIDTH, 0, 0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST); // Blit the fog buffer glReadBuffer(GL_COLOR_ATTACHMENT3_EXT); glDrawBuffer(GL_COLOR_ATTACHMENT3_EXT); glBlitFramebufferEXT(0, GPU_FRAMEBUFFER_NATIVE_HEIGHT, GPU_FRAMEBUFFER_NATIVE_WIDTH, 0, 0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST); // Blit the color buffer. Do this last so that color attachment 0 is set to the read FBO. glReadBuffer(GL_COLOR_ATTACHMENT0_EXT); glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); glBlitFramebufferEXT(0, GPU_FRAMEBUFFER_NATIVE_HEIGHT, GPU_FRAMEBUFFER_NATIVE_WIDTH, 0, 0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_NEAREST); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.fboRenderID); glDrawBuffers(4, RenderDrawList); if (this->isMultisampledFBOSupported) { OGLRef.selectedRenderingFBO = (CommonSettings.GFX3D_Renderer_Multisample) ? OGLRef.fboMSIntermediateRenderID : OGLRef.fboRenderID; if (OGLRef.selectedRenderingFBO == OGLRef.fboMSIntermediateRenderID) { glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, OGLRef.fboRenderID); glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, OGLRef.selectedRenderingFBO); glClearStencil(polyIDBuffer[0]); glClear(GL_STENCIL_BUFFER_BIT); // Blit the working depth buffer glReadBuffer(GL_COLOR_ATTACHMENT1_EXT); glDrawBuffer(GL_COLOR_ATTACHMENT1_EXT); glBlitFramebufferEXT(0, 0, this->_framebufferWidth, this->_framebufferHeight, 0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST); // Blit the polygon ID buffer glReadBuffer(GL_COLOR_ATTACHMENT2_EXT); glDrawBuffer(GL_COLOR_ATTACHMENT2_EXT); glBlitFramebufferEXT(0, 0, this->_framebufferWidth, this->_framebufferHeight, 0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST); // Blit the fog buffer glReadBuffer(GL_COLOR_ATTACHMENT3_EXT); glDrawBuffer(GL_COLOR_ATTACHMENT3_EXT); glBlitFramebufferEXT(0, 0, this->_framebufferWidth, this->_framebufferHeight, 0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST); // Blit the color buffer. Do this last so that color attachment 0 is set to the read FBO. glReadBuffer(GL_COLOR_ATTACHMENT0_EXT); glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); glBlitFramebufferEXT(0, 0, this->_framebufferWidth, this->_framebufferHeight, 0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_NEAREST); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.selectedRenderingFBO); glDrawBuffers(4, RenderDrawList); } } return OGLERROR_NOERR; } Render3DError OpenGLRenderer_1_2::ClearUsingValues(const FragmentColor &clearColor, const FragmentAttributes &clearAttributes) const { OGLRenderRef &OGLRef = *this->ref; if (this->isMultisampledFBOSupported) { OGLRef.selectedRenderingFBO = (CommonSettings.GFX3D_Renderer_Multisample) ? OGLRef.fboMSIntermediateRenderID : OGLRef.fboRenderID; glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.selectedRenderingFBO); } glDepthMask(GL_TRUE); if (this->isShaderSupported && this->isFBOSupported) { glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); // texGColorID glClearColor(divide5bitBy31_LUT[clearColor.r], divide5bitBy31_LUT[clearColor.g], divide5bitBy31_LUT[clearColor.b], divide5bitBy31_LUT[clearColor.a]); glClearDepth((GLclampd)clearAttributes.depth / (GLclampd)0x00FFFFFF); glClearStencil(0xFF); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); glDrawBuffer(GL_COLOR_ATTACHMENT1_EXT); // texGDepthID glClearColor((GLfloat)(clearAttributes.depth & 0x000000FF)/255.0f, (GLfloat)((clearAttributes.depth >> 8) & 0x000000FF)/255.0f, (GLfloat)((clearAttributes.depth >> 16) & 0x000000FF)/255.0f, 1.0); glClear(GL_COLOR_BUFFER_BIT); glDrawBuffer(GL_COLOR_ATTACHMENT2_EXT); // texGPolyID glClearColor((GLfloat)clearAttributes.opaquePolyID/63.0f, 0.0, 0.0, 1.0); glClear(GL_COLOR_BUFFER_BIT); glDrawBuffer(GL_COLOR_ATTACHMENT3_EXT); // texGFogAttrID glClearColor(clearAttributes.isFogged, 0.0, 0.0, 1.0); glClear(GL_COLOR_BUFFER_BIT); glDrawBuffers(4, RenderDrawList); } else { glClearColor(divide5bitBy31_LUT[clearColor.r], divide5bitBy31_LUT[clearColor.g], divide5bitBy31_LUT[clearColor.b], divide5bitBy31_LUT[clearColor.a]); glClearDepth((GLclampd)clearAttributes.depth / (GLclampd)0x00FFFFFF); glClearStencil(clearAttributes.opaquePolyID); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); } return OGLERROR_NOERR; } void OpenGLRenderer_1_2::SetPolygonIndex(const size_t index) { this->_currentPolyIndex = index; } Render3DError OpenGLRenderer_1_2::SetupPolygon(const POLY &thePoly) { const PolygonAttributes attr = thePoly.getAttributes(); // Set up depth test mode static const GLenum oglDepthFunc[2] = {GL_LESS, GL_EQUAL}; glDepthFunc(oglDepthFunc[attr.enableDepthEqualTest]); // Set up culling mode static const GLenum oglCullingMode[4] = {GL_FRONT_AND_BACK, GL_FRONT, GL_BACK, 0}; GLenum cullingMode = oglCullingMode[attr.surfaceCullingMode]; if (cullingMode == 0) { glDisable(GL_CULL_FACE); } else { glEnable(GL_CULL_FACE); glCullFace(cullingMode); } // Set up depth write GLboolean enableDepthWrite = GL_TRUE; // Handle shadow polys. Do this after checking for depth write, since shadow polys // can change this too. if (attr.polygonMode == POLYGON_MODE_SHADOW) { glEnable(GL_STENCIL_TEST); if (attr.polygonID == 0) { //when the polyID is zero, we are writing the shadow mask. //set stencilbuf = 1 where the shadow volume is obstructed by geometry. //do not write color or depth information. glStencilFunc(GL_NOTEQUAL, 0x80, 0xFF); glStencilOp(GL_KEEP, GL_ZERO, GL_KEEP); glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); enableDepthWrite = GL_FALSE; } else { //when the polyid is nonzero, we are drawing the shadow poly. //only draw the shadow poly where the stencilbuf==1. glStencilFunc(GL_EQUAL, 0, 0xFF); glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); enableDepthWrite = GL_TRUE; } } else if ( attr.isTranslucent || (std::find(this->_shadowPolyID.begin(), this->_shadowPolyID.end(), attr.polygonID) == this->_shadowPolyID.end()) ) { glDisable(GL_STENCIL_TEST); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); enableDepthWrite = (!attr.isTranslucent || ( (attr.polygonMode == POLYGON_MODE_DECAL) && attr.isOpaque ) || attr.enableAlphaDepthWrite) ? GL_TRUE : GL_FALSE; } else { glEnable(GL_STENCIL_TEST); glStencilFunc(GL_ALWAYS, 0x80, 0xFF); glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); enableDepthWrite = GL_TRUE; } glDepthMask(enableDepthWrite); // Set up polygon attributes if (this->isShaderSupported) { OGLRenderRef &OGLRef = *this->ref; glUniform1i(OGLRef.uniformPolyMode, attr.polygonMode); glUniform1i(OGLRef.uniformPolyEnableFog, (attr.enableRenderFog) ? GL_TRUE : GL_FALSE); glUniform1f(OGLRef.uniformPolyAlpha, (!attr.isWireframe && attr.isTranslucent) ? divide5bitBy31_LUT[attr.alpha] : 1.0f); glUniform1i(OGLRef.uniformPolyID, attr.polygonID); glUniform1i(OGLRef.uniformPolyEnableDepthWrite, enableDepthWrite); glUniform1i(OGLRef.uniformPolySetNewDepthForTranslucent, (attr.enableAlphaDepthWrite) ? GL_TRUE : GL_FALSE); } else { // Set the texture blending mode static const GLint oglTexBlendMode[4] = {GL_MODULATE, GL_DECAL, GL_MODULATE, GL_MODULATE}; glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, oglTexBlendMode[attr.polygonMode]); } return OGLERROR_NOERR; } Render3DError OpenGLRenderer_1_2::SetupTexture(const POLY &thePoly, bool enableTexturing) { OGLRenderRef &OGLRef = *this->ref; const PolygonTexParams params = thePoly.getTexParams(); // Check if we need to use textures if (params.texFormat == TEXMODE_NONE || !enableTexturing) { if (this->isShaderSupported) { glUniform1i(OGLRef.uniformPolyEnableTexture, GL_FALSE); } else { glDisable(GL_TEXTURE_2D); } return OGLERROR_NOERR; } // Enable textures if they weren't already enabled if (this->isShaderSupported) { glUniform1i(OGLRef.uniformPolyEnableTexture, GL_TRUE); } else { glEnable(GL_TEXTURE_2D); } TexCacheItem *newTexture = TexCache_SetTexture(TexFormat_32bpp, thePoly.texParam, thePoly.texPalette); if(newTexture != this->currTexture) { this->currTexture = newTexture; //has the ogl renderer initialized the texture? if(this->currTexture->GetDeleteCallback() == NULL) { this->currTexture->SetDeleteCallback(&texDeleteCallback, this, NULL); if(OGLRef.freeTextureIDs.empty()) { this->ExpandFreeTextures(); } this->currTexture->texid = (u64)OGLRef.freeTextureIDs.front(); OGLRef.freeTextureIDs.pop(); glBindTexture(GL_TEXTURE_2D, (GLuint)this->currTexture->texid); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, (params.enableRepeatS ? (params.enableMirroredRepeatS ? OGLRef.stateTexMirroredRepeat : GL_REPEAT) : GL_CLAMP_TO_EDGE)); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, (params.enableRepeatT ? (params.enableMirroredRepeatT ? OGLRef.stateTexMirroredRepeat : GL_REPEAT) : GL_CLAMP_TO_EDGE)); u32 *textureSrc = (u32 *)currTexture->decoded; size_t texWidth = currTexture->sizeX; size_t texHeight = currTexture->sizeY; if (this->_textureDeposterizeBuffer != NULL) { this->TextureDeposterize(textureSrc, texWidth, texHeight); textureSrc = this->_textureDeposterizeBuffer; } switch (this->_textureScalingFactor) { case 2: { this->TextureUpscale<2>(textureSrc, texWidth, texHeight); textureSrc = this->_textureUpscaleBuffer; break; } case 4: { this->TextureUpscale<4>(textureSrc, texWidth, texHeight); textureSrc = this->_textureUpscaleBuffer; break; } default: break; } glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texWidth, texHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, textureSrc); } else { //otherwise, just bind it glBindTexture(GL_TEXTURE_2D, (GLuint)this->currTexture->texid); } if (this->isShaderSupported) { glUniform2f(OGLRef.uniformPolyTexScale, this->currTexture->invSizeX, this->currTexture->invSizeY); } else { glMatrixMode(GL_TEXTURE); glLoadIdentity(); glScalef(this->currTexture->invSizeX, this->currTexture->invSizeY, 1.0f); } } return OGLERROR_NOERR; } Render3DError OpenGLRenderer_1_2::SetupViewport(const u32 viewportValue) { const GLfloat wScalar = this->_framebufferWidth / GPU_FRAMEBUFFER_NATIVE_WIDTH; const GLfloat hScalar = this->_framebufferHeight / GPU_FRAMEBUFFER_NATIVE_HEIGHT; VIEWPORT viewport; viewport.decode(viewportValue); glViewport(viewport.x * wScalar, viewport.y * hScalar, viewport.width * wScalar, viewport.height * hScalar); return OGLERROR_NOERR; } Render3DError OpenGLRenderer_1_2::Reset() { OGLRenderRef &OGLRef = *this->ref; if(!BEGINGL()) { return OGLERROR_BEGINGL_FAILED; } glFinish(); if (!this->isShaderSupported) { glEnable(GL_NORMALIZE); glEnable(GL_TEXTURE_1D); glEnable(GL_TEXTURE_2D); glAlphaFunc(GL_GREATER, 0); glEnable(GL_ALPHA_TEST); glEnable(GL_BLEND); } ENDGL(); this->_pixelReadNeedsFinish = false; if (OGLRef.color4fBuffer != NULL) { memset(OGLRef.color4fBuffer, 0, VERTLIST_SIZE * 4 * sizeof(GLfloat)); } if (OGLRef.vertIndexBuffer != NULL) { memset(OGLRef.vertIndexBuffer, 0, OGLRENDER_VERT_INDEX_BUFFER_COUNT * sizeof(GLushort)); } this->currTexture = NULL; this->_currentPolyIndex = 0; OGLRef.vtxPtrPosition = (GLvoid *)offsetof(VERT, coord); OGLRef.vtxPtrTexCoord = (GLvoid *)offsetof(VERT, texcoord); OGLRef.vtxPtrColor = (this->isShaderSupported) ? (GLvoid *)offsetof(VERT, color) : OGLRef.color4fBuffer; memset(this->clearImageColor16Buffer, 0, sizeof(this->clearImageColor16Buffer)); memset(this->clearImageDepthBuffer, 0, sizeof(this->clearImageDepthBuffer)); memset(this->clearImagePolyIDBuffer, 0, sizeof(this->clearImagePolyIDBuffer)); memset(this->clearImageFogBuffer, 0, sizeof(this->clearImageFogBuffer)); TexCache_Reset(); return OGLERROR_NOERR; } Render3DError OpenGLRenderer_1_2::RenderFinish() { if (!this->_renderNeedsFinish || !this->_pixelReadNeedsFinish) { return OGLERROR_NOERR; } FragmentColor *framebufferMain = (this->_willFlushFramebufferRGBA6665) ? GPU->GetEngineMain()->Get3DFramebufferRGBA6665() : NULL; u16 *framebufferRGBA5551 = (this->_willFlushFramebufferRGBA5551) ? GPU->GetEngineMain()->Get3DFramebufferRGBA5551() : NULL; if ( (framebufferMain != NULL) || (framebufferRGBA5551 != NULL) ) { if(!BEGINGL()) { return OGLERROR_BEGINGL_FAILED; } if (this->isPBOSupported) { this->_mappedFramebuffer = (FragmentColor *__restrict)glMapBufferARB(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY_ARB); this->FlushFramebuffer(this->_mappedFramebuffer, framebufferMain, framebufferRGBA5551); } else { glReadPixels(0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_BGRA, GL_UNSIGNED_BYTE, this->_framebufferColor); this->FlushFramebuffer(this->_framebufferColor, framebufferMain, framebufferRGBA5551); } ENDGL(); } this->_pixelReadNeedsFinish = false; return OGLERROR_NOERR; } Render3DError OpenGLRenderer_1_2::SetFramebufferSize(size_t w, size_t h) { OGLRenderRef &OGLRef = *this->ref; if (w < GPU_FRAMEBUFFER_NATIVE_WIDTH || h < GPU_FRAMEBUFFER_NATIVE_HEIGHT) { return OGLERROR_NOERR; } if (!BEGINGL()) { return OGLERROR_BEGINGL_FAILED; } if (this->isPBOSupported) { if (this->_mappedFramebuffer != NULL) { glUnmapBufferARB(GL_PIXEL_PACK_BUFFER_ARB); this->_mappedFramebuffer = NULL; } } if (this->isFBOSupported) { glActiveTextureARB(GL_TEXTURE0_ARB + OGLTextureUnitID_GColor); glBindTexture(GL_TEXTURE_2D, OGLRef.texGDepthStencilID); glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8_EXT, w, h, 0, GL_DEPTH_STENCIL_EXT, GL_UNSIGNED_INT_24_8_EXT, NULL); glBindTexture(GL_TEXTURE_2D, OGLRef.texGColorID); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL); glActiveTextureARB(GL_TEXTURE0_ARB + OGLTextureUnitID_GDepth); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL); glActiveTextureARB(GL_TEXTURE0_ARB + OGLTextureUnitID_GPolyID); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL); glActiveTextureARB(GL_TEXTURE0_ARB + OGLTextureUnitID_FogAttr); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL); glActiveTextureARB(GL_TEXTURE0_ARB); glBindTexture(GL_TEXTURE_2D, OGLRef.texPostprocessFogID); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL); } if (this->isMultisampledFBOSupported) { GLint maxSamples = 0; glGetIntegerv(GL_MAX_SAMPLES_EXT, &maxSamples); glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, OGLRef.rboMSGColorID); glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, maxSamples, GL_RGBA, w, h); glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, OGLRef.rboMSGDepthID); glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, maxSamples, GL_RGBA, w, h); glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, OGLRef.rboMSGPolyID); glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, maxSamples, GL_RGBA, w, h); glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, OGLRef.rboMSGFogAttrID); glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, maxSamples, GL_RGBA, w, h); glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, OGLRef.rboMSGDepthStencilID); glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, maxSamples, GL_DEPTH24_STENCIL8_EXT, w, h); } if (this->willFlipFramebufferOnGPU) { glActiveTextureARB(GL_TEXTURE0_ARB + OGLTextureUnitID_FinalColor); glBindTexture(GL_TEXTURE_2D, OGLRef.texFinalColorID); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL); } if (this->willConvertFramebufferOnGPU) { glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, OGLRef.rboFramebufferRGBA6665ID); glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGBA, w, h); } const size_t newFramebufferColorSizeBytes = w * h * sizeof(FragmentColor); this->_framebufferWidth = w; this->_framebufferHeight = h; this->_framebufferColorSizeBytes = newFramebufferColorSizeBytes; if (this->isPBOSupported) { glBufferDataARB(GL_PIXEL_PACK_BUFFER_ARB, newFramebufferColorSizeBytes, NULL, GL_STREAM_READ_ARB); this->_framebufferColor = NULL; } else { FragmentColor *oldFramebufferColor = this->_framebufferColor; FragmentColor *newFramebufferColor = (FragmentColor *)memalign_alloc_aligned(newFramebufferColorSizeBytes); this->_framebufferColor = newFramebufferColor; free_aligned(oldFramebufferColor); } if (oglrender_framebufferDidResizeCallback != NULL) { oglrender_framebufferDidResizeCallback(w, h); } ENDGL(); return OGLERROR_NOERR; } Render3DError OpenGLRenderer_1_3::CreateToonTable() { OGLRenderRef &OGLRef = *this->ref; u16 tempToonTable[32]; memset(tempToonTable, 0, sizeof(tempToonTable)); // The toon table is a special 1D texture where each pixel corresponds // to a specific color in the toon table. glGenTextures(1, &OGLRef.texToonTableID); glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_ToonTable); glBindTexture(GL_TEXTURE_1D, OGLRef.texToonTableID); glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexImage1D(GL_TEXTURE_1D, 0, GL_RGB, 32, 0, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, tempToonTable); glActiveTexture(GL_TEXTURE0); return OGLERROR_NOERR; } Render3DError OpenGLRenderer_1_3::UpdateToonTable(const u16 *toonTableBuffer) { glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_ToonTable); glTexSubImage1D(GL_TEXTURE_1D, 0, 0, 32, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, toonTableBuffer); return OGLERROR_NOERR; } Render3DError OpenGLRenderer_1_3::UploadClearImage(const u16 *__restrict colorBuffer, const u32 *__restrict depthBuffer, const u8 *__restrict fogBuffer, const u8 *__restrict polyIDBuffer) { OGLRenderRef &OGLRef = *this->ref; if (this->isShaderSupported) { for (size_t i = 0; i < GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT; i++) { OGLRef.workingCIDepthStencilBuffer[i] = (depthBuffer[i] << 8) | polyIDBuffer[i]; OGLRef.workingCIDepthBuffer[i] = depthBuffer[i] | 0xFF000000; OGLRef.workingCIFogAttributesBuffer[i] = (fogBuffer[i]) ? 0xFF0000FF : 0xFF000000; OGLRef.workingCIPolyIDBuffer[i] = (GLuint)polyIDBuffer[i] | 0xFF000000; } } else { for (size_t i = 0; i < GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT; i++) { OGLRef.workingCIDepthStencilBuffer[i] = (depthBuffer[i] << 8) | polyIDBuffer[i]; } } glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, OGLRef.texCIColorID); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, GPU_FRAMEBUFFER_NATIVE_WIDTH, GPU_FRAMEBUFFER_NATIVE_HEIGHT, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, colorBuffer); glBindTexture(GL_TEXTURE_2D, OGLRef.texCIDepthStencilID); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, GPU_FRAMEBUFFER_NATIVE_WIDTH, GPU_FRAMEBUFFER_NATIVE_HEIGHT, GL_DEPTH_STENCIL_EXT, GL_UNSIGNED_INT_24_8_EXT, OGLRef.workingCIDepthStencilBuffer); if (this->isShaderSupported) { glBindTexture(GL_TEXTURE_2D, OGLRef.texCIDepthID); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, GPU_FRAMEBUFFER_NATIVE_WIDTH, GPU_FRAMEBUFFER_NATIVE_HEIGHT, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, OGLRef.workingCIDepthBuffer); glBindTexture(GL_TEXTURE_2D, OGLRef.texCIFogAttrID); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, GPU_FRAMEBUFFER_NATIVE_WIDTH, GPU_FRAMEBUFFER_NATIVE_HEIGHT, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, OGLRef.workingCIFogAttributesBuffer); glBindTexture(GL_TEXTURE_2D, OGLRef.texCIPolyID); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, GPU_FRAMEBUFFER_NATIVE_WIDTH, GPU_FRAMEBUFFER_NATIVE_HEIGHT, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, OGLRef.workingCIPolyIDBuffer); } glBindTexture(GL_TEXTURE_2D, 0); return OGLERROR_NOERR; } Render3DError OpenGLRenderer_1_3::SetFramebufferSize(size_t w, size_t h) { OGLRenderRef &OGLRef = *this->ref; if (w < GPU_FRAMEBUFFER_NATIVE_WIDTH || h < GPU_FRAMEBUFFER_NATIVE_HEIGHT) { return OGLERROR_NOERR; } if (!BEGINGL()) { return OGLERROR_BEGINGL_FAILED; } if (this->isPBOSupported) { if (this->_mappedFramebuffer != NULL) { glUnmapBufferARB(GL_PIXEL_PACK_BUFFER_ARB); this->_mappedFramebuffer = NULL; } } if (this->isFBOSupported) { glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_GColor); glBindTexture(GL_TEXTURE_2D, OGLRef.texGDepthStencilID); glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8_EXT, w, h, 0, GL_DEPTH_STENCIL_EXT, GL_UNSIGNED_INT_24_8_EXT, NULL); glBindTexture(GL_TEXTURE_2D, OGLRef.texGColorID); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL); glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_GDepth); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL); glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_GPolyID); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL); glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_FogAttr); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, OGLRef.texPostprocessFogID); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL); } if (this->isMultisampledFBOSupported) { GLint maxSamples = 0; glGetIntegerv(GL_MAX_SAMPLES_EXT, &maxSamples); glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, OGLRef.rboMSGColorID); glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, maxSamples, GL_RGBA, w, h); glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, OGLRef.rboMSGDepthID); glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, maxSamples, GL_RGBA, w, h); glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, OGLRef.rboMSGPolyID); glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, maxSamples, GL_RGBA, w, h); glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, OGLRef.rboMSGFogAttrID); glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, maxSamples, GL_RGBA, w, h); glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, OGLRef.rboMSGDepthStencilID); glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, maxSamples, GL_DEPTH24_STENCIL8_EXT, w, h); } if (this->willFlipFramebufferOnGPU) { glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_FinalColor); glBindTexture(GL_TEXTURE_2D, OGLRef.texFinalColorID); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL); } if (this->willConvertFramebufferOnGPU) { glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, OGLRef.rboFramebufferRGBA6665ID); glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGBA, w, h); } const size_t newFramebufferColorSizeBytes = w * h * sizeof(FragmentColor); this->_framebufferWidth = w; this->_framebufferHeight = h; this->_framebufferColorSizeBytes = newFramebufferColorSizeBytes; if (this->isPBOSupported) { glBufferDataARB(GL_PIXEL_PACK_BUFFER_ARB, newFramebufferColorSizeBytes, NULL, GL_STREAM_READ_ARB); this->_framebufferColor = NULL; } else { FragmentColor *oldFramebufferColor = this->_framebufferColor; FragmentColor *newFramebufferColor = (FragmentColor *)memalign_alloc_aligned(newFramebufferColorSizeBytes); this->_framebufferColor = newFramebufferColor; free_aligned(oldFramebufferColor); } if (oglrender_framebufferDidResizeCallback != NULL) { oglrender_framebufferDidResizeCallback(w, h); } ENDGL(); return OGLERROR_NOERR; } Render3DError OpenGLRenderer_1_4::InitFinalRenderStates(const std::set *oglExtensionSet) { OGLRenderRef &OGLRef = *this->ref; bool isBlendEquationSeparateSupported = this->IsExtensionPresent(oglExtensionSet, "GL_EXT_blend_equation_separate"); // Blending Support if (isBlendEquationSeparateSupported) { // we want to use alpha destination blending so we can track the last-rendered alpha value // test: new super mario brothers renders the stormclouds at the beginning glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA, GL_DST_ALPHA); glBlendEquationSeparateEXT(GL_FUNC_ADD, GL_MAX); } else { glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_DST_ALPHA); } // Mirrored Repeat Mode Support OGLRef.stateTexMirroredRepeat = GL_MIRRORED_REPEAT; // Map the vertex list's colors with 4 floats per color. This is being done // because OpenGL needs 4-colors per vertex to support translucency. (The DS // uses 3-colors per vertex, and adds alpha through the poly, so we can't // simply reference the colors+alpha from just the vertices by themselves.) OGLRef.color4fBuffer = (this->isShaderSupported) ? NULL : new GLfloat[VERTLIST_SIZE * 4]; // If VBOs aren't supported, then we need to create the index buffer on the // client side so that we have a buffer to update. OGLRef.vertIndexBuffer = (this->isVBOSupported) ? NULL : new GLushort[OGLRENDER_VERT_INDEX_BUFFER_COUNT]; return OGLERROR_NOERR; } OpenGLRenderer_1_5::~OpenGLRenderer_1_5() { glFinish(); DestroyVAOs(); DestroyVBOs(); DestroyPBOs(); } Render3DError OpenGLRenderer_1_5::CreateVBOs() { OGLRenderRef &OGLRef = *this->ref; glGenBuffers(1, &OGLRef.vboGeometryVtxID); glGenBuffers(1, &OGLRef.iboGeometryIndexID); glGenBuffers(1, &OGLRef.vboPostprocessVtxID); glGenBuffers(1, &OGLRef.iboPostprocessIndexID); glBindBuffer(GL_ARRAY_BUFFER, OGLRef.vboGeometryVtxID); glBufferData(GL_ARRAY_BUFFER, VERTLIST_SIZE * sizeof(VERT), NULL, GL_STREAM_DRAW); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, OGLRef.iboGeometryIndexID); glBufferData(GL_ELEMENT_ARRAY_BUFFER, OGLRENDER_VERT_INDEX_BUFFER_COUNT * sizeof(GLushort), NULL, GL_STREAM_DRAW); glBindBuffer(GL_ARRAY_BUFFER, OGLRef.vboPostprocessVtxID); glBufferData(GL_ARRAY_BUFFER, sizeof(PostprocessVtxBuffer), PostprocessVtxBuffer, GL_STATIC_DRAW); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, OGLRef.iboPostprocessIndexID); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(PostprocessElementBuffer), PostprocessElementBuffer, GL_STATIC_DRAW); glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); return OGLERROR_NOERR; } void OpenGLRenderer_1_5::DestroyVBOs() { if (!this->isVBOSupported) { return; } OGLRenderRef &OGLRef = *this->ref; glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); glDeleteBuffers(1, &OGLRef.vboGeometryVtxID); glDeleteBuffers(1, &OGLRef.iboGeometryIndexID); glDeleteBuffers(1, &OGLRef.vboPostprocessVtxID); glDeleteBuffers(1, &OGLRef.iboPostprocessIndexID); this->isVBOSupported = false; } Render3DError OpenGLRenderer_1_5::CreateVAOs() { OGLRenderRef &OGLRef = *this->ref; glGenVertexArrays(1, &OGLRef.vaoGeometryStatesID); glGenVertexArrays(1, &OGLRef.vaoPostprocessStatesID); glBindVertexArray(OGLRef.vaoGeometryStatesID); glBindBuffer(GL_ARRAY_BUFFER, OGLRef.vboGeometryVtxID); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, OGLRef.iboGeometryIndexID); glEnableVertexAttribArray(OGLVertexAttributeID_Position); glEnableVertexAttribArray(OGLVertexAttributeID_TexCoord0); glEnableVertexAttribArray(OGLVertexAttributeID_Color); glVertexAttribPointer(OGLVertexAttributeID_Position, 4, GL_FLOAT, GL_FALSE, sizeof(VERT), (const GLvoid *)offsetof(VERT, coord)); glVertexAttribPointer(OGLVertexAttributeID_TexCoord0, 2, GL_FLOAT, GL_FALSE, sizeof(VERT), (const GLvoid *)offsetof(VERT, texcoord)); glVertexAttribPointer(OGLVertexAttributeID_Color, 3, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(VERT), (const GLvoid *)offsetof(VERT, color)); glBindVertexArray(0); glBindVertexArray(OGLRef.vaoPostprocessStatesID); glBindBuffer(GL_ARRAY_BUFFER, OGLRef.vboPostprocessVtxID); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, OGLRef.iboPostprocessIndexID); glEnableVertexAttribArray(OGLVertexAttributeID_Position); glEnableVertexAttribArray(OGLVertexAttributeID_TexCoord0); glVertexAttribPointer(OGLVertexAttributeID_Position, 2, GL_FLOAT, GL_FALSE, 0, 0); glVertexAttribPointer(OGLVertexAttributeID_TexCoord0, 2, GL_FLOAT, GL_FALSE, 0, (const GLvoid *)(sizeof(GLfloat) * 8)); glBindVertexArray(0); return OGLERROR_NOERR; } Render3DError OpenGLRenderer_1_5::EnableVertexAttributes() { OGLRenderRef &OGLRef = *this->ref; if (this->isVAOSupported) { glBindVertexArray(OGLRef.vaoGeometryStatesID); } else { if (this->isShaderSupported) { glEnableVertexAttribArray(OGLVertexAttributeID_Position); glEnableVertexAttribArray(OGLVertexAttributeID_TexCoord0); glEnableVertexAttribArray(OGLVertexAttributeID_Color); glVertexAttribPointer(OGLVertexAttributeID_Position, 4, GL_FLOAT, GL_FALSE, sizeof(VERT), OGLRef.vtxPtrPosition); glVertexAttribPointer(OGLVertexAttributeID_TexCoord0, 2, GL_FLOAT, GL_FALSE, sizeof(VERT), OGLRef.vtxPtrTexCoord); glVertexAttribPointer(OGLVertexAttributeID_Color, 3, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(VERT), OGLRef.vtxPtrColor); } else { glEnableClientState(GL_TEXTURE_COORD_ARRAY); glEnableClientState(GL_COLOR_ARRAY); glEnableClientState(GL_VERTEX_ARRAY); glBindBuffer(GL_ARRAY_BUFFER, 0); glColorPointer(4, GL_FLOAT, 0, OGLRef.vtxPtrColor); glBindBuffer(GL_ARRAY_BUFFER, OGLRef.vboGeometryVtxID); glVertexPointer(4, GL_FLOAT, sizeof(VERT), OGLRef.vtxPtrPosition); glTexCoordPointer(2, GL_FLOAT, sizeof(VERT), OGLRef.vtxPtrTexCoord); } } glActiveTexture(GL_TEXTURE0); return OGLERROR_NOERR; } Render3DError OpenGLRenderer_1_5::DisableVertexAttributes() { if (this->isVAOSupported) { glBindVertexArray(0); } else { if (this->isShaderSupported) { glDisableVertexAttribArray(OGLVertexAttributeID_Position); glDisableVertexAttribArray(OGLVertexAttributeID_TexCoord0); glDisableVertexAttribArray(OGLVertexAttributeID_Color); } else { glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_COLOR_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY); } } return OGLERROR_NOERR; } Render3DError OpenGLRenderer_1_5::BeginRender(const GFX3D &engine) { OGLRenderRef &OGLRef = *this->ref; if(!BEGINGL()) { return OGLERROR_BEGINGL_FAILED; } if (this->isShaderSupported) { glUseProgram(OGLRef.programGeometryID); glUniform1i(OGLRef.uniformStateToonShadingMode, engine.renderState.shading); glUniform1i(OGLRef.uniformStateEnableAlphaTest, (engine.renderState.enableAlphaTest) ? GL_TRUE : GL_FALSE); glUniform1i(OGLRef.uniformStateEnableAntialiasing, (engine.renderState.enableAntialiasing) ? GL_TRUE : GL_FALSE); glUniform1i(OGLRef.uniformStateEnableEdgeMarking, (engine.renderState.enableEdgeMarking) ? GL_TRUE : GL_FALSE); glUniform1i(OGLRef.uniformStateUseWDepth, (engine.renderState.wbuffer) ? GL_TRUE : GL_FALSE); glUniform1f(OGLRef.uniformStateAlphaTestRef, divide5bitBy31_LUT[engine.renderState.alphaTestRef]); } else { if(engine.renderState.enableAlphaTest && (engine.renderState.alphaTestRef > 0)) { glAlphaFunc(GL_GEQUAL, divide5bitBy31_LUT[engine.renderState.alphaTestRef]); } else { glAlphaFunc(GL_GREATER, 0); } glMatrixMode(GL_PROJECTION); glLoadIdentity(); } glBindBuffer(GL_ARRAY_BUFFER, OGLRef.vboGeometryVtxID); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, OGLRef.iboGeometryIndexID); size_t vertIndexCount = 0; GLushort *indexPtr = (GLushort *)glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY); for (size_t i = 0; i < engine.polylist->count; i++) { const POLY *thePoly = &engine.polylist->list[engine.indexlist.list[i]]; const size_t polyType = thePoly->type; for (size_t j = 0; j < polyType; j++) { const GLushort vertIndex = thePoly->vertIndexes[j]; // While we're looping through our vertices, add each vertex index to // a buffer. For GFX3D_QUADS and GFX3D_QUAD_STRIP, we also add additional // vertices here to convert them to GL_TRIANGLES, which are much easier // to work with and won't be deprecated in future OpenGL versions. indexPtr[vertIndexCount++] = vertIndex; if (thePoly->vtxFormat == GFX3D_QUADS || thePoly->vtxFormat == GFX3D_QUAD_STRIP) { if (j == 2) { indexPtr[vertIndexCount++] = vertIndex; } else if (j == 3) { indexPtr[vertIndexCount++] = thePoly->vertIndexes[0]; } } } } glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER); glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(VERT) * engine.vertlist->count, engine.vertlist); return OGLERROR_NOERR; } Render3DError OpenGLRenderer_2_0::InitExtensions() { Render3DError error = OGLERROR_NOERR; // Get OpenGL extensions std::set oglExtensionSet; this->GetExtensionSet(&oglExtensionSet); // Initialize OpenGL this->InitTables(); // Load and create shaders. Return on any error, since a v2.0 driver will assume that shaders are available. this->isShaderSupported = true; std::string vertexShaderProgram; std::string fragmentShaderProgram; error = this->LoadGeometryShaders(vertexShaderProgram, fragmentShaderProgram); if (error != OGLERROR_NOERR) { this->isShaderSupported = false; return error; } error = this->InitGeometryProgram(vertexShaderProgram, fragmentShaderProgram); if (error != OGLERROR_NOERR) { this->isShaderSupported = false; return error; } std::string edgeMarkVtxShaderString = std::string(EdgeMarkVtxShader_100); std::string edgeMarkFragShaderString = std::string(EdgeMarkFragShader_100); std::string fogVtxShaderString = std::string(FogVtxShader_100); std::string fogFragShaderString = std::string(FogFragShader_100); std::string framebufferOutputVtxShaderString = std::string(FramebufferOutputVtxShader_100); std::string framebufferOutputRGBA6665FragShaderString = std::string(FramebufferOutputRGBA6665FragShader_100); std::string framebufferOutputRGBA8888FragShaderString = std::string(FramebufferOutputRGBA8888FragShader_100); error = this->InitPostprocessingPrograms(edgeMarkVtxShaderString, edgeMarkFragShaderString, fogVtxShaderString, fogFragShaderString, framebufferOutputVtxShaderString, framebufferOutputRGBA6665FragShaderString, framebufferOutputRGBA8888FragShaderString); if (error != OGLERROR_NOERR) { this->DestroyGeometryProgram(); this->isShaderSupported = false; } this->isVBOSupported = true; this->CreateVBOs(); this->isPBOSupported = this->IsExtensionPresent(&oglExtensionSet, "GL_ARB_vertex_buffer_object") && (this->IsExtensionPresent(&oglExtensionSet, "GL_ARB_pixel_buffer_object") || this->IsExtensionPresent(&oglExtensionSet, "GL_EXT_pixel_buffer_object")); if (this->isPBOSupported) { this->CreatePBOs(); } this->isVAOSupported = this->isShaderSupported && this->isVBOSupported && (this->IsExtensionPresent(&oglExtensionSet, "GL_ARB_vertex_array_object") || this->IsExtensionPresent(&oglExtensionSet, "GL_APPLE_vertex_array_object")); if (this->isVAOSupported) { this->CreateVAOs(); } // Don't use ARB versions since we're using the EXT versions for backwards compatibility. this->isFBOSupported = this->IsExtensionPresent(&oglExtensionSet, "GL_EXT_framebuffer_object") && this->IsExtensionPresent(&oglExtensionSet, "GL_EXT_framebuffer_blit") && this->IsExtensionPresent(&oglExtensionSet, "GL_EXT_packed_depth_stencil"); if (this->isFBOSupported) { this->willFlipFramebufferOnGPU = true; this->willConvertFramebufferOnGPU = (this->isShaderSupported && this->isVAOSupported && this->isPBOSupported && this->isFBOSupported); error = this->CreateFBOs(); if (error != OGLERROR_NOERR) { this->isFBOSupported = false; } } else { INFO("OpenGL: FBOs are unsupported. Some emulation features will be disabled.\n"); } // Set these again after FBO creation just in case FBO creation fails. this->willFlipFramebufferOnGPU = this->isFBOSupported; this->willConvertFramebufferOnGPU = (this->isShaderSupported && this->isVAOSupported && this->isPBOSupported && this->isFBOSupported); // Don't use ARB versions since we're using the EXT versions for backwards compatibility. this->isMultisampledFBOSupported = this->isFBOSupported && this->IsExtensionPresent(&oglExtensionSet, "GL_EXT_framebuffer_multisample"); if (this->isMultisampledFBOSupported) { error = this->CreateMultisampledFBO(); if (error != OGLERROR_NOERR) { this->isMultisampledFBOSupported = false; } } else { INFO("OpenGL: Multisampled FBOs are unsupported. Multisample antialiasing will be disabled.\n"); } this->InitTextures(); this->InitFinalRenderStates(&oglExtensionSet); // This must be done last return OGLERROR_NOERR; } Render3DError OpenGLRenderer_2_0::InitFinalRenderStates(const std::set *oglExtensionSet) { OGLRenderRef &OGLRef = *this->ref; // we want to use alpha destination blending so we can track the last-rendered alpha value // test: new super mario brothers renders the stormclouds at the beginning // Blending Support glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA, GL_DST_ALPHA); glBlendEquationSeparate(GL_FUNC_ADD, GL_MAX); // Mirrored Repeat Mode Support OGLRef.stateTexMirroredRepeat = GL_MIRRORED_REPEAT; // Ignore our color buffer since we'll transfer the polygon alpha through a uniform. OGLRef.color4fBuffer = NULL; // VBOs are supported here, so just use the index buffer on the GPU. OGLRef.vertIndexBuffer = NULL; return OGLERROR_NOERR; } Render3DError OpenGLRenderer_2_0::InitPostprocessingPrograms(const std::string &edgeMarkVtxShader, const std::string &edgeMarkFragShader, const std::string &fogVtxShader, const std::string &fogFragShader, const std::string &framebufferOutputVtxShader, const std::string &framebufferOutputRGBA6665FragShader, const std::string &framebufferOutputRGBA8888FragShader) { Render3DError error = OGLERROR_NOERR; OGLRenderRef &OGLRef = *this->ref; OGLRef.vertexEdgeMarkShaderID = glCreateShader(GL_VERTEX_SHADER); if(!OGLRef.vertexEdgeMarkShaderID) { INFO("OpenGL: Failed to create the edge mark vertex shader.\n"); return OGLERROR_SHADER_CREATE_ERROR; } const char *edgeMarkVtxShaderCStr = edgeMarkVtxShader.c_str(); glShaderSource(OGLRef.vertexEdgeMarkShaderID, 1, (const GLchar **)&edgeMarkVtxShaderCStr, NULL); glCompileShader(OGLRef.vertexEdgeMarkShaderID); if (!this->ValidateShaderCompile(OGLRef.vertexEdgeMarkShaderID)) { glDeleteShader(OGLRef.vertexEdgeMarkShaderID); INFO("OpenGL: Failed to compile the edge mark vertex shader.\n"); return OGLERROR_SHADER_CREATE_ERROR; } OGLRef.fragmentEdgeMarkShaderID = glCreateShader(GL_FRAGMENT_SHADER); if(!OGLRef.fragmentEdgeMarkShaderID) { glDeleteShader(OGLRef.vertexEdgeMarkShaderID); INFO("OpenGL: Failed to create the edge mark fragment shader.\n"); return OGLERROR_SHADER_CREATE_ERROR; } const char *edgeMarkFragShaderCStr = edgeMarkFragShader.c_str(); glShaderSource(OGLRef.fragmentEdgeMarkShaderID, 1, (const GLchar **)&edgeMarkFragShaderCStr, NULL); glCompileShader(OGLRef.fragmentEdgeMarkShaderID); if (!this->ValidateShaderCompile(OGLRef.fragmentEdgeMarkShaderID)) { glDeleteShader(OGLRef.vertexEdgeMarkShaderID); glDeleteShader(OGLRef.fragmentEdgeMarkShaderID); INFO("OpenGL: Failed to compile the edge mark fragment shader.\n"); return OGLERROR_SHADER_CREATE_ERROR; } OGLRef.programEdgeMarkID = glCreateProgram(); if(!OGLRef.programEdgeMarkID) { glDeleteShader(OGLRef.vertexEdgeMarkShaderID); glDeleteShader(OGLRef.fragmentEdgeMarkShaderID); INFO("OpenGL: Failed to create the edge mark shader program.\n"); return OGLERROR_SHADER_CREATE_ERROR; } glAttachShader(OGLRef.programEdgeMarkID, OGLRef.vertexEdgeMarkShaderID); glAttachShader(OGLRef.programEdgeMarkID, OGLRef.fragmentEdgeMarkShaderID); error = this->InitEdgeMarkProgramBindings(); if (error != OGLERROR_NOERR) { glDetachShader(OGLRef.programEdgeMarkID, OGLRef.vertexEdgeMarkShaderID); glDetachShader(OGLRef.programEdgeMarkID, OGLRef.fragmentEdgeMarkShaderID); glDeleteProgram(OGLRef.programEdgeMarkID); glDeleteShader(OGLRef.vertexEdgeMarkShaderID); glDeleteShader(OGLRef.fragmentEdgeMarkShaderID); INFO("OpenGL: Failed to make the edge mark shader bindings.\n"); return error; } glLinkProgram(OGLRef.programEdgeMarkID); if (!this->ValidateShaderProgramLink(OGLRef.programEdgeMarkID)) { glDetachShader(OGLRef.programEdgeMarkID, OGLRef.vertexEdgeMarkShaderID); glDetachShader(OGLRef.programEdgeMarkID, OGLRef.fragmentEdgeMarkShaderID); glDeleteProgram(OGLRef.programEdgeMarkID); glDeleteShader(OGLRef.vertexEdgeMarkShaderID); glDeleteShader(OGLRef.fragmentEdgeMarkShaderID); INFO("OpenGL: Failed to link the edge mark shader program.\n"); return OGLERROR_SHADER_CREATE_ERROR; } glValidateProgram(OGLRef.programEdgeMarkID); this->InitEdgeMarkProgramShaderLocations(); // ------------------------------------------ OGLRef.vertexFogShaderID = glCreateShader(GL_VERTEX_SHADER); if(!OGLRef.vertexFogShaderID) { INFO("OpenGL: Failed to create the fog vertex shader.\n"); return OGLERROR_SHADER_CREATE_ERROR; } const char *fogVtxShaderCStr = fogVtxShader.c_str(); glShaderSource(OGLRef.vertexFogShaderID, 1, (const GLchar **)&fogVtxShaderCStr, NULL); glCompileShader(OGLRef.vertexFogShaderID); if (!this->ValidateShaderCompile(OGLRef.vertexFogShaderID)) { glDeleteShader(OGLRef.vertexFogShaderID); INFO("OpenGL: Failed to compile the fog vertex shader.\n"); return OGLERROR_SHADER_CREATE_ERROR; } OGLRef.fragmentFogShaderID = glCreateShader(GL_FRAGMENT_SHADER); if(!OGLRef.fragmentFogShaderID) { glDeleteShader(OGLRef.vertexFogShaderID); INFO("OpenGL: Failed to create the fog fragment shader.\n"); return OGLERROR_SHADER_CREATE_ERROR; } const char *fogFragShaderCStr = fogFragShader.c_str(); glShaderSource(OGLRef.fragmentFogShaderID, 1, (const GLchar **)&fogFragShaderCStr, NULL); glCompileShader(OGLRef.fragmentFogShaderID); if (!this->ValidateShaderCompile(OGLRef.fragmentFogShaderID)) { glDeleteShader(OGLRef.vertexFogShaderID); glDeleteShader(OGLRef.fragmentFogShaderID); INFO("OpenGL: Failed to compile the fog fragment shader.\n"); return OGLERROR_SHADER_CREATE_ERROR; } OGLRef.programFogID = glCreateProgram(); if(!OGLRef.programFogID) { glDeleteShader(OGLRef.vertexFogShaderID); glDeleteShader(OGLRef.fragmentFogShaderID); INFO("OpenGL: Failed to create the fog shader program.\n"); return OGLERROR_SHADER_CREATE_ERROR; } glAttachShader(OGLRef.programFogID, OGLRef.vertexFogShaderID); glAttachShader(OGLRef.programFogID, OGLRef.fragmentFogShaderID); error = this->InitFogProgramBindings(); if (error != OGLERROR_NOERR) { glDetachShader(OGLRef.programFogID, OGLRef.vertexFogShaderID); glDetachShader(OGLRef.programFogID, OGLRef.fragmentFogShaderID); glDeleteProgram(OGLRef.programFogID); glDeleteShader(OGLRef.vertexFogShaderID); glDeleteShader(OGLRef.fragmentFogShaderID); INFO("OpenGL: Failed to make the fog shader bindings.\n"); return error; } glLinkProgram(OGLRef.programFogID); if (!this->ValidateShaderProgramLink(OGLRef.programFogID)) { glDetachShader(OGLRef.programFogID, OGLRef.vertexFogShaderID); glDetachShader(OGLRef.programFogID, OGLRef.fragmentFogShaderID); glDeleteProgram(OGLRef.programFogID); glDeleteShader(OGLRef.vertexFogShaderID); glDeleteShader(OGLRef.fragmentFogShaderID); INFO("OpenGL: Failed to link the fog shader program.\n"); return OGLERROR_SHADER_CREATE_ERROR; } glValidateProgram(OGLRef.programFogID); this->InitFogProgramShaderLocations(); // ------------------------------------------ OGLRef.vertexFramebufferOutputShaderID = glCreateShader(GL_VERTEX_SHADER); if(!OGLRef.vertexFramebufferOutputShaderID) { INFO("OpenGL: Failed to create the framebuffer output vertex shader.\n"); return OGLERROR_SHADER_CREATE_ERROR; } const char *framebufferOutputVtxShaderCStr = framebufferOutputVtxShader.c_str(); glShaderSource(OGLRef.vertexFramebufferOutputShaderID, 1, (const GLchar **)&framebufferOutputVtxShaderCStr, NULL); glCompileShader(OGLRef.vertexFramebufferOutputShaderID); if (!this->ValidateShaderCompile(OGLRef.vertexFramebufferOutputShaderID)) { glDeleteShader(OGLRef.vertexFramebufferOutputShaderID); INFO("OpenGL: Failed to compile the framebuffer output vertex shader.\n"); return OGLERROR_SHADER_CREATE_ERROR; } OGLRef.fragmentFramebufferRGBA6665OutputShaderID = glCreateShader(GL_FRAGMENT_SHADER); if(!OGLRef.fragmentFramebufferRGBA6665OutputShaderID) { glDeleteShader(OGLRef.vertexFramebufferOutputShaderID); INFO("OpenGL: Failed to create the framebuffer output fragment shader.\n"); return OGLERROR_SHADER_CREATE_ERROR; } OGLRef.fragmentFramebufferRGBA8888OutputShaderID = glCreateShader(GL_FRAGMENT_SHADER); if(!OGLRef.fragmentFramebufferRGBA8888OutputShaderID) { glDeleteShader(OGLRef.vertexFramebufferOutputShaderID); glDeleteShader(OGLRef.fragmentFramebufferRGBA6665OutputShaderID); INFO("OpenGL: Failed to create the framebuffer output fragment shader.\n"); return OGLERROR_SHADER_CREATE_ERROR; } const char *framebufferOutputRGBA6665FragShaderCStr = framebufferOutputRGBA6665FragShader.c_str(); glShaderSource(OGLRef.fragmentFramebufferRGBA6665OutputShaderID, 1, (const GLchar **)&framebufferOutputRGBA6665FragShaderCStr, NULL); glCompileShader(OGLRef.fragmentFramebufferRGBA6665OutputShaderID); if (!this->ValidateShaderCompile(OGLRef.fragmentFramebufferRGBA6665OutputShaderID)) { glDeleteShader(OGLRef.vertexFramebufferOutputShaderID); glDeleteShader(OGLRef.fragmentFramebufferRGBA6665OutputShaderID); glDeleteShader(OGLRef.fragmentFramebufferRGBA8888OutputShaderID); INFO("OpenGL: Failed to compile the framebuffer output fragment shader.\n"); return OGLERROR_SHADER_CREATE_ERROR; } const char *framebufferOutputRGBA8888FragShaderCStr = framebufferOutputRGBA8888FragShader.c_str(); glShaderSource(OGLRef.fragmentFramebufferRGBA8888OutputShaderID, 1, (const GLchar **)&framebufferOutputRGBA8888FragShaderCStr, NULL); glCompileShader(OGLRef.fragmentFramebufferRGBA8888OutputShaderID); if (!this->ValidateShaderCompile(OGLRef.fragmentFramebufferRGBA8888OutputShaderID)) { glDeleteShader(OGLRef.vertexFramebufferOutputShaderID); glDeleteShader(OGLRef.fragmentFramebufferRGBA6665OutputShaderID); glDeleteShader(OGLRef.fragmentFramebufferRGBA8888OutputShaderID); INFO("OpenGL: Failed to compile the framebuffer output fragment shader.\n"); return OGLERROR_SHADER_CREATE_ERROR; } OGLRef.programFramebufferRGBA6665OutputID = glCreateProgram(); if(!OGLRef.programFramebufferRGBA6665OutputID) { glDeleteShader(OGLRef.vertexFramebufferOutputShaderID); glDeleteShader(OGLRef.fragmentFramebufferRGBA6665OutputShaderID); glDeleteShader(OGLRef.fragmentFramebufferRGBA8888OutputShaderID); INFO("OpenGL: Failed to create the framebuffer output shader program.\n"); return OGLERROR_SHADER_CREATE_ERROR; } OGLRef.programFramebufferRGBA8888OutputID = glCreateProgram(); if(!OGLRef.programFramebufferRGBA8888OutputID) { glDeleteShader(OGLRef.vertexFramebufferOutputShaderID); glDeleteShader(OGLRef.fragmentFramebufferRGBA6665OutputShaderID); glDeleteShader(OGLRef.fragmentFramebufferRGBA8888OutputShaderID); INFO("OpenGL: Failed to create the framebuffer output shader program.\n"); return OGLERROR_SHADER_CREATE_ERROR; } glAttachShader(OGLRef.programFramebufferRGBA6665OutputID, OGLRef.vertexFramebufferOutputShaderID); glAttachShader(OGLRef.programFramebufferRGBA6665OutputID, OGLRef.fragmentFramebufferRGBA6665OutputShaderID); glAttachShader(OGLRef.programFramebufferRGBA8888OutputID, OGLRef.vertexFramebufferOutputShaderID); glAttachShader(OGLRef.programFramebufferRGBA8888OutputID, OGLRef.fragmentFramebufferRGBA8888OutputShaderID); error = this->InitFramebufferOutputProgramBindings(); if (error != OGLERROR_NOERR) { glDetachShader(OGLRef.programFramebufferRGBA6665OutputID, OGLRef.vertexFramebufferOutputShaderID); glDetachShader(OGLRef.programFramebufferRGBA6665OutputID, OGLRef.fragmentFramebufferRGBA6665OutputShaderID); glDetachShader(OGLRef.programFramebufferRGBA8888OutputID, OGLRef.vertexFramebufferOutputShaderID); glDetachShader(OGLRef.programFramebufferRGBA8888OutputID, OGLRef.fragmentFramebufferRGBA8888OutputShaderID); glDeleteProgram(OGLRef.programFramebufferRGBA6665OutputID); glDeleteProgram(OGLRef.programFramebufferRGBA8888OutputID); glDeleteShader(OGLRef.vertexFramebufferOutputShaderID); glDeleteShader(OGLRef.fragmentFramebufferRGBA6665OutputShaderID); glDeleteShader(OGLRef.fragmentFramebufferRGBA8888OutputShaderID); INFO("OpenGL: Failed to make the framebuffer output shader bindings.\n"); return error; } glLinkProgram(OGLRef.programFramebufferRGBA6665OutputID); glLinkProgram(OGLRef.programFramebufferRGBA8888OutputID); if (!this->ValidateShaderProgramLink(OGLRef.programFramebufferRGBA6665OutputID) || !this->ValidateShaderProgramLink(OGLRef.programFramebufferRGBA8888OutputID)) { glDetachShader(OGLRef.programFramebufferRGBA6665OutputID, OGLRef.vertexFramebufferOutputShaderID); glDetachShader(OGLRef.programFramebufferRGBA6665OutputID, OGLRef.fragmentFramebufferRGBA6665OutputShaderID); glDetachShader(OGLRef.programFramebufferRGBA8888OutputID, OGLRef.vertexFramebufferOutputShaderID); glDetachShader(OGLRef.programFramebufferRGBA8888OutputID, OGLRef.fragmentFramebufferRGBA8888OutputShaderID); glDeleteProgram(OGLRef.programFramebufferRGBA6665OutputID); glDeleteProgram(OGLRef.programFramebufferRGBA8888OutputID); glDeleteShader(OGLRef.vertexFramebufferOutputShaderID); glDeleteShader(OGLRef.fragmentFramebufferRGBA6665OutputShaderID); glDeleteShader(OGLRef.fragmentFramebufferRGBA8888OutputShaderID); INFO("OpenGL: Failed to link the framebuffer output shader program.\n"); return OGLERROR_SHADER_CREATE_ERROR; } glValidateProgram(OGLRef.programFramebufferRGBA6665OutputID); glValidateProgram(OGLRef.programFramebufferRGBA8888OutputID); this->InitFramebufferOutputShaderLocations(); // ------------------------------------------ glUseProgram(OGLRef.programGeometryID); INFO("OpenGL: Successfully created postprocess shaders.\n"); return OGLERROR_NOERR; } Render3DError OpenGLRenderer_2_0::DestroyPostprocessingPrograms() { OGLRenderRef &OGLRef = *this->ref; glUseProgram(0); glDetachShader(OGLRef.programEdgeMarkID, OGLRef.vertexEdgeMarkShaderID); glDetachShader(OGLRef.programEdgeMarkID, OGLRef.fragmentEdgeMarkShaderID); glDetachShader(OGLRef.programFogID, OGLRef.vertexFogShaderID); glDetachShader(OGLRef.programFogID, OGLRef.fragmentFogShaderID); glDeleteProgram(OGLRef.programEdgeMarkID); glDeleteProgram(OGLRef.programFogID); glDeleteShader(OGLRef.vertexEdgeMarkShaderID); glDeleteShader(OGLRef.fragmentEdgeMarkShaderID); glDeleteShader(OGLRef.vertexFogShaderID); glDeleteShader(OGLRef.fragmentFogShaderID); glDetachShader(OGLRef.programFramebufferRGBA6665OutputID, OGLRef.vertexFramebufferOutputShaderID); glDetachShader(OGLRef.programFramebufferRGBA6665OutputID, OGLRef.fragmentFramebufferRGBA6665OutputShaderID); glDetachShader(OGLRef.programFramebufferRGBA8888OutputID, OGLRef.vertexFramebufferOutputShaderID); glDetachShader(OGLRef.programFramebufferRGBA8888OutputID, OGLRef.fragmentFramebufferRGBA8888OutputShaderID); glDeleteProgram(OGLRef.programFramebufferRGBA6665OutputID); glDeleteProgram(OGLRef.programFramebufferRGBA8888OutputID); glDeleteShader(OGLRef.vertexFramebufferOutputShaderID); glDeleteShader(OGLRef.fragmentFramebufferRGBA6665OutputShaderID); glDeleteShader(OGLRef.fragmentFramebufferRGBA8888OutputShaderID); return OGLERROR_NOERR; } Render3DError OpenGLRenderer_2_0::InitEdgeMarkProgramBindings() { OGLRenderRef &OGLRef = *this->ref; glBindAttribLocation(OGLRef.programEdgeMarkID, OGLVertexAttributeID_Position, "inPosition"); glBindAttribLocation(OGLRef.programEdgeMarkID, OGLVertexAttributeID_TexCoord0, "inTexCoord0"); return OGLERROR_NOERR; } Render3DError OpenGLRenderer_2_0::InitEdgeMarkProgramShaderLocations() { OGLRenderRef &OGLRef = *this->ref; glUseProgram(OGLRef.programEdgeMarkID); const GLint uniformTexGDepth = glGetUniformLocation(OGLRef.programEdgeMarkID, "texInFragDepth"); const GLint uniformTexGPolyID = glGetUniformLocation(OGLRef.programEdgeMarkID, "texInPolyID"); glUniform1i(uniformTexGDepth, OGLTextureUnitID_GDepth); glUniform1i(uniformTexGPolyID, OGLTextureUnitID_GPolyID); OGLRef.uniformFramebufferSize = glGetUniformLocation(OGLRef.programEdgeMarkID, "framebufferSize"); OGLRef.uniformStateEdgeColor = glGetUniformLocation(OGLRef.programEdgeMarkID, "stateEdgeColor"); return OGLERROR_NOERR; } Render3DError OpenGLRenderer_2_0::InitFogProgramBindings() { OGLRenderRef &OGLRef = *this->ref; glBindAttribLocation(OGLRef.programFogID, OGLVertexAttributeID_Position, "inPosition"); glBindAttribLocation(OGLRef.programFogID, OGLVertexAttributeID_TexCoord0, "inTexCoord0"); return OGLERROR_NOERR; } Render3DError OpenGLRenderer_2_0::InitFogProgramShaderLocations() { OGLRenderRef &OGLRef = *this->ref; glUseProgram(OGLRef.programFogID); const GLint uniformTexGColor = glGetUniformLocation(OGLRef.programFogID, "texInFragColor"); const GLint uniformTexGDepth = glGetUniformLocation(OGLRef.programFogID, "texInFragDepth"); const GLint uniformTexGFog = glGetUniformLocation(OGLRef.programFogID, "texInFogAttributes"); glUniform1i(uniformTexGColor, OGLTextureUnitID_GColor); glUniform1i(uniformTexGDepth, OGLTextureUnitID_GDepth); glUniform1i(uniformTexGFog, OGLTextureUnitID_FogAttr); OGLRef.uniformStateEnableFogAlphaOnly = glGetUniformLocation(OGLRef.programFogID, "stateEnableFogAlphaOnly"); OGLRef.uniformStateFogColor = glGetUniformLocation(OGLRef.programFogID, "stateFogColor"); OGLRef.uniformStateFogDensity = glGetUniformLocation(OGLRef.programFogID, "stateFogDensity"); OGLRef.uniformStateFogOffset = glGetUniformLocation(OGLRef.programFogID, "stateFogOffset"); OGLRef.uniformStateFogStep = glGetUniformLocation(OGLRef.programFogID, "stateFogStep"); return OGLERROR_NOERR; } Render3DError OpenGLRenderer_2_0::InitFramebufferOutputProgramBindings() { OGLRenderRef &OGLRef = *this->ref; glBindAttribLocation(OGLRef.programFramebufferRGBA6665OutputID, OGLVertexAttributeID_Position, "inPosition"); glBindAttribLocation(OGLRef.programFramebufferRGBA6665OutputID, OGLVertexAttributeID_TexCoord0, "inTexCoord0"); glBindAttribLocation(OGLRef.programFramebufferRGBA8888OutputID, OGLVertexAttributeID_Position, "inPosition"); glBindAttribLocation(OGLRef.programFramebufferRGBA8888OutputID, OGLVertexAttributeID_TexCoord0, "inTexCoord0"); return OGLERROR_NOERR; } Render3DError OpenGLRenderer_2_0::InitFramebufferOutputShaderLocations() { OGLRenderRef &OGLRef = *this->ref; glUseProgram(OGLRef.programFramebufferRGBA6665OutputID); const GLint uniformTexFinalColorRGBA6665 = glGetUniformLocation(OGLRef.programFramebufferRGBA6665OutputID, "texInFragColor"); glUniform1i(uniformTexFinalColorRGBA6665, OGLTextureUnitID_FinalColor); glUseProgram(OGLRef.programFramebufferRGBA8888OutputID); const GLint uniformTexFinalColorRGBA8888 = glGetUniformLocation(OGLRef.programFramebufferRGBA8888OutputID, "texInFragColor"); glUniform1i(uniformTexFinalColorRGBA8888, OGLTextureUnitID_FinalColor); return OGLERROR_NOERR; } Render3DError OpenGLRenderer_2_0::EnableVertexAttributes() { OGLRenderRef &OGLRef = *this->ref; if (this->isVAOSupported) { glBindVertexArray(OGLRef.vaoGeometryStatesID); } else { glEnableVertexAttribArray(OGLVertexAttributeID_Position); glEnableVertexAttribArray(OGLVertexAttributeID_TexCoord0); glEnableVertexAttribArray(OGLVertexAttributeID_Color); glVertexAttribPointer(OGLVertexAttributeID_Position, 4, GL_FLOAT, GL_FALSE, sizeof(VERT), OGLRef.vtxPtrPosition); glVertexAttribPointer(OGLVertexAttributeID_TexCoord0, 2, GL_FLOAT, GL_FALSE, sizeof(VERT), OGLRef.vtxPtrTexCoord); glVertexAttribPointer(OGLVertexAttributeID_Color, 3, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(VERT), OGLRef.vtxPtrColor); } glActiveTexture(GL_TEXTURE0); return OGLERROR_NOERR; } Render3DError OpenGLRenderer_2_0::DisableVertexAttributes() { if (this->isVAOSupported) { glBindVertexArray(0); } else { glDisableVertexAttribArray(OGLVertexAttributeID_Position); glDisableVertexAttribArray(OGLVertexAttributeID_TexCoord0); glDisableVertexAttribArray(OGLVertexAttributeID_Color); } return OGLERROR_NOERR; } Render3DError OpenGLRenderer_2_0::BeginRender(const GFX3D &engine) { OGLRenderRef &OGLRef = *this->ref; if(!BEGINGL()) { return OGLERROR_BEGINGL_FAILED; } // Setup render states glUseProgram(OGLRef.programGeometryID); glUniform1i(OGLRef.uniformStateToonShadingMode, engine.renderState.shading); glUniform1i(OGLRef.uniformStateEnableAlphaTest, (engine.renderState.enableAlphaTest) ? GL_TRUE : GL_FALSE); glUniform1i(OGLRef.uniformStateEnableAntialiasing, (engine.renderState.enableAntialiasing) ? GL_TRUE : GL_FALSE); glUniform1i(OGLRef.uniformStateEnableEdgeMarking, (engine.renderState.enableEdgeMarking) ? GL_TRUE : GL_FALSE); glUniform1i(OGLRef.uniformStateUseWDepth, (engine.renderState.wbuffer) ? GL_TRUE : GL_FALSE); glUniform1f(OGLRef.uniformStateAlphaTestRef, divide5bitBy31_LUT[engine.renderState.alphaTestRef]); glBindBuffer(GL_ARRAY_BUFFER, OGLRef.vboGeometryVtxID); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, OGLRef.iboGeometryIndexID); size_t vertIndexCount = 0; GLushort *indexPtr = (GLushort *)glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY); for (size_t i = 0; i < engine.polylist->count; i++) { const POLY *thePoly = &engine.polylist->list[engine.indexlist.list[i]]; const size_t polyType = thePoly->type; for (size_t j = 0; j < polyType; j++) { const GLushort vertIndex = thePoly->vertIndexes[j]; // While we're looping through our vertices, add each vertex index to // a buffer. For GFX3D_QUADS and GFX3D_QUAD_STRIP, we also add additional // vertices here to convert them to GL_TRIANGLES, which are much easier // to work with and won't be deprecated in future OpenGL versions. indexPtr[vertIndexCount++] = vertIndex; if (thePoly->vtxFormat == GFX3D_QUADS || thePoly->vtxFormat == GFX3D_QUAD_STRIP) { if (j == 2) { indexPtr[vertIndexCount++] = vertIndex; } else if (j == 3) { indexPtr[vertIndexCount++] = thePoly->vertIndexes[0]; } } } } glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER); glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(VERT) * engine.vertlist->count, engine.vertlist); return OGLERROR_NOERR; } Render3DError OpenGLRenderer_2_0::RenderEdgeMarking(const u16 *colorTable, const bool useAntialias) { OGLRenderRef &OGLRef = *this->ref; const GLfloat alpha = (useAntialias) ? (16.0f/31.0f) : 1.0f; const GLfloat oglColor[4*8] = {divide5bitBy31_LUT[(colorTable[0] ) & 0x001F], divide5bitBy31_LUT[(colorTable[0] >> 5) & 0x001F], divide5bitBy31_LUT[(colorTable[0] >> 10) & 0x001F], alpha, divide5bitBy31_LUT[(colorTable[1] ) & 0x001F], divide5bitBy31_LUT[(colorTable[1] >> 5) & 0x001F], divide5bitBy31_LUT[(colorTable[1] >> 10) & 0x001F], alpha, divide5bitBy31_LUT[(colorTable[2] ) & 0x001F], divide5bitBy31_LUT[(colorTable[2] >> 5) & 0x001F], divide5bitBy31_LUT[(colorTable[2] >> 10) & 0x001F], alpha, divide5bitBy31_LUT[(colorTable[3] ) & 0x001F], divide5bitBy31_LUT[(colorTable[3] >> 5) & 0x001F], divide5bitBy31_LUT[(colorTable[3] >> 10) & 0x001F], alpha, divide5bitBy31_LUT[(colorTable[4] ) & 0x001F], divide5bitBy31_LUT[(colorTable[4] >> 5) & 0x001F], divide5bitBy31_LUT[(colorTable[4] >> 10) & 0x001F], alpha, divide5bitBy31_LUT[(colorTable[5] ) & 0x001F], divide5bitBy31_LUT[(colorTable[5] >> 5) & 0x001F], divide5bitBy31_LUT[(colorTable[5] >> 10) & 0x001F], alpha, divide5bitBy31_LUT[(colorTable[6] ) & 0x001F], divide5bitBy31_LUT[(colorTable[6] >> 5) & 0x001F], divide5bitBy31_LUT[(colorTable[6] >> 10) & 0x001F], alpha, divide5bitBy31_LUT[(colorTable[7] ) & 0x001F], divide5bitBy31_LUT[(colorTable[7] >> 5) & 0x001F], divide5bitBy31_LUT[(colorTable[7] >> 10) & 0x001F], alpha}; glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.fboRenderID); glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); glUseProgram(OGLRef.programEdgeMarkID); glUniform2f(OGLRef.uniformFramebufferSize, this->_framebufferWidth, this->_framebufferHeight); glUniform4fv(OGLRef.uniformStateEdgeColor, 8, oglColor); glViewport(0, 0, this->_framebufferWidth, this->_framebufferHeight); glDisable(GL_DEPTH_TEST); glDisable(GL_STENCIL_TEST); glEnable(GL_BLEND); glDisable(GL_CULL_FACE); glBindBuffer(GL_ARRAY_BUFFER, OGLRef.vboPostprocessVtxID); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, OGLRef.iboPostprocessIndexID); if (this->isVAOSupported) { glBindVertexArray(OGLRef.vaoPostprocessStatesID); } else { glEnableVertexAttribArray(OGLVertexAttributeID_Position); glEnableVertexAttribArray(OGLVertexAttributeID_TexCoord0); glVertexAttribPointer(OGLVertexAttributeID_Position, 2, GL_FLOAT, GL_FALSE, 0, 0); glVertexAttribPointer(OGLVertexAttributeID_TexCoord0, 2, GL_FLOAT, GL_FALSE, 0, (const GLvoid *)(sizeof(GLfloat) * 8)); } glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, 0); if (this->isVAOSupported) { glBindVertexArray(0); } else { glDisableVertexAttribArray(OGLVertexAttributeID_Position); glDisableVertexAttribArray(OGLVertexAttributeID_TexCoord0); } return RENDER3DERROR_NOERR; } Render3DError OpenGLRenderer_2_0::RenderFog(const u8 *densityTable, const u32 color, const u32 offset, const u8 shift, const bool alphaOnly) { OGLRenderRef &OGLRef = *this->ref; static GLfloat oglDensityTable[32]; if (!this->isFBOSupported) { return OGLERROR_FEATURE_UNSUPPORTED; } for (size_t i = 0; i < 32; i++) { oglDensityTable[i] = (densityTable[i] == 127) ? 1.0f : (GLfloat)densityTable[i] / 128.0f; } const GLfloat oglColor[4] = {divide5bitBy31_LUT[(color ) & 0x0000001F], divide5bitBy31_LUT[(color >> 5) & 0x0000001F], divide5bitBy31_LUT[(color >> 10) & 0x0000001F], divide5bitBy31_LUT[(color >> 16) & 0x0000001F]}; const GLfloat oglOffset = (GLfloat)offset / 32767.0f; const GLfloat oglFogStep = (GLfloat)(0x0400 >> shift) / 32767.0f; glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.fboPostprocessID); glUseProgram(OGLRef.programFogID); glUniform1i(OGLRef.uniformStateEnableFogAlphaOnly, (alphaOnly) ? GL_TRUE : GL_FALSE); glUniform4f(OGLRef.uniformStateFogColor, oglColor[0], oglColor[1], oglColor[2], oglColor[3]); glUniform1f(OGLRef.uniformStateFogOffset, oglOffset); glUniform1f(OGLRef.uniformStateFogStep, oglFogStep); glUniform1fv(OGLRef.uniformStateFogDensity, 32, oglDensityTable); glViewport(0, 0, this->_framebufferWidth, this->_framebufferHeight); glDisable(GL_DEPTH_TEST); glDisable(GL_STENCIL_TEST); glDisable(GL_BLEND); glDisable(GL_CULL_FACE); glBindBuffer(GL_ARRAY_BUFFER, OGLRef.vboPostprocessVtxID); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, OGLRef.iboPostprocessIndexID); if (this->isVAOSupported) { glBindVertexArray(OGLRef.vaoPostprocessStatesID); } else { glEnableVertexAttribArray(OGLVertexAttributeID_Position); glEnableVertexAttribArray(OGLVertexAttributeID_TexCoord0); glVertexAttribPointer(OGLVertexAttributeID_Position, 2, GL_FLOAT, GL_FALSE, 0, 0); glVertexAttribPointer(OGLVertexAttributeID_TexCoord0, 2, GL_FLOAT, GL_FALSE, 0, (const GLvoid *)(sizeof(GLfloat) * 8)); } glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, 0); if (this->isVAOSupported) { glBindVertexArray(0); } else { glDisableVertexAttribArray(OGLVertexAttributeID_Position); glDisableVertexAttribArray(OGLVertexAttributeID_TexCoord0); } return OGLERROR_NOERR; } Render3DError OpenGLRenderer_2_0::SetupPolygon(const POLY &thePoly) { const PolygonAttributes attr = thePoly.getAttributes(); // Set up depth test mode static const GLenum oglDepthFunc[2] = {GL_LESS, GL_EQUAL}; glDepthFunc(oglDepthFunc[attr.enableDepthEqualTest]); // Set up culling mode static const GLenum oglCullingMode[4] = {GL_FRONT_AND_BACK, GL_FRONT, GL_BACK, 0}; GLenum cullingMode = oglCullingMode[attr.surfaceCullingMode]; if (cullingMode == 0) { glDisable(GL_CULL_FACE); } else { glEnable(GL_CULL_FACE); glCullFace(cullingMode); } // Set up depth write GLboolean enableDepthWrite = GL_TRUE; // Handle shadow polys. Do this after checking for depth write, since shadow polys // can change this too. if (attr.polygonMode == POLYGON_MODE_SHADOW) { glEnable(GL_STENCIL_TEST); if (attr.polygonID == 0) { //when the polyID is zero, we are writing the shadow mask. //set stencilbuf = 1 where the shadow volume is obstructed by geometry. //do not write color or depth information. glStencilFunc(GL_NOTEQUAL, 0x80, 0xFF); glStencilOp(GL_KEEP, GL_ZERO, GL_KEEP); glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); enableDepthWrite = GL_FALSE; } else { //when the polyid is nonzero, we are drawing the shadow poly. //only draw the shadow poly where the stencilbuf==1. glStencilFunc(GL_EQUAL, 0, 0xFF); glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); enableDepthWrite = GL_TRUE; } } else if ( attr.isTranslucent || (std::find(this->_shadowPolyID.begin(), this->_shadowPolyID.end(), attr.polygonID) == this->_shadowPolyID.end()) ) { glDisable(GL_STENCIL_TEST); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); enableDepthWrite = (!attr.isTranslucent || ( (attr.polygonMode == POLYGON_MODE_DECAL) && attr.isOpaque ) || attr.enableAlphaDepthWrite) ? GL_TRUE : GL_FALSE; } else { glEnable(GL_STENCIL_TEST); glStencilFunc(GL_ALWAYS, 0x80, 0xFF); glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); enableDepthWrite = GL_TRUE; } glDepthMask(enableDepthWrite); // Set up polygon attributes OGLRenderRef &OGLRef = *this->ref; glUniform1i(OGLRef.uniformPolyMode, attr.polygonMode); glUniform1i(OGLRef.uniformPolyEnableFog, (attr.enableRenderFog) ? GL_TRUE : GL_FALSE); glUniform1f(OGLRef.uniformPolyAlpha, (!attr.isWireframe && attr.isTranslucent) ? divide5bitBy31_LUT[attr.alpha] : 1.0f); glUniform1i(OGLRef.uniformPolyID, attr.polygonID); glUniform1i(OGLRef.uniformPolyEnableDepthWrite, enableDepthWrite); glUniform1i(OGLRef.uniformPolySetNewDepthForTranslucent, (attr.enableAlphaDepthWrite) ? GL_TRUE : GL_FALSE); return OGLERROR_NOERR; } Render3DError OpenGLRenderer_2_0::SetupTexture(const POLY &thePoly, bool enableTexturing) { OGLRenderRef &OGLRef = *this->ref; const PolygonTexParams params = thePoly.getTexParams(); // Check if we need to use textures if (params.texFormat == TEXMODE_NONE || !enableTexturing) { glUniform1i(OGLRef.uniformPolyEnableTexture, GL_FALSE); return OGLERROR_NOERR; } glUniform1i(OGLRef.uniformPolyEnableTexture, GL_TRUE); TexCacheItem *newTexture = TexCache_SetTexture(TexFormat_32bpp, thePoly.texParam, thePoly.texPalette); if(newTexture != this->currTexture) { this->currTexture = newTexture; //has the ogl renderer initialized the texture? if(this->currTexture->GetDeleteCallback() == NULL) { this->currTexture->SetDeleteCallback(&texDeleteCallback, this, NULL); if(OGLRef.freeTextureIDs.empty()) { this->ExpandFreeTextures(); } this->currTexture->texid = (u64)OGLRef.freeTextureIDs.front(); OGLRef.freeTextureIDs.pop(); glBindTexture(GL_TEXTURE_2D, (GLuint)this->currTexture->texid); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, (params.enableRepeatS ? (params.enableMirroredRepeatS ? GL_MIRRORED_REPEAT : GL_REPEAT) : GL_CLAMP_TO_EDGE)); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, (params.enableRepeatT ? (params.enableMirroredRepeatT ? GL_MIRRORED_REPEAT : GL_REPEAT) : GL_CLAMP_TO_EDGE)); u32 *textureSrc = (u32 *)currTexture->decoded; size_t texWidth = currTexture->sizeX; size_t texHeight = currTexture->sizeY; if (this->_textureDeposterizeBuffer != NULL) { this->TextureDeposterize(textureSrc, texWidth, texHeight); textureSrc = this->_textureDeposterizeBuffer; } switch (this->_textureScalingFactor) { case 2: { this->TextureUpscale<2>(textureSrc, texWidth, texHeight); textureSrc = this->_textureUpscaleBuffer; break; } case 4: { this->TextureUpscale<4>(textureSrc, texWidth, texHeight); textureSrc = this->_textureUpscaleBuffer; break; } default: break; } glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texWidth, texHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, textureSrc); } else { //otherwise, just bind it glBindTexture(GL_TEXTURE_2D, (GLuint)this->currTexture->texid); } glUniform2f(OGLRef.uniformPolyTexScale, this->currTexture->invSizeX, this->currTexture->invSizeY); } return OGLERROR_NOERR; } Render3DError OpenGLRenderer_2_1::ReadBackPixels() { OGLRenderRef &OGLRef = *this->ref; if (this->_mappedFramebuffer != NULL) { glUnmapBuffer(GL_PIXEL_PACK_BUFFER); this->_mappedFramebuffer = NULL; } // Flip the framebuffer in Y to match the coordinates of OpenGL and the NDS hardware. if (this->willFlipFramebufferOnGPU) { glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, OGLRef.fboPostprocessID); glDrawBuffer(GL_COLOR_ATTACHMENT1_EXT); glBlitFramebufferEXT(0, this->_framebufferHeight, this->_framebufferWidth, 0, 0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.fboPostprocessID); glReadBuffer(GL_COLOR_ATTACHMENT1_EXT); } if (this->willConvertFramebufferOnGPU) { // Perform the color space conversion while we're still on the GPU so // that we can avoid having to do it on the CPU. const GLuint convertProgramID = (this->_outputFormat == NDSColorFormat_BGR666_Rev) ? OGLRef.programFramebufferRGBA6665OutputID : OGLRef.programFramebufferRGBA8888OutputID; glDrawBuffer(GL_COLOR_ATTACHMENT2_EXT); glUseProgram(convertProgramID); glViewport(0, 0, this->_framebufferWidth, this->_framebufferHeight); glDisable(GL_DEPTH_TEST); glDisable(GL_STENCIL_TEST); glDisable(GL_BLEND); glDisable(GL_CULL_FACE); glBindBuffer(GL_ARRAY_BUFFER, OGLRef.vboPostprocessVtxID); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, OGLRef.iboPostprocessIndexID); glBindVertexArray(OGLRef.vaoPostprocessStatesID); glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, 0); glBindVertexArray(0); // Read back the pixels. glReadBuffer(GL_COLOR_ATTACHMENT2_EXT); } // Read back the pixels in BGRA format, since legacy OpenGL devices may experience a performance // penalty if the readback is in any other format. glReadPixels(0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_BGRA, GL_UNSIGNED_BYTE, 0); // Set the read and draw target buffers back to color attachment 0, which is always the default. if (this->willFlipFramebufferOnGPU || this->willConvertFramebufferOnGPU) { glReadBuffer(GL_COLOR_ATTACHMENT0_EXT); glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); } this->_pixelReadNeedsFinish = true; return OGLERROR_NOERR; } Render3DError OpenGLRenderer_2_1::RenderFinish() { if (!this->_renderNeedsFinish || !this->_pixelReadNeedsFinish) { return OGLERROR_NOERR; } FragmentColor *framebufferMain = (this->_willFlushFramebufferRGBA6665) ? GPU->GetEngineMain()->Get3DFramebufferRGBA6665() : NULL; u16 *framebufferRGBA5551 = (this->_willFlushFramebufferRGBA5551) ? GPU->GetEngineMain()->Get3DFramebufferRGBA5551() : NULL; if ( (framebufferMain != NULL) || (framebufferRGBA5551 != NULL) ) { if(!BEGINGL()) { return OGLERROR_BEGINGL_FAILED; } this->_mappedFramebuffer = (FragmentColor *__restrict)glMapBuffer(GL_PIXEL_PACK_BUFFER, GL_READ_ONLY); this->FlushFramebuffer(this->_mappedFramebuffer, framebufferMain, framebufferRGBA5551); ENDGL(); } this->_pixelReadNeedsFinish = false; return OGLERROR_NOERR; } desmume/src/libretro-common/include/lists/dir_list.h000664 001750 001750 00000004774 12755534123 024026 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2016 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (dir_list.h). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef __LIBRETRO_SDK_DIR_LIST_H #define __LIBRETRO_SDK_DIR_LIST_H #include #include RETRO_BEGIN_DECLS /** * dir_list_new: * @dir : directory path. * @ext : allowed extensions of file directory entries to include. * @include_dirs : include directories as part of the finished directory listing? * @include_compressed : include compressed files, even when not part of ext. * * Create a directory listing. * * Returns: pointer to a directory listing of type 'struct string_list *' on success, * NULL in case of error. Has to be freed manually. **/ struct string_list *dir_list_new(const char *dir, const char *ext, bool include_dirs, bool include_compressed); /** * dir_list_sort: * @list : pointer to the directory listing. * @dir_first : move the directories in the listing to the top? * * Sorts a directory listing. * **/ void dir_list_sort(struct string_list *list, bool dir_first); /** * dir_list_free: * @list : pointer to the directory listing * * Frees a directory listing. * **/ void dir_list_free(struct string_list *list); RETRO_END_DECLS #endif desmume/src/utils/libfat/libfat_pc.h000664 001750 001750 00000005411 12755534123 020635 0ustar00sergiosergio000000 000000 #ifndef _LIBFAT_PC_H #define _LIBFAT_PC_H #ifdef LIBFAT_PC #include #include #include #ifdef _MSC_VER #define ENOTSUP 0 #define EOVERFLOW 0 #include #include #define strcasecmp(x,y) _stricmp(x,y) #define strncasecmp(x, y, l) strnicmp(x, y, l) #define S_IRUSR S_IREAD #define S_IRGRP S_IREAD #define S_IROTH S_IREAD #define S_IWUSR S_IWRITE #define S_IWGRP S_IWRITE #define S_IWOTH S_IWRITE #else // (!_MSC_VER) #include #ifdef _WIN32 #ifndef S_IRGRP #define S_IRGRP S_IREAD #endif #ifndef S_IROTH #define S_IROTH S_IREAD #endif #ifndef S_IWGRP #define S_IWGRP S_IWRITE #endif #ifndef S_IWOTH #define S_IWOTH S_IWRITE #endif #endif #endif //_MSC_VER #if !defined(PSP) && !defined(VITA) struct _reent { intptr_t _errno; }; #endif #ifdef __APPLE__ typedef __darwin_mode_t mode_t; #elif defined(_MSC_VER) typedef uint32_t mode_t; #else #include #endif struct DIR_ITER { void* dirStruct; }; struct devoptab_t { const char *name; int structSize; intptr_t (*open_r)(struct _reent *r, void *fileStruct, const char *path, int flags, int mode); intptr_t (*close_r)(struct _reent *r, intptr_t fd); ssize_t (*write_r)(struct _reent *r, intptr_t fd, const char *ptr, size_t len); ssize_t (*read_r)(struct _reent *r, intptr_t fd, char *ptr, size_t len); off_t (*seek_r)(struct _reent *r, intptr_t fd, off_t pos, int dir); int (*fstat_r)(struct _reent *r, intptr_t fd, struct stat *st); int (*stat_r)(struct _reent *r, const char *file, struct stat *st); int (*link_r)(struct _reent *r, const char *existing, const char *newLink); int (*unlink_r)(struct _reent *r, const char *name); int (*chdir_r)(struct _reent *r, const char *name); int (*rename_r) (struct _reent *r, const char *oldName, const char *newName); int (*mkdir_r) (struct _reent *r, const char *path, int mode); int dirStateSize; struct DIR_ITER* (*diropen_r)(struct _reent *r, struct DIR_ITER *dirState, const char *path); int (*dirreset_r)(struct _reent *r, struct DIR_ITER *dirState); int (*dirnext_r)(struct _reent *r, struct DIR_ITER *dirState, char *filename, struct stat *filestat); int (*dirclose_r)(struct _reent *r, struct DIR_ITER *dirState); #ifndef LIBFAT_PC int (*statvfs_r)(struct _reent *r, const char *path, struct statvfs *buf); #endif int (*ftruncate_r)(struct _reent *r, intptr_t fd, off_t len); int (*fsync_r)(struct _reent *r, intptr_t fd); void *deviceData; int (*chmod_r)(struct _reent *r, const char *path, mode_t mode); int (*fchmod_r)(struct _reent *r, int fd, mode_t mode); }; struct devoptab_t* GetDeviceOpTab(const char* name); #define _ATTR_WEAK_ #endif //LIBFAT_PC #endif //_LIBFAT_PC_H desmume/src/libretro-common/formats/json/000700 001750 001750 00000000000 12756420131 021651 5ustar00sergiosergio000000 000000 desmume/src/libretro-common/compat/compat_strcasestr.c000664 001750 001750 00000004177 12755534123 024447 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2015 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (compat_strcasestr.c). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include #include #include /* Pretty much strncasecmp. */ static int casencmp(const char *a, const char *b, size_t n) { size_t i; for (i = 0; i < n; i++) { int a_lower = tolower(a[i]); int b_lower = tolower(b[i]); if (a_lower != b_lower) return a_lower - b_lower; } return 0; } char *strcasestr_retro__(const char *haystack, const char *needle) { size_t i, hay_len, needle_len, search_off; hay_len = strlen(haystack); needle_len = strlen(needle); if (needle_len > hay_len) return NULL; search_off = hay_len - needle_len; for (i = 0; i <= search_off; i++) if (!casencmp(haystack + i, needle, needle_len)) return (char*)haystack + i; return NULL; } desmume/src/libretro-common/gfx/000700 001750 001750 00000000000 12756420131 020011 5ustar00sergiosergio000000 000000 desmume/src/armcpu.cpp000664 001750 001750 00000042753 12755534123 016145 0ustar00sergiosergio000000 000000 /* Copyright (C) 2006 yopyop Copyright (C) 2009-2015 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the this software. If not, see . */ #include #include #include #include #include "armcpu.h" #include "common.h" #include "instructions.h" #include "cp15.h" #include "bios.h" #ifdef DEBUG #include "debug.h" #include "Disassembler.h" #endif #include "NDSSystem.h" #include "MMU_timing.h" #include "utils/bits.h" #ifdef HAVE_JIT #include "arm_jit.h" #endif template static u32 armcpu_prefetch(); FORCEINLINE u32 armcpu_prefetch(armcpu_t *armcpu) { if(armcpu->proc_ID==0) return armcpu_prefetch<0>(); else return armcpu_prefetch<1>(); } armcpu_t NDS_ARM7; armcpu_t NDS_ARM9; #define SWAP(a, b, c) do \ { \ c=a; \ a=b; \ b=c; \ } \ while(0) #define STALLED_CYCLE_COUNT 10 static void stall_cpu( void *instance) { armcpu_t *armcpu = (armcpu_t *)instance; printf("STALL\n"); armcpu->stalled = 1; } static void unstall_cpu( void *instance) { armcpu_t *armcpu = (armcpu_t *)instance; printf("UNSTALL\n"); 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; } static u32 read_cpu_reg( void *instance, u32 reg_num) { armcpu_t *armcpu = (armcpu_t *)instance; if ( reg_num <= 14) { return armcpu->R[reg_num]; } else if ( reg_num == 15) { return armcpu->instruct_adr; } else if ( reg_num == 16) { //CPSR return armcpu->CPSR.val; } return 0; } 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 */ } } int armcpu_new( armcpu_t *armcpu, u32 id) { armcpu->proc_ID = id; armcpu->stalled = 0; armcpu->base_mem_if.prefetch32 = NULL; armcpu->base_mem_if.prefetch16 = NULL; armcpu->base_mem_if.read8 = NULL; armcpu->base_mem_if.read16 = NULL; armcpu->base_mem_if.read32 = NULL; armcpu->base_mem_if.write8 = NULL; armcpu->base_mem_if.write16 = NULL; armcpu->base_mem_if.write32 = NULL; armcpu->base_mem_if.data = NULL; armcpu->SetControlInterface(&arm_default_ctrl_iface); armcpu->SetControlInterfaceData(armcpu); armcpu->SetCurrentMemoryInterface(NULL); armcpu->SetCurrentMemoryInterfaceData(NULL); armcpu->post_ex_fn = NULL; armcpu->post_ex_fn_data = NULL; armcpu_init(armcpu, 0); return 0; } void armcpu_t::SetControlInterface(const armcpu_ctrl_iface *theControlInterface) { this->ctrl_iface = *theControlInterface; } armcpu_ctrl_iface* armcpu_t::GetControlInterface() { return &this->ctrl_iface; } void armcpu_t::SetControlInterfaceData(void *theData) { this->ctrl_iface.data = theData; } void* armcpu_t::GetControlInterfaceData() { return this->ctrl_iface.data; } void armcpu_t::SetCurrentMemoryInterface(armcpu_memory_iface *theMemoryInterface) { this->mem_if = theMemoryInterface; } armcpu_memory_iface* armcpu_t::GetCurrentMemoryInterface() { return this->mem_if; } void armcpu_t::SetCurrentMemoryInterfaceData(void *theData) { if (this->mem_if != NULL) { this->mem_if->data = theData; } } void* armcpu_t::GetCurrentMemoryInterfaceData() { return (this->mem_if != NULL) ? this->mem_if->data : NULL; } void armcpu_t::SetBaseMemoryInterface(const armcpu_memory_iface *theMemInterface) { this->base_mem_if = *theMemInterface; } armcpu_memory_iface* armcpu_t::GetBaseMemoryInterface() { return &this->base_mem_if; } void armcpu_t::SetBaseMemoryInterfaceData(void *theData) { this->base_mem_if.data = theData; } void* armcpu_t::GetBaseMemoryInterfaceData() { return this->base_mem_if.data; } void armcpu_t::ResetMemoryInterfaceToBase() { this->SetCurrentMemoryInterface(this->GetBaseMemoryInterface()); this->SetCurrentMemoryInterfaceData(this->GetBaseMemoryInterfaceData()); } //call this whenever CPSR is changed (other than CNVZQ or T flags); interrupts may need to be unleashed void armcpu_t::changeCPSR() { //but all it does is give them a chance to unleash by forcing an immediate reschedule //TODO - we could actually set CPSR through here and look for a change in the I bit //that would be a little optimization as well as a safety measure if we prevented setting CPSR directly NDS_Reschedule(); } void armcpu_init(armcpu_t *armcpu, u32 adr) { #if defined(_M_X64) || defined(__x86_64__) memcpy(&armcpu->cond_table[0], &arm_cond_table[0], sizeof(arm_cond_table)); #endif armcpu->LDTBit = (armcpu->proc_ID==0); //set ARMv5 style bit--different for each processor armcpu->intVector = 0xFFFF0000 * (armcpu->proc_ID==0); armcpu->waitIRQ = FALSE; armcpu->halt_IE_and_IF = FALSE; armcpu->intrWaitARM_state = 0; for(int i = 0; i < 16; ++i) armcpu->R[i] = 0; 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; //do something sensible when booting up to a thumb address armcpu->next_instruction = adr & ~1; armcpu->CPSR.bits.T = BIT0(adr); armcpu_prefetch(armcpu); } 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 : printf("switchMode: WRONG mode %02X\n",mode); break; } armcpu->CPSR.bits.mode = mode & 0x1F; armcpu->changeCPSR(); return oldmode; } u32 armcpu_Wait4IRQ(armcpu_t *cpu) { cpu->waitIRQ = TRUE; cpu->halt_IE_and_IF = TRUE; return 1; } template FORCEINLINE static u32 armcpu_prefetch() { armcpu_t* const armcpu = &ARMPROC; u32 curInstruction = armcpu->next_instruction; if(armcpu->CPSR.bits.T == 0) { curInstruction &= 0xFFFFFFFC; //please don't change this to 0x0FFFFFFC -- the NDS will happily run on 0xF******* addresses all day long //please note that we must setup R[15] before reading the instruction since there is a protection //which prevents PC > 0x3FFF from reading the bios region armcpu->instruct_adr = curInstruction; armcpu->next_instruction = curInstruction + 4; armcpu->R[15] = curInstruction + 8; armcpu->instruction = _MMU_read32(curInstruction); return MMU_codeFetchCycles(curInstruction); } curInstruction &= 0xFFFFFFFE; //please don't change this to 0x0FFFFFFE -- the NDS will happily run on 0xF******* addresses all day long //please note that we must setup R[15] before reading the instruction since there is a protection //which prevents PC > 0x3FFF from reading the bios region armcpu->instruct_adr = curInstruction; armcpu->next_instruction = curInstruction + 2; armcpu->R[15] = curInstruction + 4; armcpu->instruction = _MMU_read16(curInstruction); if(PROCNUM==0) { // arm9 fetches 2 instructions at a time in thumb mode if(!(curInstruction == armcpu->instruct_adr + 2 && (curInstruction & 2))) return MMU_codeFetchCycles(curInstruction); else return 0; } return MMU_codeFetchCycles(curInstruction); } #if 0 /* not used */ 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)) #endif //TODO - merge with armcpu_irqException? //http://www.ethernut.de/en/documents/arm-exceptions.html //http://docs.google.com/viewer?a=v&q=cache:V4ht1YkxprMJ:www.cs.nctu.edu.tw/~wjtsai/EmbeddedSystemDesign/Ch3-1.pdf+arm+exception+handling&hl=en&gl=us&pid=bl&srcid=ADGEEShx9VTHbUhWdDOrTVRzLkcCsVfJiijncNDkkgkrlJkLa7D0LCpO8fQ_hhU3DTcgZh9rcZWWQq4TYhhCovJ625h41M0ZUX3WGasyzWQFxYzDCB-VS6bsUmpoJnRxAc-bdkD0qmsu&sig=AHIEtbR9VHvDOCRmZFQDUVwy53iJDjoSPQ void armcpu_exception(armcpu_t *cpu, u32 number) { Mode cpumode = USR; switch(number) { case EXCEPTION_RESET: cpumode = SVC; break; case EXCEPTION_UNDEFINED_INSTRUCTION: cpumode = UND; break; case EXCEPTION_SWI: cpumode = SVC; break; case EXCEPTION_PREFETCH_ABORT: cpumode = ABT; break; case EXCEPTION_DATA_ABORT: cpumode = ABT; break; case EXCEPTION_RESERVED_0x14: emu_halt(); break; case EXCEPTION_IRQ: cpumode = IRQ; break; case EXCEPTION_FAST_IRQ: cpumode = FIQ; break; } Status_Reg tmp = cpu->CPSR; armcpu_switchMode(cpu, cpumode); //enter new mode cpu->R[14] = cpu->next_instruction; cpu->SPSR = tmp; //save old CPSR as new SPSR cpu->CPSR.bits.T = 0; //handle as ARM32 code cpu->CPSR.bits.I = 1; cpu->changeCPSR(); cpu->R[15] = cpu->intVector + number; cpu->next_instruction = cpu->R[15]; printf("armcpu_exception!\n"); //extern bool dolog; //dolog=true; //HOW DOES THIS WORTK WITHOUT A PREFETCH, LIKE IRQ BELOW? //I REALLY WISH WE DIDNT PREFETCH BEFORE EXECUTING } BOOL armcpu_irqException(armcpu_t *armcpu) { Status_Reg tmp; tmp = armcpu->CPSR; armcpu_switchMode(armcpu, IRQ); armcpu->R[14] = armcpu->instruct_adr + 4; armcpu->SPSR = tmp; armcpu->CPSR.bits.T = 0; armcpu->CPSR.bits.I = 1; armcpu->next_instruction = armcpu->intVector + 0x18; armcpu->waitIRQ = 0; //must retain invariant of having next instruction to be executed prefetched //(yucky) armcpu_prefetch(armcpu); return TRUE; } u32 TRAPUNDEF(armcpu_t* cpu) { #ifdef DEBUG INFO("ARM%c: Undefined instruction: 0x%08X PC=0x%08X\n", cpu->proc_ID?'7':'9', cpu->instruction, cpu->instruct_adr); #endif if (((cpu->intVector != 0) ^ (cpu->proc_ID == ARMCPU_ARM9))) { armcpu_exception(&NDS_ARM9,EXCEPTION_UNDEFINED_INSTRUCTION); return 4; } else { emu_halt(); return 4; } } template u32 armcpu_exec() { // Usually, fetching and executing are processed parallelly. // So this function stores the cycles of each process to // the variables below, and returns appropriate cycle count. u32 cFetch = 0; u32 cExecute = 0; //this assert is annoying. but sometimes it is handy. //assert(ARMPROC.instruct_adr!=0x00000000); //#ifdef DEVELOPER #if 0 if ((((ARMPROC.instruct_adr & 0x0F000000) == 0x0F000000) && (PROCNUM == 0)) || (((ARMPROC.instruct_adr & 0x0F000000) == 0x00000000) && (PROCNUM == 1))) { switch (ARMPROC.instruct_adr & 0xFFFF) { case 0x00000000: printf("BIOS%c: Reset!!!\n", PROCNUM?'7':'9'); emu_halt(); break; case 0x00000004: printf("BIOS%c: Undefined instruction\n", PROCNUM?'7':'9'); //emu_halt(); break; case 0x00000008: //printf("BIOS%c: SWI\n", PROCNUM?'7':'9'); break; case 0x0000000C: printf("BIOS%c: Prefetch Abort!!!\n", PROCNUM?'7':'9'); //emu_halt(); break; case 0x00000010: //printf("BIOS%c: Data Abort!!!\n", PROCNUM?'7':'9'); //emu_halt(); break; case 0x00000014: printf("BIOS%c: Reserved!!!\n", PROCNUM?'7':'9'); break; case 0x00000018: //printf("BIOS%c: IRQ\n", PROCNUM?'7':'9'); break; case 0x0000001C: printf("BIOS%c: Fast IRQ\n", PROCNUM?'7':'9'); break; } } #endif //cFetch = armcpu_prefetch(&ARMPROC); //printf("%d: %08X\n",PROCNUM,ARMPROC.instruct_adr); if(ARMPROC.CPSR.bits.T == 0) { if( CONDITION(ARMPROC.instruction) == 0x0E //fast path for unconditional instructions || (TEST_COND(CONDITION(ARMPROC.instruction), CODE(ARMPROC.instruction), ARMPROC.CPSR)) //handles any condition ) { #ifdef DEVELOPER DEBUG_statistics.instructionHits[PROCNUM].arm[INSTRUCTION_INDEX(ARMPROC.instruction)]++; #endif cExecute = arm_instructions_set[PROCNUM][INSTRUCTION_INDEX(ARMPROC.instruction)](ARMPROC.instruction); } else cExecute = 1; // If condition=false: 1S cycle cFetch = armcpu_prefetch(); return MMU_fetchExecuteCycles(cExecute, cFetch); } #ifdef DEVELOPER DEBUG_statistics.instructionHits[PROCNUM].thumb[ARMPROC.instruction>>6]++; #endif cExecute = thumb_instructions_set[PROCNUM][ARMPROC.instruction>>6](ARMPROC.instruction); cFetch = armcpu_prefetch(); return MMU_fetchExecuteCycles(cExecute, cFetch); } //these templates needed to be instantiated manually template u32 armcpu_exec<0>(); template u32 armcpu_exec<1>(); #ifdef HAVE_JIT void arm_jit_sync() { NDS_ARM7.next_instruction = NDS_ARM7.instruct_adr; NDS_ARM9.next_instruction = NDS_ARM9.instruct_adr; armcpu_prefetch<0>(); armcpu_prefetch<1>(); } template u32 armcpu_exec() { if (jit) { ARMPROC.instruct_adr &= ARMPROC.CPSR.bits.T?0xFFFFFFFE:0xFFFFFFFC; ArmOpCompiled f = (ArmOpCompiled)JIT_COMPILED_FUNC(ARMPROC.instruct_adr, PROCNUM); return f ? f() : arm_jit_compile(); } return armcpu_exec(); } template u32 armcpu_exec<0,false>(); template u32 armcpu_exec<0,true>(); template u32 armcpu_exec<1,false>(); template u32 armcpu_exec<1,true>(); #endif void setIF(int PROCNUM, u32 flag) { //don't set generated bits!!! assert(!(flag&0x00200000)); MMU.reg_IF_bits[PROCNUM] |= flag; NDS_Reschedule(); } const armcpu_ctrl_iface arm_default_ctrl_iface = { stall_cpu, unstall_cpu, read_cpu_reg, set_cpu_reg, install_post_exec_fn, remove_post_exec_fn, NULL }; desmume/src/utils/AsmJit/x86/x86operand.h000664 001750 001750 00000217375 12755534123 021301 0ustar00sergiosergio000000 000000 // [AsmJit] // Complete JIT Assembler for C++ Language. // // [License] // Zlib - See COPYING file in this package. // [Guard] #ifndef _ASMJIT_X86_X86OPERAND_H #define _ASMJIT_X86_X86OPERAND_H // [Dependencies - AsmJit] #include "../core/defs.h" #include "../core/operand.h" #include "../x86/x86defs.h" namespace AsmJit { // ============================================================================ // [Forward Declarations] // ============================================================================ struct GpReg; struct GpVar; struct Mem; struct MmReg; struct MmVar; struct Var; struct X87Reg; struct X87Var; struct XmmReg; struct XmmVar; struct SegmentReg; //! @addtogroup AsmJit_X86 //! @{ // ============================================================================ // [AsmJit::MmData] // ============================================================================ //! @brief Structure used for MMX specific data (64-bit). //! //! This structure can be used to load / store data from / to MMX register. union MmData { // -------------------------------------------------------------------------- // [Methods] // -------------------------------------------------------------------------- //! @brief Set all eight signed 8-bit integers. inline void setSB( int8_t x0, int8_t x1, int8_t x2, int8_t x3, int8_t x4, int8_t x5, int8_t x6, int8_t x7) { sb[0] = x0; sb[1] = x1; sb[2] = x2; sb[3] = x3; sb[4] = x4; sb[5] = x5; sb[6] = x6; sb[7] = x7; } //! @brief Set all eight unsigned 8-bit integers. inline void setUB( uint8_t x0, uint8_t x1, uint8_t x2, uint8_t x3, uint8_t x4, uint8_t x5, uint8_t x6, uint8_t x7) { ub[0] = x0; ub[1] = x1; ub[2] = x2; ub[3] = x3; ub[4] = x4; ub[5] = x5; ub[6] = x6; ub[7] = x7; } //! @brief Set all four signed 16-bit integers. inline void setSW( int16_t x0, int16_t x1, int16_t x2, int16_t x3) { sw[0] = x0; sw[1] = x1; sw[2] = x2; sw[3] = x3; } //! @brief Set all four unsigned 16-bit integers. inline void setUW( uint16_t x0, uint16_t x1, uint16_t x2, uint16_t x3) { uw[0] = x0; uw[1] = x1; uw[2] = x2; uw[3] = x3; } //! @brief Set all two signed 32-bit integers. inline void setSD( int32_t x0, int32_t x1) { sd[0] = x0; sd[1] = x1; } //! @brief Set all two unsigned 32-bit integers. inline void setUD( uint32_t x0, uint32_t x1) { ud[0] = x0; ud[1] = x1; } //! @brief Set signed 64-bit integer. inline void setSQ( int64_t x0) { sq[0] = x0; } //! @brief Set unsigned 64-bit integer. inline void setUQ( uint64_t x0) { uq[0] = x0; } //! @brief Set all two SP-FP values. inline void setSF( float x0, float x1) { sf[0] = x0; sf[1] = x1; } // -------------------------------------------------------------------------- // [Members] // -------------------------------------------------------------------------- //! @brief Array of eight signed 8-bit integers. int8_t sb[8]; //! @brief Array of eight unsigned 8-bit integers. uint8_t ub[8]; //! @brief Array of four signed 16-bit integers. int16_t sw[4]; //! @brief Array of four unsigned 16-bit integers. uint16_t uw[4]; //! @brief Array of two signed 32-bit integers. int32_t sd[2]; //! @brief Array of two unsigned 32-bit integers. uint32_t ud[2]; //! @brief Array of one signed 64-bit integer. int64_t sq[1]; //! @brief Array of one unsigned 64-bit integer. uint64_t uq[1]; //! @brief Array of two SP-FP values. float sf[2]; }; // ============================================================================ // [AsmJit::XmmData] // ============================================================================ //! @brief Structure used for SSE specific data (128-bit). //! //! This structure can be used to load / store data from / to SSE register. //! //! @note Always align SSE data to 16-bytes. union XmmData { // -------------------------------------------------------------------------- // [Methods] // -------------------------------------------------------------------------- //! @brief Set all sixteen signed 8-bit integers. inline void setSB( int8_t x0, int8_t x1, int8_t x2 , int8_t x3 , int8_t x4 , int8_t x5 , int8_t x6 , int8_t x7 , int8_t x8, int8_t x9, int8_t x10, int8_t x11, int8_t x12, int8_t x13, int8_t x14, int8_t x15) { sb[0] = x0; sb[1] = x1; sb[ 2] = x2 ; sb[3 ] = x3 ; sb[4 ] = x4 ; sb[5 ] = x5 ; sb[6 ] = x6 ; sb[7 ] = x7 ; sb[8] = x8; sb[9] = x9; sb[10] = x10; sb[11] = x11; sb[12] = x12; sb[13] = x13; sb[14] = x14; sb[15] = x15; } //! @brief Set all sixteen unsigned 8-bit integers. inline void setUB( uint8_t x0, uint8_t x1, uint8_t x2 , uint8_t x3 , uint8_t x4 , uint8_t x5 , uint8_t x6 , uint8_t x7 , uint8_t x8, uint8_t x9, uint8_t x10, uint8_t x11, uint8_t x12, uint8_t x13, uint8_t x14, uint8_t x15) { ub[0] = x0; ub[1] = x1; ub[ 2] = x2 ; ub[3 ] = x3 ; ub[4 ] = x4 ; ub[5 ] = x5 ; ub[6 ] = x6 ; ub[7 ] = x7 ; ub[8] = x8; ub[9] = x9; ub[10] = x10; ub[11] = x11; ub[12] = x12; ub[13] = x13; ub[14] = x14; ub[15] = x15; } //! @brief Set all eight signed 16-bit integers. inline void setSW( int16_t x0, int16_t x1, int16_t x2, int16_t x3, int16_t x4, int16_t x5, int16_t x6, int16_t x7) { sw[0] = x0; sw[1] = x1; sw[2] = x2; sw[3] = x3; sw[4] = x4; sw[5] = x5; sw[6] = x6; sw[7] = x7; } //! @brief Set all eight unsigned 16-bit integers. inline void setUW( uint16_t x0, uint16_t x1, uint16_t x2, uint16_t x3, uint16_t x4, uint16_t x5, uint16_t x6, uint16_t x7) { uw[0] = x0; uw[1] = x1; uw[2] = x2; uw[3] = x3; uw[4] = x4; uw[5] = x5; uw[6] = x6; uw[7] = x7; } //! @brief Set all four signed 32-bit integers. inline void setSD( int32_t x0, int32_t x1, int32_t x2, int32_t x3) { sd[0] = x0; sd[1] = x1; sd[2] = x2; sd[3] = x3; } //! @brief Set all four unsigned 32-bit integers. inline void setUD( uint32_t x0, uint32_t x1, uint32_t x2, uint32_t x3) { ud[0] = x0; ud[1] = x1; ud[2] = x2; ud[3] = x3; } //! @brief Set all two signed 64-bit integers. inline void setSQ( int64_t x0, int64_t x1) { sq[0] = x0; sq[1] = x1; } //! @brief Set all two unsigned 64-bit integers. inline void setUQ( uint64_t x0, uint64_t x1) { uq[0] = x0; uq[1] = x1; } //! @brief Set all four SP-FP floats. inline void setSF( float x0, float x1, float x2, float x3) { sf[0] = x0; sf[1] = x1; sf[2] = x2; sf[3] = x3; } //! @brief Set all two DP-FP floats. inline void setDF( double x0, double x1) { df[0] = x0; df[1] = x1; } // -------------------------------------------------------------------------- // [Members] // -------------------------------------------------------------------------- //! @brief Array of sixteen signed 8-bit integers. int8_t sb[16]; //! @brief Array of sixteen unsigned 8-bit integers. uint8_t ub[16]; //! @brief Array of eight signed 16-bit integers. int16_t sw[8]; //! @brief Array of eight unsigned 16-bit integers. uint16_t uw[8]; //! @brief Array of four signed 32-bit integers. int32_t sd[4]; //! @brief Array of four unsigned 32-bit integers. uint32_t ud[4]; //! @brief Array of two signed 64-bit integers. int64_t sq[2]; //! @brief Array of two unsigned 64-bit integers. uint64_t uq[2]; //! @brief Array of four 32-bit single precision floating points. float sf[4]; //! @brief Array of two 64-bit double precision floating points. double df[2]; }; // ============================================================================ // [AsmJit::GpReg] // ============================================================================ //! @brief General purpose register. //! //! This class is for all general purpose registers (64, 32, 16 and 8-bit). struct GpReg : public Reg { // -------------------------------------------------------------------------- // [Construction / Destruction] // -------------------------------------------------------------------------- //! @brief Create non-initialized general purpose register. inline GpReg() : Reg(kInvalidValue, 0) {} //! @brief Create a reference to @a other general purpose register. inline GpReg(const GpReg& other) : Reg(other) {} #if !defined(ASMJIT_NODOC) inline GpReg(const _DontInitialize& dontInitialize) : Reg(dontInitialize) {} inline GpReg(const _Initialize&, uint32_t code) : Reg(code, static_cast(1U << ((code & kRegTypeMask) >> 12))) {} #endif // ASMJIT_NODOC // -------------------------------------------------------------------------- // [Reg Specific] // -------------------------------------------------------------------------- //! @brief Set register code to @a code. inline GpReg& setCode(uint32_t code) { _reg.code = code; return *this; } //! @brief Set register size to @a size. inline GpReg& setSize(uint32_t size) { _reg.size = static_cast(size); return *this; } // -------------------------------------------------------------------------- // [GpReg Specific] // -------------------------------------------------------------------------- //! @brief Get whether the general purpose register is BYTE (8-bit) type. inline bool isGpb() const { return (_reg.code & kRegTypeMask) <= kX86RegTypeGpbHi; } //! @brief Get whether the general purpose register is LO-BYTE (8-bit) type. inline bool isGpbLo() const { return (_reg.code & kRegTypeMask) == kX86RegTypeGpbLo; } //! @brief Get whether the general purpose register is HI-BYTE (8-bit) type. inline bool isGpbHi() const { return (_reg.code & kRegTypeMask) == kX86RegTypeGpbHi; } //! @brief Get whether the general purpose register is WORD (16-bit) type. inline bool isGpw() const { return (_reg.code & kRegTypeMask) == kX86RegTypeGpw; } //! @brief Get whether the general purpose register is DWORD (32-bit) type. //! //! This is default type for 32-bit platforms. inline bool isGpd() const { return (_reg.code & kRegTypeMask) == kX86RegTypeGpd; } //! @brief Get whether the general purpose register is QWORD (64-bit) type. //! //! This is default type for 64-bit platforms. inline bool isGpq() const { return (_reg.code & kRegTypeMask) == kX86RegTypeGpq; } // -------------------------------------------------------------------------- // [Operator Overload] // -------------------------------------------------------------------------- #if !defined(ASMJIT_NODOC) inline GpReg& operator=(const GpReg& other) { _copy(other); return *this; } inline bool operator==(const GpReg& other) const { return getRegCode() == other.getRegCode(); } inline bool operator!=(const GpReg& other) const { return getRegCode() != other.getRegCode(); } #endif // ASMJIT_NODOC }; // ============================================================================ // [AsmJit::X87Reg] // ============================================================================ //! @brief 80-bit x87 floating point register. //! //! To create instance of x87 register, use @c st() function. struct X87Reg : public Reg { // -------------------------------------------------------------------------- // [Construction / Destruction] // -------------------------------------------------------------------------- //! @brief Create non-initialized x87 register. inline X87Reg() : Reg(kInvalidValue, 10) {} //! @brief Create a reference to @a other x87 register. inline X87Reg(const X87Reg& other) : Reg(other) {} #if !defined(ASMJIT_NODOC) inline X87Reg(const _DontInitialize& dontInitialize) : Reg(dontInitialize) {} inline X87Reg(const _Initialize&, uint32_t code) : Reg(code | kX86RegTypeX87, 10) {} #endif // ASMJIT_NODOC // -------------------------------------------------------------------------- // [Reg Specific] // -------------------------------------------------------------------------- //! @brief Set register code to @a code. inline X87Reg& setCode(uint32_t code) { _reg.code = code; return *this; } //! @brief Set register size to @a size. inline X87Reg& setSize(uint32_t size) { _reg.size = static_cast(size); return *this; } // -------------------------------------------------------------------------- // [Operator Overload] // -------------------------------------------------------------------------- #if !defined(ASMJIT_NODOC) inline X87Reg& operator=(const X87Reg& other) { _copy(other); return *this; } inline bool operator==(const X87Reg& other) const { return getRegCode() == other.getRegCode(); } inline bool operator!=(const X87Reg& other) const { return getRegCode() != other.getRegCode(); } #endif // ASMJIT_NODOC }; // ============================================================================ // [AsmJit::MmReg] // ============================================================================ //! @brief 64-bit MMX register. struct MmReg : public Reg { // -------------------------------------------------------------------------- // [Construction / Destruction] // -------------------------------------------------------------------------- //! @brief Create non-initialized MM register. inline MmReg() : Reg(kInvalidValue, 8) {} //! @brief Create a reference to @a other MM register. inline MmReg(const MmReg& other) : Reg(other) {} #if !defined(ASMJIT_NODOC) inline MmReg(const _DontInitialize& dontInitialize) : Reg(dontInitialize) {} inline MmReg(const _Initialize&, uint32_t code) : Reg(code, 8) {} #endif // ASMJIT_NODOC // -------------------------------------------------------------------------- // [Reg Specific] // -------------------------------------------------------------------------- //! @brief Set register code to @a code. inline MmReg& setCode(uint32_t code) { _reg.code = code; return *this; } //! @brief Set register size to @a size. inline MmReg& setSize(uint32_t size) { _reg.size = static_cast(size); return *this; } // -------------------------------------------------------------------------- // [Operator Overload] // -------------------------------------------------------------------------- #if !defined(ASMJIT_NODOC) inline MmReg& operator=(const MmReg& other) { _copy(other); return *this; } inline bool operator==(const MmReg& other) const { return getRegCode() == other.getRegCode(); } inline bool operator!=(const MmReg& other) const { return getRegCode() != other.getRegCode(); } #endif // ASMJIT_NODOC }; // ============================================================================ // [AsmJit::XmmReg] // ============================================================================ //! @brief 128-bit SSE register. struct XmmReg : public Reg { // -------------------------------------------------------------------------- // [Construction / Destruction] // -------------------------------------------------------------------------- //! @brief Create non-initialized XMM register. inline XmmReg() : Reg(kInvalidValue, 16) {} //! @brief Create a reference to @a other XMM register. inline XmmReg(const _Initialize&, uint32_t code) : Reg(code, 16) {} #if !defined(ASMJIT_NODOC) inline XmmReg(const _DontInitialize& dontInitialize) : Reg(dontInitialize) {} inline XmmReg(const XmmReg& other) : Reg(other) {} #endif // ASMJIT_NODOC // -------------------------------------------------------------------------- // [Reg Specific] // -------------------------------------------------------------------------- //! @brief Set register code to @a code. inline XmmReg& setCode(uint32_t code) { _reg.code = code; return *this; } //! @brief Set register size to @a size. inline XmmReg& setSize(uint32_t size) { _reg.size = static_cast(size); return *this; } // -------------------------------------------------------------------------- // [Operator Overload] // -------------------------------------------------------------------------- #if !defined(ASMJIT_NODOC) inline XmmReg& operator=(const XmmReg& other) { _copy(other); return *this; } inline bool operator==(const XmmReg& other) const { return getRegCode() == other.getRegCode(); } inline bool operator!=(const XmmReg& other) const { return getRegCode() != other.getRegCode(); } #endif // ASMJIT_NODOC }; // ============================================================================ // [AsmJit::SegmentReg] // ============================================================================ //! @brief Segment register. struct SegmentReg : public Reg { // -------------------------------------------------------------------------- // [Construction / Destruction] // -------------------------------------------------------------------------- //! @brief Create non-initialized segment register. inline SegmentReg() : Reg(kInvalidValue, 2) {} //! @brief Create a reference to @a other segment register. inline SegmentReg(const _Initialize&, uint32_t code) : Reg(code, 2) {} #if !defined(ASMJIT_NODOC) inline SegmentReg(const _DontInitialize& dontInitialize) : Reg(dontInitialize) {} inline SegmentReg(const SegmentReg& other) : Reg(other) {} #endif // ASMJIT_NODOC // -------------------------------------------------------------------------- // [Reg Specific] // -------------------------------------------------------------------------- //! @brief Set register code to @a code. inline SegmentReg& setCode(uint32_t code) { _reg.code = code; return *this; } //! @brief Set register size to @a size. inline SegmentReg& setSize(uint32_t size) { _reg.size = static_cast(size); return *this; } // -------------------------------------------------------------------------- // [Operator Overload] // -------------------------------------------------------------------------- #if !defined(ASMJIT_NODOC) inline SegmentReg& operator=(const SegmentReg& other) { _copy(other); return *this; } inline bool operator==(const SegmentReg& other) const { return getRegCode() == other.getRegCode(); } inline bool operator!=(const SegmentReg& other) const { return getRegCode() != other.getRegCode(); } #endif // ASMJIT_NODOC }; // ============================================================================ // [AsmJit::Registers - no_reg] // ============================================================================ //! @brief No register, can be used only in @c Mem operand. ASMJIT_VAR const GpReg no_reg; // ============================================================================ // [AsmJit::Registers - 8-bit] // ============================================================================ //! @brief 8-bit General purpose register. ASMJIT_VAR const GpReg al; //! @brief 8-bit General purpose register. ASMJIT_VAR const GpReg cl; //! @brief 8-bit General purpose register. ASMJIT_VAR const GpReg dl; //! @brief 8-bit General purpose register. ASMJIT_VAR const GpReg bl; #if defined(ASMJIT_X64) //! @brief 8-bit General purpose register (64-bit mode only). ASMJIT_VAR const GpReg spl; //! @brief 8-bit General purpose register (64-bit mode only). ASMJIT_VAR const GpReg bpl; //! @brief 8-bit General purpose register (64-bit mode only). ASMJIT_VAR const GpReg sil; //! @brief 8-bit General purpose register (64-bit mode only). ASMJIT_VAR const GpReg dil; //! @brief 8-bit General purpose register (64-bit mode only). ASMJIT_VAR const GpReg r8b; //! @brief 8-bit General purpose register (64-bit mode only). ASMJIT_VAR const GpReg r9b; //! @brief 8-bit General purpose register (64-bit mode only). ASMJIT_VAR const GpReg r10b; //! @brief 8-bit General purpose register (64-bit mode only). ASMJIT_VAR const GpReg r11b; //! @brief 8-bit General purpose register (64-bit mode only). ASMJIT_VAR const GpReg r12b; //! @brief 8-bit General purpose register (64-bit mode only). ASMJIT_VAR const GpReg r13b; //! @brief 8-bit General purpose register (64-bit mode only). ASMJIT_VAR const GpReg r14b; //! @brief 8-bit General purpose register (64-bit mode only). ASMJIT_VAR const GpReg r15b; #endif // ASMJIT_X64 //! @brief 8-bit General purpose register. ASMJIT_VAR const GpReg ah; //! @brief 8-bit General purpose register. ASMJIT_VAR const GpReg ch; //! @brief 8-bit General purpose register. ASMJIT_VAR const GpReg dh; //! @brief 8-bit General purpose register. ASMJIT_VAR const GpReg bh; // ============================================================================ // [AsmJit::Registers - 16-bit] // ============================================================================ //! @brief 16-bit General purpose register. ASMJIT_VAR const GpReg ax; //! @brief 16-bit General purpose register. ASMJIT_VAR const GpReg cx; //! @brief 16-bit General purpose register. ASMJIT_VAR const GpReg dx; //! @brief 16-bit General purpose register. ASMJIT_VAR const GpReg bx; //! @brief 16-bit General purpose register. ASMJIT_VAR const GpReg sp; //! @brief 16-bit General purpose register. ASMJIT_VAR const GpReg bp; //! @brief 16-bit General purpose register. ASMJIT_VAR const GpReg si; //! @brief 16-bit General purpose register. ASMJIT_VAR const GpReg di; #if defined(ASMJIT_X64) //! @brief 16-bit General purpose register (64-bit mode only). ASMJIT_VAR const GpReg r8w; //! @brief 16-bit General purpose register (64-bit mode only). ASMJIT_VAR const GpReg r9w; //! @brief 16-bit General purpose register (64-bit mode only). ASMJIT_VAR const GpReg r10w; //! @brief 16-bit General purpose register (64-bit mode only). ASMJIT_VAR const GpReg r11w; //! @brief 16-bit General purpose register (64-bit mode only). ASMJIT_VAR const GpReg r12w; //! @brief 16-bit General purpose register (64-bit mode only). ASMJIT_VAR const GpReg r13w; //! @brief 16-bit General purpose register (64-bit mode only). ASMJIT_VAR const GpReg r14w; //! @brief 16-bit General purpose register (64-bit mode only). ASMJIT_VAR const GpReg r15w; #endif // ASMJIT_X64 // ============================================================================ // [AsmJit::Registers - 32-bit] // ============================================================================ //! @brief 32-bit General purpose register. ASMJIT_VAR const GpReg eax; //! @brief 32-bit General purpose register. ASMJIT_VAR const GpReg ecx; //! @brief 32-bit General purpose register. ASMJIT_VAR const GpReg edx; //! @brief 32-bit General purpose register. ASMJIT_VAR const GpReg ebx; //! @brief 32-bit General purpose register. ASMJIT_VAR const GpReg esp; //! @brief 32-bit General purpose register. ASMJIT_VAR const GpReg ebp; //! @brief 32-bit General purpose register. ASMJIT_VAR const GpReg esi; //! @brief 32-bit General purpose register. ASMJIT_VAR const GpReg edi; #if defined(ASMJIT_X64) //! @brief 32-bit General purpose register. ASMJIT_VAR const GpReg r8d; //! @brief 32-bit General purpose register. ASMJIT_VAR const GpReg r9d; //! @brief 32-bit General purpose register. ASMJIT_VAR const GpReg r10d; //! @brief 32-bit General purpose register. ASMJIT_VAR const GpReg r11d; //! @brief 32-bit General purpose register. ASMJIT_VAR const GpReg r12d; //! @brief 32-bit General purpose register. ASMJIT_VAR const GpReg r13d; //! @brief 32-bit General purpose register. ASMJIT_VAR const GpReg r14d; //! @brief 32-bit General purpose register. ASMJIT_VAR const GpReg r15d; #endif // ASMJIT_X64 // ============================================================================ // [AsmJit::Registers - 64-bit] // ============================================================================ #if defined(ASMJIT_X64) //! @brief 64-bit General purpose register (64-bit mode only). ASMJIT_VAR const GpReg rax; //! @brief 64-bit General purpose register (64-bit mode only). ASMJIT_VAR const GpReg rcx; //! @brief 64-bit General purpose register (64-bit mode only). ASMJIT_VAR const GpReg rdx; //! @brief 64-bit General purpose register (64-bit mode only). ASMJIT_VAR const GpReg rbx; //! @brief 64-bit General purpose register (64-bit mode only). ASMJIT_VAR const GpReg rsp; //! @brief 64-bit General purpose register (64-bit mode only). ASMJIT_VAR const GpReg rbp; //! @brief 64-bit General purpose register (64-bit mode only). ASMJIT_VAR const GpReg rsi; //! @brief 64-bit General purpose register (64-bit mode only). ASMJIT_VAR const GpReg rdi; //! @brief 64-bit General purpose register (64-bit mode only). ASMJIT_VAR const GpReg r8; //! @brief 64-bit General purpose register (64-bit mode only). ASMJIT_VAR const GpReg r9; //! @brief 64-bit General purpose register (64-bit mode only). ASMJIT_VAR const GpReg r10; //! @brief 64-bit General purpose register (64-bit mode only). ASMJIT_VAR const GpReg r11; //! @brief 64-bit General purpose register (64-bit mode only). ASMJIT_VAR const GpReg r12; //! @brief 64-bit General purpose register (64-bit mode only). ASMJIT_VAR const GpReg r13; //! @brief 64-bit General purpose register (64-bit mode only). ASMJIT_VAR const GpReg r14; //! @brief 64-bit General purpose register (64-bit mode only). ASMJIT_VAR const GpReg r15; #endif // ASMJIT_X64 // ============================================================================ // [AsmJit::Registers - Native (AsmJit extension)] // ============================================================================ //! @brief 32-bit or 64-bit General purpose register. ASMJIT_VAR const GpReg zax; //! @brief 32-bit or 64-bit General purpose register. ASMJIT_VAR const GpReg zcx; //! @brief 32-bit or 64-bit General purpose register. ASMJIT_VAR const GpReg zdx; //! @brief 32-bit or 64-bit General purpose register. ASMJIT_VAR const GpReg zbx; //! @brief 32-bit or 64-bit General purpose register. ASMJIT_VAR const GpReg zsp; //! @brief 32-bit or 64-bit General purpose register. ASMJIT_VAR const GpReg zbp; //! @brief 32-bit or 64-bit General purpose register. ASMJIT_VAR const GpReg zsi; //! @brief 32-bit or 64-bit General purpose register. ASMJIT_VAR const GpReg zdi; // ============================================================================ // [AsmJit::Registers - MM] // ============================================================================ //! @brief 64-bit MM register. ASMJIT_VAR const MmReg mm0; //! @brief 64-bit MM register. ASMJIT_VAR const MmReg mm1; //! @brief 64-bit MM register. ASMJIT_VAR const MmReg mm2; //! @brief 64-bit MM register. ASMJIT_VAR const MmReg mm3; //! @brief 64-bit MM register. ASMJIT_VAR const MmReg mm4; //! @brief 64-bit MM register. ASMJIT_VAR const MmReg mm5; //! @brief 64-bit MM register. ASMJIT_VAR const MmReg mm6; //! @brief 64-bit MM register. ASMJIT_VAR const MmReg mm7; // ============================================================================ // [AsmJit::Registers - XMM] // ============================================================================ //! @brief 128-bit XMM register. ASMJIT_VAR const XmmReg xmm0; //! @brief 128-bit XMM register. ASMJIT_VAR const XmmReg xmm1; //! @brief 128-bit XMM register. ASMJIT_VAR const XmmReg xmm2; //! @brief 128-bit XMM register. ASMJIT_VAR const XmmReg xmm3; //! @brief 128-bit XMM register. ASMJIT_VAR const XmmReg xmm4; //! @brief 128-bit XMM register. ASMJIT_VAR const XmmReg xmm5; //! @brief 128-bit XMM register. ASMJIT_VAR const XmmReg xmm6; //! @brief 128-bit XMM register. ASMJIT_VAR const XmmReg xmm7; #if defined(ASMJIT_X64) //! @brief 128-bit XMM register (64-bit mode only). ASMJIT_VAR const XmmReg xmm8; //! @brief 128-bit XMM register (64-bit mode only). ASMJIT_VAR const XmmReg xmm9; //! @brief 128-bit XMM register (64-bit mode only). ASMJIT_VAR const XmmReg xmm10; //! @brief 128-bit XMM register (64-bit mode only). ASMJIT_VAR const XmmReg xmm11; //! @brief 128-bit XMM register (64-bit mode only). ASMJIT_VAR const XmmReg xmm12; //! @brief 128-bit XMM register (64-bit mode only). ASMJIT_VAR const XmmReg xmm13; //! @brief 128-bit XMM register (64-bit mode only). ASMJIT_VAR const XmmReg xmm14; //! @brief 128-bit XMM register (64-bit mode only). ASMJIT_VAR const XmmReg xmm15; #endif // ASMJIT_X64 // ============================================================================ // [AsmJit::Registers - Segment] // ============================================================================ //! @brief CS segment register. ASMJIT_VAR const SegmentReg cs; //! @brief SS segment register. ASMJIT_VAR const SegmentReg ss; //! @brief DS segment register. ASMJIT_VAR const SegmentReg ds; //! @brief ES segment register. ASMJIT_VAR const SegmentReg es; //! @brief FS segment register. ASMJIT_VAR const SegmentReg fs; //! @brief GS segment register. ASMJIT_VAR const SegmentReg gs; // ============================================================================ // [AsmJit::Registers - Register From Index] // ============================================================================ //! @brief Get general purpose register of byte size. static inline GpReg gpb_lo(uint32_t index) { return GpReg(_Initialize(), static_cast(index | kX86RegTypeGpbLo)); } //! @brief Get general purpose register of byte size. static inline GpReg gpb_hi(uint32_t index) { return GpReg(_Initialize(), static_cast(index | kX86RegTypeGpbHi)); } //! @brief Get general purpose register of word size. static inline GpReg gpw(uint32_t index) { return GpReg(_Initialize(), static_cast(index | kX86RegTypeGpw)); } //! @brief Get general purpose register of dword size. static inline GpReg gpd(uint32_t index) { return GpReg(_Initialize(), static_cast(index | kX86RegTypeGpd)); } #if defined(ASMJIT_X64) //! @brief Get general purpose register of qword size (64-bit only). static inline GpReg gpq(uint32_t index) { return GpReg(_Initialize(), static_cast(index | kX86RegTypeGpq)); } #endif //! @brief Get general purpose dword/qword register (depending to architecture). static inline GpReg gpz(uint32_t index) { return GpReg(_Initialize(), static_cast(index | kX86RegTypeGpz)); } //! @brief Get MMX (MM) register . static inline MmReg mm(uint32_t index) { return MmReg(_Initialize(), static_cast(index | kX86RegTypeMm)); } //! @brief Get SSE (XMM) register. static inline XmmReg xmm(uint32_t index) { return XmmReg(_Initialize(), static_cast(index | kX86RegTypeXmm)); } //! @brief Get x87 register with index @a i. static inline X87Reg st(uint32_t i) { ASMJIT_ASSERT(i < 8); return X87Reg(_Initialize(), static_cast(i)); } // ============================================================================ // [AsmJit::Mem] // ============================================================================ //! @brief Memory operand. struct Mem : public Operand { // -------------------------------------------------------------------------- // [Construction / Destruction] // -------------------------------------------------------------------------- inline Mem() : Operand(_DontInitialize()) { _mem.op = kOperandMem; _mem.size = 0; _mem.type = kOperandMemNative; _mem.segment = kX86SegNone; _mem.sizePrefix = 0; _mem.shift = 0; _mem.id = kInvalidValue; _mem.base = kInvalidValue; _mem.index = kInvalidValue; _mem.target = NULL; _mem.displacement = 0; } inline Mem(const Label& label, sysint_t displacement, uint32_t size = 0) : Operand(_DontInitialize()) { _mem.op = kOperandMem; _mem.size = (uint8_t)size; _mem.type = kOperandMemLabel; _mem.segment = kX86SegNone; _mem.sizePrefix = 0; _mem.shift = 0; _mem.id = kInvalidValue; _mem.base = reinterpret_cast(label)._base.id; _mem.index = kInvalidValue; _mem.target = NULL; _mem.displacement = displacement; } inline Mem(const GpReg& base, sysint_t displacement, uint32_t size = 0) : Operand(_DontInitialize()) { _mem.op = kOperandMem; _mem.size = (uint8_t)size; _mem.type = kOperandMemNative; _mem.segment = kX86SegNone; #if defined(ASMJIT_X86) _mem.sizePrefix = base.getSize() != 4; #else _mem.sizePrefix = base.getSize() != 8; #endif _mem.shift = 0; _mem.id = kInvalidValue; _mem.base = base.getRegCode() & kRegIndexMask; _mem.index = kInvalidValue; _mem.target = NULL; _mem.displacement = displacement; } inline Mem(const GpVar& base, sysint_t displacement, uint32_t size = 0) : Operand(_DontInitialize()) { _mem.op = kOperandMem; _mem.size = (uint8_t)size; _mem.type = kOperandMemNative; _mem.segment = kX86SegNone; #if defined(ASMJIT_X86) _mem.sizePrefix = (reinterpret_cast(base)._var.size) != 4; #else _mem.sizePrefix = (reinterpret_cast(base)._var.size) != 8; #endif _mem.shift = 0; _mem.id = kInvalidValue; _mem.base = reinterpret_cast(base).getId(); _mem.index = kInvalidValue; _mem.target = NULL; _mem.displacement = displacement; } inline Mem(const GpReg& base, const GpReg& index, uint32_t shift, sysint_t displacement, uint32_t size = 0) : Operand(_DontInitialize()) { ASMJIT_ASSERT(shift <= 3); _mem.op = kOperandMem; _mem.size = (uint8_t)size; _mem.type = kOperandMemNative; _mem.segment = kX86SegNone; #if defined(ASMJIT_X86) _mem.sizePrefix = (base.getSize() | index.getSize()) != 4; #else _mem.sizePrefix = (base.getSize() | index.getSize()) != 8; #endif _mem.shift = (uint8_t)shift; _mem.id = kInvalidValue; _mem.base = base.getRegIndex(); _mem.index = index.getRegIndex(); _mem.target = NULL; _mem.displacement = displacement; } inline Mem(const GpVar& base, const GpVar& index, uint32_t shift, sysint_t displacement, uint32_t size = 0) : Operand(_DontInitialize()) { ASMJIT_ASSERT(shift <= 3); _mem.op = kOperandMem; _mem.size = (uint8_t)size; _mem.type = kOperandMemNative; _mem.segment = kX86SegNone; #if defined(ASMJIT_X86) _mem.sizePrefix = (reinterpret_cast(base )._var.size | reinterpret_cast(index)._var.size ) != 4; #else _mem.sizePrefix = (reinterpret_cast(base )._var.size | reinterpret_cast(index)._var.size ) != 8; #endif _mem.shift = (uint8_t)shift; _mem.id = kInvalidValue; _mem.base = reinterpret_cast(base).getId(); _mem.index = reinterpret_cast(index).getId(); _mem.target = NULL; _mem.displacement = displacement; } inline Mem(const Mem& other) : Operand(other) { } inline Mem(const _DontInitialize& dontInitialize) : Operand(dontInitialize) { } // -------------------------------------------------------------------------- // [Mem Specific] // -------------------------------------------------------------------------- //! @brief Get type of memory operand, see @c kOperandMemType. inline uint32_t getMemType() const { return _mem.type; } //! @brief Get memory operand segment, see @c kX86Seg. inline uint32_t getSegment() const { return _mem.segment; } //! @brief Set memory operand segment, see @c kX86Seg. inline Mem& setSegment(uint32_t seg) { _mem.segment = static_cast(seg); return *this; } //! @brief Set memory operand segment, see @c kX86Seg. inline Mem& setSegment(const SegmentReg& seg) { _mem.segment = static_cast(seg.getRegIndex()); return *this; } //! @brief Get whether the memory operand has segment override prefix. inline bool hasSegment() const { return _mem.segment >= kX86SegCount; } //! @brief Get whether the memory operand has base register. inline bool hasBase() const { return _mem.base != kInvalidValue; } //! @brief Get whether the memory operand has index. inline bool hasIndex() const { return _mem.index != kInvalidValue; } //! @brief Get whether the memory operand has shift used. inline bool hasShift() const { return _mem.shift != 0; } //! @brief Get memory operand base register or @c kInvalidValue. inline uint32_t getBase() const { return _mem.base; } //! @brief Get memory operand index register or @c kInvalidValue. inline uint32_t getIndex() const { return _mem.index; } //! @brief Get memory operand index scale (0, 1, 2 or 3). inline uint32_t getShift() const { return _mem.shift; } //! @brief Get whether to use size-override prefix. //! //! @note This is useful only for MOV and LEA type of instructions. inline bool getSizePrefix() const { return _mem.sizePrefix; } //! @brief Set whether to use size-override prefix. inline Mem& setSizePrefix(bool b) { _mem.sizePrefix = b; return *this; } //! @brief Get absolute target address. //! //! @note You should always check if operand contains address by @c getMemType(). inline void* getTarget() const { return _mem.target; } //! @brief Set absolute target address. inline Mem& setTarget(void* target) { _mem.target = target; return *this; } //! @brief Set memory operand size. inline Mem& setSize(uint32_t size) { _mem.size = size; return *this; } //! @brief Get memory operand relative displacement. inline sysint_t getDisplacement() const { return _mem.displacement; } //! @brief Set memory operand relative displacement. inline Mem& setDisplacement(sysint_t displacement) { _mem.displacement = displacement; return *this; } //! @brief Adjust memory operand relative displacement by @a displacement. inline Mem& adjust(sysint_t displacement) { _mem.displacement += displacement; return *this; } //! @brief Get new memory operand adjusted by @a displacement. inline Mem adjusted(sysint_t displacement) const { Mem result(*this); result.adjust(displacement); return result; } // -------------------------------------------------------------------------- // [Operator Overload] // -------------------------------------------------------------------------- #if !defined(ASMJIT_NODOC) inline Mem& operator=(const Mem& other) { _copy(other); return *this; } inline bool operator==(const Mem& other) const { return _bin.u32[0] == other._bin.u32[0] && _bin.u32[1] == other._bin.u32[1] && _bin.u32[2] == other._bin.u32[2] && _bin.u32[3] == other._bin.u32[3] && _bin.uptr[0] == other._bin.uptr[0] && _bin.uptr[1] == other._bin.uptr[1]; } inline bool operator!=(const Mem& other) const { return !(*this == other); } #endif // ASMJIT_NODOC }; // ============================================================================ // [AsmJit::Var] // ============================================================================ ASMJIT_API Mem _BaseVarMem(const Var& var, uint32_t size); ASMJIT_API Mem _BaseVarMem(const Var& var, uint32_t size, sysint_t disp); ASMJIT_API Mem _BaseVarMem(const Var& var, uint32_t size, const GpVar& index, uint32_t shift, sysint_t disp); //! @brief Base class for all variables. struct Var : public Operand { // -------------------------------------------------------------------------- // [Construction / Destruction] // -------------------------------------------------------------------------- #if !defined(ASMJIT_NODOC) inline Var(const _DontInitialize& dontInitialize) : Operand(dontInitialize) { } #endif // ASMJIT_NODOC inline Var() : Operand(_DontInitialize()) { _var.op = kOperandVar; _var.size = 0; _var.regCode = kInvalidValue; _var.varType = kInvalidValue; _var.id = kInvalidValue; } inline Var(const Var& other) : Operand(other) { } // -------------------------------------------------------------------------- // [Type] // -------------------------------------------------------------------------- inline uint32_t getVarType() const { return _var.varType; } inline bool isGpVar() const { return _var.varType <= kX86VarTypeGpq; } inline bool isX87Var() const { return _var.varType >= kX86VarTypeX87 && _var.varType <= kX86VarTypeX87SD; } inline bool isMmVar() const { return _var.varType == kX86VarTypeMm; } inline bool isXmmVar() const { return _var.varType >= kX86VarTypeXmm && _var.varType <= kX86VarTypeXmmPD; } // -------------------------------------------------------------------------- // [Memory Cast] // -------------------------------------------------------------------------- //! @brief Cast this variable to memory operand. //! //! @note Size of operand depends on native variable type, you can use other //! variants if you want specific one. inline Mem m() const { return _BaseVarMem(*this, kInvalidValue); } //! @overload. inline Mem m(sysint_t disp) const { return _BaseVarMem(*this, kInvalidValue, disp); } //! @overload. inline Mem m(const GpVar& index, uint32_t shift = 0, sysint_t disp = 0) const { return _BaseVarMem(*this, kInvalidValue, index, shift, disp); } //! @brief Cast this variable to 8-bit memory operand. inline Mem m8() const { return _BaseVarMem(*this, 1); } //! @overload. inline Mem m8(sysint_t disp) const { return _BaseVarMem(*this, 1, disp); } //! @overload. inline Mem m8(const GpVar& index, uint32_t shift = 0, sysint_t disp = 0) const { return _BaseVarMem(*this, 1, index, shift, disp); } //! @brief Cast this variable to 16-bit memory operand. inline Mem m16() const { return _BaseVarMem(*this, 2); } //! @overload. inline Mem m16(sysint_t disp) const { return _BaseVarMem(*this, 2, disp); } //! @overload. inline Mem m16(const GpVar& index, uint32_t shift = 0, sysint_t disp = 0) const { return _BaseVarMem(*this, 2, index, shift, disp); } //! @brief Cast this variable to 32-bit memory operand. inline Mem m32() const { return _BaseVarMem(*this, 4); } //! @overload. inline Mem m32(sysint_t disp) const { return _BaseVarMem(*this, 4, disp); } //! @overload. inline Mem m32(const GpVar& index, uint32_t shift = 0, sysint_t disp = 0) const { return _BaseVarMem(*this, 4, index, shift, disp); } //! @brief Cast this variable to 64-bit memory operand. inline Mem m64() const { return _BaseVarMem(*this, 8); } //! @overload. inline Mem m64(sysint_t disp) const { return _BaseVarMem(*this, 8, disp); } //! @overload. inline Mem m64(const GpVar& index, uint32_t shift = 0, sysint_t disp = 0) const { return _BaseVarMem(*this, 8, index, shift, disp); } //! @brief Cast this variable to 80-bit memory operand (long double). inline Mem m80() const { return _BaseVarMem(*this, 10); } //! @overload. inline Mem m80(sysint_t disp) const { return _BaseVarMem(*this, 10, disp); } //! @overload. inline Mem m80(const GpVar& index, uint32_t shift = 0, sysint_t disp = 0) const { return _BaseVarMem(*this, 10, index, shift, disp); } //! @brief Cast this variable to 128-bit memory operand. inline Mem m128() const { return _BaseVarMem(*this, 16); } //! @overload. inline Mem m128(sysint_t disp) const { return _BaseVarMem(*this, 16, disp); } //! @overload. inline Mem m128(const GpVar& index, uint32_t shift = 0, sysint_t disp = 0) const { return _BaseVarMem(*this, 16, index, shift, disp); } // -------------------------------------------------------------------------- // [Operator Overload] // -------------------------------------------------------------------------- #if !defined(ASMJIT_NODOC) inline Var& operator=(const Var& other) { _copy(other); return *this; } inline bool operator==(const Var& other) const { return _base.id == other._base.id && _var.regCode == other._var.regCode; } inline bool operator!=(const Var& other) const { return _base.id != other._base.id || _var.regCode != other._var.regCode; } #endif // ASMJIT_NODOC // -------------------------------------------------------------------------- // [Private] // -------------------------------------------------------------------------- protected: inline Var(const Var& other, uint32_t regCode, uint32_t size) : Operand(_DontInitialize()) { _var.op = kOperandVar; _var.size = (uint8_t)size; _var.id = other._base.id; _var.regCode = regCode; _var.varType = other._var.varType; } }; // ============================================================================ // [AsmJit::X87Var] // ============================================================================ //! @brief X87 Variable operand. struct X87Var : public Var { // -------------------------------------------------------------------------- // [Construction / Destruction] // -------------------------------------------------------------------------- inline X87Var(const _DontInitialize& dontInitialize) : Var(dontInitialize) { } inline X87Var() : Var(_DontInitialize()) { _var.op = kOperandVar; _var.size = 12; _var.id = kInvalidValue; _var.regCode = kX86RegTypeX87; _var.varType = kX86VarTypeX87; } inline X87Var(const X87Var& other) : Var(other) {} // -------------------------------------------------------------------------- // [Operator Overload] // -------------------------------------------------------------------------- #if !defined(ASMJIT_NODOC) inline X87Var& operator=(const X87Var& other) { _copy(other); return *this; } inline bool operator==(const X87Var& other) const { return _base.id == other._base.id; } inline bool operator!=(const X87Var& other) const { return _base.id != other._base.id; } #endif // ASMJIT_NODOC }; // ============================================================================ // [AsmJit::GpVar] // ============================================================================ //! @brief GP variable operand. struct GpVar : public Var { // -------------------------------------------------------------------------- // [Construction / Destruction] // -------------------------------------------------------------------------- //! @brief Create new uninitialized @c GpVar instance (internal constructor). inline GpVar(const _DontInitialize& dontInitialize) : Var(dontInitialize) { } //! @brief Create new uninitialized @c GpVar instance. inline GpVar() : Var(_DontInitialize()) { _var.op = kOperandVar; _var.size = sizeof(sysint_t); _var.id = kInvalidValue; _var.regCode = kX86RegTypeGpz; _var.varType = kX86VarTypeGpz; } //! @brief Create new @c GpVar instance using @a other. //! //! Note this will not create a different variable, use @c Compiler::newGpVar() //! if you want to do so. This is only copy-constructor that allows to store //! the same variable in different places. inline GpVar(const GpVar& other) : Var(other) {} // -------------------------------------------------------------------------- // [GpVar Specific] // -------------------------------------------------------------------------- //! @brief Get whether this variable is general purpose BYTE register. inline bool isGpb() const { return (_var.regCode & kRegTypeMask) <= kX86RegTypeGpbHi; } //! @brief Get whether this variable is general purpose BYTE.LO register. inline bool isGpbLo() const { return (_var.regCode & kRegTypeMask) == kX86RegTypeGpbLo; } //! @brief Get whether this variable is general purpose BYTE.HI register. inline bool isGpbHi() const { return (_var.regCode & kRegTypeMask) == kX86RegTypeGpbHi; } //! @brief Get whether this variable is general purpose WORD register. inline bool isGpw() const { return (_var.regCode & kRegTypeMask) == kX86RegTypeGpw; } //! @brief Get whether this variable is general purpose DWORD register. inline bool isGpd() const { return (_var.regCode & kRegTypeMask) == kX86RegTypeGpd; } //! @brief Get whether this variable is general purpose QWORD (only 64-bit) register. inline bool isGpq() const { return (_var.regCode & kRegTypeMask) == kX86RegTypeGpq; } // -------------------------------------------------------------------------- // [GpVar Cast] // -------------------------------------------------------------------------- //! @brief Cast this variable to 8-bit (LO) part of variable inline GpVar r8() const { return GpVar(*this, kX86RegTypeGpbLo, 1); } //! @brief Cast this variable to 8-bit (LO) part of variable inline GpVar r8Lo() const { return GpVar(*this, kX86RegTypeGpbLo, 1); } //! @brief Cast this variable to 8-bit (HI) part of variable inline GpVar r8Hi() const { return GpVar(*this, kX86RegTypeGpbHi, 1); } //! @brief Cast this variable to 16-bit part of variable inline GpVar r16() const { return GpVar(*this, kX86RegTypeGpw, 2); } //! @brief Cast this variable to 32-bit part of variable inline GpVar r32() const { return GpVar(*this, kX86RegTypeGpd, 4); } #if defined(ASMJIT_X64) //! @brief Cast this variable to 64-bit part of variable inline GpVar r64() const { return GpVar(*this, kX86RegTypeGpq, 8); } #endif // ASMJIT_X64 // -------------------------------------------------------------------------- // [Operator Overload] // -------------------------------------------------------------------------- #if !defined(ASMJIT_NODOC) inline GpVar& operator=(const GpVar& other) { _copy(other); return *this; } inline bool operator==(const GpVar& other) const { return _base.id == other._base.id && _var.regCode == other._var.regCode; } inline bool operator!=(const GpVar& other) const { return _base.id != other._base.id || _var.regCode != other._var.regCode; } #endif // ASMJIT_NODOC // -------------------------------------------------------------------------- // [Private] // -------------------------------------------------------------------------- protected: inline GpVar(const GpVar& other, uint32_t regCode, uint32_t size) : Var(other, regCode, size) { } }; // ============================================================================ // [AsmJit::MmVar] // ============================================================================ //! @brief MM variable operand. struct MmVar : public Var { // -------------------------------------------------------------------------- // [Construction / Destruction] // -------------------------------------------------------------------------- //! @brief Create new uninitialized @c MmVar instance (internal constructor). inline MmVar(const _DontInitialize& dontInitialize) : Var(dontInitialize) { } //! @brief Create new uninitialized @c MmVar instance. inline MmVar() : Var(_DontInitialize()) { _var.op = kOperandVar; _var.size = 8; _var.id = kInvalidValue; _var.regCode = kX86RegTypeMm; _var.varType = kX86VarTypeMm; } //! @brief Create new @c MmVar instance using @a other. //! //! Note this will not create a different variable, use @c Compiler::newMmVar() //! if you want to do so. This is only copy-constructor that allows to store //! the same variable in different places. inline MmVar(const MmVar& other) : Var(other) {} // -------------------------------------------------------------------------- // [MmVar Cast] // -------------------------------------------------------------------------- // -------------------------------------------------------------------------- // [Operator Overload] // -------------------------------------------------------------------------- #if !defined(ASMJIT_NODOC) inline MmVar& operator=(const MmVar& other) { _copy(other); return *this; } inline bool operator==(const MmVar& other) const { return _base.id == other._base.id; } inline bool operator!=(const MmVar& other) const { return _base.id != other._base.id; } #endif // ASMJIT_NODOC }; // ============================================================================ // [AsmJit::XmmVar] // ============================================================================ //! @brief XMM Variable operand. struct XmmVar : public Var { // -------------------------------------------------------------------------- // [Construction / Destruction] // -------------------------------------------------------------------------- inline XmmVar(const _DontInitialize& dontInitialize) : Var(dontInitialize) { } inline XmmVar() : Var(_DontInitialize()) { _var.op = kOperandVar; _var.size = 16; _var.id = kInvalidValue; _var.regCode = kX86RegTypeXmm; _var.varType = kX86VarTypeXmm; } inline XmmVar(const XmmVar& other) : Var(other) {} // -------------------------------------------------------------------------- // [XmmVar Access] // -------------------------------------------------------------------------- // -------------------------------------------------------------------------- // [Operator Overload] // -------------------------------------------------------------------------- #if !defined(ASMJIT_NODOC) inline XmmVar& operator=(const XmmVar& other) { _copy(other); return *this; } inline bool operator==(const XmmVar& other) const { return _base.id == other._base.id; } inline bool operator!=(const XmmVar& other) const { return _base.id != other._base.id; } #endif // ASMJIT_NODOC }; // ============================================================================ // [AsmJit::Mem - [label + displacement]] // ============================================================================ //! @brief Create a custom pointer operand. ASMJIT_API Mem ptr(const Label& label, sysint_t disp = 0, uint32_t size = 0); //! @brief Create a byte pointer operand. static inline Mem byte_ptr(const Label& label, sysint_t disp = 0) { return ptr(label, disp, kSizeByte); } //! @brief Create a word pointer operand. static inline Mem word_ptr(const Label& label, sysint_t disp = 0) { return ptr(label, disp, kSizeWord); } //! @brief Create a dword pointer operand. static inline Mem dword_ptr(const Label& label, sysint_t disp = 0) { return ptr(label, disp, kSizeDWord); } //! @brief Create a qword pointer operand. static inline Mem qword_ptr(const Label& label, sysint_t disp = 0) { return ptr(label, disp, kSizeQWord); } //! @brief Create a tword pointer operand. static inline Mem tword_ptr(const Label& label, sysint_t disp = 0) { return ptr(label, disp, kSizeTWord); } //! @brief Create a dqword pointer operand. static inline Mem dqword_ptr(const Label& label, sysint_t disp = 0) { return ptr(label, disp, kSizeDQWord); } //! @brief Create a mmword pointer operand. static inline Mem mmword_ptr(const Label& label, sysint_t disp = 0) { return ptr(label, disp, kSizeQWord); } //! @brief Create a xmmword pointer operand. static inline Mem xmmword_ptr(const Label& label, sysint_t disp = 0) { return ptr(label, disp, kSizeDQWord); } //! @brief Create an intptr_t pointer operand. static inline Mem sysint_ptr(const Label& label, sysint_t disp = 0) { return ptr(label, disp, sizeof(sysint_t)); } // ============================================================================ // [AsmJit::Mem - [label + index << shift + displacement]] // ============================================================================ //! @brief Create a custom pointer operand. ASMJIT_API Mem ptr(const Label& label, const GpReg& index, uint32_t shift, sysint_t disp = 0, uint32_t size = 0); //! @brief Create a byte pointer operand. static inline Mem byte_ptr(const Label& label, const GpReg& index, uint32_t shift, sysint_t disp = 0) { return ptr(label, index, shift, disp, kSizeByte); } //! @brief Create a word pointer operand. static inline Mem word_ptr(const Label& label, const GpReg& index, uint32_t shift, sysint_t disp = 0) { return ptr(label, index, shift, disp, kSizeWord); } //! @brief Create a dword pointer operand. static inline Mem dword_ptr(const Label& label, const GpReg& index, uint32_t shift, sysint_t disp = 0) { return ptr(label, index, shift, disp, kSizeDWord); } //! @brief Create a qword pointer operand. static inline Mem qword_ptr(const Label& label, const GpReg& index, uint32_t shift, sysint_t disp = 0) { return ptr(label, index, shift, disp, kSizeQWord); } //! @brief Create a tword pointer operand. static inline Mem tword_ptr(const Label& label, const GpReg& index, uint32_t shift, sysint_t disp = 0) { return ptr(label, index, shift, disp, kSizeTWord); } //! @brief Create a dqword pointer operand. static inline Mem dqword_ptr(const Label& label, const GpReg& index, uint32_t shift, sysint_t disp = 0) { return ptr(label, index, shift, disp, kSizeDQWord); } //! @brief Create a mmword pointer operand. static inline Mem mmword_ptr(const Label& label, const GpReg& index, uint32_t shift, sysint_t disp = 0) { return ptr(label, index, shift, disp, kSizeQWord); } //! @brief Create a xmmword pointer operand. static inline Mem xmmword_ptr(const Label& label, const GpReg& index, uint32_t shift, sysint_t disp = 0) { return ptr(label, index, shift, disp, kSizeDQWord); } //! @brief Create an intptr_t pointer operand. static inline Mem sysint_ptr(const Label& label, const GpReg& index, uint32_t shift, sysint_t disp = 0) { return ptr(label, index, shift, disp, sizeof(sysint_t)); } //! @brief Create a custom pointer operand. ASMJIT_API Mem ptr(const Label& label, const GpVar& index, uint32_t shift, sysint_t disp = 0, uint32_t size = 0); //! @brief Create a byte pointer operand. static inline Mem byte_ptr(const Label& label, const GpVar& index, uint32_t shift, sysint_t disp = 0) { return ptr(label, index, shift, disp, kSizeByte); } //! @brief Create a word pointer operand. static inline Mem word_ptr(const Label& label, const GpVar& index, uint32_t shift, sysint_t disp = 0) { return ptr(label, index, shift, disp, kSizeWord); } //! @brief Create a dword pointer operand. static inline Mem dword_ptr(const Label& label, const GpVar& index, uint32_t shift, sysint_t disp = 0) { return ptr(label, index, shift, disp, kSizeDWord); } //! @brief Create a qword pointer operand. static inline Mem qword_ptr(const Label& label, const GpVar& index, uint32_t shift, sysint_t disp = 0) { return ptr(label, index, shift, disp, kSizeQWord); } //! @brief Create a tword pointer operand. static inline Mem tword_ptr(const Label& label, const GpVar& index, uint32_t shift, sysint_t disp = 0) { return ptr(label, index, shift, disp, kSizeTWord); } //! @brief Create a dqword pointer operand. static inline Mem dqword_ptr(const Label& label, const GpVar& index, uint32_t shift, sysint_t disp = 0) { return ptr(label, index, shift, disp, kSizeDQWord); } //! @brief Create a mmword pointer operand. static inline Mem mmword_ptr(const Label& label, const GpVar& index, uint32_t shift, sysint_t disp = 0) { return ptr(label, index, shift, disp, kSizeQWord); } //! @brief Create a xmmword pointer operand. static inline Mem xmmword_ptr(const Label& label, const GpVar& index, uint32_t shift, sysint_t disp = 0) { return ptr(label, index, shift, disp, kSizeDQWord); } //! @brief Create an intptr_t pointer operand. static inline Mem sysint_ptr(const Label& label, const GpVar& index, uint32_t shift, sysint_t disp = 0) { return ptr(label, index, shift, disp, sizeof(sysint_t)); } // ============================================================================ // [AsmJit::Mem - segment[target + displacement] // ============================================================================ //! @brief Create a custom pointer operand. ASMJIT_API Mem ptr_abs(void* target, sysint_t disp = 0, uint32_t size = 0); //! @brief Create a byte pointer operand. static inline Mem byte_ptr_abs(void* target, sysint_t disp = 0) { return ptr_abs(target, disp, kSizeByte); } //! @brief Create a word pointer operand. static inline Mem word_ptr_abs(void* target, sysint_t disp = 0) { return ptr_abs(target, disp, kSizeWord); } //! @brief Create a dword pointer operand. static inline Mem dword_ptr_abs(void* target, sysint_t disp = 0) { return ptr_abs(target, disp, kSizeDWord); } //! @brief Create a qword pointer operand. static inline Mem qword_ptr_abs(void* target, sysint_t disp = 0) { return ptr_abs(target, disp, kSizeQWord); } //! @brief Create a tword pointer operand (used for 80-bit floating points). static inline Mem tword_ptr_abs(void* target, sysint_t disp = 0) { return ptr_abs(target, disp, kSizeTWord); } //! @brief Create a dqword pointer operand. static inline Mem dqword_ptr_abs(void* target, sysint_t disp = 0) { return ptr_abs(target, disp, kSizeDQWord); } //! @brief Create a mmword pointer operand. static inline Mem mmword_ptr_abs(void* target, sysint_t disp = 0) { return ptr_abs(target, disp, kSizeQWord); } //! @brief Create a xmmword pointer operand. static inline Mem xmmword_ptr_abs(void* target, sysint_t disp = 0) { return ptr_abs(target, disp, kSizeDQWord); } //! @brief Create an intptr_t pointer operand. static inline Mem sysint_ptr_abs(void* target, sysint_t disp = 0) { return ptr_abs(target, disp, sizeof(sysint_t)); } // ============================================================================ // [AsmJit::Mem - segment[target + index << shift + displacement] // ============================================================================ //! @brief Create a custom pointer operand. ASMJIT_API Mem ptr_abs(void* target, const GpReg& index, uint32_t shift, sysint_t disp = 0, uint32_t size = 0); //! @brief Create a byte pointer operand. static inline Mem byte_ptr_abs(void* target, const GpReg& index, uint32_t shift, sysint_t disp = 0) { return ptr_abs(target, index, shift, disp, kSizeByte); } //! @brief Create a word pointer operand. static inline Mem word_ptr_abs(void* target, const GpReg& index, uint32_t shift, sysint_t disp = 0) { return ptr_abs(target, index, shift, disp, kSizeWord); } //! @brief Create a dword pointer operand. static inline Mem dword_ptr_abs(void* target, const GpReg& index, uint32_t shift, sysint_t disp = 0) { return ptr_abs(target, index, shift, disp, kSizeDWord); } //! @brief Create a qword pointer operand. static inline Mem qword_ptr_abs(void* target, const GpReg& index, uint32_t shift, sysint_t disp = 0) { return ptr_abs(target, index, shift, disp, kSizeQWord); } //! @brief Create a tword pointer operand. static inline Mem tword_ptr_abs(void* target, const GpReg& index, uint32_t shift, sysint_t disp = 0) { return ptr_abs(target, index, shift, disp, kSizeTWord); } //! @brief Create a dqword pointer operand. static inline Mem dqword_ptr_abs(void* target, const GpReg& index, uint32_t shift, sysint_t disp = 0) { return ptr_abs(target, index, shift, disp, kSizeDQWord); } //! @brief Create a mmword pointer operand. static inline Mem mmword_ptr_abs(void* target, const GpReg& index, uint32_t shift, sysint_t disp = 0) { return ptr_abs(target, index, shift, disp, kSizeQWord); } //! @brief Create a xmmword pointer operand. static inline Mem xmmword_ptr_abs(void* target, const GpReg& index, uint32_t shift, sysint_t disp = 0) { return ptr_abs(target, index, shift, disp, kSizeDQWord); } //! @brief Create an intptr_t pointer operand. static inline Mem sysint_ptr_abs(void* target, const GpReg& index, uint32_t shift, sysint_t disp = 0) { return ptr_abs(target, index, shift, disp, sizeof(sysint_t)); } //! @brief Create a custom pointer operand. ASMJIT_API Mem ptr_abs(void* target, const GpVar& index, uint32_t shift, sysint_t disp = 0, uint32_t size = 0); //! @brief Create a byte pointer operand. static inline Mem byte_ptr_abs(void* target, const GpVar& index, uint32_t shift, sysint_t disp = 0) { return ptr_abs(target, index, shift, disp, kSizeByte); } //! @brief Create a word pointer operand. static inline Mem word_ptr_abs(void* target, const GpVar& index, uint32_t shift, sysint_t disp = 0) { return ptr_abs(target, index, shift, disp, kSizeWord); } //! @brief Create a dword pointer operand. static inline Mem dword_ptr_abs(void* target, const GpVar& index, uint32_t shift, sysint_t disp = 0) { return ptr_abs(target, index, shift, disp, kSizeDWord); } //! @brief Create a qword pointer operand. static inline Mem qword_ptr_abs(void* target, const GpVar& index, uint32_t shift, sysint_t disp = 0) { return ptr_abs(target, index, shift, disp, kSizeQWord); } //! @brief Create a tword pointer operand. static inline Mem tword_ptr_abs(void* target, const GpVar& index, uint32_t shift, sysint_t disp = 0) { return ptr_abs(target, index, shift, disp, kSizeTWord); } //! @brief Create a dqword pointer operand. static inline Mem dqword_ptr_abs(void* target, const GpVar& index, uint32_t shift, sysint_t disp = 0) { return ptr_abs(target, index, shift, disp, kSizeDQWord); } //! @brief Create a mmword pointer operand. static inline Mem mmword_ptr_abs(void* target, const GpVar& index, uint32_t shift, sysint_t disp = 0) { return ptr_abs(target, index, shift, disp, kSizeQWord); } //! @brief Create a xmmword pointer operand. static inline Mem xmmword_ptr_abs(void* target, const GpVar& index, uint32_t shift, sysint_t disp = 0) { return ptr_abs(target, index, shift, disp, kSizeDQWord); } //! @brief Create an intptr_t pointer operand. static inline Mem sysint_ptr_abs(void* target, const GpVar& index, uint32_t shift, sysint_t disp = 0) { return ptr_abs(target, index, shift, disp, sizeof(sysint_t)); } // ============================================================================ // [AsmJit::Mem - ptr[base + displacement]] // ============================================================================ //! @brief Create a custom pointer operand. ASMJIT_API Mem ptr(const GpReg& base, sysint_t disp = 0, uint32_t size = 0); //! @brief Create a byte pointer operand. static inline Mem byte_ptr(const GpReg& base, sysint_t disp = 0) { return ptr(base, disp, kSizeByte); } //! @brief Create a word pointer operand. static inline Mem word_ptr(const GpReg& base, sysint_t disp = 0) { return ptr(base, disp, kSizeWord); } //! @brief Create a dword pointer operand. static inline Mem dword_ptr(const GpReg& base, sysint_t disp = 0) { return ptr(base, disp, kSizeDWord); } //! @brief Create a qword pointer operand. static inline Mem qword_ptr(const GpReg& base, sysint_t disp = 0) { return ptr(base, disp, kSizeQWord); } //! @brief Create a tword pointer operand. static inline Mem tword_ptr(const GpReg& base, sysint_t disp = 0) { return ptr(base, disp, kSizeTWord); } //! @brief Create a dqword pointer operand. static inline Mem dqword_ptr(const GpReg& base, sysint_t disp = 0) { return ptr(base, disp, kSizeDQWord); } //! @brief Create a mmword pointer operand. static inline Mem mmword_ptr(const GpReg& base, sysint_t disp = 0) { return ptr(base, disp, kSizeQWord); } //! @brief Create a xmmword pointer operand. static inline Mem xmmword_ptr(const GpReg& base, sysint_t disp = 0) { return ptr(base, disp, kSizeDQWord); } //! @brief Create an intptr_t pointer operand. static inline Mem sysint_ptr(const GpReg& base, sysint_t disp = 0) { return ptr(base, disp, sizeof(sysint_t)); } //! @brief Create a custom pointer operand. ASMJIT_API Mem ptr(const GpVar& base, sysint_t disp = 0, uint32_t size = 0); //! @brief Create a byte pointer operand. static inline Mem byte_ptr(const GpVar& base, sysint_t disp = 0) { return ptr(base, disp, kSizeByte); } //! @brief Create a word pointer operand. static inline Mem word_ptr(const GpVar& base, sysint_t disp = 0) { return ptr(base, disp, kSizeWord); } //! @brief Create a dword pointer operand. static inline Mem dword_ptr(const GpVar& base, sysint_t disp = 0) { return ptr(base, disp, kSizeDWord); } //! @brief Create a qword pointer operand. static inline Mem qword_ptr(const GpVar& base, sysint_t disp = 0) { return ptr(base, disp, kSizeQWord); } //! @brief Create a tword pointer operand. static inline Mem tword_ptr(const GpVar& base, sysint_t disp = 0) { return ptr(base, disp, kSizeTWord); } //! @brief Create a dqword pointer operand. static inline Mem dqword_ptr(const GpVar& base, sysint_t disp = 0) { return ptr(base, disp, kSizeDQWord); } //! @brief Create a mmword pointer operand. static inline Mem mmword_ptr(const GpVar& base, sysint_t disp = 0) { return ptr(base, disp, kSizeQWord); } //! @brief Create a xmmword pointer operand. static inline Mem xmmword_ptr(const GpVar& base, sysint_t disp = 0) { return ptr(base, disp, kSizeDQWord); } //! @brief Create an intptr_t pointer operand. static inline Mem sysint_ptr(const GpVar& base, sysint_t disp = 0) { return ptr(base, disp, sizeof(sysint_t)); } // ============================================================================ // [AsmJit::Mem - ptr[base + (index << shift) + displacement]] // ============================================================================ //! @brief Create a custom pointer operand. ASMJIT_API Mem ptr(const GpReg& base, const GpReg& index, uint32_t shift = 0, sysint_t disp = 0, uint32_t size = 0); //! @brief Create a byte pointer operand. static inline Mem byte_ptr(const GpReg& base, const GpReg& index, uint32_t shift = 0, sysint_t disp = 0) { return ptr(base, index, shift, disp, kSizeByte); } //! @brief Create a word pointer operand. static inline Mem word_ptr(const GpReg& base, const GpReg& index, uint32_t shift = 0, sysint_t disp = 0) { return ptr(base, index, shift, disp, kSizeWord); } //! @brief Create a dword pointer operand. static inline Mem dword_ptr(const GpReg& base, const GpReg& index, uint32_t shift = 0, sysint_t disp = 0) { return ptr(base, index, shift, disp, kSizeDWord); } //! @brief Create a qword pointer operand. static inline Mem qword_ptr(const GpReg& base, const GpReg& index, uint32_t shift = 0, sysint_t disp = 0) { return ptr(base, index, shift, disp, kSizeQWord); } //! @brief Create a tword pointer operand. static inline Mem tword_ptr(const GpReg& base, const GpReg& index, uint32_t shift = 0, sysint_t disp = 0) { return ptr(base, index, shift, disp, kSizeTWord); } //! @brief Create a dqword pointer operand. static inline Mem dqword_ptr(const GpReg& base, const GpReg& index, uint32_t shift = 0, sysint_t disp = 0) { return ptr(base, index, shift, disp, kSizeDQWord); } //! @brief Create a mmword pointer operand. static inline Mem mmword_ptr(const GpReg& base, const GpReg& index, uint32_t shift = 0, sysint_t disp = 0) { return ptr(base, index, shift, disp, kSizeQWord); } //! @brief Create a xmmword pointer operand. static inline Mem xmmword_ptr(const GpReg& base, const GpReg& index, uint32_t shift = 0, sysint_t disp = 0) { return ptr(base, index, shift, disp, kSizeDQWord); } //! @brief Create an intptr_t pointer operand. static inline Mem sysint_ptr(const GpReg& base, const GpReg& index, uint32_t shift = 0, sysint_t disp = 0) { return ptr(base, index, shift, disp, sizeof(sysint_t)); } //! @brief Create a custom pointer operand. ASMJIT_API Mem ptr(const GpVar& base, const GpVar& index, uint32_t shift = 0, sysint_t disp = 0, uint32_t size = 0); //! @brief Create a byte pointer operand. static inline Mem byte_ptr(const GpVar& base, const GpVar& index, uint32_t shift = 0, sysint_t disp = 0) { return ptr(base, index, shift, disp, kSizeByte); } //! @brief Create a word pointer operand. static inline Mem word_ptr(const GpVar& base, const GpVar& index, uint32_t shift = 0, sysint_t disp = 0) { return ptr(base, index, shift, disp, kSizeWord); } //! @brief Create a dword pointer operand. static inline Mem dword_ptr(const GpVar& base, const GpVar& index, uint32_t shift = 0, sysint_t disp = 0) { return ptr(base, index, shift, disp, kSizeDWord); } //! @brief Create a qword pointer operand. static inline Mem qword_ptr(const GpVar& base, const GpVar& index, uint32_t shift = 0, sysint_t disp = 0) { return ptr(base, index, shift, disp, kSizeQWord); } //! @brief Create a tword pointer operand. static inline Mem tword_ptr(const GpVar& base, const GpVar& index, uint32_t shift = 0, sysint_t disp = 0) { return ptr(base, index, shift, disp, kSizeTWord); } //! @brief Create a dqword pointer operand. static inline Mem dqword_ptr(const GpVar& base, const GpVar& index, uint32_t shift = 0, sysint_t disp = 0) { return ptr(base, index, shift, disp, kSizeDQWord); } //! @brief Create a mmword pointer operand. static inline Mem mmword_ptr(const GpVar& base, const GpVar& index, uint32_t shift = 0, sysint_t disp = 0) { return ptr(base, index, shift, disp, kSizeQWord); } //! @brief Create a xmmword pointer operand. static inline Mem xmmword_ptr(const GpVar& base, const GpVar& index, uint32_t shift = 0, sysint_t disp = 0) { return ptr(base, index, shift, disp, kSizeDQWord); } //! @brief Create an intptr_t pointer operand. static inline Mem sysint_ptr(const GpVar& base, const GpVar& index, uint32_t shift = 0, sysint_t disp = 0) { return ptr(base, index, shift, disp, sizeof(sysint_t)); } // ============================================================================ // [AsmJit::Macros] // ============================================================================ //! @brief Create Shuffle Constant for MMX/SSE shuffle instrutions. //! @param z First component position, number at interval [0, 3] inclusive. //! @param x Second component position, number at interval [0, 3] inclusive. //! @param y Third component position, number at interval [0, 3] inclusive. //! @param w Fourth component position, number at interval [0, 3] inclusive. //! //! Shuffle constants can be used to make immediate value for these intrinsics: //! - @ref X86Assembler::pshufw() //! - @ref X86Assembler::pshufd() //! - @ref X86Assembler::pshufhw() //! - @ref X86Assembler::pshuflw() //! - @ref X86Assembler::shufps() static inline uint8_t mm_shuffle(uint8_t z, uint8_t y, uint8_t x, uint8_t w) { return (z << 6) | (y << 4) | (x << 2) | w; } //! @} } // AsmJit namespace // [Guard] #endif // _ASMJIT_X86_X86OPERAND_H desmume/src/libretro-common/formats/png/test/rpng_test.c000664 001750 001750 00000012033 12755534123 024635 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2016 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (rpng_test.c). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include #include #include #include #ifdef HAVE_IMLIB2 #include #endif #include #include #include static bool rpng_load_image_argb(const char *path, uint32_t **data, unsigned *width, unsigned *height) { int retval; size_t file_len; bool ret = true; rpng_t *rpng = NULL; void *ptr = NULL; struct nbio_t* handle = (struct nbio_t*)nbio_open(path, NBIO_READ); if (!handle) goto end; nbio_begin_read(handle); while (!nbio_iterate(handle)); ptr = nbio_get_ptr(handle, &file_len); if (!ptr) { ret = false; goto end; } rpng = rpng_alloc(); if (!rpng) { ret = false; goto end; } if (!rpng_set_buf_ptr(rpng, (uint8_t*)ptr)) { ret = false; goto end; } if (!rpng_start(rpng)) { ret = false; goto end; } while (rpng_iterate_image(rpng)); if (!rpng_is_valid(rpng)) { ret = false; goto end; } do { retval = rpng_process_image(rpng, (void**)data, file_len, width, height); }while(retval == IMAGE_PROCESS_NEXT); if (retval == IMAGE_PROCESS_ERROR || retval == IMAGE_PROCESS_ERROR_END) ret = false; end: if (handle) nbio_free(handle); if (rpng) rpng_free(rpng); rpng = NULL; if (!ret) free(*data); return ret; } static int test_rpng(const char *in_path) { #ifdef HAVE_IMLIB2 Imlib_Image img; const uint32_t *imlib_data = NULL; #endif const uint32_t test_data[] = { 0xff000000 | 0x50, 0xff000000 | 0x80, 0xff000000 | 0x40, 0xff000000 | 0x88, 0xff000000 | 0x50, 0xff000000 | 0x80, 0xff000000 | 0x40, 0xff000000 | 0x88, 0xff000000 | 0xc3, 0xff000000 | 0xd3, 0xff000000 | 0xc3, 0xff000000 | 0xd3, 0xff000000 | 0xc3, 0xff000000 | 0xd3, 0xff000000 | 0xc3, 0xff000000 | 0xd3, }; uint32_t *data = NULL; unsigned width = 0; unsigned height = 0; if (!rpng_save_image_argb("/tmp/test.png", test_data, 4, 4, 16)) return 1; if (!rpng_load_image_argb(in_path, &data, &width, &height)) return 2; fprintf(stderr, "Path: %s.\n", in_path); fprintf(stderr, "Got image: %u x %u.\n", width, height); #if 0 fprintf(stderr, "\nRPNG:\n"); for (unsigned h = 0; h < height; h++) { unsigned w; for (w = 0; w < width; w++) fprintf(stderr, "[%08x] ", data[h * width + w]); fprintf(stderr, "\n"); } #endif #ifdef HAVE_IMLIB2 /* Validate with imlib2 as well. */ img = imlib_load_image(in_path); if (!img) return 4; imlib_context_set_image(img); width = imlib_image_get_width(); height = imlib_image_get_width(); imlib_data = imlib_image_get_data_for_reading_only(); #if 0 fprintf(stderr, "\nImlib:\n"); for (unsigned h = 0; h < height; h++) { for (unsigned w = 0; w < width; w++) fprintf(stderr, "[%08x] ", imlib_data[h * width + w]); fprintf(stderr, "\n"); } #endif if (memcmp(imlib_data, data, width * height * sizeof(uint32_t)) != 0) { fprintf(stderr, "Imlib and RPNG differs!\n"); return 5; } else fprintf(stderr, "Imlib and RPNG are equivalent!\n"); imlib_free_image(); #endif free(data); return 0; } int main(int argc, char *argv[]) { const char *in_path = "/tmp/test.png"; if (argc > 2) { fprintf(stderr, "Usage: %s \n", argv[0]); return 1; } if (argc == 2) in_path = argv[1]; fprintf(stderr, "Doing tests...\n"); if (test_rpng(in_path) != 0) { fprintf(stderr, "Test failed.\n"); return -1; } return 0; } desmume/src/libretro-common/include/file/archive_file.h000664 001750 001750 00000012072 12755534123 024404 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2016 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (archive_file.h). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef LIBRETRO_SDK_ARCHIVE_FILE_H__ #define LIBRETRO_SDK_ARCHIVE_FILE_H__ #include #include #include enum file_archive_transfer_type { ZLIB_TRANSFER_NONE = 0, ZLIB_TRANSFER_INIT, ZLIB_TRANSFER_ITERATE, ZLIB_TRANSFER_DEINIT, ZLIB_TRANSFER_DEINIT_ERROR }; typedef struct file_archive_handle { void *stream; uint8_t *data; uint32_t real_checksum; const struct file_archive_file_backend *backend; } file_archive_file_handle_t; struct file_archive_file_backend { void *(*stream_new)(void); void (*stream_free)(void *); void (*stream_set)(void *, uint32_t, uint32_t, const uint8_t *, uint8_t *); uint32_t (*stream_get_avail_in)(void*); uint32_t (*stream_get_avail_out)(void*); uint64_t (*stream_get_total_out)(void*); void (*stream_decrement_total_out)(void *, unsigned); bool (*stream_decompress_init)(void *); bool (*stream_decompress_data_to_file_init)( file_archive_file_handle_t *, const uint8_t *, uint32_t, uint32_t); int (*stream_decompress_data_to_file_iterate)(void *); void (*stream_compress_init)(void *, int); void (*stream_compress_free)(void *); int (*stream_compress_data_to_file)(void *); uint32_t (*stream_crc_calculate)(uint32_t, const uint8_t *, size_t); const char *ident; }; typedef struct file_archive_transfer { void *handle; const uint8_t *footer; const uint8_t *directory; const uint8_t *data; int32_t zip_size; enum file_archive_transfer_type type; const struct file_archive_file_backend *backend; } file_archive_transfer_t; /* Returns true when parsing should continue. False to stop. */ typedef int (*file_archive_file_cb)(const char *name, const char *valid_exts, const uint8_t *cdata, unsigned cmode, uint32_t csize, uint32_t size, uint32_t crc32, void *userdata); int file_archive_parse_file_iterate( file_archive_transfer_t *state, bool *returnerr, const char *file, const char *valid_exts, file_archive_file_cb file_cb, void *userdata); void file_archive_parse_file_iterate_stop(file_archive_transfer_t *state); int file_archive_parse_file_progress(file_archive_transfer_t *state); /** * file_archive_extract_first_content_file: * @zip_path : filename path to ZIP archive. * @zip_path_size : size of ZIP archive. * @valid_exts : valid extensions for a content file. * @extraction_directory : the directory to extract temporary * unzipped content to. * * Extract first content file from archive. * * Returns : true (1) on success, otherwise false (0). **/ bool file_archive_extract_first_content_file(char *zip_path, size_t zip_path_size, const char *valid_exts, const char *extraction_dir, char *out_path, size_t len); /** * file_archive_get_file_list: * @path : filename path of archive * @valid_exts : Valid extensions of archive to be parsed. * If NULL, allow all. * * Returns: string listing of files from archive on success, otherwise NULL. **/ struct string_list *file_archive_get_file_list(const char *path, const char *valid_exts); bool file_archive_perform_mode(const char *name, const char *valid_exts, const uint8_t *cdata, unsigned cmode, uint32_t csize, uint32_t size, uint32_t crc32, void *userdata); struct string_list *compressed_file_list_new(const char *filename, const char* ext); void file_archive_deflate_init(void *data, int level); const struct file_archive_file_backend *file_archive_get_default_file_backend(void); extern const struct file_archive_file_backend zlib_backend; #endif desmume/src/bios.cpp000664 001750 001750 00000120205 12755534123 015577 0ustar00sergiosergio000000 000000 /* Copyright (C) 2006 yopyop Copyright (C) 2008-2016 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the this software. If not, see . */ //this file contains HLE for the arm9 and arm7 bios SWI routines. //it renders the use of bios files generally unnecessary. //it turns out that they're not too complex, although of course the timings will be all wrong here. #include "armcpu.h" #include "cp15.h" #include #include "MMU.h" #include "debug.h" #include "registers.h" #include "NDSSystem.h" #include "utils/bits.h" #define cpu (&ARMPROC) #define TEMPLATE template struct CompressionHeader { public: CompressionHeader(u32 _value) : value(_value) {} u32 DataSize() const { return value&15; } u32 Type() const { return (value>>4)&15; } u32 DecompressedSize() const { return value>>8; } private: u32 value; }; static const 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 const 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 const 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 }; static u32 bios_nop_ARM9(void) { LOG("SWI: ARM%c Unimplemented BIOS function %02X was used. R0:%08X, R1:%08X, R2:%08X\n", '9', (cpu->instruction)&0x1F, cpu->R[0], cpu->R[1], cpu->R[2]); return 3; } static u32 bios_nop_ARM7(void) { LOG("SWI: ARM%c Unimplemented BIOS function %02X was used. R0:%08X, R1:%08X, R2:%08X\n", '7', (cpu->instruction)&0x1F, cpu->R[0], cpu->R[1], cpu->R[2]); return 3; } TEMPLATE static u32 WaitByLoop() { u32 elapsed; //printf("%lld waitbyloop\n",nds_timer); //INFO("ARM%c: SWI 0x03 (WaitByLoop)\n", PROCNUM?'7':'9'); if (PROCNUM == ARMCPU_ARM9) { if (cp15.ctrl & ((1<<16)|(1<<18))) // DTCM or ITCM is on (cache) elapsed = cpu->R[0] * 2; else elapsed = cpu->R[0] * 8; } else elapsed = cpu->R[0] * 4; cpu->R[0] = 0; return elapsed; } static u32 wait4IRQ_ARM9(void) { (&(NDS_ARM9))->waitIRQ = TRUE; (&(NDS_ARM9))->halt_IE_and_IF = TRUE; return 1; } static u32 wait4IRQ_ARM7(void) { (&(NDS_ARM7))->waitIRQ = TRUE; (&(NDS_ARM7))->halt_IE_and_IF = TRUE; return 1; } TEMPLATE static u32 intrWaitARM(void) { //TODO - account for differences between arm7 and arm9 (according to gbatek, the "bug doesn't work") const u32 intrFlagAdr = (PROCNUM == ARMCPU_ARM7) ? 0x380FFF8 : (cp15.DTCMRegion&0xFFFFF000)+0x3FF8; //set IME=1 //without this, no irq handlers can happen (even though IF&IE waits can happily happen) //and so no bits in the OS irq flag variable can get set by the handlers _MMU_write32(0x04000208, 1); //analyze the OS irq flag variable u32 intr = _MMU_read32(intrFlagAdr); u32 intrFlag = (cpu->R[1] & intr); //if the user requested us to discard flags, then clear the flag(s) we're going to be waiting on. //(be sure to only do this only on the first run through. use a little state machine to control that) if(cpu->intrWaitARM_state==0 && cpu->R[0]==1) { intr ^= intrFlag; _MMU_write32(intrFlagAdr, intr); //we want to make sure we wait at least once below intrFlag = 0; } cpu->intrWaitARM_state = 1; //now, if the condition is satisfied (and it won't be the first time through, no matter what, due to cares taken above) if(intrFlag) { //write back the OS irq flags with the ones we were waiting for cleared intr ^= intrFlag; _MMU_write32(intrFlagAdr, intr); cpu->intrWaitARM_state = 0; return 1; } //the condition wasn't satisfied. this means that we need to halt, wait for some enabled interrupt, //and then ensure that we return to this opcode again to check the condition again cpu->waitIRQ = TRUE; cpu->halt_IE_and_IF = TRUE; //(rewire PC to jump back to this opcode) u32 instructAddr = cpu->instruct_adr; cpu->R[15] = instructAddr; cpu->next_instruction = instructAddr; return 1; } TEMPLATE static u32 waitVBlankARM() { cpu->R[0] = 1; cpu->R[1] = 1; return intrWaitARM(); } TEMPLATE static u32 sleep() { //just set REG_HALTCNT to the fixed Sleep value _MMU_write08(REG_HALTCNT, 0xC0); return 1; } //ARM7 only TEMPLATE static u32 CustomHalt() { //just set REG_HALTCNT to the provided value _MMU_write08(REG_HALTCNT, cpu->R[2]); return 1; } static u32 divide_ARM9(void) { s32 res; s32 num = (s32)(&(NDS_ARM9))->R[0]; s32 dnum = (s32)(&(NDS_ARM9))->R[1]; if(dnum==0) return 0; res = num / dnum; (&(NDS_ARM9))->R[0] = (u32)res; (&(NDS_ARM9))->R[1] = (u32)(num % dnum); (&(NDS_ARM9))->R[3] = (u32)abs(res); return 6; } static u32 divide_ARM7(void) { s32 res; s32 num = (s32)(&(NDS_ARM7))->R[0]; s32 dnum = (s32)(&(NDS_ARM7))->R[1]; if(dnum==0) return 0; res = num / dnum; (&(NDS_ARM7))->R[0] = (u32)res; (&(NDS_ARM7))->R[1] = (u32)(num % dnum); (&(NDS_ARM7))->R[3] = (u32)abs(res); return 6; } TEMPLATE static u32 copy() { u32 src = cpu->R[0]; u32 dst = cpu->R[1]; u32 cnt = cpu->R[2]; //INFO("swi copy from %08X to %08X, cnt=%08X\n", src, dst, cnt); switch(BIT26(cnt)) { case 0: src &= 0xFFFFFFFE; dst &= 0xFFFFFFFE; switch(BIT24(cnt)) { case 0: cnt &= 0x1FFFFF; while(cnt) { _MMU_write16(dst, _MMU_read16(src)); cnt--; dst+=2; src+=2; } break; case 1: { u16 val = _MMU_read16(src); cnt &= 0x1FFFFF; while(cnt) { _MMU_write16(dst, val); cnt--; dst+=2; } } break; } break; case 1: src &= 0xFFFFFFFC; dst &= 0xFFFFFFFC; switch(BIT24(cnt)) { case 0: cnt &= 0x1FFFFF; while(cnt) { _MMU_write32(dst, _MMU_read32(src)); cnt--; dst+=4; src+=4; } break; case 1: { u32 val = _MMU_read32(src); cnt &= 0x1FFFFF; while(cnt) { _MMU_write32(dst, val); cnt--; dst+=4; } } break; } break; } return 1; } TEMPLATE static u32 fastCopy() { u32 src = cpu->R[0] & 0xFFFFFFFC; u32 dst = cpu->R[1] & 0xFFFFFFFC; u32 cnt = cpu->R[2]; //INFO("swi fastcopy from %08X to %08X, cnt=%08X\n", src, dst, cnt); switch(BIT24(cnt)) { case 0: cnt &= 0x1FFFFF; while(cnt) { _MMU_write32(dst, _MMU_read32(src)); cnt--; dst+=4; src+=4; } break; case 1: { u32 val = _MMU_read32(src); cnt &= 0x1FFFFF; while(cnt) { _MMU_write32(dst, val); cnt--; dst+=4; } } break; } return 1; } TEMPLATE static u32 LZ77UnCompVram() { 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(source); source += 4; //INFO("swi lz77uncompvram\n"); 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_read08(source++); if(d) { for(i1 = 0; i1 < 8; i1++) { if(d & 0x80) { int length; int offset; u32 windowOffset; u16 data = _MMU_read08(source++) << 8; data |= _MMU_read08(source++); length = (data >> 12) + 3; offset = (data & 0x0FFF); windowOffset = dest + byteCount - offset - 1; for(i2 = 0; i2 < length; i2++) { writeValue |= (_MMU_read08(windowOffset++) << byteShift); byteShift += 8; byteCount++; if(byteCount == 2) { _MMU_write16(dest, writeValue); dest += 2; byteCount = 0; byteShift = 0; writeValue = 0; } len--; if(len == 0) return 0; } } else { writeValue |= (_MMU_read08(source++) << byteShift); byteShift += 8; byteCount++; if(byteCount == 2) { _MMU_write16(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_read08(source++) << byteShift); byteShift += 8; byteCount++; if(byteCount == 2) { _MMU_write16(dest, writeValue); dest += 2; byteShift = 0; byteCount = 0; writeValue = 0; } len--; if(len == 0) return 0; } } } return 1; } TEMPLATE static u32 LZ77UnCompWram() { int i1, i2; int len; u32 source = cpu->R[0]; u32 dest = cpu->R[1]; u32 header = _MMU_read32(source); source += 4; //INFO("swi lz77uncompwram\n"); if(((source & 0xe000000) == 0) || ((source + ((header >> 8) & 0x1fffff)) & 0xe000000) == 0) return 0; len = header >> 8; while(len > 0) { u8 d = _MMU_read08(source++); if(d) { for(i1 = 0; i1 < 8; i1++) { if(d & 0x80) { int length; int offset; u32 windowOffset; u16 data = _MMU_read08(source++) << 8; data |= _MMU_read08(source++); length = (data >> 12) + 3; offset = (data & 0x0FFF); windowOffset = dest - offset - 1; for(i2 = 0; i2 < length; i2++) { _MMU_write08(dest++, _MMU_read08(windowOffset++)); len--; if(len == 0) return 0; } } else { _MMU_write08(dest++, _MMU_read08(source++)); len--; if(len == 0) return 0; } d <<= 1; } } else { for(i1 = 0; i1 < 8; i1++) { _MMU_write08(dest++, _MMU_read08(source++)); len--; if(len == 0) return 0; } } } return 1; } TEMPLATE static u32 RLUnCompVram() { int i; int len; int byteCount; int byteShift; u32 writeValue; u32 source = cpu->R[0]; u32 dest = cpu->R[1]; u32 header = _MMU_read32(source); source += 4; //INFO("swi rluncompvram\n"); 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_read08(source++); int l = d & 0x7F; if(d & 0x80) { u8 data = _MMU_read08(source++); l += 3; for(i = 0;i < l; i++) { writeValue |= (data << byteShift); byteShift += 8; byteCount++; if(byteCount == 2) { _MMU_write16(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_read08(source++) << byteShift); byteShift += 8; byteCount++; if(byteCount == 2) { _MMU_write16(dest, writeValue); dest += 2; byteCount = 0; byteShift = 0; writeValue = 0; } len--; if(len == 0) return 0; } } } return 1; } TEMPLATE static u32 RLUnCompWram() { //this routine is used by yoshi touch&go from the very beginning //printf("RLUnCompWram\n"); int i; int len; u32 source = cpu->R[0]; u32 dest = cpu->R[1]; u32 header = _MMU_read32(source); source += 4; //INFO("swi rluncompwram\n"); if(((source & 0xe000000) == 0) || ((source + ((header >> 8) & 0x1fffff)) & 0xe000000) == 0) return 0; len = header >> 8; while(len > 0) { u8 d = _MMU_read08(source++); int l = d & 0x7F; if(d & 0x80) { u8 data = _MMU_read08(source++); l += 3; for(i = 0;i < l; i++) { _MMU_write08(dest++, data); len--; if(len == 0) return 0; } } else { l++; for(i = 0; i < l; i++) { _MMU_write08(dest++, _MMU_read08(source++)); len--; if(len == 0) return 0; } } } return 1; } TEMPLATE static u32 UnCompHuffman() { //this routine is used by the nintendo logo in the firmware boot screen 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_read32(source); source += 4; //INFO("swi uncomphuffman\n"); if(((source & 0xe000000) == 0) || ((source + ((header >> 8) & 0x1fffff)) & 0xe000000) == 0) return 0; treeSize = _MMU_read08(source++); treeStart = source; source += ((treeSize+1)<<1)-1; // minus because we already skipped one byte len = header >> 8; mask = 0x80000000; data = _MMU_read32(source); source += 4; pos = 0; rootNode = _MMU_read08(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_read08(treeStart+pos+1); } else { // left if(currentNode & 0x80) writeData = 1; currentNode = _MMU_read08(treeStart+pos); } if(writeData) { writeValue |= (currentNode << byteShift); byteCount++; byteShift += 8; pos = 0; currentNode = rootNode; writeData = 0; if(byteCount == 4) { byteCount = 0; byteShift = 0; _MMU_write32(dest, writeValue); writeValue = 0; dest += 4; len -= 4; } } mask >>= 1; if(mask == 0) { mask = 0x80000000; data = _MMU_read32(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_read08(treeStart+pos+1); } else { // left if(currentNode & 0x80) writeData = 1; currentNode = _MMU_read08(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_write32(dest, writeValue); dest += 4; writeValue = 0; len -= 4; } } pos = 0; currentNode = rootNode; writeData = 0; } mask >>= 1; if(mask == 0) { mask = 0x80000000; data = _MMU_read32(source); source += 4; } } } return 1; } TEMPLATE static u32 BitUnPack() { u32 source,dest,header,base,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(header); bits = _MMU_read08(header+2); switch (bits) { case 1: case 2: case 4: case 8: break; default: return (0); // error } dataSize = _MMU_read08(header+3); switch (dataSize) { case 1: case 2: case 4: case 8: case 16: case 32: break; default: return (0); // error } revbits = 8 - bits; base = _MMU_read32(header+4); addBase = (base & 0x80000000) ? 1 : 0; base &= 0x7fffffff; //INFO("SWI10: bitunpack src 0x%08X dst 0x%08X hdr 0x%08X (src len %05i src bits %02i dst bits %02i)\n\n", source, dest, header, len, bits, dataSize); data = 0; bitwritecount = 0; while(1) { len -= 1; if(len < 0) break; mask = 0xff >> revbits; b = _MMU_read08(source); source++; bitcount = 0; while(1) { if(bitcount >= 8) break; temp = b & mask; if(temp) temp += base; else if(addBase) temp += base; //you might think you should do this. but you would be wrong! //this is meant for palette adjusting things, i.e. 16col data to 256col data in colors 240..255. In that case theres no modulo normally. //Users expecting modulo have done something wrong anyway. //temp &= (1<= 32) { _MMU_write32(dest, data); dest += 4; data = 0; bitwritecount = 0; } bitcount += bits; b >>= bits; } } return 1; } TEMPLATE static u32 Diff8bitUnFilterWram() //this one might be different on arm7 and needs checking { //INFO("swi Diff8bitUnFilterWram\n"); u32 source = cpu->R[0]; u32 dest = cpu->R[1]; CompressionHeader header(_MMU_read32(source)); source += 4; if(header.DataSize() != 1) printf("WARNING: incorrect header passed to Diff8bitUnFilterWram\n"); if(header.Type() != 8) printf("WARNING: incorrect header passed to Diff8bitUnFilterWram\n"); u32 len = header.DecompressedSize(); u8 data = _MMU_read08(source++); _MMU_write08(dest++, data); len--; while(len > 0) { u8 diff = _MMU_read08(source++); data += diff; _MMU_write08(dest++, data); len--; } return 1; } TEMPLATE static u32 Diff16bitUnFilter() { //INFO("swi Diff16bitUnFilter\n"); u32 source = cpu->R[0]; u32 dest = cpu->R[1]; CompressionHeader header(_MMU_read32(source)); source += 4; if(header.DataSize() != 2) printf("WARNING: incorrect header passed to Diff16bitUnFilter\n"); if(header.Type() != 8) printf("WARNING: incorrect header passed to Diff16bitUnFilter\n"); u32 len = header.DecompressedSize(); u16 data = _MMU_read16(source); source += 2; _MMU_write16(dest, data); dest += 2; len -= 2; while(len >= 2) { u16 diff = _MMU_read16(source); source += 2; data += diff; _MMU_write16(dest, data); dest += 2; len -= 2; } return 1; } static u32 bios_sqrt_ARM9(void) { (&(NDS_ARM9))->R[0] = (u32)sqrt((double)((&(NDS_ARM9))->R[0])); return 1; } static u32 bios_sqrt_ARM7(void) { (&(NDS_ARM7))->R[0] = (u32)sqrt((double)((&(NDS_ARM9))->R[0])); return 1; } //ARM9 only TEMPLATE static u32 CustomPost() { //just write provided value to REG_POSTFLG _MMU_write08(REG_POSTFLG, cpu->R[0]); return 1; } //ARM7 only static u32 getSineTab(void) { //ds returns garbage according to gbatek, but we must protect ourselves if((&(NDS_ARM7))->R[0] >= ARRAY_SIZE(getsinetbl)) { printf("Invalid SWI getSineTab: %08X\n", (&(NDS_ARM7))->R[0]); return 1; } (&(NDS_ARM7))->R[0] = getsinetbl[(&(NDS_ARM7))->R[0]]; return 1; } //ARM7 only static u32 getPitchTab(void) { //ds returns garbage according to gbatek, but we must protect ourselves if((&(NDS_ARM7))->R[0] >= ARRAY_SIZE(getpitchtbl)) { printf("Invalid SWI getPitchTab: %08X\n",(&(NDS_ARM7))->R[0]); return 1; } (&(NDS_ARM7))->R[0] = getpitchtbl[(&(NDS_ARM7))->R[0]]; return 1; } //ARM7 only static u32 getVolumeTab(void) { //ds returns garbage according to gbatek, but we must protect ourselves if((&(NDS_ARM7))->R[0] >= ARRAY_SIZE(getvoltbl)) { printf("Invalid SWI getVolumeTab: %08X\n", (&(NDS_ARM7))->R[0]); return 1; } (&(NDS_ARM7))->R[0] = getvoltbl[(&(NDS_ARM7))->R[0]]; return 1; } TEMPLATE static u32 getCRC16_old_and_broken(u32 crc, u32 datap, u32 size) { unsigned int i,j; const u16 val[] = { 0xC0C1,0xC181,0xC301,0xC601,0xCC01,0xD801,0xF001,0xA001 }; for(i = 0; i < size; i++) { crc = crc ^ _MMU_read08(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)); } } } return crc; } TEMPLATE static u32 getCRC16() { //dawn of sorrow uses this to checksum its save data; //if this implementation is wrong, then it won't match what the real bios returns, //and savefiles created with a bios will be invalid when loaded with non-bios (and vice-versa). //Once upon a time, desmume was doing this wrongly; this was due to its mis-use of high bits of the input CRC. //Additionally, that implementation was not handling odd sizes and addresses correctly (but this was discovered independently) //We have confirmed that the crc16 works the same on the arm9 and arm7. //The following call is left here so we can A/B test with the old version. Glad I left it, because we keep coming back to this code. //u32 old = getCRC16_old_and_broken(cpu->R[0],cpu->R[1],cpu->R[2]); u16 crc = (u16)cpu->R[0]; u32 datap = cpu->R[1]; u32 size = cpu->R[2]>>1; u16 currVal = 0; const u16 val[] = { 0x0000,0xCC01,0xD801,0x1400,0xF001,0x3C00,0x2800,0xE401,0xA001,0x6C00,0x7800,0xB401,0x5000,0x9C01,0x8801,0x4400}; for(u32 i = 0; i < size; i++) { currVal = _MMU_read16(datap + i*2); for(int j=0;j<4;j++) { u16 tabVal = val[crc&0xF]; crc >>= 4; crc ^= tabVal; u16 tempVal = currVal >> (4*j); tabVal = val[tempVal&0xF]; crc ^= tabVal; } } cpu->R[0] = crc; //R3 contains the last processed halfword //this is significant -- why? Can we get a test case? Supposedly there is one.. cpu->R[3] = currVal; return 1; } static u32 isDebugger_ARM9(void) { //gbatek has additional specifications which are not emulated here if(nds.Is_DebugConsole()) (&(NDS_ARM9))->R[0] = 1; else (&(NDS_ARM9))->R[0] = 0; return 1; } static u32 isDebugger_ARM7(void) { //gbatek has additional specifications which are not emulated here if(nds.Is_DebugConsole()) (&(NDS_ARM7))->R[0] = 1; else (&(NDS_ARM7))->R[0] = 0; return 1; } //ARM7 only static u32 SoundBias(void) { u32 curBias = _MMU_read32(0x04000504); u32 newBias = (curBias == 0) ? 0x000:0x200; u32 delay = (newBias > curBias) ? (newBias-curBias) : (curBias-newBias); _MMU_write32(0x04000504, newBias); return (&(NDS_ARM7))->R[1] * delay; } //ARM7 only static u32 getBootProcs(void) { (&(NDS_ARM7))->R[0] = 0x00000A2E; (&(NDS_ARM7))->R[1] = 0x00002C3C; (&(NDS_ARM7))->R[3] = 0x000005FF; return 1; } static u32 SoftReset(void) { //not emulated yet return 1; } u32 (* ARM_swi_tab[2][32])()={ { SoftReset, // 0x00 bios_nop_ARM9, // 0x01 bios_nop_ARM9, // 0x02 WaitByLoop, // 0x03 intrWaitARM, // 0x04 waitVBlankARM, // 0x05 wait4IRQ_ARM9, /* 0x06 */ bios_nop_ARM9, // 0x07 bios_nop_ARM9, /* 0x08 */ divide_ARM9, /* 0x09 */ bios_nop_ARM9, // 0x0A copy, // 0x0B fastCopy, // 0x0C bios_sqrt_ARM9, /* 0x0D */ getCRC16, // 0x0E isDebugger_ARM9, /* 0x0F */ BitUnPack, // 0x10 LZ77UnCompWram, // 0x11 LZ77UnCompVram, // 0x12 UnCompHuffman, // 0x13 RLUnCompWram, // 0x14 RLUnCompVram, // 0x15 Diff8bitUnFilterWram, // 0x16 bios_nop_ARM9, // 0x17 Diff16bitUnFilter, // 0x18 bios_nop_ARM9, // 0x19 bios_nop_ARM9, // 0x1A bios_nop_ARM9, // 0x1B bios_nop_ARM9, // 0x1C bios_nop_ARM9, // 0x1D bios_nop_ARM9, // 0x1E CustomPost, // 0x1F }, { SoftReset, // 0x00 bios_nop_ARM7, // 0x01 bios_nop_ARM7, // 0x02 WaitByLoop, // 0x03 intrWaitARM, // 0x04 waitVBlankARM, // 0x05 wait4IRQ_ARM7, /* 0x06 */ sleep, // 0x07 SoundBias, /* 0x08 */ divide_ARM7, /* 0x09 */ bios_nop_ARM7, // 0x0A copy, // 0x0B fastCopy, // 0x0C bios_sqrt_ARM7, /* 0x0D */ getCRC16, // 0x0E isDebugger_ARM7, /* 0x0F */ BitUnPack, // 0x10 LZ77UnCompWram, // 0x11 LZ77UnCompVram, // 0x12 UnCompHuffman, // 0x13 RLUnCompWram, // 0x14 RLUnCompVram, // 0x15 bios_nop_ARM7, // 0x16 bios_nop_ARM7, // 0x17 bios_nop_ARM7, // 0x18 bios_nop_ARM7, // 0x19 getSineTab, /* 0x1A */ getPitchTab, /* 0x1B */ getVolumeTab, /* 0x1C */ getBootProcs, /* 0x1D */ bios_nop_ARM7, // 0x1E CustomHalt, // 0x1F } }; #define BIOS_NOP "bios_nop" const char* ARM_swi_names[2][32] = { { "SoftReset", // 0x00 BIOS_NOP, // 0x01 BIOS_NOP, // 0x02 "WaitByLoop", // 0x03 "IntrWait", // 0x04 "VBlankIntrWait", // 0x05 "Halt", // 0x06 BIOS_NOP, // 0x07 BIOS_NOP, // 0x08 "Div", // 0x09 BIOS_NOP, // 0x0A "CpuSet", // 0x0B "CpuFastSet", // 0x0C "Sqrt", // 0x0D "GetCRC16", // 0x0E "IsDebugger", // 0x0F "BitUnPack", // 0x10 "LZ77UnCompWram", // 0x11 "LZ77UnCompVram", // 0x12 "HuffUnComp", // 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 "CustomPost", // 0x1F }, { "SoftReset", // 0x00 BIOS_NOP, // 0x01 BIOS_NOP, // 0x02 "WaitByLoop", // 0x03 "IntrWait", // 0x04 "VBlankIntrWait", // 0x05 "Halt", // 0x06 "Sleep", // 0x07 "SoundBias", // 0x08 "Div", // 0x09 BIOS_NOP, // 0x0A "CpuSet", // 0x0B "CpuFastSet", // 0x0C "Sqrt", // 0x0D "GetCRC16", // 0x0E "IsDebugger", // 0x0F "BitUnPack", // 0x10 "LZ77UnCompWram", // 0x11 "LZ77UnCompVram", // 0x12 "HuffUnComp", // 0x13 "RLUnCompWram", // 0x14 "RLUnCompVram", // 0x15 BIOS_NOP, // 0x16 BIOS_NOP, // 0x17 BIOS_NOP, // 0x18 BIOS_NOP, // 0x19 "GetSineTable", // 0x1A "GetPitchTable", // 0x1B "GetVolumeTable", // 0x1C "GetBootProcs", // 0x1D BIOS_NOP, // 0x1E "CustomHalt", // 0x1F } }; #undef BIOS_NOP desmume/src/libretro-common/algorithms/000700 001750 001750 00000000000 12756420130 021375 5ustar00sergiosergio000000 000000 desmume/src/slot1.cpp000664 001750 001750 00000013330 12755534123 015705 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2013 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the this software. If not, see . */ /* Notes for future development: Despite gbatek's specifications contrariwise, GCDATAIN is writeable. R4 uses this for writes to the card. Despite gbatek's specifications contrariwise, GCROMCTRL[30] can take a value of 1 to indicate that the GC bus transaction should be writes. It is unclear what kicks GC bus transactions. It's possibly bit 31 of GCROMCTRL, but normmatt thinks he might have had to hack around that to make something work, and that it might just be any write to GCROMCTRL. Since GCROMCTRL[26:24] can't represent 'data block size' of 1 or 2, it is assumed that transactions always happen in 4 byte pieces. ...so, any 8/16bit accesses to GCDATAIN would transfer a whole 32bit unit and then just return the requested portion */ //TODO - create a Slot1_TurboRom which we can select when booting from fakebios/nonfirmware and which would provide a useful service to people porting to tighter platforms by bypassing largely useless cruft #include #include "types.h" #include "slot1.h" #include "NDSSystem.h" #include "emufile.h" #include "utils/vfat.h" #include "path.h" bool slot1_R4_path_type = false; //------- //fat-related common elements static EMUFILE* fatImage = NULL; static std::string fatDir; static void scanDir() { if(fatDir == "") return; if (fatImage) { delete fatImage; fatImage = NULL; } VFAT vfat; if(vfat.build(slot1_R4_path_type?path.RomDirectory.c_str():fatDir.c_str(), 16)) fatImage = vfat.detach(); } void slot1_SetFatDir(const std::string& dir, bool sameAsRom) { //printf("FAT path %s\n", dir.c_str()); slot1_R4_path_type = sameAsRom; if (!slot1_R4_path_type) fatDir = dir; } std::string slot1_GetFatDir() { return fatDir; } EMUFILE* slot1_GetFatImage() { return fatImage; } //------------ ISlot1Interface* slot1_List[NDS_SLOT1_COUNT] = {0}; ISlot1Interface* slot1_device = NULL; NDS_SLOT1_TYPE slot1_device_type = NDS_SLOT1_RETAIL_AUTO; //default for frontends that dont even configure this NDS_SLOT1_TYPE slot1_selected_type = NDS_SLOT1_NONE; void slot1_Init() { //due to sloppy initialization code in various untestable desmume ports, we might try this more than once static bool initialized = false; if(initialized) return; initialized = true; //construct all devices extern TISlot1InterfaceConstructor construct_Slot1_None; extern TISlot1InterfaceConstructor construct_Slot1_Retail_Auto; extern TISlot1InterfaceConstructor construct_Slot1_R4; extern TISlot1InterfaceConstructor construct_Slot1_Retail_NAND; extern TISlot1InterfaceConstructor construct_Slot1_Retail_MCROM; extern TISlot1InterfaceConstructor construct_Slot1_Retail_DEBUG; slot1_List[NDS_SLOT1_NONE] = construct_Slot1_None(); slot1_List[NDS_SLOT1_RETAIL_AUTO] = construct_Slot1_Retail_Auto(); slot1_List[NDS_SLOT1_R4] = construct_Slot1_R4(); slot1_List[NDS_SLOT1_RETAIL_NAND] = construct_Slot1_Retail_NAND(); slot1_List[NDS_SLOT1_RETAIL_MCROM] = construct_Slot1_Retail_MCROM(); #ifndef VITA slot1_List[NDS_SLOT1_RETAIL_DEBUG] = construct_Slot1_Retail_DEBUG(); #endif } void slot1_Shutdown() { for(int i=0;ishutdown(); delete slot1_List[i]; } } bool slot1_Connect() { slot1_device->connect(); return true; } void slot1_Disconnect() { slot1_device->disconnect(); //be careful to do this second, maybe the device will write something more if (fatImage) { delete fatImage; fatImage = NULL; } } void slot1_Reset() { //disconnect existing device if(slot1_device != NULL) slot1_device->disconnect(); //connect new device slot1_device = slot1_List[slot1_device_type]; if (slot1_device_type == NDS_SLOT1_R4) scanDir(); slot1_device->connect(); } bool slot1_Change(NDS_SLOT1_TYPE changeToType) { if((changeToType == slot1_device_type) || (changeToType == slot1_GetSelectedType())) return FALSE; //nothing to do if (changeToType > NDS_SLOT1_COUNT || changeToType < 0) return FALSE; if(slot1_device != NULL) slot1_device->disconnect(); slot1_device_type = changeToType; slot1_device = slot1_List[slot1_device_type]; printf("Slot 1: %s\n", slot1_device->info()->name()); printf("sending eject signal to SLOT-1\n"); NDS_TriggerCardEjectIRQ(); slot1_device->connect(); return true; } bool slot1_getTypeByID(u8 ID, NDS_SLOT1_TYPE &type) { for (u8 i = 0; i < NDS_SLOT1_COUNT; i++) { if (slot1_List[i]->info()->id() == ID) { type = (NDS_SLOT1_TYPE)i; return true; } } return false; } bool slot1_ChangeByID(u8 ID) { NDS_SLOT1_TYPE type = NDS_SLOT1_RETAIL_AUTO; slot1_getTypeByID(ID, type); return slot1_Change(type); } NDS_SLOT1_TYPE slot1_GetCurrentType() { return slot1_device_type; } NDS_SLOT1_TYPE slot1_GetSelectedType() { if (slot1_device_type == NDS_SLOT1_RETAIL_AUTO) return slot1_selected_type; return slot1_device_type; } void slot1_Savestate(EMUFILE* os) { slot1_device->savestate(os); } void slot1_Loadstate(EMUFILE* is) { slot1_device->loadstate(is); } desmume/src/libretro-common/include/queues/000700 001750 001750 00000000000 12756420131 022157 5ustar00sergiosergio000000 000000 desmume/src/libretro-common/features/000700 001750 001750 00000000000 12756420131 021043 5ustar00sergiosergio000000 000000 desmume/src/libretro-common/include/retro_endianness.h000664 001750 001750 00000013175 12755534123 024414 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2015 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (retro_endianness.h). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef __LIBRETRO_SDK_ENDIANNESS_H #define __LIBRETRO_SDK_ENDIANNESS_H #include #include #include #if defined(_MSC_VER) #define SWAP16 _byteswap_ushort #define SWAP32 _byteswap_ulong #else #define SWAP16(x) ((uint16_t)( \ (((uint16_t)(x) & 0x00ff) << 8) | \ (((uint16_t)(x) & 0xff00) >> 8) \ )) #define SWAP32(x) ((uint32_t)( \ (((uint32_t)(x) & 0x000000ff) << 24) | \ (((uint32_t)(x) & 0x0000ff00) << 8) | \ (((uint32_t)(x) & 0x00ff0000) >> 8) | \ (((uint32_t)(x) & 0xff000000) >> 24) \ )) #endif #define SWAP64(val) \ ((((uint64_t)(val) & 0x00000000000000ffULL) << 56) \ | (((uint64_t)(val) & 0x000000000000ff00ULL) << 40) \ | (((uint64_t)(val) & 0x0000000000ff0000ULL) << 24) \ | (((uint64_t)(val) & 0x00000000ff000000ULL) << 8) \ | (((uint64_t)(val) & 0x000000ff00000000ULL) >> 8) \ | (((uint64_t)(val) & 0x0000ff0000000000ULL) >> 24) \ | (((uint64_t)(val) & 0x00ff000000000000ULL) >> 40) \ | (((uint64_t)(val) & 0xff00000000000000ULL) >> 56)) /** * is_little_endian: * * Checks if the system is little endian or big-endian. * * Returns: greater than 0 if little-endian, * otherwise big-endian. **/ static INLINE uint8_t is_little_endian(void) { #if defined(__x86_64) || defined(__i386) || defined(_M_IX86) || defined(_M_X64) return 1; #elif defined(MSB_FIRST) return 0; #else union { uint16_t x; uint8_t y[2]; } u; u.x = 1; return u.y[0]; #endif } /** * swap_if_big64: * @val : unsigned 64-bit value * * Byteswap unsigned 64-bit value if system is big-endian. * * Returns: Byteswapped value in case system is big-endian, * otherwise returns same value. **/ static INLINE uint64_t swap_if_big64(uint64_t val) { if (is_little_endian()) return val; return SWAP64(val); } /** * swap_if_big32: * @val : unsigned 32-bit value * * Byteswap unsigned 32-bit value if system is big-endian. * * Returns: Byteswapped value in case system is big-endian, * otherwise returns same value. **/ static INLINE uint32_t swap_if_big32(uint32_t val) { if (is_little_endian()) return val; return SWAP32(val); } /** * swap_if_little64: * @val : unsigned 64-bit value * * Byteswap unsigned 64-bit value if system is little-endian. * * Returns: Byteswapped value in case system is little-endian, * otherwise returns same value. **/ static INLINE uint64_t swap_if_little64(uint64_t val) { if (is_little_endian()) return SWAP64(val); return val; } /** * swap_if_little32: * @val : unsigned 32-bit value * * Byteswap unsigned 32-bit value if system is little-endian. * * Returns: Byteswapped value in case system is little-endian, * otherwise returns same value. **/ static INLINE uint32_t swap_if_little32(uint32_t val) { if (is_little_endian()) return SWAP32(val); return val; } /** * swap_if_big16: * @val : unsigned 16-bit value * * Byteswap unsigned 16-bit value if system is big-endian. * * Returns: Byteswapped value in case system is big-endian, * otherwise returns same value. **/ static INLINE uint16_t swap_if_big16(uint16_t val) { if (is_little_endian()) return val; return SWAP16(val); } /** * swap_if_little16: * @val : unsigned 16-bit value * * Byteswap unsigned 16-bit value if system is little-endian. * * Returns: Byteswapped value in case system is little-endian, * otherwise returns same value. **/ static INLINE uint16_t swap_if_little16(uint16_t val) { if (is_little_endian()) return SWAP16(val); return val; } /** * store32be: * @addr : pointer to unsigned 32-bit buffer * @data : unsigned 32-bit value to write * * Write data to address. Endian-safe. Byteswaps the data * first if necessary before storing it. **/ static INLINE void store32be(uint32_t *addr, uint32_t data) { *addr = swap_if_little32(data); } /** * load32be: * @addr : pointer to unsigned 32-bit buffer * * Load value from address. Endian-safe. * * Returns: value from address, byte-swapped if necessary. **/ static INLINE uint32_t load32be(const uint32_t *addr) { return swap_if_little32(*addr); } #endif desmume/src/libretro-common/encodings/000700 001750 001750 00000000000 12756420131 021176 5ustar00sergiosergio000000 000000 desmume/src/libretro-common/include/glsym/glsym_gl.h000664 001750 001750 00000716302 12755534123 024024 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2015 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this libretro SDK code part (glsym). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef RGLGEN_DECL_H__ #define RGLGEN_DECL_H__ #ifdef __cplusplus extern "C" { #endif #ifdef GL_APIENTRY typedef void (GL_APIENTRY *RGLGENGLDEBUGPROC)(GLenum, GLenum, GLuint, GLenum, GLsizei, const GLchar*, GLvoid*); typedef void (GL_APIENTRY *RGLGENGLDEBUGPROCKHR)(GLenum, GLenum, GLuint, GLenum, GLsizei, const GLchar*, GLvoid*); #else #ifndef APIENTRY #define APIENTRY #endif #ifndef APIENTRYP #define APIENTRYP APIENTRY * #endif typedef void (APIENTRY *RGLGENGLDEBUGPROCARB)(GLenum, GLenum, GLuint, GLenum, GLsizei, const GLchar*, GLvoid*); typedef void (APIENTRY *RGLGENGLDEBUGPROC)(GLenum, GLenum, GLuint, GLenum, GLsizei, const GLchar*, GLvoid*); #endif #ifndef GL_OES_EGL_image typedef void *GLeglImageOES; #endif #if !defined(GL_OES_fixed_point) && !defined(HAVE_OPENGLES2) typedef GLint GLfixed; #endif #if defined(__MACH__) && !defined(OS_TARGET_IPHONE) && !defined(MAC_OS_X_VERSION_10_7) typedef long long int GLint64; typedef unsigned long long int GLuint64; typedef unsigned long long int GLuint64EXT; typedef struct __GLsync *GLsync; #endif typedef void (APIENTRYP RGLSYMGLDRAWRANGEELEMENTSPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices); typedef void (APIENTRYP RGLSYMGLTEXIMAGE3DPROC) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels); typedef void (APIENTRYP RGLSYMGLTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels); typedef void (APIENTRYP RGLSYMGLCOPYTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); typedef void (APIENTRYP RGLSYMGLACTIVETEXTUREPROC) (GLenum texture); typedef void (APIENTRYP RGLSYMGLSAMPLECOVERAGEPROC) (GLfloat value, GLboolean invert); typedef void (APIENTRYP RGLSYMGLCOMPRESSEDTEXIMAGE3DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data); typedef void (APIENTRYP RGLSYMGLCOMPRESSEDTEXIMAGE2DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *data); typedef void (APIENTRYP RGLSYMGLCOMPRESSEDTEXIMAGE1DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const void *data); typedef void (APIENTRYP RGLSYMGLCOMPRESSEDTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data); typedef void (APIENTRYP RGLSYMGLCOMPRESSEDTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data); typedef void (APIENTRYP RGLSYMGLCOMPRESSEDTEXSUBIMAGE1DPROC) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void *data); typedef void (APIENTRYP RGLSYMGLGETCOMPRESSEDTEXIMAGEPROC) (GLenum target, GLint level, void *img); typedef void (APIENTRYP RGLSYMGLCLIENTACTIVETEXTUREPROC) (GLenum texture); typedef void (APIENTRYP RGLSYMGLMULTITEXCOORD1DPROC) (GLenum target, GLdouble s); typedef void (APIENTRYP RGLSYMGLMULTITEXCOORD1DVPROC) (GLenum target, const GLdouble *v); typedef void (APIENTRYP RGLSYMGLMULTITEXCOORD1FPROC) (GLenum target, GLfloat s); typedef void (APIENTRYP RGLSYMGLMULTITEXCOORD1FVPROC) (GLenum target, const GLfloat *v); typedef void (APIENTRYP RGLSYMGLMULTITEXCOORD1IPROC) (GLenum target, GLint s); typedef void (APIENTRYP RGLSYMGLMULTITEXCOORD1IVPROC) (GLenum target, const GLint *v); typedef void (APIENTRYP RGLSYMGLMULTITEXCOORD1SPROC) (GLenum target, GLshort s); typedef void (APIENTRYP RGLSYMGLMULTITEXCOORD1SVPROC) (GLenum target, const GLshort *v); typedef void (APIENTRYP RGLSYMGLMULTITEXCOORD2DPROC) (GLenum target, GLdouble s, GLdouble t); typedef void (APIENTRYP RGLSYMGLMULTITEXCOORD2DVPROC) (GLenum target, const GLdouble *v); typedef void (APIENTRYP RGLSYMGLMULTITEXCOORD2FPROC) (GLenum target, GLfloat s, GLfloat t); typedef void (APIENTRYP RGLSYMGLMULTITEXCOORD2FVPROC) (GLenum target, const GLfloat *v); typedef void (APIENTRYP RGLSYMGLMULTITEXCOORD2IPROC) (GLenum target, GLint s, GLint t); typedef void (APIENTRYP RGLSYMGLMULTITEXCOORD2IVPROC) (GLenum target, const GLint *v); typedef void (APIENTRYP RGLSYMGLMULTITEXCOORD2SPROC) (GLenum target, GLshort s, GLshort t); typedef void (APIENTRYP RGLSYMGLMULTITEXCOORD2SVPROC) (GLenum target, const GLshort *v); typedef void (APIENTRYP RGLSYMGLMULTITEXCOORD3DPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r); typedef void (APIENTRYP RGLSYMGLMULTITEXCOORD3DVPROC) (GLenum target, const GLdouble *v); typedef void (APIENTRYP RGLSYMGLMULTITEXCOORD3FPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r); typedef void (APIENTRYP RGLSYMGLMULTITEXCOORD3FVPROC) (GLenum target, const GLfloat *v); typedef void (APIENTRYP RGLSYMGLMULTITEXCOORD3IPROC) (GLenum target, GLint s, GLint t, GLint r); typedef void (APIENTRYP RGLSYMGLMULTITEXCOORD3IVPROC) (GLenum target, const GLint *v); typedef void (APIENTRYP RGLSYMGLMULTITEXCOORD3SPROC) (GLenum target, GLshort s, GLshort t, GLshort r); typedef void (APIENTRYP RGLSYMGLMULTITEXCOORD3SVPROC) (GLenum target, const GLshort *v); typedef void (APIENTRYP RGLSYMGLMULTITEXCOORD4DPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q); typedef void (APIENTRYP RGLSYMGLMULTITEXCOORD4DVPROC) (GLenum target, const GLdouble *v); typedef void (APIENTRYP RGLSYMGLMULTITEXCOORD4FPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q); typedef void (APIENTRYP RGLSYMGLMULTITEXCOORD4FVPROC) (GLenum target, const GLfloat *v); typedef void (APIENTRYP RGLSYMGLMULTITEXCOORD4IPROC) (GLenum target, GLint s, GLint t, GLint r, GLint q); typedef void (APIENTRYP RGLSYMGLMULTITEXCOORD4IVPROC) (GLenum target, const GLint *v); typedef void (APIENTRYP RGLSYMGLMULTITEXCOORD4SPROC) (GLenum target, GLshort s, GLshort t, GLshort r, GLshort q); typedef void (APIENTRYP RGLSYMGLMULTITEXCOORD4SVPROC) (GLenum target, const GLshort *v); typedef void (APIENTRYP RGLSYMGLLOADTRANSPOSEMATRIXFPROC) (const GLfloat *m); typedef void (APIENTRYP RGLSYMGLLOADTRANSPOSEMATRIXDPROC) (const GLdouble *m); typedef void (APIENTRYP RGLSYMGLMULTTRANSPOSEMATRIXFPROC) (const GLfloat *m); typedef void (APIENTRYP RGLSYMGLMULTTRANSPOSEMATRIXDPROC) (const GLdouble *m); typedef void (APIENTRYP RGLSYMGLBLENDFUNCSEPARATEPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha); typedef void (APIENTRYP RGLSYMGLMULTIDRAWARRAYSPROC) (GLenum mode, const GLint *first, const GLsizei *count, GLsizei drawcount); typedef void (APIENTRYP RGLSYMGLMULTIDRAWELEMENTSPROC) (GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei drawcount); typedef void (APIENTRYP RGLSYMGLPOINTPARAMETERFPROC) (GLenum pname, GLfloat param); typedef void (APIENTRYP RGLSYMGLPOINTPARAMETERFVPROC) (GLenum pname, const GLfloat *params); typedef void (APIENTRYP RGLSYMGLPOINTPARAMETERIPROC) (GLenum pname, GLint param); typedef void (APIENTRYP RGLSYMGLPOINTPARAMETERIVPROC) (GLenum pname, const GLint *params); typedef void (APIENTRYP RGLSYMGLFOGCOORDFPROC) (GLfloat coord); typedef void (APIENTRYP RGLSYMGLFOGCOORDFVPROC) (const GLfloat *coord); typedef void (APIENTRYP RGLSYMGLFOGCOORDDPROC) (GLdouble coord); typedef void (APIENTRYP RGLSYMGLFOGCOORDDVPROC) (const GLdouble *coord); typedef void (APIENTRYP RGLSYMGLFOGCOORDPOINTERPROC) (GLenum type, GLsizei stride, const void *pointer); typedef void (APIENTRYP RGLSYMGLSECONDARYCOLOR3BPROC) (GLbyte red, GLbyte green, GLbyte blue); typedef void (APIENTRYP RGLSYMGLSECONDARYCOLOR3BVPROC) (const GLbyte *v); typedef void (APIENTRYP RGLSYMGLSECONDARYCOLOR3DPROC) (GLdouble red, GLdouble green, GLdouble blue); typedef void (APIENTRYP RGLSYMGLSECONDARYCOLOR3DVPROC) (const GLdouble *v); typedef void (APIENTRYP RGLSYMGLSECONDARYCOLOR3FPROC) (GLfloat red, GLfloat green, GLfloat blue); typedef void (APIENTRYP RGLSYMGLSECONDARYCOLOR3FVPROC) (const GLfloat *v); typedef void (APIENTRYP RGLSYMGLSECONDARYCOLOR3IPROC) (GLint red, GLint green, GLint blue); typedef void (APIENTRYP RGLSYMGLSECONDARYCOLOR3IVPROC) (const GLint *v); typedef void (APIENTRYP RGLSYMGLSECONDARYCOLOR3SPROC) (GLshort red, GLshort green, GLshort blue); typedef void (APIENTRYP RGLSYMGLSECONDARYCOLOR3SVPROC) (const GLshort *v); typedef void (APIENTRYP RGLSYMGLSECONDARYCOLOR3UBPROC) (GLubyte red, GLubyte green, GLubyte blue); typedef void (APIENTRYP RGLSYMGLSECONDARYCOLOR3UBVPROC) (const GLubyte *v); typedef void (APIENTRYP RGLSYMGLSECONDARYCOLOR3UIPROC) (GLuint red, GLuint green, GLuint blue); typedef void (APIENTRYP RGLSYMGLSECONDARYCOLOR3UIVPROC) (const GLuint *v); typedef void (APIENTRYP RGLSYMGLSECONDARYCOLOR3USPROC) (GLushort red, GLushort green, GLushort blue); typedef void (APIENTRYP RGLSYMGLSECONDARYCOLOR3USVPROC) (const GLushort *v); typedef void (APIENTRYP RGLSYMGLSECONDARYCOLORPOINTERPROC) (GLint size, GLenum type, GLsizei stride, const void *pointer); typedef void (APIENTRYP RGLSYMGLWINDOWPOS2DPROC) (GLdouble x, GLdouble y); typedef void (APIENTRYP RGLSYMGLWINDOWPOS2DVPROC) (const GLdouble *v); typedef void (APIENTRYP RGLSYMGLWINDOWPOS2FPROC) (GLfloat x, GLfloat y); typedef void (APIENTRYP RGLSYMGLWINDOWPOS2FVPROC) (const GLfloat *v); typedef void (APIENTRYP RGLSYMGLWINDOWPOS2IPROC) (GLint x, GLint y); typedef void (APIENTRYP RGLSYMGLWINDOWPOS2IVPROC) (const GLint *v); typedef void (APIENTRYP RGLSYMGLWINDOWPOS2SPROC) (GLshort x, GLshort y); typedef void (APIENTRYP RGLSYMGLWINDOWPOS2SVPROC) (const GLshort *v); typedef void (APIENTRYP RGLSYMGLWINDOWPOS3DPROC) (GLdouble x, GLdouble y, GLdouble z); typedef void (APIENTRYP RGLSYMGLWINDOWPOS3DVPROC) (const GLdouble *v); typedef void (APIENTRYP RGLSYMGLWINDOWPOS3FPROC) (GLfloat x, GLfloat y, GLfloat z); typedef void (APIENTRYP RGLSYMGLWINDOWPOS3FVPROC) (const GLfloat *v); typedef void (APIENTRYP RGLSYMGLWINDOWPOS3IPROC) (GLint x, GLint y, GLint z); typedef void (APIENTRYP RGLSYMGLWINDOWPOS3IVPROC) (const GLint *v); typedef void (APIENTRYP RGLSYMGLWINDOWPOS3SPROC) (GLshort x, GLshort y, GLshort z); typedef void (APIENTRYP RGLSYMGLWINDOWPOS3SVPROC) (const GLshort *v); typedef void (APIENTRYP RGLSYMGLBLENDCOLORPROC) (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); typedef void (APIENTRYP RGLSYMGLBLENDEQUATIONPROC) (GLenum mode); typedef void (APIENTRYP RGLSYMGLGENQUERIESPROC) (GLsizei n, GLuint *ids); typedef void (APIENTRYP RGLSYMGLDELETEQUERIESPROC) (GLsizei n, const GLuint *ids); typedef GLboolean (APIENTRYP RGLSYMGLISQUERYPROC) (GLuint id); typedef void (APIENTRYP RGLSYMGLBEGINQUERYPROC) (GLenum target, GLuint id); typedef void (APIENTRYP RGLSYMGLENDQUERYPROC) (GLenum target); typedef void (APIENTRYP RGLSYMGLGETQUERYIVPROC) (GLenum target, GLenum pname, GLint *params); typedef void (APIENTRYP RGLSYMGLGETQUERYOBJECTIVPROC) (GLuint id, GLenum pname, GLint *params); typedef void (APIENTRYP RGLSYMGLGETQUERYOBJECTUIVPROC) (GLuint id, GLenum pname, GLuint *params); typedef void (APIENTRYP RGLSYMGLBINDBUFFERPROC) (GLenum target, GLuint buffer); typedef void (APIENTRYP RGLSYMGLDELETEBUFFERSPROC) (GLsizei n, const GLuint *buffers); typedef void (APIENTRYP RGLSYMGLGENBUFFERSPROC) (GLsizei n, GLuint *buffers); typedef GLboolean (APIENTRYP RGLSYMGLISBUFFERPROC) (GLuint buffer); typedef void (APIENTRYP RGLSYMGLBUFFERDATAPROC) (GLenum target, GLsizeiptr size, const void *data, GLenum usage); typedef void (APIENTRYP RGLSYMGLBUFFERSUBDATAPROC) (GLenum target, GLintptr offset, GLsizeiptr size, const void *data); typedef void (APIENTRYP RGLSYMGLGETBUFFERSUBDATAPROC) (GLenum target, GLintptr offset, GLsizeiptr size, void *data); typedef void *(APIENTRYP RGLSYMGLMAPBUFFERPROC) (GLenum target, GLenum access); typedef GLboolean (APIENTRYP RGLSYMGLUNMAPBUFFERPROC) (GLenum target); typedef void (APIENTRYP RGLSYMGLGETBUFFERPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params); typedef void (APIENTRYP RGLSYMGLGETBUFFERPOINTERVPROC) (GLenum target, GLenum pname, void **params); typedef void (APIENTRYP RGLSYMGLBLENDEQUATIONSEPARATEPROC) (GLenum modeRGB, GLenum modeAlpha); typedef void (APIENTRYP RGLSYMGLDRAWBUFFERSPROC) (GLsizei n, const GLenum *bufs); typedef void (APIENTRYP RGLSYMGLSTENCILOPSEPARATEPROC) (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass); typedef void (APIENTRYP RGLSYMGLSTENCILFUNCSEPARATEPROC) (GLenum face, GLenum func, GLint ref, GLuint mask); typedef void (APIENTRYP RGLSYMGLSTENCILMASKSEPARATEPROC) (GLenum face, GLuint mask); typedef void (APIENTRYP RGLSYMGLATTACHSHADERPROC) (GLuint program, GLuint shader); typedef void (APIENTRYP RGLSYMGLBINDATTRIBLOCATIONPROC) (GLuint program, GLuint index, const GLchar *name); typedef void (APIENTRYP RGLSYMGLCOMPILESHADERPROC) (GLuint shader); typedef GLuint (APIENTRYP RGLSYMGLCREATEPROGRAMPROC) (void); typedef GLuint (APIENTRYP RGLSYMGLCREATESHADERPROC) (GLenum type); typedef void (APIENTRYP RGLSYMGLDELETEPROGRAMPROC) (GLuint program); typedef void (APIENTRYP RGLSYMGLDELETESHADERPROC) (GLuint shader); typedef void (APIENTRYP RGLSYMGLDETACHSHADERPROC) (GLuint program, GLuint shader); typedef void (APIENTRYP RGLSYMGLDISABLEVERTEXATTRIBARRAYPROC) (GLuint index); typedef void (APIENTRYP RGLSYMGLENABLEVERTEXATTRIBARRAYPROC) (GLuint index); typedef void (APIENTRYP RGLSYMGLGETACTIVEATTRIBPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name); typedef void (APIENTRYP RGLSYMGLGETACTIVEUNIFORMPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name); typedef void (APIENTRYP RGLSYMGLGETATTACHEDSHADERSPROC) (GLuint program, GLsizei maxCount, GLsizei *count, GLuint *shaders); typedef GLint (APIENTRYP RGLSYMGLGETATTRIBLOCATIONPROC) (GLuint program, const GLchar *name); typedef void (APIENTRYP RGLSYMGLGETPROGRAMIVPROC) (GLuint program, GLenum pname, GLint *params); typedef void (APIENTRYP RGLSYMGLGETPROGRAMINFOLOGPROC) (GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog); typedef void (APIENTRYP RGLSYMGLGETSHADERIVPROC) (GLuint shader, GLenum pname, GLint *params); typedef void (APIENTRYP RGLSYMGLGETSHADERINFOLOGPROC) (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog); typedef void (APIENTRYP RGLSYMGLGETSHADERSOURCEPROC) (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *source); typedef GLint (APIENTRYP RGLSYMGLGETUNIFORMLOCATIONPROC) (GLuint program, const GLchar *name); typedef void (APIENTRYP RGLSYMGLGETUNIFORMFVPROC) (GLuint program, GLint location, GLfloat *params); typedef void (APIENTRYP RGLSYMGLGETUNIFORMIVPROC) (GLuint program, GLint location, GLint *params); typedef void (APIENTRYP RGLSYMGLGETVERTEXATTRIBDVPROC) (GLuint index, GLenum pname, GLdouble *params); typedef void (APIENTRYP RGLSYMGLGETVERTEXATTRIBFVPROC) (GLuint index, GLenum pname, GLfloat *params); typedef void (APIENTRYP RGLSYMGLGETVERTEXATTRIBIVPROC) (GLuint index, GLenum pname, GLint *params); typedef void (APIENTRYP RGLSYMGLGETVERTEXATTRIBPOINTERVPROC) (GLuint index, GLenum pname, void **pointer); typedef GLboolean (APIENTRYP RGLSYMGLISPROGRAMPROC) (GLuint program); typedef GLboolean (APIENTRYP RGLSYMGLISSHADERPROC) (GLuint shader); typedef void (APIENTRYP RGLSYMGLLINKPROGRAMPROC) (GLuint program); typedef void (APIENTRYP RGLSYMGLSHADERSOURCEPROC) (GLuint shader, GLsizei count, const GLchar *const*string, const GLint *length); typedef void (APIENTRYP RGLSYMGLUSEPROGRAMPROC) (GLuint program); typedef void (APIENTRYP RGLSYMGLUNIFORM1FPROC) (GLint location, GLfloat v0); typedef void (APIENTRYP RGLSYMGLUNIFORM2FPROC) (GLint location, GLfloat v0, GLfloat v1); typedef void (APIENTRYP RGLSYMGLUNIFORM3FPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2); typedef void (APIENTRYP RGLSYMGLUNIFORM4FPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); typedef void (APIENTRYP RGLSYMGLUNIFORM1IPROC) (GLint location, GLint v0); typedef void (APIENTRYP RGLSYMGLUNIFORM2IPROC) (GLint location, GLint v0, GLint v1); typedef void (APIENTRYP RGLSYMGLUNIFORM3IPROC) (GLint location, GLint v0, GLint v1, GLint v2); typedef void (APIENTRYP RGLSYMGLUNIFORM4IPROC) (GLint location, GLint v0, GLint v1, GLint v2, GLint v3); typedef void (APIENTRYP RGLSYMGLUNIFORM1FVPROC) (GLint location, GLsizei count, const GLfloat *value); typedef void (APIENTRYP RGLSYMGLUNIFORM2FVPROC) (GLint location, GLsizei count, const GLfloat *value); typedef void (APIENTRYP RGLSYMGLUNIFORM3FVPROC) (GLint location, GLsizei count, const GLfloat *value); typedef void (APIENTRYP RGLSYMGLUNIFORM4FVPROC) (GLint location, GLsizei count, const GLfloat *value); typedef void (APIENTRYP RGLSYMGLUNIFORM1IVPROC) (GLint location, GLsizei count, const GLint *value); typedef void (APIENTRYP RGLSYMGLUNIFORM2IVPROC) (GLint location, GLsizei count, const GLint *value); typedef void (APIENTRYP RGLSYMGLUNIFORM3IVPROC) (GLint location, GLsizei count, const GLint *value); typedef void (APIENTRYP RGLSYMGLUNIFORM4IVPROC) (GLint location, GLsizei count, const GLint *value); typedef void (APIENTRYP RGLSYMGLUNIFORMMATRIX2FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); typedef void (APIENTRYP RGLSYMGLUNIFORMMATRIX3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); typedef void (APIENTRYP RGLSYMGLUNIFORMMATRIX4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); typedef void (APIENTRYP RGLSYMGLVALIDATEPROGRAMPROC) (GLuint program); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIB1DPROC) (GLuint index, GLdouble x); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIB1DVPROC) (GLuint index, const GLdouble *v); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIB1FPROC) (GLuint index, GLfloat x); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIB1FVPROC) (GLuint index, const GLfloat *v); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIB1SPROC) (GLuint index, GLshort x); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIB1SVPROC) (GLuint index, const GLshort *v); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIB2DPROC) (GLuint index, GLdouble x, GLdouble y); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIB2DVPROC) (GLuint index, const GLdouble *v); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIB2FPROC) (GLuint index, GLfloat x, GLfloat y); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIB2FVPROC) (GLuint index, const GLfloat *v); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIB2SPROC) (GLuint index, GLshort x, GLshort y); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIB2SVPROC) (GLuint index, const GLshort *v); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIB3DPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIB3DVPROC) (GLuint index, const GLdouble *v); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIB3FPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIB3FVPROC) (GLuint index, const GLfloat *v); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIB3SPROC) (GLuint index, GLshort x, GLshort y, GLshort z); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIB3SVPROC) (GLuint index, const GLshort *v); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIB4NBVPROC) (GLuint index, const GLbyte *v); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIB4NIVPROC) (GLuint index, const GLint *v); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIB4NSVPROC) (GLuint index, const GLshort *v); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIB4NUBPROC) (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIB4NUBVPROC) (GLuint index, const GLubyte *v); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIB4NUIVPROC) (GLuint index, const GLuint *v); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIB4NUSVPROC) (GLuint index, const GLushort *v); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIB4BVPROC) (GLuint index, const GLbyte *v); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIB4DPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIB4DVPROC) (GLuint index, const GLdouble *v); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIB4FPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIB4FVPROC) (GLuint index, const GLfloat *v); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIB4IVPROC) (GLuint index, const GLint *v); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIB4SPROC) (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIB4SVPROC) (GLuint index, const GLshort *v); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIB4UBVPROC) (GLuint index, const GLubyte *v); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIB4UIVPROC) (GLuint index, const GLuint *v); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIB4USVPROC) (GLuint index, const GLushort *v); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIBPOINTERPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer); typedef void (APIENTRYP RGLSYMGLUNIFORMMATRIX2X3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); typedef void (APIENTRYP RGLSYMGLUNIFORMMATRIX3X2FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); typedef void (APIENTRYP RGLSYMGLUNIFORMMATRIX2X4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); typedef void (APIENTRYP RGLSYMGLUNIFORMMATRIX4X2FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); typedef void (APIENTRYP RGLSYMGLUNIFORMMATRIX3X4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); typedef void (APIENTRYP RGLSYMGLUNIFORMMATRIX4X3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); typedef void (APIENTRYP RGLSYMGLCOLORMASKIPROC) (GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a); typedef void (APIENTRYP RGLSYMGLGETBOOLEANI_VPROC) (GLenum target, GLuint index, GLboolean *data); typedef void (APIENTRYP RGLSYMGLGETINTEGERI_VPROC) (GLenum target, GLuint index, GLint *data); typedef void (APIENTRYP RGLSYMGLENABLEIPROC) (GLenum target, GLuint index); typedef void (APIENTRYP RGLSYMGLDISABLEIPROC) (GLenum target, GLuint index); typedef GLboolean (APIENTRYP RGLSYMGLISENABLEDIPROC) (GLenum target, GLuint index); typedef void (APIENTRYP RGLSYMGLBEGINTRANSFORMFEEDBACKPROC) (GLenum primitiveMode); typedef void (APIENTRYP RGLSYMGLENDTRANSFORMFEEDBACKPROC) (void); typedef void (APIENTRYP RGLSYMGLBINDBUFFERRANGEPROC) (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size); typedef void (APIENTRYP RGLSYMGLBINDBUFFERBASEPROC) (GLenum target, GLuint index, GLuint buffer); typedef void (APIENTRYP RGLSYMGLTRANSFORMFEEDBACKVARYINGSPROC) (GLuint program, GLsizei count, const GLchar *const*varyings, GLenum bufferMode); typedef void (APIENTRYP RGLSYMGLGETTRANSFORMFEEDBACKVARYINGPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name); typedef void (APIENTRYP RGLSYMGLCLAMPCOLORPROC) (GLenum target, GLenum clamp); typedef void (APIENTRYP RGLSYMGLBEGINCONDITIONALRENDERPROC) (GLuint id, GLenum mode); typedef void (APIENTRYP RGLSYMGLENDCONDITIONALRENDERPROC) (void); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIBIPOINTERPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const void *pointer); typedef void (APIENTRYP RGLSYMGLGETVERTEXATTRIBIIVPROC) (GLuint index, GLenum pname, GLint *params); typedef void (APIENTRYP RGLSYMGLGETVERTEXATTRIBIUIVPROC) (GLuint index, GLenum pname, GLuint *params); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIBI1IPROC) (GLuint index, GLint x); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIBI2IPROC) (GLuint index, GLint x, GLint y); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIBI3IPROC) (GLuint index, GLint x, GLint y, GLint z); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIBI4IPROC) (GLuint index, GLint x, GLint y, GLint z, GLint w); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIBI1UIPROC) (GLuint index, GLuint x); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIBI2UIPROC) (GLuint index, GLuint x, GLuint y); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIBI3UIPROC) (GLuint index, GLuint x, GLuint y, GLuint z); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIBI4UIPROC) (GLuint index, GLuint x, GLuint y, GLuint z, GLuint w); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIBI1IVPROC) (GLuint index, const GLint *v); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIBI2IVPROC) (GLuint index, const GLint *v); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIBI3IVPROC) (GLuint index, const GLint *v); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIBI4IVPROC) (GLuint index, const GLint *v); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIBI1UIVPROC) (GLuint index, const GLuint *v); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIBI2UIVPROC) (GLuint index, const GLuint *v); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIBI3UIVPROC) (GLuint index, const GLuint *v); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIBI4UIVPROC) (GLuint index, const GLuint *v); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIBI4BVPROC) (GLuint index, const GLbyte *v); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIBI4SVPROC) (GLuint index, const GLshort *v); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIBI4UBVPROC) (GLuint index, const GLubyte *v); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIBI4USVPROC) (GLuint index, const GLushort *v); typedef void (APIENTRYP RGLSYMGLGETUNIFORMUIVPROC) (GLuint program, GLint location, GLuint *params); typedef void (APIENTRYP RGLSYMGLBINDFRAGDATALOCATIONPROC) (GLuint program, GLuint color, const GLchar *name); typedef GLint (APIENTRYP RGLSYMGLGETFRAGDATALOCATIONPROC) (GLuint program, const GLchar *name); typedef void (APIENTRYP RGLSYMGLUNIFORM1UIPROC) (GLint location, GLuint v0); typedef void (APIENTRYP RGLSYMGLUNIFORM2UIPROC) (GLint location, GLuint v0, GLuint v1); typedef void (APIENTRYP RGLSYMGLUNIFORM3UIPROC) (GLint location, GLuint v0, GLuint v1, GLuint v2); typedef void (APIENTRYP RGLSYMGLUNIFORM4UIPROC) (GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3); typedef void (APIENTRYP RGLSYMGLUNIFORM1UIVPROC) (GLint location, GLsizei count, const GLuint *value); typedef void (APIENTRYP RGLSYMGLUNIFORM2UIVPROC) (GLint location, GLsizei count, const GLuint *value); typedef void (APIENTRYP RGLSYMGLUNIFORM3UIVPROC) (GLint location, GLsizei count, const GLuint *value); typedef void (APIENTRYP RGLSYMGLUNIFORM4UIVPROC) (GLint location, GLsizei count, const GLuint *value); typedef void (APIENTRYP RGLSYMGLTEXPARAMETERIIVPROC) (GLenum target, GLenum pname, const GLint *params); typedef void (APIENTRYP RGLSYMGLTEXPARAMETERIUIVPROC) (GLenum target, GLenum pname, const GLuint *params); typedef void (APIENTRYP RGLSYMGLGETTEXPARAMETERIIVPROC) (GLenum target, GLenum pname, GLint *params); typedef void (APIENTRYP RGLSYMGLGETTEXPARAMETERIUIVPROC) (GLenum target, GLenum pname, GLuint *params); typedef void (APIENTRYP RGLSYMGLCLEARBUFFERIVPROC) (GLenum buffer, GLint drawbuffer, const GLint *value); typedef void (APIENTRYP RGLSYMGLCLEARBUFFERUIVPROC) (GLenum buffer, GLint drawbuffer, const GLuint *value); typedef void (APIENTRYP RGLSYMGLCLEARBUFFERFVPROC) (GLenum buffer, GLint drawbuffer, const GLfloat *value); typedef void (APIENTRYP RGLSYMGLCLEARBUFFERFIPROC) (GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil); typedef const GLubyte *(APIENTRYP RGLSYMGLGETSTRINGIPROC) (GLenum name, GLuint index); typedef GLboolean (APIENTRYP RGLSYMGLISRENDERBUFFERPROC) (GLuint renderbuffer); typedef void (APIENTRYP RGLSYMGLBINDRENDERBUFFERPROC) (GLenum target, GLuint renderbuffer); typedef void (APIENTRYP RGLSYMGLDELETERENDERBUFFERSPROC) (GLsizei n, const GLuint *renderbuffers); typedef void (APIENTRYP RGLSYMGLGENRENDERBUFFERSPROC) (GLsizei n, GLuint *renderbuffers); typedef void (APIENTRYP RGLSYMGLRENDERBUFFERSTORAGEPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height); typedef void (APIENTRYP RGLSYMGLGETRENDERBUFFERPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params); typedef GLboolean (APIENTRYP RGLSYMGLISFRAMEBUFFERPROC) (GLuint framebuffer); typedef void (APIENTRYP RGLSYMGLBINDFRAMEBUFFERPROC) (GLenum target, GLuint framebuffer); typedef void (APIENTRYP RGLSYMGLDELETEFRAMEBUFFERSPROC) (GLsizei n, const GLuint *framebuffers); typedef void (APIENTRYP RGLSYMGLGENFRAMEBUFFERSPROC) (GLsizei n, GLuint *framebuffers); typedef GLenum (APIENTRYP RGLSYMGLCHECKFRAMEBUFFERSTATUSPROC) (GLenum target); typedef void (APIENTRYP RGLSYMGLFRAMEBUFFERTEXTURE1DPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); typedef void (APIENTRYP RGLSYMGLFRAMEBUFFERTEXTURE2DPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); typedef void (APIENTRYP RGLSYMGLFRAMEBUFFERTEXTURE3DPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset); typedef void (APIENTRYP RGLSYMGLFRAMEBUFFERRENDERBUFFERPROC) (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); typedef void (APIENTRYP RGLSYMGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC) (GLenum target, GLenum attachment, GLenum pname, GLint *params); typedef void (APIENTRYP RGLSYMGLGENERATEMIPMAPPROC) (GLenum target); typedef void (APIENTRYP RGLSYMGLBLITFRAMEBUFFERPROC) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); typedef void (APIENTRYP RGLSYMGLRENDERBUFFERSTORAGEMULTISAMPLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); typedef void (APIENTRYP RGLSYMGLFRAMEBUFFERTEXTURELAYERPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer); typedef void *(APIENTRYP RGLSYMGLMAPBUFFERRANGEPROC) (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access); typedef void (APIENTRYP RGLSYMGLFLUSHMAPPEDBUFFERRANGEPROC) (GLenum target, GLintptr offset, GLsizeiptr length); typedef void (APIENTRYP RGLSYMGLBINDVERTEXARRAYPROC) (GLuint array); typedef void (APIENTRYP RGLSYMGLDELETEVERTEXARRAYSPROC) (GLsizei n, const GLuint *arrays); typedef void (APIENTRYP RGLSYMGLGENVERTEXARRAYSPROC) (GLsizei n, GLuint *arrays); typedef GLboolean (APIENTRYP RGLSYMGLISVERTEXARRAYPROC) (GLuint array); typedef void (APIENTRYP RGLSYMGLDRAWARRAYSINSTANCEDPROC) (GLenum mode, GLint first, GLsizei count, GLsizei instancecount); typedef void (APIENTRYP RGLSYMGLDRAWELEMENTSINSTANCEDPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount); typedef void (APIENTRYP RGLSYMGLTEXBUFFERPROC) (GLenum target, GLenum internalformat, GLuint buffer); typedef void (APIENTRYP RGLSYMGLPRIMITIVERESTARTINDEXPROC) (GLuint index); typedef void (APIENTRYP RGLSYMGLCOPYBUFFERSUBDATAPROC) (GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size); typedef void (APIENTRYP RGLSYMGLGETUNIFORMINDICESPROC) (GLuint program, GLsizei uniformCount, const GLchar *const*uniformNames, GLuint *uniformIndices); typedef void (APIENTRYP RGLSYMGLGETACTIVEUNIFORMSIVPROC) (GLuint program, GLsizei uniformCount, const GLuint *uniformIndices, GLenum pname, GLint *params); typedef void (APIENTRYP RGLSYMGLGETACTIVEUNIFORMNAMEPROC) (GLuint program, GLuint uniformIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformName); typedef GLuint (APIENTRYP RGLSYMGLGETUNIFORMBLOCKINDEXPROC) (GLuint program, const GLchar *uniformBlockName); typedef void (APIENTRYP RGLSYMGLGETACTIVEUNIFORMBLOCKIVPROC) (GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint *params); typedef void (APIENTRYP RGLSYMGLGETACTIVEUNIFORMBLOCKNAMEPROC) (GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName); typedef void (APIENTRYP RGLSYMGLUNIFORMBLOCKBINDINGPROC) (GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding); typedef void (APIENTRYP RGLSYMGLDRAWELEMENTSBASEVERTEXPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLint basevertex); typedef void (APIENTRYP RGLSYMGLDRAWRANGEELEMENTSBASEVERTEXPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices, GLint basevertex); typedef void (APIENTRYP RGLSYMGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex); typedef void (APIENTRYP RGLSYMGLMULTIDRAWELEMENTSBASEVERTEXPROC) (GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei drawcount, const GLint *basevertex); typedef void (APIENTRYP RGLSYMGLPROVOKINGVERTEXPROC) (GLenum mode); typedef GLsync (APIENTRYP RGLSYMGLFENCESYNCPROC) (GLenum condition, GLbitfield flags); typedef GLboolean (APIENTRYP RGLSYMGLISSYNCPROC) (GLsync sync); typedef void (APIENTRYP RGLSYMGLDELETESYNCPROC) (GLsync sync); typedef GLenum (APIENTRYP RGLSYMGLCLIENTWAITSYNCPROC) (GLsync sync, GLbitfield flags, GLuint64 timeout); typedef void (APIENTRYP RGLSYMGLWAITSYNCPROC) (GLsync sync, GLbitfield flags, GLuint64 timeout); typedef void (APIENTRYP RGLSYMGLGETINTEGER64VPROC) (GLenum pname, GLint64 *data); typedef void (APIENTRYP RGLSYMGLGETSYNCIVPROC) (GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values); typedef void (APIENTRYP RGLSYMGLGETINTEGER64I_VPROC) (GLenum target, GLuint index, GLint64 *data); typedef void (APIENTRYP RGLSYMGLGETBUFFERPARAMETERI64VPROC) (GLenum target, GLenum pname, GLint64 *params); typedef void (APIENTRYP RGLSYMGLFRAMEBUFFERTEXTUREPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level); typedef void (APIENTRYP RGLSYMGLTEXIMAGE2DMULTISAMPLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations); typedef void (APIENTRYP RGLSYMGLTEXIMAGE3DMULTISAMPLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations); typedef void (APIENTRYP RGLSYMGLGETMULTISAMPLEFVPROC) (GLenum pname, GLuint index, GLfloat *val); typedef void (APIENTRYP RGLSYMGLSAMPLEMASKIPROC) (GLuint index, GLbitfield mask); typedef void (APIENTRYP RGLSYMGLBINDFRAGDATALOCATIONINDEXEDPROC) (GLuint program, GLuint colorNumber, GLuint index, const GLchar *name); typedef GLint (APIENTRYP RGLSYMGLGETFRAGDATAINDEXPROC) (GLuint program, const GLchar *name); typedef void (APIENTRYP RGLSYMGLGENSAMPLERSPROC) (GLsizei count, GLuint *samplers); typedef void (APIENTRYP RGLSYMGLDELETESAMPLERSPROC) (GLsizei count, const GLuint *samplers); typedef GLboolean (APIENTRYP RGLSYMGLISSAMPLERPROC) (GLuint sampler); typedef void (APIENTRYP RGLSYMGLBINDSAMPLERPROC) (GLuint unit, GLuint sampler); typedef void (APIENTRYP RGLSYMGLSAMPLERPARAMETERIPROC) (GLuint sampler, GLenum pname, GLint param); typedef void (APIENTRYP RGLSYMGLSAMPLERPARAMETERIVPROC) (GLuint sampler, GLenum pname, const GLint *param); typedef void (APIENTRYP RGLSYMGLSAMPLERPARAMETERFPROC) (GLuint sampler, GLenum pname, GLfloat param); typedef void (APIENTRYP RGLSYMGLSAMPLERPARAMETERFVPROC) (GLuint sampler, GLenum pname, const GLfloat *param); typedef void (APIENTRYP RGLSYMGLSAMPLERPARAMETERIIVPROC) (GLuint sampler, GLenum pname, const GLint *param); typedef void (APIENTRYP RGLSYMGLSAMPLERPARAMETERIUIVPROC) (GLuint sampler, GLenum pname, const GLuint *param); typedef void (APIENTRYP RGLSYMGLGETSAMPLERPARAMETERIVPROC) (GLuint sampler, GLenum pname, GLint *params); typedef void (APIENTRYP RGLSYMGLGETSAMPLERPARAMETERIIVPROC) (GLuint sampler, GLenum pname, GLint *params); typedef void (APIENTRYP RGLSYMGLGETSAMPLERPARAMETERFVPROC) (GLuint sampler, GLenum pname, GLfloat *params); typedef void (APIENTRYP RGLSYMGLGETSAMPLERPARAMETERIUIVPROC) (GLuint sampler, GLenum pname, GLuint *params); typedef void (APIENTRYP RGLSYMGLQUERYCOUNTERPROC) (GLuint id, GLenum target); typedef void (APIENTRYP RGLSYMGLGETQUERYOBJECTI64VPROC) (GLuint id, GLenum pname, GLint64 *params); typedef void (APIENTRYP RGLSYMGLGETQUERYOBJECTUI64VPROC) (GLuint id, GLenum pname, GLuint64 *params); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIBDIVISORPROC) (GLuint index, GLuint divisor); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIBP1UIPROC) (GLuint index, GLenum type, GLboolean normalized, GLuint value); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIBP1UIVPROC) (GLuint index, GLenum type, GLboolean normalized, const GLuint *value); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIBP2UIPROC) (GLuint index, GLenum type, GLboolean normalized, GLuint value); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIBP2UIVPROC) (GLuint index, GLenum type, GLboolean normalized, const GLuint *value); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIBP3UIPROC) (GLuint index, GLenum type, GLboolean normalized, GLuint value); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIBP3UIVPROC) (GLuint index, GLenum type, GLboolean normalized, const GLuint *value); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIBP4UIPROC) (GLuint index, GLenum type, GLboolean normalized, GLuint value); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIBP4UIVPROC) (GLuint index, GLenum type, GLboolean normalized, const GLuint *value); typedef void (APIENTRYP RGLSYMGLVERTEXP2UIPROC) (GLenum type, GLuint value); typedef void (APIENTRYP RGLSYMGLVERTEXP2UIVPROC) (GLenum type, const GLuint *value); typedef void (APIENTRYP RGLSYMGLVERTEXP3UIPROC) (GLenum type, GLuint value); typedef void (APIENTRYP RGLSYMGLVERTEXP3UIVPROC) (GLenum type, const GLuint *value); typedef void (APIENTRYP RGLSYMGLVERTEXP4UIPROC) (GLenum type, GLuint value); typedef void (APIENTRYP RGLSYMGLVERTEXP4UIVPROC) (GLenum type, const GLuint *value); typedef void (APIENTRYP RGLSYMGLTEXCOORDP1UIPROC) (GLenum type, GLuint coords); typedef void (APIENTRYP RGLSYMGLTEXCOORDP1UIVPROC) (GLenum type, const GLuint *coords); typedef void (APIENTRYP RGLSYMGLTEXCOORDP2UIPROC) (GLenum type, GLuint coords); typedef void (APIENTRYP RGLSYMGLTEXCOORDP2UIVPROC) (GLenum type, const GLuint *coords); typedef void (APIENTRYP RGLSYMGLTEXCOORDP3UIPROC) (GLenum type, GLuint coords); typedef void (APIENTRYP RGLSYMGLTEXCOORDP3UIVPROC) (GLenum type, const GLuint *coords); typedef void (APIENTRYP RGLSYMGLTEXCOORDP4UIPROC) (GLenum type, GLuint coords); typedef void (APIENTRYP RGLSYMGLTEXCOORDP4UIVPROC) (GLenum type, const GLuint *coords); typedef void (APIENTRYP RGLSYMGLMULTITEXCOORDP1UIPROC) (GLenum texture, GLenum type, GLuint coords); typedef void (APIENTRYP RGLSYMGLMULTITEXCOORDP1UIVPROC) (GLenum texture, GLenum type, const GLuint *coords); typedef void (APIENTRYP RGLSYMGLMULTITEXCOORDP2UIPROC) (GLenum texture, GLenum type, GLuint coords); typedef void (APIENTRYP RGLSYMGLMULTITEXCOORDP2UIVPROC) (GLenum texture, GLenum type, const GLuint *coords); typedef void (APIENTRYP RGLSYMGLMULTITEXCOORDP3UIPROC) (GLenum texture, GLenum type, GLuint coords); typedef void (APIENTRYP RGLSYMGLMULTITEXCOORDP3UIVPROC) (GLenum texture, GLenum type, const GLuint *coords); typedef void (APIENTRYP RGLSYMGLMULTITEXCOORDP4UIPROC) (GLenum texture, GLenum type, GLuint coords); typedef void (APIENTRYP RGLSYMGLMULTITEXCOORDP4UIVPROC) (GLenum texture, GLenum type, const GLuint *coords); typedef void (APIENTRYP RGLSYMGLNORMALP3UIPROC) (GLenum type, GLuint coords); typedef void (APIENTRYP RGLSYMGLNORMALP3UIVPROC) (GLenum type, const GLuint *coords); typedef void (APIENTRYP RGLSYMGLCOLORP3UIPROC) (GLenum type, GLuint color); typedef void (APIENTRYP RGLSYMGLCOLORP3UIVPROC) (GLenum type, const GLuint *color); typedef void (APIENTRYP RGLSYMGLCOLORP4UIPROC) (GLenum type, GLuint color); typedef void (APIENTRYP RGLSYMGLCOLORP4UIVPROC) (GLenum type, const GLuint *color); typedef void (APIENTRYP RGLSYMGLSECONDARYCOLORP3UIPROC) (GLenum type, GLuint color); typedef void (APIENTRYP RGLSYMGLSECONDARYCOLORP3UIVPROC) (GLenum type, const GLuint *color); typedef void (APIENTRYP RGLSYMGLMINSAMPLESHADINGPROC) (GLfloat value); typedef void (APIENTRYP RGLSYMGLBLENDEQUATIONIPROC) (GLuint buf, GLenum mode); typedef void (APIENTRYP RGLSYMGLBLENDEQUATIONSEPARATEIPROC) (GLuint buf, GLenum modeRGB, GLenum modeAlpha); typedef void (APIENTRYP RGLSYMGLBLENDFUNCIPROC) (GLuint buf, GLenum src, GLenum dst); typedef void (APIENTRYP RGLSYMGLBLENDFUNCSEPARATEIPROC) (GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha); typedef void (APIENTRYP RGLSYMGLDRAWARRAYSINDIRECTPROC) (GLenum mode, const void *indirect); typedef void (APIENTRYP RGLSYMGLDRAWELEMENTSINDIRECTPROC) (GLenum mode, GLenum type, const void *indirect); typedef void (APIENTRYP RGLSYMGLUNIFORM1DPROC) (GLint location, GLdouble x); typedef void (APIENTRYP RGLSYMGLUNIFORM2DPROC) (GLint location, GLdouble x, GLdouble y); typedef void (APIENTRYP RGLSYMGLUNIFORM3DPROC) (GLint location, GLdouble x, GLdouble y, GLdouble z); typedef void (APIENTRYP RGLSYMGLUNIFORM4DPROC) (GLint location, GLdouble x, GLdouble y, GLdouble z, GLdouble w); typedef void (APIENTRYP RGLSYMGLUNIFORM1DVPROC) (GLint location, GLsizei count, const GLdouble *value); typedef void (APIENTRYP RGLSYMGLUNIFORM2DVPROC) (GLint location, GLsizei count, const GLdouble *value); typedef void (APIENTRYP RGLSYMGLUNIFORM3DVPROC) (GLint location, GLsizei count, const GLdouble *value); typedef void (APIENTRYP RGLSYMGLUNIFORM4DVPROC) (GLint location, GLsizei count, const GLdouble *value); typedef void (APIENTRYP RGLSYMGLUNIFORMMATRIX2DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); typedef void (APIENTRYP RGLSYMGLUNIFORMMATRIX3DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); typedef void (APIENTRYP RGLSYMGLUNIFORMMATRIX4DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); typedef void (APIENTRYP RGLSYMGLUNIFORMMATRIX2X3DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); typedef void (APIENTRYP RGLSYMGLUNIFORMMATRIX2X4DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); typedef void (APIENTRYP RGLSYMGLUNIFORMMATRIX3X2DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); typedef void (APIENTRYP RGLSYMGLUNIFORMMATRIX3X4DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); typedef void (APIENTRYP RGLSYMGLUNIFORMMATRIX4X2DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); typedef void (APIENTRYP RGLSYMGLUNIFORMMATRIX4X3DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); typedef void (APIENTRYP RGLSYMGLGETUNIFORMDVPROC) (GLuint program, GLint location, GLdouble *params); typedef GLint (APIENTRYP RGLSYMGLGETSUBROUTINEUNIFORMLOCATIONPROC) (GLuint program, GLenum shadertype, const GLchar *name); typedef GLuint (APIENTRYP RGLSYMGLGETSUBROUTINEINDEXPROC) (GLuint program, GLenum shadertype, const GLchar *name); typedef void (APIENTRYP RGLSYMGLGETACTIVESUBROUTINEUNIFORMIVPROC) (GLuint program, GLenum shadertype, GLuint index, GLenum pname, GLint *values); typedef void (APIENTRYP RGLSYMGLGETACTIVESUBROUTINEUNIFORMNAMEPROC) (GLuint program, GLenum shadertype, GLuint index, GLsizei bufsize, GLsizei *length, GLchar *name); typedef void (APIENTRYP RGLSYMGLGETACTIVESUBROUTINENAMEPROC) (GLuint program, GLenum shadertype, GLuint index, GLsizei bufsize, GLsizei *length, GLchar *name); typedef void (APIENTRYP RGLSYMGLUNIFORMSUBROUTINESUIVPROC) (GLenum shadertype, GLsizei count, const GLuint *indices); typedef void (APIENTRYP RGLSYMGLGETUNIFORMSUBROUTINEUIVPROC) (GLenum shadertype, GLint location, GLuint *params); typedef void (APIENTRYP RGLSYMGLGETPROGRAMSTAGEIVPROC) (GLuint program, GLenum shadertype, GLenum pname, GLint *values); typedef void (APIENTRYP RGLSYMGLPATCHPARAMETERIPROC) (GLenum pname, GLint value); typedef void (APIENTRYP RGLSYMGLPATCHPARAMETERFVPROC) (GLenum pname, const GLfloat *values); typedef void (APIENTRYP RGLSYMGLBINDTRANSFORMFEEDBACKPROC) (GLenum target, GLuint id); typedef void (APIENTRYP RGLSYMGLDELETETRANSFORMFEEDBACKSPROC) (GLsizei n, const GLuint *ids); typedef void (APIENTRYP RGLSYMGLGENTRANSFORMFEEDBACKSPROC) (GLsizei n, GLuint *ids); typedef GLboolean (APIENTRYP RGLSYMGLISTRANSFORMFEEDBACKPROC) (GLuint id); typedef void (APIENTRYP RGLSYMGLPAUSETRANSFORMFEEDBACKPROC) (void); typedef void (APIENTRYP RGLSYMGLRESUMETRANSFORMFEEDBACKPROC) (void); typedef void (APIENTRYP RGLSYMGLDRAWTRANSFORMFEEDBACKPROC) (GLenum mode, GLuint id); typedef void (APIENTRYP RGLSYMGLDRAWTRANSFORMFEEDBACKSTREAMPROC) (GLenum mode, GLuint id, GLuint stream); typedef void (APIENTRYP RGLSYMGLBEGINQUERYINDEXEDPROC) (GLenum target, GLuint index, GLuint id); typedef void (APIENTRYP RGLSYMGLENDQUERYINDEXEDPROC) (GLenum target, GLuint index); typedef void (APIENTRYP RGLSYMGLGETQUERYINDEXEDIVPROC) (GLenum target, GLuint index, GLenum pname, GLint *params); typedef void (APIENTRYP RGLSYMGLRELEASESHADERCOMPILERPROC) (void); typedef void (APIENTRYP RGLSYMGLSHADERBINARYPROC) (GLsizei count, const GLuint *shaders, GLenum binaryformat, const void *binary, GLsizei length); typedef void (APIENTRYP RGLSYMGLGETSHADERPRECISIONFORMATPROC) (GLenum shadertype, GLenum precisiontype, GLint *range, GLint *precision); typedef void (APIENTRYP RGLSYMGLDEPTHRANGEFPROC) (GLfloat n, GLfloat f); typedef void (APIENTRYP RGLSYMGLCLEARDEPTHFPROC) (GLfloat d); typedef void (APIENTRYP RGLSYMGLGETPROGRAMBINARYPROC) (GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, void *binary); typedef void (APIENTRYP RGLSYMGLPROGRAMBINARYPROC) (GLuint program, GLenum binaryFormat, const void *binary, GLsizei length); typedef void (APIENTRYP RGLSYMGLPROGRAMPARAMETERIPROC) (GLuint program, GLenum pname, GLint value); typedef void (APIENTRYP RGLSYMGLUSEPROGRAMSTAGESPROC) (GLuint pipeline, GLbitfield stages, GLuint program); typedef void (APIENTRYP RGLSYMGLACTIVESHADERPROGRAMPROC) (GLuint pipeline, GLuint program); typedef GLuint (APIENTRYP RGLSYMGLCREATESHADERPROGRAMVPROC) (GLenum type, GLsizei count, const GLchar *const*strings); typedef void (APIENTRYP RGLSYMGLBINDPROGRAMPIPELINEPROC) (GLuint pipeline); typedef void (APIENTRYP RGLSYMGLDELETEPROGRAMPIPELINESPROC) (GLsizei n, const GLuint *pipelines); typedef void (APIENTRYP RGLSYMGLGENPROGRAMPIPELINESPROC) (GLsizei n, GLuint *pipelines); typedef GLboolean (APIENTRYP RGLSYMGLISPROGRAMPIPELINEPROC) (GLuint pipeline); typedef void (APIENTRYP RGLSYMGLGETPROGRAMPIPELINEIVPROC) (GLuint pipeline, GLenum pname, GLint *params); typedef void (APIENTRYP RGLSYMGLPROGRAMUNIFORM1IPROC) (GLuint program, GLint location, GLint v0); typedef void (APIENTRYP RGLSYMGLPROGRAMUNIFORM1IVPROC) (GLuint program, GLint location, GLsizei count, const GLint *value); typedef void (APIENTRYP RGLSYMGLPROGRAMUNIFORM1FPROC) (GLuint program, GLint location, GLfloat v0); typedef void (APIENTRYP RGLSYMGLPROGRAMUNIFORM1FVPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value); typedef void (APIENTRYP RGLSYMGLPROGRAMUNIFORM1DPROC) (GLuint program, GLint location, GLdouble v0); typedef void (APIENTRYP RGLSYMGLPROGRAMUNIFORM1DVPROC) (GLuint program, GLint location, GLsizei count, const GLdouble *value); typedef void (APIENTRYP RGLSYMGLPROGRAMUNIFORM1UIPROC) (GLuint program, GLint location, GLuint v0); typedef void (APIENTRYP RGLSYMGLPROGRAMUNIFORM1UIVPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value); typedef void (APIENTRYP RGLSYMGLPROGRAMUNIFORM2IPROC) (GLuint program, GLint location, GLint v0, GLint v1); typedef void (APIENTRYP RGLSYMGLPROGRAMUNIFORM2IVPROC) (GLuint program, GLint location, GLsizei count, const GLint *value); typedef void (APIENTRYP RGLSYMGLPROGRAMUNIFORM2FPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1); typedef void (APIENTRYP RGLSYMGLPROGRAMUNIFORM2FVPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value); typedef void (APIENTRYP RGLSYMGLPROGRAMUNIFORM2DPROC) (GLuint program, GLint location, GLdouble v0, GLdouble v1); typedef void (APIENTRYP RGLSYMGLPROGRAMUNIFORM2DVPROC) (GLuint program, GLint location, GLsizei count, const GLdouble *value); typedef void (APIENTRYP RGLSYMGLPROGRAMUNIFORM2UIPROC) (GLuint program, GLint location, GLuint v0, GLuint v1); typedef void (APIENTRYP RGLSYMGLPROGRAMUNIFORM2UIVPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value); typedef void (APIENTRYP RGLSYMGLPROGRAMUNIFORM3IPROC) (GLuint program, GLint location, GLint v0, GLint v1, GLint v2); typedef void (APIENTRYP RGLSYMGLPROGRAMUNIFORM3IVPROC) (GLuint program, GLint location, GLsizei count, const GLint *value); typedef void (APIENTRYP RGLSYMGLPROGRAMUNIFORM3FPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2); typedef void (APIENTRYP RGLSYMGLPROGRAMUNIFORM3FVPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value); typedef void (APIENTRYP RGLSYMGLPROGRAMUNIFORM3DPROC) (GLuint program, GLint location, GLdouble v0, GLdouble v1, GLdouble v2); typedef void (APIENTRYP RGLSYMGLPROGRAMUNIFORM3DVPROC) (GLuint program, GLint location, GLsizei count, const GLdouble *value); typedef void (APIENTRYP RGLSYMGLPROGRAMUNIFORM3UIPROC) (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2); typedef void (APIENTRYP RGLSYMGLPROGRAMUNIFORM3UIVPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value); typedef void (APIENTRYP RGLSYMGLPROGRAMUNIFORM4IPROC) (GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3); typedef void (APIENTRYP RGLSYMGLPROGRAMUNIFORM4IVPROC) (GLuint program, GLint location, GLsizei count, const GLint *value); typedef void (APIENTRYP RGLSYMGLPROGRAMUNIFORM4FPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); typedef void (APIENTRYP RGLSYMGLPROGRAMUNIFORM4FVPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value); typedef void (APIENTRYP RGLSYMGLPROGRAMUNIFORM4DPROC) (GLuint program, GLint location, GLdouble v0, GLdouble v1, GLdouble v2, GLdouble v3); typedef void (APIENTRYP RGLSYMGLPROGRAMUNIFORM4DVPROC) (GLuint program, GLint location, GLsizei count, const GLdouble *value); typedef void (APIENTRYP RGLSYMGLPROGRAMUNIFORM4UIPROC) (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3); typedef void (APIENTRYP RGLSYMGLPROGRAMUNIFORM4UIVPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value); typedef void (APIENTRYP RGLSYMGLPROGRAMUNIFORMMATRIX2FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); typedef void (APIENTRYP RGLSYMGLPROGRAMUNIFORMMATRIX3FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); typedef void (APIENTRYP RGLSYMGLPROGRAMUNIFORMMATRIX4FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); typedef void (APIENTRYP RGLSYMGLPROGRAMUNIFORMMATRIX2DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); typedef void (APIENTRYP RGLSYMGLPROGRAMUNIFORMMATRIX3DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); typedef void (APIENTRYP RGLSYMGLPROGRAMUNIFORMMATRIX4DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); typedef void (APIENTRYP RGLSYMGLPROGRAMUNIFORMMATRIX2X3FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); typedef void (APIENTRYP RGLSYMGLPROGRAMUNIFORMMATRIX3X2FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); typedef void (APIENTRYP RGLSYMGLPROGRAMUNIFORMMATRIX2X4FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); typedef void (APIENTRYP RGLSYMGLPROGRAMUNIFORMMATRIX4X2FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); typedef void (APIENTRYP RGLSYMGLPROGRAMUNIFORMMATRIX3X4FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); typedef void (APIENTRYP RGLSYMGLPROGRAMUNIFORMMATRIX4X3FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); typedef void (APIENTRYP RGLSYMGLPROGRAMUNIFORMMATRIX2X3DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); typedef void (APIENTRYP RGLSYMGLPROGRAMUNIFORMMATRIX3X2DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); typedef void (APIENTRYP RGLSYMGLPROGRAMUNIFORMMATRIX2X4DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); typedef void (APIENTRYP RGLSYMGLPROGRAMUNIFORMMATRIX4X2DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); typedef void (APIENTRYP RGLSYMGLPROGRAMUNIFORMMATRIX3X4DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); typedef void (APIENTRYP RGLSYMGLPROGRAMUNIFORMMATRIX4X3DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); typedef void (APIENTRYP RGLSYMGLVALIDATEPROGRAMPIPELINEPROC) (GLuint pipeline); typedef void (APIENTRYP RGLSYMGLGETPROGRAMPIPELINEINFOLOGPROC) (GLuint pipeline, GLsizei bufSize, GLsizei *length, GLchar *infoLog); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIBL1DPROC) (GLuint index, GLdouble x); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIBL2DPROC) (GLuint index, GLdouble x, GLdouble y); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIBL3DPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIBL4DPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIBL1DVPROC) (GLuint index, const GLdouble *v); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIBL2DVPROC) (GLuint index, const GLdouble *v); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIBL3DVPROC) (GLuint index, const GLdouble *v); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIBL4DVPROC) (GLuint index, const GLdouble *v); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIBLPOINTERPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const void *pointer); typedef void (APIENTRYP RGLSYMGLGETVERTEXATTRIBLDVPROC) (GLuint index, GLenum pname, GLdouble *params); typedef void (APIENTRYP RGLSYMGLVIEWPORTARRAYVPROC) (GLuint first, GLsizei count, const GLfloat *v); typedef void (APIENTRYP RGLSYMGLVIEWPORTINDEXEDFPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat w, GLfloat h); typedef void (APIENTRYP RGLSYMGLVIEWPORTINDEXEDFVPROC) (GLuint index, const GLfloat *v); typedef void (APIENTRYP RGLSYMGLSCISSORARRAYVPROC) (GLuint first, GLsizei count, const GLint *v); typedef void (APIENTRYP RGLSYMGLSCISSORINDEXEDPROC) (GLuint index, GLint left, GLint bottom, GLsizei width, GLsizei height); typedef void (APIENTRYP RGLSYMGLSCISSORINDEXEDVPROC) (GLuint index, const GLint *v); typedef void (APIENTRYP RGLSYMGLDEPTHRANGEARRAYVPROC) (GLuint first, GLsizei count, const GLdouble *v); typedef void (APIENTRYP RGLSYMGLDEPTHRANGEINDEXEDPROC) (GLuint index, GLdouble n, GLdouble f); typedef void (APIENTRYP RGLSYMGLGETFLOATI_VPROC) (GLenum target, GLuint index, GLfloat *data); typedef void (APIENTRYP RGLSYMGLGETDOUBLEI_VPROC) (GLenum target, GLuint index, GLdouble *data); typedef void (APIENTRYP RGLSYMGLDRAWARRAYSINSTANCEDBASEINSTANCEPROC) (GLenum mode, GLint first, GLsizei count, GLsizei instancecount, GLuint baseinstance); typedef void (APIENTRYP RGLSYMGLDRAWELEMENTSINSTANCEDBASEINSTANCEPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLuint baseinstance); typedef void (APIENTRYP RGLSYMGLDRAWELEMENTSINSTANCEDBASEVERTEXBASEINSTANCEPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex, GLuint baseinstance); typedef void (APIENTRYP RGLSYMGLGETINTERNALFORMATIVPROC) (GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint *params); typedef void (APIENTRYP RGLSYMGLGETACTIVEATOMICCOUNTERBUFFERIVPROC) (GLuint program, GLuint bufferIndex, GLenum pname, GLint *params); typedef void (APIENTRYP RGLSYMGLBINDIMAGETEXTUREPROC) (GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLenum format); typedef void (APIENTRYP RGLSYMGLMEMORYBARRIERPROC) (GLbitfield barriers); typedef void (APIENTRYP RGLSYMGLTEXSTORAGE1DPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width); typedef void (APIENTRYP RGLSYMGLTEXSTORAGE2DPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height); typedef void (APIENTRYP RGLSYMGLTEXSTORAGE3DPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); typedef void (APIENTRYP RGLSYMGLDRAWTRANSFORMFEEDBACKINSTANCEDPROC) (GLenum mode, GLuint id, GLsizei instancecount); typedef void (APIENTRYP RGLSYMGLDRAWTRANSFORMFEEDBACKSTREAMINSTANCEDPROC) (GLenum mode, GLuint id, GLuint stream, GLsizei instancecount); typedef void (APIENTRYP RGLSYMGLCLEARBUFFERDATAPROC) (GLenum target, GLenum internalformat, GLenum format, GLenum type, const void *data); typedef void (APIENTRYP RGLSYMGLCLEARBUFFERSUBDATAPROC) (GLenum target, GLenum internalformat, GLintptr offset, GLsizeiptr size, GLenum format, GLenum type, const void *data); typedef void (APIENTRYP RGLSYMGLDISPATCHCOMPUTEPROC) (GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z); typedef void (APIENTRYP RGLSYMGLDISPATCHCOMPUTEINDIRECTPROC) (GLintptr indirect); typedef void (APIENTRYP RGLSYMGLCOPYIMAGESUBDATAPROC) (GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth); typedef void (APIENTRYP RGLSYMGLFRAMEBUFFERPARAMETERIPROC) (GLenum target, GLenum pname, GLint param); typedef void (APIENTRYP RGLSYMGLGETFRAMEBUFFERPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params); typedef void (APIENTRYP RGLSYMGLGETINTERNALFORMATI64VPROC) (GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint64 *params); typedef void (APIENTRYP RGLSYMGLINVALIDATETEXSUBIMAGEPROC) (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth); typedef void (APIENTRYP RGLSYMGLINVALIDATETEXIMAGEPROC) (GLuint texture, GLint level); typedef void (APIENTRYP RGLSYMGLINVALIDATEBUFFERSUBDATAPROC) (GLuint buffer, GLintptr offset, GLsizeiptr length); typedef void (APIENTRYP RGLSYMGLINVALIDATEBUFFERDATAPROC) (GLuint buffer); typedef void (APIENTRYP RGLSYMGLINVALIDATEFRAMEBUFFERPROC) (GLenum target, GLsizei numAttachments, const GLenum *attachments); typedef void (APIENTRYP RGLSYMGLINVALIDATESUBFRAMEBUFFERPROC) (GLenum target, GLsizei numAttachments, const GLenum *attachments, GLint x, GLint y, GLsizei width, GLsizei height); typedef void (APIENTRYP RGLSYMGLMULTIDRAWARRAYSINDIRECTPROC) (GLenum mode, const void *indirect, GLsizei drawcount, GLsizei stride); typedef void (APIENTRYP RGLSYMGLMULTIDRAWELEMENTSINDIRECTPROC) (GLenum mode, GLenum type, const void *indirect, GLsizei drawcount, GLsizei stride); typedef void (APIENTRYP RGLSYMGLGETPROGRAMINTERFACEIVPROC) (GLuint program, GLenum programInterface, GLenum pname, GLint *params); typedef GLuint (APIENTRYP RGLSYMGLGETPROGRAMRESOURCEINDEXPROC) (GLuint program, GLenum programInterface, const GLchar *name); typedef void (APIENTRYP RGLSYMGLGETPROGRAMRESOURCENAMEPROC) (GLuint program, GLenum programInterface, GLuint index, GLsizei bufSize, GLsizei *length, GLchar *name); typedef void (APIENTRYP RGLSYMGLGETPROGRAMRESOURCEIVPROC) (GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum *props, GLsizei bufSize, GLsizei *length, GLint *params); typedef GLint (APIENTRYP RGLSYMGLGETPROGRAMRESOURCELOCATIONPROC) (GLuint program, GLenum programInterface, const GLchar *name); typedef GLint (APIENTRYP RGLSYMGLGETPROGRAMRESOURCELOCATIONINDEXPROC) (GLuint program, GLenum programInterface, const GLchar *name); typedef void (APIENTRYP RGLSYMGLSHADERSTORAGEBLOCKBINDINGPROC) (GLuint program, GLuint storageBlockIndex, GLuint storageBlockBinding); typedef void (APIENTRYP RGLSYMGLTEXBUFFERRANGEPROC) (GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size); typedef void (APIENTRYP RGLSYMGLTEXSTORAGE2DMULTISAMPLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations); typedef void (APIENTRYP RGLSYMGLTEXSTORAGE3DMULTISAMPLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations); typedef void (APIENTRYP RGLSYMGLTEXTUREVIEWPROC) (GLuint texture, GLenum target, GLuint origtexture, GLenum internalformat, GLuint minlevel, GLuint numlevels, GLuint minlayer, GLuint numlayers); typedef void (APIENTRYP RGLSYMGLBINDVERTEXBUFFERPROC) (GLuint bindingindex, GLuint buffer, GLintptr offset, GLsizei stride); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIBFORMATPROC) (GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIBIFORMATPROC) (GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIBLFORMATPROC) (GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIBBINDINGPROC) (GLuint attribindex, GLuint bindingindex); typedef void (APIENTRYP RGLSYMGLVERTEXBINDINGDIVISORPROC) (GLuint bindingindex, GLuint divisor); typedef void (APIENTRYP RGLSYMGLDEBUGMESSAGECONTROLPROC) (GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled); typedef void (APIENTRYP RGLSYMGLDEBUGMESSAGEINSERTPROC) (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *buf); typedef void (APIENTRYP RGLSYMGLDEBUGMESSAGECALLBACKPROC) (RGLGENGLDEBUGPROC callback, const void *userParam); typedef GLuint (APIENTRYP RGLSYMGLGETDEBUGMESSAGELOGPROC) (GLuint count, GLsizei bufSize, GLenum *sources, GLenum *types, GLuint *ids, GLenum *severities, GLsizei *lengths, GLchar *messageLog); typedef void (APIENTRYP RGLSYMGLPUSHDEBUGGROUPPROC) (GLenum source, GLuint id, GLsizei length, const GLchar *message); typedef void (APIENTRYP RGLSYMGLPOPDEBUGGROUPPROC) (void); typedef void (APIENTRYP RGLSYMGLOBJECTLABELPROC) (GLenum identifier, GLuint name, GLsizei length, const GLchar *label); typedef void (APIENTRYP RGLSYMGLGETOBJECTLABELPROC) (GLenum identifier, GLuint name, GLsizei bufSize, GLsizei *length, GLchar *label); typedef void (APIENTRYP RGLSYMGLOBJECTPTRLABELPROC) (const void *ptr, GLsizei length, const GLchar *label); typedef void (APIENTRYP RGLSYMGLGETOBJECTPTRLABELPROC) (const void *ptr, GLsizei bufSize, GLsizei *length, GLchar *label); typedef void (APIENTRYP RGLSYMGLBUFFERSTORAGEPROC) (GLenum target, GLsizeiptr size, const void *data, GLbitfield flags); typedef void (APIENTRYP RGLSYMGLCLEARTEXIMAGEPROC) (GLuint texture, GLint level, GLenum format, GLenum type, const void *data); typedef void (APIENTRYP RGLSYMGLCLEARTEXSUBIMAGEPROC) (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *data); typedef void (APIENTRYP RGLSYMGLBINDBUFFERSBASEPROC) (GLenum target, GLuint first, GLsizei count, const GLuint *buffers); typedef void (APIENTRYP RGLSYMGLBINDBUFFERSRANGEPROC) (GLenum target, GLuint first, GLsizei count, const GLuint *buffers, const GLintptr *offsets, const GLsizeiptr *sizes); typedef void (APIENTRYP RGLSYMGLBINDTEXTURESPROC) (GLuint first, GLsizei count, const GLuint *textures); typedef void (APIENTRYP RGLSYMGLBINDSAMPLERSPROC) (GLuint first, GLsizei count, const GLuint *samplers); typedef void (APIENTRYP RGLSYMGLBINDIMAGETEXTURESPROC) (GLuint first, GLsizei count, const GLuint *textures); typedef void (APIENTRYP RGLSYMGLBINDVERTEXBUFFERSPROC) (GLuint first, GLsizei count, const GLuint *buffers, const GLintptr *offsets, const GLsizei *strides); typedef GLuint64 (APIENTRYP RGLSYMGLGETTEXTUREHANDLEARBPROC) (GLuint texture); typedef GLuint64 (APIENTRYP RGLSYMGLGETTEXTURESAMPLERHANDLEARBPROC) (GLuint texture, GLuint sampler); typedef void (APIENTRYP RGLSYMGLMAKETEXTUREHANDLERESIDENTARBPROC) (GLuint64 handle); typedef void (APIENTRYP RGLSYMGLMAKETEXTUREHANDLENONRESIDENTARBPROC) (GLuint64 handle); typedef GLuint64 (APIENTRYP RGLSYMGLGETIMAGEHANDLEARBPROC) (GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum format); typedef void (APIENTRYP RGLSYMGLMAKEIMAGEHANDLERESIDENTARBPROC) (GLuint64 handle, GLenum access); typedef void (APIENTRYP RGLSYMGLMAKEIMAGEHANDLENONRESIDENTARBPROC) (GLuint64 handle); typedef void (APIENTRYP RGLSYMGLUNIFORMHANDLEUI64ARBPROC) (GLint location, GLuint64 value); typedef void (APIENTRYP RGLSYMGLUNIFORMHANDLEUI64VARBPROC) (GLint location, GLsizei count, const GLuint64 *value); typedef void (APIENTRYP RGLSYMGLPROGRAMUNIFORMHANDLEUI64ARBPROC) (GLuint program, GLint location, GLuint64 value); typedef void (APIENTRYP RGLSYMGLPROGRAMUNIFORMHANDLEUI64VARBPROC) (GLuint program, GLint location, GLsizei count, const GLuint64 *values); typedef GLboolean (APIENTRYP RGLSYMGLISTEXTUREHANDLERESIDENTARBPROC) (GLuint64 handle); typedef GLboolean (APIENTRYP RGLSYMGLISIMAGEHANDLERESIDENTARBPROC) (GLuint64 handle); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIBL1UI64ARBPROC) (GLuint index, GLuint64EXT x); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIBL1UI64VARBPROC) (GLuint index, const GLuint64EXT *v); typedef void (APIENTRYP RGLSYMGLGETVERTEXATTRIBLUI64VARBPROC) (GLuint index, GLenum pname, GLuint64EXT *params); #ifdef __APPLE__ struct _cl_context; struct _cl_event; #endif typedef GLsync (APIENTRYP RGLSYMGLCREATESYNCFROMCLEVENTARBPROC) (struct _cl_context *context, struct _cl_event *event, GLbitfield flags); typedef void (APIENTRYP RGLSYMGLCLAMPCOLORARBPROC) (GLenum target, GLenum clamp); typedef void (APIENTRYP RGLSYMGLDISPATCHCOMPUTEGROUPSIZEARBPROC) (GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z, GLuint group_size_x, GLuint group_size_y, GLuint group_size_z); typedef void (APIENTRYP RGLSYMGLDEBUGMESSAGECONTROLARBPROC) (GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled); typedef void (APIENTRYP RGLSYMGLDEBUGMESSAGEINSERTARBPROC) (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *buf); typedef void (APIENTRYP RGLSYMGLDEBUGMESSAGECALLBACKARBPROC) (RGLGENGLDEBUGPROCARB callback, const void *userParam); typedef GLuint (APIENTRYP RGLSYMGLGETDEBUGMESSAGELOGARBPROC) (GLuint count, GLsizei bufSize, GLenum *sources, GLenum *types, GLuint *ids, GLenum *severities, GLsizei *lengths, GLchar *messageLog); typedef void (APIENTRYP RGLSYMGLDRAWBUFFERSARBPROC) (GLsizei n, const GLenum *bufs); typedef void (APIENTRYP RGLSYMGLBLENDEQUATIONIARBPROC) (GLuint buf, GLenum mode); typedef void (APIENTRYP RGLSYMGLBLENDEQUATIONSEPARATEIARBPROC) (GLuint buf, GLenum modeRGB, GLenum modeAlpha); typedef void (APIENTRYP RGLSYMGLBLENDFUNCIARBPROC) (GLuint buf, GLenum src, GLenum dst); typedef void (APIENTRYP RGLSYMGLBLENDFUNCSEPARATEIARBPROC) (GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha); typedef void (APIENTRYP RGLSYMGLDRAWARRAYSINSTANCEDARBPROC) (GLenum mode, GLint first, GLsizei count, GLsizei primcount); typedef void (APIENTRYP RGLSYMGLDRAWELEMENTSINSTANCEDARBPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount); typedef void (APIENTRYP RGLSYMGLPROGRAMSTRINGARBPROC) (GLenum target, GLenum format, GLsizei len, const void *string); typedef void (APIENTRYP RGLSYMGLBINDPROGRAMARBPROC) (GLenum target, GLuint program); typedef void (APIENTRYP RGLSYMGLDELETEPROGRAMSARBPROC) (GLsizei n, const GLuint *programs); typedef void (APIENTRYP RGLSYMGLGENPROGRAMSARBPROC) (GLsizei n, GLuint *programs); typedef void (APIENTRYP RGLSYMGLPROGRAMENVPARAMETER4DARBPROC) (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); typedef void (APIENTRYP RGLSYMGLPROGRAMENVPARAMETER4DVARBPROC) (GLenum target, GLuint index, const GLdouble *params); typedef void (APIENTRYP RGLSYMGLPROGRAMENVPARAMETER4FARBPROC) (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); typedef void (APIENTRYP RGLSYMGLPROGRAMENVPARAMETER4FVARBPROC) (GLenum target, GLuint index, const GLfloat *params); typedef void (APIENTRYP RGLSYMGLPROGRAMLOCALPARAMETER4DARBPROC) (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); typedef void (APIENTRYP RGLSYMGLPROGRAMLOCALPARAMETER4DVARBPROC) (GLenum target, GLuint index, const GLdouble *params); typedef void (APIENTRYP RGLSYMGLPROGRAMLOCALPARAMETER4FARBPROC) (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); typedef void (APIENTRYP RGLSYMGLPROGRAMLOCALPARAMETER4FVARBPROC) (GLenum target, GLuint index, const GLfloat *params); typedef void (APIENTRYP RGLSYMGLGETPROGRAMENVPARAMETERDVARBPROC) (GLenum target, GLuint index, GLdouble *params); typedef void (APIENTRYP RGLSYMGLGETPROGRAMENVPARAMETERFVARBPROC) (GLenum target, GLuint index, GLfloat *params); typedef void (APIENTRYP RGLSYMGLGETPROGRAMLOCALPARAMETERDVARBPROC) (GLenum target, GLuint index, GLdouble *params); typedef void (APIENTRYP RGLSYMGLGETPROGRAMLOCALPARAMETERFVARBPROC) (GLenum target, GLuint index, GLfloat *params); typedef void (APIENTRYP RGLSYMGLGETPROGRAMIVARBPROC) (GLenum target, GLenum pname, GLint *params); typedef void (APIENTRYP RGLSYMGLGETPROGRAMSTRINGARBPROC) (GLenum target, GLenum pname, void *string); typedef GLboolean (APIENTRYP RGLSYMGLISPROGRAMARBPROC) (GLuint program); typedef void (APIENTRYP RGLSYMGLPROGRAMPARAMETERIARBPROC) (GLuint program, GLenum pname, GLint value); typedef void (APIENTRYP RGLSYMGLFRAMEBUFFERTEXTUREARBPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level); typedef void (APIENTRYP RGLSYMGLFRAMEBUFFERTEXTURELAYERARBPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer); typedef void (APIENTRYP RGLSYMGLFRAMEBUFFERTEXTUREFACEARBPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLenum face); typedef void (APIENTRYP RGLSYMGLCOLORTABLEPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const void *table); typedef void (APIENTRYP RGLSYMGLCOLORTABLEPARAMETERFVPROC) (GLenum target, GLenum pname, const GLfloat *params); typedef void (APIENTRYP RGLSYMGLCOLORTABLEPARAMETERIVPROC) (GLenum target, GLenum pname, const GLint *params); typedef void (APIENTRYP RGLSYMGLCOPYCOLORTABLEPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width); typedef void (APIENTRYP RGLSYMGLGETCOLORTABLEPROC) (GLenum target, GLenum format, GLenum type, void *table); typedef void (APIENTRYP RGLSYMGLGETCOLORTABLEPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params); typedef void (APIENTRYP RGLSYMGLGETCOLORTABLEPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params); typedef void (APIENTRYP RGLSYMGLCOLORSUBTABLEPROC) (GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const GLvoid *data); typedef void (APIENTRYP RGLSYMGLCOPYCOLORSUBTABLEPROC) (GLenum target, GLsizei start, GLint x, GLint y, GLsizei width); typedef void (APIENTRYP RGLSYMGLCONVOLUTIONFILTER1DPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const void *image); typedef void (APIENTRYP RGLSYMGLCONVOLUTIONFILTER2DPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *image); typedef void (APIENTRYP RGLSYMGLCONVOLUTIONPARAMETERFPROC) (GLenum target, GLenum pname, GLfloat params); typedef void (APIENTRYP RGLSYMGLCONVOLUTIONPARAMETERFVPROC) (GLenum target, GLenum pname, const GLfloat *params); typedef void (APIENTRYP RGLSYMGLCONVOLUTIONPARAMETERIPROC) (GLenum target, GLenum pname, GLint params); typedef void (APIENTRYP RGLSYMGLCONVOLUTIONPARAMETERIVPROC) (GLenum target, GLenum pname, const GLint *params); typedef void (APIENTRYP RGLSYMGLCOPYCONVOLUTIONFILTER1DPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width); typedef void (APIENTRYP RGLSYMGLCOPYCONVOLUTIONFILTER2DPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height); typedef void (APIENTRYP RGLSYMGLGETCONVOLUTIONFILTERPROC) (GLenum target, GLenum format, GLenum type, void *image); typedef void (APIENTRYP RGLSYMGLGETCONVOLUTIONPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params); typedef void (APIENTRYP RGLSYMGLGETCONVOLUTIONPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params); typedef void (APIENTRYP RGLSYMGLGETSEPARABLEFILTERPROC) (GLenum target, GLenum format, GLenum type, void *row, void *column, void *span); typedef void (APIENTRYP RGLSYMGLSEPARABLEFILTER2DPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *row, const void *column); typedef void (APIENTRYP RGLSYMGLGETHISTOGRAMPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, void *values); typedef void (APIENTRYP RGLSYMGLGETHISTOGRAMPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params); typedef void (APIENTRYP RGLSYMGLGETHISTOGRAMPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params); typedef void (APIENTRYP RGLSYMGLGETMINMAXPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, void *values); typedef void (APIENTRYP RGLSYMGLGETMINMAXPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params); typedef void (APIENTRYP RGLSYMGLGETMINMAXPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params); typedef void (APIENTRYP RGLSYMGLHISTOGRAMPROC) (GLenum target, GLsizei width, GLenum internalformat, GLboolean sink); typedef void (APIENTRYP RGLSYMGLMINMAXPROC) (GLenum target, GLenum internalformat, GLboolean sink); typedef void (APIENTRYP RGLSYMGLRESETHISTOGRAMPROC) (GLenum target); typedef void (APIENTRYP RGLSYMGLRESETMINMAXPROC) (GLenum target); typedef void (APIENTRYP RGLSYMGLMULTIDRAWARRAYSINDIRECTCOUNTARBPROC) (GLenum mode, GLintptr indirect, GLintptr drawcount, GLsizei maxdrawcount, GLsizei stride); typedef void (APIENTRYP RGLSYMGLMULTIDRAWELEMENTSINDIRECTCOUNTARBPROC) (GLenum mode, GLenum type, GLintptr indirect, GLintptr drawcount, GLsizei maxdrawcount, GLsizei stride); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIBDIVISORARBPROC) (GLuint index, GLuint divisor); typedef void (APIENTRYP RGLSYMGLCURRENTPALETTEMATRIXARBPROC) (GLint index); typedef void (APIENTRYP RGLSYMGLMATRIXINDEXUBVARBPROC) (GLint size, const GLubyte *indices); typedef void (APIENTRYP RGLSYMGLMATRIXINDEXUSVARBPROC) (GLint size, const GLushort *indices); typedef void (APIENTRYP RGLSYMGLMATRIXINDEXUIVARBPROC) (GLint size, const GLuint *indices); typedef void (APIENTRYP RGLSYMGLMATRIXINDEXPOINTERARBPROC) (GLint size, GLenum type, GLsizei stride, const void *pointer); typedef void (APIENTRYP RGLSYMGLSAMPLECOVERAGEARBPROC) (GLfloat value, GLboolean invert); typedef void (APIENTRYP RGLSYMGLACTIVETEXTUREARBPROC) (GLenum texture); typedef void (APIENTRYP RGLSYMGLCLIENTACTIVETEXTUREARBPROC) (GLenum texture); typedef void (APIENTRYP RGLSYMGLMULTITEXCOORD1DARBPROC) (GLenum target, GLdouble s); typedef void (APIENTRYP RGLSYMGLMULTITEXCOORD1DVARBPROC) (GLenum target, const GLdouble *v); typedef void (APIENTRYP RGLSYMGLMULTITEXCOORD1FARBPROC) (GLenum target, GLfloat s); typedef void (APIENTRYP RGLSYMGLMULTITEXCOORD1FVARBPROC) (GLenum target, const GLfloat *v); typedef void (APIENTRYP RGLSYMGLMULTITEXCOORD1IARBPROC) (GLenum target, GLint s); typedef void (APIENTRYP RGLSYMGLMULTITEXCOORD1IVARBPROC) (GLenum target, const GLint *v); typedef void (APIENTRYP RGLSYMGLMULTITEXCOORD1SARBPROC) (GLenum target, GLshort s); typedef void (APIENTRYP RGLSYMGLMULTITEXCOORD1SVARBPROC) (GLenum target, const GLshort *v); typedef void (APIENTRYP RGLSYMGLMULTITEXCOORD2DARBPROC) (GLenum target, GLdouble s, GLdouble t); typedef void (APIENTRYP RGLSYMGLMULTITEXCOORD2DVARBPROC) (GLenum target, const GLdouble *v); typedef void (APIENTRYP RGLSYMGLMULTITEXCOORD2FARBPROC) (GLenum target, GLfloat s, GLfloat t); typedef void (APIENTRYP RGLSYMGLMULTITEXCOORD2FVARBPROC) (GLenum target, const GLfloat *v); typedef void (APIENTRYP RGLSYMGLMULTITEXCOORD2IARBPROC) (GLenum target, GLint s, GLint t); typedef void (APIENTRYP RGLSYMGLMULTITEXCOORD2IVARBPROC) (GLenum target, const GLint *v); typedef void (APIENTRYP RGLSYMGLMULTITEXCOORD2SARBPROC) (GLenum target, GLshort s, GLshort t); typedef void (APIENTRYP RGLSYMGLMULTITEXCOORD2SVARBPROC) (GLenum target, const GLshort *v); typedef void (APIENTRYP RGLSYMGLMULTITEXCOORD3DARBPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r); typedef void (APIENTRYP RGLSYMGLMULTITEXCOORD3DVARBPROC) (GLenum target, const GLdouble *v); typedef void (APIENTRYP RGLSYMGLMULTITEXCOORD3FARBPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r); typedef void (APIENTRYP RGLSYMGLMULTITEXCOORD3FVARBPROC) (GLenum target, const GLfloat *v); typedef void (APIENTRYP RGLSYMGLMULTITEXCOORD3IARBPROC) (GLenum target, GLint s, GLint t, GLint r); typedef void (APIENTRYP RGLSYMGLMULTITEXCOORD3IVARBPROC) (GLenum target, const GLint *v); typedef void (APIENTRYP RGLSYMGLMULTITEXCOORD3SARBPROC) (GLenum target, GLshort s, GLshort t, GLshort r); typedef void (APIENTRYP RGLSYMGLMULTITEXCOORD3SVARBPROC) (GLenum target, const GLshort *v); typedef void (APIENTRYP RGLSYMGLMULTITEXCOORD4DARBPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q); typedef void (APIENTRYP RGLSYMGLMULTITEXCOORD4DVARBPROC) (GLenum target, const GLdouble *v); typedef void (APIENTRYP RGLSYMGLMULTITEXCOORD4FARBPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q); typedef void (APIENTRYP RGLSYMGLMULTITEXCOORD4FVARBPROC) (GLenum target, const GLfloat *v); typedef void (APIENTRYP RGLSYMGLMULTITEXCOORD4IARBPROC) (GLenum target, GLint s, GLint t, GLint r, GLint q); typedef void (APIENTRYP RGLSYMGLMULTITEXCOORD4IVARBPROC) (GLenum target, const GLint *v); typedef void (APIENTRYP RGLSYMGLMULTITEXCOORD4SARBPROC) (GLenum target, GLshort s, GLshort t, GLshort r, GLshort q); typedef void (APIENTRYP RGLSYMGLMULTITEXCOORD4SVARBPROC) (GLenum target, const GLshort *v); typedef void (APIENTRYP RGLSYMGLGENQUERIESARBPROC) (GLsizei n, GLuint *ids); typedef void (APIENTRYP RGLSYMGLDELETEQUERIESARBPROC) (GLsizei n, const GLuint *ids); typedef GLboolean (APIENTRYP RGLSYMGLISQUERYARBPROC) (GLuint id); typedef void (APIENTRYP RGLSYMGLBEGINQUERYARBPROC) (GLenum target, GLuint id); typedef void (APIENTRYP RGLSYMGLENDQUERYARBPROC) (GLenum target); typedef void (APIENTRYP RGLSYMGLGETQUERYIVARBPROC) (GLenum target, GLenum pname, GLint *params); typedef void (APIENTRYP RGLSYMGLGETQUERYOBJECTIVARBPROC) (GLuint id, GLenum pname, GLint *params); typedef void (APIENTRYP RGLSYMGLGETQUERYOBJECTUIVARBPROC) (GLuint id, GLenum pname, GLuint *params); typedef void (APIENTRYP RGLSYMGLPOINTPARAMETERFARBPROC) (GLenum pname, GLfloat param); typedef void (APIENTRYP RGLSYMGLPOINTPARAMETERFVARBPROC) (GLenum pname, const GLfloat *params); typedef GLenum (APIENTRYP RGLSYMGLGETGRAPHICSRESETSTATUSARBPROC) (void); typedef void (APIENTRYP RGLSYMGLGETNTEXIMAGEARBPROC) (GLenum target, GLint level, GLenum format, GLenum type, GLsizei bufSize, void *img); typedef void (APIENTRYP RGLSYMGLREADNPIXELSARBPROC) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void *data); typedef void (APIENTRYP RGLSYMGLGETNCOMPRESSEDTEXIMAGEARBPROC) (GLenum target, GLint lod, GLsizei bufSize, void *img); typedef void (APIENTRYP RGLSYMGLGETNUNIFORMFVARBPROC) (GLuint program, GLint location, GLsizei bufSize, GLfloat *params); typedef void (APIENTRYP RGLSYMGLGETNUNIFORMIVARBPROC) (GLuint program, GLint location, GLsizei bufSize, GLint *params); typedef void (APIENTRYP RGLSYMGLGETNUNIFORMUIVARBPROC) (GLuint program, GLint location, GLsizei bufSize, GLuint *params); typedef void (APIENTRYP RGLSYMGLGETNUNIFORMDVARBPROC) (GLuint program, GLint location, GLsizei bufSize, GLdouble *params); typedef void (APIENTRYP RGLSYMGLGETNMAPDVARBPROC) (GLenum target, GLenum query, GLsizei bufSize, GLdouble *v); typedef void (APIENTRYP RGLSYMGLGETNMAPFVARBPROC) (GLenum target, GLenum query, GLsizei bufSize, GLfloat *v); typedef void (APIENTRYP RGLSYMGLGETNMAPIVARBPROC) (GLenum target, GLenum query, GLsizei bufSize, GLint *v); typedef void (APIENTRYP RGLSYMGLGETNPIXELMAPFVARBPROC) (GLenum map, GLsizei bufSize, GLfloat *values); typedef void (APIENTRYP RGLSYMGLGETNPIXELMAPUIVARBPROC) (GLenum map, GLsizei bufSize, GLuint *values); typedef void (APIENTRYP RGLSYMGLGETNPIXELMAPUSVARBPROC) (GLenum map, GLsizei bufSize, GLushort *values); typedef void (APIENTRYP RGLSYMGLGETNPOLYGONSTIPPLEARBPROC) (GLsizei bufSize, GLubyte *pattern); typedef void (APIENTRYP RGLSYMGLGETNCOLORTABLEARBPROC) (GLenum target, GLenum format, GLenum type, GLsizei bufSize, void *table); typedef void (APIENTRYP RGLSYMGLGETNCONVOLUTIONFILTERARBPROC) (GLenum target, GLenum format, GLenum type, GLsizei bufSize, void *image); typedef void (APIENTRYP RGLSYMGLGETNSEPARABLEFILTERARBPROC) (GLenum target, GLenum format, GLenum type, GLsizei rowBufSize, void *row, GLsizei columnBufSize, void *column, void *span); typedef void (APIENTRYP RGLSYMGLGETNHISTOGRAMARBPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLsizei bufSize, void *values); typedef void (APIENTRYP RGLSYMGLGETNMINMAXARBPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLsizei bufSize, void *values); typedef void (APIENTRYP RGLSYMGLMINSAMPLESHADINGARBPROC) (GLfloat value); typedef void (APIENTRYP RGLSYMGLDELETEOBJECTARBPROC) (GLhandleARB obj); typedef GLhandleARB (APIENTRYP RGLSYMGLGETHANDLEARBPROC) (GLenum pname); typedef void (APIENTRYP RGLSYMGLDETACHOBJECTARBPROC) (GLhandleARB containerObj, GLhandleARB attachedObj); typedef GLhandleARB (APIENTRYP RGLSYMGLCREATESHADEROBJECTARBPROC) (GLenum shaderType); typedef void (APIENTRYP RGLSYMGLSHADERSOURCEARBPROC) (GLhandleARB shaderObj, GLsizei count, const GLcharARB **string, const GLint *length); typedef void (APIENTRYP RGLSYMGLCOMPILESHADERARBPROC) (GLhandleARB shaderObj); typedef GLhandleARB (APIENTRYP RGLSYMGLCREATEPROGRAMOBJECTARBPROC) (void); typedef void (APIENTRYP RGLSYMGLATTACHOBJECTARBPROC) (GLhandleARB containerObj, GLhandleARB obj); typedef void (APIENTRYP RGLSYMGLLINKPROGRAMARBPROC) (GLhandleARB programObj); typedef void (APIENTRYP RGLSYMGLUSEPROGRAMOBJECTARBPROC) (GLhandleARB programObj); typedef void (APIENTRYP RGLSYMGLVALIDATEPROGRAMARBPROC) (GLhandleARB programObj); typedef void (APIENTRYP RGLSYMGLUNIFORM1FARBPROC) (GLint location, GLfloat v0); typedef void (APIENTRYP RGLSYMGLUNIFORM2FARBPROC) (GLint location, GLfloat v0, GLfloat v1); typedef void (APIENTRYP RGLSYMGLUNIFORM3FARBPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2); typedef void (APIENTRYP RGLSYMGLUNIFORM4FARBPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); typedef void (APIENTRYP RGLSYMGLUNIFORM1IARBPROC) (GLint location, GLint v0); typedef void (APIENTRYP RGLSYMGLUNIFORM2IARBPROC) (GLint location, GLint v0, GLint v1); typedef void (APIENTRYP RGLSYMGLUNIFORM3IARBPROC) (GLint location, GLint v0, GLint v1, GLint v2); typedef void (APIENTRYP RGLSYMGLUNIFORM4IARBPROC) (GLint location, GLint v0, GLint v1, GLint v2, GLint v3); typedef void (APIENTRYP RGLSYMGLUNIFORM1FVARBPROC) (GLint location, GLsizei count, const GLfloat *value); typedef void (APIENTRYP RGLSYMGLUNIFORM2FVARBPROC) (GLint location, GLsizei count, const GLfloat *value); typedef void (APIENTRYP RGLSYMGLUNIFORM3FVARBPROC) (GLint location, GLsizei count, const GLfloat *value); typedef void (APIENTRYP RGLSYMGLUNIFORM4FVARBPROC) (GLint location, GLsizei count, const GLfloat *value); typedef void (APIENTRYP RGLSYMGLUNIFORM1IVARBPROC) (GLint location, GLsizei count, const GLint *value); typedef void (APIENTRYP RGLSYMGLUNIFORM2IVARBPROC) (GLint location, GLsizei count, const GLint *value); typedef void (APIENTRYP RGLSYMGLUNIFORM3IVARBPROC) (GLint location, GLsizei count, const GLint *value); typedef void (APIENTRYP RGLSYMGLUNIFORM4IVARBPROC) (GLint location, GLsizei count, const GLint *value); typedef void (APIENTRYP RGLSYMGLUNIFORMMATRIX2FVARBPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); typedef void (APIENTRYP RGLSYMGLUNIFORMMATRIX3FVARBPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); typedef void (APIENTRYP RGLSYMGLUNIFORMMATRIX4FVARBPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); typedef void (APIENTRYP RGLSYMGLGETOBJECTPARAMETERFVARBPROC) (GLhandleARB obj, GLenum pname, GLfloat *params); typedef void (APIENTRYP RGLSYMGLGETOBJECTPARAMETERIVARBPROC) (GLhandleARB obj, GLenum pname, GLint *params); typedef void (APIENTRYP RGLSYMGLGETINFOLOGARBPROC) (GLhandleARB obj, GLsizei maxLength, GLsizei *length, GLcharARB *infoLog); typedef void (APIENTRYP RGLSYMGLGETATTACHEDOBJECTSARBPROC) (GLhandleARB containerObj, GLsizei maxCount, GLsizei *count, GLhandleARB *obj); typedef GLint (APIENTRYP RGLSYMGLGETUNIFORMLOCATIONARBPROC) (GLhandleARB programObj, const GLcharARB *name); typedef void (APIENTRYP RGLSYMGLGETACTIVEUNIFORMARBPROC) (GLhandleARB programObj, GLuint index, GLsizei maxLength, GLsizei *length, GLint *size, GLenum *type, GLcharARB *name); typedef void (APIENTRYP RGLSYMGLGETUNIFORMFVARBPROC) (GLhandleARB programObj, GLint location, GLfloat *params); typedef void (APIENTRYP RGLSYMGLGETUNIFORMIVARBPROC) (GLhandleARB programObj, GLint location, GLint *params); typedef void (APIENTRYP RGLSYMGLGETSHADERSOURCEARBPROC) (GLhandleARB obj, GLsizei maxLength, GLsizei *length, GLcharARB *source); typedef void (APIENTRYP RGLSYMGLNAMEDSTRINGARBPROC) (GLenum type, GLint namelen, const GLchar *name, GLint stringlen, const GLchar *string); typedef void (APIENTRYP RGLSYMGLDELETENAMEDSTRINGARBPROC) (GLint namelen, const GLchar *name); typedef void (APIENTRYP RGLSYMGLCOMPILESHADERINCLUDEARBPROC) (GLuint shader, GLsizei count, const GLchar *const*path, const GLint *length); typedef GLboolean (APIENTRYP RGLSYMGLISNAMEDSTRINGARBPROC) (GLint namelen, const GLchar *name); typedef void (APIENTRYP RGLSYMGLGETNAMEDSTRINGARBPROC) (GLint namelen, const GLchar *name, GLsizei bufSize, GLint *stringlen, GLchar *string); typedef void (APIENTRYP RGLSYMGLGETNAMEDSTRINGIVARBPROC) (GLint namelen, const GLchar *name, GLenum pname, GLint *params); typedef void (APIENTRYP RGLSYMGLTEXPAGECOMMITMENTARBPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLboolean resident); typedef void (APIENTRYP RGLSYMGLTEXBUFFERARBPROC) (GLenum target, GLenum internalformat, GLuint buffer); typedef void (APIENTRYP RGLSYMGLCOMPRESSEDTEXIMAGE3DARBPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data); typedef void (APIENTRYP RGLSYMGLCOMPRESSEDTEXIMAGE2DARBPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *data); typedef void (APIENTRYP RGLSYMGLCOMPRESSEDTEXIMAGE1DARBPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const void *data); typedef void (APIENTRYP RGLSYMGLCOMPRESSEDTEXSUBIMAGE3DARBPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data); typedef void (APIENTRYP RGLSYMGLCOMPRESSEDTEXSUBIMAGE2DARBPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data); typedef void (APIENTRYP RGLSYMGLCOMPRESSEDTEXSUBIMAGE1DARBPROC) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void *data); typedef void (APIENTRYP RGLSYMGLGETCOMPRESSEDTEXIMAGEARBPROC) (GLenum target, GLint level, void *img); typedef void (APIENTRYP RGLSYMGLLOADTRANSPOSEMATRIXFARBPROC) (const GLfloat *m); typedef void (APIENTRYP RGLSYMGLLOADTRANSPOSEMATRIXDARBPROC) (const GLdouble *m); typedef void (APIENTRYP RGLSYMGLMULTTRANSPOSEMATRIXFARBPROC) (const GLfloat *m); typedef void (APIENTRYP RGLSYMGLMULTTRANSPOSEMATRIXDARBPROC) (const GLdouble *m); typedef void (APIENTRYP RGLSYMGLWEIGHTBVARBPROC) (GLint size, const GLbyte *weights); typedef void (APIENTRYP RGLSYMGLWEIGHTSVARBPROC) (GLint size, const GLshort *weights); typedef void (APIENTRYP RGLSYMGLWEIGHTIVARBPROC) (GLint size, const GLint *weights); typedef void (APIENTRYP RGLSYMGLWEIGHTFVARBPROC) (GLint size, const GLfloat *weights); typedef void (APIENTRYP RGLSYMGLWEIGHTDVARBPROC) (GLint size, const GLdouble *weights); typedef void (APIENTRYP RGLSYMGLWEIGHTUBVARBPROC) (GLint size, const GLubyte *weights); typedef void (APIENTRYP RGLSYMGLWEIGHTUSVARBPROC) (GLint size, const GLushort *weights); typedef void (APIENTRYP RGLSYMGLWEIGHTUIVARBPROC) (GLint size, const GLuint *weights); typedef void (APIENTRYP RGLSYMGLWEIGHTPOINTERARBPROC) (GLint size, GLenum type, GLsizei stride, const void *pointer); typedef void (APIENTRYP RGLSYMGLVERTEXBLENDARBPROC) (GLint count); typedef void (APIENTRYP RGLSYMGLBINDBUFFERARBPROC) (GLenum target, GLuint buffer); typedef void (APIENTRYP RGLSYMGLDELETEBUFFERSARBPROC) (GLsizei n, const GLuint *buffers); typedef void (APIENTRYP RGLSYMGLGENBUFFERSARBPROC) (GLsizei n, GLuint *buffers); typedef GLboolean (APIENTRYP RGLSYMGLISBUFFERARBPROC) (GLuint buffer); typedef void (APIENTRYP RGLSYMGLBUFFERDATAARBPROC) (GLenum target, GLsizeiptrARB size, const void *data, GLenum usage); typedef void (APIENTRYP RGLSYMGLBUFFERSUBDATAARBPROC) (GLenum target, GLintptrARB offset, GLsizeiptrARB size, const void *data); typedef void (APIENTRYP RGLSYMGLGETBUFFERSUBDATAARBPROC) (GLenum target, GLintptrARB offset, GLsizeiptrARB size, void *data); typedef void *(APIENTRYP RGLSYMGLMAPBUFFERARBPROC) (GLenum target, GLenum access); typedef GLboolean (APIENTRYP RGLSYMGLUNMAPBUFFERARBPROC) (GLenum target); typedef void (APIENTRYP RGLSYMGLGETBUFFERPARAMETERIVARBPROC) (GLenum target, GLenum pname, GLint *params); typedef void (APIENTRYP RGLSYMGLGETBUFFERPOINTERVARBPROC) (GLenum target, GLenum pname, void **params); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIB1DARBPROC) (GLuint index, GLdouble x); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIB1DVARBPROC) (GLuint index, const GLdouble *v); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIB1FARBPROC) (GLuint index, GLfloat x); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIB1FVARBPROC) (GLuint index, const GLfloat *v); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIB1SARBPROC) (GLuint index, GLshort x); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIB1SVARBPROC) (GLuint index, const GLshort *v); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIB2DARBPROC) (GLuint index, GLdouble x, GLdouble y); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIB2DVARBPROC) (GLuint index, const GLdouble *v); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIB2FARBPROC) (GLuint index, GLfloat x, GLfloat y); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIB2FVARBPROC) (GLuint index, const GLfloat *v); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIB2SARBPROC) (GLuint index, GLshort x, GLshort y); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIB2SVARBPROC) (GLuint index, const GLshort *v); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIB3DARBPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIB3DVARBPROC) (GLuint index, const GLdouble *v); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIB3FARBPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIB3FVARBPROC) (GLuint index, const GLfloat *v); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIB3SARBPROC) (GLuint index, GLshort x, GLshort y, GLshort z); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIB3SVARBPROC) (GLuint index, const GLshort *v); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIB4NBVARBPROC) (GLuint index, const GLbyte *v); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIB4NIVARBPROC) (GLuint index, const GLint *v); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIB4NSVARBPROC) (GLuint index, const GLshort *v); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIB4NUBARBPROC) (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIB4NUBVARBPROC) (GLuint index, const GLubyte *v); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIB4NUIVARBPROC) (GLuint index, const GLuint *v); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIB4NUSVARBPROC) (GLuint index, const GLushort *v); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIB4BVARBPROC) (GLuint index, const GLbyte *v); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIB4DARBPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIB4DVARBPROC) (GLuint index, const GLdouble *v); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIB4FARBPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIB4FVARBPROC) (GLuint index, const GLfloat *v); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIB4IVARBPROC) (GLuint index, const GLint *v); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIB4SARBPROC) (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIB4SVARBPROC) (GLuint index, const GLshort *v); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIB4UBVARBPROC) (GLuint index, const GLubyte *v); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIB4UIVARBPROC) (GLuint index, const GLuint *v); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIB4USVARBPROC) (GLuint index, const GLushort *v); typedef void (APIENTRYP RGLSYMGLVERTEXATTRIBPOINTERARBPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer); typedef void (APIENTRYP RGLSYMGLENABLEVERTEXATTRIBARRAYARBPROC) (GLuint index); typedef void (APIENTRYP RGLSYMGLDISABLEVERTEXATTRIBARRAYARBPROC) (GLuint index); typedef void (APIENTRYP RGLSYMGLGETVERTEXATTRIBDVARBPROC) (GLuint index, GLenum pname, GLdouble *params); typedef void (APIENTRYP RGLSYMGLGETVERTEXATTRIBFVARBPROC) (GLuint index, GLenum pname, GLfloat *params); typedef void (APIENTRYP RGLSYMGLGETVERTEXATTRIBIVARBPROC) (GLuint index, GLenum pname, GLint *params); typedef void (APIENTRYP RGLSYMGLGETVERTEXATTRIBPOINTERVARBPROC) (GLuint index, GLenum pname, void **pointer); typedef void (APIENTRYP RGLSYMGLBINDATTRIBLOCATIONARBPROC) (GLhandleARB programObj, GLuint index, const GLcharARB *name); typedef void (APIENTRYP RGLSYMGLGETACTIVEATTRIBARBPROC) (GLhandleARB programObj, GLuint index, GLsizei maxLength, GLsizei *length, GLint *size, GLenum *type, GLcharARB *name); typedef GLint (APIENTRYP RGLSYMGLGETATTRIBLOCATIONARBPROC) (GLhandleARB programObj, const GLcharARB *name); typedef void (APIENTRYP RGLSYMGLWINDOWPOS2DARBPROC) (GLdouble x, GLdouble y); typedef void (APIENTRYP RGLSYMGLWINDOWPOS2DVARBPROC) (const GLdouble *v); typedef void (APIENTRYP RGLSYMGLWINDOWPOS2FARBPROC) (GLfloat x, GLfloat y); typedef void (APIENTRYP RGLSYMGLWINDOWPOS2FVARBPROC) (const GLfloat *v); typedef void (APIENTRYP RGLSYMGLWINDOWPOS2IARBPROC) (GLint x, GLint y); typedef void (APIENTRYP RGLSYMGLWINDOWPOS2IVARBPROC) (const GLint *v); typedef void (APIENTRYP RGLSYMGLWINDOWPOS2SARBPROC) (GLshort x, GLshort y); typedef void (APIENTRYP RGLSYMGLWINDOWPOS2SVARBPROC) (const GLshort *v); typedef void (APIENTRYP RGLSYMGLWINDOWPOS3DARBPROC) (GLdouble x, GLdouble y, GLdouble z); typedef void (APIENTRYP RGLSYMGLWINDOWPOS3DVARBPROC) (const GLdouble *v); typedef void (APIENTRYP RGLSYMGLWINDOWPOS3FARBPROC) (GLfloat x, GLfloat y, GLfloat z); typedef void (APIENTRYP RGLSYMGLWINDOWPOS3FVARBPROC) (const GLfloat *v); typedef void (APIENTRYP RGLSYMGLWINDOWPOS3IARBPROC) (GLint x, GLint y, GLint z); typedef void (APIENTRYP RGLSYMGLWINDOWPOS3IVARBPROC) (const GLint *v); typedef void (APIENTRYP RGLSYMGLWINDOWPOS3SARBPROC) (GLshort x, GLshort y, GLshort z); typedef void (APIENTRYP RGLSYMGLWINDOWPOS3SVARBPROC) (const GLshort *v); typedef void (APIENTRYP RGLSYMGLMULTITEXCOORD1BOESPROC) (GLenum texture, GLbyte s); typedef void (APIENTRYP RGLSYMGLMULTITEXCOORD1BVOESPROC) (GLenum texture, const GLbyte *coords); typedef void (APIENTRYP RGLSYMGLMULTITEXCOORD2BOESPROC) (GLenum texture, GLbyte s, GLbyte t); typedef void (APIENTRYP RGLSYMGLMULTITEXCOORD2BVOESPROC) (GLenum texture, const GLbyte *coords); typedef void (APIENTRYP RGLSYMGLMULTITEXCOORD3BOESPROC) (GLenum texture, GLbyte s, GLbyte t, GLbyte r); typedef void (APIENTRYP RGLSYMGLMULTITEXCOORD3BVOESPROC) (GLenum texture, const GLbyte *coords); typedef void (APIENTRYP RGLSYMGLMULTITEXCOORD4BOESPROC) (GLenum texture, GLbyte s, GLbyte t, GLbyte r, GLbyte q); typedef void (APIENTRYP RGLSYMGLMULTITEXCOORD4BVOESPROC) (GLenum texture, const GLbyte *coords); typedef void (APIENTRYP RGLSYMGLTEXCOORD1BOESPROC) (GLbyte s); typedef void (APIENTRYP RGLSYMGLTEXCOORD1BVOESPROC) (const GLbyte *coords); typedef void (APIENTRYP RGLSYMGLTEXCOORD2BOESPROC) (GLbyte s, GLbyte t); typedef void (APIENTRYP RGLSYMGLTEXCOORD2BVOESPROC) (const GLbyte *coords); typedef void (APIENTRYP RGLSYMGLTEXCOORD3BOESPROC) (GLbyte s, GLbyte t, GLbyte r); typedef void (APIENTRYP RGLSYMGLTEXCOORD3BVOESPROC) (const GLbyte *coords); typedef void (APIENTRYP RGLSYMGLTEXCOORD4BOESPROC) (GLbyte s, GLbyte t, GLbyte r, GLbyte q); typedef void (APIENTRYP RGLSYMGLTEXCOORD4BVOESPROC) (const GLbyte *coords); typedef void (APIENTRYP RGLSYMGLVERTEX2BOESPROC) (GLbyte x); typedef void (APIENTRYP RGLSYMGLVERTEX2BVOESPROC) (const GLbyte *coords); typedef void (APIENTRYP RGLSYMGLVERTEX3BOESPROC) (GLbyte x, GLbyte y); typedef void (APIENTRYP RGLSYMGLVERTEX3BVOESPROC) (const GLbyte *coords); typedef void (APIENTRYP RGLSYMGLVERTEX4BOESPROC) (GLbyte x, GLbyte y, GLbyte z); typedef void (APIENTRYP RGLSYMGLVERTEX4BVOESPROC) (const GLbyte *coords); typedef void (APIENTRYP RGLSYMGLALPHAFUNCXOESPROC) (GLenum func, GLfixed ref); typedef void (APIENTRYP RGLSYMGLCLEARCOLORXOESPROC) (GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha); typedef void (APIENTRYP RGLSYMGLCLEARDEPTHXOESPROC) (GLfixed depth); typedef void (APIENTRYP RGLSYMGLCLIPPLANEXOESPROC) (GLenum plane, const GLfixed *equation); typedef void (APIENTRYP RGLSYMGLCOLOR4XOESPROC) (GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha); typedef void (APIENTRYP RGLSYMGLDEPTHRANGEXOESPROC) (GLfixed n, GLfixed f); typedef void (APIENTRYP RGLSYMGLFOGXOESPROC) (GLenum pname, GLfixed param); typedef void (APIENTRYP RGLSYMGLFOGXVOESPROC) (GLenum pname, const GLfixed *param); typedef void (APIENTRYP RGLSYMGLFRUSTUMXOESPROC) (GLfixed l, GLfixed r, GLfixed b, GLfixed t, GLfixed n, GLfixed f); typedef void (APIENTRYP RGLSYMGLGETCLIPPLANEXOESPROC) (GLenum plane, GLfixed *equation); typedef void (APIENTRYP RGLSYMGLGETFIXEDVOESPROC) (GLenum pname, GLfixed *params); typedef void (APIENTRYP RGLSYMGLGETTEXENVXVOESPROC) (GLenum target, GLenum pname, GLfixed *params); typedef void (APIENTRYP RGLSYMGLGETTEXPARAMETERXVOESPROC) (GLenum target, GLenum pname, GLfixed *params); typedef void (APIENTRYP RGLSYMGLLIGHTMODELXOESPROC) (GLenum pname, GLfixed param); typedef void (APIENTRYP RGLSYMGLLIGHTMODELXVOESPROC) (GLenum pname, const GLfixed *param); typedef void (APIENTRYP RGLSYMGLLIGHTXOESPROC) (GLenum light, GLenum pname, GLfixed param); typedef void (APIENTRYP RGLSYMGLLIGHTXVOESPROC) (GLenum light, GLenum pname, const GLfixed *params); typedef void (APIENTRYP RGLSYMGLLINEWIDTHXOESPROC) (GLfixed width); typedef void (APIENTRYP RGLSYMGLLOADMATRIXXOESPROC) (const GLfixed *m); typedef void (APIENTRYP RGLSYMGLMATERIALXOESPROC) (GLenum face, GLenum pname, GLfixed param); typedef void (APIENTRYP RGLSYMGLMATERIALXVOESPROC) (GLenum face, GLenum pname, const GLfixed *param); typedef void (APIENTRYP RGLSYMGLMULTMATRIXXOESPROC) (const GLfixed *m); typedef void (APIENTRYP RGLSYMGLMULTITEXCOORD4XOESPROC) (GLenum texture, GLfixed s, GLfixed t, GLfixed r, GLfixed q); typedef void (APIENTRYP RGLSYMGLNORMAL3XOESPROC) (GLfixed nx, GLfixed ny, GLfixed nz); typedef void (APIENTRYP RGLSYMGLORTHOXOESPROC) (GLfixed l, GLfixed r, GLfixed b, GLfixed t, GLfixed n, GLfixed f); typedef void (APIENTRYP RGLSYMGLPOINTPARAMETERXVOESPROC) (GLenum pname, const GLfixed *params); typedef void (APIENTRYP RGLSYMGLPOINTSIZEXOESPROC) (GLfixed size); typedef void (APIENTRYP RGLSYMGLPOLYGONOFFSETXOESPROC) (GLfixed factor, GLfixed units); typedef void (APIENTRYP RGLSYMGLROTATEXOESPROC) (GLfixed angle, GLfixed x, GLfixed y, GLfixed z); typedef void (APIENTRYP RGLSYMGLSAMPLECOVERAGEOESPROC) (GLfixed value, GLboolean invert); typedef void (APIENTRYP RGLSYMGLSCALEXOESPROC) (GLfixed x, GLfixed y, GLfixed z); typedef void (APIENTRYP RGLSYMGLTEXENVXOESPROC) (GLenum target, GLenum pname, GLfixed param); typedef void (APIENTRYP RGLSYMGLTEXENVXVOESPROC) (GLenum target, GLenum pname, const GLfixed *params); typedef void (APIENTRYP RGLSYMGLTEXPARAMETERXOESPROC) (GLenum target, GLenum pname, GLfixed param); typedef void (APIENTRYP RGLSYMGLTEXPARAMETERXVOESPROC) (GLenum target, GLenum pname, const GLfixed *params); typedef void (APIENTRYP RGLSYMGLTRANSLATEXOESPROC) (GLfixed x, GLfixed y, GLfixed z); typedef void (APIENTRYP RGLSYMGLACCUMXOESPROC) (GLenum op, GLfixed value); typedef void (APIENTRYP RGLSYMGLBITMAPXOESPROC) (GLsizei width, GLsizei height, GLfixed xorig, GLfixed yorig, GLfixed xmove, GLfixed ymove, const GLubyte *bitmap); typedef void (APIENTRYP RGLSYMGLBLENDCOLORXOESPROC) (GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha); typedef void (APIENTRYP RGLSYMGLCLEARACCUMXOESPROC) (GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha); typedef void (APIENTRYP RGLSYMGLCOLOR3XOESPROC) (GLfixed red, GLfixed green, GLfixed blue); typedef void (APIENTRYP RGLSYMGLCOLOR3XVOESPROC) (const GLfixed *components); typedef void (APIENTRYP RGLSYMGLCOLOR4XVOESPROC) (const GLfixed *components); typedef void (APIENTRYP RGLSYMGLCONVOLUTIONPARAMETERXOESPROC) (GLenum target, GLenum pname, GLfixed param); typedef void (APIENTRYP RGLSYMGLCONVOLUTIONPARAMETERXVOESPROC) (GLenum target, GLenum pname, const GLfixed *params); typedef void (APIENTRYP RGLSYMGLEVALCOORD1XOESPROC) (GLfixed u); typedef void (APIENTRYP RGLSYMGLEVALCOORD1XVOESPROC) (const GLfixed *coords); typedef void (APIENTRYP RGLSYMGLEVALCOORD2XOESPROC) (GLfixed u, GLfixed v); typedef void (APIENTRYP RGLSYMGLEVALCOORD2XVOESPROC) (const GLfixed *coords); typedef void (APIENTRYP RGLSYMGLFEEDBACKBUFFERXOESPROC) (GLsizei n, GLenum type, const GLfixed *buffer); typedef void (APIENTRYP RGLSYMGLGETCONVOLUTIONPARAMETERXVOESPROC) (GLenum target, GLenum pname, GLfixed *params); typedef void (APIENTRYP RGLSYMGLGETHISTOGRAMPARAMETERXVOESPROC) (GLenum target, GLenum pname, GLfixed *params); typedef void (APIENTRYP RGLSYMGLGETLIGHTXOESPROC) (GLenum light, GLenum pname, GLfixed *params); typedef void (APIENTRYP RGLSYMGLGETMAPXVOESPROC) (GLenum target, GLenum query, GLfixed *v); typedef void (APIENTRYP RGLSYMGLGETMATERIALXOESPROC) (GLenum face, GLenum pname, GLfixed param); typedef void (APIENTRYP RGLSYMGLGETPIXELMAPXVPROC) (GLenum map, GLint size, GLfixed *values); typedef void (APIENTRYP RGLSYMGLGETTEXGENXVOESPROC) (GLenum coord, GLenum pname, GLfixed *params); typedef void (APIENTRYP RGLSYMGLGETTEXLEVELPARAMETERXVOESPROC) (GLenum target, GLint level, GLenum pname, GLfixed *params); typedef void (APIENTRYP RGLSYMGLINDEXXOESPROC) (GLfixed component); typedef void (APIENTRYP RGLSYMGLINDEXXVOESPROC) (const GLfixed *component); typedef void (APIENTRYP RGLSYMGLLOADTRANSPOSEMATRIXXOESPROC) (const GLfixed *m); typedef void (APIENTRYP RGLSYMGLMAP1XOESPROC) (GLenum target, GLfixed u1, GLfixed u2, GLint stride, GLint order, GLfixed points); typedef void (APIENTRYP RGLSYMGLMAP2XOESPROC) (GLenum target, GLfixed u1, GLfixed u2, GLint ustride, GLint uorder, GLfixed v1, GLfixed v2, GLint vstride, GLint vorder, GLfixed points); typedef void (APIENTRYP RGLSYMGLMAPGRID1XOESPROC) (GLint n, GLfixed u1, GLfixed u2); typedef void (APIENTRYP RGLSYMGLMAPGRID2XOESPROC) (GLint n, GLfixed u1, GLfixed u2, GLfixed v1, GLfixed v2); typedef void (APIENTRYP RGLSYMGLMULTTRANSPOSEMATRIXXOESPROC) (const GLfixed *m); typedef void (APIENTRYP RGLSYMGLMULTITEXCOORD1XOESPROC) (GLenum texture, GLfixed s); typedef void (APIENTRYP RGLSYMGLMULTITEXCOORD1XVOESPROC) (GLenum texture, const GLfixed *coords); typedef void (APIENTRYP RGLSYMGLMULTITEXCOORD2XOESPROC) (GLenum texture, GLfixed s, GLfixed t); typedef void (APIENTRYP RGLSYMGLMULTITEXCOORD2XVOESPROC) (GLenum texture, const GLfixed *coords); typedef void (APIENTRYP RGLSYMGLMULTITEXCOORD3XOESPROC) (GLenum texture, GLfixed s, GLfixed t, GLfixed r); typedef void (APIENTRYP RGLSYMGLMULTITEXCOORD3XVOESPROC) (GLenum texture, const GLfixed *coords); typedef void (APIENTRYP RGLSYMGLMULTITEXCOORD4XVOESPROC) (GLenum texture, const GLfixed *coords); typedef void (APIENTRYP RGLSYMGLNORMAL3XVOESPROC) (const GLfixed *coords); typedef void (APIENTRYP RGLSYMGLPASSTHROUGHXOESPROC) (GLfixed token); typedef void (APIENTRYP RGLSYMGLPIXELMAPXPROC) (GLenum map, GLint size, const GLfixed *values); typedef void (APIENTRYP RGLSYMGLPIXELSTOREXPROC) (GLenum pname, GLfixed param); typedef void (APIENTRYP RGLSYMGLPIXELTRANSFERXOESPROC) (GLenum pname, GLfixed param); typedef void (APIENTRYP RGLSYMGLPIXELZOOMXOESPROC) (GLfixed xfactor, GLfixed yfactor); typedef void (APIENTRYP RGLSYMGLPRIORITIZETEXTURESXOESPROC) (GLsizei n, const GLuint *textures, const GLfixed *priorities); typedef void (APIENTRYP RGLSYMGLRASTERPOS2XOESPROC) (GLfixed x, GLfixed y); typedef void (APIENTRYP RGLSYMGLRASTERPOS2XVOESPROC) (const GLfixed *coords); typedef void (APIENTRYP RGLSYMGLRASTERPOS3XOESPROC) (GLfixed x, GLfixed y, GLfixed z); typedef void (APIENTRYP RGLSYMGLRASTERPOS3XVOESPROC) (const GLfixed *coords); typedef void (APIENTRYP RGLSYMGLRASTERPOS4XOESPROC) (GLfixed x, GLfixed y, GLfixed z, GLfixed w); typedef void (APIENTRYP RGLSYMGLRASTERPOS4XVOESPROC) (const GLfixed *coords); typedef void (APIENTRYP RGLSYMGLRECTXOESPROC) (GLfixed x1, GLfixed y1, GLfixed x2, GLfixed y2); typedef void (APIENTRYP RGLSYMGLRECTXVOESPROC) (const GLfixed *v1, const GLfixed *v2); typedef void (APIENTRYP RGLSYMGLTEXCOORD1XOESPROC) (GLfixed s); typedef void (APIENTRYP RGLSYMGLTEXCOORD1XVOESPROC) (const GLfixed *coords); typedef void (APIENTRYP RGLSYMGLTEXCOORD2XOESPROC) (GLfixed s, GLfixed t); typedef void (APIENTRYP RGLSYMGLTEXCOORD2XVOESPROC) (const GLfixed *coords); typedef void (APIENTRYP RGLSYMGLTEXCOORD3XOESPROC) (GLfixed s, GLfixed t, GLfixed r); typedef void (APIENTRYP RGLSYMGLTEXCOORD3XVOESPROC) (const GLfixed *coords); typedef void (APIENTRYP RGLSYMGLTEXCOORD4XOESPROC) (GLfixed s, GLfixed t, GLfixed r, GLfixed q); typedef void (APIENTRYP RGLSYMGLTEXCOORD4XVOESPROC) (const GLfixed *coords); typedef void (APIENTRYP RGLSYMGLTEXGENXOESPROC) (GLenum coord, GLenum pname, GLfixed param); typedef void (APIENTRYP RGLSYMGLTEXGENXVOESPROC) (GLenum coord, GLenum pname, const GLfixed *params); typedef void (APIENTRYP RGLSYMGLVERTEX2XOESPROC) (GLfixed x); typedef void (APIENTRYP RGLSYMGLVERTEX2XVOESPROC) (const GLfixed *coords); typedef void (APIENTRYP RGLSYMGLVERTEX3XOESPROC) (GLfixed x, GLfixed y); typedef void (APIENTRYP RGLSYMGLVERTEX3XVOESPROC) (const GLfixed *coords); typedef void (APIENTRYP RGLSYMGLVERTEX4XOESPROC) (GLfixed x, GLfixed y, GLfixed z); typedef void (APIENTRYP RGLSYMGLVERTEX4XVOESPROC) (const GLfixed *coords); typedef GLbitfield (APIENTRYP RGLSYMGLQUERYMATRIXXOESPROC) (GLfixed *mantissa, GLint *exponent); typedef void (APIENTRYP RGLSYMGLCLEARDEPTHFOESPROC) (GLclampf depth); typedef void (APIENTRYP RGLSYMGLCLIPPLANEFOESPROC) (GLenum plane, const GLfloat *equation); typedef void (APIENTRYP RGLSYMGLDEPTHRANGEFOESPROC) (GLclampf n, GLclampf f); typedef void (APIENTRYP RGLSYMGLFRUSTUMFOESPROC) (GLfloat l, GLfloat r, GLfloat b, GLfloat t, GLfloat n, GLfloat f); typedef void (APIENTRYP RGLSYMGLGETCLIPPLANEFOESPROC) (GLenum plane, GLfloat *equation); typedef void (APIENTRYP RGLSYMGLORTHOFOESPROC) (GLfloat l, GLfloat r, GLfloat b, GLfloat t, GLfloat n, GLfloat f); typedef void (APIENTRYP RGLSYMGLIMAGETRANSFORMPARAMETERIHPPROC) (GLenum target, GLenum pname, GLint param); typedef void (APIENTRYP RGLSYMGLIMAGETRANSFORMPARAMETERFHPPROC) (GLenum target, GLenum pname, GLfloat param); typedef void (APIENTRYP RGLSYMGLIMAGETRANSFORMPARAMETERIVHPPROC) (GLenum target, GLenum pname, const GLint *params); typedef void (APIENTRYP RGLSYMGLIMAGETRANSFORMPARAMETERFVHPPROC) (GLenum target, GLenum pname, const GLfloat *params); typedef void (APIENTRYP RGLSYMGLGETIMAGETRANSFORMPARAMETERIVHPPROC) (GLenum target, GLenum pname, GLint *params); typedef void (APIENTRYP RGLSYMGLGETIMAGETRANSFORMPARAMETERFVHPPROC) (GLenum target, GLenum pname, GLfloat *params); #define glDrawRangeElements __rglgen_glDrawRangeElements #define glTexImage3D __rglgen_glTexImage3D #define glTexSubImage3D __rglgen_glTexSubImage3D #define glCopyTexSubImage3D __rglgen_glCopyTexSubImage3D #define glActiveTexture __rglgen_glActiveTexture #define glSampleCoverage __rglgen_glSampleCoverage #define glCompressedTexImage3D __rglgen_glCompressedTexImage3D #define glCompressedTexImage2D __rglgen_glCompressedTexImage2D #define glCompressedTexImage1D __rglgen_glCompressedTexImage1D #define glCompressedTexSubImage3D __rglgen_glCompressedTexSubImage3D #define glCompressedTexSubImage2D __rglgen_glCompressedTexSubImage2D #define glCompressedTexSubImage1D __rglgen_glCompressedTexSubImage1D #define glGetCompressedTexImage __rglgen_glGetCompressedTexImage #define glClientActiveTexture __rglgen_glClientActiveTexture #define glMultiTexCoord1d __rglgen_glMultiTexCoord1d #define glMultiTexCoord1dv __rglgen_glMultiTexCoord1dv #define glMultiTexCoord1f __rglgen_glMultiTexCoord1f #define glMultiTexCoord1fv __rglgen_glMultiTexCoord1fv #define glMultiTexCoord1i __rglgen_glMultiTexCoord1i #define glMultiTexCoord1iv __rglgen_glMultiTexCoord1iv #define glMultiTexCoord1s __rglgen_glMultiTexCoord1s #define glMultiTexCoord1sv __rglgen_glMultiTexCoord1sv #define glMultiTexCoord2d __rglgen_glMultiTexCoord2d #define glMultiTexCoord2dv __rglgen_glMultiTexCoord2dv #define glMultiTexCoord2f __rglgen_glMultiTexCoord2f #define glMultiTexCoord2fv __rglgen_glMultiTexCoord2fv #define glMultiTexCoord2i __rglgen_glMultiTexCoord2i #define glMultiTexCoord2iv __rglgen_glMultiTexCoord2iv #define glMultiTexCoord2s __rglgen_glMultiTexCoord2s #define glMultiTexCoord2sv __rglgen_glMultiTexCoord2sv #define glMultiTexCoord3d __rglgen_glMultiTexCoord3d #define glMultiTexCoord3dv __rglgen_glMultiTexCoord3dv #define glMultiTexCoord3f __rglgen_glMultiTexCoord3f #define glMultiTexCoord3fv __rglgen_glMultiTexCoord3fv #define glMultiTexCoord3i __rglgen_glMultiTexCoord3i #define glMultiTexCoord3iv __rglgen_glMultiTexCoord3iv #define glMultiTexCoord3s __rglgen_glMultiTexCoord3s #define glMultiTexCoord3sv __rglgen_glMultiTexCoord3sv #define glMultiTexCoord4d __rglgen_glMultiTexCoord4d #define glMultiTexCoord4dv __rglgen_glMultiTexCoord4dv #define glMultiTexCoord4f __rglgen_glMultiTexCoord4f #define glMultiTexCoord4fv __rglgen_glMultiTexCoord4fv #define glMultiTexCoord4i __rglgen_glMultiTexCoord4i #define glMultiTexCoord4iv __rglgen_glMultiTexCoord4iv #define glMultiTexCoord4s __rglgen_glMultiTexCoord4s #define glMultiTexCoord4sv __rglgen_glMultiTexCoord4sv #define glLoadTransposeMatrixf __rglgen_glLoadTransposeMatrixf #define glLoadTransposeMatrixd __rglgen_glLoadTransposeMatrixd #define glMultTransposeMatrixf __rglgen_glMultTransposeMatrixf #define glMultTransposeMatrixd __rglgen_glMultTransposeMatrixd #define glBlendFuncSeparate __rglgen_glBlendFuncSeparate #define glMultiDrawArrays __rglgen_glMultiDrawArrays #define glMultiDrawElements __rglgen_glMultiDrawElements #define glPointParameterf __rglgen_glPointParameterf #define glPointParameterfv __rglgen_glPointParameterfv #define glPointParameteri __rglgen_glPointParameteri #define glPointParameteriv __rglgen_glPointParameteriv #define glFogCoordf __rglgen_glFogCoordf #define glFogCoordfv __rglgen_glFogCoordfv #define glFogCoordd __rglgen_glFogCoordd #define glFogCoorddv __rglgen_glFogCoorddv #define glFogCoordPointer __rglgen_glFogCoordPointer #define glSecondaryColor3b __rglgen_glSecondaryColor3b #define glSecondaryColor3bv __rglgen_glSecondaryColor3bv #define glSecondaryColor3d __rglgen_glSecondaryColor3d #define glSecondaryColor3dv __rglgen_glSecondaryColor3dv #define glSecondaryColor3f __rglgen_glSecondaryColor3f #define glSecondaryColor3fv __rglgen_glSecondaryColor3fv #define glSecondaryColor3i __rglgen_glSecondaryColor3i #define glSecondaryColor3iv __rglgen_glSecondaryColor3iv #define glSecondaryColor3s __rglgen_glSecondaryColor3s #define glSecondaryColor3sv __rglgen_glSecondaryColor3sv #define glSecondaryColor3ub __rglgen_glSecondaryColor3ub #define glSecondaryColor3ubv __rglgen_glSecondaryColor3ubv #define glSecondaryColor3ui __rglgen_glSecondaryColor3ui #define glSecondaryColor3uiv __rglgen_glSecondaryColor3uiv #define glSecondaryColor3us __rglgen_glSecondaryColor3us #define glSecondaryColor3usv __rglgen_glSecondaryColor3usv #define glSecondaryColorPointer __rglgen_glSecondaryColorPointer #define glWindowPos2d __rglgen_glWindowPos2d #define glWindowPos2dv __rglgen_glWindowPos2dv #define glWindowPos2f __rglgen_glWindowPos2f #define glWindowPos2fv __rglgen_glWindowPos2fv #define glWindowPos2i __rglgen_glWindowPos2i #define glWindowPos2iv __rglgen_glWindowPos2iv #define glWindowPos2s __rglgen_glWindowPos2s #define glWindowPos2sv __rglgen_glWindowPos2sv #define glWindowPos3d __rglgen_glWindowPos3d #define glWindowPos3dv __rglgen_glWindowPos3dv #define glWindowPos3f __rglgen_glWindowPos3f #define glWindowPos3fv __rglgen_glWindowPos3fv #define glWindowPos3i __rglgen_glWindowPos3i #define glWindowPos3iv __rglgen_glWindowPos3iv #define glWindowPos3s __rglgen_glWindowPos3s #define glWindowPos3sv __rglgen_glWindowPos3sv #define glBlendColor __rglgen_glBlendColor #define glBlendEquation __rglgen_glBlendEquation #define glGenQueries __rglgen_glGenQueries #define glDeleteQueries __rglgen_glDeleteQueries #define glIsQuery __rglgen_glIsQuery #define glBeginQuery __rglgen_glBeginQuery #define glEndQuery __rglgen_glEndQuery #define glGetQueryiv __rglgen_glGetQueryiv #define glGetQueryObjectiv __rglgen_glGetQueryObjectiv #define glGetQueryObjectuiv __rglgen_glGetQueryObjectuiv #define glBindBuffer __rglgen_glBindBuffer #define glDeleteBuffers __rglgen_glDeleteBuffers #define glGenBuffers __rglgen_glGenBuffers #define glIsBuffer __rglgen_glIsBuffer #define glBufferData __rglgen_glBufferData #define glBufferSubData __rglgen_glBufferSubData #define glGetBufferSubData __rglgen_glGetBufferSubData #define glMapBuffer __rglgen_glMapBuffer #define glUnmapBuffer __rglgen_glUnmapBuffer #define glGetBufferParameteriv __rglgen_glGetBufferParameteriv #define glGetBufferPointerv __rglgen_glGetBufferPointerv #define glBlendEquationSeparate __rglgen_glBlendEquationSeparate #define glDrawBuffers __rglgen_glDrawBuffers #define glStencilOpSeparate __rglgen_glStencilOpSeparate #define glStencilFuncSeparate __rglgen_glStencilFuncSeparate #define glStencilMaskSeparate __rglgen_glStencilMaskSeparate #define glAttachShader __rglgen_glAttachShader #define glBindAttribLocation __rglgen_glBindAttribLocation #define glCompileShader __rglgen_glCompileShader #define glCreateProgram __rglgen_glCreateProgram #define glCreateShader __rglgen_glCreateShader #define glDeleteProgram __rglgen_glDeleteProgram #define glDeleteShader __rglgen_glDeleteShader #define glDetachShader __rglgen_glDetachShader #define glDisableVertexAttribArray __rglgen_glDisableVertexAttribArray #define glEnableVertexAttribArray __rglgen_glEnableVertexAttribArray #define glGetActiveAttrib __rglgen_glGetActiveAttrib #define glGetActiveUniform __rglgen_glGetActiveUniform #define glGetAttachedShaders __rglgen_glGetAttachedShaders #define glGetAttribLocation __rglgen_glGetAttribLocation #define glGetProgramiv __rglgen_glGetProgramiv #define glGetProgramInfoLog __rglgen_glGetProgramInfoLog #define glGetShaderiv __rglgen_glGetShaderiv #define glGetShaderInfoLog __rglgen_glGetShaderInfoLog #define glGetShaderSource __rglgen_glGetShaderSource #define glGetUniformLocation __rglgen_glGetUniformLocation #define glGetUniformfv __rglgen_glGetUniformfv #define glGetUniformiv __rglgen_glGetUniformiv #define glGetVertexAttribdv __rglgen_glGetVertexAttribdv #define glGetVertexAttribfv __rglgen_glGetVertexAttribfv #define glGetVertexAttribiv __rglgen_glGetVertexAttribiv #define glGetVertexAttribPointerv __rglgen_glGetVertexAttribPointerv #define glIsProgram __rglgen_glIsProgram #define glIsShader __rglgen_glIsShader #define glLinkProgram __rglgen_glLinkProgram #define glShaderSource __rglgen_glShaderSource #define glUseProgram __rglgen_glUseProgram #define glUniform1f __rglgen_glUniform1f #define glUniform2f __rglgen_glUniform2f #define glUniform3f __rglgen_glUniform3f #define glUniform4f __rglgen_glUniform4f #define glUniform1i __rglgen_glUniform1i #define glUniform2i __rglgen_glUniform2i #define glUniform3i __rglgen_glUniform3i #define glUniform4i __rglgen_glUniform4i #define glUniform1fv __rglgen_glUniform1fv #define glUniform2fv __rglgen_glUniform2fv #define glUniform3fv __rglgen_glUniform3fv #define glUniform4fv __rglgen_glUniform4fv #define glUniform1iv __rglgen_glUniform1iv #define glUniform2iv __rglgen_glUniform2iv #define glUniform3iv __rglgen_glUniform3iv #define glUniform4iv __rglgen_glUniform4iv #define glUniformMatrix2fv __rglgen_glUniformMatrix2fv #define glUniformMatrix3fv __rglgen_glUniformMatrix3fv #define glUniformMatrix4fv __rglgen_glUniformMatrix4fv #define glValidateProgram __rglgen_glValidateProgram #define glVertexAttrib1d __rglgen_glVertexAttrib1d #define glVertexAttrib1dv __rglgen_glVertexAttrib1dv #define glVertexAttrib1f __rglgen_glVertexAttrib1f #define glVertexAttrib1fv __rglgen_glVertexAttrib1fv #define glVertexAttrib1s __rglgen_glVertexAttrib1s #define glVertexAttrib1sv __rglgen_glVertexAttrib1sv #define glVertexAttrib2d __rglgen_glVertexAttrib2d #define glVertexAttrib2dv __rglgen_glVertexAttrib2dv #define glVertexAttrib2f __rglgen_glVertexAttrib2f #define glVertexAttrib2fv __rglgen_glVertexAttrib2fv #define glVertexAttrib2s __rglgen_glVertexAttrib2s #define glVertexAttrib2sv __rglgen_glVertexAttrib2sv #define glVertexAttrib3d __rglgen_glVertexAttrib3d #define glVertexAttrib3dv __rglgen_glVertexAttrib3dv #define glVertexAttrib3f __rglgen_glVertexAttrib3f #define glVertexAttrib3fv __rglgen_glVertexAttrib3fv #define glVertexAttrib3s __rglgen_glVertexAttrib3s #define glVertexAttrib3sv __rglgen_glVertexAttrib3sv #define glVertexAttrib4Nbv __rglgen_glVertexAttrib4Nbv #define glVertexAttrib4Niv __rglgen_glVertexAttrib4Niv #define glVertexAttrib4Nsv __rglgen_glVertexAttrib4Nsv #define glVertexAttrib4Nub __rglgen_glVertexAttrib4Nub #define glVertexAttrib4Nubv __rglgen_glVertexAttrib4Nubv #define glVertexAttrib4Nuiv __rglgen_glVertexAttrib4Nuiv #define glVertexAttrib4Nusv __rglgen_glVertexAttrib4Nusv #define glVertexAttrib4bv __rglgen_glVertexAttrib4bv #define glVertexAttrib4d __rglgen_glVertexAttrib4d #define glVertexAttrib4dv __rglgen_glVertexAttrib4dv #define glVertexAttrib4f __rglgen_glVertexAttrib4f #define glVertexAttrib4fv __rglgen_glVertexAttrib4fv #define glVertexAttrib4iv __rglgen_glVertexAttrib4iv #define glVertexAttrib4s __rglgen_glVertexAttrib4s #define glVertexAttrib4sv __rglgen_glVertexAttrib4sv #define glVertexAttrib4ubv __rglgen_glVertexAttrib4ubv #define glVertexAttrib4uiv __rglgen_glVertexAttrib4uiv #define glVertexAttrib4usv __rglgen_glVertexAttrib4usv #define glVertexAttribPointer __rglgen_glVertexAttribPointer #define glUniformMatrix2x3fv __rglgen_glUniformMatrix2x3fv #define glUniformMatrix3x2fv __rglgen_glUniformMatrix3x2fv #define glUniformMatrix2x4fv __rglgen_glUniformMatrix2x4fv #define glUniformMatrix4x2fv __rglgen_glUniformMatrix4x2fv #define glUniformMatrix3x4fv __rglgen_glUniformMatrix3x4fv #define glUniformMatrix4x3fv __rglgen_glUniformMatrix4x3fv #define glColorMaski __rglgen_glColorMaski #define glGetBooleani_v __rglgen_glGetBooleani_v #define glGetIntegeri_v __rglgen_glGetIntegeri_v #define glEnablei __rglgen_glEnablei #define glDisablei __rglgen_glDisablei #define glIsEnabledi __rglgen_glIsEnabledi #define glBeginTransformFeedback __rglgen_glBeginTransformFeedback #define glEndTransformFeedback __rglgen_glEndTransformFeedback #define glBindBufferRange __rglgen_glBindBufferRange #define glBindBufferBase __rglgen_glBindBufferBase #define glTransformFeedbackVaryings __rglgen_glTransformFeedbackVaryings #define glGetTransformFeedbackVarying __rglgen_glGetTransformFeedbackVarying #define glClampColor __rglgen_glClampColor #define glBeginConditionalRender __rglgen_glBeginConditionalRender #define glEndConditionalRender __rglgen_glEndConditionalRender #define glVertexAttribIPointer __rglgen_glVertexAttribIPointer #define glGetVertexAttribIiv __rglgen_glGetVertexAttribIiv #define glGetVertexAttribIuiv __rglgen_glGetVertexAttribIuiv #define glVertexAttribI1i __rglgen_glVertexAttribI1i #define glVertexAttribI2i __rglgen_glVertexAttribI2i #define glVertexAttribI3i __rglgen_glVertexAttribI3i #define glVertexAttribI4i __rglgen_glVertexAttribI4i #define glVertexAttribI1ui __rglgen_glVertexAttribI1ui #define glVertexAttribI2ui __rglgen_glVertexAttribI2ui #define glVertexAttribI3ui __rglgen_glVertexAttribI3ui #define glVertexAttribI4ui __rglgen_glVertexAttribI4ui #define glVertexAttribI1iv __rglgen_glVertexAttribI1iv #define glVertexAttribI2iv __rglgen_glVertexAttribI2iv #define glVertexAttribI3iv __rglgen_glVertexAttribI3iv #define glVertexAttribI4iv __rglgen_glVertexAttribI4iv #define glVertexAttribI1uiv __rglgen_glVertexAttribI1uiv #define glVertexAttribI2uiv __rglgen_glVertexAttribI2uiv #define glVertexAttribI3uiv __rglgen_glVertexAttribI3uiv #define glVertexAttribI4uiv __rglgen_glVertexAttribI4uiv #define glVertexAttribI4bv __rglgen_glVertexAttribI4bv #define glVertexAttribI4sv __rglgen_glVertexAttribI4sv #define glVertexAttribI4ubv __rglgen_glVertexAttribI4ubv #define glVertexAttribI4usv __rglgen_glVertexAttribI4usv #define glGetUniformuiv __rglgen_glGetUniformuiv #define glBindFragDataLocation __rglgen_glBindFragDataLocation #define glGetFragDataLocation __rglgen_glGetFragDataLocation #define glUniform1ui __rglgen_glUniform1ui #define glUniform2ui __rglgen_glUniform2ui #define glUniform3ui __rglgen_glUniform3ui #define glUniform4ui __rglgen_glUniform4ui #define glUniform1uiv __rglgen_glUniform1uiv #define glUniform2uiv __rglgen_glUniform2uiv #define glUniform3uiv __rglgen_glUniform3uiv #define glUniform4uiv __rglgen_glUniform4uiv #define glTexParameterIiv __rglgen_glTexParameterIiv #define glTexParameterIuiv __rglgen_glTexParameterIuiv #define glGetTexParameterIiv __rglgen_glGetTexParameterIiv #define glGetTexParameterIuiv __rglgen_glGetTexParameterIuiv #define glClearBufferiv __rglgen_glClearBufferiv #define glClearBufferuiv __rglgen_glClearBufferuiv #define glClearBufferfv __rglgen_glClearBufferfv #define glClearBufferfi __rglgen_glClearBufferfi #define glGetStringi __rglgen_glGetStringi #define glIsRenderbuffer __rglgen_glIsRenderbuffer #define glBindRenderbuffer __rglgen_glBindRenderbuffer #define glDeleteRenderbuffers __rglgen_glDeleteRenderbuffers #define glGenRenderbuffers __rglgen_glGenRenderbuffers #define glRenderbufferStorage __rglgen_glRenderbufferStorage #define glGetRenderbufferParameteriv __rglgen_glGetRenderbufferParameteriv #define glIsFramebuffer __rglgen_glIsFramebuffer #define glBindFramebuffer __rglgen_glBindFramebuffer #define glDeleteFramebuffers __rglgen_glDeleteFramebuffers #define glGenFramebuffers __rglgen_glGenFramebuffers #define glCheckFramebufferStatus __rglgen_glCheckFramebufferStatus #define glFramebufferTexture1D __rglgen_glFramebufferTexture1D #define glFramebufferTexture2D __rglgen_glFramebufferTexture2D #define glFramebufferTexture3D __rglgen_glFramebufferTexture3D #define glFramebufferRenderbuffer __rglgen_glFramebufferRenderbuffer #define glGetFramebufferAttachmentParameteriv __rglgen_glGetFramebufferAttachmentParameteriv #define glGenerateMipmap __rglgen_glGenerateMipmap #define glBlitFramebuffer __rglgen_glBlitFramebuffer #define glRenderbufferStorageMultisample __rglgen_glRenderbufferStorageMultisample #define glFramebufferTextureLayer __rglgen_glFramebufferTextureLayer #define glMapBufferRange __rglgen_glMapBufferRange #define glFlushMappedBufferRange __rglgen_glFlushMappedBufferRange #define glBindVertexArray __rglgen_glBindVertexArray #define glDeleteVertexArrays __rglgen_glDeleteVertexArrays #define glGenVertexArrays __rglgen_glGenVertexArrays #define glIsVertexArray __rglgen_glIsVertexArray #define glDrawArraysInstanced __rglgen_glDrawArraysInstanced #define glDrawElementsInstanced __rglgen_glDrawElementsInstanced #define glTexBuffer __rglgen_glTexBuffer #define glPrimitiveRestartIndex __rglgen_glPrimitiveRestartIndex #define glCopyBufferSubData __rglgen_glCopyBufferSubData #define glGetUniformIndices __rglgen_glGetUniformIndices #define glGetActiveUniformsiv __rglgen_glGetActiveUniformsiv #define glGetActiveUniformName __rglgen_glGetActiveUniformName #define glGetUniformBlockIndex __rglgen_glGetUniformBlockIndex #define glGetActiveUniformBlockiv __rglgen_glGetActiveUniformBlockiv #define glGetActiveUniformBlockName __rglgen_glGetActiveUniformBlockName #define glUniformBlockBinding __rglgen_glUniformBlockBinding #define glDrawElementsBaseVertex __rglgen_glDrawElementsBaseVertex #define glDrawRangeElementsBaseVertex __rglgen_glDrawRangeElementsBaseVertex #define glDrawElementsInstancedBaseVertex __rglgen_glDrawElementsInstancedBaseVertex #define glMultiDrawElementsBaseVertex __rglgen_glMultiDrawElementsBaseVertex #define glProvokingVertex __rglgen_glProvokingVertex #define glFenceSync __rglgen_glFenceSync #define glIsSync __rglgen_glIsSync #define glDeleteSync __rglgen_glDeleteSync #define glClientWaitSync __rglgen_glClientWaitSync #define glWaitSync __rglgen_glWaitSync #define glGetInteger64v __rglgen_glGetInteger64v #define glGetSynciv __rglgen_glGetSynciv #define glGetInteger64i_v __rglgen_glGetInteger64i_v #define glGetBufferParameteri64v __rglgen_glGetBufferParameteri64v #define glFramebufferTexture __rglgen_glFramebufferTexture #define glTexImage2DMultisample __rglgen_glTexImage2DMultisample #define glTexImage3DMultisample __rglgen_glTexImage3DMultisample #define glGetMultisamplefv __rglgen_glGetMultisamplefv #define glSampleMaski __rglgen_glSampleMaski #define glBindFragDataLocationIndexed __rglgen_glBindFragDataLocationIndexed #define glGetFragDataIndex __rglgen_glGetFragDataIndex #define glGenSamplers __rglgen_glGenSamplers #define glDeleteSamplers __rglgen_glDeleteSamplers #define glIsSampler __rglgen_glIsSampler #define glBindSampler __rglgen_glBindSampler #define glSamplerParameteri __rglgen_glSamplerParameteri #define glSamplerParameteriv __rglgen_glSamplerParameteriv #define glSamplerParameterf __rglgen_glSamplerParameterf #define glSamplerParameterfv __rglgen_glSamplerParameterfv #define glSamplerParameterIiv __rglgen_glSamplerParameterIiv #define glSamplerParameterIuiv __rglgen_glSamplerParameterIuiv #define glGetSamplerParameteriv __rglgen_glGetSamplerParameteriv #define glGetSamplerParameterIiv __rglgen_glGetSamplerParameterIiv #define glGetSamplerParameterfv __rglgen_glGetSamplerParameterfv #define glGetSamplerParameterIuiv __rglgen_glGetSamplerParameterIuiv #define glQueryCounter __rglgen_glQueryCounter #define glGetQueryObjecti64v __rglgen_glGetQueryObjecti64v #define glGetQueryObjectui64v __rglgen_glGetQueryObjectui64v #define glVertexAttribDivisor __rglgen_glVertexAttribDivisor #define glVertexAttribP1ui __rglgen_glVertexAttribP1ui #define glVertexAttribP1uiv __rglgen_glVertexAttribP1uiv #define glVertexAttribP2ui __rglgen_glVertexAttribP2ui #define glVertexAttribP2uiv __rglgen_glVertexAttribP2uiv #define glVertexAttribP3ui __rglgen_glVertexAttribP3ui #define glVertexAttribP3uiv __rglgen_glVertexAttribP3uiv #define glVertexAttribP4ui __rglgen_glVertexAttribP4ui #define glVertexAttribP4uiv __rglgen_glVertexAttribP4uiv #define glVertexP2ui __rglgen_glVertexP2ui #define glVertexP2uiv __rglgen_glVertexP2uiv #define glVertexP3ui __rglgen_glVertexP3ui #define glVertexP3uiv __rglgen_glVertexP3uiv #define glVertexP4ui __rglgen_glVertexP4ui #define glVertexP4uiv __rglgen_glVertexP4uiv #define glTexCoordP1ui __rglgen_glTexCoordP1ui #define glTexCoordP1uiv __rglgen_glTexCoordP1uiv #define glTexCoordP2ui __rglgen_glTexCoordP2ui #define glTexCoordP2uiv __rglgen_glTexCoordP2uiv #define glTexCoordP3ui __rglgen_glTexCoordP3ui #define glTexCoordP3uiv __rglgen_glTexCoordP3uiv #define glTexCoordP4ui __rglgen_glTexCoordP4ui #define glTexCoordP4uiv __rglgen_glTexCoordP4uiv #define glMultiTexCoordP1ui __rglgen_glMultiTexCoordP1ui #define glMultiTexCoordP1uiv __rglgen_glMultiTexCoordP1uiv #define glMultiTexCoordP2ui __rglgen_glMultiTexCoordP2ui #define glMultiTexCoordP2uiv __rglgen_glMultiTexCoordP2uiv #define glMultiTexCoordP3ui __rglgen_glMultiTexCoordP3ui #define glMultiTexCoordP3uiv __rglgen_glMultiTexCoordP3uiv #define glMultiTexCoordP4ui __rglgen_glMultiTexCoordP4ui #define glMultiTexCoordP4uiv __rglgen_glMultiTexCoordP4uiv #define glNormalP3ui __rglgen_glNormalP3ui #define glNormalP3uiv __rglgen_glNormalP3uiv #define glColorP3ui __rglgen_glColorP3ui #define glColorP3uiv __rglgen_glColorP3uiv #define glColorP4ui __rglgen_glColorP4ui #define glColorP4uiv __rglgen_glColorP4uiv #define glSecondaryColorP3ui __rglgen_glSecondaryColorP3ui #define glSecondaryColorP3uiv __rglgen_glSecondaryColorP3uiv #define glMinSampleShading __rglgen_glMinSampleShading #define glBlendEquationi __rglgen_glBlendEquationi #define glBlendEquationSeparatei __rglgen_glBlendEquationSeparatei #define glBlendFunci __rglgen_glBlendFunci #define glBlendFuncSeparatei __rglgen_glBlendFuncSeparatei #define glDrawArraysIndirect __rglgen_glDrawArraysIndirect #define glDrawElementsIndirect __rglgen_glDrawElementsIndirect #define glUniform1d __rglgen_glUniform1d #define glUniform2d __rglgen_glUniform2d #define glUniform3d __rglgen_glUniform3d #define glUniform4d __rglgen_glUniform4d #define glUniform1dv __rglgen_glUniform1dv #define glUniform2dv __rglgen_glUniform2dv #define glUniform3dv __rglgen_glUniform3dv #define glUniform4dv __rglgen_glUniform4dv #define glUniformMatrix2dv __rglgen_glUniformMatrix2dv #define glUniformMatrix3dv __rglgen_glUniformMatrix3dv #define glUniformMatrix4dv __rglgen_glUniformMatrix4dv #define glUniformMatrix2x3dv __rglgen_glUniformMatrix2x3dv #define glUniformMatrix2x4dv __rglgen_glUniformMatrix2x4dv #define glUniformMatrix3x2dv __rglgen_glUniformMatrix3x2dv #define glUniformMatrix3x4dv __rglgen_glUniformMatrix3x4dv #define glUniformMatrix4x2dv __rglgen_glUniformMatrix4x2dv #define glUniformMatrix4x3dv __rglgen_glUniformMatrix4x3dv #define glGetUniformdv __rglgen_glGetUniformdv #define glGetSubroutineUniformLocation __rglgen_glGetSubroutineUniformLocation #define glGetSubroutineIndex __rglgen_glGetSubroutineIndex #define glGetActiveSubroutineUniformiv __rglgen_glGetActiveSubroutineUniformiv #define glGetActiveSubroutineUniformName __rglgen_glGetActiveSubroutineUniformName #define glGetActiveSubroutineName __rglgen_glGetActiveSubroutineName #define glUniformSubroutinesuiv __rglgen_glUniformSubroutinesuiv #define glGetUniformSubroutineuiv __rglgen_glGetUniformSubroutineuiv #define glGetProgramStageiv __rglgen_glGetProgramStageiv #define glPatchParameteri __rglgen_glPatchParameteri #define glPatchParameterfv __rglgen_glPatchParameterfv #define glBindTransformFeedback __rglgen_glBindTransformFeedback #define glDeleteTransformFeedbacks __rglgen_glDeleteTransformFeedbacks #define glGenTransformFeedbacks __rglgen_glGenTransformFeedbacks #define glIsTransformFeedback __rglgen_glIsTransformFeedback #define glPauseTransformFeedback __rglgen_glPauseTransformFeedback #define glResumeTransformFeedback __rglgen_glResumeTransformFeedback #define glDrawTransformFeedback __rglgen_glDrawTransformFeedback #define glDrawTransformFeedbackStream __rglgen_glDrawTransformFeedbackStream #define glBeginQueryIndexed __rglgen_glBeginQueryIndexed #define glEndQueryIndexed __rglgen_glEndQueryIndexed #define glGetQueryIndexediv __rglgen_glGetQueryIndexediv #define glReleaseShaderCompiler __rglgen_glReleaseShaderCompiler #define glShaderBinary __rglgen_glShaderBinary #define glGetShaderPrecisionFormat __rglgen_glGetShaderPrecisionFormat #define glDepthRangef __rglgen_glDepthRangef #define glClearDepthf __rglgen_glClearDepthf #define glGetProgramBinary __rglgen_glGetProgramBinary #define glProgramBinary __rglgen_glProgramBinary #define glProgramParameteri __rglgen_glProgramParameteri #define glUseProgramStages __rglgen_glUseProgramStages #define glActiveShaderProgram __rglgen_glActiveShaderProgram #define glCreateShaderProgramv __rglgen_glCreateShaderProgramv #define glBindProgramPipeline __rglgen_glBindProgramPipeline #define glDeleteProgramPipelines __rglgen_glDeleteProgramPipelines #define glGenProgramPipelines __rglgen_glGenProgramPipelines #define glIsProgramPipeline __rglgen_glIsProgramPipeline #define glGetProgramPipelineiv __rglgen_glGetProgramPipelineiv #define glProgramUniform1i __rglgen_glProgramUniform1i #define glProgramUniform1iv __rglgen_glProgramUniform1iv #define glProgramUniform1f __rglgen_glProgramUniform1f #define glProgramUniform1fv __rglgen_glProgramUniform1fv #define glProgramUniform1d __rglgen_glProgramUniform1d #define glProgramUniform1dv __rglgen_glProgramUniform1dv #define glProgramUniform1ui __rglgen_glProgramUniform1ui #define glProgramUniform1uiv __rglgen_glProgramUniform1uiv #define glProgramUniform2i __rglgen_glProgramUniform2i #define glProgramUniform2iv __rglgen_glProgramUniform2iv #define glProgramUniform2f __rglgen_glProgramUniform2f #define glProgramUniform2fv __rglgen_glProgramUniform2fv #define glProgramUniform2d __rglgen_glProgramUniform2d #define glProgramUniform2dv __rglgen_glProgramUniform2dv #define glProgramUniform2ui __rglgen_glProgramUniform2ui #define glProgramUniform2uiv __rglgen_glProgramUniform2uiv #define glProgramUniform3i __rglgen_glProgramUniform3i #define glProgramUniform3iv __rglgen_glProgramUniform3iv #define glProgramUniform3f __rglgen_glProgramUniform3f #define glProgramUniform3fv __rglgen_glProgramUniform3fv #define glProgramUniform3d __rglgen_glProgramUniform3d #define glProgramUniform3dv __rglgen_glProgramUniform3dv #define glProgramUniform3ui __rglgen_glProgramUniform3ui #define glProgramUniform3uiv __rglgen_glProgramUniform3uiv #define glProgramUniform4i __rglgen_glProgramUniform4i #define glProgramUniform4iv __rglgen_glProgramUniform4iv #define glProgramUniform4f __rglgen_glProgramUniform4f #define glProgramUniform4fv __rglgen_glProgramUniform4fv #define glProgramUniform4d __rglgen_glProgramUniform4d #define glProgramUniform4dv __rglgen_glProgramUniform4dv #define glProgramUniform4ui __rglgen_glProgramUniform4ui #define glProgramUniform4uiv __rglgen_glProgramUniform4uiv #define glProgramUniformMatrix2fv __rglgen_glProgramUniformMatrix2fv #define glProgramUniformMatrix3fv __rglgen_glProgramUniformMatrix3fv #define glProgramUniformMatrix4fv __rglgen_glProgramUniformMatrix4fv #define glProgramUniformMatrix2dv __rglgen_glProgramUniformMatrix2dv #define glProgramUniformMatrix3dv __rglgen_glProgramUniformMatrix3dv #define glProgramUniformMatrix4dv __rglgen_glProgramUniformMatrix4dv #define glProgramUniformMatrix2x3fv __rglgen_glProgramUniformMatrix2x3fv #define glProgramUniformMatrix3x2fv __rglgen_glProgramUniformMatrix3x2fv #define glProgramUniformMatrix2x4fv __rglgen_glProgramUniformMatrix2x4fv #define glProgramUniformMatrix4x2fv __rglgen_glProgramUniformMatrix4x2fv #define glProgramUniformMatrix3x4fv __rglgen_glProgramUniformMatrix3x4fv #define glProgramUniformMatrix4x3fv __rglgen_glProgramUniformMatrix4x3fv #define glProgramUniformMatrix2x3dv __rglgen_glProgramUniformMatrix2x3dv #define glProgramUniformMatrix3x2dv __rglgen_glProgramUniformMatrix3x2dv #define glProgramUniformMatrix2x4dv __rglgen_glProgramUniformMatrix2x4dv #define glProgramUniformMatrix4x2dv __rglgen_glProgramUniformMatrix4x2dv #define glProgramUniformMatrix3x4dv __rglgen_glProgramUniformMatrix3x4dv #define glProgramUniformMatrix4x3dv __rglgen_glProgramUniformMatrix4x3dv #define glValidateProgramPipeline __rglgen_glValidateProgramPipeline #define glGetProgramPipelineInfoLog __rglgen_glGetProgramPipelineInfoLog #define glVertexAttribL1d __rglgen_glVertexAttribL1d #define glVertexAttribL2d __rglgen_glVertexAttribL2d #define glVertexAttribL3d __rglgen_glVertexAttribL3d #define glVertexAttribL4d __rglgen_glVertexAttribL4d #define glVertexAttribL1dv __rglgen_glVertexAttribL1dv #define glVertexAttribL2dv __rglgen_glVertexAttribL2dv #define glVertexAttribL3dv __rglgen_glVertexAttribL3dv #define glVertexAttribL4dv __rglgen_glVertexAttribL4dv #define glVertexAttribLPointer __rglgen_glVertexAttribLPointer #define glGetVertexAttribLdv __rglgen_glGetVertexAttribLdv #define glViewportArrayv __rglgen_glViewportArrayv #define glViewportIndexedf __rglgen_glViewportIndexedf #define glViewportIndexedfv __rglgen_glViewportIndexedfv #define glScissorArrayv __rglgen_glScissorArrayv #define glScissorIndexed __rglgen_glScissorIndexed #define glScissorIndexedv __rglgen_glScissorIndexedv #define glDepthRangeArrayv __rglgen_glDepthRangeArrayv #define glDepthRangeIndexed __rglgen_glDepthRangeIndexed #define glGetFloati_v __rglgen_glGetFloati_v #define glGetDoublei_v __rglgen_glGetDoublei_v #define glDrawArraysInstancedBaseInstance __rglgen_glDrawArraysInstancedBaseInstance #define glDrawElementsInstancedBaseInstance __rglgen_glDrawElementsInstancedBaseInstance #define glDrawElementsInstancedBaseVertexBaseInstance __rglgen_glDrawElementsInstancedBaseVertexBaseInstance #define glGetInternalformativ __rglgen_glGetInternalformativ #define glGetActiveAtomicCounterBufferiv __rglgen_glGetActiveAtomicCounterBufferiv #define glBindImageTexture __rglgen_glBindImageTexture #define glMemoryBarrier __rglgen_glMemoryBarrier #define glTexStorage1D __rglgen_glTexStorage1D #define glTexStorage2D __rglgen_glTexStorage2D #define glTexStorage3D __rglgen_glTexStorage3D #define glDrawTransformFeedbackInstanced __rglgen_glDrawTransformFeedbackInstanced #define glDrawTransformFeedbackStreamInstanced __rglgen_glDrawTransformFeedbackStreamInstanced #define glClearBufferData __rglgen_glClearBufferData #define glClearBufferSubData __rglgen_glClearBufferSubData #define glDispatchCompute __rglgen_glDispatchCompute #define glDispatchComputeIndirect __rglgen_glDispatchComputeIndirect #define glCopyImageSubData __rglgen_glCopyImageSubData #define glFramebufferParameteri __rglgen_glFramebufferParameteri #define glGetFramebufferParameteriv __rglgen_glGetFramebufferParameteriv #define glGetInternalformati64v __rglgen_glGetInternalformati64v #define glInvalidateTexSubImage __rglgen_glInvalidateTexSubImage #define glInvalidateTexImage __rglgen_glInvalidateTexImage #define glInvalidateBufferSubData __rglgen_glInvalidateBufferSubData #define glInvalidateBufferData __rglgen_glInvalidateBufferData #define glInvalidateFramebuffer __rglgen_glInvalidateFramebuffer #define glInvalidateSubFramebuffer __rglgen_glInvalidateSubFramebuffer #define glMultiDrawArraysIndirect __rglgen_glMultiDrawArraysIndirect #define glMultiDrawElementsIndirect __rglgen_glMultiDrawElementsIndirect #define glGetProgramInterfaceiv __rglgen_glGetProgramInterfaceiv #define glGetProgramResourceIndex __rglgen_glGetProgramResourceIndex #define glGetProgramResourceName __rglgen_glGetProgramResourceName #define glGetProgramResourceiv __rglgen_glGetProgramResourceiv #define glGetProgramResourceLocation __rglgen_glGetProgramResourceLocation #define glGetProgramResourceLocationIndex __rglgen_glGetProgramResourceLocationIndex #define glShaderStorageBlockBinding __rglgen_glShaderStorageBlockBinding #define glTexBufferRange __rglgen_glTexBufferRange #define glTexStorage2DMultisample __rglgen_glTexStorage2DMultisample #define glTexStorage3DMultisample __rglgen_glTexStorage3DMultisample #define glTextureView __rglgen_glTextureView #define glBindVertexBuffer __rglgen_glBindVertexBuffer #define glVertexAttribFormat __rglgen_glVertexAttribFormat #define glVertexAttribIFormat __rglgen_glVertexAttribIFormat #define glVertexAttribLFormat __rglgen_glVertexAttribLFormat #define glVertexAttribBinding __rglgen_glVertexAttribBinding #define glVertexBindingDivisor __rglgen_glVertexBindingDivisor #define glDebugMessageControl __rglgen_glDebugMessageControl #define glDebugMessageInsert __rglgen_glDebugMessageInsert #define glDebugMessageCallback __rglgen_glDebugMessageCallback #define glGetDebugMessageLog __rglgen_glGetDebugMessageLog #define glPushDebugGroup __rglgen_glPushDebugGroup #define glPopDebugGroup __rglgen_glPopDebugGroup #define glObjectLabel __rglgen_glObjectLabel #define glGetObjectLabel __rglgen_glGetObjectLabel #define glObjectPtrLabel __rglgen_glObjectPtrLabel #define glGetObjectPtrLabel __rglgen_glGetObjectPtrLabel #define glBufferStorage __rglgen_glBufferStorage #define glClearTexImage __rglgen_glClearTexImage #define glClearTexSubImage __rglgen_glClearTexSubImage #define glBindBuffersBase __rglgen_glBindBuffersBase #define glBindBuffersRange __rglgen_glBindBuffersRange #define glBindTextures __rglgen_glBindTextures #define glBindSamplers __rglgen_glBindSamplers #define glBindImageTextures __rglgen_glBindImageTextures #define glBindVertexBuffers __rglgen_glBindVertexBuffers #define glGetTextureHandleARB __rglgen_glGetTextureHandleARB #define glGetTextureSamplerHandleARB __rglgen_glGetTextureSamplerHandleARB #define glMakeTextureHandleResidentARB __rglgen_glMakeTextureHandleResidentARB #define glMakeTextureHandleNonResidentARB __rglgen_glMakeTextureHandleNonResidentARB #define glGetImageHandleARB __rglgen_glGetImageHandleARB #define glMakeImageHandleResidentARB __rglgen_glMakeImageHandleResidentARB #define glMakeImageHandleNonResidentARB __rglgen_glMakeImageHandleNonResidentARB #define glUniformHandleui64ARB __rglgen_glUniformHandleui64ARB #define glUniformHandleui64vARB __rglgen_glUniformHandleui64vARB #define glProgramUniformHandleui64ARB __rglgen_glProgramUniformHandleui64ARB #define glProgramUniformHandleui64vARB __rglgen_glProgramUniformHandleui64vARB #define glIsTextureHandleResidentARB __rglgen_glIsTextureHandleResidentARB #define glIsImageHandleResidentARB __rglgen_glIsImageHandleResidentARB #define glVertexAttribL1ui64ARB __rglgen_glVertexAttribL1ui64ARB #define glVertexAttribL1ui64vARB __rglgen_glVertexAttribL1ui64vARB #define glGetVertexAttribLui64vARB __rglgen_glGetVertexAttribLui64vARB #define glCreateSyncFromCLeventARB __rglgen_glCreateSyncFromCLeventARB #define glClampColorARB __rglgen_glClampColorARB #define glDispatchComputeGroupSizeARB __rglgen_glDispatchComputeGroupSizeARB #define glDebugMessageControlARB __rglgen_glDebugMessageControlARB #define glDebugMessageInsertARB __rglgen_glDebugMessageInsertARB #define glDebugMessageCallbackARB __rglgen_glDebugMessageCallbackARB #define glGetDebugMessageLogARB __rglgen_glGetDebugMessageLogARB #define glDrawBuffersARB __rglgen_glDrawBuffersARB #define glBlendEquationiARB __rglgen_glBlendEquationiARB #define glBlendEquationSeparateiARB __rglgen_glBlendEquationSeparateiARB #define glBlendFunciARB __rglgen_glBlendFunciARB #define glBlendFuncSeparateiARB __rglgen_glBlendFuncSeparateiARB #define glDrawArraysInstancedARB __rglgen_glDrawArraysInstancedARB #define glDrawElementsInstancedARB __rglgen_glDrawElementsInstancedARB #define glProgramStringARB __rglgen_glProgramStringARB #define glBindProgramARB __rglgen_glBindProgramARB #define glDeleteProgramsARB __rglgen_glDeleteProgramsARB #define glGenProgramsARB __rglgen_glGenProgramsARB #define glProgramEnvParameter4dARB __rglgen_glProgramEnvParameter4dARB #define glProgramEnvParameter4dvARB __rglgen_glProgramEnvParameter4dvARB #define glProgramEnvParameter4fARB __rglgen_glProgramEnvParameter4fARB #define glProgramEnvParameter4fvARB __rglgen_glProgramEnvParameter4fvARB #define glProgramLocalParameter4dARB __rglgen_glProgramLocalParameter4dARB #define glProgramLocalParameter4dvARB __rglgen_glProgramLocalParameter4dvARB #define glProgramLocalParameter4fARB __rglgen_glProgramLocalParameter4fARB #define glProgramLocalParameter4fvARB __rglgen_glProgramLocalParameter4fvARB #define glGetProgramEnvParameterdvARB __rglgen_glGetProgramEnvParameterdvARB #define glGetProgramEnvParameterfvARB __rglgen_glGetProgramEnvParameterfvARB #define glGetProgramLocalParameterdvARB __rglgen_glGetProgramLocalParameterdvARB #define glGetProgramLocalParameterfvARB __rglgen_glGetProgramLocalParameterfvARB #define glGetProgramivARB __rglgen_glGetProgramivARB #define glGetProgramStringARB __rglgen_glGetProgramStringARB #define glIsProgramARB __rglgen_glIsProgramARB #define glProgramParameteriARB __rglgen_glProgramParameteriARB #define glFramebufferTextureARB __rglgen_glFramebufferTextureARB #define glFramebufferTextureLayerARB __rglgen_glFramebufferTextureLayerARB #define glFramebufferTextureFaceARB __rglgen_glFramebufferTextureFaceARB #define glColorTable __rglgen_glColorTable #define glColorTableParameterfv __rglgen_glColorTableParameterfv #define glColorTableParameteriv __rglgen_glColorTableParameteriv #define glCopyColorTable __rglgen_glCopyColorTable #define glGetColorTable __rglgen_glGetColorTable #define glGetColorTableParameterfv __rglgen_glGetColorTableParameterfv #define glGetColorTableParameteriv __rglgen_glGetColorTableParameteriv #define glColorSubTable __rglgen_glColorSubTable #define glCopyColorSubTable __rglgen_glCopyColorSubTable #define glConvolutionFilter1D __rglgen_glConvolutionFilter1D #define glConvolutionFilter2D __rglgen_glConvolutionFilter2D #define glConvolutionParameterf __rglgen_glConvolutionParameterf #define glConvolutionParameterfv __rglgen_glConvolutionParameterfv #define glConvolutionParameteri __rglgen_glConvolutionParameteri #define glConvolutionParameteriv __rglgen_glConvolutionParameteriv #define glCopyConvolutionFilter1D __rglgen_glCopyConvolutionFilter1D #define glCopyConvolutionFilter2D __rglgen_glCopyConvolutionFilter2D #define glGetConvolutionFilter __rglgen_glGetConvolutionFilter #define glGetConvolutionParameterfv __rglgen_glGetConvolutionParameterfv #define glGetConvolutionParameteriv __rglgen_glGetConvolutionParameteriv #define glGetSeparableFilter __rglgen_glGetSeparableFilter #define glSeparableFilter2D __rglgen_glSeparableFilter2D #define glGetHistogram __rglgen_glGetHistogram #define glGetHistogramParameterfv __rglgen_glGetHistogramParameterfv #define glGetHistogramParameteriv __rglgen_glGetHistogramParameteriv #define glGetMinmax __rglgen_glGetMinmax #define glGetMinmaxParameterfv __rglgen_glGetMinmaxParameterfv #define glGetMinmaxParameteriv __rglgen_glGetMinmaxParameteriv #define glHistogram __rglgen_glHistogram #define glMinmax __rglgen_glMinmax #define glResetHistogram __rglgen_glResetHistogram #define glResetMinmax __rglgen_glResetMinmax #define glMultiDrawArraysIndirectCountARB __rglgen_glMultiDrawArraysIndirectCountARB #define glMultiDrawElementsIndirectCountARB __rglgen_glMultiDrawElementsIndirectCountARB #define glVertexAttribDivisorARB __rglgen_glVertexAttribDivisorARB #define glCurrentPaletteMatrixARB __rglgen_glCurrentPaletteMatrixARB #define glMatrixIndexubvARB __rglgen_glMatrixIndexubvARB #define glMatrixIndexusvARB __rglgen_glMatrixIndexusvARB #define glMatrixIndexuivARB __rglgen_glMatrixIndexuivARB #define glMatrixIndexPointerARB __rglgen_glMatrixIndexPointerARB #define glSampleCoverageARB __rglgen_glSampleCoverageARB #define glActiveTextureARB __rglgen_glActiveTextureARB #define glClientActiveTextureARB __rglgen_glClientActiveTextureARB #define glMultiTexCoord1dARB __rglgen_glMultiTexCoord1dARB #define glMultiTexCoord1dvARB __rglgen_glMultiTexCoord1dvARB #define glMultiTexCoord1fARB __rglgen_glMultiTexCoord1fARB #define glMultiTexCoord1fvARB __rglgen_glMultiTexCoord1fvARB #define glMultiTexCoord1iARB __rglgen_glMultiTexCoord1iARB #define glMultiTexCoord1ivARB __rglgen_glMultiTexCoord1ivARB #define glMultiTexCoord1sARB __rglgen_glMultiTexCoord1sARB #define glMultiTexCoord1svARB __rglgen_glMultiTexCoord1svARB #define glMultiTexCoord2dARB __rglgen_glMultiTexCoord2dARB #define glMultiTexCoord2dvARB __rglgen_glMultiTexCoord2dvARB #define glMultiTexCoord2fARB __rglgen_glMultiTexCoord2fARB #define glMultiTexCoord2fvARB __rglgen_glMultiTexCoord2fvARB #define glMultiTexCoord2iARB __rglgen_glMultiTexCoord2iARB #define glMultiTexCoord2ivARB __rglgen_glMultiTexCoord2ivARB #define glMultiTexCoord2sARB __rglgen_glMultiTexCoord2sARB #define glMultiTexCoord2svARB __rglgen_glMultiTexCoord2svARB #define glMultiTexCoord3dARB __rglgen_glMultiTexCoord3dARB #define glMultiTexCoord3dvARB __rglgen_glMultiTexCoord3dvARB #define glMultiTexCoord3fARB __rglgen_glMultiTexCoord3fARB #define glMultiTexCoord3fvARB __rglgen_glMultiTexCoord3fvARB #define glMultiTexCoord3iARB __rglgen_glMultiTexCoord3iARB #define glMultiTexCoord3ivARB __rglgen_glMultiTexCoord3ivARB #define glMultiTexCoord3sARB __rglgen_glMultiTexCoord3sARB #define glMultiTexCoord3svARB __rglgen_glMultiTexCoord3svARB #define glMultiTexCoord4dARB __rglgen_glMultiTexCoord4dARB #define glMultiTexCoord4dvARB __rglgen_glMultiTexCoord4dvARB #define glMultiTexCoord4fARB __rglgen_glMultiTexCoord4fARB #define glMultiTexCoord4fvARB __rglgen_glMultiTexCoord4fvARB #define glMultiTexCoord4iARB __rglgen_glMultiTexCoord4iARB #define glMultiTexCoord4ivARB __rglgen_glMultiTexCoord4ivARB #define glMultiTexCoord4sARB __rglgen_glMultiTexCoord4sARB #define glMultiTexCoord4svARB __rglgen_glMultiTexCoord4svARB #define glGenQueriesARB __rglgen_glGenQueriesARB #define glDeleteQueriesARB __rglgen_glDeleteQueriesARB #define glIsQueryARB __rglgen_glIsQueryARB #define glBeginQueryARB __rglgen_glBeginQueryARB #define glEndQueryARB __rglgen_glEndQueryARB #define glGetQueryivARB __rglgen_glGetQueryivARB #define glGetQueryObjectivARB __rglgen_glGetQueryObjectivARB #define glGetQueryObjectuivARB __rglgen_glGetQueryObjectuivARB #define glPointParameterfARB __rglgen_glPointParameterfARB #define glPointParameterfvARB __rglgen_glPointParameterfvARB #define glGetGraphicsResetStatusARB __rglgen_glGetGraphicsResetStatusARB #define glGetnTexImageARB __rglgen_glGetnTexImageARB #define glReadnPixelsARB __rglgen_glReadnPixelsARB #define glGetnCompressedTexImageARB __rglgen_glGetnCompressedTexImageARB #define glGetnUniformfvARB __rglgen_glGetnUniformfvARB #define glGetnUniformivARB __rglgen_glGetnUniformivARB #define glGetnUniformuivARB __rglgen_glGetnUniformuivARB #define glGetnUniformdvARB __rglgen_glGetnUniformdvARB #define glGetnMapdvARB __rglgen_glGetnMapdvARB #define glGetnMapfvARB __rglgen_glGetnMapfvARB #define glGetnMapivARB __rglgen_glGetnMapivARB #define glGetnPixelMapfvARB __rglgen_glGetnPixelMapfvARB #define glGetnPixelMapuivARB __rglgen_glGetnPixelMapuivARB #define glGetnPixelMapusvARB __rglgen_glGetnPixelMapusvARB #define glGetnPolygonStippleARB __rglgen_glGetnPolygonStippleARB #define glGetnColorTableARB __rglgen_glGetnColorTableARB #define glGetnConvolutionFilterARB __rglgen_glGetnConvolutionFilterARB #define glGetnSeparableFilterARB __rglgen_glGetnSeparableFilterARB #define glGetnHistogramARB __rglgen_glGetnHistogramARB #define glGetnMinmaxARB __rglgen_glGetnMinmaxARB #define glMinSampleShadingARB __rglgen_glMinSampleShadingARB #define glDeleteObjectARB __rglgen_glDeleteObjectARB #define glGetHandleARB __rglgen_glGetHandleARB #define glDetachObjectARB __rglgen_glDetachObjectARB #define glCreateShaderObjectARB __rglgen_glCreateShaderObjectARB #define glShaderSourceARB __rglgen_glShaderSourceARB #define glCompileShaderARB __rglgen_glCompileShaderARB #define glCreateProgramObjectARB __rglgen_glCreateProgramObjectARB #define glAttachObjectARB __rglgen_glAttachObjectARB #define glLinkProgramARB __rglgen_glLinkProgramARB #define glUseProgramObjectARB __rglgen_glUseProgramObjectARB #define glValidateProgramARB __rglgen_glValidateProgramARB #define glUniform1fARB __rglgen_glUniform1fARB #define glUniform2fARB __rglgen_glUniform2fARB #define glUniform3fARB __rglgen_glUniform3fARB #define glUniform4fARB __rglgen_glUniform4fARB #define glUniform1iARB __rglgen_glUniform1iARB #define glUniform2iARB __rglgen_glUniform2iARB #define glUniform3iARB __rglgen_glUniform3iARB #define glUniform4iARB __rglgen_glUniform4iARB #define glUniform1fvARB __rglgen_glUniform1fvARB #define glUniform2fvARB __rglgen_glUniform2fvARB #define glUniform3fvARB __rglgen_glUniform3fvARB #define glUniform4fvARB __rglgen_glUniform4fvARB #define glUniform1ivARB __rglgen_glUniform1ivARB #define glUniform2ivARB __rglgen_glUniform2ivARB #define glUniform3ivARB __rglgen_glUniform3ivARB #define glUniform4ivARB __rglgen_glUniform4ivARB #define glUniformMatrix2fvARB __rglgen_glUniformMatrix2fvARB #define glUniformMatrix3fvARB __rglgen_glUniformMatrix3fvARB #define glUniformMatrix4fvARB __rglgen_glUniformMatrix4fvARB #define glGetObjectParameterfvARB __rglgen_glGetObjectParameterfvARB #define glGetObjectParameterivARB __rglgen_glGetObjectParameterivARB #define glGetInfoLogARB __rglgen_glGetInfoLogARB #define glGetAttachedObjectsARB __rglgen_glGetAttachedObjectsARB #define glGetUniformLocationARB __rglgen_glGetUniformLocationARB #define glGetActiveUniformARB __rglgen_glGetActiveUniformARB #define glGetUniformfvARB __rglgen_glGetUniformfvARB #define glGetUniformivARB __rglgen_glGetUniformivARB #define glGetShaderSourceARB __rglgen_glGetShaderSourceARB #define glNamedStringARB __rglgen_glNamedStringARB #define glDeleteNamedStringARB __rglgen_glDeleteNamedStringARB #define glCompileShaderIncludeARB __rglgen_glCompileShaderIncludeARB #define glIsNamedStringARB __rglgen_glIsNamedStringARB #define glGetNamedStringARB __rglgen_glGetNamedStringARB #define glGetNamedStringivARB __rglgen_glGetNamedStringivARB #define glTexPageCommitmentARB __rglgen_glTexPageCommitmentARB #define glTexBufferARB __rglgen_glTexBufferARB #define glCompressedTexImage3DARB __rglgen_glCompressedTexImage3DARB #define glCompressedTexImage2DARB __rglgen_glCompressedTexImage2DARB #define glCompressedTexImage1DARB __rglgen_glCompressedTexImage1DARB #define glCompressedTexSubImage3DARB __rglgen_glCompressedTexSubImage3DARB #define glCompressedTexSubImage2DARB __rglgen_glCompressedTexSubImage2DARB #define glCompressedTexSubImage1DARB __rglgen_glCompressedTexSubImage1DARB #define glGetCompressedTexImageARB __rglgen_glGetCompressedTexImageARB #define glLoadTransposeMatrixfARB __rglgen_glLoadTransposeMatrixfARB #define glLoadTransposeMatrixdARB __rglgen_glLoadTransposeMatrixdARB #define glMultTransposeMatrixfARB __rglgen_glMultTransposeMatrixfARB #define glMultTransposeMatrixdARB __rglgen_glMultTransposeMatrixdARB #define glWeightbvARB __rglgen_glWeightbvARB #define glWeightsvARB __rglgen_glWeightsvARB #define glWeightivARB __rglgen_glWeightivARB #define glWeightfvARB __rglgen_glWeightfvARB #define glWeightdvARB __rglgen_glWeightdvARB #define glWeightubvARB __rglgen_glWeightubvARB #define glWeightusvARB __rglgen_glWeightusvARB #define glWeightuivARB __rglgen_glWeightuivARB #define glWeightPointerARB __rglgen_glWeightPointerARB #define glVertexBlendARB __rglgen_glVertexBlendARB #define glBindBufferARB __rglgen_glBindBufferARB #define glDeleteBuffersARB __rglgen_glDeleteBuffersARB #define glGenBuffersARB __rglgen_glGenBuffersARB #define glIsBufferARB __rglgen_glIsBufferARB #define glBufferDataARB __rglgen_glBufferDataARB #define glBufferSubDataARB __rglgen_glBufferSubDataARB #define glGetBufferSubDataARB __rglgen_glGetBufferSubDataARB #define glMapBufferARB __rglgen_glMapBufferARB #define glUnmapBufferARB __rglgen_glUnmapBufferARB #define glGetBufferParameterivARB __rglgen_glGetBufferParameterivARB #define glGetBufferPointervARB __rglgen_glGetBufferPointervARB #define glVertexAttrib1dARB __rglgen_glVertexAttrib1dARB #define glVertexAttrib1dvARB __rglgen_glVertexAttrib1dvARB #define glVertexAttrib1fARB __rglgen_glVertexAttrib1fARB #define glVertexAttrib1fvARB __rglgen_glVertexAttrib1fvARB #define glVertexAttrib1sARB __rglgen_glVertexAttrib1sARB #define glVertexAttrib1svARB __rglgen_glVertexAttrib1svARB #define glVertexAttrib2dARB __rglgen_glVertexAttrib2dARB #define glVertexAttrib2dvARB __rglgen_glVertexAttrib2dvARB #define glVertexAttrib2fARB __rglgen_glVertexAttrib2fARB #define glVertexAttrib2fvARB __rglgen_glVertexAttrib2fvARB #define glVertexAttrib2sARB __rglgen_glVertexAttrib2sARB #define glVertexAttrib2svARB __rglgen_glVertexAttrib2svARB #define glVertexAttrib3dARB __rglgen_glVertexAttrib3dARB #define glVertexAttrib3dvARB __rglgen_glVertexAttrib3dvARB #define glVertexAttrib3fARB __rglgen_glVertexAttrib3fARB #define glVertexAttrib3fvARB __rglgen_glVertexAttrib3fvARB #define glVertexAttrib3sARB __rglgen_glVertexAttrib3sARB #define glVertexAttrib3svARB __rglgen_glVertexAttrib3svARB #define glVertexAttrib4NbvARB __rglgen_glVertexAttrib4NbvARB #define glVertexAttrib4NivARB __rglgen_glVertexAttrib4NivARB #define glVertexAttrib4NsvARB __rglgen_glVertexAttrib4NsvARB #define glVertexAttrib4NubARB __rglgen_glVertexAttrib4NubARB #define glVertexAttrib4NubvARB __rglgen_glVertexAttrib4NubvARB #define glVertexAttrib4NuivARB __rglgen_glVertexAttrib4NuivARB #define glVertexAttrib4NusvARB __rglgen_glVertexAttrib4NusvARB #define glVertexAttrib4bvARB __rglgen_glVertexAttrib4bvARB #define glVertexAttrib4dARB __rglgen_glVertexAttrib4dARB #define glVertexAttrib4dvARB __rglgen_glVertexAttrib4dvARB #define glVertexAttrib4fARB __rglgen_glVertexAttrib4fARB #define glVertexAttrib4fvARB __rglgen_glVertexAttrib4fvARB #define glVertexAttrib4ivARB __rglgen_glVertexAttrib4ivARB #define glVertexAttrib4sARB __rglgen_glVertexAttrib4sARB #define glVertexAttrib4svARB __rglgen_glVertexAttrib4svARB #define glVertexAttrib4ubvARB __rglgen_glVertexAttrib4ubvARB #define glVertexAttrib4uivARB __rglgen_glVertexAttrib4uivARB #define glVertexAttrib4usvARB __rglgen_glVertexAttrib4usvARB #define glVertexAttribPointerARB __rglgen_glVertexAttribPointerARB #define glEnableVertexAttribArrayARB __rglgen_glEnableVertexAttribArrayARB #define glDisableVertexAttribArrayARB __rglgen_glDisableVertexAttribArrayARB #define glGetVertexAttribdvARB __rglgen_glGetVertexAttribdvARB #define glGetVertexAttribfvARB __rglgen_glGetVertexAttribfvARB #define glGetVertexAttribivARB __rglgen_glGetVertexAttribivARB #define glGetVertexAttribPointervARB __rglgen_glGetVertexAttribPointervARB #define glBindAttribLocationARB __rglgen_glBindAttribLocationARB #define glGetActiveAttribARB __rglgen_glGetActiveAttribARB #define glGetAttribLocationARB __rglgen_glGetAttribLocationARB #define glWindowPos2dARB __rglgen_glWindowPos2dARB #define glWindowPos2dvARB __rglgen_glWindowPos2dvARB #define glWindowPos2fARB __rglgen_glWindowPos2fARB #define glWindowPos2fvARB __rglgen_glWindowPos2fvARB #define glWindowPos2iARB __rglgen_glWindowPos2iARB #define glWindowPos2ivARB __rglgen_glWindowPos2ivARB #define glWindowPos2sARB __rglgen_glWindowPos2sARB #define glWindowPos2svARB __rglgen_glWindowPos2svARB #define glWindowPos3dARB __rglgen_glWindowPos3dARB #define glWindowPos3dvARB __rglgen_glWindowPos3dvARB #define glWindowPos3fARB __rglgen_glWindowPos3fARB #define glWindowPos3fvARB __rglgen_glWindowPos3fvARB #define glWindowPos3iARB __rglgen_glWindowPos3iARB #define glWindowPos3ivARB __rglgen_glWindowPos3ivARB #define glWindowPos3sARB __rglgen_glWindowPos3sARB #define glWindowPos3svARB __rglgen_glWindowPos3svARB #define glMultiTexCoord1bOES __rglgen_glMultiTexCoord1bOES #define glMultiTexCoord1bvOES __rglgen_glMultiTexCoord1bvOES #define glMultiTexCoord2bOES __rglgen_glMultiTexCoord2bOES #define glMultiTexCoord2bvOES __rglgen_glMultiTexCoord2bvOES #define glMultiTexCoord3bOES __rglgen_glMultiTexCoord3bOES #define glMultiTexCoord3bvOES __rglgen_glMultiTexCoord3bvOES #define glMultiTexCoord4bOES __rglgen_glMultiTexCoord4bOES #define glMultiTexCoord4bvOES __rglgen_glMultiTexCoord4bvOES #define glTexCoord1bOES __rglgen_glTexCoord1bOES #define glTexCoord1bvOES __rglgen_glTexCoord1bvOES #define glTexCoord2bOES __rglgen_glTexCoord2bOES #define glTexCoord2bvOES __rglgen_glTexCoord2bvOES #define glTexCoord3bOES __rglgen_glTexCoord3bOES #define glTexCoord3bvOES __rglgen_glTexCoord3bvOES #define glTexCoord4bOES __rglgen_glTexCoord4bOES #define glTexCoord4bvOES __rglgen_glTexCoord4bvOES #define glVertex2bOES __rglgen_glVertex2bOES #define glVertex2bvOES __rglgen_glVertex2bvOES #define glVertex3bOES __rglgen_glVertex3bOES #define glVertex3bvOES __rglgen_glVertex3bvOES #define glVertex4bOES __rglgen_glVertex4bOES #define glVertex4bvOES __rglgen_glVertex4bvOES #define glAlphaFuncxOES __rglgen_glAlphaFuncxOES #define glClearColorxOES __rglgen_glClearColorxOES #define glClearDepthxOES __rglgen_glClearDepthxOES #define glClipPlanexOES __rglgen_glClipPlanexOES #define glColor4xOES __rglgen_glColor4xOES #define glDepthRangexOES __rglgen_glDepthRangexOES #define glFogxOES __rglgen_glFogxOES #define glFogxvOES __rglgen_glFogxvOES #define glFrustumxOES __rglgen_glFrustumxOES #define glGetClipPlanexOES __rglgen_glGetClipPlanexOES #define glGetFixedvOES __rglgen_glGetFixedvOES #define glGetTexEnvxvOES __rglgen_glGetTexEnvxvOES #define glGetTexParameterxvOES __rglgen_glGetTexParameterxvOES #define glLightModelxOES __rglgen_glLightModelxOES #define glLightModelxvOES __rglgen_glLightModelxvOES #define glLightxOES __rglgen_glLightxOES #define glLightxvOES __rglgen_glLightxvOES #define glLineWidthxOES __rglgen_glLineWidthxOES #define glLoadMatrixxOES __rglgen_glLoadMatrixxOES #define glMaterialxOES __rglgen_glMaterialxOES #define glMaterialxvOES __rglgen_glMaterialxvOES #define glMultMatrixxOES __rglgen_glMultMatrixxOES #define glMultiTexCoord4xOES __rglgen_glMultiTexCoord4xOES #define glNormal3xOES __rglgen_glNormal3xOES #define glOrthoxOES __rglgen_glOrthoxOES #define glPointParameterxvOES __rglgen_glPointParameterxvOES #define glPointSizexOES __rglgen_glPointSizexOES #define glPolygonOffsetxOES __rglgen_glPolygonOffsetxOES #define glRotatexOES __rglgen_glRotatexOES #define glSampleCoverageOES __rglgen_glSampleCoverageOES #define glScalexOES __rglgen_glScalexOES #define glTexEnvxOES __rglgen_glTexEnvxOES #define glTexEnvxvOES __rglgen_glTexEnvxvOES #define glTexParameterxOES __rglgen_glTexParameterxOES #define glTexParameterxvOES __rglgen_glTexParameterxvOES #define glTranslatexOES __rglgen_glTranslatexOES #define glAccumxOES __rglgen_glAccumxOES #define glBitmapxOES __rglgen_glBitmapxOES #define glBlendColorxOES __rglgen_glBlendColorxOES #define glClearAccumxOES __rglgen_glClearAccumxOES #define glColor3xOES __rglgen_glColor3xOES #define glColor3xvOES __rglgen_glColor3xvOES #define glColor4xvOES __rglgen_glColor4xvOES #define glConvolutionParameterxOES __rglgen_glConvolutionParameterxOES #define glConvolutionParameterxvOES __rglgen_glConvolutionParameterxvOES #define glEvalCoord1xOES __rglgen_glEvalCoord1xOES #define glEvalCoord1xvOES __rglgen_glEvalCoord1xvOES #define glEvalCoord2xOES __rglgen_glEvalCoord2xOES #define glEvalCoord2xvOES __rglgen_glEvalCoord2xvOES #define glFeedbackBufferxOES __rglgen_glFeedbackBufferxOES #define glGetConvolutionParameterxvOES __rglgen_glGetConvolutionParameterxvOES #define glGetHistogramParameterxvOES __rglgen_glGetHistogramParameterxvOES #define glGetLightxOES __rglgen_glGetLightxOES #define glGetMapxvOES __rglgen_glGetMapxvOES #define glGetMaterialxOES __rglgen_glGetMaterialxOES #define glGetPixelMapxv __rglgen_glGetPixelMapxv #define glGetTexGenxvOES __rglgen_glGetTexGenxvOES #define glGetTexLevelParameterxvOES __rglgen_glGetTexLevelParameterxvOES #define glIndexxOES __rglgen_glIndexxOES #define glIndexxvOES __rglgen_glIndexxvOES #define glLoadTransposeMatrixxOES __rglgen_glLoadTransposeMatrixxOES #define glMap1xOES __rglgen_glMap1xOES #define glMap2xOES __rglgen_glMap2xOES #define glMapGrid1xOES __rglgen_glMapGrid1xOES #define glMapGrid2xOES __rglgen_glMapGrid2xOES #define glMultTransposeMatrixxOES __rglgen_glMultTransposeMatrixxOES #define glMultiTexCoord1xOES __rglgen_glMultiTexCoord1xOES #define glMultiTexCoord1xvOES __rglgen_glMultiTexCoord1xvOES #define glMultiTexCoord2xOES __rglgen_glMultiTexCoord2xOES #define glMultiTexCoord2xvOES __rglgen_glMultiTexCoord2xvOES #define glMultiTexCoord3xOES __rglgen_glMultiTexCoord3xOES #define glMultiTexCoord3xvOES __rglgen_glMultiTexCoord3xvOES #define glMultiTexCoord4xvOES __rglgen_glMultiTexCoord4xvOES #define glNormal3xvOES __rglgen_glNormal3xvOES #define glPassThroughxOES __rglgen_glPassThroughxOES #define glPixelMapx __rglgen_glPixelMapx #define glPixelStorex __rglgen_glPixelStorex #define glPixelTransferxOES __rglgen_glPixelTransferxOES #define glPixelZoomxOES __rglgen_glPixelZoomxOES #define glPrioritizeTexturesxOES __rglgen_glPrioritizeTexturesxOES #define glRasterPos2xOES __rglgen_glRasterPos2xOES #define glRasterPos2xvOES __rglgen_glRasterPos2xvOES #define glRasterPos3xOES __rglgen_glRasterPos3xOES #define glRasterPos3xvOES __rglgen_glRasterPos3xvOES #define glRasterPos4xOES __rglgen_glRasterPos4xOES #define glRasterPos4xvOES __rglgen_glRasterPos4xvOES #define glRectxOES __rglgen_glRectxOES #define glRectxvOES __rglgen_glRectxvOES #define glTexCoord1xOES __rglgen_glTexCoord1xOES #define glTexCoord1xvOES __rglgen_glTexCoord1xvOES #define glTexCoord2xOES __rglgen_glTexCoord2xOES #define glTexCoord2xvOES __rglgen_glTexCoord2xvOES #define glTexCoord3xOES __rglgen_glTexCoord3xOES #define glTexCoord3xvOES __rglgen_glTexCoord3xvOES #define glTexCoord4xOES __rglgen_glTexCoord4xOES #define glTexCoord4xvOES __rglgen_glTexCoord4xvOES #define glTexGenxOES __rglgen_glTexGenxOES #define glTexGenxvOES __rglgen_glTexGenxvOES #define glVertex2xOES __rglgen_glVertex2xOES #define glVertex2xvOES __rglgen_glVertex2xvOES #define glVertex3xOES __rglgen_glVertex3xOES #define glVertex3xvOES __rglgen_glVertex3xvOES #define glVertex4xOES __rglgen_glVertex4xOES #define glVertex4xvOES __rglgen_glVertex4xvOES #define glQueryMatrixxOES __rglgen_glQueryMatrixxOES #define glClearDepthfOES __rglgen_glClearDepthfOES #define glClipPlanefOES __rglgen_glClipPlanefOES #define glDepthRangefOES __rglgen_glDepthRangefOES #define glFrustumfOES __rglgen_glFrustumfOES #define glGetClipPlanefOES __rglgen_glGetClipPlanefOES #define glOrthofOES __rglgen_glOrthofOES #define glImageTransformParameteriHP __rglgen_glImageTransformParameteriHP #define glImageTransformParameterfHP __rglgen_glImageTransformParameterfHP #define glImageTransformParameterivHP __rglgen_glImageTransformParameterivHP #define glImageTransformParameterfvHP __rglgen_glImageTransformParameterfvHP #define glGetImageTransformParameterivHP __rglgen_glGetImageTransformParameterivHP #define glGetImageTransformParameterfvHP __rglgen_glGetImageTransformParameterfvHP extern RGLSYMGLDRAWRANGEELEMENTSPROC __rglgen_glDrawRangeElements; extern RGLSYMGLTEXIMAGE3DPROC __rglgen_glTexImage3D; extern RGLSYMGLTEXSUBIMAGE3DPROC __rglgen_glTexSubImage3D; extern RGLSYMGLCOPYTEXSUBIMAGE3DPROC __rglgen_glCopyTexSubImage3D; extern RGLSYMGLACTIVETEXTUREPROC __rglgen_glActiveTexture; extern RGLSYMGLSAMPLECOVERAGEPROC __rglgen_glSampleCoverage; extern RGLSYMGLCOMPRESSEDTEXIMAGE3DPROC __rglgen_glCompressedTexImage3D; extern RGLSYMGLCOMPRESSEDTEXIMAGE2DPROC __rglgen_glCompressedTexImage2D; extern RGLSYMGLCOMPRESSEDTEXIMAGE1DPROC __rglgen_glCompressedTexImage1D; extern RGLSYMGLCOMPRESSEDTEXSUBIMAGE3DPROC __rglgen_glCompressedTexSubImage3D; extern RGLSYMGLCOMPRESSEDTEXSUBIMAGE2DPROC __rglgen_glCompressedTexSubImage2D; extern RGLSYMGLCOMPRESSEDTEXSUBIMAGE1DPROC __rglgen_glCompressedTexSubImage1D; extern RGLSYMGLGETCOMPRESSEDTEXIMAGEPROC __rglgen_glGetCompressedTexImage; extern RGLSYMGLCLIENTACTIVETEXTUREPROC __rglgen_glClientActiveTexture; extern RGLSYMGLMULTITEXCOORD1DPROC __rglgen_glMultiTexCoord1d; extern RGLSYMGLMULTITEXCOORD1DVPROC __rglgen_glMultiTexCoord1dv; extern RGLSYMGLMULTITEXCOORD1FPROC __rglgen_glMultiTexCoord1f; extern RGLSYMGLMULTITEXCOORD1FVPROC __rglgen_glMultiTexCoord1fv; extern RGLSYMGLMULTITEXCOORD1IPROC __rglgen_glMultiTexCoord1i; extern RGLSYMGLMULTITEXCOORD1IVPROC __rglgen_glMultiTexCoord1iv; extern RGLSYMGLMULTITEXCOORD1SPROC __rglgen_glMultiTexCoord1s; extern RGLSYMGLMULTITEXCOORD1SVPROC __rglgen_glMultiTexCoord1sv; extern RGLSYMGLMULTITEXCOORD2DPROC __rglgen_glMultiTexCoord2d; extern RGLSYMGLMULTITEXCOORD2DVPROC __rglgen_glMultiTexCoord2dv; extern RGLSYMGLMULTITEXCOORD2FPROC __rglgen_glMultiTexCoord2f; extern RGLSYMGLMULTITEXCOORD2FVPROC __rglgen_glMultiTexCoord2fv; extern RGLSYMGLMULTITEXCOORD2IPROC __rglgen_glMultiTexCoord2i; extern RGLSYMGLMULTITEXCOORD2IVPROC __rglgen_glMultiTexCoord2iv; extern RGLSYMGLMULTITEXCOORD2SPROC __rglgen_glMultiTexCoord2s; extern RGLSYMGLMULTITEXCOORD2SVPROC __rglgen_glMultiTexCoord2sv; extern RGLSYMGLMULTITEXCOORD3DPROC __rglgen_glMultiTexCoord3d; extern RGLSYMGLMULTITEXCOORD3DVPROC __rglgen_glMultiTexCoord3dv; extern RGLSYMGLMULTITEXCOORD3FPROC __rglgen_glMultiTexCoord3f; extern RGLSYMGLMULTITEXCOORD3FVPROC __rglgen_glMultiTexCoord3fv; extern RGLSYMGLMULTITEXCOORD3IPROC __rglgen_glMultiTexCoord3i; extern RGLSYMGLMULTITEXCOORD3IVPROC __rglgen_glMultiTexCoord3iv; extern RGLSYMGLMULTITEXCOORD3SPROC __rglgen_glMultiTexCoord3s; extern RGLSYMGLMULTITEXCOORD3SVPROC __rglgen_glMultiTexCoord3sv; extern RGLSYMGLMULTITEXCOORD4DPROC __rglgen_glMultiTexCoord4d; extern RGLSYMGLMULTITEXCOORD4DVPROC __rglgen_glMultiTexCoord4dv; extern RGLSYMGLMULTITEXCOORD4FPROC __rglgen_glMultiTexCoord4f; extern RGLSYMGLMULTITEXCOORD4FVPROC __rglgen_glMultiTexCoord4fv; extern RGLSYMGLMULTITEXCOORD4IPROC __rglgen_glMultiTexCoord4i; extern RGLSYMGLMULTITEXCOORD4IVPROC __rglgen_glMultiTexCoord4iv; extern RGLSYMGLMULTITEXCOORD4SPROC __rglgen_glMultiTexCoord4s; extern RGLSYMGLMULTITEXCOORD4SVPROC __rglgen_glMultiTexCoord4sv; extern RGLSYMGLLOADTRANSPOSEMATRIXFPROC __rglgen_glLoadTransposeMatrixf; extern RGLSYMGLLOADTRANSPOSEMATRIXDPROC __rglgen_glLoadTransposeMatrixd; extern RGLSYMGLMULTTRANSPOSEMATRIXFPROC __rglgen_glMultTransposeMatrixf; extern RGLSYMGLMULTTRANSPOSEMATRIXDPROC __rglgen_glMultTransposeMatrixd; extern RGLSYMGLBLENDFUNCSEPARATEPROC __rglgen_glBlendFuncSeparate; extern RGLSYMGLMULTIDRAWARRAYSPROC __rglgen_glMultiDrawArrays; extern RGLSYMGLMULTIDRAWELEMENTSPROC __rglgen_glMultiDrawElements; extern RGLSYMGLPOINTPARAMETERFPROC __rglgen_glPointParameterf; extern RGLSYMGLPOINTPARAMETERFVPROC __rglgen_glPointParameterfv; extern RGLSYMGLPOINTPARAMETERIPROC __rglgen_glPointParameteri; extern RGLSYMGLPOINTPARAMETERIVPROC __rglgen_glPointParameteriv; extern RGLSYMGLFOGCOORDFPROC __rglgen_glFogCoordf; extern RGLSYMGLFOGCOORDFVPROC __rglgen_glFogCoordfv; extern RGLSYMGLFOGCOORDDPROC __rglgen_glFogCoordd; extern RGLSYMGLFOGCOORDDVPROC __rglgen_glFogCoorddv; extern RGLSYMGLFOGCOORDPOINTERPROC __rglgen_glFogCoordPointer; extern RGLSYMGLSECONDARYCOLOR3BPROC __rglgen_glSecondaryColor3b; extern RGLSYMGLSECONDARYCOLOR3BVPROC __rglgen_glSecondaryColor3bv; extern RGLSYMGLSECONDARYCOLOR3DPROC __rglgen_glSecondaryColor3d; extern RGLSYMGLSECONDARYCOLOR3DVPROC __rglgen_glSecondaryColor3dv; extern RGLSYMGLSECONDARYCOLOR3FPROC __rglgen_glSecondaryColor3f; extern RGLSYMGLSECONDARYCOLOR3FVPROC __rglgen_glSecondaryColor3fv; extern RGLSYMGLSECONDARYCOLOR3IPROC __rglgen_glSecondaryColor3i; extern RGLSYMGLSECONDARYCOLOR3IVPROC __rglgen_glSecondaryColor3iv; extern RGLSYMGLSECONDARYCOLOR3SPROC __rglgen_glSecondaryColor3s; extern RGLSYMGLSECONDARYCOLOR3SVPROC __rglgen_glSecondaryColor3sv; extern RGLSYMGLSECONDARYCOLOR3UBPROC __rglgen_glSecondaryColor3ub; extern RGLSYMGLSECONDARYCOLOR3UBVPROC __rglgen_glSecondaryColor3ubv; extern RGLSYMGLSECONDARYCOLOR3UIPROC __rglgen_glSecondaryColor3ui; extern RGLSYMGLSECONDARYCOLOR3UIVPROC __rglgen_glSecondaryColor3uiv; extern RGLSYMGLSECONDARYCOLOR3USPROC __rglgen_glSecondaryColor3us; extern RGLSYMGLSECONDARYCOLOR3USVPROC __rglgen_glSecondaryColor3usv; extern RGLSYMGLSECONDARYCOLORPOINTERPROC __rglgen_glSecondaryColorPointer; extern RGLSYMGLWINDOWPOS2DPROC __rglgen_glWindowPos2d; extern RGLSYMGLWINDOWPOS2DVPROC __rglgen_glWindowPos2dv; extern RGLSYMGLWINDOWPOS2FPROC __rglgen_glWindowPos2f; extern RGLSYMGLWINDOWPOS2FVPROC __rglgen_glWindowPos2fv; extern RGLSYMGLWINDOWPOS2IPROC __rglgen_glWindowPos2i; extern RGLSYMGLWINDOWPOS2IVPROC __rglgen_glWindowPos2iv; extern RGLSYMGLWINDOWPOS2SPROC __rglgen_glWindowPos2s; extern RGLSYMGLWINDOWPOS2SVPROC __rglgen_glWindowPos2sv; extern RGLSYMGLWINDOWPOS3DPROC __rglgen_glWindowPos3d; extern RGLSYMGLWINDOWPOS3DVPROC __rglgen_glWindowPos3dv; extern RGLSYMGLWINDOWPOS3FPROC __rglgen_glWindowPos3f; extern RGLSYMGLWINDOWPOS3FVPROC __rglgen_glWindowPos3fv; extern RGLSYMGLWINDOWPOS3IPROC __rglgen_glWindowPos3i; extern RGLSYMGLWINDOWPOS3IVPROC __rglgen_glWindowPos3iv; extern RGLSYMGLWINDOWPOS3SPROC __rglgen_glWindowPos3s; extern RGLSYMGLWINDOWPOS3SVPROC __rglgen_glWindowPos3sv; extern RGLSYMGLBLENDCOLORPROC __rglgen_glBlendColor; extern RGLSYMGLBLENDEQUATIONPROC __rglgen_glBlendEquation; extern RGLSYMGLGENQUERIESPROC __rglgen_glGenQueries; extern RGLSYMGLDELETEQUERIESPROC __rglgen_glDeleteQueries; extern RGLSYMGLISQUERYPROC __rglgen_glIsQuery; extern RGLSYMGLBEGINQUERYPROC __rglgen_glBeginQuery; extern RGLSYMGLENDQUERYPROC __rglgen_glEndQuery; extern RGLSYMGLGETQUERYIVPROC __rglgen_glGetQueryiv; extern RGLSYMGLGETQUERYOBJECTIVPROC __rglgen_glGetQueryObjectiv; extern RGLSYMGLGETQUERYOBJECTUIVPROC __rglgen_glGetQueryObjectuiv; extern RGLSYMGLBINDBUFFERPROC __rglgen_glBindBuffer; extern RGLSYMGLDELETEBUFFERSPROC __rglgen_glDeleteBuffers; extern RGLSYMGLGENBUFFERSPROC __rglgen_glGenBuffers; extern RGLSYMGLISBUFFERPROC __rglgen_glIsBuffer; extern RGLSYMGLBUFFERDATAPROC __rglgen_glBufferData; extern RGLSYMGLBUFFERSUBDATAPROC __rglgen_glBufferSubData; extern RGLSYMGLGETBUFFERSUBDATAPROC __rglgen_glGetBufferSubData; extern RGLSYMGLMAPBUFFERPROC __rglgen_glMapBuffer; extern RGLSYMGLUNMAPBUFFERPROC __rglgen_glUnmapBuffer; extern RGLSYMGLGETBUFFERPARAMETERIVPROC __rglgen_glGetBufferParameteriv; extern RGLSYMGLGETBUFFERPOINTERVPROC __rglgen_glGetBufferPointerv; extern RGLSYMGLBLENDEQUATIONSEPARATEPROC __rglgen_glBlendEquationSeparate; extern RGLSYMGLDRAWBUFFERSPROC __rglgen_glDrawBuffers; extern RGLSYMGLSTENCILOPSEPARATEPROC __rglgen_glStencilOpSeparate; extern RGLSYMGLSTENCILFUNCSEPARATEPROC __rglgen_glStencilFuncSeparate; extern RGLSYMGLSTENCILMASKSEPARATEPROC __rglgen_glStencilMaskSeparate; extern RGLSYMGLATTACHSHADERPROC __rglgen_glAttachShader; extern RGLSYMGLBINDATTRIBLOCATIONPROC __rglgen_glBindAttribLocation; extern RGLSYMGLCOMPILESHADERPROC __rglgen_glCompileShader; extern RGLSYMGLCREATEPROGRAMPROC __rglgen_glCreateProgram; extern RGLSYMGLCREATESHADERPROC __rglgen_glCreateShader; extern RGLSYMGLDELETEPROGRAMPROC __rglgen_glDeleteProgram; extern RGLSYMGLDELETESHADERPROC __rglgen_glDeleteShader; extern RGLSYMGLDETACHSHADERPROC __rglgen_glDetachShader; extern RGLSYMGLDISABLEVERTEXATTRIBARRAYPROC __rglgen_glDisableVertexAttribArray; extern RGLSYMGLENABLEVERTEXATTRIBARRAYPROC __rglgen_glEnableVertexAttribArray; extern RGLSYMGLGETACTIVEATTRIBPROC __rglgen_glGetActiveAttrib; extern RGLSYMGLGETACTIVEUNIFORMPROC __rglgen_glGetActiveUniform; extern RGLSYMGLGETATTACHEDSHADERSPROC __rglgen_glGetAttachedShaders; extern RGLSYMGLGETATTRIBLOCATIONPROC __rglgen_glGetAttribLocation; extern RGLSYMGLGETPROGRAMIVPROC __rglgen_glGetProgramiv; extern RGLSYMGLGETPROGRAMINFOLOGPROC __rglgen_glGetProgramInfoLog; extern RGLSYMGLGETSHADERIVPROC __rglgen_glGetShaderiv; extern RGLSYMGLGETSHADERINFOLOGPROC __rglgen_glGetShaderInfoLog; extern RGLSYMGLGETSHADERSOURCEPROC __rglgen_glGetShaderSource; extern RGLSYMGLGETUNIFORMLOCATIONPROC __rglgen_glGetUniformLocation; extern RGLSYMGLGETUNIFORMFVPROC __rglgen_glGetUniformfv; extern RGLSYMGLGETUNIFORMIVPROC __rglgen_glGetUniformiv; extern RGLSYMGLGETVERTEXATTRIBDVPROC __rglgen_glGetVertexAttribdv; extern RGLSYMGLGETVERTEXATTRIBFVPROC __rglgen_glGetVertexAttribfv; extern RGLSYMGLGETVERTEXATTRIBIVPROC __rglgen_glGetVertexAttribiv; extern RGLSYMGLGETVERTEXATTRIBPOINTERVPROC __rglgen_glGetVertexAttribPointerv; extern RGLSYMGLISPROGRAMPROC __rglgen_glIsProgram; extern RGLSYMGLISSHADERPROC __rglgen_glIsShader; extern RGLSYMGLLINKPROGRAMPROC __rglgen_glLinkProgram; extern RGLSYMGLSHADERSOURCEPROC __rglgen_glShaderSource; extern RGLSYMGLUSEPROGRAMPROC __rglgen_glUseProgram; extern RGLSYMGLUNIFORM1FPROC __rglgen_glUniform1f; extern RGLSYMGLUNIFORM2FPROC __rglgen_glUniform2f; extern RGLSYMGLUNIFORM3FPROC __rglgen_glUniform3f; extern RGLSYMGLUNIFORM4FPROC __rglgen_glUniform4f; extern RGLSYMGLUNIFORM1IPROC __rglgen_glUniform1i; extern RGLSYMGLUNIFORM2IPROC __rglgen_glUniform2i; extern RGLSYMGLUNIFORM3IPROC __rglgen_glUniform3i; extern RGLSYMGLUNIFORM4IPROC __rglgen_glUniform4i; extern RGLSYMGLUNIFORM1FVPROC __rglgen_glUniform1fv; extern RGLSYMGLUNIFORM2FVPROC __rglgen_glUniform2fv; extern RGLSYMGLUNIFORM3FVPROC __rglgen_glUniform3fv; extern RGLSYMGLUNIFORM4FVPROC __rglgen_glUniform4fv; extern RGLSYMGLUNIFORM1IVPROC __rglgen_glUniform1iv; extern RGLSYMGLUNIFORM2IVPROC __rglgen_glUniform2iv; extern RGLSYMGLUNIFORM3IVPROC __rglgen_glUniform3iv; extern RGLSYMGLUNIFORM4IVPROC __rglgen_glUniform4iv; extern RGLSYMGLUNIFORMMATRIX2FVPROC __rglgen_glUniformMatrix2fv; extern RGLSYMGLUNIFORMMATRIX3FVPROC __rglgen_glUniformMatrix3fv; extern RGLSYMGLUNIFORMMATRIX4FVPROC __rglgen_glUniformMatrix4fv; extern RGLSYMGLVALIDATEPROGRAMPROC __rglgen_glValidateProgram; extern RGLSYMGLVERTEXATTRIB1DPROC __rglgen_glVertexAttrib1d; extern RGLSYMGLVERTEXATTRIB1DVPROC __rglgen_glVertexAttrib1dv; extern RGLSYMGLVERTEXATTRIB1FPROC __rglgen_glVertexAttrib1f; extern RGLSYMGLVERTEXATTRIB1FVPROC __rglgen_glVertexAttrib1fv; extern RGLSYMGLVERTEXATTRIB1SPROC __rglgen_glVertexAttrib1s; extern RGLSYMGLVERTEXATTRIB1SVPROC __rglgen_glVertexAttrib1sv; extern RGLSYMGLVERTEXATTRIB2DPROC __rglgen_glVertexAttrib2d; extern RGLSYMGLVERTEXATTRIB2DVPROC __rglgen_glVertexAttrib2dv; extern RGLSYMGLVERTEXATTRIB2FPROC __rglgen_glVertexAttrib2f; extern RGLSYMGLVERTEXATTRIB2FVPROC __rglgen_glVertexAttrib2fv; extern RGLSYMGLVERTEXATTRIB2SPROC __rglgen_glVertexAttrib2s; extern RGLSYMGLVERTEXATTRIB2SVPROC __rglgen_glVertexAttrib2sv; extern RGLSYMGLVERTEXATTRIB3DPROC __rglgen_glVertexAttrib3d; extern RGLSYMGLVERTEXATTRIB3DVPROC __rglgen_glVertexAttrib3dv; extern RGLSYMGLVERTEXATTRIB3FPROC __rglgen_glVertexAttrib3f; extern RGLSYMGLVERTEXATTRIB3FVPROC __rglgen_glVertexAttrib3fv; extern RGLSYMGLVERTEXATTRIB3SPROC __rglgen_glVertexAttrib3s; extern RGLSYMGLVERTEXATTRIB3SVPROC __rglgen_glVertexAttrib3sv; extern RGLSYMGLVERTEXATTRIB4NBVPROC __rglgen_glVertexAttrib4Nbv; extern RGLSYMGLVERTEXATTRIB4NIVPROC __rglgen_glVertexAttrib4Niv; extern RGLSYMGLVERTEXATTRIB4NSVPROC __rglgen_glVertexAttrib4Nsv; extern RGLSYMGLVERTEXATTRIB4NUBPROC __rglgen_glVertexAttrib4Nub; extern RGLSYMGLVERTEXATTRIB4NUBVPROC __rglgen_glVertexAttrib4Nubv; extern RGLSYMGLVERTEXATTRIB4NUIVPROC __rglgen_glVertexAttrib4Nuiv; extern RGLSYMGLVERTEXATTRIB4NUSVPROC __rglgen_glVertexAttrib4Nusv; extern RGLSYMGLVERTEXATTRIB4BVPROC __rglgen_glVertexAttrib4bv; extern RGLSYMGLVERTEXATTRIB4DPROC __rglgen_glVertexAttrib4d; extern RGLSYMGLVERTEXATTRIB4DVPROC __rglgen_glVertexAttrib4dv; extern RGLSYMGLVERTEXATTRIB4FPROC __rglgen_glVertexAttrib4f; extern RGLSYMGLVERTEXATTRIB4FVPROC __rglgen_glVertexAttrib4fv; extern RGLSYMGLVERTEXATTRIB4IVPROC __rglgen_glVertexAttrib4iv; extern RGLSYMGLVERTEXATTRIB4SPROC __rglgen_glVertexAttrib4s; extern RGLSYMGLVERTEXATTRIB4SVPROC __rglgen_glVertexAttrib4sv; extern RGLSYMGLVERTEXATTRIB4UBVPROC __rglgen_glVertexAttrib4ubv; extern RGLSYMGLVERTEXATTRIB4UIVPROC __rglgen_glVertexAttrib4uiv; extern RGLSYMGLVERTEXATTRIB4USVPROC __rglgen_glVertexAttrib4usv; extern RGLSYMGLVERTEXATTRIBPOINTERPROC __rglgen_glVertexAttribPointer; extern RGLSYMGLUNIFORMMATRIX2X3FVPROC __rglgen_glUniformMatrix2x3fv; extern RGLSYMGLUNIFORMMATRIX3X2FVPROC __rglgen_glUniformMatrix3x2fv; extern RGLSYMGLUNIFORMMATRIX2X4FVPROC __rglgen_glUniformMatrix2x4fv; extern RGLSYMGLUNIFORMMATRIX4X2FVPROC __rglgen_glUniformMatrix4x2fv; extern RGLSYMGLUNIFORMMATRIX3X4FVPROC __rglgen_glUniformMatrix3x4fv; extern RGLSYMGLUNIFORMMATRIX4X3FVPROC __rglgen_glUniformMatrix4x3fv; extern RGLSYMGLCOLORMASKIPROC __rglgen_glColorMaski; extern RGLSYMGLGETBOOLEANI_VPROC __rglgen_glGetBooleani_v; extern RGLSYMGLGETINTEGERI_VPROC __rglgen_glGetIntegeri_v; extern RGLSYMGLENABLEIPROC __rglgen_glEnablei; extern RGLSYMGLDISABLEIPROC __rglgen_glDisablei; extern RGLSYMGLISENABLEDIPROC __rglgen_glIsEnabledi; extern RGLSYMGLBEGINTRANSFORMFEEDBACKPROC __rglgen_glBeginTransformFeedback; extern RGLSYMGLENDTRANSFORMFEEDBACKPROC __rglgen_glEndTransformFeedback; extern RGLSYMGLBINDBUFFERRANGEPROC __rglgen_glBindBufferRange; extern RGLSYMGLBINDBUFFERBASEPROC __rglgen_glBindBufferBase; extern RGLSYMGLTRANSFORMFEEDBACKVARYINGSPROC __rglgen_glTransformFeedbackVaryings; extern RGLSYMGLGETTRANSFORMFEEDBACKVARYINGPROC __rglgen_glGetTransformFeedbackVarying; extern RGLSYMGLCLAMPCOLORPROC __rglgen_glClampColor; extern RGLSYMGLBEGINCONDITIONALRENDERPROC __rglgen_glBeginConditionalRender; extern RGLSYMGLENDCONDITIONALRENDERPROC __rglgen_glEndConditionalRender; extern RGLSYMGLVERTEXATTRIBIPOINTERPROC __rglgen_glVertexAttribIPointer; extern RGLSYMGLGETVERTEXATTRIBIIVPROC __rglgen_glGetVertexAttribIiv; extern RGLSYMGLGETVERTEXATTRIBIUIVPROC __rglgen_glGetVertexAttribIuiv; extern RGLSYMGLVERTEXATTRIBI1IPROC __rglgen_glVertexAttribI1i; extern RGLSYMGLVERTEXATTRIBI2IPROC __rglgen_glVertexAttribI2i; extern RGLSYMGLVERTEXATTRIBI3IPROC __rglgen_glVertexAttribI3i; extern RGLSYMGLVERTEXATTRIBI4IPROC __rglgen_glVertexAttribI4i; extern RGLSYMGLVERTEXATTRIBI1UIPROC __rglgen_glVertexAttribI1ui; extern RGLSYMGLVERTEXATTRIBI2UIPROC __rglgen_glVertexAttribI2ui; extern RGLSYMGLVERTEXATTRIBI3UIPROC __rglgen_glVertexAttribI3ui; extern RGLSYMGLVERTEXATTRIBI4UIPROC __rglgen_glVertexAttribI4ui; extern RGLSYMGLVERTEXATTRIBI1IVPROC __rglgen_glVertexAttribI1iv; extern RGLSYMGLVERTEXATTRIBI2IVPROC __rglgen_glVertexAttribI2iv; extern RGLSYMGLVERTEXATTRIBI3IVPROC __rglgen_glVertexAttribI3iv; extern RGLSYMGLVERTEXATTRIBI4IVPROC __rglgen_glVertexAttribI4iv; extern RGLSYMGLVERTEXATTRIBI1UIVPROC __rglgen_glVertexAttribI1uiv; extern RGLSYMGLVERTEXATTRIBI2UIVPROC __rglgen_glVertexAttribI2uiv; extern RGLSYMGLVERTEXATTRIBI3UIVPROC __rglgen_glVertexAttribI3uiv; extern RGLSYMGLVERTEXATTRIBI4UIVPROC __rglgen_glVertexAttribI4uiv; extern RGLSYMGLVERTEXATTRIBI4BVPROC __rglgen_glVertexAttribI4bv; extern RGLSYMGLVERTEXATTRIBI4SVPROC __rglgen_glVertexAttribI4sv; extern RGLSYMGLVERTEXATTRIBI4UBVPROC __rglgen_glVertexAttribI4ubv; extern RGLSYMGLVERTEXATTRIBI4USVPROC __rglgen_glVertexAttribI4usv; extern RGLSYMGLGETUNIFORMUIVPROC __rglgen_glGetUniformuiv; extern RGLSYMGLBINDFRAGDATALOCATIONPROC __rglgen_glBindFragDataLocation; extern RGLSYMGLGETFRAGDATALOCATIONPROC __rglgen_glGetFragDataLocation; extern RGLSYMGLUNIFORM1UIPROC __rglgen_glUniform1ui; extern RGLSYMGLUNIFORM2UIPROC __rglgen_glUniform2ui; extern RGLSYMGLUNIFORM3UIPROC __rglgen_glUniform3ui; extern RGLSYMGLUNIFORM4UIPROC __rglgen_glUniform4ui; extern RGLSYMGLUNIFORM1UIVPROC __rglgen_glUniform1uiv; extern RGLSYMGLUNIFORM2UIVPROC __rglgen_glUniform2uiv; extern RGLSYMGLUNIFORM3UIVPROC __rglgen_glUniform3uiv; extern RGLSYMGLUNIFORM4UIVPROC __rglgen_glUniform4uiv; extern RGLSYMGLTEXPARAMETERIIVPROC __rglgen_glTexParameterIiv; extern RGLSYMGLTEXPARAMETERIUIVPROC __rglgen_glTexParameterIuiv; extern RGLSYMGLGETTEXPARAMETERIIVPROC __rglgen_glGetTexParameterIiv; extern RGLSYMGLGETTEXPARAMETERIUIVPROC __rglgen_glGetTexParameterIuiv; extern RGLSYMGLCLEARBUFFERIVPROC __rglgen_glClearBufferiv; extern RGLSYMGLCLEARBUFFERUIVPROC __rglgen_glClearBufferuiv; extern RGLSYMGLCLEARBUFFERFVPROC __rglgen_glClearBufferfv; extern RGLSYMGLCLEARBUFFERFIPROC __rglgen_glClearBufferfi; extern RGLSYMGLGETSTRINGIPROC __rglgen_glGetStringi; extern RGLSYMGLISRENDERBUFFERPROC __rglgen_glIsRenderbuffer; extern RGLSYMGLBINDRENDERBUFFERPROC __rglgen_glBindRenderbuffer; extern RGLSYMGLDELETERENDERBUFFERSPROC __rglgen_glDeleteRenderbuffers; extern RGLSYMGLGENRENDERBUFFERSPROC __rglgen_glGenRenderbuffers; extern RGLSYMGLRENDERBUFFERSTORAGEPROC __rglgen_glRenderbufferStorage; extern RGLSYMGLGETRENDERBUFFERPARAMETERIVPROC __rglgen_glGetRenderbufferParameteriv; extern RGLSYMGLISFRAMEBUFFERPROC __rglgen_glIsFramebuffer; extern RGLSYMGLBINDFRAMEBUFFERPROC __rglgen_glBindFramebuffer; extern RGLSYMGLDELETEFRAMEBUFFERSPROC __rglgen_glDeleteFramebuffers; extern RGLSYMGLGENFRAMEBUFFERSPROC __rglgen_glGenFramebuffers; extern RGLSYMGLCHECKFRAMEBUFFERSTATUSPROC __rglgen_glCheckFramebufferStatus; extern RGLSYMGLFRAMEBUFFERTEXTURE1DPROC __rglgen_glFramebufferTexture1D; extern RGLSYMGLFRAMEBUFFERTEXTURE2DPROC __rglgen_glFramebufferTexture2D; extern RGLSYMGLFRAMEBUFFERTEXTURE3DPROC __rglgen_glFramebufferTexture3D; extern RGLSYMGLFRAMEBUFFERRENDERBUFFERPROC __rglgen_glFramebufferRenderbuffer; extern RGLSYMGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC __rglgen_glGetFramebufferAttachmentParameteriv; extern RGLSYMGLGENERATEMIPMAPPROC __rglgen_glGenerateMipmap; extern RGLSYMGLBLITFRAMEBUFFERPROC __rglgen_glBlitFramebuffer; extern RGLSYMGLRENDERBUFFERSTORAGEMULTISAMPLEPROC __rglgen_glRenderbufferStorageMultisample; extern RGLSYMGLFRAMEBUFFERTEXTURELAYERPROC __rglgen_glFramebufferTextureLayer; extern RGLSYMGLMAPBUFFERRANGEPROC __rglgen_glMapBufferRange; extern RGLSYMGLFLUSHMAPPEDBUFFERRANGEPROC __rglgen_glFlushMappedBufferRange; extern RGLSYMGLBINDVERTEXARRAYPROC __rglgen_glBindVertexArray; extern RGLSYMGLDELETEVERTEXARRAYSPROC __rglgen_glDeleteVertexArrays; extern RGLSYMGLGENVERTEXARRAYSPROC __rglgen_glGenVertexArrays; extern RGLSYMGLISVERTEXARRAYPROC __rglgen_glIsVertexArray; extern RGLSYMGLDRAWARRAYSINSTANCEDPROC __rglgen_glDrawArraysInstanced; extern RGLSYMGLDRAWELEMENTSINSTANCEDPROC __rglgen_glDrawElementsInstanced; extern RGLSYMGLTEXBUFFERPROC __rglgen_glTexBuffer; extern RGLSYMGLPRIMITIVERESTARTINDEXPROC __rglgen_glPrimitiveRestartIndex; extern RGLSYMGLCOPYBUFFERSUBDATAPROC __rglgen_glCopyBufferSubData; extern RGLSYMGLGETUNIFORMINDICESPROC __rglgen_glGetUniformIndices; extern RGLSYMGLGETACTIVEUNIFORMSIVPROC __rglgen_glGetActiveUniformsiv; extern RGLSYMGLGETACTIVEUNIFORMNAMEPROC __rglgen_glGetActiveUniformName; extern RGLSYMGLGETUNIFORMBLOCKINDEXPROC __rglgen_glGetUniformBlockIndex; extern RGLSYMGLGETACTIVEUNIFORMBLOCKIVPROC __rglgen_glGetActiveUniformBlockiv; extern RGLSYMGLGETACTIVEUNIFORMBLOCKNAMEPROC __rglgen_glGetActiveUniformBlockName; extern RGLSYMGLUNIFORMBLOCKBINDINGPROC __rglgen_glUniformBlockBinding; extern RGLSYMGLDRAWELEMENTSBASEVERTEXPROC __rglgen_glDrawElementsBaseVertex; extern RGLSYMGLDRAWRANGEELEMENTSBASEVERTEXPROC __rglgen_glDrawRangeElementsBaseVertex; extern RGLSYMGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC __rglgen_glDrawElementsInstancedBaseVertex; extern RGLSYMGLMULTIDRAWELEMENTSBASEVERTEXPROC __rglgen_glMultiDrawElementsBaseVertex; extern RGLSYMGLPROVOKINGVERTEXPROC __rglgen_glProvokingVertex; extern RGLSYMGLFENCESYNCPROC __rglgen_glFenceSync; extern RGLSYMGLISSYNCPROC __rglgen_glIsSync; extern RGLSYMGLDELETESYNCPROC __rglgen_glDeleteSync; extern RGLSYMGLCLIENTWAITSYNCPROC __rglgen_glClientWaitSync; extern RGLSYMGLWAITSYNCPROC __rglgen_glWaitSync; extern RGLSYMGLGETINTEGER64VPROC __rglgen_glGetInteger64v; extern RGLSYMGLGETSYNCIVPROC __rglgen_glGetSynciv; extern RGLSYMGLGETINTEGER64I_VPROC __rglgen_glGetInteger64i_v; extern RGLSYMGLGETBUFFERPARAMETERI64VPROC __rglgen_glGetBufferParameteri64v; extern RGLSYMGLFRAMEBUFFERTEXTUREPROC __rglgen_glFramebufferTexture; extern RGLSYMGLTEXIMAGE2DMULTISAMPLEPROC __rglgen_glTexImage2DMultisample; extern RGLSYMGLTEXIMAGE3DMULTISAMPLEPROC __rglgen_glTexImage3DMultisample; extern RGLSYMGLGETMULTISAMPLEFVPROC __rglgen_glGetMultisamplefv; extern RGLSYMGLSAMPLEMASKIPROC __rglgen_glSampleMaski; extern RGLSYMGLBINDFRAGDATALOCATIONINDEXEDPROC __rglgen_glBindFragDataLocationIndexed; extern RGLSYMGLGETFRAGDATAINDEXPROC __rglgen_glGetFragDataIndex; extern RGLSYMGLGENSAMPLERSPROC __rglgen_glGenSamplers; extern RGLSYMGLDELETESAMPLERSPROC __rglgen_glDeleteSamplers; extern RGLSYMGLISSAMPLERPROC __rglgen_glIsSampler; extern RGLSYMGLBINDSAMPLERPROC __rglgen_glBindSampler; extern RGLSYMGLSAMPLERPARAMETERIPROC __rglgen_glSamplerParameteri; extern RGLSYMGLSAMPLERPARAMETERIVPROC __rglgen_glSamplerParameteriv; extern RGLSYMGLSAMPLERPARAMETERFPROC __rglgen_glSamplerParameterf; extern RGLSYMGLSAMPLERPARAMETERFVPROC __rglgen_glSamplerParameterfv; extern RGLSYMGLSAMPLERPARAMETERIIVPROC __rglgen_glSamplerParameterIiv; extern RGLSYMGLSAMPLERPARAMETERIUIVPROC __rglgen_glSamplerParameterIuiv; extern RGLSYMGLGETSAMPLERPARAMETERIVPROC __rglgen_glGetSamplerParameteriv; extern RGLSYMGLGETSAMPLERPARAMETERIIVPROC __rglgen_glGetSamplerParameterIiv; extern RGLSYMGLGETSAMPLERPARAMETERFVPROC __rglgen_glGetSamplerParameterfv; extern RGLSYMGLGETSAMPLERPARAMETERIUIVPROC __rglgen_glGetSamplerParameterIuiv; extern RGLSYMGLQUERYCOUNTERPROC __rglgen_glQueryCounter; extern RGLSYMGLGETQUERYOBJECTI64VPROC __rglgen_glGetQueryObjecti64v; extern RGLSYMGLGETQUERYOBJECTUI64VPROC __rglgen_glGetQueryObjectui64v; extern RGLSYMGLVERTEXATTRIBDIVISORPROC __rglgen_glVertexAttribDivisor; extern RGLSYMGLVERTEXATTRIBP1UIPROC __rglgen_glVertexAttribP1ui; extern RGLSYMGLVERTEXATTRIBP1UIVPROC __rglgen_glVertexAttribP1uiv; extern RGLSYMGLVERTEXATTRIBP2UIPROC __rglgen_glVertexAttribP2ui; extern RGLSYMGLVERTEXATTRIBP2UIVPROC __rglgen_glVertexAttribP2uiv; extern RGLSYMGLVERTEXATTRIBP3UIPROC __rglgen_glVertexAttribP3ui; extern RGLSYMGLVERTEXATTRIBP3UIVPROC __rglgen_glVertexAttribP3uiv; extern RGLSYMGLVERTEXATTRIBP4UIPROC __rglgen_glVertexAttribP4ui; extern RGLSYMGLVERTEXATTRIBP4UIVPROC __rglgen_glVertexAttribP4uiv; extern RGLSYMGLVERTEXP2UIPROC __rglgen_glVertexP2ui; extern RGLSYMGLVERTEXP2UIVPROC __rglgen_glVertexP2uiv; extern RGLSYMGLVERTEXP3UIPROC __rglgen_glVertexP3ui; extern RGLSYMGLVERTEXP3UIVPROC __rglgen_glVertexP3uiv; extern RGLSYMGLVERTEXP4UIPROC __rglgen_glVertexP4ui; extern RGLSYMGLVERTEXP4UIVPROC __rglgen_glVertexP4uiv; extern RGLSYMGLTEXCOORDP1UIPROC __rglgen_glTexCoordP1ui; extern RGLSYMGLTEXCOORDP1UIVPROC __rglgen_glTexCoordP1uiv; extern RGLSYMGLTEXCOORDP2UIPROC __rglgen_glTexCoordP2ui; extern RGLSYMGLTEXCOORDP2UIVPROC __rglgen_glTexCoordP2uiv; extern RGLSYMGLTEXCOORDP3UIPROC __rglgen_glTexCoordP3ui; extern RGLSYMGLTEXCOORDP3UIVPROC __rglgen_glTexCoordP3uiv; extern RGLSYMGLTEXCOORDP4UIPROC __rglgen_glTexCoordP4ui; extern RGLSYMGLTEXCOORDP4UIVPROC __rglgen_glTexCoordP4uiv; extern RGLSYMGLMULTITEXCOORDP1UIPROC __rglgen_glMultiTexCoordP1ui; extern RGLSYMGLMULTITEXCOORDP1UIVPROC __rglgen_glMultiTexCoordP1uiv; extern RGLSYMGLMULTITEXCOORDP2UIPROC __rglgen_glMultiTexCoordP2ui; extern RGLSYMGLMULTITEXCOORDP2UIVPROC __rglgen_glMultiTexCoordP2uiv; extern RGLSYMGLMULTITEXCOORDP3UIPROC __rglgen_glMultiTexCoordP3ui; extern RGLSYMGLMULTITEXCOORDP3UIVPROC __rglgen_glMultiTexCoordP3uiv; extern RGLSYMGLMULTITEXCOORDP4UIPROC __rglgen_glMultiTexCoordP4ui; extern RGLSYMGLMULTITEXCOORDP4UIVPROC __rglgen_glMultiTexCoordP4uiv; extern RGLSYMGLNORMALP3UIPROC __rglgen_glNormalP3ui; extern RGLSYMGLNORMALP3UIVPROC __rglgen_glNormalP3uiv; extern RGLSYMGLCOLORP3UIPROC __rglgen_glColorP3ui; extern RGLSYMGLCOLORP3UIVPROC __rglgen_glColorP3uiv; extern RGLSYMGLCOLORP4UIPROC __rglgen_glColorP4ui; extern RGLSYMGLCOLORP4UIVPROC __rglgen_glColorP4uiv; extern RGLSYMGLSECONDARYCOLORP3UIPROC __rglgen_glSecondaryColorP3ui; extern RGLSYMGLSECONDARYCOLORP3UIVPROC __rglgen_glSecondaryColorP3uiv; extern RGLSYMGLMINSAMPLESHADINGPROC __rglgen_glMinSampleShading; extern RGLSYMGLBLENDEQUATIONIPROC __rglgen_glBlendEquationi; extern RGLSYMGLBLENDEQUATIONSEPARATEIPROC __rglgen_glBlendEquationSeparatei; extern RGLSYMGLBLENDFUNCIPROC __rglgen_glBlendFunci; extern RGLSYMGLBLENDFUNCSEPARATEIPROC __rglgen_glBlendFuncSeparatei; extern RGLSYMGLDRAWARRAYSINDIRECTPROC __rglgen_glDrawArraysIndirect; extern RGLSYMGLDRAWELEMENTSINDIRECTPROC __rglgen_glDrawElementsIndirect; extern RGLSYMGLUNIFORM1DPROC __rglgen_glUniform1d; extern RGLSYMGLUNIFORM2DPROC __rglgen_glUniform2d; extern RGLSYMGLUNIFORM3DPROC __rglgen_glUniform3d; extern RGLSYMGLUNIFORM4DPROC __rglgen_glUniform4d; extern RGLSYMGLUNIFORM1DVPROC __rglgen_glUniform1dv; extern RGLSYMGLUNIFORM2DVPROC __rglgen_glUniform2dv; extern RGLSYMGLUNIFORM3DVPROC __rglgen_glUniform3dv; extern RGLSYMGLUNIFORM4DVPROC __rglgen_glUniform4dv; extern RGLSYMGLUNIFORMMATRIX2DVPROC __rglgen_glUniformMatrix2dv; extern RGLSYMGLUNIFORMMATRIX3DVPROC __rglgen_glUniformMatrix3dv; extern RGLSYMGLUNIFORMMATRIX4DVPROC __rglgen_glUniformMatrix4dv; extern RGLSYMGLUNIFORMMATRIX2X3DVPROC __rglgen_glUniformMatrix2x3dv; extern RGLSYMGLUNIFORMMATRIX2X4DVPROC __rglgen_glUniformMatrix2x4dv; extern RGLSYMGLUNIFORMMATRIX3X2DVPROC __rglgen_glUniformMatrix3x2dv; extern RGLSYMGLUNIFORMMATRIX3X4DVPROC __rglgen_glUniformMatrix3x4dv; extern RGLSYMGLUNIFORMMATRIX4X2DVPROC __rglgen_glUniformMatrix4x2dv; extern RGLSYMGLUNIFORMMATRIX4X3DVPROC __rglgen_glUniformMatrix4x3dv; extern RGLSYMGLGETUNIFORMDVPROC __rglgen_glGetUniformdv; extern RGLSYMGLGETSUBROUTINEUNIFORMLOCATIONPROC __rglgen_glGetSubroutineUniformLocation; extern RGLSYMGLGETSUBROUTINEINDEXPROC __rglgen_glGetSubroutineIndex; extern RGLSYMGLGETACTIVESUBROUTINEUNIFORMIVPROC __rglgen_glGetActiveSubroutineUniformiv; extern RGLSYMGLGETACTIVESUBROUTINEUNIFORMNAMEPROC __rglgen_glGetActiveSubroutineUniformName; extern RGLSYMGLGETACTIVESUBROUTINENAMEPROC __rglgen_glGetActiveSubroutineName; extern RGLSYMGLUNIFORMSUBROUTINESUIVPROC __rglgen_glUniformSubroutinesuiv; extern RGLSYMGLGETUNIFORMSUBROUTINEUIVPROC __rglgen_glGetUniformSubroutineuiv; extern RGLSYMGLGETPROGRAMSTAGEIVPROC __rglgen_glGetProgramStageiv; extern RGLSYMGLPATCHPARAMETERIPROC __rglgen_glPatchParameteri; extern RGLSYMGLPATCHPARAMETERFVPROC __rglgen_glPatchParameterfv; extern RGLSYMGLBINDTRANSFORMFEEDBACKPROC __rglgen_glBindTransformFeedback; extern RGLSYMGLDELETETRANSFORMFEEDBACKSPROC __rglgen_glDeleteTransformFeedbacks; extern RGLSYMGLGENTRANSFORMFEEDBACKSPROC __rglgen_glGenTransformFeedbacks; extern RGLSYMGLISTRANSFORMFEEDBACKPROC __rglgen_glIsTransformFeedback; extern RGLSYMGLPAUSETRANSFORMFEEDBACKPROC __rglgen_glPauseTransformFeedback; extern RGLSYMGLRESUMETRANSFORMFEEDBACKPROC __rglgen_glResumeTransformFeedback; extern RGLSYMGLDRAWTRANSFORMFEEDBACKPROC __rglgen_glDrawTransformFeedback; extern RGLSYMGLDRAWTRANSFORMFEEDBACKSTREAMPROC __rglgen_glDrawTransformFeedbackStream; extern RGLSYMGLBEGINQUERYINDEXEDPROC __rglgen_glBeginQueryIndexed; extern RGLSYMGLENDQUERYINDEXEDPROC __rglgen_glEndQueryIndexed; extern RGLSYMGLGETQUERYINDEXEDIVPROC __rglgen_glGetQueryIndexediv; extern RGLSYMGLRELEASESHADERCOMPILERPROC __rglgen_glReleaseShaderCompiler; extern RGLSYMGLSHADERBINARYPROC __rglgen_glShaderBinary; extern RGLSYMGLGETSHADERPRECISIONFORMATPROC __rglgen_glGetShaderPrecisionFormat; extern RGLSYMGLDEPTHRANGEFPROC __rglgen_glDepthRangef; extern RGLSYMGLCLEARDEPTHFPROC __rglgen_glClearDepthf; extern RGLSYMGLGETPROGRAMBINARYPROC __rglgen_glGetProgramBinary; extern RGLSYMGLPROGRAMBINARYPROC __rglgen_glProgramBinary; extern RGLSYMGLPROGRAMPARAMETERIPROC __rglgen_glProgramParameteri; extern RGLSYMGLUSEPROGRAMSTAGESPROC __rglgen_glUseProgramStages; extern RGLSYMGLACTIVESHADERPROGRAMPROC __rglgen_glActiveShaderProgram; extern RGLSYMGLCREATESHADERPROGRAMVPROC __rglgen_glCreateShaderProgramv; extern RGLSYMGLBINDPROGRAMPIPELINEPROC __rglgen_glBindProgramPipeline; extern RGLSYMGLDELETEPROGRAMPIPELINESPROC __rglgen_glDeleteProgramPipelines; extern RGLSYMGLGENPROGRAMPIPELINESPROC __rglgen_glGenProgramPipelines; extern RGLSYMGLISPROGRAMPIPELINEPROC __rglgen_glIsProgramPipeline; extern RGLSYMGLGETPROGRAMPIPELINEIVPROC __rglgen_glGetProgramPipelineiv; extern RGLSYMGLPROGRAMUNIFORM1IPROC __rglgen_glProgramUniform1i; extern RGLSYMGLPROGRAMUNIFORM1IVPROC __rglgen_glProgramUniform1iv; extern RGLSYMGLPROGRAMUNIFORM1FPROC __rglgen_glProgramUniform1f; extern RGLSYMGLPROGRAMUNIFORM1FVPROC __rglgen_glProgramUniform1fv; extern RGLSYMGLPROGRAMUNIFORM1DPROC __rglgen_glProgramUniform1d; extern RGLSYMGLPROGRAMUNIFORM1DVPROC __rglgen_glProgramUniform1dv; extern RGLSYMGLPROGRAMUNIFORM1UIPROC __rglgen_glProgramUniform1ui; extern RGLSYMGLPROGRAMUNIFORM1UIVPROC __rglgen_glProgramUniform1uiv; extern RGLSYMGLPROGRAMUNIFORM2IPROC __rglgen_glProgramUniform2i; extern RGLSYMGLPROGRAMUNIFORM2IVPROC __rglgen_glProgramUniform2iv; extern RGLSYMGLPROGRAMUNIFORM2FPROC __rglgen_glProgramUniform2f; extern RGLSYMGLPROGRAMUNIFORM2FVPROC __rglgen_glProgramUniform2fv; extern RGLSYMGLPROGRAMUNIFORM2DPROC __rglgen_glProgramUniform2d; extern RGLSYMGLPROGRAMUNIFORM2DVPROC __rglgen_glProgramUniform2dv; extern RGLSYMGLPROGRAMUNIFORM2UIPROC __rglgen_glProgramUniform2ui; extern RGLSYMGLPROGRAMUNIFORM2UIVPROC __rglgen_glProgramUniform2uiv; extern RGLSYMGLPROGRAMUNIFORM3IPROC __rglgen_glProgramUniform3i; extern RGLSYMGLPROGRAMUNIFORM3IVPROC __rglgen_glProgramUniform3iv; extern RGLSYMGLPROGRAMUNIFORM3FPROC __rglgen_glProgramUniform3f; extern RGLSYMGLPROGRAMUNIFORM3FVPROC __rglgen_glProgramUniform3fv; extern RGLSYMGLPROGRAMUNIFORM3DPROC __rglgen_glProgramUniform3d; extern RGLSYMGLPROGRAMUNIFORM3DVPROC __rglgen_glProgramUniform3dv; extern RGLSYMGLPROGRAMUNIFORM3UIPROC __rglgen_glProgramUniform3ui; extern RGLSYMGLPROGRAMUNIFORM3UIVPROC __rglgen_glProgramUniform3uiv; extern RGLSYMGLPROGRAMUNIFORM4IPROC __rglgen_glProgramUniform4i; extern RGLSYMGLPROGRAMUNIFORM4IVPROC __rglgen_glProgramUniform4iv; extern RGLSYMGLPROGRAMUNIFORM4FPROC __rglgen_glProgramUniform4f; extern RGLSYMGLPROGRAMUNIFORM4FVPROC __rglgen_glProgramUniform4fv; extern RGLSYMGLPROGRAMUNIFORM4DPROC __rglgen_glProgramUniform4d; extern RGLSYMGLPROGRAMUNIFORM4DVPROC __rglgen_glProgramUniform4dv; extern RGLSYMGLPROGRAMUNIFORM4UIPROC __rglgen_glProgramUniform4ui; extern RGLSYMGLPROGRAMUNIFORM4UIVPROC __rglgen_glProgramUniform4uiv; extern RGLSYMGLPROGRAMUNIFORMMATRIX2FVPROC __rglgen_glProgramUniformMatrix2fv; extern RGLSYMGLPROGRAMUNIFORMMATRIX3FVPROC __rglgen_glProgramUniformMatrix3fv; extern RGLSYMGLPROGRAMUNIFORMMATRIX4FVPROC __rglgen_glProgramUniformMatrix4fv; extern RGLSYMGLPROGRAMUNIFORMMATRIX2DVPROC __rglgen_glProgramUniformMatrix2dv; extern RGLSYMGLPROGRAMUNIFORMMATRIX3DVPROC __rglgen_glProgramUniformMatrix3dv; extern RGLSYMGLPROGRAMUNIFORMMATRIX4DVPROC __rglgen_glProgramUniformMatrix4dv; extern RGLSYMGLPROGRAMUNIFORMMATRIX2X3FVPROC __rglgen_glProgramUniformMatrix2x3fv; extern RGLSYMGLPROGRAMUNIFORMMATRIX3X2FVPROC __rglgen_glProgramUniformMatrix3x2fv; extern RGLSYMGLPROGRAMUNIFORMMATRIX2X4FVPROC __rglgen_glProgramUniformMatrix2x4fv; extern RGLSYMGLPROGRAMUNIFORMMATRIX4X2FVPROC __rglgen_glProgramUniformMatrix4x2fv; extern RGLSYMGLPROGRAMUNIFORMMATRIX3X4FVPROC __rglgen_glProgramUniformMatrix3x4fv; extern RGLSYMGLPROGRAMUNIFORMMATRIX4X3FVPROC __rglgen_glProgramUniformMatrix4x3fv; extern RGLSYMGLPROGRAMUNIFORMMATRIX2X3DVPROC __rglgen_glProgramUniformMatrix2x3dv; extern RGLSYMGLPROGRAMUNIFORMMATRIX3X2DVPROC __rglgen_glProgramUniformMatrix3x2dv; extern RGLSYMGLPROGRAMUNIFORMMATRIX2X4DVPROC __rglgen_glProgramUniformMatrix2x4dv; extern RGLSYMGLPROGRAMUNIFORMMATRIX4X2DVPROC __rglgen_glProgramUniformMatrix4x2dv; extern RGLSYMGLPROGRAMUNIFORMMATRIX3X4DVPROC __rglgen_glProgramUniformMatrix3x4dv; extern RGLSYMGLPROGRAMUNIFORMMATRIX4X3DVPROC __rglgen_glProgramUniformMatrix4x3dv; extern RGLSYMGLVALIDATEPROGRAMPIPELINEPROC __rglgen_glValidateProgramPipeline; extern RGLSYMGLGETPROGRAMPIPELINEINFOLOGPROC __rglgen_glGetProgramPipelineInfoLog; extern RGLSYMGLVERTEXATTRIBL1DPROC __rglgen_glVertexAttribL1d; extern RGLSYMGLVERTEXATTRIBL2DPROC __rglgen_glVertexAttribL2d; extern RGLSYMGLVERTEXATTRIBL3DPROC __rglgen_glVertexAttribL3d; extern RGLSYMGLVERTEXATTRIBL4DPROC __rglgen_glVertexAttribL4d; extern RGLSYMGLVERTEXATTRIBL1DVPROC __rglgen_glVertexAttribL1dv; extern RGLSYMGLVERTEXATTRIBL2DVPROC __rglgen_glVertexAttribL2dv; extern RGLSYMGLVERTEXATTRIBL3DVPROC __rglgen_glVertexAttribL3dv; extern RGLSYMGLVERTEXATTRIBL4DVPROC __rglgen_glVertexAttribL4dv; extern RGLSYMGLVERTEXATTRIBLPOINTERPROC __rglgen_glVertexAttribLPointer; extern RGLSYMGLGETVERTEXATTRIBLDVPROC __rglgen_glGetVertexAttribLdv; extern RGLSYMGLVIEWPORTARRAYVPROC __rglgen_glViewportArrayv; extern RGLSYMGLVIEWPORTINDEXEDFPROC __rglgen_glViewportIndexedf; extern RGLSYMGLVIEWPORTINDEXEDFVPROC __rglgen_glViewportIndexedfv; extern RGLSYMGLSCISSORARRAYVPROC __rglgen_glScissorArrayv; extern RGLSYMGLSCISSORINDEXEDPROC __rglgen_glScissorIndexed; extern RGLSYMGLSCISSORINDEXEDVPROC __rglgen_glScissorIndexedv; extern RGLSYMGLDEPTHRANGEARRAYVPROC __rglgen_glDepthRangeArrayv; extern RGLSYMGLDEPTHRANGEINDEXEDPROC __rglgen_glDepthRangeIndexed; extern RGLSYMGLGETFLOATI_VPROC __rglgen_glGetFloati_v; extern RGLSYMGLGETDOUBLEI_VPROC __rglgen_glGetDoublei_v; extern RGLSYMGLDRAWARRAYSINSTANCEDBASEINSTANCEPROC __rglgen_glDrawArraysInstancedBaseInstance; extern RGLSYMGLDRAWELEMENTSINSTANCEDBASEINSTANCEPROC __rglgen_glDrawElementsInstancedBaseInstance; extern RGLSYMGLDRAWELEMENTSINSTANCEDBASEVERTEXBASEINSTANCEPROC __rglgen_glDrawElementsInstancedBaseVertexBaseInstance; extern RGLSYMGLGETINTERNALFORMATIVPROC __rglgen_glGetInternalformativ; extern RGLSYMGLGETACTIVEATOMICCOUNTERBUFFERIVPROC __rglgen_glGetActiveAtomicCounterBufferiv; extern RGLSYMGLBINDIMAGETEXTUREPROC __rglgen_glBindImageTexture; extern RGLSYMGLMEMORYBARRIERPROC __rglgen_glMemoryBarrier; extern RGLSYMGLTEXSTORAGE1DPROC __rglgen_glTexStorage1D; extern RGLSYMGLTEXSTORAGE2DPROC __rglgen_glTexStorage2D; extern RGLSYMGLTEXSTORAGE3DPROC __rglgen_glTexStorage3D; extern RGLSYMGLDRAWTRANSFORMFEEDBACKINSTANCEDPROC __rglgen_glDrawTransformFeedbackInstanced; extern RGLSYMGLDRAWTRANSFORMFEEDBACKSTREAMINSTANCEDPROC __rglgen_glDrawTransformFeedbackStreamInstanced; extern RGLSYMGLCLEARBUFFERDATAPROC __rglgen_glClearBufferData; extern RGLSYMGLCLEARBUFFERSUBDATAPROC __rglgen_glClearBufferSubData; extern RGLSYMGLDISPATCHCOMPUTEPROC __rglgen_glDispatchCompute; extern RGLSYMGLDISPATCHCOMPUTEINDIRECTPROC __rglgen_glDispatchComputeIndirect; extern RGLSYMGLCOPYIMAGESUBDATAPROC __rglgen_glCopyImageSubData; extern RGLSYMGLFRAMEBUFFERPARAMETERIPROC __rglgen_glFramebufferParameteri; extern RGLSYMGLGETFRAMEBUFFERPARAMETERIVPROC __rglgen_glGetFramebufferParameteriv; extern RGLSYMGLGETINTERNALFORMATI64VPROC __rglgen_glGetInternalformati64v; extern RGLSYMGLINVALIDATETEXSUBIMAGEPROC __rglgen_glInvalidateTexSubImage; extern RGLSYMGLINVALIDATETEXIMAGEPROC __rglgen_glInvalidateTexImage; extern RGLSYMGLINVALIDATEBUFFERSUBDATAPROC __rglgen_glInvalidateBufferSubData; extern RGLSYMGLINVALIDATEBUFFERDATAPROC __rglgen_glInvalidateBufferData; extern RGLSYMGLINVALIDATEFRAMEBUFFERPROC __rglgen_glInvalidateFramebuffer; extern RGLSYMGLINVALIDATESUBFRAMEBUFFERPROC __rglgen_glInvalidateSubFramebuffer; extern RGLSYMGLMULTIDRAWARRAYSINDIRECTPROC __rglgen_glMultiDrawArraysIndirect; extern RGLSYMGLMULTIDRAWELEMENTSINDIRECTPROC __rglgen_glMultiDrawElementsIndirect; extern RGLSYMGLGETPROGRAMINTERFACEIVPROC __rglgen_glGetProgramInterfaceiv; extern RGLSYMGLGETPROGRAMRESOURCEINDEXPROC __rglgen_glGetProgramResourceIndex; extern RGLSYMGLGETPROGRAMRESOURCENAMEPROC __rglgen_glGetProgramResourceName; extern RGLSYMGLGETPROGRAMRESOURCEIVPROC __rglgen_glGetProgramResourceiv; extern RGLSYMGLGETPROGRAMRESOURCELOCATIONPROC __rglgen_glGetProgramResourceLocation; extern RGLSYMGLGETPROGRAMRESOURCELOCATIONINDEXPROC __rglgen_glGetProgramResourceLocationIndex; extern RGLSYMGLSHADERSTORAGEBLOCKBINDINGPROC __rglgen_glShaderStorageBlockBinding; extern RGLSYMGLTEXBUFFERRANGEPROC __rglgen_glTexBufferRange; extern RGLSYMGLTEXSTORAGE2DMULTISAMPLEPROC __rglgen_glTexStorage2DMultisample; extern RGLSYMGLTEXSTORAGE3DMULTISAMPLEPROC __rglgen_glTexStorage3DMultisample; extern RGLSYMGLTEXTUREVIEWPROC __rglgen_glTextureView; extern RGLSYMGLBINDVERTEXBUFFERPROC __rglgen_glBindVertexBuffer; extern RGLSYMGLVERTEXATTRIBFORMATPROC __rglgen_glVertexAttribFormat; extern RGLSYMGLVERTEXATTRIBIFORMATPROC __rglgen_glVertexAttribIFormat; extern RGLSYMGLVERTEXATTRIBLFORMATPROC __rglgen_glVertexAttribLFormat; extern RGLSYMGLVERTEXATTRIBBINDINGPROC __rglgen_glVertexAttribBinding; extern RGLSYMGLVERTEXBINDINGDIVISORPROC __rglgen_glVertexBindingDivisor; extern RGLSYMGLDEBUGMESSAGECONTROLPROC __rglgen_glDebugMessageControl; extern RGLSYMGLDEBUGMESSAGEINSERTPROC __rglgen_glDebugMessageInsert; extern RGLSYMGLDEBUGMESSAGECALLBACKPROC __rglgen_glDebugMessageCallback; extern RGLSYMGLGETDEBUGMESSAGELOGPROC __rglgen_glGetDebugMessageLog; extern RGLSYMGLPUSHDEBUGGROUPPROC __rglgen_glPushDebugGroup; extern RGLSYMGLPOPDEBUGGROUPPROC __rglgen_glPopDebugGroup; extern RGLSYMGLOBJECTLABELPROC __rglgen_glObjectLabel; extern RGLSYMGLGETOBJECTLABELPROC __rglgen_glGetObjectLabel; extern RGLSYMGLOBJECTPTRLABELPROC __rglgen_glObjectPtrLabel; extern RGLSYMGLGETOBJECTPTRLABELPROC __rglgen_glGetObjectPtrLabel; extern RGLSYMGLBUFFERSTORAGEPROC __rglgen_glBufferStorage; extern RGLSYMGLCLEARTEXIMAGEPROC __rglgen_glClearTexImage; extern RGLSYMGLCLEARTEXSUBIMAGEPROC __rglgen_glClearTexSubImage; extern RGLSYMGLBINDBUFFERSBASEPROC __rglgen_glBindBuffersBase; extern RGLSYMGLBINDBUFFERSRANGEPROC __rglgen_glBindBuffersRange; extern RGLSYMGLBINDTEXTURESPROC __rglgen_glBindTextures; extern RGLSYMGLBINDSAMPLERSPROC __rglgen_glBindSamplers; extern RGLSYMGLBINDIMAGETEXTURESPROC __rglgen_glBindImageTextures; extern RGLSYMGLBINDVERTEXBUFFERSPROC __rglgen_glBindVertexBuffers; extern RGLSYMGLGETTEXTUREHANDLEARBPROC __rglgen_glGetTextureHandleARB; extern RGLSYMGLGETTEXTURESAMPLERHANDLEARBPROC __rglgen_glGetTextureSamplerHandleARB; extern RGLSYMGLMAKETEXTUREHANDLERESIDENTARBPROC __rglgen_glMakeTextureHandleResidentARB; extern RGLSYMGLMAKETEXTUREHANDLENONRESIDENTARBPROC __rglgen_glMakeTextureHandleNonResidentARB; extern RGLSYMGLGETIMAGEHANDLEARBPROC __rglgen_glGetImageHandleARB; extern RGLSYMGLMAKEIMAGEHANDLERESIDENTARBPROC __rglgen_glMakeImageHandleResidentARB; extern RGLSYMGLMAKEIMAGEHANDLENONRESIDENTARBPROC __rglgen_glMakeImageHandleNonResidentARB; extern RGLSYMGLUNIFORMHANDLEUI64ARBPROC __rglgen_glUniformHandleui64ARB; extern RGLSYMGLUNIFORMHANDLEUI64VARBPROC __rglgen_glUniformHandleui64vARB; extern RGLSYMGLPROGRAMUNIFORMHANDLEUI64ARBPROC __rglgen_glProgramUniformHandleui64ARB; extern RGLSYMGLPROGRAMUNIFORMHANDLEUI64VARBPROC __rglgen_glProgramUniformHandleui64vARB; extern RGLSYMGLISTEXTUREHANDLERESIDENTARBPROC __rglgen_glIsTextureHandleResidentARB; extern RGLSYMGLISIMAGEHANDLERESIDENTARBPROC __rglgen_glIsImageHandleResidentARB; extern RGLSYMGLVERTEXATTRIBL1UI64ARBPROC __rglgen_glVertexAttribL1ui64ARB; extern RGLSYMGLVERTEXATTRIBL1UI64VARBPROC __rglgen_glVertexAttribL1ui64vARB; extern RGLSYMGLGETVERTEXATTRIBLUI64VARBPROC __rglgen_glGetVertexAttribLui64vARB; extern RGLSYMGLCREATESYNCFROMCLEVENTARBPROC __rglgen_glCreateSyncFromCLeventARB; extern RGLSYMGLCLAMPCOLORARBPROC __rglgen_glClampColorARB; extern RGLSYMGLDISPATCHCOMPUTEGROUPSIZEARBPROC __rglgen_glDispatchComputeGroupSizeARB; extern RGLSYMGLDEBUGMESSAGECONTROLARBPROC __rglgen_glDebugMessageControlARB; extern RGLSYMGLDEBUGMESSAGEINSERTARBPROC __rglgen_glDebugMessageInsertARB; extern RGLSYMGLDEBUGMESSAGECALLBACKARBPROC __rglgen_glDebugMessageCallbackARB; extern RGLSYMGLGETDEBUGMESSAGELOGARBPROC __rglgen_glGetDebugMessageLogARB; extern RGLSYMGLDRAWBUFFERSARBPROC __rglgen_glDrawBuffersARB; extern RGLSYMGLBLENDEQUATIONIARBPROC __rglgen_glBlendEquationiARB; extern RGLSYMGLBLENDEQUATIONSEPARATEIARBPROC __rglgen_glBlendEquationSeparateiARB; extern RGLSYMGLBLENDFUNCIARBPROC __rglgen_glBlendFunciARB; extern RGLSYMGLBLENDFUNCSEPARATEIARBPROC __rglgen_glBlendFuncSeparateiARB; extern RGLSYMGLDRAWARRAYSINSTANCEDARBPROC __rglgen_glDrawArraysInstancedARB; extern RGLSYMGLDRAWELEMENTSINSTANCEDARBPROC __rglgen_glDrawElementsInstancedARB; extern RGLSYMGLPROGRAMSTRINGARBPROC __rglgen_glProgramStringARB; extern RGLSYMGLBINDPROGRAMARBPROC __rglgen_glBindProgramARB; extern RGLSYMGLDELETEPROGRAMSARBPROC __rglgen_glDeleteProgramsARB; extern RGLSYMGLGENPROGRAMSARBPROC __rglgen_glGenProgramsARB; extern RGLSYMGLPROGRAMENVPARAMETER4DARBPROC __rglgen_glProgramEnvParameter4dARB; extern RGLSYMGLPROGRAMENVPARAMETER4DVARBPROC __rglgen_glProgramEnvParameter4dvARB; extern RGLSYMGLPROGRAMENVPARAMETER4FARBPROC __rglgen_glProgramEnvParameter4fARB; extern RGLSYMGLPROGRAMENVPARAMETER4FVARBPROC __rglgen_glProgramEnvParameter4fvARB; extern RGLSYMGLPROGRAMLOCALPARAMETER4DARBPROC __rglgen_glProgramLocalParameter4dARB; extern RGLSYMGLPROGRAMLOCALPARAMETER4DVARBPROC __rglgen_glProgramLocalParameter4dvARB; extern RGLSYMGLPROGRAMLOCALPARAMETER4FARBPROC __rglgen_glProgramLocalParameter4fARB; extern RGLSYMGLPROGRAMLOCALPARAMETER4FVARBPROC __rglgen_glProgramLocalParameter4fvARB; extern RGLSYMGLGETPROGRAMENVPARAMETERDVARBPROC __rglgen_glGetProgramEnvParameterdvARB; extern RGLSYMGLGETPROGRAMENVPARAMETERFVARBPROC __rglgen_glGetProgramEnvParameterfvARB; extern RGLSYMGLGETPROGRAMLOCALPARAMETERDVARBPROC __rglgen_glGetProgramLocalParameterdvARB; extern RGLSYMGLGETPROGRAMLOCALPARAMETERFVARBPROC __rglgen_glGetProgramLocalParameterfvARB; extern RGLSYMGLGETPROGRAMIVARBPROC __rglgen_glGetProgramivARB; extern RGLSYMGLGETPROGRAMSTRINGARBPROC __rglgen_glGetProgramStringARB; extern RGLSYMGLISPROGRAMARBPROC __rglgen_glIsProgramARB; extern RGLSYMGLPROGRAMPARAMETERIARBPROC __rglgen_glProgramParameteriARB; extern RGLSYMGLFRAMEBUFFERTEXTUREARBPROC __rglgen_glFramebufferTextureARB; extern RGLSYMGLFRAMEBUFFERTEXTURELAYERARBPROC __rglgen_glFramebufferTextureLayerARB; extern RGLSYMGLFRAMEBUFFERTEXTUREFACEARBPROC __rglgen_glFramebufferTextureFaceARB; extern RGLSYMGLCOLORTABLEPROC __rglgen_glColorTable; extern RGLSYMGLCOLORTABLEPARAMETERFVPROC __rglgen_glColorTableParameterfv; extern RGLSYMGLCOLORTABLEPARAMETERIVPROC __rglgen_glColorTableParameteriv; extern RGLSYMGLCOPYCOLORTABLEPROC __rglgen_glCopyColorTable; extern RGLSYMGLGETCOLORTABLEPROC __rglgen_glGetColorTable; extern RGLSYMGLGETCOLORTABLEPARAMETERFVPROC __rglgen_glGetColorTableParameterfv; extern RGLSYMGLGETCOLORTABLEPARAMETERIVPROC __rglgen_glGetColorTableParameteriv; extern RGLSYMGLCOLORSUBTABLEPROC __rglgen_glColorSubTable; extern RGLSYMGLCOPYCOLORSUBTABLEPROC __rglgen_glCopyColorSubTable; extern RGLSYMGLCONVOLUTIONFILTER1DPROC __rglgen_glConvolutionFilter1D; extern RGLSYMGLCONVOLUTIONFILTER2DPROC __rglgen_glConvolutionFilter2D; extern RGLSYMGLCONVOLUTIONPARAMETERFPROC __rglgen_glConvolutionParameterf; extern RGLSYMGLCONVOLUTIONPARAMETERFVPROC __rglgen_glConvolutionParameterfv; extern RGLSYMGLCONVOLUTIONPARAMETERIPROC __rglgen_glConvolutionParameteri; extern RGLSYMGLCONVOLUTIONPARAMETERIVPROC __rglgen_glConvolutionParameteriv; extern RGLSYMGLCOPYCONVOLUTIONFILTER1DPROC __rglgen_glCopyConvolutionFilter1D; extern RGLSYMGLCOPYCONVOLUTIONFILTER2DPROC __rglgen_glCopyConvolutionFilter2D; extern RGLSYMGLGETCONVOLUTIONFILTERPROC __rglgen_glGetConvolutionFilter; extern RGLSYMGLGETCONVOLUTIONPARAMETERFVPROC __rglgen_glGetConvolutionParameterfv; extern RGLSYMGLGETCONVOLUTIONPARAMETERIVPROC __rglgen_glGetConvolutionParameteriv; extern RGLSYMGLGETSEPARABLEFILTERPROC __rglgen_glGetSeparableFilter; extern RGLSYMGLSEPARABLEFILTER2DPROC __rglgen_glSeparableFilter2D; extern RGLSYMGLGETHISTOGRAMPROC __rglgen_glGetHistogram; extern RGLSYMGLGETHISTOGRAMPARAMETERFVPROC __rglgen_glGetHistogramParameterfv; extern RGLSYMGLGETHISTOGRAMPARAMETERIVPROC __rglgen_glGetHistogramParameteriv; extern RGLSYMGLGETMINMAXPROC __rglgen_glGetMinmax; extern RGLSYMGLGETMINMAXPARAMETERFVPROC __rglgen_glGetMinmaxParameterfv; extern RGLSYMGLGETMINMAXPARAMETERIVPROC __rglgen_glGetMinmaxParameteriv; extern RGLSYMGLHISTOGRAMPROC __rglgen_glHistogram; extern RGLSYMGLMINMAXPROC __rglgen_glMinmax; extern RGLSYMGLRESETHISTOGRAMPROC __rglgen_glResetHistogram; extern RGLSYMGLRESETMINMAXPROC __rglgen_glResetMinmax; extern RGLSYMGLMULTIDRAWARRAYSINDIRECTCOUNTARBPROC __rglgen_glMultiDrawArraysIndirectCountARB; extern RGLSYMGLMULTIDRAWELEMENTSINDIRECTCOUNTARBPROC __rglgen_glMultiDrawElementsIndirectCountARB; extern RGLSYMGLVERTEXATTRIBDIVISORARBPROC __rglgen_glVertexAttribDivisorARB; extern RGLSYMGLCURRENTPALETTEMATRIXARBPROC __rglgen_glCurrentPaletteMatrixARB; extern RGLSYMGLMATRIXINDEXUBVARBPROC __rglgen_glMatrixIndexubvARB; extern RGLSYMGLMATRIXINDEXUSVARBPROC __rglgen_glMatrixIndexusvARB; extern RGLSYMGLMATRIXINDEXUIVARBPROC __rglgen_glMatrixIndexuivARB; extern RGLSYMGLMATRIXINDEXPOINTERARBPROC __rglgen_glMatrixIndexPointerARB; extern RGLSYMGLSAMPLECOVERAGEARBPROC __rglgen_glSampleCoverageARB; extern RGLSYMGLACTIVETEXTUREARBPROC __rglgen_glActiveTextureARB; extern RGLSYMGLCLIENTACTIVETEXTUREARBPROC __rglgen_glClientActiveTextureARB; extern RGLSYMGLMULTITEXCOORD1DARBPROC __rglgen_glMultiTexCoord1dARB; extern RGLSYMGLMULTITEXCOORD1DVARBPROC __rglgen_glMultiTexCoord1dvARB; extern RGLSYMGLMULTITEXCOORD1FARBPROC __rglgen_glMultiTexCoord1fARB; extern RGLSYMGLMULTITEXCOORD1FVARBPROC __rglgen_glMultiTexCoord1fvARB; extern RGLSYMGLMULTITEXCOORD1IARBPROC __rglgen_glMultiTexCoord1iARB; extern RGLSYMGLMULTITEXCOORD1IVARBPROC __rglgen_glMultiTexCoord1ivARB; extern RGLSYMGLMULTITEXCOORD1SARBPROC __rglgen_glMultiTexCoord1sARB; extern RGLSYMGLMULTITEXCOORD1SVARBPROC __rglgen_glMultiTexCoord1svARB; extern RGLSYMGLMULTITEXCOORD2DARBPROC __rglgen_glMultiTexCoord2dARB; extern RGLSYMGLMULTITEXCOORD2DVARBPROC __rglgen_glMultiTexCoord2dvARB; extern RGLSYMGLMULTITEXCOORD2FARBPROC __rglgen_glMultiTexCoord2fARB; extern RGLSYMGLMULTITEXCOORD2FVARBPROC __rglgen_glMultiTexCoord2fvARB; extern RGLSYMGLMULTITEXCOORD2IARBPROC __rglgen_glMultiTexCoord2iARB; extern RGLSYMGLMULTITEXCOORD2IVARBPROC __rglgen_glMultiTexCoord2ivARB; extern RGLSYMGLMULTITEXCOORD2SARBPROC __rglgen_glMultiTexCoord2sARB; extern RGLSYMGLMULTITEXCOORD2SVARBPROC __rglgen_glMultiTexCoord2svARB; extern RGLSYMGLMULTITEXCOORD3DARBPROC __rglgen_glMultiTexCoord3dARB; extern RGLSYMGLMULTITEXCOORD3DVARBPROC __rglgen_glMultiTexCoord3dvARB; extern RGLSYMGLMULTITEXCOORD3FARBPROC __rglgen_glMultiTexCoord3fARB; extern RGLSYMGLMULTITEXCOORD3FVARBPROC __rglgen_glMultiTexCoord3fvARB; extern RGLSYMGLMULTITEXCOORD3IARBPROC __rglgen_glMultiTexCoord3iARB; extern RGLSYMGLMULTITEXCOORD3IVARBPROC __rglgen_glMultiTexCoord3ivARB; extern RGLSYMGLMULTITEXCOORD3SARBPROC __rglgen_glMultiTexCoord3sARB; extern RGLSYMGLMULTITEXCOORD3SVARBPROC __rglgen_glMultiTexCoord3svARB; extern RGLSYMGLMULTITEXCOORD4DARBPROC __rglgen_glMultiTexCoord4dARB; extern RGLSYMGLMULTITEXCOORD4DVARBPROC __rglgen_glMultiTexCoord4dvARB; extern RGLSYMGLMULTITEXCOORD4FARBPROC __rglgen_glMultiTexCoord4fARB; extern RGLSYMGLMULTITEXCOORD4FVARBPROC __rglgen_glMultiTexCoord4fvARB; extern RGLSYMGLMULTITEXCOORD4IARBPROC __rglgen_glMultiTexCoord4iARB; extern RGLSYMGLMULTITEXCOORD4IVARBPROC __rglgen_glMultiTexCoord4ivARB; extern RGLSYMGLMULTITEXCOORD4SARBPROC __rglgen_glMultiTexCoord4sARB; extern RGLSYMGLMULTITEXCOORD4SVARBPROC __rglgen_glMultiTexCoord4svARB; extern RGLSYMGLGENQUERIESARBPROC __rglgen_glGenQueriesARB; extern RGLSYMGLDELETEQUERIESARBPROC __rglgen_glDeleteQueriesARB; extern RGLSYMGLISQUERYARBPROC __rglgen_glIsQueryARB; extern RGLSYMGLBEGINQUERYARBPROC __rglgen_glBeginQueryARB; extern RGLSYMGLENDQUERYARBPROC __rglgen_glEndQueryARB; extern RGLSYMGLGETQUERYIVARBPROC __rglgen_glGetQueryivARB; extern RGLSYMGLGETQUERYOBJECTIVARBPROC __rglgen_glGetQueryObjectivARB; extern RGLSYMGLGETQUERYOBJECTUIVARBPROC __rglgen_glGetQueryObjectuivARB; extern RGLSYMGLPOINTPARAMETERFARBPROC __rglgen_glPointParameterfARB; extern RGLSYMGLPOINTPARAMETERFVARBPROC __rglgen_glPointParameterfvARB; extern RGLSYMGLGETGRAPHICSRESETSTATUSARBPROC __rglgen_glGetGraphicsResetStatusARB; extern RGLSYMGLGETNTEXIMAGEARBPROC __rglgen_glGetnTexImageARB; extern RGLSYMGLREADNPIXELSARBPROC __rglgen_glReadnPixelsARB; extern RGLSYMGLGETNCOMPRESSEDTEXIMAGEARBPROC __rglgen_glGetnCompressedTexImageARB; extern RGLSYMGLGETNUNIFORMFVARBPROC __rglgen_glGetnUniformfvARB; extern RGLSYMGLGETNUNIFORMIVARBPROC __rglgen_glGetnUniformivARB; extern RGLSYMGLGETNUNIFORMUIVARBPROC __rglgen_glGetnUniformuivARB; extern RGLSYMGLGETNUNIFORMDVARBPROC __rglgen_glGetnUniformdvARB; extern RGLSYMGLGETNMAPDVARBPROC __rglgen_glGetnMapdvARB; extern RGLSYMGLGETNMAPFVARBPROC __rglgen_glGetnMapfvARB; extern RGLSYMGLGETNMAPIVARBPROC __rglgen_glGetnMapivARB; extern RGLSYMGLGETNPIXELMAPFVARBPROC __rglgen_glGetnPixelMapfvARB; extern RGLSYMGLGETNPIXELMAPUIVARBPROC __rglgen_glGetnPixelMapuivARB; extern RGLSYMGLGETNPIXELMAPUSVARBPROC __rglgen_glGetnPixelMapusvARB; extern RGLSYMGLGETNPOLYGONSTIPPLEARBPROC __rglgen_glGetnPolygonStippleARB; extern RGLSYMGLGETNCOLORTABLEARBPROC __rglgen_glGetnColorTableARB; extern RGLSYMGLGETNCONVOLUTIONFILTERARBPROC __rglgen_glGetnConvolutionFilterARB; extern RGLSYMGLGETNSEPARABLEFILTERARBPROC __rglgen_glGetnSeparableFilterARB; extern RGLSYMGLGETNHISTOGRAMARBPROC __rglgen_glGetnHistogramARB; extern RGLSYMGLGETNMINMAXARBPROC __rglgen_glGetnMinmaxARB; extern RGLSYMGLMINSAMPLESHADINGARBPROC __rglgen_glMinSampleShadingARB; extern RGLSYMGLDELETEOBJECTARBPROC __rglgen_glDeleteObjectARB; extern RGLSYMGLGETHANDLEARBPROC __rglgen_glGetHandleARB; extern RGLSYMGLDETACHOBJECTARBPROC __rglgen_glDetachObjectARB; extern RGLSYMGLCREATESHADEROBJECTARBPROC __rglgen_glCreateShaderObjectARB; extern RGLSYMGLSHADERSOURCEARBPROC __rglgen_glShaderSourceARB; extern RGLSYMGLCOMPILESHADERARBPROC __rglgen_glCompileShaderARB; extern RGLSYMGLCREATEPROGRAMOBJECTARBPROC __rglgen_glCreateProgramObjectARB; extern RGLSYMGLATTACHOBJECTARBPROC __rglgen_glAttachObjectARB; extern RGLSYMGLLINKPROGRAMARBPROC __rglgen_glLinkProgramARB; extern RGLSYMGLUSEPROGRAMOBJECTARBPROC __rglgen_glUseProgramObjectARB; extern RGLSYMGLVALIDATEPROGRAMARBPROC __rglgen_glValidateProgramARB; extern RGLSYMGLUNIFORM1FARBPROC __rglgen_glUniform1fARB; extern RGLSYMGLUNIFORM2FARBPROC __rglgen_glUniform2fARB; extern RGLSYMGLUNIFORM3FARBPROC __rglgen_glUniform3fARB; extern RGLSYMGLUNIFORM4FARBPROC __rglgen_glUniform4fARB; extern RGLSYMGLUNIFORM1IARBPROC __rglgen_glUniform1iARB; extern RGLSYMGLUNIFORM2IARBPROC __rglgen_glUniform2iARB; extern RGLSYMGLUNIFORM3IARBPROC __rglgen_glUniform3iARB; extern RGLSYMGLUNIFORM4IARBPROC __rglgen_glUniform4iARB; extern RGLSYMGLUNIFORM1FVARBPROC __rglgen_glUniform1fvARB; extern RGLSYMGLUNIFORM2FVARBPROC __rglgen_glUniform2fvARB; extern RGLSYMGLUNIFORM3FVARBPROC __rglgen_glUniform3fvARB; extern RGLSYMGLUNIFORM4FVARBPROC __rglgen_glUniform4fvARB; extern RGLSYMGLUNIFORM1IVARBPROC __rglgen_glUniform1ivARB; extern RGLSYMGLUNIFORM2IVARBPROC __rglgen_glUniform2ivARB; extern RGLSYMGLUNIFORM3IVARBPROC __rglgen_glUniform3ivARB; extern RGLSYMGLUNIFORM4IVARBPROC __rglgen_glUniform4ivARB; extern RGLSYMGLUNIFORMMATRIX2FVARBPROC __rglgen_glUniformMatrix2fvARB; extern RGLSYMGLUNIFORMMATRIX3FVARBPROC __rglgen_glUniformMatrix3fvARB; extern RGLSYMGLUNIFORMMATRIX4FVARBPROC __rglgen_glUniformMatrix4fvARB; extern RGLSYMGLGETOBJECTPARAMETERFVARBPROC __rglgen_glGetObjectParameterfvARB; extern RGLSYMGLGETOBJECTPARAMETERIVARBPROC __rglgen_glGetObjectParameterivARB; extern RGLSYMGLGETINFOLOGARBPROC __rglgen_glGetInfoLogARB; extern RGLSYMGLGETATTACHEDOBJECTSARBPROC __rglgen_glGetAttachedObjectsARB; extern RGLSYMGLGETUNIFORMLOCATIONARBPROC __rglgen_glGetUniformLocationARB; extern RGLSYMGLGETACTIVEUNIFORMARBPROC __rglgen_glGetActiveUniformARB; extern RGLSYMGLGETUNIFORMFVARBPROC __rglgen_glGetUniformfvARB; extern RGLSYMGLGETUNIFORMIVARBPROC __rglgen_glGetUniformivARB; extern RGLSYMGLGETSHADERSOURCEARBPROC __rglgen_glGetShaderSourceARB; extern RGLSYMGLNAMEDSTRINGARBPROC __rglgen_glNamedStringARB; extern RGLSYMGLDELETENAMEDSTRINGARBPROC __rglgen_glDeleteNamedStringARB; extern RGLSYMGLCOMPILESHADERINCLUDEARBPROC __rglgen_glCompileShaderIncludeARB; extern RGLSYMGLISNAMEDSTRINGARBPROC __rglgen_glIsNamedStringARB; extern RGLSYMGLGETNAMEDSTRINGARBPROC __rglgen_glGetNamedStringARB; extern RGLSYMGLGETNAMEDSTRINGIVARBPROC __rglgen_glGetNamedStringivARB; extern RGLSYMGLTEXPAGECOMMITMENTARBPROC __rglgen_glTexPageCommitmentARB; extern RGLSYMGLTEXBUFFERARBPROC __rglgen_glTexBufferARB; extern RGLSYMGLCOMPRESSEDTEXIMAGE3DARBPROC __rglgen_glCompressedTexImage3DARB; extern RGLSYMGLCOMPRESSEDTEXIMAGE2DARBPROC __rglgen_glCompressedTexImage2DARB; extern RGLSYMGLCOMPRESSEDTEXIMAGE1DARBPROC __rglgen_glCompressedTexImage1DARB; extern RGLSYMGLCOMPRESSEDTEXSUBIMAGE3DARBPROC __rglgen_glCompressedTexSubImage3DARB; extern RGLSYMGLCOMPRESSEDTEXSUBIMAGE2DARBPROC __rglgen_glCompressedTexSubImage2DARB; extern RGLSYMGLCOMPRESSEDTEXSUBIMAGE1DARBPROC __rglgen_glCompressedTexSubImage1DARB; extern RGLSYMGLGETCOMPRESSEDTEXIMAGEARBPROC __rglgen_glGetCompressedTexImageARB; extern RGLSYMGLLOADTRANSPOSEMATRIXFARBPROC __rglgen_glLoadTransposeMatrixfARB; extern RGLSYMGLLOADTRANSPOSEMATRIXDARBPROC __rglgen_glLoadTransposeMatrixdARB; extern RGLSYMGLMULTTRANSPOSEMATRIXFARBPROC __rglgen_glMultTransposeMatrixfARB; extern RGLSYMGLMULTTRANSPOSEMATRIXDARBPROC __rglgen_glMultTransposeMatrixdARB; extern RGLSYMGLWEIGHTBVARBPROC __rglgen_glWeightbvARB; extern RGLSYMGLWEIGHTSVARBPROC __rglgen_glWeightsvARB; extern RGLSYMGLWEIGHTIVARBPROC __rglgen_glWeightivARB; extern RGLSYMGLWEIGHTFVARBPROC __rglgen_glWeightfvARB; extern RGLSYMGLWEIGHTDVARBPROC __rglgen_glWeightdvARB; extern RGLSYMGLWEIGHTUBVARBPROC __rglgen_glWeightubvARB; extern RGLSYMGLWEIGHTUSVARBPROC __rglgen_glWeightusvARB; extern RGLSYMGLWEIGHTUIVARBPROC __rglgen_glWeightuivARB; extern RGLSYMGLWEIGHTPOINTERARBPROC __rglgen_glWeightPointerARB; extern RGLSYMGLVERTEXBLENDARBPROC __rglgen_glVertexBlendARB; extern RGLSYMGLBINDBUFFERARBPROC __rglgen_glBindBufferARB; extern RGLSYMGLDELETEBUFFERSARBPROC __rglgen_glDeleteBuffersARB; extern RGLSYMGLGENBUFFERSARBPROC __rglgen_glGenBuffersARB; extern RGLSYMGLISBUFFERARBPROC __rglgen_glIsBufferARB; extern RGLSYMGLBUFFERDATAARBPROC __rglgen_glBufferDataARB; extern RGLSYMGLBUFFERSUBDATAARBPROC __rglgen_glBufferSubDataARB; extern RGLSYMGLGETBUFFERSUBDATAARBPROC __rglgen_glGetBufferSubDataARB; extern RGLSYMGLMAPBUFFERARBPROC __rglgen_glMapBufferARB; extern RGLSYMGLUNMAPBUFFERARBPROC __rglgen_glUnmapBufferARB; extern RGLSYMGLGETBUFFERPARAMETERIVARBPROC __rglgen_glGetBufferParameterivARB; extern RGLSYMGLGETBUFFERPOINTERVARBPROC __rglgen_glGetBufferPointervARB; extern RGLSYMGLVERTEXATTRIB1DARBPROC __rglgen_glVertexAttrib1dARB; extern RGLSYMGLVERTEXATTRIB1DVARBPROC __rglgen_glVertexAttrib1dvARB; extern RGLSYMGLVERTEXATTRIB1FARBPROC __rglgen_glVertexAttrib1fARB; extern RGLSYMGLVERTEXATTRIB1FVARBPROC __rglgen_glVertexAttrib1fvARB; extern RGLSYMGLVERTEXATTRIB1SARBPROC __rglgen_glVertexAttrib1sARB; extern RGLSYMGLVERTEXATTRIB1SVARBPROC __rglgen_glVertexAttrib1svARB; extern RGLSYMGLVERTEXATTRIB2DARBPROC __rglgen_glVertexAttrib2dARB; extern RGLSYMGLVERTEXATTRIB2DVARBPROC __rglgen_glVertexAttrib2dvARB; extern RGLSYMGLVERTEXATTRIB2FARBPROC __rglgen_glVertexAttrib2fARB; extern RGLSYMGLVERTEXATTRIB2FVARBPROC __rglgen_glVertexAttrib2fvARB; extern RGLSYMGLVERTEXATTRIB2SARBPROC __rglgen_glVertexAttrib2sARB; extern RGLSYMGLVERTEXATTRIB2SVARBPROC __rglgen_glVertexAttrib2svARB; extern RGLSYMGLVERTEXATTRIB3DARBPROC __rglgen_glVertexAttrib3dARB; extern RGLSYMGLVERTEXATTRIB3DVARBPROC __rglgen_glVertexAttrib3dvARB; extern RGLSYMGLVERTEXATTRIB3FARBPROC __rglgen_glVertexAttrib3fARB; extern RGLSYMGLVERTEXATTRIB3FVARBPROC __rglgen_glVertexAttrib3fvARB; extern RGLSYMGLVERTEXATTRIB3SARBPROC __rglgen_glVertexAttrib3sARB; extern RGLSYMGLVERTEXATTRIB3SVARBPROC __rglgen_glVertexAttrib3svARB; extern RGLSYMGLVERTEXATTRIB4NBVARBPROC __rglgen_glVertexAttrib4NbvARB; extern RGLSYMGLVERTEXATTRIB4NIVARBPROC __rglgen_glVertexAttrib4NivARB; extern RGLSYMGLVERTEXATTRIB4NSVARBPROC __rglgen_glVertexAttrib4NsvARB; extern RGLSYMGLVERTEXATTRIB4NUBARBPROC __rglgen_glVertexAttrib4NubARB; extern RGLSYMGLVERTEXATTRIB4NUBVARBPROC __rglgen_glVertexAttrib4NubvARB; extern RGLSYMGLVERTEXATTRIB4NUIVARBPROC __rglgen_glVertexAttrib4NuivARB; extern RGLSYMGLVERTEXATTRIB4NUSVARBPROC __rglgen_glVertexAttrib4NusvARB; extern RGLSYMGLVERTEXATTRIB4BVARBPROC __rglgen_glVertexAttrib4bvARB; extern RGLSYMGLVERTEXATTRIB4DARBPROC __rglgen_glVertexAttrib4dARB; extern RGLSYMGLVERTEXATTRIB4DVARBPROC __rglgen_glVertexAttrib4dvARB; extern RGLSYMGLVERTEXATTRIB4FARBPROC __rglgen_glVertexAttrib4fARB; extern RGLSYMGLVERTEXATTRIB4FVARBPROC __rglgen_glVertexAttrib4fvARB; extern RGLSYMGLVERTEXATTRIB4IVARBPROC __rglgen_glVertexAttrib4ivARB; extern RGLSYMGLVERTEXATTRIB4SARBPROC __rglgen_glVertexAttrib4sARB; extern RGLSYMGLVERTEXATTRIB4SVARBPROC __rglgen_glVertexAttrib4svARB; extern RGLSYMGLVERTEXATTRIB4UBVARBPROC __rglgen_glVertexAttrib4ubvARB; extern RGLSYMGLVERTEXATTRIB4UIVARBPROC __rglgen_glVertexAttrib4uivARB; extern RGLSYMGLVERTEXATTRIB4USVARBPROC __rglgen_glVertexAttrib4usvARB; extern RGLSYMGLVERTEXATTRIBPOINTERARBPROC __rglgen_glVertexAttribPointerARB; extern RGLSYMGLENABLEVERTEXATTRIBARRAYARBPROC __rglgen_glEnableVertexAttribArrayARB; extern RGLSYMGLDISABLEVERTEXATTRIBARRAYARBPROC __rglgen_glDisableVertexAttribArrayARB; extern RGLSYMGLGETVERTEXATTRIBDVARBPROC __rglgen_glGetVertexAttribdvARB; extern RGLSYMGLGETVERTEXATTRIBFVARBPROC __rglgen_glGetVertexAttribfvARB; extern RGLSYMGLGETVERTEXATTRIBIVARBPROC __rglgen_glGetVertexAttribivARB; extern RGLSYMGLGETVERTEXATTRIBPOINTERVARBPROC __rglgen_glGetVertexAttribPointervARB; extern RGLSYMGLBINDATTRIBLOCATIONARBPROC __rglgen_glBindAttribLocationARB; extern RGLSYMGLGETACTIVEATTRIBARBPROC __rglgen_glGetActiveAttribARB; extern RGLSYMGLGETATTRIBLOCATIONARBPROC __rglgen_glGetAttribLocationARB; extern RGLSYMGLWINDOWPOS2DARBPROC __rglgen_glWindowPos2dARB; extern RGLSYMGLWINDOWPOS2DVARBPROC __rglgen_glWindowPos2dvARB; extern RGLSYMGLWINDOWPOS2FARBPROC __rglgen_glWindowPos2fARB; extern RGLSYMGLWINDOWPOS2FVARBPROC __rglgen_glWindowPos2fvARB; extern RGLSYMGLWINDOWPOS2IARBPROC __rglgen_glWindowPos2iARB; extern RGLSYMGLWINDOWPOS2IVARBPROC __rglgen_glWindowPos2ivARB; extern RGLSYMGLWINDOWPOS2SARBPROC __rglgen_glWindowPos2sARB; extern RGLSYMGLWINDOWPOS2SVARBPROC __rglgen_glWindowPos2svARB; extern RGLSYMGLWINDOWPOS3DARBPROC __rglgen_glWindowPos3dARB; extern RGLSYMGLWINDOWPOS3DVARBPROC __rglgen_glWindowPos3dvARB; extern RGLSYMGLWINDOWPOS3FARBPROC __rglgen_glWindowPos3fARB; extern RGLSYMGLWINDOWPOS3FVARBPROC __rglgen_glWindowPos3fvARB; extern RGLSYMGLWINDOWPOS3IARBPROC __rglgen_glWindowPos3iARB; extern RGLSYMGLWINDOWPOS3IVARBPROC __rglgen_glWindowPos3ivARB; extern RGLSYMGLWINDOWPOS3SARBPROC __rglgen_glWindowPos3sARB; extern RGLSYMGLWINDOWPOS3SVARBPROC __rglgen_glWindowPos3svARB; extern RGLSYMGLMULTITEXCOORD1BOESPROC __rglgen_glMultiTexCoord1bOES; extern RGLSYMGLMULTITEXCOORD1BVOESPROC __rglgen_glMultiTexCoord1bvOES; extern RGLSYMGLMULTITEXCOORD2BOESPROC __rglgen_glMultiTexCoord2bOES; extern RGLSYMGLMULTITEXCOORD2BVOESPROC __rglgen_glMultiTexCoord2bvOES; extern RGLSYMGLMULTITEXCOORD3BOESPROC __rglgen_glMultiTexCoord3bOES; extern RGLSYMGLMULTITEXCOORD3BVOESPROC __rglgen_glMultiTexCoord3bvOES; extern RGLSYMGLMULTITEXCOORD4BOESPROC __rglgen_glMultiTexCoord4bOES; extern RGLSYMGLMULTITEXCOORD4BVOESPROC __rglgen_glMultiTexCoord4bvOES; extern RGLSYMGLTEXCOORD1BOESPROC __rglgen_glTexCoord1bOES; extern RGLSYMGLTEXCOORD1BVOESPROC __rglgen_glTexCoord1bvOES; extern RGLSYMGLTEXCOORD2BOESPROC __rglgen_glTexCoord2bOES; extern RGLSYMGLTEXCOORD2BVOESPROC __rglgen_glTexCoord2bvOES; extern RGLSYMGLTEXCOORD3BOESPROC __rglgen_glTexCoord3bOES; extern RGLSYMGLTEXCOORD3BVOESPROC __rglgen_glTexCoord3bvOES; extern RGLSYMGLTEXCOORD4BOESPROC __rglgen_glTexCoord4bOES; extern RGLSYMGLTEXCOORD4BVOESPROC __rglgen_glTexCoord4bvOES; extern RGLSYMGLVERTEX2BOESPROC __rglgen_glVertex2bOES; extern RGLSYMGLVERTEX2BVOESPROC __rglgen_glVertex2bvOES; extern RGLSYMGLVERTEX3BOESPROC __rglgen_glVertex3bOES; extern RGLSYMGLVERTEX3BVOESPROC __rglgen_glVertex3bvOES; extern RGLSYMGLVERTEX4BOESPROC __rglgen_glVertex4bOES; extern RGLSYMGLVERTEX4BVOESPROC __rglgen_glVertex4bvOES; extern RGLSYMGLALPHAFUNCXOESPROC __rglgen_glAlphaFuncxOES; extern RGLSYMGLCLEARCOLORXOESPROC __rglgen_glClearColorxOES; extern RGLSYMGLCLEARDEPTHXOESPROC __rglgen_glClearDepthxOES; extern RGLSYMGLCLIPPLANEXOESPROC __rglgen_glClipPlanexOES; extern RGLSYMGLCOLOR4XOESPROC __rglgen_glColor4xOES; extern RGLSYMGLDEPTHRANGEXOESPROC __rglgen_glDepthRangexOES; extern RGLSYMGLFOGXOESPROC __rglgen_glFogxOES; extern RGLSYMGLFOGXVOESPROC __rglgen_glFogxvOES; extern RGLSYMGLFRUSTUMXOESPROC __rglgen_glFrustumxOES; extern RGLSYMGLGETCLIPPLANEXOESPROC __rglgen_glGetClipPlanexOES; extern RGLSYMGLGETFIXEDVOESPROC __rglgen_glGetFixedvOES; extern RGLSYMGLGETTEXENVXVOESPROC __rglgen_glGetTexEnvxvOES; extern RGLSYMGLGETTEXPARAMETERXVOESPROC __rglgen_glGetTexParameterxvOES; extern RGLSYMGLLIGHTMODELXOESPROC __rglgen_glLightModelxOES; extern RGLSYMGLLIGHTMODELXVOESPROC __rglgen_glLightModelxvOES; extern RGLSYMGLLIGHTXOESPROC __rglgen_glLightxOES; extern RGLSYMGLLIGHTXVOESPROC __rglgen_glLightxvOES; extern RGLSYMGLLINEWIDTHXOESPROC __rglgen_glLineWidthxOES; extern RGLSYMGLLOADMATRIXXOESPROC __rglgen_glLoadMatrixxOES; extern RGLSYMGLMATERIALXOESPROC __rglgen_glMaterialxOES; extern RGLSYMGLMATERIALXVOESPROC __rglgen_glMaterialxvOES; extern RGLSYMGLMULTMATRIXXOESPROC __rglgen_glMultMatrixxOES; extern RGLSYMGLMULTITEXCOORD4XOESPROC __rglgen_glMultiTexCoord4xOES; extern RGLSYMGLNORMAL3XOESPROC __rglgen_glNormal3xOES; extern RGLSYMGLORTHOXOESPROC __rglgen_glOrthoxOES; extern RGLSYMGLPOINTPARAMETERXVOESPROC __rglgen_glPointParameterxvOES; extern RGLSYMGLPOINTSIZEXOESPROC __rglgen_glPointSizexOES; extern RGLSYMGLPOLYGONOFFSETXOESPROC __rglgen_glPolygonOffsetxOES; extern RGLSYMGLROTATEXOESPROC __rglgen_glRotatexOES; extern RGLSYMGLSAMPLECOVERAGEOESPROC __rglgen_glSampleCoverageOES; extern RGLSYMGLSCALEXOESPROC __rglgen_glScalexOES; extern RGLSYMGLTEXENVXOESPROC __rglgen_glTexEnvxOES; extern RGLSYMGLTEXENVXVOESPROC __rglgen_glTexEnvxvOES; extern RGLSYMGLTEXPARAMETERXOESPROC __rglgen_glTexParameterxOES; extern RGLSYMGLTEXPARAMETERXVOESPROC __rglgen_glTexParameterxvOES; extern RGLSYMGLTRANSLATEXOESPROC __rglgen_glTranslatexOES; extern RGLSYMGLACCUMXOESPROC __rglgen_glAccumxOES; extern RGLSYMGLBITMAPXOESPROC __rglgen_glBitmapxOES; extern RGLSYMGLBLENDCOLORXOESPROC __rglgen_glBlendColorxOES; extern RGLSYMGLCLEARACCUMXOESPROC __rglgen_glClearAccumxOES; extern RGLSYMGLCOLOR3XOESPROC __rglgen_glColor3xOES; extern RGLSYMGLCOLOR3XVOESPROC __rglgen_glColor3xvOES; extern RGLSYMGLCOLOR4XVOESPROC __rglgen_glColor4xvOES; extern RGLSYMGLCONVOLUTIONPARAMETERXOESPROC __rglgen_glConvolutionParameterxOES; extern RGLSYMGLCONVOLUTIONPARAMETERXVOESPROC __rglgen_glConvolutionParameterxvOES; extern RGLSYMGLEVALCOORD1XOESPROC __rglgen_glEvalCoord1xOES; extern RGLSYMGLEVALCOORD1XVOESPROC __rglgen_glEvalCoord1xvOES; extern RGLSYMGLEVALCOORD2XOESPROC __rglgen_glEvalCoord2xOES; extern RGLSYMGLEVALCOORD2XVOESPROC __rglgen_glEvalCoord2xvOES; extern RGLSYMGLFEEDBACKBUFFERXOESPROC __rglgen_glFeedbackBufferxOES; extern RGLSYMGLGETCONVOLUTIONPARAMETERXVOESPROC __rglgen_glGetConvolutionParameterxvOES; extern RGLSYMGLGETHISTOGRAMPARAMETERXVOESPROC __rglgen_glGetHistogramParameterxvOES; extern RGLSYMGLGETLIGHTXOESPROC __rglgen_glGetLightxOES; extern RGLSYMGLGETMAPXVOESPROC __rglgen_glGetMapxvOES; extern RGLSYMGLGETMATERIALXOESPROC __rglgen_glGetMaterialxOES; extern RGLSYMGLGETPIXELMAPXVPROC __rglgen_glGetPixelMapxv; extern RGLSYMGLGETTEXGENXVOESPROC __rglgen_glGetTexGenxvOES; extern RGLSYMGLGETTEXLEVELPARAMETERXVOESPROC __rglgen_glGetTexLevelParameterxvOES; extern RGLSYMGLINDEXXOESPROC __rglgen_glIndexxOES; extern RGLSYMGLINDEXXVOESPROC __rglgen_glIndexxvOES; extern RGLSYMGLLOADTRANSPOSEMATRIXXOESPROC __rglgen_glLoadTransposeMatrixxOES; extern RGLSYMGLMAP1XOESPROC __rglgen_glMap1xOES; extern RGLSYMGLMAP2XOESPROC __rglgen_glMap2xOES; extern RGLSYMGLMAPGRID1XOESPROC __rglgen_glMapGrid1xOES; extern RGLSYMGLMAPGRID2XOESPROC __rglgen_glMapGrid2xOES; extern RGLSYMGLMULTTRANSPOSEMATRIXXOESPROC __rglgen_glMultTransposeMatrixxOES; extern RGLSYMGLMULTITEXCOORD1XOESPROC __rglgen_glMultiTexCoord1xOES; extern RGLSYMGLMULTITEXCOORD1XVOESPROC __rglgen_glMultiTexCoord1xvOES; extern RGLSYMGLMULTITEXCOORD2XOESPROC __rglgen_glMultiTexCoord2xOES; extern RGLSYMGLMULTITEXCOORD2XVOESPROC __rglgen_glMultiTexCoord2xvOES; extern RGLSYMGLMULTITEXCOORD3XOESPROC __rglgen_glMultiTexCoord3xOES; extern RGLSYMGLMULTITEXCOORD3XVOESPROC __rglgen_glMultiTexCoord3xvOES; extern RGLSYMGLMULTITEXCOORD4XVOESPROC __rglgen_glMultiTexCoord4xvOES; extern RGLSYMGLNORMAL3XVOESPROC __rglgen_glNormal3xvOES; extern RGLSYMGLPASSTHROUGHXOESPROC __rglgen_glPassThroughxOES; extern RGLSYMGLPIXELMAPXPROC __rglgen_glPixelMapx; extern RGLSYMGLPIXELSTOREXPROC __rglgen_glPixelStorex; extern RGLSYMGLPIXELTRANSFERXOESPROC __rglgen_glPixelTransferxOES; extern RGLSYMGLPIXELZOOMXOESPROC __rglgen_glPixelZoomxOES; extern RGLSYMGLPRIORITIZETEXTURESXOESPROC __rglgen_glPrioritizeTexturesxOES; extern RGLSYMGLRASTERPOS2XOESPROC __rglgen_glRasterPos2xOES; extern RGLSYMGLRASTERPOS2XVOESPROC __rglgen_glRasterPos2xvOES; extern RGLSYMGLRASTERPOS3XOESPROC __rglgen_glRasterPos3xOES; extern RGLSYMGLRASTERPOS3XVOESPROC __rglgen_glRasterPos3xvOES; extern RGLSYMGLRASTERPOS4XOESPROC __rglgen_glRasterPos4xOES; extern RGLSYMGLRASTERPOS4XVOESPROC __rglgen_glRasterPos4xvOES; extern RGLSYMGLRECTXOESPROC __rglgen_glRectxOES; extern RGLSYMGLRECTXVOESPROC __rglgen_glRectxvOES; extern RGLSYMGLTEXCOORD1XOESPROC __rglgen_glTexCoord1xOES; extern RGLSYMGLTEXCOORD1XVOESPROC __rglgen_glTexCoord1xvOES; extern RGLSYMGLTEXCOORD2XOESPROC __rglgen_glTexCoord2xOES; extern RGLSYMGLTEXCOORD2XVOESPROC __rglgen_glTexCoord2xvOES; extern RGLSYMGLTEXCOORD3XOESPROC __rglgen_glTexCoord3xOES; extern RGLSYMGLTEXCOORD3XVOESPROC __rglgen_glTexCoord3xvOES; extern RGLSYMGLTEXCOORD4XOESPROC __rglgen_glTexCoord4xOES; extern RGLSYMGLTEXCOORD4XVOESPROC __rglgen_glTexCoord4xvOES; extern RGLSYMGLTEXGENXOESPROC __rglgen_glTexGenxOES; extern RGLSYMGLTEXGENXVOESPROC __rglgen_glTexGenxvOES; extern RGLSYMGLVERTEX2XOESPROC __rglgen_glVertex2xOES; extern RGLSYMGLVERTEX2XVOESPROC __rglgen_glVertex2xvOES; extern RGLSYMGLVERTEX3XOESPROC __rglgen_glVertex3xOES; extern RGLSYMGLVERTEX3XVOESPROC __rglgen_glVertex3xvOES; extern RGLSYMGLVERTEX4XOESPROC __rglgen_glVertex4xOES; extern RGLSYMGLVERTEX4XVOESPROC __rglgen_glVertex4xvOES; extern RGLSYMGLQUERYMATRIXXOESPROC __rglgen_glQueryMatrixxOES; extern RGLSYMGLCLEARDEPTHFOESPROC __rglgen_glClearDepthfOES; extern RGLSYMGLCLIPPLANEFOESPROC __rglgen_glClipPlanefOES; extern RGLSYMGLDEPTHRANGEFOESPROC __rglgen_glDepthRangefOES; extern RGLSYMGLFRUSTUMFOESPROC __rglgen_glFrustumfOES; extern RGLSYMGLGETCLIPPLANEFOESPROC __rglgen_glGetClipPlanefOES; extern RGLSYMGLORTHOFOESPROC __rglgen_glOrthofOES; extern RGLSYMGLIMAGETRANSFORMPARAMETERIHPPROC __rglgen_glImageTransformParameteriHP; extern RGLSYMGLIMAGETRANSFORMPARAMETERFHPPROC __rglgen_glImageTransformParameterfHP; extern RGLSYMGLIMAGETRANSFORMPARAMETERIVHPPROC __rglgen_glImageTransformParameterivHP; extern RGLSYMGLIMAGETRANSFORMPARAMETERFVHPPROC __rglgen_glImageTransformParameterfvHP; extern RGLSYMGLGETIMAGETRANSFORMPARAMETERIVHPPROC __rglgen_glGetImageTransformParameterivHP; extern RGLSYMGLGETIMAGETRANSFORMPARAMETERFVHPPROC __rglgen_glGetImageTransformParameterfvHP; struct rglgen_sym_map { const char *sym; void *ptr; }; extern const struct rglgen_sym_map rglgen_symbol_map[]; #ifdef __cplusplus } #endif #endif desmume/src/MMU.h000664 001750 001750 00000063217 12755534123 014757 0ustar00sergiosergio000000 000000 /* Copyright (C) 2006 yopyop Copyright (C) 2007 shash Copyright (C) 2007-2015 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the this software. If not, see . */ #ifndef MMU_H #define MMU_H #include "debug.h" #include "firmware.h" #include "mc.h" #include "mem.h" #ifdef HAVE_JIT #include "arm_jit.h" #endif #define ARMCPU_ARM7 1 #define ARMCPU_ARM9 0 #define ARMPROC (PROCNUM ? NDS_ARM7:NDS_ARM9) class EMUFILE; typedef const u8 TWaitState; enum EDMAMode { EDMAMode_Immediate = 0, EDMAMode_VBlank = 1, EDMAMode_HBlank = 2, EDMAMode_HStart = 3, EDMAMode_MemDisplay = 4, EDMAMode_Card = 5, EDMAMode_GBASlot = 6, EDMAMode_GXFifo = 7, EDMAMode7_Wifi = 8, EDMAMode7_GBASlot = 9 }; enum EDMABitWidth { EDMABitWidth_16 = 0, EDMABitWidth_32 = 1 }; enum EDMASourceUpdate { EDMASourceUpdate_Increment = 0, EDMASourceUpdate_Decrement = 1, EDMASourceUpdate_Fixed = 2, EDMASourceUpdate_Invalid = 3 }; enum EDMADestinationUpdate { EDMADestinationUpdate_Increment = 0, EDMADestinationUpdate_Decrement = 1, EDMADestinationUpdate_Fixed = 2, EDMADestinationUpdate_IncrementReload = 3 }; //TODO //n.b. this may be a bad idea, for complex registers like the dma control register. //we need to know exactly what part was written to, instead of assuming all 32bits were written. class TRegister_32 { public: virtual u32 read32() = 0; virtual void write32(const u32 val) = 0; void write(const int size, const u32 adr, const u32 val) { if(size==32) write32(val); else { const u32 offset = adr&3; if(size==8) { printf("WARNING! 8BIT DMA ACCESS\n"); u32 mask = 0xFF<<(offset<<3); write32((read32()&~mask)|(val<<(offset<<3))); } else if(size==16) { u32 mask = 0xFFFF<<(offset<<3); write32((read32()&~mask)|(val<<(offset<<3))); } } } u32 read(const int size, const u32 adr) { if(size==32) return read32(); else { const u32 offset = adr&3; if(size==8) { printf("WARNING! 8BIT DMA ACCESS\n"); return (read32()>>(offset<<3))&0xFF; } else return (read32()>>(offset<<3))&0xFFFF; } } }; struct TGXSTAT : public TRegister_32 { TGXSTAT() { gxfifo_irq = se = tr = tb = sb = 0; fifo_empty = true; fifo_low = false; } u8 tb; //test busy u8 tr; //test result u8 se; //stack error u8 sb; //stack busy u8 gxfifo_irq; //irq configuration bool fifo_empty, fifo_low; virtual u32 read32(); virtual void write32(const u32 val); void savestate(EMUFILE *f); bool loadstate(EMUFILE *f); }; void triggerDma(EDMAMode mode); class DivController { public: DivController() : mode(0), busy(0) {} void exec(); u8 mode, busy, div0; u16 read16() { return mode|(busy<<15)|(div0<<14); } void write16(u16 val) { mode = val&3; //todo - do we clear the div0 flag here or is that strictly done by the divider unit? } void savestate(EMUFILE* os); bool loadstate(EMUFILE* is, int version); }; class SqrtController { public: SqrtController() : mode(0), busy(0) {} void exec(); u8 mode, busy; u16 read16() { return mode|(busy<<15); } void write16(u16 val) { mode = val&1; } void savestate(EMUFILE* os); bool loadstate(EMUFILE* is, int version); }; class DmaController { public: u8 enable, irq, repeatMode, _startmode; u8 userEnable; u32 wordcount; EDMAMode startmode; EDMABitWidth bitWidth; EDMASourceUpdate sar; EDMADestinationUpdate dar; u32 saddr, daddr; u32 saddr_user, daddr_user; //indicates whether the dma needs to be checked for triggering BOOL dmaCheck; //indicates whether the dma right now is logically running //(though for now we copy all the data when it triggers) BOOL running; BOOL paused; //this flag will sometimes be set when a start condition is triggered //other conditions may be automatically triggered based on scanning conditions BOOL triggered; u64 nextEvent; int procnum, chan; void savestate(EMUFILE *f); bool loadstate(EMUFILE *f); void exec(); template void doCopy(); void doPause(); void doStop(); void doSchedule(); void tryTrigger(EDMAMode mode); DmaController() : enable(0), irq(0), repeatMode(0), _startmode(0), wordcount(0), startmode(EDMAMode_Immediate), bitWidth(EDMABitWidth_16), sar(EDMASourceUpdate_Increment), dar(EDMADestinationUpdate_Increment), //if saddr isnt cleared then rings of fate will trigger copy protection //by inspecting dma3 saddr when it boots saddr(0), daddr(0), saddr_user(0), daddr_user(0), dmaCheck(FALSE), running(FALSE), paused(FALSE), triggered(FALSE), nextEvent(0), sad(&saddr_user), dad(&daddr_user) { sad.controller = this; dad.controller = this; ctrl.controller = this; regs[0] = &sad; regs[1] = &dad; regs[2] = &ctrl; } class AddressRegister : public TRegister_32 { public: //we pass in a pointer to the controller here so we can alert it if anything changes DmaController* controller; u32 * const ptr; AddressRegister(u32* _ptr) : ptr(_ptr) {} virtual u32 read32() { return *ptr; } virtual void write32(const u32 val) { *ptr = val; } }; class ControlRegister : public TRegister_32 { public: //we pass in a pointer to the controller here so we can alert it if anything changes DmaController* controller; ControlRegister() {} virtual u32 read32() { return controller->read32(); } virtual void write32(const u32 val) { return controller->write32(val); } }; AddressRegister sad, dad; ControlRegister ctrl; TRegister_32* regs[3]; void write32(const u32 val); u32 read32(); }; enum eCardMode { //when the GC system is first booted up, the protocol is in raw mode eCardMode_RAW = 0, //an intermediate stage during the protocol bootup process. commands are KEY1 encrypted. eCardMode_KEY1, //an intermediate stage during the protocol bootup process. commands are KEY1 encrypted, while replies are KEY2 encrypted eCardMode_KEY2, //the final stage of the protocol bootup process. "main data load" mode. commands are KEY2 encrypted, and replies are KEY2 encrypted. //optionally, according to some flag we havent designed yet but should probably go in GCBUS_Controller, the whole KEY2 part can be bypassed //(this is typical when skipping the firmware boot process) eCardMode_NORMAL, //help fix to 32bit eCardMode_Pad = 0xFFFFFFFF }; //#define GCLOG(...) printf(__VA_ARGS__); #define GCLOG(...) void MMU_GC_endTransfer(u32 PROCNUM); struct GC_Command { u8 bytes[8]; void print(); void toCryptoBuffer(u32 buf[2]); void fromCryptoBuffer(u32 buf[2]); }; //should rather be known as GCBUS controller, or somesuch struct GCBUS_Controller { int transfer_count; eCardMode mode; //probably only one of these }; #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 struct MMU_struct { //ARM9 mem u8 ARM9_ITCM[0x8000]; u8 ARM9_DTCM[0x4000]; //u8 MAIN_MEM[4*1024*1024]; //expanded from 4MB to 8MB to support debug consoles //u8 MAIN_MEM[8*1024*1024]; //expanded from 8MB to 16MB to support dsi u8 MAIN_MEM[16*1024*1024]; //expanded from 8MB to 16MB to support dsi u8 ARM9_REG[0x1000000]; //this variable is evil and should be removed by correctly emulating all registers. u8 ARM9_BIOS[0x8000]; u8 ARM9_VMEM[0x800]; #include "PACKED.h" struct { u8 ARM9_LCD[0xA4000]; //an extra 128KB for blank memory, directly after arm9_lcd, so that //we can easily map things to the end of arm9_lcd to represent //an unmapped state u8 blank_memory[0x20000]; }; #include "PACKED_END.h" u8 ARM9_OAM[0x800]; u8* ExtPal[2][4]; u8* ObjExtPal[2][2]; struct TextureInfo { u8* texPalSlot[6]; u8* textureSlotAddr[4]; } texInfo; //ARM7 mem u8 ARM7_BIOS[0x4000]; u8 ARM7_ERAM[0x10000]; //64KB of exclusive WRAM u8 ARM7_REG[0x10000]; u8 ARM7_WIRAM[0x10000]; //WIFI ram // VRAM mapping u8 VRAM_MAP[4][32]; u32 LCD_VRAM_ADDR[10]; u8 LCDCenable[10]; //32KB of shared WRAM - can be switched between ARM7 & ARM9 in two blocks u8 SWIRAM[0x8000]; //Unused ram u8 UNUSED_RAM[4]; //this is here so that we can trap glitchy emulator code //which is accessing offsets 5,6,7 of unused ram due to unaligned accesses //(also since the emulator doesn't prevent unaligned accesses) u8 MORE_UNUSED_RAM[4]; static u8 * MMU_MEM[2][256]; static u32 MMU_MASK[2][256]; u8 ARM9_RW_MODE; 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]; //these are the user-controlled IF bits. some IF bits are generated as necessary from hardware conditions u32 reg_IF_bits[2]; //these flags are set occasionally to indicate that an irq should have entered the pipeline, and processing will be deferred a tiny bit to help emulate things u32 reg_IF_pending[2]; u32 reg_DISP3DCNT_bits; template u32 gen_IF(); BOOL divRunning; s64 divResult; s64 divMod; u64 divCycles; BOOL sqrtRunning; u32 sqrtResult; u64 sqrtCycles; u16 SPI_CNT; u16 SPI_CMD; u16 AUX_SPI_CNT; //u16 AUX_SPI_CMD; //zero 20-aug-2013 - this seems pointless u8 WRAMCNT; u64 gfx3dCycles; u8 powerMan_CntReg; BOOL powerMan_CntRegWritten; u8 powerMan_Reg[5]; fw_memory_chip fw; GCBUS_Controller dscard[2]; }; //everything in here is derived from libnds behaviours. no hardware tests yet class DSI_TSC { public: DSI_TSC(); void reset_command(); u16 write16(u16 val); bool save_state(EMUFILE* os); bool load_state(EMUFILE* is); private: u16 read16(); u8 reg_selection; u8 read_flag; s32 state; s32 readcount; //registers[0] contains the current page. //we are going to go ahead and save these out in case we want to change the way this is emulated in the future.. //we may want to poke registers in here at more convenient times and have the TSC dumbly pluck them out, //rather than generate the values on the fly u8 registers[0x80]; }; //this contains things which can't be memzeroed because they are smarter classes struct MMU_struct_new { MMU_struct_new() ; BackupDevice backupDevice; DmaController dma[2][4]; TGXSTAT gxstat; SqrtController sqrt; DivController div; DSI_TSC dsi_tsc; void write_dma(const int proc, const int size, const u32 adr, const u32 val); u32 read_dma(const int proc, const int size, const u32 adr); bool is_dma(const u32 adr); }; extern MMU_struct MMU; extern MMU_struct_new MMU_new; 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; }; void MMU_Init(void); void MMU_DeInit(void); void MMU_Reset( void); void print_memory_profiling( void); // Memory reading/writing (old) u8 FASTCALL MMU_read8(u32 proc, u32 adr); u16 FASTCALL MMU_read16(u32 proc, u32 adr); u32 FASTCALL MMU_read32(u32 proc, u32 adr); 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); //template void FASTCALL MMU_doDMA(u32 num); //The base ARM memory interfaces extern const armcpu_memory_iface arm9_base_memory_iface; extern const armcpu_memory_iface arm7_base_memory_iface; extern const armcpu_memory_iface arm9_direct_memory_iface; #define VRAM_BANKS 9 #define VRAM_BANK_A 0 #define VRAM_BANK_B 1 #define VRAM_BANK_C 2 #define VRAM_BANK_D 3 #define VRAM_BANK_E 4 #define VRAM_BANK_F 5 #define VRAM_BANK_G 6 #define VRAM_BANK_H 7 #define VRAM_BANK_I 8 #define VRAM_PAGE_ABG 0 #define VRAM_PAGE_BBG 128 #define VRAM_PAGE_AOBJ 256 #define VRAM_PAGE_BOBJ 384 struct VramConfiguration { enum Purpose { OFF, INVALID, ABG, BBG, AOBJ, BOBJ, LCDC, ARM7, TEX, TEXPAL, ABGEXTPAL, BBGEXTPAL, AOBJEXTPAL, BOBJEXTPAL }; struct BankInfo { Purpose purpose; int ofs; } banks[VRAM_BANKS]; inline void clear() { for(int i=0;i> 14) & (VRAM_ARM9_PAGES - 1) ]; const u32 ofs = vram_addr & 0x3FFF; //blank pages are handled by the extra 16KB of blank memory at the end of ARM9_LCD //and the fact that blank pages are mapped to appear at that location return MMU.ARM9_LCD + (vram_page << 14) + ofs; } template u8 _MMU_read08(u32 addr); template u16 _MMU_read16(u32 addr); template u32 _MMU_read32(u32 addr); template void _MMU_write08(u32 addr, u8 val); template void _MMU_write16(u32 addr, u16 val); template void _MMU_write32(u32 addr, u32 val); template FORCEINLINE u8 _MMU_read08(u32 addr) { return _MMU_read08(addr); } template FORCEINLINE u16 _MMU_read16(u32 addr) { return _MMU_read16(addr); } template FORCEINLINE u32 _MMU_read32(u32 addr) { return _MMU_read32(addr); } template FORCEINLINE void _MMU_write08(u32 addr, u8 val) { _MMU_write08(addr,val); } template FORCEINLINE void _MMU_write16(u32 addr, u16 val) { _MMU_write16(addr,val); } template FORCEINLINE void _MMU_write32(u32 addr, u32 val) { _MMU_write32(addr,val); } void FASTCALL _MMU_ARM9_write08(u32 adr, u8 val); void FASTCALL _MMU_ARM9_write16(u32 adr, u16 val); void FASTCALL _MMU_ARM9_write32(u32 adr, u32 val); u8 FASTCALL _MMU_ARM9_read08(u32 adr); u16 FASTCALL _MMU_ARM9_read16(u32 adr); u32 FASTCALL _MMU_ARM9_read32(u32 adr); void FASTCALL _MMU_ARM7_write08(u32 adr, u8 val); void FASTCALL _MMU_ARM7_write16(u32 adr, u16 val); void FASTCALL _MMU_ARM7_write32(u32 adr, u32 val); u8 FASTCALL _MMU_ARM7_read08(u32 adr); u16 FASTCALL _MMU_ARM7_read16(u32 adr); u32 FASTCALL _MMU_ARM7_read32(u32 adr); extern u32 partie; extern u32 _MMU_MAIN_MEM_MASK; extern u32 _MMU_MAIN_MEM_MASK16; extern u32 _MMU_MAIN_MEM_MASK32; void SetupMMU(bool debugConsole, bool dsi); #ifdef DEBUG FORCEINLINE void CheckMemoryDebugEvent(EDEBUG_EVENT event, const MMU_ACCESS_TYPE type, const u32 procnum, const u32 addr, const u32 size, const u32 val) { //TODO - ugh work out a better prefetch event system if(type == MMU_AT_CODE && event == DEBUG_EVENT_READ) event = DEBUG_EVENT_EXECUTE; if(CheckDebugEvent(event)) { DebugEventData.memAccessType = type; DebugEventData.procnum = procnum; DebugEventData.addr = addr; DebugEventData.size = size; DebugEventData.val = val; HandleDebugEvent(event); } } #endif //ALERT!!!!!!!!!!!!!! //the following inline functions dont do the 0x0FFFFFFF mask. //this may result in some unexpected behavior FORCEINLINE u8 _MMU_read08(const int PROCNUM, const MMU_ACCESS_TYPE AT, const u32 addr) { #ifdef DEBUG CheckMemoryDebugEvent(DEBUG_EVENT_READ,AT,PROCNUM,addr,8,0); #endif //special handling to un-protect the ARM7 bios during debug reading if(PROCNUM == ARMCPU_ARM7 && AT == MMU_AT_DEBUG && addr<0x00004000) return T1ReadByte(MMU.ARM7_BIOS, addr); //special handling for DMA: read 0 from TCM if(PROCNUM==ARMCPU_ARM9 && AT == MMU_AT_DMA) { if(addr<0x02000000) return 0; //itcm if((addr&(~0x3FFF)) == MMU.DTCMRegion) return 0; //dtcm } if(PROCNUM==ARMCPU_ARM9) if((addr&(~0x3FFF)) == MMU.DTCMRegion) { //Returns data from DTCM (ARM9 only) return T1ReadByte(MMU.ARM9_DTCM, addr & 0x3FFF); } if ( (addr & 0x0F000000) == 0x02000000) return T1ReadByte( MMU.MAIN_MEM, addr & _MMU_MAIN_MEM_MASK); if(PROCNUM==ARMCPU_ARM9) return _MMU_ARM9_read08(addr); return _MMU_ARM7_read08(addr); } FORCEINLINE u16 _MMU_read16(const int PROCNUM, const MMU_ACCESS_TYPE AT, const u32 addr) { #ifdef DEBUG CheckMemoryDebugEvent(DEBUG_EVENT_READ,AT,PROCNUM,addr,16,0); #endif //special handling to un-protect the ARM7 bios during debug reading if(PROCNUM == ARMCPU_ARM7 && AT == MMU_AT_DEBUG && addr<0x00004000) return T1ReadWord_guaranteedAligned(MMU.ARM7_BIOS, addr); //special handling for DMA: read 0 from TCM if(PROCNUM==ARMCPU_ARM9 && AT == MMU_AT_DMA) { if(addr<0x02000000) return 0; //itcm if((addr&(~0x3FFF)) == MMU.DTCMRegion) return 0; //dtcm } //special handling for execution from arm9, since we spend so much time in there if(PROCNUM==ARMCPU_ARM9 && AT == MMU_AT_CODE) { if ((addr & 0x0F000000) == 0x02000000) return T1ReadWord_guaranteedAligned( MMU.MAIN_MEM, addr & _MMU_MAIN_MEM_MASK16); if(addr<0x02000000) return T1ReadWord_guaranteedAligned(MMU.ARM9_ITCM, addr&0x7FFE); goto dunno; } if(PROCNUM==ARMCPU_ARM9) if((addr&(~0x3FFF)) == MMU.DTCMRegion) { //Returns data from DTCM (ARM9 only) return T1ReadWord_guaranteedAligned(MMU.ARM9_DTCM, addr & 0x3FFE); } if ( (addr & 0x0F000000) == 0x02000000) return T1ReadWord_guaranteedAligned( MMU.MAIN_MEM, addr & _MMU_MAIN_MEM_MASK16); dunno: if(PROCNUM==ARMCPU_ARM9) return _MMU_ARM9_read16(addr); else return _MMU_ARM7_read16(addr); } FORCEINLINE u32 _MMU_read32(const int PROCNUM, const MMU_ACCESS_TYPE AT, const u32 addr) { #ifdef DEBUG CheckMemoryDebugEvent(DEBUG_EVENT_READ,AT,PROCNUM,addr,32,0); #endif //special handling to un-protect the ARM7 bios during debug reading if(PROCNUM == ARMCPU_ARM7 && AT == MMU_AT_DEBUG && addr<0x00004000) return T1ReadLong_guaranteedAligned(MMU.ARM7_BIOS, addr); //special handling for DMA: read 0 from TCM if(PROCNUM==ARMCPU_ARM9 && AT == MMU_AT_DMA) { if(addr<0x02000000) return 0; //itcm if((addr&(~0x3FFF)) == MMU.DTCMRegion) return 0; //dtcm } //special handling for execution from arm9, since we spend so much time in there if(PROCNUM==ARMCPU_ARM9 && AT == MMU_AT_CODE) { if ( (addr & 0x0F000000) == 0x02000000) return T1ReadLong_guaranteedAligned( MMU.MAIN_MEM, addr & _MMU_MAIN_MEM_MASK32); if(addr<0x02000000) return T1ReadLong_guaranteedAligned(MMU.ARM9_ITCM, addr&0x7FFC); //what happens when we execute from DTCM? nocash makes it look like we get 0xFFFFFFFF but i can't seem to verify it //historically, desmume would fall through to its old memory map struct //which would return unused memory (0) //it seems the hardware returns 0 or something benign because in actuality 0xFFFFFFFF is an undefined opcode //and we know our handling for that is solid goto dunno; } //special handling for execution from arm7. try reading from main memory first if(PROCNUM==ARMCPU_ARM7) { if ( (addr & 0x0F000000) == 0x02000000) return T1ReadLong_guaranteedAligned( MMU.MAIN_MEM, addr & _MMU_MAIN_MEM_MASK32); } //for other arm9 cases, we have to check from dtcm first because it is patched on top of the main memory range if(PROCNUM==ARMCPU_ARM9) { if((addr&(~0x3FFF)) == MMU.DTCMRegion) { //Returns data from DTCM (ARM9 only) return T1ReadLong_guaranteedAligned(MMU.ARM9_DTCM, addr & 0x3FFC); } if ( (addr & 0x0F000000) == 0x02000000) return T1ReadLong_guaranteedAligned( MMU.MAIN_MEM, addr & _MMU_MAIN_MEM_MASK32); } dunno: if(PROCNUM==ARMCPU_ARM9) return _MMU_ARM9_read32(addr); return _MMU_ARM7_read32(addr); } FORCEINLINE void _MMU_write08(const int PROCNUM, const MMU_ACCESS_TYPE AT, const u32 addr, u8 val) { #ifdef DEBUG CheckMemoryDebugEvent(DEBUG_EVENT_WRITE,AT,PROCNUM,addr,8,val); #endif //special handling for DMA: discard writes to TCM if(PROCNUM==ARMCPU_ARM9 && AT == MMU_AT_DMA) { if(addr<0x02000000) return; //itcm if((addr&(~0x3FFF)) == MMU.DTCMRegion) return; //dtcm } if(PROCNUM==ARMCPU_ARM9) if((addr&(~0x3FFF)) == MMU.DTCMRegion) { T1WriteByte(MMU.ARM9_DTCM, addr & 0x3FFF, val); return; } if ( (addr & 0x0F000000) == 0x02000000) { #ifdef HAVE_JIT JIT_COMPILED_FUNC_KNOWNBANK(addr, MAIN_MEM, _MMU_MAIN_MEM_MASK, 0) = 0; #endif T1WriteByte( MMU.MAIN_MEM, addr & _MMU_MAIN_MEM_MASK, val); return; } if(PROCNUM==ARMCPU_ARM9) _MMU_ARM9_write08(addr,val); else _MMU_ARM7_write08(addr,val); } FORCEINLINE void _MMU_write16(const int PROCNUM, const MMU_ACCESS_TYPE AT, const u32 addr, u16 val) { #ifdef DEBUG CheckMemoryDebugEvent(DEBUG_EVENT_WRITE,AT,PROCNUM,addr,16,val); #endif //special handling for DMA: discard writes to TCM if(PROCNUM==ARMCPU_ARM9 && AT == MMU_AT_DMA) { if(addr<0x02000000) return; //itcm if((addr&(~0x3FFF)) == MMU.DTCMRegion) return; //dtcm } if(PROCNUM==ARMCPU_ARM9) if((addr&(~0x3FFF)) == MMU.DTCMRegion) { T1WriteWord(MMU.ARM9_DTCM, addr & 0x3FFE, val); return; } if ( (addr & 0x0F000000) == 0x02000000) { #ifdef HAVE_JIT JIT_COMPILED_FUNC_KNOWNBANK(addr, MAIN_MEM, _MMU_MAIN_MEM_MASK16, 0) = 0; #endif T1WriteWord( MMU.MAIN_MEM, addr & _MMU_MAIN_MEM_MASK16, val); return; } if(PROCNUM==ARMCPU_ARM9) _MMU_ARM9_write16(addr,val); else _MMU_ARM7_write16(addr,val); } FORCEINLINE void _MMU_write32(const int PROCNUM, const MMU_ACCESS_TYPE AT, const u32 addr, u32 val) { #ifdef DEBUG CheckMemoryDebugEvent(DEBUG_EVENT_WRITE,AT,PROCNUM,addr,32,val); #endif //special handling for DMA: discard writes to TCM if(PROCNUM==ARMCPU_ARM9 && AT == MMU_AT_DMA) { if(addr<0x02000000) return; //itcm if((addr&(~0x3FFF)) == MMU.DTCMRegion) return; //dtcm } if(PROCNUM==ARMCPU_ARM9) if((addr&(~0x3FFF)) == MMU.DTCMRegion) { T1WriteLong(MMU.ARM9_DTCM, addr & 0x3FFC, val); return; } if ( (addr & 0x0F000000) == 0x02000000) { #ifdef HAVE_JIT JIT_COMPILED_FUNC_KNOWNBANK(addr, MAIN_MEM, _MMU_MAIN_MEM_MASK32, 0) = 0; JIT_COMPILED_FUNC_KNOWNBANK(addr, MAIN_MEM, _MMU_MAIN_MEM_MASK32, 1) = 0; #endif T1WriteLong( MMU.MAIN_MEM, addr & _MMU_MAIN_MEM_MASK32, val); return; } if(PROCNUM==ARMCPU_ARM9) _MMU_ARM9_write32(addr,val); else _MMU_ARM7_write32(addr,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); // 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_write8_acl(proc, adr, val) _MMU_write08(adr, val) // #define MMU_write16_acl(proc, adr, val) _MMU_write16(adr, val) // #define MMU_write32_acl(proc, adr, val) _MMU_write32(adr, val) // #define MMU_read8_acl(proc,adr,access) _MMU_read08(adr) // #define MMU_read16_acl(proc,adr,access) ((access==CP15_ACCESS_EXECUTE)?_MMU_read16(adr):_MMU_read16(adr)) // #define MMU_read32_acl(proc,adr,access) ((access==CP15_ACCESS_EXECUTE)?_MMU_read32(adr):_MMU_read32(adr)) //#endif // Use this macros for reading/writing, so the GDB stub isn't broken #define READ32(a,b) _MMU_read32((b) & 0xFFFFFFFC) #define WRITE32(a,b,c) _MMU_write32((b) & 0xFFFFFFFC,c) #define READ16(a,b) _MMU_read16((b) & 0xFFFFFFFE) #define WRITE16(a,b,c) _MMU_write16((b) & 0xFFFFFFFE,c) #define READ8(a,b) _MMU_read08(b) #define WRITE8(a,b,c) _MMU_write08(b, c) template FORCEINLINE u8 _MMU_read08(u32 addr) { return _MMU_read08(PROCNUM, AT, addr); } template FORCEINLINE u16 _MMU_read16(u32 addr) { return _MMU_read16(PROCNUM, AT, addr); } template FORCEINLINE u32 _MMU_read32(u32 addr) { return _MMU_read32(PROCNUM, AT, addr); } template FORCEINLINE void _MMU_write08(u32 addr, u8 val) { _MMU_write08(PROCNUM, AT, addr, val); } template FORCEINLINE void _MMU_write16(u32 addr, u16 val) { _MMU_write16(PROCNUM, AT, addr, val); } template FORCEINLINE void _MMU_write32(u32 addr, u32 val) { _MMU_write32(PROCNUM, AT, addr, val); } void FASTCALL MMU_DumpMemBlock(u8 proc, u32 address, u32 size, u8 *buffer); #endif desmume/src/libretro-common/net/test/net_http_test.c000664 001750 001750 00000004142 12755534123 024045 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2016 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (net_http_test.c). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include #include #include #ifdef _WIN32 #include #endif int main(void) { char *data; struct http_t *http1, *http3; size_t len, pos = 0, tot = 0; if (!network_init()) return -1; http1 = net_http_new("http://buildbot.libretro.com/nightly/win-x86/latest/mednafen_psx_libretro.dll.zip"); while (!net_http_update(http1, &pos, &tot)) printf("%.9lu / %.9lu \r",pos,tot); http3 = net_http_new("http://www.wikipedia.org/"); while (!net_http_update(http3, NULL, NULL)) {} data = (char*)net_http_data(http3, &len, false); printf("%.*s\n", (int)256, data); net_http_delete(http1); net_http_delete(http3); network_deinit(); return 0; } desmume/src/libretro-common/include/streams/000700 001750 001750 00000000000 12756420131 022326 5ustar00sergiosergio000000 000000 desmume/src/mic_alsa.cpp000664 001750 001750 00000010326 12755534123 016415 0ustar00sergiosergio000000 000000 /* Copyright (C) 2009-2010 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the this software. If not, see . */ #include #include #include "types.h" #include "mic.h" #include "debug.h" #include "readwrite.h" #include "emufile.h" #define MIC_BUFSIZE 4096 BOOL Mic_Inited = FALSE; u8 Mic_Buffer[2][MIC_BUFSIZE]; u16 Mic_BufPos; u8 Mic_PlayBuf; u8 Mic_WriteBuf; int MicButtonPressed; /* Alsa stuff */ static snd_pcm_t *pcm_handle; BOOL Mic_Init() { snd_pcm_hw_params_t *hwparams; snd_pcm_uframes_t mic_bufsize, periods; int err; if (Mic_Inited) return TRUE; if ((err = snd_pcm_open(&pcm_handle, "default", SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK)) < 0) { g_printerr("Failed to open device: %s\n", snd_strerror(err)); return FALSE; } /* Hardware params */ snd_pcm_hw_params_alloca(&hwparams); if ((err = snd_pcm_hw_params_any(pcm_handle, hwparams)) < 0) { g_printerr("Failed to setup hw parameters: %s\n", snd_strerror(err)); return FALSE; } if ((err = snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) { g_printerr("Failed to set access: %s\n", snd_strerror(err)); return FALSE; } /* 8bit signed, mono, 16000hz */ if ((err = snd_pcm_hw_params_set_format(pcm_handle, hwparams, SND_PCM_FORMAT_S8)) < 0) { g_printerr("Failed to set format: %s\n", snd_strerror(err)); return FALSE; } if ((err = snd_pcm_hw_params_set_channels(pcm_handle, hwparams, 1)) < 0) { g_printerr("Failed to set channels: %s\n", snd_strerror(err)); return FALSE; } if ((err = snd_pcm_hw_params_set_rate(pcm_handle, hwparams, 16000, 0)) < 0) { g_printerr("Failed to set rate: %s\n", snd_strerror(err)); return FALSE; } if ((err = snd_pcm_hw_params(pcm_handle, hwparams)) < 0) { g_printerr("Failed to set hw parameters: %s\n", snd_strerror(err)); return FALSE; } /* Query the driver for buffer and period sizes */ if ((err = snd_pcm_hw_params_get_buffer_size(hwparams, &mic_bufsize)) < 0) { g_printerr("Failed to get buffer size: %s\n", snd_strerror(err)); return FALSE; } if ((err = snd_pcm_hw_params_get_period_size(hwparams, &periods, 0)) < 0) { g_printerr("Failed to get period size: %s\n", snd_strerror(err)); return FALSE; } Mic_Inited = TRUE; Mic_Reset(); return TRUE; } void Mic_Reset() { if (!Mic_Inited) return; memset(Mic_Buffer, 0, MIC_BUFSIZE * 2); Mic_BufPos = 0; Mic_PlayBuf = 1; Mic_WriteBuf = 0; } void Mic_DeInit() { if (!Mic_Inited) return; Mic_Inited = FALSE; snd_pcm_drop(pcm_handle); snd_pcm_close(pcm_handle); } static void snd_pcm_read() { int error; error = snd_pcm_readi(pcm_handle, Mic_Buffer[Mic_WriteBuf], MIC_BUFSIZE); if (error < 0) error = snd_pcm_recover(pcm_handle, error, 0); if (error < 0) LOG("snd_pcm_readi FAIL!: %s\n", snd_strerror(error)); } u8 Mic_ReadSample() { u8 tmp; u8 ret; if (!Mic_Inited) return 0; tmp = Mic_Buffer[Mic_PlayBuf][Mic_BufPos >> 1]; if (Mic_BufPos & 0x1) { ret = ((tmp & 0x1) << 7); } else { ret = ((tmp & 0xFE) >> 1); snd_pcm_read(); } Mic_BufPos++; if (Mic_BufPos >= (MIC_BUFSIZE << 1)) { snd_pcm_read(); Mic_BufPos = 0; Mic_PlayBuf ^= 1; Mic_WriteBuf ^= 1; } return ret; } /* FIXME: stub! */ void mic_savestate(EMUFILE* os) { write32le((u32)(-1),os); } bool mic_loadstate(EMUFILE* is, int size) { is->fseek(size, SEEK_CUR); return TRUE; } desmume/src/saves.cpp000664 001750 001750 00000072260 12755534123 015773 0ustar00sergiosergio000000 000000 /* Copyright (C) 2006 Normmatt Copyright (C) 2006 Theo Berkau Copyright (C) 2007 Pascal Giard Copyright (C) 2008-2015 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the this software. If not, see . */ #include #include #include #include #include #include #include #include "common.h" #include "armcpu.h" #include "registers.h" #include "FIFO.h" #include "driver.h" #include "saves.h" #include "emufile.h" #include "MMU.h" #include "NDSSystem.h" #include "render3D.h" #include "cp15.h" #include "GPU.h" #include "version.h" #include "readwrite.h" #include "gfx3d.h" #include "movie.h" #include "mic.h" #include "MMU_timing.h" #include "slot1.h" #include "slot2.h" #include "SPU.h" #include "wifi.h" #include "path.h" //void*v is actually a void** which will be indirected before reading //since this isnt supported right now, it is declared in here to make things compile #define SS_INDIRECT 0x80000000 u32 _DESMUME_version = EMU_DESMUME_VERSION_NUMERIC(); u32 svn_rev = EMU_DESMUME_SUBVERSION_NUMERIC(); s64 save_time = 0; NDS_SLOT1_TYPE slot1Type = NDS_SLOT1_RETAIL_AUTO; NDS_SLOT2_TYPE slot2Type = NDS_SLOT2_AUTO; #define SAVESTATE_VERSION 12 static const char* magic = "DeSmuME SState\0"; //a savestate chunk loader can set this if it wants to permit a silent failure (for compatibility) static bool SAV_silent_fail_flag; SFORMAT SF_NDS_INFO[]={ { "GINF", 1, sizeof(gameInfo.header), &gameInfo.header}, { "GRSZ", 1, 4, &gameInfo.romsize}, { "DVMJ", 1, 1, (void*)&DESMUME_VERSION_MAJOR}, { "DVMI", 1, 1, (void*)&DESMUME_VERSION_MINOR}, { "DSBD", 1, 1, (void*)&DESMUME_VERSION_BUILD}, { "GREV", 1, 4, &svn_rev}, { "GTIM", 1, 8, &save_time}, { 0 } }; SFORMAT SF_ARM7[]={ { "7INS", 4, 1, &NDS_ARM7.instruction }, { "7INA", 4, 1, &NDS_ARM7.instruct_adr }, { "7INN", 4, 1, &NDS_ARM7.next_instruction }, { "7REG", 4,16, NDS_ARM7.R }, { "7CPS", 4, 1, &NDS_ARM7.CPSR }, { "7SPS", 4, 1, &NDS_ARM7.SPSR }, { "7DUS", 4, 1, &NDS_ARM7.R13_usr }, { "7EUS", 4, 1, &NDS_ARM7.R14_usr }, { "7DSV", 4, 1, &NDS_ARM7.R13_svc }, { "7ESV", 4, 1, &NDS_ARM7.R14_svc }, { "7DAB", 4, 1, &NDS_ARM7.R13_abt }, { "7EAB", 4, 1, &NDS_ARM7.R14_abt }, { "7DUN", 4, 1, &NDS_ARM7.R13_und }, { "7EUN", 4, 1, &NDS_ARM7.R14_und }, { "7DIR", 4, 1, &NDS_ARM7.R13_irq }, { "7EIR", 4, 1, &NDS_ARM7.R14_irq }, { "78FI", 4, 1, &NDS_ARM7.R8_fiq }, { "79FI", 4, 1, &NDS_ARM7.R9_fiq }, { "7AFI", 4, 1, &NDS_ARM7.R10_fiq }, { "7BFI", 4, 1, &NDS_ARM7.R11_fiq }, { "7CFI", 4, 1, &NDS_ARM7.R12_fiq }, { "7DFI", 4, 1, &NDS_ARM7.R13_fiq }, { "7EFI", 4, 1, &NDS_ARM7.R14_fiq }, { "7SVC", 4, 1, &NDS_ARM7.SPSR_svc }, { "7ABT", 4, 1, &NDS_ARM7.SPSR_abt }, { "7UND", 4, 1, &NDS_ARM7.SPSR_und }, { "7IRQ", 4, 1, &NDS_ARM7.SPSR_irq }, { "7FIQ", 4, 1, &NDS_ARM7.SPSR_fiq }, { "7int", 4, 1, &NDS_ARM7.intVector }, { "7LDT", 1, 1, &NDS_ARM7.LDTBit }, { "7Wai", 4, 1, &NDS_ARM7.waitIRQ }, { "7hef", 4, 1, &NDS_ARM7.halt_IE_and_IF }, { "7iws", 1, 1, &NDS_ARM7.intrWaitARM_state }, { 0 } }; SFORMAT SF_ARM9[]={ { "9INS", 4, 1, &NDS_ARM9.instruction}, { "9INA", 4, 1, &NDS_ARM9.instruct_adr}, { "9INN", 4, 1, &NDS_ARM9.next_instruction}, { "9REG", 4,16, NDS_ARM9.R}, { "9CPS", 4, 1, &NDS_ARM9.CPSR}, { "9SPS", 4, 1, &NDS_ARM9.SPSR}, { "9DUS", 4, 1, &NDS_ARM9.R13_usr}, { "9EUS", 4, 1, &NDS_ARM9.R14_usr}, { "9DSV", 4, 1, &NDS_ARM9.R13_svc}, { "9ESV", 4, 1, &NDS_ARM9.R14_svc}, { "9DAB", 4, 1, &NDS_ARM9.R13_abt}, { "9EAB", 4, 1, &NDS_ARM9.R14_abt}, { "9DUN", 4, 1, &NDS_ARM9.R13_und}, { "9EUN", 4, 1, &NDS_ARM9.R14_und}, { "9DIR", 4, 1, &NDS_ARM9.R13_irq}, { "9EIR", 4, 1, &NDS_ARM9.R14_irq}, { "98FI", 4, 1, &NDS_ARM9.R8_fiq}, { "99FI", 4, 1, &NDS_ARM9.R9_fiq}, { "9AFI", 4, 1, &NDS_ARM9.R10_fiq}, { "9BFI", 4, 1, &NDS_ARM9.R11_fiq}, { "9CFI", 4, 1, &NDS_ARM9.R12_fiq}, { "9DFI", 4, 1, &NDS_ARM9.R13_fiq}, { "9EFI", 4, 1, &NDS_ARM9.R14_fiq}, { "9SVC", 4, 1, &NDS_ARM9.SPSR_svc}, { "9ABT", 4, 1, &NDS_ARM9.SPSR_abt}, { "9UND", 4, 1, &NDS_ARM9.SPSR_und}, { "9IRQ", 4, 1, &NDS_ARM9.SPSR_irq}, { "9FIQ", 4, 1, &NDS_ARM9.SPSR_fiq}, { "9int", 4, 1, &NDS_ARM9.intVector}, { "9LDT", 1, 1, &NDS_ARM9.LDTBit}, { "9Wai", 4, 1, &NDS_ARM9.waitIRQ}, { "9hef", 4, 1, &NDS_ARM9.halt_IE_and_IF }, { "9iws", 1, 1, &NDS_ARM9.intrWaitARM_state }, { 0 } }; SFORMAT SF_MEM[]={ { "ITCM", 1, sizeof(MMU.ARM9_ITCM), MMU.ARM9_ITCM}, { "DTCM", 1, sizeof(MMU.ARM9_DTCM), MMU.ARM9_DTCM}, //for legacy purposes, WRAX is a separate variable. shouldnt be a problem. { "WRAM", 1, 0x400000, MMU.MAIN_MEM}, { "WRAX", 1, 0x400000, MMU.MAIN_MEM+0x400000}, //NOTE - this is not as large as the allocated memory. //the memory is overlarge due to the way our memory map system is setup //but there are actually no more registers than this { "9REG", 1, 0x2000, MMU.ARM9_REG}, { "VMEM", 1, sizeof(MMU.ARM9_VMEM), MMU.ARM9_VMEM}, { "OAMS", 1, sizeof(MMU.ARM9_OAM), MMU.ARM9_OAM}, //this size is specially chosen to avoid saving the blank space at the end { "LCDM", 1, 0xA4000, MMU.ARM9_LCD}, { 0 } }; SFORMAT SF_NDS[]={ { "_WCY", 4, 1, &nds.wifiCycle}, { "_TCY", 8, 8, nds.timerCycle}, { "_VCT", 4, 1, &nds.VCount}, { "_OLD", 4, 1, &nds.old}, { "_TPX", 2, 1, &nds.adc_touchX}, { "_TPY", 2, 1, &nds.adc_touchY}, { "_TPC", 2, 1, &nds.adc_jitterctr}, { "_STX", 2, 1, &nds.scr_touchX}, { "_STY", 2, 1, &nds.scr_touchY}, { "_TPB", 4, 1, &nds.isTouch}, { "_IFB", 4, 1, &nds.isFakeBooted}, { "_DBG", 4, 1, &nds._DebugConsole}, { "_ENS", 4, 1, &nds.ensataEmulation}, { "_TYP", 4, 1, &nds.ConsoleType}, { "_ENH", 4, 1, &nds.ensataHandshake}, { "_ENI", 4, 1, &nds.ensataIpcSyncCounter}, { "_SLP", 4, 1, &nds.sleeping}, { "_FBS", 4, 1, &nds.freezeBus}, { "_CEJ", 4, 1, &nds.cardEjected}, { "_PDL", 2, 1, &nds.paddle}, { "_P00", 1, 1, &nds.power1.lcd}, { "_P01", 1, 1, &nds.power1.gpuMain}, { "_P02", 1, 1, &nds.power1.gfx3d_render}, { "_P03", 1, 1, &nds.power1.gfx3d_geometry}, { "_P04", 1, 1, &nds.power1.gpuSub}, { "_P05", 1, 1, &nds.power1.dispswap}, { "_P06", 1, 1, &nds.power2.speakers}, { "_P07", 1, 1, &nds.power2.wifi}, { 0 } }; SFORMAT SF_MMU[]={ { "M7BI", 1, sizeof(MMU.ARM7_BIOS), MMU.ARM7_BIOS}, { "M7ER", 1, sizeof(MMU.ARM7_ERAM), MMU.ARM7_ERAM}, { "M7RG", 1, sizeof(MMU.ARM7_REG), MMU.ARM7_REG}, { "M7WI", 1, sizeof(MMU.ARM7_WIRAM), MMU.ARM7_WIRAM}, { "MSWI", 1, sizeof(MMU.SWIRAM), MMU.SWIRAM}, { "M9RW", 1, 1, &MMU.ARM9_RW_MODE}, { "MDTC", 4, 1, &MMU.DTCMRegion}, { "MITC", 4, 1, &MMU.ITCMRegion}, { "MTIM", 2, 8, MMU.timer}, { "MTMO", 4, 8, MMU.timerMODE}, { "MTON", 4, 8, MMU.timerON}, { "MTRN", 4, 8, MMU.timerRUN}, { "MTRL", 2, 8, MMU.timerReload}, { "MIME", 4, 2, MMU.reg_IME}, { "MIE_", 4, 2, MMU.reg_IE}, { "MIF_", 4, 2, MMU.reg_IF_bits}, { "MIFP", 4, 2, MMU.reg_IF_pending}, { "MGXC", 8, 1, &MMU.gfx3dCycles}, { "M_SX", 1, 2, &MMU.SPI_CNT}, { "M_SC", 1, 2, &MMU.SPI_CMD}, { "MASX", 1, 2, &MMU.AUX_SPI_CNT}, //{ "MASC", 1, 2, &MMU.AUX_SPI_CMD}, //zero 20-aug-2013 - this seems pointless { "MWRA", 1, 2, &MMU.WRAMCNT}, { "MDV1", 4, 1, &MMU.divRunning}, { "MDV2", 8, 1, &MMU.divResult}, { "MDV3", 8, 1, &MMU.divMod}, { "MDV5", 8, 1, &MMU.divCycles}, { "MSQ1", 4, 1, &MMU.sqrtRunning}, { "MSQ2", 4, 1, &MMU.sqrtResult}, { "MSQ4", 8, 1, &MMU.sqrtCycles}, //begin memory chips { "BUCO", 1, 1, &MMU.fw.com}, { "BUAD", 4, 1, &MMU.fw.addr}, { "BUAS", 1, 1, &MMU.fw.addr_shift}, { "BUAZ", 1, 1, &MMU.fw.addr_size}, { "BUWE", 4, 1, &MMU.fw.write_enable}, { "BUWR", 4, 1, &MMU.fw.writeable_buffer}, //end memory chips //TODO:slot-1 plugins { "GC0T", 4, 1, &MMU.dscard[0].transfer_count}, { "GC0M", 4, 1, &MMU.dscard[0].mode}, { "GC1T", 4, 1, &MMU.dscard[1].transfer_count}, { "GC1M", 4, 1, &MMU.dscard[1].mode}, //{ "MCHT", 4, 1, &MMU.CheckTimers}, //{ "MCHD", 4, 1, &MMU.CheckDMAs}, //fifos { "F0TH", 1, 1, &ipc_fifo[0].head}, { "F0TL", 1, 1, &ipc_fifo[0].tail}, { "F0SZ", 1, 1, &ipc_fifo[0].size}, { "F0BF", 4, 16, ipc_fifo[0].buf}, { "F1TH", 1, 1, &ipc_fifo[1].head}, { "F1TL", 1, 1, &ipc_fifo[1].tail}, { "F1SZ", 1, 1, &ipc_fifo[1].size}, { "F1BF", 4, 16, ipc_fifo[1].buf}, { "FDHD", 4, 1, &disp_fifo.head}, { "FDTL", 4, 1, &disp_fifo.tail}, { "FDBF", 4, 0x6000, disp_fifo.buf}, { "PMCN", 1, 1, &MMU.powerMan_CntReg}, { "PMCW", 4, 1, &MMU.powerMan_CntRegWritten}, { "PMCR", 1, 5, &MMU.powerMan_Reg}, { "MR3D", 4, 1, &MMU.reg_DISP3DCNT_bits}, { 0 } }; SFORMAT SF_MOVIE[]={ { "FRAC", 4, 1, &currFrameCounter}, { "LAGC", 4, 1, &currFrameCounter}, { 0 } }; // TODO: integrate the new wifi state variables once everything is settled SFORMAT SF_WIFI[]={ { "W000", 4, 1, &wifiMac.powerOn}, { "W010", 4, 1, &wifiMac.powerOnPending}, { "W020", 2, 1, &wifiMac.rfStatus}, { "W030", 2, 1, &wifiMac.rfPins}, { "W040", 2, 1, &wifiMac.IE}, { "W050", 2, 1, &wifiMac.IF}, { "W060", 2, 1, &wifiMac.macMode}, { "W070", 2, 1, &wifiMac.wepMode}, { "W080", 4, 1, &wifiMac.WEP_enable}, { "W100", 2, 1, &wifiMac.TXCnt}, { "W120", 2, 1, &wifiMac.TXStat}, { "W200", 2, 1, &wifiMac.RXCnt}, { "W210", 2, 1, &wifiMac.RXCheckCounter}, { "W220", 1, 6, &wifiMac.mac.bytes}, { "W230", 1, 6, &wifiMac.bss.bytes}, { "W240", 2, 1, &wifiMac.aid}, { "W250", 2, 1, &wifiMac.pid}, { "W260", 2, 1, &wifiMac.retryLimit}, { "W270", 4, 1, &wifiMac.crystalEnabled}, { "W280", 8, 1, &wifiMac.usec}, { "W290", 4, 1, &wifiMac.usecEnable}, { "W300", 8, 1, &wifiMac.ucmp}, { "W310", 4, 1, &wifiMac.ucmpEnable}, { "W320", 2, 1, &wifiMac.eCount}, { "W330", 4, 1, &wifiMac.eCountEnable}, { "WR00", 4, 1, &wifiMac.RF.CFG1.val}, { "WR01", 4, 1, &wifiMac.RF.IFPLL1.val}, { "WR02", 4, 1, &wifiMac.RF.IFPLL2.val}, { "WR03", 4, 1, &wifiMac.RF.IFPLL3.val}, { "WR04", 4, 1, &wifiMac.RF.RFPLL1.val}, { "WR05", 4, 1, &wifiMac.RF.RFPLL2.val}, { "WR06", 4, 1, &wifiMac.RF.RFPLL3.val}, { "WR07", 4, 1, &wifiMac.RF.RFPLL4.val}, { "WR08", 4, 1, &wifiMac.RF.CAL1.val}, { "WR09", 4, 1, &wifiMac.RF.TXRX1.val}, { "WR10", 4, 1, &wifiMac.RF.PCNT1.val}, { "WR11", 4, 1, &wifiMac.RF.PCNT2.val}, { "WR12", 4, 1, &wifiMac.RF.VCOT1.val}, { "W340", 1, 105, &wifiMac.BB.data[0]}, { "W350", 2, 1, &wifiMac.rfIOCnt.val}, { "W360", 2, 1, &wifiMac.rfIOStatus.val}, { "W370", 4, 1, &wifiMac.rfIOData.val}, { "W380", 2, 1, &wifiMac.bbIOCnt.val}, { "W400", 2, 0x1000, &wifiMac.RAM[0]}, { "W410", 2, 1, &wifiMac.RXRangeBegin}, { "W420", 2, 1, &wifiMac.RXRangeEnd}, { "W430", 2, 1, &wifiMac.RXWriteCursor}, { "W460", 2, 1, &wifiMac.RXReadCursor}, { "W470", 2, 1, &wifiMac.RXUnits}, { "W480", 2, 1, &wifiMac.RXBufCount}, { "W490", 2, 1, &wifiMac.CircBufReadAddress}, { "W500", 2, 1, &wifiMac.CircBufWriteAddress}, { "W510", 2, 1, &wifiMac.CircBufRdEnd}, { "W520", 2, 1, &wifiMac.CircBufRdSkip}, { "W530", 2, 1, &wifiMac.CircBufWrEnd}, { "W540", 2, 1, &wifiMac.CircBufWrSkip}, { "W580", 2, 0x800, &wifiMac.IOPorts[0]}, { "W590", 2, 1, &wifiMac.randomSeed}, { 0 } }; extern SFORMAT SF_RTC[]; static u8 reserveVal = 0; SFORMAT reserveChunks[] = { { "RESV", 1, 1, &reserveVal}, { 0 } }; #ifdef MSB_FIRST /* endian-flips count bytes. count should be even and nonzero. */ static INLINE void FlipByteOrder(u8 *src, u32 count) { u8 *start=src; u8 *end=src+count-1; if((count&1) || !count) return; /* This shouldn't happen. */ while(count--) { u8 tmp; tmp=*end; *end=*start; *start=tmp; end--; start++; } } #endif static bool s_slot1_loadstate(EMUFILE* is, int size) { u32 version = is->read32le(); //version 0: if(version >= 0) { u8 slotID = is->read32le(); slot1Type = NDS_SLOT1_RETAIL_AUTO; if (version >= 1) slot1_getTypeByID(slotID, slot1Type); slot1_Change(slot1Type); EMUFILE_MEMORY temp; is->readMemoryStream(&temp); temp.fseek(0,SEEK_SET); slot1_Loadstate(&temp); } return true; } static void s_slot1_savestate(EMUFILE* os) { u32 version = 1; os->write32le(version); u8 slotID = (u8)slot1_List[slot1_GetSelectedType()]->info()->id(); os->write32le(slotID); EMUFILE_MEMORY temp; slot1_Savestate(&temp); os->writeMemoryStream(&temp); } static bool s_slot2_loadstate(EMUFILE* is, int size) { u32 version = is->read32le(); //version 0: if(version >= 0) { slot2Type = NDS_SLOT2_AUTO; u8 slotID = is->read32le(); if (version == 0) slot2_getTypeByID(slotID, slot2Type); slot2_Change(slot2Type); EMUFILE_MEMORY temp; is->readMemoryStream(&temp); temp.fseek(0,SEEK_SET); slot2_Loadstate(&temp); } return true; } static void s_slot2_savestate(EMUFILE* os) { u32 version = 0; os->write32le(version); //version 0: u8 slotID = (u8)slot2_List[slot2_GetSelectedType()]->info()->id(); os->write32le(slotID); EMUFILE_MEMORY temp; slot2_Savestate(&temp); os->writeMemoryStream(&temp); } static void mmu_savestate(EMUFILE* os) { u32 version = 8; write32le(version,os); //version 2: MMU_new.backupDevice.save_state(os); //version 3: MMU_new.gxstat.savestate(os); for(int i=0;i<2;i++) for(int j=0;j<4;j++) MMU_new.dma[i][j].savestate(os); MMU_timing.arm9codeFetch.savestate(os, version); MMU_timing.arm9dataFetch.savestate(os, version); MMU_timing.arm7codeFetch.savestate(os, version); MMU_timing.arm7dataFetch.savestate(os, version); MMU_timing.arm9codeCache.savestate(os, version); MMU_timing.arm9dataCache.savestate(os, version); //version 4: MMU_new.sqrt.savestate(os); MMU_new.div.savestate(os); //version 6: MMU_new.dsi_tsc.save_state(os); //version 8: os->write32le(MMU.fw.size); os->fwrite(MMU.fw.data,MMU.fw.size); } static bool mmu_loadstate(EMUFILE* is, int size) { //read version u32 version; if(read32le(&version,is) != 1) return false; if(version == 0 || version == 1) { u32 bupmem_size; u32 addr_size; if(version == 0) { //version 0 was buggy and didnt save the type. //it would silently fail if there was a size mismatch SAV_silent_fail_flag = true; if(read32le(&bupmem_size,is) != 1) return false; //if(bupmem_size != MMU.bupmem.size) return false; //mismatch between current initialized and saved size addr_size = BackupDevice::addr_size_for_old_save_size(bupmem_size); } else if(version == 1) { //version 1 reinitializes the save system with the type that was saved u32 bupmem_type; if(read32le(&bupmem_type,is) != 1) return false; if(read32le(&bupmem_size,is) != 1) return false; addr_size = BackupDevice::addr_size_for_old_save_type(bupmem_type); if(addr_size == 0xFFFFFFFF) addr_size = BackupDevice::addr_size_for_old_save_size(bupmem_size); } if(addr_size == 0xFFFFFFFF) return false; u8* temp = new u8[bupmem_size]; is->fread((char*)temp,bupmem_size); MMU_new.backupDevice.load_old_state(addr_size,temp,bupmem_size); delete[] temp; if(is->fail()) return false; } if(version < 2) return true; bool ok = MMU_new.backupDevice.load_state(is); if(version < 3) return ok; ok &= MMU_new.gxstat.loadstate(is); for(int i=0;i<2;i++) for(int j=0;j<4;j++) ok &= MMU_new.dma[i][j].loadstate(is); ok &= MMU_timing.arm9codeFetch.loadstate(is, version); ok &= MMU_timing.arm9dataFetch.loadstate(is, version); ok &= MMU_timing.arm7codeFetch.loadstate(is, version); ok &= MMU_timing.arm7dataFetch.loadstate(is, version); ok &= MMU_timing.arm9codeCache.loadstate(is, version); ok &= MMU_timing.arm9dataCache.loadstate(is, version); if(version < 4) return ok; ok &= MMU_new.sqrt.loadstate(is,version); ok &= MMU_new.div.loadstate(is,version); //to prevent old savestates from confusing IF bits, mask out ones which had been stored but should have been generated MMU.reg_IF_bits[0] &= ~0x00200000; MMU.reg_IF_bits[1] &= ~0x00000000; MMU_new.gxstat.fifo_low = gxFIFO.size <= 127; MMU_new.gxstat.fifo_empty = gxFIFO.size == 0; if(version < 5) MMU.reg_DISP3DCNT_bits = T1ReadWord(MMU.ARM9_REG,0x60); if(version < 6) return ok; MMU_new.dsi_tsc.load_state(is); //version 6 if(version < 7) { //recover WRAMCNT from the stashed WRAMSTAT memory location MMU.WRAMCNT = MMU.MMU_MEM[ARMCPU_ARM7][0x40][0x241]; } if(version<8) return ok; //version 8: delete[] MMU.fw.data; MMU.fw.size = is->read32le(); MMU.fw.data = new u8[size]; is->fread(MMU.fw.data,MMU.fw.size); return ok; } static void cp15_savestate(EMUFILE* os) { //version write32le(1,os); cp15.saveone(os); //ARM7 not have coprocessor //cp15_saveone((armcp15_t *)NDS_ARM7.coproc[15],os); } static bool cp15_loadstate(EMUFILE* is, int size) { //read version u32 version; if(read32le(&version,is) != 1) return false; if(version > 1) return false; if(!cp15.loadone(is)) return false; if(version == 0) { //ARM7 not have coprocessor u8 *tmp_buf = new u8 [sizeof(armcp15_t)]; if (!tmp_buf) return false; if(!cp15.loadone(is)) return false; delete [] tmp_buf; tmp_buf = NULL; } return true; } // note: guessSF is so we don't have to do a linear search through the SFORMAT array every time // in the (most common) case that we already know where the next entry is. static const SFORMAT *CheckS(const SFORMAT *guessSF, const SFORMAT *firstSF, u32 size, u32 count, char *desc) { const SFORMAT *sf = guessSF ? guessSF : firstSF; while(sf->v) { //NOT SUPPORTED RIGHT NOW //if(sf->size==~0) // Link to another SFORMAT structure. //{ // SFORMAT *tmp; // if((tmp= CheckS((SFORMAT *)sf->v, tsize, desc) )) // return(tmp); // sf++; // continue; //} if(!memcmp(desc,sf->desc,4)) { if(sf->size != size || sf->count != count) return 0; return sf; } // failed to find it, have to keep iterating if(guessSF) { sf = firstSF; guessSF = NULL; } else { sf++; } } return 0; } static bool ReadStateChunk(EMUFILE* is, const SFORMAT *sf, int size) { const SFORMAT *tmp = NULL; const SFORMAT *guessSF = NULL; int temp = is->ftell(); while(is->ftell()fread(toa,4); if(is->fail()) return false; if(!read32le(&sz,is)) return false; if(!read32le(&count,is)) return false; if((tmp=CheckS(guessSF,sf,sz,count,toa))) { #ifdef MSB_FIRST if(sz == 1) { //special case: read a huge byte array is->fread((char *)tmp->v,count); } else { for(unsigned int i=0;ifread((char *)tmp->v + i*sz,sz); FlipByteOrder((u8*)tmp->v + i*sz,sz); } } #else // no need to ever loop one at a time if not flipping byte order is->fread((char *)tmp->v,sz*count); #endif guessSF = tmp + 1; } else { is->fseek(sz*count,SEEK_CUR); guessSF = NULL; } } // while(...) return true; } static int SubWrite(EMUFILE* os, const SFORMAT *sf) { uint32 acc=0; #ifdef DEBUG std::set keyset; #endif const SFORMAT* temp = sf; while(temp->v) { const SFORMAT* seek = sf; while(seek->v && seek != temp) { if(!strcmp(seek->desc,temp->desc)) { printf("ERROR! duplicated chunk name: %s\n", temp->desc); } seek++; } temp++; } while(sf->v) { //not supported right now //if(sf->size==~0) //Link to another struct //{ // uint32 tmp; // if(!(tmp=SubWrite(os,(SFORMAT *)sf->v))) // return(0); // acc+=tmp; // sf++; // continue; //} int count = sf->count; int size = sf->size; //add size of current node to the accumulator acc += 4 + sizeof(sf->size) + sizeof(sf->count); acc += count * size; if(os) //Are we writing or calculating the size of this block? { os->fwrite(sf->desc,4); write32le(sf->size,os); write32le(sf->count,os); #ifdef DEBUG //make sure we dont dup any keys if(keyset.find(sf->desc) != keyset.end()) { printf("duplicate save key!\n"); assert(false); } keyset.insert(sf->desc); #endif #ifdef MSB_FIRST if(size == 1) { //special case: write a huge byte array os->fwrite((char *)sf->v,count); } else { for(int i=0;iv + i*size, size); os->fwrite((char*)sf->v + i*size,size); //Now restore the original byte order. FlipByteOrder((u8*)sf->v + i*size, size); } } #else // no need to ever loop one at a time if not flipping byte order os->fwrite((char *)sf->v,size*count); #endif } sf++; } return(acc); } static int savestate_WriteChunk(EMUFILE* os, int type, const SFORMAT *sf) { write32le(type,os); if(!sf) return 4; int bsize = SubWrite((EMUFILE*)0,sf); write32le(bsize,os); if(!SubWrite(os,sf)) { return 8; } return (bsize+8); } static void savestate_WriteChunk(EMUFILE* os, int type, void (*saveproc)(EMUFILE* os)) { u32 pos1 = os->ftell(); //write the type, size(placeholder), and data write32le(type,os); os->fseek(4, SEEK_CUR); // skip the size, we write that later saveproc(os); //get the size u32 pos2 = os->ftell(); assert(pos2 != (u32)-1); // if this assert fails, saveproc did something bad u32 size = (pos2 - pos1) - (2 * sizeof(u32)); //fill in the actual size os->fseek(pos1 + sizeof(u32),SEEK_SET); write32le(size,os); os->fseek(pos2,SEEK_SET); /* // old version of this function, // for reference in case the new one above starts misbehaving somehow: // - this is retarded. why not write placeholders for size and then write directly to the stream //and then go back and fill them in //get the size memorystream mstemp; saveproc(&mstemp); mstemp.flush(); u32 size = mstemp.size(); //write the type, size, and data write32le(type,os); write32le(size,os); os->write(mstemp.buf(),size); */ } static void writechunks(EMUFILE* os); bool savestate_save(EMUFILE* outstream) { #ifdef HAVE_JIT arm_jit_sync(); #endif EMUFILE_MEMORY ms; EMUFILE* os = outstream; os->fseek(32,SEEK_SET); //skip the header writechunks(os); //save the length of the file u32 len = os->ftell(); u32 comprlen = 0xFFFFFFFF; u8* cbuf; //dump the header outstream->fseek(0,SEEK_SET); outstream->fwrite(magic,16); write32le(SAVESTATE_VERSION,outstream); write32le(EMU_DESMUME_VERSION_NUMERIC(),outstream); //desmume version write32le(len,outstream); //uncompressed length write32le(comprlen,outstream); //compressed length (-1 if it is not compressed) return true; } static void writechunks(EMUFILE* os) { DateTime tm = DateTime::get_Now(); svn_rev = EMU_DESMUME_SUBVERSION_NUMERIC(); save_time = tm.get_Ticks(); savestate_WriteChunk(os,1,SF_ARM9); savestate_WriteChunk(os,2,SF_ARM7); savestate_WriteChunk(os,3,cp15_savestate); savestate_WriteChunk(os,4,SF_MEM); savestate_WriteChunk(os,5,SF_NDS); savestate_WriteChunk(os,51,nds_savestate); savestate_WriteChunk(os,60,SF_MMU); savestate_WriteChunk(os,61,mmu_savestate); savestate_WriteChunk(os,7,gpu_savestate); savestate_WriteChunk(os,8,spu_savestate); savestate_WriteChunk(os,81,mic_savestate); savestate_WriteChunk(os,90,SF_GFX3D); savestate_WriteChunk(os,91,gfx3d_savestate); savestate_WriteChunk(os,100,SF_MOVIE); savestate_WriteChunk(os,110,SF_WIFI); savestate_WriteChunk(os,120,SF_RTC); savestate_WriteChunk(os,130,SF_NDS_INFO); savestate_WriteChunk(os,140,s_slot1_savestate); savestate_WriteChunk(os,150,s_slot2_savestate); // reserved for future versions savestate_WriteChunk(os,160,reserveChunks); savestate_WriteChunk(os,170,reserveChunks); savestate_WriteChunk(os,180,reserveChunks); // ============================ savestate_WriteChunk(os,0xFFFFFFFF,(SFORMAT*)0); } static bool ReadStateChunks(EMUFILE* is, s32 totalsize) { bool ret = true; bool haveInfo = false; s64 save_time = 0; u32 romsize = 0; u8 version_major = 0; u8 version_minor = 0; u8 version_build = 0; NDS_header header; SFORMAT SF_INFO[]={ { "GINF", 1, sizeof(header), &header}, { "GRSZ", 1, 4, &romsize}, { "DVMJ", 1, 1, &version_major}, { "DVMI", 1, 1, &version_minor}, { "DSBD", 1, 1, &version_build}, { "GREV", 1, 4, &svn_rev}, { "GTIM", 1, 8, &save_time}, { 0 } }; memset(&header, 0, sizeof(header)); while(totalsize > 0) { u32 size = 0; u32 t = 0; if(!read32le(&t,is)) { ret=false; break; } if(t == 0xFFFFFFFF) break; if(!read32le(&size,is)) { ret=false; break; } switch(t) { case 1: if(!ReadStateChunk(is,SF_ARM9,size)) ret=false; break; case 2: if(!ReadStateChunk(is,SF_ARM7,size)) ret=false; break; case 3: if(!cp15_loadstate(is,size)) ret=false; break; case 4: if(!ReadStateChunk(is,SF_MEM,size)) ret=false; break; case 5: if(!ReadStateChunk(is,SF_NDS,size)) ret=false; break; case 51: if(!nds_loadstate(is,size)) ret=false; break; case 60: if(!ReadStateChunk(is,SF_MMU,size)) ret=false; break; case 61: if(!mmu_loadstate(is,size)) ret=false; break; case 7: if(!gpu_loadstate(is,size)) ret=false; break; case 8: if(!spu_loadstate(is,size)) ret=false; break; case 81: if(!mic_loadstate(is,size)) ret=false; break; case 90: if(!ReadStateChunk(is,SF_GFX3D,size)) ret=false; break; case 91: if(!gfx3d_loadstate(is,size)) ret=false; break; case 100: if(!ReadStateChunk(is,SF_MOVIE, size)) ret=false; break; case 101: break; case 110: if(!ReadStateChunk(is,SF_WIFI,size)) ret=false; break; case 120: if(!ReadStateChunk(is,SF_RTC,size)) ret=false; break; case 130: if(!ReadStateChunk(is,SF_INFO,size)) ret=false; break; case 140: if(!s_slot1_loadstate(is, size)) ret=false; break; case 150: if(!s_slot2_loadstate(is, size)) ret=false; break; // reserved for future versions case 160: case 170: case 180: if(!ReadStateChunk(is,reserveChunks,size)) ret=false; break; // ============================ default: return false; } if(!ret) return false; } return ret; } static void loadstate() { // This should regenerate the vram banks for (int i = 0; i < 0xA; i++) _MMU_write08(0x04000240+i, _MMU_read08(0x04000240+i)); // This should regenerate the graphics power control register _MMU_write16(0x04000304, _MMU_read16(0x04000304)); // This should regenerate the graphics configuration //zero 27-jul-09 : was formerly up to 7F but that wrote to dispfifo which is dumb (one of nitsuja's desynch bugs [that he found, not caused]) //so then i brought it down to 66 but this resulted in a conceptual bug with affine start registers, which shouldnt get regenerated //so then i just made this exhaustive list // for (int i = REG_BASE_DISPA; i<=REG_BASE_DISPA + 0x66; i+=2) //_MMU_write16(i, _MMU_read16(i)); // for (int i = REG_BASE_DISPB; i<=REG_BASE_DISPB + 0x7F; i+=2) //_MMU_write16(i, _MMU_read16(i)); static const u8 mainRegenAddr[] = {0x00,0x02,0x08,0x0a,0x0c,0x0e,0x40,0x42,0x44,0x46,0x48,0x4a,0x4c,0x50,0x52,0x54,0x64,0x66,0x6c}; static const u8 subRegenAddr[] = {0x00,0x02,0x08,0x0a,0x0c,0x0e,0x40,0x42,0x44,0x46,0x48,0x4a,0x4c,0x50,0x52,0x54,0x6c}; for(u32 i=0;i(REG_BASE_DISPA+mainRegenAddr[i], _MMU_read16(REG_BASE_DISPA+mainRegenAddr[i])); for(u32 i=0;i(REG_BASE_DISPB+subRegenAddr[i], _MMU_read16(REG_BASE_DISPB+subRegenAddr[i])); // no need to restore 0x60 since control and MMU.ARM9_REG are both in the savestates, and restoring it could mess up the ack bits anyway SetupMMU(nds.Is_DebugConsole(),nds.Is_DSI()); execute = !driver->EMU_IsEmulationPaused(); } bool savestate_load(EMUFILE* is) { SAV_silent_fail_flag = false; char header[16]; is->fread(header,16); if(is->fail() || memcmp(header,magic,16)) return false; u32 ssversion,len,comprlen; if(!read32le(&ssversion,is)) return false; if(!read32le(&_DESMUME_version,is)) return false; if(!read32le(&len,is)) return false; if(!read32le(&comprlen,is)) return false; if(ssversion != SAVESTATE_VERSION) return false; std::vector buf(len); is->fread((char*)&buf[0],len-32); //GO!! READ THE SAVESTATE //THERE IS NO GOING BACK NOW //reset the emulator first to clean out the host's state NDS_Reset(); //reset some options to their old defaults which werent saved nds._DebugConsole = FALSE; //GPU_Reset(MainScreen.gpu, 0); //GPU_Reset(SubScreen.gpu, 1); //gfx3d_reset(); //gpu3D->NDS_3D_Reset(); //SPU_Reset(); EMUFILE_MEMORY mstemp(&buf); bool x = ReadStateChunks(&mstemp,(s32)len); if(!x && !SAV_silent_fail_flag) { msgbox->error("Error loading savestate. It failed halfway through;\nSince there is no savestate backup system, your current game session is wrecked"); return false; } loadstate(); if(nds.ConsoleType != CommonSettings.ConsoleType) { printf("WARNING: forcing console type to: ConsoleType=%d\n",nds.ConsoleType); } if((nds._DebugConsole!=0) != CommonSettings.DebugConsole) { printf("WARNING: forcing console debug mode to: debugmode=%s\n",nds._DebugConsole?"TRUE":"FALSE"); } return true; } desmume/src/utils/AsmJit/x86/x86compileritem.h000664 001750 001750 00000024117 12755534123 022330 0ustar00sergiosergio000000 000000 // [AsmJit] // Complete JIT Assembler for C++ Language. // // [License] // Zlib - See COPYING file in this package. // [Guard] #ifndef _ASMJIT_X86_X86COMPILERITEM_H #define _ASMJIT_X86_X86COMPILERITEM_H // [Dependencies - AsmJit] #include "../x86/x86assembler.h" #include "../x86/x86compiler.h" // [Api-Begin] #include "../core/apibegin.h" namespace AsmJit { //! @addtogroup AsmJit_X86 //! @{ // ============================================================================ // [AsmJit::X86CompilerAlign] // ============================================================================ //! @brief Compiler align item. struct X86CompilerAlign : public CompilerAlign { ASMJIT_NO_COPY(X86CompilerAlign) // -------------------------------------------------------------------------- // [Construction / Destruction] // -------------------------------------------------------------------------- //! @brief Create a new @ref CompilerAlign instance. ASMJIT_API X86CompilerAlign(X86Compiler* x86Compiler, uint32_t size = 0); //! @brief Destroy the @ref CompilerAlign instance. ASMJIT_API virtual ~X86CompilerAlign(); // -------------------------------------------------------------------------- // [Accessors] // -------------------------------------------------------------------------- //! @brief Get compiler as @ref X86Compiler. inline X86Compiler* getCompiler() const { return reinterpret_cast(_compiler); } // -------------------------------------------------------------------------- // [Interface] // -------------------------------------------------------------------------- ASMJIT_API virtual void emit(Assembler& a); }; // ============================================================================ // [AsmJit::X86CompilerHint] // ============================================================================ //! @brief @ref X86Compiler variable hint item. struct X86CompilerHint : public CompilerHint { ASMJIT_NO_COPY(X86CompilerHint) // -------------------------------------------------------------------------- // [Construction / Destruction] // -------------------------------------------------------------------------- //! @brief Create a new @ref X86CompilerHint instance. ASMJIT_API X86CompilerHint(X86Compiler* compiler, X86CompilerVar* var, uint32_t hintId, uint32_t hintValue); //! @brief Destroy the @ref X86CompilerHint instance. ASMJIT_API virtual ~X86CompilerHint(); // -------------------------------------------------------------------------- // [Accessors] // -------------------------------------------------------------------------- //! @brief Get variable as @ref X86CompilerVar. inline X86CompilerVar* getVar() const { return reinterpret_cast(_var); } // -------------------------------------------------------------------------- // [Interface] // -------------------------------------------------------------------------- ASMJIT_API virtual void prepare(CompilerContext& cc); ASMJIT_API virtual CompilerItem* translate(CompilerContext& cc); // -------------------------------------------------------------------------- // [Misc] // -------------------------------------------------------------------------- ASMJIT_API virtual int getMaxSize() const; }; // ============================================================================ // [AsmJit::X86CompilerTarget] // ============================================================================ //! @brief X86Compiler target item. struct X86CompilerTarget : public CompilerTarget { ASMJIT_NO_COPY(X86CompilerTarget) // -------------------------------------------------------------------------- // [Construction / Destruction] // -------------------------------------------------------------------------- //! @brief Create a new @ref X86CompilerTarget instance. ASMJIT_API X86CompilerTarget(X86Compiler* x86Compiler, const Label& target); //! @brief Destroy the @ref X86CompilerTarget instance. ASMJIT_API virtual ~X86CompilerTarget(); // -------------------------------------------------------------------------- // [Accessors] // -------------------------------------------------------------------------- //! @brief Get compiler as @ref X86Compiler. inline X86Compiler* getCompiler() const { return reinterpret_cast(_compiler); } //! @brief Get state as @ref X86CompilerState. inline X86CompilerState* getState() const { return reinterpret_cast(_state); } // -------------------------------------------------------------------------- // [Interface] // -------------------------------------------------------------------------- ASMJIT_API virtual void prepare(CompilerContext& cc); ASMJIT_API virtual CompilerItem* translate(CompilerContext& cc); ASMJIT_API virtual void emit(Assembler& a); }; // ============================================================================ // [AsmJit::X86CompilerInst] // ============================================================================ //! @brief @ref X86Compiler instruction item. struct X86CompilerInst : public CompilerInst { ASMJIT_NO_COPY(X86CompilerInst) // -------------------------------------------------------------------------- // [Construction / Destruction] // -------------------------------------------------------------------------- //! @brief Create a new @ref X86CompilerInst instance. ASMJIT_API X86CompilerInst(X86Compiler* x86Compiler, uint32_t code, Operand* opData, uint32_t opCount); //! @brief Destroy the @ref X86CompilerInst instance. ASMJIT_API virtual ~X86CompilerInst(); // -------------------------------------------------------------------------- // [Accessors] // -------------------------------------------------------------------------- //! @brief Get compiler as @ref X86Compiler. inline X86Compiler* getCompiler() const { return reinterpret_cast(_compiler); } //! @brief Get whether the instruction is special. inline bool isSpecial() const { return (_instFlags & kX86CompilerInstFlagIsSpecial) != 0; } //! @brief Get whether the instruction is FPU. inline bool isFpu() const { return (_instFlags & kX86CompilerInstFlagIsFpu) != 0; } //! @brief Get whether the instruction is used with GpbLo register. inline bool isGpbLoUsed() const { return (_instFlags & kX86CompilerInstFlagIsGpbLoUsed) != 0; } //! @brief Get whether the instruction is used with GpbHi register. inline bool isGpbHiUsed() const { return (_instFlags & kX86CompilerInstFlagIsGpbHiUsed) != 0; } //! @brief Get memory operand. inline Mem* getMemOp() { return _memOp; } //! @brief Set memory operand. inline void setMemOp(Mem* memOp) { _memOp = memOp; } //! @brief Get operands array (3 operands total). inline VarAllocRecord* getVars() { return _vars; } //! @brief Get operands array (3 operands total). inline const VarAllocRecord* getVars() const { return _vars; } // -------------------------------------------------------------------------- // [Interface] // -------------------------------------------------------------------------- ASMJIT_API virtual void prepare(CompilerContext& cc); ASMJIT_API virtual CompilerItem* translate(CompilerContext& cc); ASMJIT_API virtual void emit(Assembler& a); // -------------------------------------------------------------------------- // [Misc] // -------------------------------------------------------------------------- ASMJIT_API virtual int getMaxSize() const; ASMJIT_API virtual bool _tryUnuseVar(CompilerVar* v); // -------------------------------------------------------------------------- // [Members] // -------------------------------------------------------------------------- //! @brief Memory operand or NULL. Mem* _memOp; //! @brief Variables (extracted from operands). VarAllocRecord* _vars; }; // ============================================================================ // [AsmJit::X86CompilerJmpInst] // ============================================================================ //! @brief @ref X86Compiler "jmp" instruction item. struct X86CompilerJmpInst : public X86CompilerInst { ASMJIT_NO_COPY(X86CompilerJmpInst) // -------------------------------------------------------------------------- // [Construction / Destruction] // -------------------------------------------------------------------------- ASMJIT_API X86CompilerJmpInst(X86Compiler* x86Compiler, uint32_t code, Operand* opData, uint32_t opCount); ASMJIT_API virtual ~X86CompilerJmpInst(); // -------------------------------------------------------------------------- // [Accessors] // -------------------------------------------------------------------------- inline X86CompilerJmpInst* getJumpNext() const { return _jumpNext; } inline bool isTaken() const { return (_instFlags & kX86CompilerInstFlagIsTaken) != 0; } // -------------------------------------------------------------------------- // [Interface] // -------------------------------------------------------------------------- ASMJIT_API virtual void prepare(CompilerContext& cc); ASMJIT_API virtual CompilerItem* translate(CompilerContext& cc); ASMJIT_API virtual void emit(Assembler& a); // -------------------------------------------------------------------------- // [DoJump] // -------------------------------------------------------------------------- ASMJIT_API void doJump(CompilerContext& cc); // -------------------------------------------------------------------------- // [Jump] // -------------------------------------------------------------------------- ASMJIT_API virtual CompilerTarget* getJumpTarget() const; // -------------------------------------------------------------------------- // [Members] // -------------------------------------------------------------------------- //! @brief Jump target. X86CompilerTarget* _jumpTarget; //! @brief Next jump to the same target in a single linked list. X86CompilerJmpInst *_jumpNext; //! @brief State associated with the jump. X86CompilerState* _state; }; //! @} } // AsmJit namespace // [Api-End] #include "../core/apiend.h" // [Guard] #endif // _ASMJIT_X86_X86COMPILERITEM_H desmume/src/utils/datetime.cpp000664 001750 001750 00000000527 12755534123 017603 0ustar00sergiosergio000000 000000 #include "datetime.h" const char* DateTime::monthnames[] = { NULL, "JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT", "NOV", "DEC" }; const int DateTime::daysmonth[] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; const int DateTime::daysmonthleap[] = { 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; desmume/src/libretro-common/gfx/scaler/scaler_filter.c000664 001750 001750 00000021337 12755534123 024274 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2015 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (scaler_filter.c). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include #include #include #include #include #include #include #include static bool allocate_filters(struct scaler_ctx *ctx) { ctx->horiz.filter = (int16_t*)scaler_alloc(sizeof(int16_t), ctx->horiz.filter_stride * ctx->out_width); ctx->horiz.filter_pos = (int*)scaler_alloc(sizeof(int), ctx->out_width); ctx->vert.filter = (int16_t*)scaler_alloc(sizeof(int16_t), ctx->vert.filter_stride * ctx->out_height); ctx->vert.filter_pos = (int*)scaler_alloc(sizeof(int), ctx->out_height); return ctx->horiz.filter && ctx->vert.filter; } static void gen_filter_point_sub(struct scaler_filter *filter, int len, int pos, int step) { int i; for (i = 0; i < len; i++, pos += step) { filter->filter_pos[i] = pos >> 16; filter->filter[i] = FILTER_UNITY; } } static bool gen_filter_point(struct scaler_ctx *ctx) { int x_pos, x_step, y_pos, y_step; ctx->horiz.filter_len = 1; ctx->horiz.filter_stride = 1; ctx->vert.filter_len = 1; ctx->vert.filter_stride = 1; if (!allocate_filters(ctx)) return false; x_pos = (1 << 15) * ctx->in_width / ctx->out_width - (1 << 15); x_step = (1 << 16) * ctx->in_width / ctx->out_width; y_pos = (1 << 15) * ctx->in_height / ctx->out_height - (1 << 15); y_step = (1 << 16) * ctx->in_height / ctx->out_height; gen_filter_point_sub(&ctx->horiz, ctx->out_width, x_pos, x_step); gen_filter_point_sub(&ctx->vert, ctx->out_height, y_pos, y_step); ctx->scaler_special = scaler_argb8888_point_special; return true; } static void gen_filter_bilinear_sub(struct scaler_filter *filter, int len, int pos, int step) { int i; for (i = 0; i < len; i++, pos += step) { filter->filter_pos[i] = pos >> 16; filter->filter[i * 2 + 1] = (pos & 0xffff) >> 2; filter->filter[i * 2 + 0] = FILTER_UNITY - filter->filter[i * 2 + 1]; } } static bool gen_filter_bilinear(struct scaler_ctx *ctx) { int x_pos, x_step, y_pos, y_step; ctx->horiz.filter_len = 2; ctx->horiz.filter_stride = 2; ctx->vert.filter_len = 2; ctx->vert.filter_stride = 2; if (!allocate_filters(ctx)) return false; x_pos = (1 << 15) * ctx->in_width / ctx->out_width - (1 << 15); x_step = (1 << 16) * ctx->in_width / ctx->out_width; y_pos = (1 << 15) * ctx->in_height / ctx->out_height - (1 << 15); y_step = (1 << 16) * ctx->in_height / ctx->out_height; gen_filter_bilinear_sub(&ctx->horiz, ctx->out_width, x_pos, x_step); gen_filter_bilinear_sub(&ctx->vert, ctx->out_height, y_pos, y_step); return true; } static void gen_filter_sinc_sub(struct scaler_filter *filter, int len, int pos, int step, double phase_mul) { int i, j; const int sinc_size = filter->filter_len; for (i = 0; i < len; i++, pos += step) { filter->filter_pos[i] = pos >> 16; for (j = 0; j < sinc_size; j++) { double sinc_phase = M_PI * ((double)((sinc_size << 15) + (pos & 0xffff)) / 0x10000 - j); double lanczos_phase = sinc_phase / ((sinc_size >> 1)); int16_t sinc_val = FILTER_UNITY * sinc(sinc_phase * phase_mul) * sinc(lanczos_phase) * phase_mul; filter->filter[i * sinc_size + j] = sinc_val; } } } static bool gen_filter_sinc(struct scaler_ctx *ctx) { int x_pos, x_step, y_pos, y_step; double phase_mul_horiz, phase_mul_vert; /* Need to expand the filter when downsampling * to get a proper low-pass effect. */ const int sinc_size = 8 * ((ctx->in_width > ctx->out_width) ? next_pow2(ctx->in_width / ctx->out_width) : 1); ctx->horiz.filter_len = sinc_size; ctx->horiz.filter_stride = sinc_size; ctx->vert.filter_len = sinc_size; ctx->vert.filter_stride = sinc_size; if (!allocate_filters(ctx)) return false; x_pos = (1 << 15) * ctx->in_width / ctx->out_width - (1 << 15) - (sinc_size << 15); x_step = (1 << 16) * ctx->in_width / ctx->out_width; y_pos = (1 << 15) * ctx->in_height / ctx->out_height - (1 << 15) - (sinc_size << 15); y_step = (1 << 16) * ctx->in_height / ctx->out_height; phase_mul_horiz = ctx->in_width > ctx->out_width ? (double)ctx->out_width / ctx->in_width : 1.0; phase_mul_vert = ctx->in_height > ctx->out_height ? (double)ctx->out_height / ctx->in_height : 1.0; gen_filter_sinc_sub(&ctx->horiz, ctx->out_width, x_pos, x_step, phase_mul_horiz); gen_filter_sinc_sub(&ctx->vert, ctx->out_height, y_pos, y_step, phase_mul_vert); return true; } static bool validate_filter(struct scaler_ctx *ctx) { int i; int max_h_pos; int max_w_pos = ctx->in_width - ctx->horiz.filter_len; for (i = 0; i < ctx->out_width; i++) { if (ctx->horiz.filter_pos[i] > max_w_pos || ctx->horiz.filter_pos[i] < 0) { fprintf(stderr, "Out X = %d => In X = %d\n", i, ctx->horiz.filter_pos[i]); return false; } } max_h_pos = ctx->in_height - ctx->vert.filter_len; for (i = 0; i < ctx->out_height; i++) { if (ctx->vert.filter_pos[i] > max_h_pos || ctx->vert.filter_pos[i] < 0) { fprintf(stderr, "Out Y = %d => In Y = %d\n", i, ctx->vert.filter_pos[i]); return false; } } return true; } static void fixup_filter_sub(struct scaler_filter *filter, int out_len, int in_len) { int i; int max_pos = in_len - filter->filter_len; for (i = 0; i < out_len; i++) { int postsample = filter->filter_pos[i] - max_pos; int presample = -filter->filter_pos[i]; if (postsample > 0) { int16_t *base_filter = NULL; filter->filter_pos[i] -= postsample; base_filter = filter->filter + i * filter->filter_stride; if (postsample > (int)filter->filter_len) memset(base_filter, 0, filter->filter_len * sizeof(int16_t)); else { memmove(base_filter + postsample, base_filter, (filter->filter_len - postsample) * sizeof(int16_t)); memset(base_filter, 0, postsample * sizeof(int16_t)); } } if (presample > 0) { int16_t *base_filter = NULL; filter->filter_pos[i] += presample; base_filter = filter->filter + i * filter->filter_stride; if (presample > (int)filter->filter_len) memset(base_filter, 0, filter->filter_len * sizeof(int16_t)); else { memmove(base_filter, base_filter + presample, (filter->filter_len - presample) * sizeof(int16_t)); memset(base_filter + (filter->filter_len - presample), 0, presample * sizeof(int16_t)); } } } } /* Makes sure that we never sample outside our rectangle. */ static void fixup_filter(struct scaler_ctx *ctx) { fixup_filter_sub(&ctx->horiz, ctx->out_width, ctx->in_width); fixup_filter_sub(&ctx->vert, ctx->out_height, ctx->in_height); } bool scaler_gen_filter(struct scaler_ctx *ctx) { bool ret = true; switch (ctx->scaler_type) { case SCALER_TYPE_POINT: ret = gen_filter_point(ctx); break; case SCALER_TYPE_BILINEAR: ret = gen_filter_bilinear(ctx); break; case SCALER_TYPE_SINC: ret = gen_filter_sinc(ctx); break; default: return false; } if (!ret) return false; fixup_filter(ctx); return validate_filter(ctx); } desmume/src/utils/libfat/libfat.c000664 001750 001750 00000016167 12755534123 020160 0ustar00sergiosergio000000 000000 /* libfat.c Simple functionality for startup, mounting and unmounting of FAT-based devices. Copyright (c) 2006 Michael "Chishm" Chisholm Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. 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. 3. The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 "common.h" #include "partition.h" #include "fatfile.h" #include "fatdir.h" #include "lock.h" #include "mem_allocate.h" #include "disc.h" #ifndef LIBFAT_PC #include #include #endif static const struct devoptab_t dotab_fat = { "fat", sizeof (FILE_STRUCT), _FAT_open_r, _FAT_close_r, _FAT_write_r, _FAT_read_r, _FAT_seek_r, _FAT_fstat_r, _FAT_stat_r, _FAT_link_r, _FAT_unlink_r, _FAT_chdir_r, _FAT_rename_r, _FAT_mkdir_r, sizeof (DIR_STATE_STRUCT), _FAT_diropen_r, _FAT_dirreset_r, _FAT_dirnext_r, _FAT_dirclose_r, #ifndef LIBFAT_PC _FAT_statvfs_r, #endif _FAT_ftruncate_r, _FAT_fsync_r, NULL, /* Device data */ NULL, NULL }; #ifdef LIBFAT_PC static struct devoptab_t* _sole_device = NULL; struct devoptab_t* GetDeviceOpTab(const char* name) { return _sole_device; } #endif bool fatMount (const char* name, const DISC_INTERFACE* interface, sec_t startSector, uint32_t cacheSize, uint32_t SectorsPerPage) { PARTITION* partition; struct devoptab_t* devops; //char* nameCopy; if(!name || strlen(name) > 8 || !interface) return false; if(!interface->startup()) return false; if(!interface->isInserted()) return false; //char devname[10]; //sprintf(devname, "%s:", name); //if(FindDevice(devname) >= 0) // return true; devops = (struct devoptab_t*)_FAT_mem_allocate (sizeof(struct devoptab_t) + strlen(name) + 1); if (!devops) { return false; } #ifdef LIBFAT_PC _sole_device = devops; #endif // Use the space allocated at the end of the devoptab struct for storing the name //nameCopy = (char*)(devops+1); // Initialize the file system partition = _FAT_partition_constructor (interface, cacheSize, SectorsPerPage, startSector); if (!partition) { _FAT_mem_free (devops); return false; } // Add an entry for this device to the devoptab table memcpy (devops, &dotab_fat, sizeof(dotab_fat)); //strcpy (nameCopy, name); //devops->name = nameCopy; devops->deviceData = partition; //AddDevice (devops); return true; } bool fatMountSimple (const char* name, const DISC_INTERFACE* interface) { return fatMount (name, interface, 0, DEFAULT_CACHE_PAGES, DEFAULT_SECTORS_PAGE); } void fatUnmountDirect (struct devoptab_t *devops) { PARTITION* partition = (PARTITION*)devops->deviceData; _FAT_partition_destructor (partition); _FAT_mem_free (devops); _sole_device = NULL; } //void fatUnmount (const char* name) { // struct devoptab_t *devops; // PARTITION* partition; // // if(!name) // return; // // devops = (struct devoptab_t*)GetDeviceOpTab (name); // if (!devops) { // return; // } // // // Perform a quick check to make sure we're dealing with a libfat controlled device // //if (devops->open_r != dotab_fat.open_r) { // // return; // //} // // if (RemoveDevice (name) == -1) { // return; // } // // partition = (PARTITION*)devops->deviceData; // _FAT_partition_destructor (partition); // _FAT_mem_free (devops); //} //bool fatInit (uint32_t cacheSize, bool setAsDefaultDevice) { // int i; // int defaultDevice = -1; // const DISC_INTERFACE *disc; // // for (i = 0; // _FAT_disc_interfaces[i].name != NULL && _FAT_disc_interfaces[i].getInterface != NULL; // i++) // { // disc = _FAT_disc_interfaces[i].getInterface(); // if (fatMount (_FAT_disc_interfaces[i].name, disc, 0, cacheSize, DEFAULT_SECTORS_PAGE)) { // // The first device to successfully mount is set as the default // if (defaultDevice < 0) { // defaultDevice = i; // } // } // } // // if (defaultDevice < 0) { // // None of our devices mounted // return false; // } // // if (setAsDefaultDevice) { // char filePath[MAXPATHLEN * 2]; // strcpy (filePath, _FAT_disc_interfaces[defaultDevice].name); // strcat (filePath, ":/"); //#ifdef ARGV_MAGIC // if ( __system_argv->argvMagic == ARGV_MAGIC && __system_argv->argc >= 1 && strrchr( __system_argv->argv[0], '/' )!=NULL ) { // // Check the app's path against each of our mounted devices, to see // // if we can support it. If so, change to that path. // for (i = 0; // _FAT_disc_interfaces[i].name != NULL && _FAT_disc_interfaces[i].getInterface != NULL; // i++) // { // if ( !strncasecmp( __system_argv->argv[0], _FAT_disc_interfaces[i].name, // strlen(_FAT_disc_interfaces[i].name))) // { // char *lastSlash; // strcpy(filePath, __system_argv->argv[0]); // lastSlash = strrchr( filePath, '/' ); // // if ( NULL != lastSlash) { // if ( *(lastSlash - 1) == ':') lastSlash++; // *lastSlash = 0; // } // } // } // } //#endif // chdir (filePath); // } // // return true; //} //bool fatInitDefault (void) { // return fatInit (DEFAULT_CACHE_PAGES, true); //} //void fatGetVolumeLabel (const char* name, char *label) { // struct devoptab_t *devops; // PARTITION* partition; // char *buf; // int namelen,i; // // if(!name || !label) // return; // // namelen = strlen(name); // buf=(char*)_FAT_mem_allocate(sizeof(char)*namelen+2); // strcpy(buf,name); // // if (name[namelen-1] == '/') { // buf[namelen-1]='\0'; // namelen--; // } // // if (name[namelen-1] != ':') { // buf[namelen]=':'; // buf[namelen+1]='\0'; // } // // devops = (struct devoptab_t*)GetDeviceOpTab(buf); // // for(i=0;buf[i]!='\0' && buf[i]!=':';i++); // if (!devops || strncasecmp(buf,devops->name,i)) { // _FAT_mem_free(buf); // return; // } // // _FAT_mem_free(buf); // // // Perform a quick check to make sure we're dealing with a libfat controlled device // if (devops->open_r != dotab_fat.open_r) { // return; // } // // partition = (PARTITION*)devops->deviceData; // // if(!_FAT_directory_getVolumeLabel(partition, label)) { // strncpy(label,partition->label,11); // label[11]='\0'; // } // if(!strncmp(label, "NO NAME", 7)) label[0]='\0'; //} desmume/src/libretro-common/lists/file_list.c000664 001750 001750 00000026510 12755534123 022527 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2016 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (file_list.c). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include #include #include #include #include #include #include /** * file_list_capacity: * @list : pointer to file list * @cap : new capacity for file list. * * Change maximum capacity of file list's size. * * Returns: true (1) if successful, otherwise false (0). **/ static struct item_file *realloc_file_list_capacity(file_list_t *list, size_t cap) { struct item_file *new_data = NULL; retro_assert(cap > list->size); new_data = (struct item_file*)realloc(list->list, cap * sizeof(struct item_file)); if (!new_data) return NULL; if (cap > list->capacity) memset(&new_data[list->capacity], 0, sizeof(*new_data) * (cap - list->capacity)); return new_data; } static void file_list_add(file_list_t *list, unsigned idx, const char *path, const char *label, unsigned type, size_t directory_ptr, size_t entry_idx) { memset(&list->list[idx], 0, sizeof(*list->list)); list->list[idx].type = type; list->list[idx].directory_ptr = directory_ptr; list->list[idx].entry_idx = entry_idx; if (label) list->list[idx].label = strdup(label); if (path) list->list[idx].path = strdup(path); list->size++; } static bool file_list_expand_if_needed(file_list_t *list) { if (list->size >= list->capacity) { size_t new_capacity = list->capacity * 2 + 1; struct item_file *items = realloc_file_list_capacity( list, new_capacity); if (!items) return false; list->list = items; list->capacity = new_capacity; } return true; } bool file_list_prepend(file_list_t *list, const char *path, const char *label, unsigned type, size_t directory_ptr, size_t entry_idx) { unsigned i; if (!file_list_expand_if_needed(list)) return false; for (i = list->size; i > 0; i--) { struct item_file *copy = (struct item_file*) calloc(1, sizeof(struct item_file)); memcpy(copy, &list->list[i-1], sizeof(struct item_file)); memcpy(&list->list[i-1], &list->list[i], sizeof(struct item_file)); memcpy(&list->list[i], copy, sizeof(struct item_file)); free(copy); } file_list_add(list, 0, path, label, type, directory_ptr, entry_idx); return true; } bool file_list_append(file_list_t *list, const char *path, const char *label, unsigned type, size_t directory_ptr, size_t entry_idx) { if (!file_list_expand_if_needed(list)) return false; file_list_add(list, list->size, path, label, type, directory_ptr, entry_idx); return true; } size_t file_list_get_size(const file_list_t *list) { if (!list) return 0; return list->size; } size_t file_list_get_directory_ptr(const file_list_t *list) { size_t size = file_list_get_size(list); return list->list[size].directory_ptr; } void file_list_pop(file_list_t *list, size_t *directory_ptr) { if (!list) return; if (list->size != 0) { --list->size; if (list->list[list->size].path) free(list->list[list->size].path); list->list[list->size].path = NULL; if (list->list[list->size].label) free(list->list[list->size].label); list->list[list->size].label = NULL; } if (directory_ptr) *directory_ptr = list->list[list->size].directory_ptr; } void file_list_free(file_list_t *list) { size_t i; if (!list) return; for (i = 0; i < list->size; i++) { file_list_free_userdata(list, i); file_list_free_actiondata(list, i); if (list->list[i].path) free(list->list[i].path); list->list[i].path = NULL; if (list->list[i].label) free(list->list[i].label); list->list[i].label = NULL; if (list->list[i].alt) free(list->list[i].alt); list->list[i].alt = NULL; } if (list->list) free(list->list); list->list = NULL; free(list); } void file_list_clear(file_list_t *list) { size_t i; if (!list) return; for (i = 0; i < list->size; i++) { if (list->list[i].path) free(list->list[i].path); list->list[i].path = NULL; if (list->list[i].label) free(list->list[i].label); list->list[i].label = NULL; if (list->list[i].alt) free(list->list[i].alt); list->list[i].alt = NULL; } list->size = 0; } void file_list_copy(const file_list_t *src, file_list_t *dst) { struct item_file *item; if (!src || !dst) return; if (dst->list) { for (item = dst->list; item < &dst->list[dst->size]; ++item) { if (item->path) free(item->path); if (item->label) free(item->label); if (item->alt) free(item->alt); } free(dst->list); } dst->size = 0; dst->capacity = 0; dst->list = (struct item_file*)malloc(src->size * sizeof(struct item_file)); if (!dst->list) return; dst->size = dst->capacity = src->size; memcpy(dst->list, src->list, dst->size * sizeof(struct item_file)); for (item = dst->list; item < &dst->list[dst->size]; ++item) { if (item->path) item->path = strdup(item->path); if (item->label) item->label = strdup(item->label); if (item->alt) item->alt = strdup(item->alt); } } void file_list_set_label_at_offset(file_list_t *list, size_t idx, const char *label) { if (!list) return; if (list->list[idx].label) free(list->list[idx].label); list->list[idx].alt = NULL; if (label) list->list[idx].label = strdup(label); } void file_list_get_label_at_offset(const file_list_t *list, size_t idx, const char **label) { if (!label || !list) return; *label = list->list[idx].path; if (list->list[idx].label) *label = list->list[idx].label; } void file_list_set_alt_at_offset(file_list_t *list, size_t idx, const char *alt) { if (!list || !alt) return; if (list->list[idx].alt) free(list->list[idx].alt); list->list[idx].alt = NULL; if (alt) list->list[idx].alt = strdup(alt); } void file_list_get_alt_at_offset(const file_list_t *list, size_t idx, const char **alt) { if (!list) return; if (alt) *alt = list->list[idx].alt ? list->list[idx].alt : list->list[idx].path; } static int file_list_alt_cmp(const void *a_, const void *b_) { const struct item_file *a = (const struct item_file*)a_; const struct item_file *b = (const struct item_file*)b_; const char *cmp_a = a->alt ? a->alt : a->path; const char *cmp_b = b->alt ? b->alt : b->path; return strcasecmp(cmp_a, cmp_b); } static int file_list_type_cmp(const void *a_, const void *b_) { const struct item_file *a = (const struct item_file*)a_; const struct item_file *b = (const struct item_file*)b_; if (a->type < b->type) return -1; if (a->type == b->type) return 0; return 1; } void file_list_sort_on_alt(file_list_t *list) { qsort(list->list, list->size, sizeof(list->list[0]), file_list_alt_cmp); } void file_list_sort_on_type(file_list_t *list) { qsort(list->list, list->size, sizeof(list->list[0]), file_list_type_cmp); } void *file_list_get_userdata_at_offset(const file_list_t *list, size_t idx) { if (!list) return NULL; return list->list[idx].userdata; } void file_list_set_userdata(const file_list_t *list, size_t idx, void *ptr) { if (!list || !ptr) return; list->list[idx].userdata = ptr; } void file_list_set_actiondata(const file_list_t *list, size_t idx, void *ptr) { if (!list || !ptr) return; list->list[idx].actiondata = ptr; } void *file_list_get_actiondata_at_offset(const file_list_t *list, size_t idx) { if (!list) return NULL; return list->list[idx].actiondata; } void file_list_free_actiondata(const file_list_t *list, size_t idx) { if (!list) return; if (list->list[idx].actiondata) free(list->list[idx].actiondata); list->list[idx].actiondata = NULL; } void file_list_free_userdata(const file_list_t *list, size_t idx) { if (!list) return; if (list->list[idx].userdata) free(list->list[idx].userdata); list->list[idx].userdata = NULL; } void *file_list_get_last_actiondata(const file_list_t *list) { if (!list) return NULL; return list->list[list->size - 1].actiondata; } void file_list_get_at_offset(const file_list_t *list, size_t idx, const char **path, const char **label, unsigned *file_type, size_t *entry_idx) { if (!list) return; if (path) *path = list->list[idx].path; if (label) *label = list->list[idx].label; if (file_type) *file_type = list->list[idx].type; if (entry_idx) *entry_idx = list->list[idx].entry_idx; } void file_list_get_last(const file_list_t *list, const char **path, const char **label, unsigned *file_type, size_t *entry_idx) { if (!list) return; if (list->size) file_list_get_at_offset(list, list->size - 1, path, label, file_type, entry_idx); } bool file_list_search(const file_list_t *list, const char *needle, size_t *idx) { size_t i; const char *alt; bool ret = false; if (!list) return false; for (i = 0; i < list->size; i++) { const char *str; file_list_get_alt_at_offset(list, i, &alt); if (!alt) { file_list_get_label_at_offset(list, i, &alt); if (!alt) continue; } str = (const char *)strcasestr(alt, needle); if (str == alt) { /* Found match with first chars, best possible match. */ *idx = i; ret = true; break; } else if (str && !ret) { /* Found mid-string match, but try to find a match with * first characters before we settle. */ *idx = i; ret = true; } } return ret; } desmume/src/utils/libfat/partition.h000664 001750 001750 00000006533 12755534123 020731 0ustar00sergiosergio000000 000000 /* partition.h Functions for mounting and dismounting partitions on various block devices. Copyright (c) 2006 Michael "Chishm" Chisholm Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. 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. 3. The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. */ #ifndef _PARTITION_H #define _PARTITION_H #include "common.h" #include "cache.h" #include "lock.h" #ifdef __cplusplus extern "C" { #endif // Device name extern const char* DEVICE_NAME; // Filesystem type typedef enum {FS_UNKNOWN, FS_FAT12, FS_FAT16, FS_FAT32} FS_TYPE; typedef struct { sec_t fatStart; uint32_t sectorsPerFat; uint32_t lastCluster; uint32_t firstFree; } FAT; typedef struct { const DISC_INTERFACE* disc; CACHE* cache; // Info about the partition FS_TYPE filesysType; uint64_t totalSize; sec_t rootDirStart; uint32_t rootDirCluster; uint32_t numberOfSectors; sec_t dataStart; uint32_t bytesPerSector; uint32_t sectorsPerCluster; uint32_t bytesPerCluster; FAT fat; // Values that may change after construction uint32_t cwdCluster; // Current working directory cluster int openFileCount; struct _FILE_STRUCT* firstOpenFile; // The start of a linked list of files mutex_t lock; // A lock for partition operations bool readOnly; // If this is set, then do not try writing to the disc char label[12]; // Volume label } PARTITION; /* Mount the supplied device and return a pointer to the struct necessary to use it */ PARTITION* _FAT_partition_constructor (const DISC_INTERFACE* disc, uint32_t cacheSize, uint32_t SectorsPerPage, sec_t startSector); /* Dismount the device and free all structures used. Will also attempt to synchronise all open files to disc. */ void _FAT_partition_destructor (PARTITION* partition); /* Return the partition specified in a path, as taken from the devoptab. */ PARTITION* _FAT_partition_getPartitionFromPath (const char* path); #ifdef __cplusplus } #endif #endif // _PARTITION_H desmume/src/libretro-common/crt/string.c000664 001750 001750 00000001200 12755534123 021502 0ustar00sergiosergio000000 000000 #ifdef _MSC_VER #include #endif #include #include void *memset(void *dst, int val, size_t count) { void *start = dst; #if defined(_M_IA64) || defined (_M_AMD64) || defined(_M_ALPHA) || defined (_M_PPC) extern void RtlFillMemory(void *, size_t count, char); RtlFillMemory(dst, count, (char)val); #else while (count--) { *(char*)dst = (char)val; dst = (char*)dst + 1; } #endif return start; } void *memcpy(void *dst, const void *src, size_t len) { size_t i; for (i = 0; i < len; i++) ((unsigned char *)dst)[i] = ((unsigned char *)src)[i]; return dst; } desmume/src/utils/libfat/partition.c000664 001750 001750 00000023473 12755534123 020726 0ustar00sergiosergio000000 000000 /* partition.c Functions for mounting and dismounting partitions on various block devices. Copyright (c) 2006 Michael "Chishm" Chisholm Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. 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. 3. The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 "partition.h" #include "bit_ops.h" #include "file_allocation_table.h" #include "directory.h" #include "mem_allocate.h" #include "fatfile.h" #include #include #ifndef LIBFAT_PC #include #endif /* This device name, as known by devkitPro toolchains */ const char* DEVICE_NAME = "fat"; /* Data offsets */ // BIOS Parameter Block offsets enum BPB { BPB_jmpBoot = 0x00, BPB_OEMName = 0x03, // BIOS Parameter Block BPB_bytesPerSector = 0x0B, BPB_sectorsPerCluster = 0x0D, BPB_reservedSectors = 0x0E, BPB_numFATs = 0x10, BPB_rootEntries = 0x11, BPB_numSectorsSmall = 0x13, BPB_mediaDesc = 0x15, BPB_sectorsPerFAT = 0x16, BPB_sectorsPerTrk = 0x18, BPB_numHeads = 0x1A, BPB_numHiddenSectors = 0x1C, BPB_numSectors = 0x20, // Ext BIOS Parameter Block for FAT16 BPB_FAT16_driveNumber = 0x24, BPB_FAT16_reserved1 = 0x25, BPB_FAT16_extBootSig = 0x26, BPB_FAT16_volumeID = 0x27, BPB_FAT16_volumeLabel = 0x2B, BPB_FAT16_fileSysType = 0x36, // Bootcode BPB_FAT16_bootCode = 0x3E, // FAT32 extended block BPB_FAT32_sectorsPerFAT32 = 0x24, BPB_FAT32_extFlags = 0x28, BPB_FAT32_fsVer = 0x2A, BPB_FAT32_rootClus = 0x2C, BPB_FAT32_fsInfo = 0x30, BPB_FAT32_bkBootSec = 0x32, // Ext BIOS Parameter Block for FAT32 BPB_FAT32_driveNumber = 0x40, BPB_FAT32_reserved1 = 0x41, BPB_FAT32_extBootSig = 0x42, BPB_FAT32_volumeID = 0x43, BPB_FAT32_volumeLabel = 0x47, BPB_FAT32_fileSysType = 0x52, // Bootcode BPB_FAT32_bootCode = 0x5A, BPB_bootSig_55 = 0x1FE, BPB_bootSig_AA = 0x1FF }; static const char FAT_SIG[3] = {'F', 'A', 'T'}; sec_t FindFirstValidPartition(const DISC_INTERFACE* disc) { uint8_t part_table[16*4]; uint8_t *ptr; int i; uint8_t sectorBuffer[BYTES_PER_READ] = {0}; // Read first sector of disc if (!_FAT_disc_readSectors (disc, 0, 1, sectorBuffer)) { return 0; } memcpy(part_table,sectorBuffer+0x1BE,16*4); ptr = part_table; for(i=0;i<4;i++,ptr+=16) { sec_t part_lba = u8array_to_u32(ptr, 0x8); if (!memcmp(sectorBuffer + BPB_FAT16_fileSysType, FAT_SIG, sizeof(FAT_SIG)) || !memcmp(sectorBuffer + BPB_FAT32_fileSysType, FAT_SIG, sizeof(FAT_SIG))) { return part_lba; } if(ptr[4]==0) continue; if(ptr[4]==0x0F) { sec_t part_lba2=part_lba; sec_t next_lba2=0; int n; for(n=0;n<8;n++) // max 8 logic partitions { if(!_FAT_disc_readSectors (disc, part_lba+next_lba2, 1, sectorBuffer)) return 0; part_lba2 = part_lba + next_lba2 + u8array_to_u32(sectorBuffer, 0x1C6) ; next_lba2 = u8array_to_u32(sectorBuffer, 0x1D6); if(!_FAT_disc_readSectors (disc, part_lba2, 1, sectorBuffer)) return 0; if (!memcmp(sectorBuffer + BPB_FAT16_fileSysType, FAT_SIG, sizeof(FAT_SIG)) || !memcmp(sectorBuffer + BPB_FAT32_fileSysType, FAT_SIG, sizeof(FAT_SIG))) { return part_lba2; } if(next_lba2==0) break; } } else { if(!_FAT_disc_readSectors (disc, part_lba, 1, sectorBuffer)) return 0; if (!memcmp(sectorBuffer + BPB_FAT16_fileSysType, FAT_SIG, sizeof(FAT_SIG)) || !memcmp(sectorBuffer + BPB_FAT32_fileSysType, FAT_SIG, sizeof(FAT_SIG))) { return part_lba; } } } return 0; } PARTITION* _FAT_partition_constructor (const DISC_INTERFACE* disc, uint32_t cacheSize, uint32_t sectorsPerPage, sec_t startSector) { PARTITION* partition; uint8_t sectorBuffer[BYTES_PER_READ] = {0}; // Read first sector of disc if (!_FAT_disc_readSectors (disc, startSector, 1, sectorBuffer)) { return NULL; } // Make sure it is a valid MBR or boot sector if ( (sectorBuffer[BPB_bootSig_55] != 0x55) || (sectorBuffer[BPB_bootSig_AA] != 0xAA)) { return NULL; } if (startSector != 0) { // We're told where to start the partition, so just accept it } else if (!memcmp(sectorBuffer + BPB_FAT16_fileSysType, FAT_SIG, sizeof(FAT_SIG))) { // Check if there is a FAT string, which indicates this is a boot sector startSector = 0; } else if (!memcmp(sectorBuffer + BPB_FAT32_fileSysType, FAT_SIG, sizeof(FAT_SIG))) { // Check for FAT32 startSector = 0; } else { startSector = FindFirstValidPartition(disc); if (!_FAT_disc_readSectors (disc, startSector, 1, sectorBuffer)) { return NULL; } } // Now verify that this is indeed a FAT partition if (memcmp(sectorBuffer + BPB_FAT16_fileSysType, FAT_SIG, sizeof(FAT_SIG)) && memcmp(sectorBuffer + BPB_FAT32_fileSysType, FAT_SIG, sizeof(FAT_SIG))) { return NULL; } partition = (PARTITION*) _FAT_mem_allocate (sizeof(PARTITION)); if (partition == NULL) { return NULL; } // Init the partition lock _FAT_lock_init(&partition->lock); if (!memcmp(sectorBuffer + BPB_FAT16_fileSysType, FAT_SIG, sizeof(FAT_SIG))) strncpy(partition->label, (char*)(sectorBuffer + BPB_FAT16_volumeLabel), 11); else strncpy(partition->label, (char*)(sectorBuffer + BPB_FAT32_volumeLabel), 11); partition->label[11] = '\0'; // Set partition's disc interface partition->disc = disc; // Store required information about the file system partition->fat.sectorsPerFat = u8array_to_u16(sectorBuffer, BPB_sectorsPerFAT); if (partition->fat.sectorsPerFat == 0) { partition->fat.sectorsPerFat = u8array_to_u32( sectorBuffer, BPB_FAT32_sectorsPerFAT32); } partition->numberOfSectors = u8array_to_u16( sectorBuffer, BPB_numSectorsSmall); if (partition->numberOfSectors == 0) { partition->numberOfSectors = u8array_to_u32( sectorBuffer, BPB_numSectors); } partition->bytesPerSector = BYTES_PER_READ; // Sector size is redefined to be 512 bytes partition->sectorsPerCluster = sectorBuffer[BPB_sectorsPerCluster] * u8array_to_u16(sectorBuffer, BPB_bytesPerSector) / BYTES_PER_READ; partition->bytesPerCluster = partition->bytesPerSector * partition->sectorsPerCluster; partition->fat.fatStart = startSector + u8array_to_u16(sectorBuffer, BPB_reservedSectors); partition->rootDirStart = partition->fat.fatStart + (sectorBuffer[BPB_numFATs] * partition->fat.sectorsPerFat); partition->dataStart = partition->rootDirStart + (( u8array_to_u16(sectorBuffer, BPB_rootEntries) * DIR_ENTRY_DATA_SIZE) / partition->bytesPerSector); partition->totalSize = ((uint64_t)partition->numberOfSectors - (partition->dataStart - startSector)) * (uint64_t)partition->bytesPerSector; // Store info about FAT uint32_t clusterCount = (partition->numberOfSectors - (uint32_t)(partition->dataStart - startSector)) / partition->sectorsPerCluster; partition->fat.lastCluster = clusterCount + CLUSTER_FIRST - 1; partition->fat.firstFree = CLUSTER_FIRST; if (clusterCount < CLUSTERS_PER_FAT12) { partition->filesysType = FS_FAT12; // FAT12 volume } else if (clusterCount < CLUSTERS_PER_FAT16) { partition->filesysType = FS_FAT16; // FAT16 volume } else { partition->filesysType = FS_FAT32; // FAT32 volume } if (partition->filesysType != FS_FAT32) { partition->rootDirCluster = FAT16_ROOT_DIR_CLUSTER; } else { // Set up for the FAT32 way partition->rootDirCluster = u8array_to_u32(sectorBuffer, BPB_FAT32_rootClus); // Check if FAT mirroring is enabled if (!(sectorBuffer[BPB_FAT32_extFlags] & 0x80)) { // Use the active FAT partition->fat.fatStart = partition->fat.fatStart + ( partition->fat.sectorsPerFat * (sectorBuffer[BPB_FAT32_extFlags] & 0x0F)); } } // Create a cache to use partition->cache = _FAT_cache_constructor (cacheSize, sectorsPerPage, partition->disc, startSector+partition->numberOfSectors); // Set current directory to the root partition->cwdCluster = partition->rootDirCluster; // Check if this disc is writable, and set the readOnly property appropriately partition->readOnly = !(_FAT_disc_features(disc) & FEATURE_MEDIUM_CANWRITE); // There are currently no open files on this partition partition->openFileCount = 0; partition->firstOpenFile = NULL; return partition; } void _FAT_partition_destructor (PARTITION* partition) { FILE_STRUCT* nextFile; _FAT_lock(&partition->lock); // Synchronize open files nextFile = partition->firstOpenFile; while (nextFile) { _FAT_syncToDisc (nextFile); nextFile = nextFile->nextOpenFile; } // Free memory used by the cache, writing it to disc at the same time _FAT_cache_destructor (partition->cache); // Unlock the partition and destroy the lock _FAT_unlock(&partition->lock); _FAT_lock_deinit(&partition->lock); // Free memory used by the partition _FAT_mem_free (partition); } PARTITION* _FAT_partition_getPartitionFromPath (const char* path) { const struct devoptab_t *devops = GetDeviceOpTab (path); if (!devops) return NULL; return (PARTITION*)devops->deviceData; } desmume/src/utils/AsmJit/core/zonememory.h000664 001750 001750 00000011043 12755534123 021772 0ustar00sergiosergio000000 000000 // [AsmJit] // Complete JIT Assembler for C++ Language. // // [License] // Zlib - See COPYING file in this package. // [Guard] #ifndef _ASMJIT_CORE_ZONEMEMORY_H #define _ASMJIT_CORE_ZONEMEMORY_H // [Dependencies - AsmJit] #include "../core/build.h" namespace AsmJit { //! @addtogroup AsmJit_Core //! @{ // ============================================================================ // [AsmJit::ZoneChunk] // ============================================================================ //! @internal //! //! @brief One allocated chunk of memory. struct ZoneChunk { // -------------------------------------------------------------------------- // [Methods] // -------------------------------------------------------------------------- //! @brief Get count of remaining (unused) bytes in chunk. inline size_t getRemainingBytes() const { return size - pos; } // -------------------------------------------------------------------------- // [Members] // -------------------------------------------------------------------------- //! @brief Link to previous chunk. ZoneChunk* prev; //! @brief Position in this chunk. size_t pos; //! @brief Size of this chunk (in bytes). size_t size; //! @brief Data. uint8_t data[sizeof(void*)]; }; // ============================================================================ // [AsmJit::ZoneMemory] // ============================================================================ //! @brief Memory allocator designed to fast alloc memory that will be freed //! in one step. //! //! @note This is hackery for performance. Concept is that objects created //! by @c ZoneMemory are freed all at once. This means that lifetime of //! these objects are the same as the zone object itself. struct ZoneMemory { // -------------------------------------------------------------------------- // [Construction / Destruction] // -------------------------------------------------------------------------- //! @brief Create new instance of @c ZoneMemory. //! @param chunkSize Default size for one zone chunk. ASMJIT_API ZoneMemory(size_t chunkSize); //! @brief Destroy @ref ZoneMemory instance. ASMJIT_API ~ZoneMemory(); // -------------------------------------------------------------------------- // [Methods] // -------------------------------------------------------------------------- //! @brief Allocate @c size bytes of memory and return pointer to it. //! //! Pointer allocated by this way will be valid until @c ZoneMemory object //! is destroyed. To create class by this way use placement @c new and //! @c delete operators: //! //! @code //! // Example of allocating simple class //! //! // Your class //! class Object //! { //! // members... //! }; //! //! // Your function //! void f() //! { //! // We are using AsmJit namespace //! using namespace AsmJit //! //! // Create zone object with chunk size of 65536 bytes. //! ZoneMemory zone(65536); //! //! // Create your objects using zone object allocating, for example: //! Object* obj = new(zone.alloc(sizeof(YourClass))) Object(); //! //! // ... lifetime of your objects ... //! //! // Destroy your objects: //! obj->~Object(); //! //! // ZoneMemory destructor will free all memory allocated through it, //! // alternative is to call @c zone.reset(). //! } //! @endcode ASMJIT_API void* alloc(size_t size); //! @brief Helper to duplicate string. ASMJIT_API char* sdup(const char* str); //! @brief Free all allocated memory except first block that remains for reuse. //! //! Note that this method will invalidate all instances using this memory //! allocated by this zone instance. ASMJIT_API void clear(); //! @brief Free all allocated memory at once. //! //! Note that this method will invalidate all instances using this memory //! allocated by this zone instance. ASMJIT_API void reset(); //! @brief Get total size of allocated objects - by @c alloc(). inline size_t getTotal() const { return _total; } //! @brief Get (default) chunk size. inline size_t getChunkSize() const { return _chunkSize; } // -------------------------------------------------------------------------- // [Members] // -------------------------------------------------------------------------- //! @brief Last allocated chunk of memory. ZoneChunk* _chunks; //! @brief Total size of allocated objects - by @c alloc() method. size_t _total; //! @brief One chunk size. size_t _chunkSize; }; //! @} } // AsmJit namespace #endif // _ASMJIT_CORE_ZONEMEMORY_H desmume/src/libretro-common/utils/djb2.c000664 001750 001750 00000000704 12755534123 021375 0ustar00sergiosergio000000 000000 /* public domain */ /* gcc -O3 -o djb2 djb2.c */ #include #include static uint32_t djb2(const char* str) { const unsigned char* aux = (const unsigned char*)str; uint32_t hash = 5381; while (*aux) hash = (hash << 5) + hash + *aux++; return hash; } int main(int argc, const char* argv[]) { int i; for (i = 1; i < argc; i++) printf( "0x%08xU: %s\n", djb2( argv[ i ] ), argv[ i ] ); return 0; } desmume/src/libretro-common/include/utils/md5.h000664 001750 001750 00000002602 12755534123 022670 0ustar00sergiosergio000000 000000 /* * This is an OpenSSL-compatible implementation of the RSA Data Security, Inc. * MD5 Message-Digest Algorithm (RFC 1321). * * Homepage: * http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5 * * Author: * Alexander Peslyak, better known as Solar Designer * * This software was written by Alexander Peslyak in 2001. No copyright is * claimed, and the software is hereby placed in the public domain. * In case this attempt to disclaim copyright and place the software in the * public domain is deemed null and void, then the software is * Copyright (c) 2001 Alexander Peslyak and it is hereby released to the * general public under the following terms: * * Redistribution and use in source and binary forms, with or without * modification, are permitted. * * There's ABSOLUTELY NO WARRANTY, express or implied. * * See md5.c for more information. */ #ifdef HAVE_OPENSSL #include #elif !defined(_MD5_H) #define _MD5_H /* Any 32-bit or wider unsigned integer data type will do */ typedef unsigned int MD5_u32plus; typedef struct { MD5_u32plus lo, hi; MD5_u32plus a, b, c, d; unsigned char buffer[64]; MD5_u32plus block[16]; } MD5_CTX; extern void MD5_Init(MD5_CTX *ctx); extern void MD5_Update(MD5_CTX *ctx, const void *data, unsigned long size); extern void MD5_Final(unsigned char *result, MD5_CTX *ctx); #endif desmume/src/addons/slot1comp_mc.h000664 001750 001750 00000002041 12755534123 020155 0ustar00sergiosergio000000 000000 /* Copyright (C) 2013-2015 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the this software. If not, see . */ //this file contains the components used for emulating standard gamecard "MC" devices (eeprom, fram, flash) #ifndef _SLOT1COMP_MC_H #define _SLOT1COMP_MC_H #include "../types.h" class Slot1Comp_MC { public: u8 auxspi_transaction(int PROCNUM, u8 value); void auxspi_reset(int PROCNUM); void connect(); }; extern Slot1Comp_MC g_Slot1Comp_MC; #endif desmume/src/libretro-common/include/compat/getopt.h000664 001750 001750 00000005232 12755534123 023632 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2016 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (compat_getopt.h). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef __LIBRETRO_SDK_COMPAT_GETOPT_H #define __LIBRETRO_SDK_COMPAT_GETOPT_H #if defined(RARCH_INTERNAL) && defined(HAVE_CONFIG_H) #include "../../../config.h" #endif /* Custom implementation of the GNU getopt_long for portability. * Not designed to be fully compatible, but compatible with * the features RetroArch uses. */ #ifdef HAVE_GETOPT_LONG #include #else /* Avoid possible naming collisions during link since we * prefer to use the actual name. */ #define getopt_long(argc, argv, optstring, longopts, longindex) __getopt_long_retro(argc, argv, optstring, longopts, longindex) #include RETRO_BEGIN_DECLS struct option { const char *name; int has_arg; int *flag; int val; }; /* argv[] is declared with char * const argv[] in GNU, * but this makes no sense, as non-POSIX getopt_long * mutates argv (non-opts are moved to the end). */ int getopt_long(int argc, char *argv[], const char *optstring, const struct option *longopts, int *longindex); extern char *optarg; extern int optind, opterr, optopt; RETRO_END_DECLS /* If these are variously #defined, then we have bigger problems */ #ifndef no_argument #define no_argument 0 #define required_argument 1 #define optional_argument 2 #endif /* HAVE_GETOPT_LONG */ #endif /* pragma once */ #endif desmume/src/utils/AsmJit/core/buffer.cpp000664 001750 001750 00000003164 12755534123 021377 0ustar00sergiosergio000000 000000 // [AsmJit] // Complete JIT Assembler for C++ Language. // // [License] // Zlib - See COPYING file in this package. #define ASMJIT_EXPORTS // [Dependencies - AsmJit] #include "../core/buffer.h" #include "../core/defs.h" // [Api-Begin] #include "../core/apibegin.h" namespace AsmJit { // ============================================================================ // [AsmJit::Buffer] // ============================================================================ void Buffer::emitData(const void* ptr, size_t len) { size_t max = getCapacity() - getOffset(); if (max < len && !realloc(getOffset() + len)) { return; } memcpy(_cur, ptr, len); _cur += len; } bool Buffer::realloc(size_t to) { if (getCapacity() < to) { size_t len = getOffset(); uint8_t *newdata; if (_data != NULL) newdata = (uint8_t*)ASMJIT_REALLOC(_data, to); else newdata = (uint8_t*)ASMJIT_MALLOC(to); if (newdata == NULL) return false; _data = newdata; _cur = newdata + len; _max = newdata + to; _max -= (to >= kBufferGrow) ? kBufferGrow : to; _capacity = to; } return true; } bool Buffer::grow() { size_t to = _capacity; if (to < 512) to = 1024; else if (to > 65536) to += 65536; else to <<= 1; return realloc(to); } void Buffer::reset() { if (_data == NULL) return; ASMJIT_FREE(_data); _data = NULL; _cur = NULL; _max = NULL; _capacity = 0; } uint8_t* Buffer::take() { uint8_t* data = _data; _data = NULL; _cur = NULL; _max = NULL; _capacity = 0; return data; } } // AsmJit namespace // [Api-End] #include "../core/apiend.h" desmume/src/libretro-common/crt/include/string.h000664 001750 001750 00000000310 12755534123 023133 0ustar00sergiosergio000000 000000 #ifndef __LIBRETRO_SDK_CRT_STRING_H_ #define __LIBRETRO_SDK_CRT_STRING_H_ #include void *memcpy(void *dst, const void *src, size_t len); void *memset(void *b, int c, size_t len); #endif desmume/src/matrix.h000664 001750 001750 00000024113 12755534123 015615 0ustar00sergiosergio000000 000000 /* Copyright (C) 2006-2007 shash Copyright (C) 2007-2012 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the this software. If not, see . */ #ifndef MATRIX_H #define MATRIX_H #include #include #include #include "types.h" #include "mem.h" #ifdef ENABLE_SSE #include #endif #ifdef ENABLE_SSE2 #include #endif struct MatrixStack { MatrixStack(int size, int type); s32 *matrix; s32 position; s32 size; u8 type; }; void MatrixInit (float *matrix); void MatrixInit (s32 *matrix); //In order to conditionally use these asm optimized functions in visual studio //without having to make new build types to exclude the assembly files. //a bit sloppy, but there aint much to it float MatrixGetMultipliedIndex (const u32 index, float *matrix, float *rightMatrix); s32 MatrixGetMultipliedIndex (const u32 index, s32 *matrix, s32 *rightMatrix); void MatrixSet (s32 *matrix, int x, int y, s32 value); void MatrixCopy (s32 * matrixDST, const s32 * matrixSRC); int MatrixCompare (const s32 * matrixDST, const float * matrixSRC); void MatrixIdentity (s32 *matrix); void MatrixStackInit (MatrixStack *stack); void MatrixStackSetMaxSize (MatrixStack *stack, int size); void MatrixStackPushMatrix (MatrixStack *stack, const s32 *ptr); void MatrixStackPopMatrix (s32 *mtxCurr, MatrixStack *stack, int size); s32* MatrixStackGetPos (MatrixStack *stack, const size_t pos); s32* MatrixStackGet (MatrixStack *stack); void MatrixStackLoadMatrix (MatrixStack *stack, const size_t pos, const s32 *ptr); //these functions are an unreliable, inaccurate floor. //it should only be used for positive numbers //this isnt as fast as it could be if we used a visual c++ intrinsic, but those appear not to be universally available FORCEINLINE u32 u32floor(float f) { #ifdef ENABLE_SSE2 return (u32)_mm_cvtt_ss2si(_mm_set_ss(f)); #else return (u32)f; #endif } FORCEINLINE u32 u32floor(double d) { #ifdef ENABLE_SSE2 return (u32)_mm_cvttsd_si32(_mm_set_sd(d)); #else return (u32)d; #endif } //same as above but works for negative values too. //be sure that the results are the same thing as floorf! FORCEINLINE s32 s32floor(float f) { #ifdef ENABLE_SSE2 return _mm_cvtss_si32( _mm_add_ss(_mm_set_ss(-0.5f),_mm_add_ss(_mm_set_ss(f), _mm_set_ss(f))) ) >> 1; #else return (s32)floorf(f); #endif } FORCEINLINE s32 s32floor(double d) { return s32floor((float)d); } //switched SSE2 functions //------------- #ifdef ENABLE_SSE2 static void memset_u16(void *dst, const u16 val, const size_t length) { size_t i; __m128i *dst_vec128 = (__m128i *)dst; const __m128i val_vec128 = _mm_set1_epi16(val); const size_t length_vec128 = length / (sizeof(val_vec128) / sizeof(val)); for (i = 0; i < length_vec128; i++) _mm_stream_si128(dst_vec128 + i, val_vec128); } template static void memset_u16_fast(void *dst, const u16 val) { __m128i *dst_vec128 = (__m128i *)dst; const __m128i val_vec128 = _mm_set1_epi16(val); MACRODO_N(LENGTH / (sizeof(val_vec128) / sizeof(val)), _mm_store_si128(dst_vec128 + (X), val_vec128)); } static void memset_u32(void *dst, const u32 val, const size_t length) { __m128i *dst_vec128 = (__m128i *)dst; const __m128i val_vec128 = _mm_set1_epi32(val); const size_t length_vec128 = length / (sizeof(val_vec128) / sizeof(val)); for (size_t i = 0; i < length_vec128; i++) _mm_stream_si128(dst_vec128 + i, val_vec128); } template static void memset_u32_fast(void *dst, const u32 val) { __m128i *dst_vec128 = (__m128i *)dst; const __m128i val_vec128 = _mm_set1_epi32(val); MACRODO_N(LENGTH / (sizeof(val_vec128) / sizeof(val)), _mm_store_si128(dst_vec128 + (X), val_vec128)); } #else //no sse2 static void memset_u16(void *dst, const u16 val, const size_t length) { size_t i; #ifdef HOST_64 u64 *dst_u64 = (u64 *)dst; const u64 val_u64 = ((u64)val << 48) | ((u64)val << 32) | ((u64)val << 16) | (u64)val; const size_t length_u64 = length / (sizeof(val_u64) / sizeof(val)); for (i = 0; i < length_u64; i++) dst_u64[i] = val_u64; #else for (i = 0; i < length; i++) ((u16 *)dst)[i] = val; #endif } template static void memset_u16_fast(void *dst, const u16 val) { #ifdef HOST_64 u64 *dst_u64 = (u64 *)dst; const u64 val_u64 = ((u64)val << 48) | ((u64)val << 32) | ((u64)val << 16) | (u64)val; MACRODO_N(LENGTH / (sizeof(val_u64) / sizeof(val)), (dst_u64[(X)] = val_u64)); #else size_t i; for (i = 0; i < LENGTH; i++) ((u16 *)dst)[i] = val; #endif } static void memset_u32(void *dst, const u32 val, const size_t length) { #ifdef HOST_64 u64 *dst_u64 = (u64 *)dst; const u64 val_u64 = ((u64)val << 32) | (u64)val; const size_t length_u64 = length / (sizeof(val_u64) / sizeof(val)); for (size_t i = 0; i < length_u64; i++) dst_u64[i] = val_u64; #else size_t i; for (i = 0; i < length; i++) ((u32 *)dst)[i] = val; #endif } template static void memset_u32_fast(void *dst, const u32 val) { #ifdef HOST_64 u64 *dst_u64 = (u64 *)dst; const u64 val_u64 = ((u64)val << 32) | (u64)val; MACRODO_N(LENGTH / (sizeof(val_u64) / sizeof(val)), (dst_u64[(X)] = val_u64)); #else size_t i; for (i = 0; i < LENGTH; i++) ((u16 *)dst)[i] = val; #endif } #endif // ENABLE_SSE2 // NOSSE version always used in gfx3d.cpp void _NOSSE_MatrixMultVec4x4 (const float *matrix, float *vecPtr); void MatrixMultVec3x3_fixed(const s32 *matrix, s32 *vecPtr); //--------------------------- //switched SSE functions #ifdef ENABLE_SSE struct SSE_MATRIX { SSE_MATRIX(const float *matrix) : row0(_mm_load_ps(matrix)) , row1(_mm_load_ps(matrix+4)) , row2(_mm_load_ps(matrix+8)) , row3(_mm_load_ps(matrix+12)) {} union { __m128 rows[4]; struct { __m128 row0; __m128 row1; __m128 row2; __m128 row3; }; }; }; FORCEINLINE __m128 _util_MatrixMultVec4x4_(const SSE_MATRIX &mat, __m128 vec) { __m128 xmm5 = _mm_shuffle_ps(vec, vec, B8(01010101)); __m128 xmm6 = _mm_shuffle_ps(vec, vec, B8(10101010)); __m128 xmm7 = _mm_shuffle_ps(vec, vec, B8(11111111)); __m128 xmm4 = _mm_shuffle_ps(vec, vec, B8(00000000)); xmm4 = _mm_mul_ps(xmm4,mat.row0); xmm5 = _mm_mul_ps(xmm5,mat.row1); xmm6 = _mm_mul_ps(xmm6,mat.row2); xmm7 = _mm_mul_ps(xmm7,mat.row3); xmm4 = _mm_add_ps(xmm4,xmm5); xmm4 = _mm_add_ps(xmm4,xmm6); xmm4 = _mm_add_ps(xmm4,xmm7); return xmm4; } FORCEINLINE void MatrixMultVec4x4(const float *matrix, float *vecPtr) { _mm_store_ps(vecPtr,_util_MatrixMultVec4x4_((SSE_MATRIX)matrix,_mm_load_ps(vecPtr))); } FORCEINLINE void MatrixMultVec4x4_M2(const float *matrix, float *vecPtr) { //there are hardly any gains from merging these manually MatrixMultVec4x4(matrix+16,vecPtr); MatrixMultVec4x4(matrix,vecPtr); } FORCEINLINE void MatrixMultVec3x3(const float * matrix, float * vecPtr) { const __m128 vec = _mm_load_ps(vecPtr); __m128 xmm5 = _mm_shuffle_ps(vec, vec, B8(01010101)); __m128 xmm6 = _mm_shuffle_ps(vec, vec, B8(10101010)); __m128 xmm4 = _mm_shuffle_ps(vec, vec, B8(00000000)); const SSE_MATRIX mat(matrix); xmm4 = _mm_mul_ps(xmm4,mat.row0); xmm5 = _mm_mul_ps(xmm5,mat.row1); xmm6 = _mm_mul_ps(xmm6,mat.row2); xmm4 = _mm_add_ps(xmm4,xmm5); xmm4 = _mm_add_ps(xmm4,xmm6); _mm_store_ps(vecPtr,xmm4); } FORCEINLINE void MatrixTranslate(float *matrix, const float *ptr) { __m128 xmm4 = _mm_load_ps(ptr); __m128 xmm5 = _mm_shuffle_ps(xmm4, xmm4, B8(01010101)); __m128 xmm6 = _mm_shuffle_ps(xmm4, xmm4, B8(10101010)); xmm4 = _mm_shuffle_ps(xmm4, xmm4, B8(00000000)); xmm4 = _mm_mul_ps(xmm4,_mm_load_ps(matrix)); xmm5 = _mm_mul_ps(xmm5,_mm_load_ps(matrix+4)); xmm6 = _mm_mul_ps(xmm6,_mm_load_ps(matrix+8)); xmm4 = _mm_add_ps(xmm4,xmm5); xmm4 = _mm_add_ps(xmm4,xmm6); xmm4 = _mm_add_ps(xmm4,_mm_load_ps(matrix+12)); _mm_store_ps(matrix+12,xmm4); } FORCEINLINE void MatrixScale(float *matrix, const float *ptr) { __m128 xmm4 = _mm_load_ps(ptr); __m128 xmm5 = _mm_shuffle_ps(xmm4, xmm4, B8(01010101)); __m128 xmm6 = _mm_shuffle_ps(xmm4, xmm4, B8(10101010)); xmm4 = _mm_shuffle_ps(xmm4, xmm4, B8(00000000)); xmm4 = _mm_mul_ps(xmm4,_mm_load_ps(matrix)); xmm5 = _mm_mul_ps(xmm5,_mm_load_ps(matrix+4)); xmm6 = _mm_mul_ps(xmm6,_mm_load_ps(matrix+8)); _mm_store_ps(matrix,xmm4); _mm_store_ps(matrix+4,xmm5); _mm_store_ps(matrix+8,xmm6); } template FORCEINLINE void vector_fix2float(float* matrix, const float divisor) { __m128 val; retro_assert(NUM_ROWS==3 || NUM_ROWS==4); val = _mm_set_ps1(divisor); _mm_store_ps(matrix,_mm_div_ps(_mm_load_ps(matrix),val)); _mm_store_ps(matrix+4,_mm_div_ps(_mm_load_ps(matrix+4),val)); _mm_store_ps(matrix+8,_mm_div_ps(_mm_load_ps(matrix+8),val)); if(NUM_ROWS==4) _mm_store_ps(matrix+12,_mm_div_ps(_mm_load_ps(matrix+12),val)); } #else //no sse void MatrixMultVec4x4 (const float *matrix, float *vecPtr); void MatrixMultVec3x3(const float * matrix, float * vecPtr); void MatrixTranslate(float *matrix, const float *ptr); void MatrixScale(float * matrix, const float * ptr); FORCEINLINE void MatrixMultVec4x4_M2(const float *matrix, float *vecPtr) { //there are hardly any gains from merging these manually MatrixMultVec4x4(matrix+16,vecPtr); MatrixMultVec4x4(matrix,vecPtr); } template FORCEINLINE void vector_fix2float(float* matrix, const float divisor) { unsigned i; for(i=0;i. */ #ifndef _FS_NITRO_H_ #define _FS_NITRO_H_ #include #ifndef _MSC_VER #include #include #endif #include "../types.h" using namespace std; enum FNT_TYPES { FS_FILE_ENTRY = 0, FS_SUBDIR_ENTRY = 1, FS_END_SUBTABLE = 2, FS_RESERVED = 3, }; #include "PACKED.h" struct FAT_NITRO { FAT_NITRO() : start(0) , end(0) , size(0) , parentOffset(0) , isOverlay(false) , file(false) , sizeFile(0) , parentID(0) { } u32 start; u32 end; u32 size; u32 parentOffset; bool isOverlay; bool file; u32 sizeFile; u16 parentID; string filename; }; struct FNT_MAIN { u32 offset; u16 firstID; u16 parentID; }; struct FNT_NITRO { FNT_NITRO() : offset(0) , firstID(0) , parentID(0) { } u32 offset; u16 firstID; u16 parentID; string filename; }; struct OVR_NITRO { u32 id; u32 RAMaddr; u32 RAMSize; u32 BSSSize; u32 start; u32 end; u32 fileID; u32 reserved; }; #include "PACKED_END.h" class FS_NITRO { private: bool inited; u32 FNameTblOff; u32 FNameTblSize; u32 FATOff; u32 FATSize; u32 FATEnd; u32 ARM9OverlayOff; u32 ARM9OverlaySize; u32 ARM7OverlayOff; u32 ARM7OverlaySize; u32 ARM9exeStart; u32 ARM9exeEnd; u32 ARM9exeSize; u32 ARM7exeStart; u32 ARM7exeEnd; u32 ARM7exeSize; u32 numFiles; u32 numDirs; u32 numOverlay7; u32 numOverlay9; u32 currentID; u8 *rom; FAT_NITRO *fat; FNT_NITRO *fnt; OVR_NITRO *ovr9; OVR_NITRO *ovr7; FNT_TYPES getFNTType(u8 type); bool loadFileTables(); bool extract(u16 id, string to); void destroy(); public: FS_NITRO(u8 *cart_rom); ~FS_NITRO(); bool getFileIdByAddr(u32 addr, u16 &id); bool getFileIdByAddr(u32 addr, u16 &id, u32 &offset); string getDirNameByID(u16 id); u16 getDirParrentByID(u16 id); string getFileNameByID(u16 id); string getFullPathByFileID(u16 id, bool addRoot = true); u16 getFileParentById(u16 id); u32 getFileSizeById(u16 id); u32 getStartAddrById(u16 id); u32 getEndAddrById(u16 id); bool isOverlay(u16 id) { if (id > numFiles) return false; return fat[id].isOverlay; } bool isARM9(u32 addr) { return ((addr >= ARM9exeStart) && (addr < ARM9exeEnd)); } bool isARM7(u32 addr) { return ((addr >= ARM7exeStart) && (addr < ARM7exeEnd)); } bool isFAT(u32 addr) { return ((addr >= FATOff) && (addr < FATEnd)); } bool rebuildFAT(u32 addr, u32 size, string pathData); bool rebuildFAT(string pathData); u32 getFATRecord(u32 addr); bool extractFile(u16 id, string to); bool extractAll(string to, void (*callback)(u32 current, u32 num) = NULL); u32 getNumDirs() { return numDirs; } u32 getNumFiles() { return numFiles; } }; #endif desmume/src/libretro-common/gfx/math/vector_3.c000664 001750 001750 00000004517 12755534123 022663 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2016 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (vector_3.c). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include #include #include float vec3_dot(const float *a, const float *b) { return a[0] * b[0] + a[1] * b[1] + a[2] * b[2]; } void vec3_cross(float* dst, const float *a, const float *b) { dst[0] = a[1]*b[2] - a[2]*b[1]; dst[1] = a[2]*b[0] - a[0]*b[2]; dst[2] = a[0]*b[1] - a[1]*b[0]; } float vec3_length(const float *a) { float length_sq = vec3_dot(a,a); float length = sqrtf(length_sq); return length; } void vec3_add(float *dst, const float *src) { dst[0] += src[0]; dst[1] += src[1]; dst[2] += src[2]; } void vec3_subtract(float *dst, const float *src) { dst[0] -= src[0]; dst[1] -= src[1]; dst[2] -= src[2]; } void vec3_scale(float *dst, const float scale) { dst[0] *= scale; dst[1] *= scale; dst[2] *= scale; } void vec3_copy(float *dst, const float *src) { dst[0] = src[0]; dst[1] = src[1]; dst[2] = src[2]; } void vec3_normalize(float *dst) { float length = vec3_length(dst); vec3_scale(dst,1.0f/length); } desmume/src/utils/AsmJit/x86/x86operand.cpp000664 001750 001750 00000026753 12755534123 021632 0ustar00sergiosergio000000 000000 // [AsmJit] // Complete JIT Assembler for C++ Language. // // [License] // Zlib - See COPYING file in this package. #define ASMJIT_EXPORTS // [Dependencies - AsmJit] #include "../x86/x86defs.h" #include "../x86/x86operand.h" // [Api-Begin] #include "../core/apibegin.h" namespace AsmJit { // ============================================================================ // [AsmJit::Registers - no_reg] // ============================================================================ const GpReg no_reg(_Initialize(), kInvalidValue); // ============================================================================ // [AsmJit::Registers - 8-bit] // ============================================================================ const GpReg al(_Initialize(), kX86RegAl); const GpReg cl(_Initialize(), kX86RegCl); const GpReg dl(_Initialize(), kX86RegDl); const GpReg bl(_Initialize(), kX86RegBl); #if defined(ASMJIT_X64) const GpReg spl(_Initialize(), kX86RegSpl); const GpReg bpl(_Initialize(), kX86RegBpl); const GpReg sil(_Initialize(), kX86RegSil); const GpReg dil(_Initialize(), kX86RegDil); const GpReg r8b(_Initialize(), kX86RegR8b); const GpReg r9b(_Initialize(), kX86RegR9b); const GpReg r10b(_Initialize(), kX86RegR10b); const GpReg r11b(_Initialize(), kX86RegR11b); const GpReg r12b(_Initialize(), kX86RegR12b); const GpReg r13b(_Initialize(), kX86RegR13b); const GpReg r14b(_Initialize(), kX86RegR14b); const GpReg r15b(_Initialize(), kX86RegR15b); #endif // ASMJIT_X64 const GpReg ah(_Initialize(), kX86RegAh); const GpReg ch(_Initialize(), kX86RegCh); const GpReg dh(_Initialize(), kX86RegDh); const GpReg bh(_Initialize(), kX86RegBh); // ============================================================================ // [AsmJit::Registers - 16-bit] // ============================================================================ const GpReg ax(_Initialize(), kX86RegAx); const GpReg cx(_Initialize(), kX86RegCx); const GpReg dx(_Initialize(), kX86RegDx); const GpReg bx(_Initialize(), kX86RegBx); const GpReg sp(_Initialize(), kX86RegSp); const GpReg bp(_Initialize(), kX86RegBp); const GpReg si(_Initialize(), kX86RegSi); const GpReg di(_Initialize(), kX86RegDi); #if defined(ASMJIT_X64) const GpReg r8w(_Initialize(), kX86RegR8w); const GpReg r9w(_Initialize(), kX86RegR9w); const GpReg r10w(_Initialize(), kX86RegR10w); const GpReg r11w(_Initialize(), kX86RegR11w); const GpReg r12w(_Initialize(), kX86RegR12w); const GpReg r13w(_Initialize(), kX86RegR13w); const GpReg r14w(_Initialize(), kX86RegR14w); const GpReg r15w(_Initialize(), kX86RegR15w); #endif // ASMJIT_X64 // ============================================================================ // [AsmJit::Registers - 32-bit] // ============================================================================ const GpReg eax(_Initialize(), kX86RegEax); const GpReg ecx(_Initialize(), kX86RegEcx); const GpReg edx(_Initialize(), kX86RegEdx); const GpReg ebx(_Initialize(), kX86RegEbx); const GpReg esp(_Initialize(), kX86RegEsp); const GpReg ebp(_Initialize(), kX86RegEbp); const GpReg esi(_Initialize(), kX86RegEsi); const GpReg edi(_Initialize(), kX86RegEdi); #if defined(ASMJIT_X64) const GpReg r8d(_Initialize(), kX86RegR8d); const GpReg r9d(_Initialize(), kX86RegR9d); const GpReg r10d(_Initialize(), kX86RegR10d); const GpReg r11d(_Initialize(), kX86RegR11d); const GpReg r12d(_Initialize(), kX86RegR12d); const GpReg r13d(_Initialize(), kX86RegR13d); const GpReg r14d(_Initialize(), kX86RegR14d); const GpReg r15d(_Initialize(), kX86RegR15d); #endif // ASMJIT_X64 // ============================================================================ // [AsmJit::Registers - 64-bit] // ============================================================================ #if defined(ASMJIT_X64) const GpReg rax(_Initialize(), kX86RegRax); const GpReg rcx(_Initialize(), kX86RegRcx); const GpReg rdx(_Initialize(), kX86RegRdx); const GpReg rbx(_Initialize(), kX86RegRbx); const GpReg rsp(_Initialize(), kX86RegRsp); const GpReg rbp(_Initialize(), kX86RegRbp); const GpReg rsi(_Initialize(), kX86RegRsi); const GpReg rdi(_Initialize(), kX86RegRdi); const GpReg r8(_Initialize(), kX86RegR8); const GpReg r9(_Initialize(), kX86RegR9); const GpReg r10(_Initialize(), kX86RegR10); const GpReg r11(_Initialize(), kX86RegR11); const GpReg r12(_Initialize(), kX86RegR12); const GpReg r13(_Initialize(), kX86RegR13); const GpReg r14(_Initialize(), kX86RegR14); const GpReg r15(_Initialize(), kX86RegR15); #endif // ASMJIT_X64 // ============================================================================ // [AsmJit::Registers - Native (AsmJit extension)] // ============================================================================ const GpReg zax(_Initialize(), kX86RegZax); const GpReg zcx(_Initialize(), kX86RegZcx); const GpReg zdx(_Initialize(), kX86RegZdx); const GpReg zbx(_Initialize(), kX86RegZbx); const GpReg zsp(_Initialize(), kX86RegZsp); const GpReg zbp(_Initialize(), kX86RegZbp); const GpReg zsi(_Initialize(), kX86RegZsi); const GpReg zdi(_Initialize(), kX86RegZdi); // ============================================================================ // [AsmJit::Registers - MM] // ============================================================================ const MmReg mm0(_Initialize(), kX86RegMm0); const MmReg mm1(_Initialize(), kX86RegMm1); const MmReg mm2(_Initialize(), kX86RegMm2); const MmReg mm3(_Initialize(), kX86RegMm3); const MmReg mm4(_Initialize(), kX86RegMm4); const MmReg mm5(_Initialize(), kX86RegMm5); const MmReg mm6(_Initialize(), kX86RegMm6); const MmReg mm7(_Initialize(), kX86RegMm7); // ============================================================================ // [AsmJit::Registers - XMM] // ============================================================================ const XmmReg xmm0(_Initialize(), kX86RegXmm0); const XmmReg xmm1(_Initialize(), kX86RegXmm1); const XmmReg xmm2(_Initialize(), kX86RegXmm2); const XmmReg xmm3(_Initialize(), kX86RegXmm3); const XmmReg xmm4(_Initialize(), kX86RegXmm4); const XmmReg xmm5(_Initialize(), kX86RegXmm5); const XmmReg xmm6(_Initialize(), kX86RegXmm6); const XmmReg xmm7(_Initialize(), kX86RegXmm7); #if defined(ASMJIT_X64) const XmmReg xmm8(_Initialize(), kX86RegXmm8); const XmmReg xmm9(_Initialize(), kX86RegXmm9); const XmmReg xmm10(_Initialize(), kX86RegXmm10); const XmmReg xmm11(_Initialize(), kX86RegXmm11); const XmmReg xmm12(_Initialize(), kX86RegXmm12); const XmmReg xmm13(_Initialize(), kX86RegXmm13); const XmmReg xmm14(_Initialize(), kX86RegXmm14); const XmmReg xmm15(_Initialize(), kX86RegXmm15); #endif // ASMJIT_X64 // ============================================================================ // [AsmJit::Registers - Segment] // ============================================================================ const SegmentReg cs(_Initialize(), kX86RegCs); const SegmentReg ss(_Initialize(), kX86RegSs); const SegmentReg ds(_Initialize(), kX86RegDs); const SegmentReg es(_Initialize(), kX86RegEs); const SegmentReg fs(_Initialize(), kX86RegFs); const SegmentReg gs(_Initialize(), kX86RegGs); // ============================================================================ // [AsmJit::Var] // ============================================================================ Mem _BaseVarMem(const Var& var, uint32_t size) { Mem m; //(_DontInitialize()); m._mem.op = kOperandMem; m._mem.size = static_cast(size == kInvalidValue ? var.getSize() : size); m._mem.type = kOperandMemNative; m._mem.segment = kX86SegNone; m._mem.sizePrefix = 0; m._mem.shift = 0; m._mem.id = var.getId(); m._mem.base = kInvalidValue; m._mem.index = kInvalidValue; m._mem.target = NULL; m._mem.displacement = 0; return m; } Mem _BaseVarMem(const Var& var, uint32_t size, sysint_t disp) { Mem m; //(_DontInitialize()); m._mem.op = kOperandMem; m._mem.size = static_cast(size == kInvalidValue ? var.getSize() : size); m._mem.type = kOperandMemNative; m._mem.segment = kX86SegNone; m._mem.sizePrefix = 0; m._mem.shift = 0; m._mem.id = var.getId(); m._mem.base = kInvalidValue; m._mem.index = kInvalidValue; m._mem.target = NULL; m._mem.displacement = disp; return m; } Mem _BaseVarMem(const Var& var, uint32_t size, const GpVar& index, uint32_t shift, sysint_t disp) { Mem m; //(_DontInitialize()); m._mem.op = kOperandMem; m._mem.size = static_cast(size == kInvalidValue ? var.getSize() : size); m._mem.type = kOperandMemNative; m._mem.segment = kX86SegNone; m._mem.sizePrefix = 0; m._mem.shift = shift; m._mem.id = var.getId(); m._mem.base = kInvalidValue; m._mem.index = index.getId(); m._mem.target = NULL; m._mem.displacement = disp; return m; } // ============================================================================ // [AsmJit::Mem - ptr[]] // ============================================================================ Mem ptr(const Label& label, sysint_t disp, uint32_t size) { return Mem(label, disp, size); } Mem ptr(const Label& label, const GpReg& index, uint32_t shift, sysint_t disp, uint32_t size) { Mem m(label, disp, size); m._mem.index = index.getRegIndex(); m._mem.shift = shift; return m; } Mem ptr(const Label& label, const GpVar& index, uint32_t shift, sysint_t disp, uint32_t size) { Mem m(label, disp, size); m._mem.index = index.getId(); m._mem.shift = shift; return m; } // ============================================================================ // [AsmJit::Mem - ptr[] - Absolute Addressing] // ============================================================================ ASMJIT_API Mem ptr_abs(void* target, sysint_t disp, uint32_t size) { Mem m; m._mem.size = size; m._mem.type = kOperandMemAbsolute; m._mem.segment = kX86SegNone; m._mem.target = target; m._mem.displacement = disp; return m; } ASMJIT_API Mem ptr_abs(void* target, const GpReg& index, uint32_t shift, sysint_t disp, uint32_t size) { Mem m;// (_DontInitialize()); m._mem.op = kOperandMem; m._mem.size = size; m._mem.type = kOperandMemAbsolute; m._mem.segment = kX86SegNone; #if defined(ASMJIT_X86) m._mem.sizePrefix = index.getSize() != 4; #else m._mem.sizePrefix = index.getSize() != 8; #endif m._mem.shift = shift; m._mem.id = kInvalidValue; m._mem.base = kInvalidValue; m._mem.index = index.getRegIndex(); m._mem.target = target; m._mem.displacement = disp; return m; } ASMJIT_API Mem ptr_abs(void* target, const GpVar& index, uint32_t shift, sysint_t disp, uint32_t size) { Mem m;// (_DontInitialize()); m._mem.op = kOperandMem; m._mem.size = size; m._mem.type = kOperandMemAbsolute; m._mem.segment = kX86SegNone; #if defined(ASMJIT_X86) m._mem.sizePrefix = index.getSize() != 4; #else m._mem.sizePrefix = index.getSize() != 8; #endif m._mem.shift = shift; m._mem.id = kInvalidValue; m._mem.base = kInvalidValue; m._mem.index = index.getId(); m._mem.target = target; m._mem.displacement = disp; return m; } // ============================================================================ // [AsmJit::Mem - ptr[base + displacement]] // ============================================================================ Mem ptr(const GpReg& base, sysint_t disp, uint32_t size) { return Mem(base, disp, size); } Mem ptr(const GpReg& base, const GpReg& index, uint32_t shift, sysint_t disp, uint32_t size) { return Mem(base, index, shift, disp, size); } Mem ptr(const GpVar& base, sysint_t disp, uint32_t size) { return Mem(base, disp, size); } Mem ptr(const GpVar& base, const GpVar& index, uint32_t shift, sysint_t disp, uint32_t size) { return Mem(base, index, shift, disp, size); } } // AsmJit namespace // [Api-End] #include "../core/apiend.h" desmume/COPYING000664 001750 001750 00000043254 12755534123 014413 0ustar00sergiosergio000000 000000 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 Lesser 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 Lesser General Public License instead of this License. desmume/src/utils/AsmJit/core/context.cpp000664 001750 001750 00000004441 12755534123 021611 0ustar00sergiosergio000000 000000 // [AsmJit] // Complete JIT Assembler for C++ Language. // // [License] // Zlib - See COPYING file in this package. #define ASMJIT_EXPORTS // [Dependencies - AsmJit] #include "../core/assembler.h" #include "../core/context.h" #include "../core/defs.h" #include "../core/memorymanager.h" #include "../core/memorymarker.h" namespace AsmJit { // ============================================================================ // [AsmJit::Context - Construction / Destruction] // ============================================================================ Context::Context() {} Context::~Context() {} // ============================================================================ // [AsmJit::JitContext - Construction / Destruction] // ============================================================================ JitContext::JitContext() : _memoryManager(NULL), _memoryMarker(NULL), _allocType(kMemAllocFreeable) { } JitContext::~JitContext() { } // ============================================================================ // [AsmJit::JitContext - Generate] // ============================================================================ uint32_t JitContext::generate(void** dest, Assembler* assembler) { // Disallow empty code generation. size_t codeSize = assembler->getCodeSize(); if (codeSize == 0) { *dest = NULL; return kErrorNoFunction; } // Switch to global memory manager if not provided. MemoryManager* memmgr = getMemoryManager(); if (memmgr == NULL) memmgr = MemoryManager::getGlobal(); void* p = memmgr->alloc(codeSize, getAllocType()); if (p == NULL) { *dest = NULL; return kErrorNoVirtualMemory; } // Relocate the code. size_t relocatedSize = assembler->relocCode(p); // Return unused memory to MemoryManager. if (relocatedSize < codeSize) memmgr->shrink(p, relocatedSize); // Mark memory if MemoryMarker provided. if (_memoryMarker) _memoryMarker->mark(p, relocatedSize); // Return the code. *dest = p; return kErrorOk; } // ============================================================================ // [AsmJit::JitContext - GetGlobal] // ============================================================================ JitContext* JitContext::getGlobal() { static JitContext global; return &global; } } // AsmJit namespace desmume/src/libretro-common/libco/armeabi.c000664 001750 001750 00000003756 12755534123 022116 0ustar00sergiosergio000000 000000 /* libco.armeabi (2013-04-05) author: Themaister license: public domain */ #define LIBCO_C #include #include #include #include #include #ifndef __APPLE__ #include #endif #ifdef __cplusplus extern "C" { #endif static thread_local uint32_t co_active_buffer[64]; static thread_local cothread_t co_active_handle; asm ( ".arm\n" ".align 4\n" ".globl co_switch_arm\n" ".globl _co_switch_arm\n" "co_switch_arm:\n" "_co_switch_arm:\n" " stmia r1!, {r4, r5, r6, r7, r8, r9, r10, r11, sp, lr}\n" " ldmia r0!, {r4, r5, r6, r7, r8, r9, r10, r11, sp, pc}\n" ); /* ASM */ void co_switch_arm(cothread_t handle, cothread_t current); static void crash(void) { /* Called only if cothread_t entrypoint returns. */ assert(0); } cothread_t co_create(unsigned int size, void (*entrypoint)(void)) { size = (size + 1023) & ~1023; cothread_t handle = 0; #if defined(__APPLE__) || HAVE_POSIX_MEMALIGN >= 1 if (posix_memalign(&handle, 1024, size + 256) < 0) return 0; #else handle = memalign(1024, size + 256); #endif if (!handle) return handle; uint32_t *ptr = (uint32_t*)handle; /* Non-volatiles. */ ptr[0] = 0; /* r4 */ ptr[1] = 0; /* r5 */ ptr[2] = 0; /* r6 */ ptr[3] = 0; /* r7 */ ptr[4] = 0; /* r8 */ ptr[5] = 0; /* r9 */ ptr[6] = 0; /* r10 */ ptr[7] = 0; /* r11 */ /* Align stack to 64-bit */ ptr[8] = (uintptr_t)ptr + size + 256 - 8; /* r13, stack pointer */ ptr[9] = (uintptr_t)entrypoint; /* r15, PC (link register r14 gets saved here). */ return handle; } cothread_t co_active(void) { if (!co_active_handle) co_active_handle = co_active_buffer; return co_active_handle; } void co_delete(cothread_t handle) { free(handle); } void co_switch(cothread_t handle) { cothread_t co_previous_handle = co_active(); co_switch_arm(co_active_handle = handle, co_previous_handle); } #ifdef __cplusplus } #endif desmume/src/render3D.cpp000664 001750 001750 00000062402 12755534123 016315 0ustar00sergiosergio000000 000000 /* Copyright (C) 2006-2007 shash Copyright (C) 2008-2015 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the this software. If not, see . */ #include "render3D.h" #include #ifdef ENABLE_SSE2 #include #endif #ifdef ENABLE_SSSE3 #include #endif #include "utils/bits.h" #include "common.h" #include "gfx3d.h" #include "MMU.h" #include "texcache.h" static CACHE_ALIGN u32 dsDepthToD24_LUT[32768] = {0}; int cur3DCore = GPU3D_NULL; GPU3DInterface gpu3DNull = { "None", Render3DBaseCreate, Render3DBaseDestroy }; GPU3DInterface *gpu3D = &gpu3DNull; Render3D *BaseRenderer = NULL; Render3D *CurrentRenderer = NULL; void Render3D_Init() { if (BaseRenderer == NULL) BaseRenderer = new Render3D; if (CurrentRenderer == NULL) { gpu3D = &gpu3DNull; cur3DCore = GPU3D_NULL; CurrentRenderer = BaseRenderer; } } void Render3D_DeInit() { gpu3D->NDS_3D_Close(); delete BaseRenderer; BaseRenderer = NULL; } bool NDS_3D_ChangeCore(int newCore) { bool result = false; Render3DInterface *newRenderInterface = core3DList[newCore]; if (newRenderInterface->NDS_3D_Init == NULL) return result; // Some resources are shared between renderers, such as the texture cache, // so we need to shut down the current renderer now to ensure that any // shared resources aren't in use. CurrentRenderer->RenderFinish(); gpu3D->NDS_3D_Close(); gpu3D = &gpu3DNull; cur3DCore = GPU3D_NULL; CurrentRenderer = BaseRenderer; Render3D *newRenderer = newRenderInterface->NDS_3D_Init(); if (newRenderer == NULL) return result; Render3DError error = newRenderer->SetFramebufferSize(GPU->GetCustomFramebufferWidth(), GPU->GetCustomFramebufferHeight()); if (error != RENDER3DERROR_NOERR) return result; gpu3D = newRenderInterface; cur3DCore = newCore; CurrentRenderer = newRenderer; result = true; return result; } Render3D* Render3DBaseCreate() { BaseRenderer->Reset(); return BaseRenderer; } void Render3DBaseDestroy() { if (CurrentRenderer != BaseRenderer) { delete CurrentRenderer; CurrentRenderer = BaseRenderer; } } FragmentAttributesBuffer::FragmentAttributesBuffer(size_t newCount) { count = newCount; depth = (u32 *)memalign_alloc_aligned(count * sizeof(u32)); opaquePolyID = (u8 *)memalign_alloc_aligned(count * sizeof(u8)); translucentPolyID = (u8 *)memalign_alloc_aligned(count * sizeof(u8)); stencil = (u8 *)memalign_alloc_aligned(count * sizeof(u8)); isFogged = (u8 *)memalign_alloc_aligned(count * sizeof(u8)); isTranslucentPoly = (u8 *)memalign_alloc_aligned(count * sizeof(u8)); } FragmentAttributesBuffer::~FragmentAttributesBuffer() { memalign_free(depth); memalign_free(opaquePolyID); memalign_free(translucentPolyID); memalign_free(stencil); memalign_free(isFogged); memalign_free(isTranslucentPoly); } void FragmentAttributesBuffer::SetAtIndex(const size_t index, const FragmentAttributes &attr) { this->depth[index] = attr.depth; this->opaquePolyID[index] = attr.opaquePolyID; this->translucentPolyID[index] = attr.translucentPolyID; this->stencil[index] = attr.stencil; this->isFogged[index] = attr.isFogged; this->isTranslucentPoly[index] = attr.isTranslucentPoly; } void FragmentAttributesBuffer::SetAll(const FragmentAttributes &attr) { size_t i = 0; #ifdef ENABLE_SSE2 const __m128i attrDepth_vec128 = _mm_set1_epi32(attr.depth); const __m128i attrOpaquePolyID_vec128 = _mm_set1_epi8(attr.opaquePolyID); const __m128i attrTranslucentPolyID_vec128 = _mm_set1_epi8(attr.translucentPolyID); const __m128i attrStencil_vec128 = _mm_set1_epi8(attr.stencil); const __m128i attrIsFogged_vec128 = _mm_set1_epi8(attr.isFogged); const __m128i attrIsTranslucentPoly_vec128 = _mm_set1_epi8(attr.isTranslucentPoly); const size_t sseCount = count - (count % 16); for (; i < sseCount; i += 16) { _mm_stream_si128((__m128i *)(this->depth + 0), attrDepth_vec128); _mm_stream_si128((__m128i *)(this->depth + 4), attrDepth_vec128); _mm_stream_si128((__m128i *)(this->depth + 8), attrDepth_vec128); _mm_stream_si128((__m128i *)(this->depth + 12), attrDepth_vec128); _mm_stream_si128((__m128i *)this->opaquePolyID, attrOpaquePolyID_vec128); _mm_stream_si128((__m128i *)this->translucentPolyID, attrTranslucentPolyID_vec128); _mm_stream_si128((__m128i *)this->stencil, attrStencil_vec128); _mm_stream_si128((__m128i *)this->isFogged, attrIsFogged_vec128); _mm_stream_si128((__m128i *)this->isTranslucentPoly, attrIsTranslucentPoly_vec128); } #endif for (; i < count; i++) this->SetAtIndex(i, attr); } Render3D::Render3D() { _renderID = RENDERID_NULL; _renderName = "None"; static bool needTableInit = true; if (needTableInit) { size_t i; for (i = 0; i < 32768; i++) dsDepthToD24_LUT[i] = (u32)DS_DEPTH15TO24(i); needTableInit = false; } _framebufferWidth = GPU_FRAMEBUFFER_NATIVE_WIDTH; _framebufferHeight = GPU_FRAMEBUFFER_NATIVE_HEIGHT; _framebufferColorSizeBytes = 0; _framebufferColor = NULL; Reset(); } Render3D::~Render3D() { memalign_free(_framebufferColor); } RendererID Render3D::GetRenderID() { return this->_renderID; } std::string Render3D::GetName() { return this->_renderName; } FragmentColor* Render3D::GetFramebuffer() { return this->_framebufferColor; } size_t Render3D::GetFramebufferWidth() { return this->_framebufferWidth; } size_t Render3D::GetFramebufferHeight() { return this->_framebufferHeight; } Render3DError Render3D::SetFramebufferSize(size_t w, size_t h) { if (w < GPU_FRAMEBUFFER_NATIVE_WIDTH || h < GPU_FRAMEBUFFER_NATIVE_HEIGHT) return RENDER3DERROR_NOERR; const size_t newFramebufferColorSizeBytes = w * h * sizeof(FragmentColor); FragmentColor *oldFramebufferColor = this->_framebufferColor; FragmentColor *newFramebufferColor = (FragmentColor *)memalign_alloc_aligned(newFramebufferColorSizeBytes); this->_framebufferWidth = w; this->_framebufferHeight = h; this->_framebufferColorSizeBytes = newFramebufferColorSizeBytes; this->_framebufferColor = newFramebufferColor; memalign_free(oldFramebufferColor); return RENDER3DERROR_NOERR; } Render3DError Render3D::BeginRender(const GFX3D &engine) { return RENDER3DERROR_NOERR; } Render3DError Render3D::RenderGeometry(const GFX3D_State &renderState, const POLYLIST *polyList, const INDEXLIST *indexList) { return RENDER3DERROR_NOERR; } Render3DError Render3D::RenderEdgeMarking(const u16 *colorTable, const bool useAntialias) { return RENDER3DERROR_NOERR; } Render3DError Render3D::RenderFog(const u8 *densityTable, const u32 color, const u32 offset, const u8 shift, const bool alphaOnly) { return RENDER3DERROR_NOERR; } Render3DError Render3D::EndRender(const u64 frameCount) { return RENDER3DERROR_NOERR; } Render3DError Render3D::FlushFramebuffer(FragmentColor *__restrict dstRGBA6665, u16 *__restrict dstRGBA5551) { size_t i; memcpy(dstRGBA6665, this->_framebufferColor, this->_framebufferColorSizeBytes); /* Convert to RGBA5551 */ for (i = 0; i < (this->_framebufferWidth * this->_framebufferHeight); i++) { dstRGBA5551[i] = R6G6B6TORGB15( this->_framebufferColor[i].r, this->_framebufferColor[i].g, this->_framebufferColor[i].b) | ((this->_framebufferColor[i].a == 0) ? 0x0000 : 0x8000); } return RENDER3DERROR_NOERR; } Render3DError Render3D::UpdateToonTable(const u16 *toonTableBuffer) { return RENDER3DERROR_NOERR; } Render3DError Render3D::ClearFramebuffer(const GFX3D_State &renderState) { Render3DError error = RENDER3DERROR_NOERR; FragmentColor clearColor; clearColor.r = renderState.clearColor & 0x1F; clearColor.g = (renderState.clearColor >> 5) & 0x1F; clearColor.b = (renderState.clearColor >> 10) & 0x1F; clearColor.a = (renderState.clearColor >> 16) & 0x1F; FragmentAttributes clearFragment; clearFragment.opaquePolyID = (renderState.clearColor >> 24) & 0x3F; //special value for uninitialized translucent polyid. without this, fires in spiderman2 dont display //I am not sure whether it is right, though. previously this was cleared to 0, as a guess, //but in spiderman2 some fires with polyid 0 try to render on top of the background clearFragment.translucentPolyID = kUnsetTranslucentPolyID; clearFragment.depth = renderState.clearDepth; clearFragment.stencil = 0; clearFragment.isTranslucentPoly = 0; clearFragment.isFogged = BIT15(renderState.clearColor); if (renderState.enableClearImage) { //the lion, the witch, and the wardrobe (thats book 1, suck it you new-school numberers) //uses the scroll registers in the main game engine const u16 *__restrict clearColorBuffer = (u16 *__restrict)MMU.texInfo.textureSlotAddr[2]; const u16 *__restrict clearDepthBuffer = (u16 *__restrict)MMU.texInfo.textureSlotAddr[3]; const u16 scrollBits = T1ReadWord(MMU.ARM9_REG, 0x356); //CLRIMAGE_OFFSET const u8 xScroll = scrollBits & 0xFF; const u8 yScroll = (scrollBits >> 8) & 0xFF; if (xScroll == 0 && yScroll == 0) { size_t i; for (i = 0; i < GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT; i++) { this->clearImageColor16Buffer[i] = clearColorBuffer[i]; this->clearImageDepthBuffer[i] = dsDepthToD24_LUT[clearDepthBuffer[i] & 0x7FFF]; this->clearImageFogBuffer[i] = BIT15(clearDepthBuffer[i]); this->clearImagePolyIDBuffer[i] = clearFragment.opaquePolyID; } } else { size_t dstIndex; size_t iy = 0; for (dstIndex = 0; iy < GPU_FRAMEBUFFER_NATIVE_HEIGHT; iy++) { size_t ix; const size_t y = ((iy + yScroll) & 0xFF) << 8; for (ix = 0; ix < GPU_FRAMEBUFFER_NATIVE_WIDTH; dstIndex++, ix++) { const size_t x = (ix + xScroll) & 0xFF; const size_t srcIndex = y | x; //this is tested by harry potter and the order of the phoenix. //TODO (optimization) dont do this if we are mapped to blank memory (such as in sonic chronicles) //(or use a special zero fill in the bulk clearing above) this->clearImageColor16Buffer[dstIndex] = clearColorBuffer[srcIndex]; //this is tested quite well in the sonic chronicles main map mode //where depth values are used for trees etc you can walk behind this->clearImageDepthBuffer[dstIndex] = dsDepthToD24_LUT[clearDepthBuffer[srcIndex] & 0x7FFF]; this->clearImageFogBuffer[dstIndex] = BIT15(clearDepthBuffer[srcIndex]); this->clearImagePolyIDBuffer[dstIndex] = clearFragment.opaquePolyID; } } } error = this->ClearUsingImage( this->clearImageColor16Buffer, this->clearImageDepthBuffer, this->clearImageFogBuffer, this->clearImagePolyIDBuffer); if (error != RENDER3DERROR_NOERR) error = this->ClearUsingValues(clearColor, clearFragment); } else error = this->ClearUsingValues(clearColor, clearFragment); return error; } Render3DError Render3D::ClearUsingImage( const u16 *__restrict colorBuffer, const u32 *__restrict depthBuffer, const u8 *__restrict fogBuffer, const u8 *__restrict polyIDBuffer) { return RENDER3DERROR_NOERR; } Render3DError Render3D::ClearUsingValues( const FragmentColor &clearColor, const FragmentAttributes &clearAttributes) const { return RENDER3DERROR_NOERR; } Render3DError Render3D::SetupPolygon(const POLY &thePoly) { return RENDER3DERROR_NOERR; } Render3DError Render3D::SetupTexture(const POLY &thePoly, bool enableTexturing) { return RENDER3DERROR_NOERR; } Render3DError Render3D::SetupViewport(const u32 viewportValue) { return RENDER3DERROR_NOERR; } Render3DError Render3D::Reset() { if (this->_framebufferColor != NULL) { memset(this->_framebufferColor, 0, this->_framebufferColorSizeBytes); this->FlushFramebuffer(GPU->GetEngineMain()->Get3DFramebufferRGBA6665(), GPU->GetEngineMain()->Get3DFramebufferRGBA5551()); } memset(this->clearImageColor16Buffer, 0, sizeof(this->clearImageColor16Buffer)); memset(this->clearImageDepthBuffer, 0, sizeof(this->clearImageDepthBuffer)); memset(this->clearImagePolyIDBuffer, 0, sizeof(this->clearImagePolyIDBuffer)); memset(this->clearImageFogBuffer, 0, sizeof(this->clearImageFogBuffer)); TexCache_Reset(); return RENDER3DERROR_NOERR; } Render3DError Render3D::Render(const GFX3D &engine) { Render3DError error = RENDER3DERROR_NOERR; error = this->BeginRender(engine); if (error != RENDER3DERROR_NOERR) { return error; } this->UpdateToonTable(engine.renderState.u16ToonTable); this->ClearFramebuffer(engine.renderState); this->RenderGeometry(engine.renderState, engine.polylist, &engine.indexlist); if (engine.renderState.enableEdgeMarking) this->RenderEdgeMarking(engine.renderState.edgeMarkColorTable, engine.renderState.enableAntialiasing); if (engine.renderState.enableFog) { this->RenderFog( engine.renderState.fogDensityTable, engine.renderState.fogColor, engine.renderState.fogOffset, engine.renderState.fogShift, engine.renderState.enableFogAlphaOnly); } this->EndRender(engine.frameCtr); return error; } Render3DError Render3D::RenderFinish() { return RENDER3DERROR_NOERR; } Render3DError Render3D::VramReconfigureSignal() { TexCache_Invalidate(); return RENDER3DERROR_NOERR; } #ifdef ENABLE_SSE2 Render3DError Render3D_SSE2::FlushFramebuffer(FragmentColor *__restrict dstRGBA6665, u16 *__restrict dstRGBA5551) { size_t i; const __m128i zero_vec128 = _mm_setzero_si128(); const size_t pixCount = this->_framebufferWidth * this->_framebufferHeight; const size_t ssePixCount = pixCount - (pixCount % 4); for (i = 0; i < ssePixCount; i += 4) { // Copy the framebufferColor buffer __m128i color = _mm_load_si128((__m128i *)(this->_framebufferColor + i)); _mm_store_si128((__m128i *)(dstRGBA6665 + i), color); // Convert to RGBA5551 __m128i r = _mm_and_si128(color, _mm_set1_epi32(0x0000003E)); // Read from R r = _mm_srli_epi32(r, 1); // Shift to R __m128i g = _mm_and_si128(color, _mm_set1_epi32(0x00003E00)); // Read from G g = _mm_srli_epi32(g, 4); // Shift in G __m128i b = _mm_and_si128(color, _mm_set1_epi32(0x003E0000)); // Read from B b = _mm_srli_epi32(b, 7); // Shift to B __m128i a = _mm_and_si128(color, _mm_set1_epi32(0xFF000000)); // Read from A a = _mm_cmpeq_epi32(a, zero_vec128); // Determine A // From here on, we're going to do an SSE2 trick to pack 32-bit down to unsigned // 16-bit. Since SSE2 only has packssdw (signed 16-bit pack), then the alpha bit // may be undefined. Now if we were using SSE4.1's packusdw (unsigned 16-bit pack), // we wouldn't have to go through this hassle. But not everyone has an SSE4.1-capable // CPU, so doing this the SSE2 way is more guaranteed to work an everyone's CPU. // // To use packssdw, we take a bit one position lower for the alpha bit, run // packssdw, then shift the bit back to its original position. Then we por the // alpha vector with the post-packed color vector to get the final color. a = _mm_andnot_si128(a, _mm_set1_epi32(0x00004000)); // Mask out the bit before A a = _mm_packs_epi32(a, zero_vec128); // Pack 32-bit down to 16-bit a = _mm_slli_epi16(a, 1); // Shift the A bit back to where it needs to be // Assemble the RGB colors, pack the 32-bit color into a signed 16-bit color, then por the alpha bit back in. color = _mm_or_si128(_mm_or_si128(r, g), b); color = _mm_packs_epi32(color, zero_vec128); color = _mm_or_si128(color, a); _mm_storel_epi64((__m128i *)(dstRGBA5551 + i), color); } for (; i < pixCount; i++) { dstRGBA6665[i] = this->_framebufferColor[i]; dstRGBA5551[i] = R6G6B6TORGB15( this->_framebufferColor[i].r, this->_framebufferColor[i].g, this->_framebufferColor[i].b) | ((this->_framebufferColor[i].a == 0) ? 0x0000 : 0x8000); } return RENDER3DERROR_NOERR; } Render3DError Render3D_SSE2::ClearFramebuffer(const GFX3D_State &renderState) { Render3DError error = RENDER3DERROR_NOERR; FragmentColor clearColor; clearColor.r = renderState.clearColor & 0x1F; clearColor.g = (renderState.clearColor >> 5) & 0x1F; clearColor.b = (renderState.clearColor >> 10) & 0x1F; clearColor.a = (renderState.clearColor >> 16) & 0x1F; FragmentAttributes clearFragment; clearFragment.opaquePolyID = (renderState.clearColor >> 24) & 0x3F; //special value for uninitialized translucent polyid. without this, fires in spiderman2 dont display //I am not sure whether it is right, though. previously this was cleared to 0, as a guess, //but in spiderman2 some fires with polyid 0 try to render on top of the background clearFragment.translucentPolyID = kUnsetTranslucentPolyID; clearFragment.depth = renderState.clearDepth; clearFragment.stencil = 0; clearFragment.isTranslucentPoly = 0; clearFragment.isFogged = BIT15(renderState.clearColor); if (renderState.enableClearImage) { //the lion, the witch, and the wardrobe (thats book 1, suck it you new-school numberers) //uses the scroll registers in the main game engine const u16 *__restrict clearColorBuffer = (u16 *__restrict)MMU.texInfo.textureSlotAddr[2]; const u16 *__restrict clearDepthBuffer = (u16 *__restrict)MMU.texInfo.textureSlotAddr[3]; const u16 scrollBits = T1ReadWord(MMU.ARM9_REG, 0x356); //CLRIMAGE_OFFSET const u8 xScroll = scrollBits & 0xFF; const u8 yScroll = (scrollBits >> 8) & 0xFF; if (xScroll == 0 && yScroll == 0) { size_t i; const __m128i depthBitMask_vec128 = _mm_set1_epi16(0x7FFF); const __m128i fogBufferBitMask_vec128 = _mm_set1_epi16(BIT(15)); const __m128i opaquePolyID_vec128 = _mm_set1_epi8(clearFragment.opaquePolyID); for (i = 0; i < GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT; i += 16) { // Copy the colors to the color buffer. Since we can only copy 8 elements at once, // we need to load-store twice. _mm_store_si128( (__m128i *)(this->clearImageColor16Buffer + i + 8), _mm_loadu_si128((__m128i *)(clearColorBuffer + i + 8)) ); _mm_store_si128( (__m128i *)(this->clearImageColor16Buffer + i), _mm_loadu_si128((__m128i *)(clearColorBuffer + i)) ); // Write the depth values to the depth buffer. __m128i clearDepthHi_vec128 = _mm_loadu_si128((__m128i *)(clearDepthBuffer + i + 8)); __m128i clearDepthLo_vec128 = _mm_loadu_si128((__m128i *)(clearDepthBuffer + i)); clearDepthHi_vec128 = _mm_and_si128(clearDepthHi_vec128, depthBitMask_vec128); clearDepthLo_vec128 = _mm_and_si128(clearDepthLo_vec128, depthBitMask_vec128); this->clearImageDepthBuffer[i+15] = dsDepthToD24_LUT[_mm_extract_epi16(clearDepthHi_vec128, 7)]; this->clearImageDepthBuffer[i+14] = dsDepthToD24_LUT[_mm_extract_epi16(clearDepthHi_vec128, 6)]; this->clearImageDepthBuffer[i+13] = dsDepthToD24_LUT[_mm_extract_epi16(clearDepthHi_vec128, 5)]; this->clearImageDepthBuffer[i+12] = dsDepthToD24_LUT[_mm_extract_epi16(clearDepthHi_vec128, 4)]; this->clearImageDepthBuffer[i+11] = dsDepthToD24_LUT[_mm_extract_epi16(clearDepthHi_vec128, 3)]; this->clearImageDepthBuffer[i+10] = dsDepthToD24_LUT[_mm_extract_epi16(clearDepthHi_vec128, 2)]; this->clearImageDepthBuffer[i+ 9] = dsDepthToD24_LUT[_mm_extract_epi16(clearDepthHi_vec128, 1)]; this->clearImageDepthBuffer[i+ 8] = dsDepthToD24_LUT[_mm_extract_epi16(clearDepthHi_vec128, 0)]; this->clearImageDepthBuffer[i+ 7] = dsDepthToD24_LUT[_mm_extract_epi16(clearDepthLo_vec128, 7)]; this->clearImageDepthBuffer[i+ 6] = dsDepthToD24_LUT[_mm_extract_epi16(clearDepthLo_vec128, 6)]; this->clearImageDepthBuffer[i+ 5] = dsDepthToD24_LUT[_mm_extract_epi16(clearDepthLo_vec128, 5)]; this->clearImageDepthBuffer[i+ 4] = dsDepthToD24_LUT[_mm_extract_epi16(clearDepthLo_vec128, 4)]; this->clearImageDepthBuffer[i+ 3] = dsDepthToD24_LUT[_mm_extract_epi16(clearDepthLo_vec128, 3)]; this->clearImageDepthBuffer[i+ 2] = dsDepthToD24_LUT[_mm_extract_epi16(clearDepthLo_vec128, 2)]; this->clearImageDepthBuffer[i+ 1] = dsDepthToD24_LUT[_mm_extract_epi16(clearDepthLo_vec128, 1)]; this->clearImageDepthBuffer[i+ 0] = dsDepthToD24_LUT[_mm_extract_epi16(clearDepthLo_vec128, 0)]; // Write the fog flags to the fog flag buffer. clearDepthHi_vec128 = _mm_loadu_si128((__m128i *)(clearDepthBuffer + i + 8)); clearDepthLo_vec128 = _mm_loadu_si128((__m128i *)(clearDepthBuffer + i)); clearDepthHi_vec128 = _mm_and_si128(clearDepthHi_vec128, fogBufferBitMask_vec128); clearDepthLo_vec128 = _mm_and_si128(clearDepthLo_vec128, fogBufferBitMask_vec128); clearDepthHi_vec128 = _mm_srli_epi16(clearDepthHi_vec128, 15); clearDepthLo_vec128 = _mm_srli_epi16(clearDepthLo_vec128, 15); _mm_store_si128((__m128i *)(this->clearImageFogBuffer + i), _mm_packus_epi16(clearDepthLo_vec128, clearDepthHi_vec128)); // The one is easy. Just set the values in the polygon ID buffer. _mm_store_si128((__m128i *)(this->clearImagePolyIDBuffer + i), opaquePolyID_vec128); } } else { size_t dstIndex; const __m128i addrOffset = _mm_set_epi16(7, 6, 5, 4, 3, 2, 1, 0); const __m128i addrRolloverMask = _mm_set1_epi16(0x00FF); const __m128i opaquePolyID_vec128 = _mm_set1_epi8(clearFragment.opaquePolyID); size_t iy = 0; for (dstIndex = 0; iy < GPU_FRAMEBUFFER_NATIVE_HEIGHT; iy++) { size_t ix; const size_t y = ((iy + yScroll) & 0xFF) << 8; __m128i y_vec128 = _mm_set1_epi16(y); for (ix = 0; ix < GPU_FRAMEBUFFER_NATIVE_WIDTH; dstIndex += 8, ix += 8) { __m128i addr_vec128 = _mm_set1_epi16(ix + xScroll); addr_vec128 = _mm_add_epi16(addr_vec128, addrOffset); addr_vec128 = _mm_and_si128(addr_vec128, addrRolloverMask); addr_vec128 = _mm_or_si128(addr_vec128, y_vec128); this->clearImageColor16Buffer[dstIndex+7] = clearColorBuffer[_mm_extract_epi16(addr_vec128, 7)]; this->clearImageColor16Buffer[dstIndex+6] = clearColorBuffer[_mm_extract_epi16(addr_vec128, 6)]; this->clearImageColor16Buffer[dstIndex+5] = clearColorBuffer[_mm_extract_epi16(addr_vec128, 5)]; this->clearImageColor16Buffer[dstIndex+4] = clearColorBuffer[_mm_extract_epi16(addr_vec128, 4)]; this->clearImageColor16Buffer[dstIndex+3] = clearColorBuffer[_mm_extract_epi16(addr_vec128, 3)]; this->clearImageColor16Buffer[dstIndex+2] = clearColorBuffer[_mm_extract_epi16(addr_vec128, 2)]; this->clearImageColor16Buffer[dstIndex+1] = clearColorBuffer[_mm_extract_epi16(addr_vec128, 1)]; this->clearImageColor16Buffer[dstIndex+0] = clearColorBuffer[_mm_extract_epi16(addr_vec128, 0)]; this->clearImageDepthBuffer[dstIndex+7] = dsDepthToD24_LUT[clearDepthBuffer[_mm_extract_epi16(addr_vec128, 7)] & 0x7FFF]; this->clearImageDepthBuffer[dstIndex+6] = dsDepthToD24_LUT[clearDepthBuffer[_mm_extract_epi16(addr_vec128, 6)] & 0x7FFF]; this->clearImageDepthBuffer[dstIndex+5] = dsDepthToD24_LUT[clearDepthBuffer[_mm_extract_epi16(addr_vec128, 5)] & 0x7FFF]; this->clearImageDepthBuffer[dstIndex+4] = dsDepthToD24_LUT[clearDepthBuffer[_mm_extract_epi16(addr_vec128, 4)] & 0x7FFF]; this->clearImageDepthBuffer[dstIndex+3] = dsDepthToD24_LUT[clearDepthBuffer[_mm_extract_epi16(addr_vec128, 3)] & 0x7FFF]; this->clearImageDepthBuffer[dstIndex+2] = dsDepthToD24_LUT[clearDepthBuffer[_mm_extract_epi16(addr_vec128, 2)] & 0x7FFF]; this->clearImageDepthBuffer[dstIndex+1] = dsDepthToD24_LUT[clearDepthBuffer[_mm_extract_epi16(addr_vec128, 1)] & 0x7FFF]; this->clearImageDepthBuffer[dstIndex+0] = dsDepthToD24_LUT[clearDepthBuffer[_mm_extract_epi16(addr_vec128, 0)] & 0x7FFF]; this->clearImageFogBuffer[dstIndex+7] = BIT15( clearDepthBuffer[_mm_extract_epi16(addr_vec128, 7)] ); this->clearImageFogBuffer[dstIndex+6] = BIT15( clearDepthBuffer[_mm_extract_epi16(addr_vec128, 6)] ); this->clearImageFogBuffer[dstIndex+5] = BIT15( clearDepthBuffer[_mm_extract_epi16(addr_vec128, 5)] ); this->clearImageFogBuffer[dstIndex+4] = BIT15( clearDepthBuffer[_mm_extract_epi16(addr_vec128, 4)] ); this->clearImageFogBuffer[dstIndex+3] = BIT15( clearDepthBuffer[_mm_extract_epi16(addr_vec128, 3)] ); this->clearImageFogBuffer[dstIndex+2] = BIT15( clearDepthBuffer[_mm_extract_epi16(addr_vec128, 2)] ); this->clearImageFogBuffer[dstIndex+1] = BIT15( clearDepthBuffer[_mm_extract_epi16(addr_vec128, 1)] ); this->clearImageFogBuffer[dstIndex+0] = BIT15( clearDepthBuffer[_mm_extract_epi16(addr_vec128, 0)] ); _mm_storel_epi64((__m128i *)(this->clearImagePolyIDBuffer + dstIndex), opaquePolyID_vec128); } } } error = this->ClearUsingImage(this->clearImageColor16Buffer, this->clearImageDepthBuffer, this->clearImageFogBuffer, this->clearImagePolyIDBuffer); if (error != RENDER3DERROR_NOERR) error = this->ClearUsingValues(clearColor, clearFragment); } else error = this->ClearUsingValues(clearColor, clearFragment); return error; } #endif // ENABLE_SSE2 desmume/src/libretro-common/conversion/s16_to_float_neon.S000664 001750 001750 00000003213 12755534123 025076 0ustar00sergiosergio000000 000000 /* RetroArch - A frontend for libretro. * Copyright (C) 2010-2014 - Hans-Kristian Arntzen * * RetroArch is free software: you can redistribute it and/or modify it under the terms * of the GNU General Public License as published by the Free Software Found- * ation, either version 3 of the License, or (at your option) any later version. * * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along with RetroArch. * If not, see . */ #if defined(__ARM_NEON__) #ifndef __MACH__ .arm #endif .align 4 .globl convert_s16_float_asm .globl _convert_s16_float_asm # convert_s16_float_asm(float *out, const int16_t *in, size_t samples, const float *gain) convert_s16_float_asm: _convert_s16_float_asm: # Hacky way to get a constant of 2^-15. # Might be faster to just load a constant from memory. # It's just done once however ... vmov.f32 q8, #0.25 vmul.f32 q8, q8, q8 vmul.f32 q8, q8, q8 vmul.f32 q8, q8, q8 vadd.f32 q8, q8, q8 # Apply gain vld1.f32 {d6[0]}, [r3] vmul.f32 q8, q8, d6[0] 1: # Preload here? vld1.s16 {q0}, [r1]! # Widen to 32-bit vmovl.s16 q1, d0 vmovl.s16 q2, d1 # Convert to float vcvt.f32.s32 q1, q1 vcvt.f32.s32 q2, q2 vmul.f32 q1, q1, q8 vmul.f32 q2, q2, q8 vst1.f32 {q1-q2}, [r0]! # Guaranteed to get samples in multiples of 8. subs r2, r2, #8 bne 1b bx lr #endif desmume/src/libretro-common/include/glsym/000700 001750 001750 00000000000 12756420131 022003 5ustar00sergiosergio000000 000000 desmume/src/libretro-common/include/retro_common_api.h000664 001750 001750 00000007214 12755534123 024403 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2016 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (retro_common_api.h). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef _LIBRETRO_COMMON_RETRO_COMMON_API_H #define _LIBRETRO_COMMON_RETRO_COMMON_API_H /* This file is designed to normalize the libretro-common compiling environment for public API headers. This should be leaner than a normal compiling environment, since it gets #included into other project's sources. */ /* ------------------------------------ */ /* Ordinarily we want to put #ifdef __cplusplus extern "C" in C library headers to enable them to get used by c++ sources. However, we want to support building this library as C++ as well, so a special technique is called for. */ #define RETRO_BEGIN_DECLS #define RETRO_END_DECLS #ifdef __cplusplus #ifdef CXX_BUILD /* build wants everything to be built as c++, so no extern "C" */ #else #undef RETRO_BEGIN_DECLS #undef RETRO_END_DECLS #define RETRO_BEGIN_DECLS extern "C" { #define RETRO_END_DECLS } #endif #else /* header is included by a C source file, so no extern "C" */ #endif /* IMO, this non-standard ssize_t should not be used. However, it's a good example of how to handle something like this. */ #ifdef _MSC_VER #ifndef HAVE_SSIZE_T #define HAVE_SSIZE_T #if defined(_WIN64) typedef __int64 ssize_t; #elif defined(_WIN32) typedef int ssize_t; #endif #endif #elif defined(__MACH__) #include #endif #ifdef _WIN32 #define STRING_REP_INT64 "%I64u" #define STRING_REP_UINT64 "%I64u" #define STRING_REP_ULONG "%Iu" #elif defined(__STDC_VERSION__) && __STDC_VERSION__>=199901L #define STRING_REP_INT64 "%llu" #define STRING_REP_UINT64 "%llu" #define STRING_REP_ULONG "%zu" #else #define STRING_REP_INT64 "%llu" #define STRING_REP_UINT64 "%llu" #define STRING_REP_ULONG "%lu" #endif /* I would like to see retro_inline.h moved in here; possibly boolean too. rationale: these are used in public APIs, and it is easier to find problems and write code that works the first time portably when theyre included uniformly than to do the analysis from scratch each time you think you need it, for each feature. Moreover it helps force you to make hard decisions: if you EVER bring in boolean.h, then you should pay the price everywhere, so you can see how much grief it will cause. Of course, another school of thought is that you should do as little damage as possible in as few places as possible... */ /* _LIBRETRO_COMMON_RETRO_COMMON_API_H */ #endif desmume/src/utils/AsmJit/core/podvector.h000664 001750 001750 00000012715 12755534123 021602 0ustar00sergiosergio000000 000000 // [AsmJit] // Complete JIT Assembler for C++ Language. // // [License] // Zlib - See COPYING file in this package. // [Guard] #ifndef _ASMJIT_CORE_PODVECTOR_H #define _ASMJIT_CORE_PODVECTOR_H // [Dependencies - AsmJit] #include "../core/assert.h" #include "../core/defs.h" namespace AsmJit { //! @addtogroup AsmJit_Core //! @{ // ============================================================================ // [AsmJit::PodVector] // ============================================================================ //! @brief Template used to store and manage array of POD data. //! //! This template has these adventages over other vector<> templates: //! - Non-copyable (designed to be non-copyable, we want it) //! - No copy-on-write (some implementations of stl can use it) //! - Optimized for working only with POD types //! - Uses ASMJIT_... memory management macros template struct PodVector { ASMJIT_NO_COPY(PodVector) // -------------------------------------------------------------------------- // [Construction / Destruction] // -------------------------------------------------------------------------- //! @brief Create new instance of PodVector template. Data will not //! be allocated (will be NULL). inline PodVector() : _data(NULL), _length(0), _capacity(0) { } //! @brief Destroy PodVector and free all data. inline ~PodVector() { if (_data != NULL) ASMJIT_FREE(_data); } // -------------------------------------------------------------------------- // [Data] // -------------------------------------------------------------------------- //! @brief Get data. inline T* getData() { return _data; } //! @overload inline const T* getData() const { return _data; } //! @brief Get length. inline size_t getLength() const { return _length; } //! @brief Get capacity. inline size_t getCapacity() const { return _capacity; } // -------------------------------------------------------------------------- // [Manipulation] // -------------------------------------------------------------------------- //! @brief Clear vector data, but not free internal buffer. void clear() { _length = 0; } //! @brief Clear vector data and free internal buffer. void reset() { if (_data != NULL) { ASMJIT_FREE(_data); _data = 0; _length = 0; _capacity = 0; } } //! @brief Prepend @a item to vector. bool prepend(const T& item) { if (_length == _capacity && !_grow()) return false; memmove(_data + 1, _data, sizeof(T) * _length); memcpy(_data, &item, sizeof(T)); _length++; return true; } //! @brief Insert an @a item at the @a index. bool insert(size_t index, const T& item) { ASMJIT_ASSERT(index <= _length); if (_length == _capacity && !_grow()) return false; T* dst = _data + index; memmove(dst + 1, dst, _length - index); memcpy(dst, &item, sizeof(T)); _length++; return true; } //! @brief Append @a item to vector. bool append(const T& item) { if (_length == _capacity && !_grow()) return false; memcpy(_data + _length, &item, sizeof(T)); _length++; return true; } //! @brief Get index of @a val or kInvalidSize if not found. size_t indexOf(const T& val) const { size_t i = 0, len = _length; for (i = 0; i < len; i++) { if (_data[i] == val) return i; } return kInvalidSize; } //! @brief Remove element at index @a i. void removeAt(size_t i) { ASMJIT_ASSERT(i < _length); T* dst = _data + i; _length--; memmove(dst, dst + 1, _length - i); } //! @brief Swap this pod-vector with @a other. void swap(PodVector& other) { T* _tmp_data = _data; size_t _tmp_length = _length; size_t _tmp_capacity = _capacity; _data = other._data; _length = other._length; _capacity = other._capacity; other._data = _tmp_data; other._length = _tmp_length; other._capacity = _tmp_capacity; } //! @brief Get item at position @a i. inline T& operator[](size_t i) { ASMJIT_ASSERT(i < _length); return _data[i]; } //! @brief Get item at position @a i. inline const T& operator[](size_t i) const { ASMJIT_ASSERT(i < _length); return _data[i]; } //! @brief Append the item and return address so it can be initialized. T* newItem() { if (_length == _capacity && !_grow()) return NULL; return _data + (_length++); } // -------------------------------------------------------------------------- // [Private] // -------------------------------------------------------------------------- //! @brief Called to grow internal array. bool _grow() { return _realloc(_capacity < 16 ? 16 : _capacity * 2); } //! @brief Realloc internal array to fit @a to items. bool _realloc(size_t to) { ASMJIT_ASSERT(to >= _length); T* p = reinterpret_cast(_data ? ASMJIT_REALLOC(_data, to * sizeof(T)) : ASMJIT_MALLOC(to * sizeof(T))); if (p == NULL) return false; _data = p; _capacity = to; return true; } // -------------------------------------------------------------------------- // [Members] // -------------------------------------------------------------------------- //! @brief Items data. T* _data; //! @brief Length of buffer (count of items in array). size_t _length; //! @brief Capacity of buffer (maximum items that can fit to current array). size_t _capacity; }; //! @} } // AsmJit namespace #endif // _ASMJIT_CORE_PODVECTOR_H desmume/src/libretro-common/include/net/net_socket.h000664 001750 001750 00000005416 12755534123 023775 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2016 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (net_socket.h). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef _LIBRETRO_SDK_NET_SOCKET_H #define _LIBRETRO_SDK_NET_SOCKET_H #include #include #include #include RETRO_BEGIN_DECLS enum socket_domain { SOCKET_DOMAIN_INET = 0 }; enum socket_type { SOCKET_TYPE_DATAGRAM = 0, SOCKET_TYPE_STREAM, SOCKET_TYPE_SEQPACKET }; enum socket_protocol { SOCKET_PROTOCOL_NONE = 0, SOCKET_PROTOCOL_TCP, SOCKET_PROTOCOL_UDP }; typedef struct socket_target { unsigned port; const char *server; enum socket_domain domain; enum socket_protocol prot; } socket_target_t; int socket_init(void **address, uint16_t port, const char *server, enum socket_type type); int socket_close(int fd); bool socket_nonblock(int fd); int socket_select(int nfds, fd_set *readfs, fd_set *writefds, fd_set *errorfds, struct timeval *timeout); int socket_send_all_blocking(int fd, const void *data_, size_t size, bool no_signal); int socket_receive_all_blocking(int fd, void *data_, size_t size); ssize_t socket_receive_all_nonblocking(int fd, bool *error, void *data_, size_t size); bool socket_bind(int fd, void *data); int socket_connect(int fd, void *data, bool timeout_enable); int socket_create( const char *name, enum socket_domain domain_type, enum socket_type socket_type, enum socket_protocol protocol_type); void socket_set_target(void *data, socket_target_t *in_addr); RETRO_END_DECLS #endif desmume/src/libretro-common/rthreads/rthreads.c000664 001750 001750 00000025661 12755534123 023055 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2016 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (rthreads.c). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifdef __unix__ #define _POSIX_C_SOURCE 199309 #endif #include #include #include /* with RETRO_WIN32_USE_PTHREADS, pthreads can be used even on win32. Maybe only supported in MSVC>=2005 */ #if defined(_WIN32) && !defined(RETRO_WIN32_USE_PTHREADS) #define USE_WIN32_THREADS #ifdef _XBOX #include #else #define WIN32_LEAN_AND_MEAN #include #endif #elif defined(GEKKO) #include "gx_pthread.h" #elif defined(PSP) || defined(VITA) #include "psp_pthread.h" #elif defined(__CELLOS_LV2__) #include #include #else #include #include #endif #if defined(VITA) #include #endif #ifdef __MACH__ #include #include #endif struct thread_data { void (*func)(void*); void *userdata; }; struct sthread { #ifdef USE_WIN32_THREADS HANDLE thread; #else pthread_t id; #endif }; struct slock { #ifdef USE_WIN32_THREADS HANDLE lock; #else pthread_mutex_t lock; #endif }; struct scond { #ifdef USE_WIN32_THREADS HANDLE event; #else pthread_cond_t cond; #endif }; #ifdef USE_WIN32_THREADS static DWORD CALLBACK thread_wrap(void *data_) #else static void *thread_wrap(void *data_) #endif { struct thread_data *data = (struct thread_data*)data_; if (!data) return 0; data->func(data->userdata); free(data); return 0; } /** * sthread_create: * @start_routine : thread entry callback function * @userdata : pointer to userdata that will be made * available in thread entry callback function * * Create a new thread. * * Returns: pointer to new thread if successful, otherwise NULL. */ sthread_t *sthread_create(void (*thread_func)(void*), void *userdata) { bool thread_created = false; struct thread_data *data = NULL; sthread_t *thread = (sthread_t*)calloc(1, sizeof(*thread)); if (!thread) return NULL; data = (struct thread_data*)calloc(1, sizeof(*data)); if (!data) goto error; data->func = thread_func; data->userdata = userdata; #ifdef USE_WIN32_THREADS thread->thread = CreateThread(NULL, 0, thread_wrap, data, 0, NULL); thread_created = !!thread->thread; #else thread_created = pthread_create(&thread->id, NULL, thread_wrap, data) == 0; #endif if (!thread_created) goto error; return thread; error: if (data) free(data); free(thread); return NULL; } /** * sthread_detach: * @thread : pointer to thread object * * Detach a thread. When a detached thread terminates, its * resource sare automatically released back to the system * without the need for another thread to join with the * terminated thread. * * Returns: 0 on success, otherwise it returns a non-zero error number. */ int sthread_detach(sthread_t *thread) { #ifdef USE_WIN32_THREADS CloseHandle(thread->thread); free(thread); return 0; #else return pthread_detach(thread->id); #endif } /** * sthread_join: * @thread : pointer to thread object * * Join with a terminated thread. Waits for the thread specified by * @thread to terminate. If that thread has already terminated, then * it will return immediately. The thread specified by @thread must * be joinable. * * Returns: 0 on success, otherwise it returns a non-zero error number. */ void sthread_join(sthread_t *thread) { #ifdef USE_WIN32_THREADS WaitForSingleObject(thread->thread, INFINITE); CloseHandle(thread->thread); #else pthread_join(thread->id, NULL); #endif free(thread); } /** * sthread_isself: * @thread : pointer to thread object * * Join with a terminated thread. Waits for the thread specified by * @thread to terminate. If that thread has already terminated, then * it will return immediately. The thread specified by @thread must * be joinable. * * Returns: true (1) if calling thread is the specified thread */ bool sthread_isself(sthread_t *thread) { #ifdef USE_WIN32_THREADS return GetCurrentThread() == thread->thread; #else return pthread_equal(pthread_self(),thread->id); #endif } /** * slock_new: * * Create and initialize a new mutex. Must be manually * freed. * * Returns: pointer to a new mutex if successful, otherwise NULL. **/ slock_t *slock_new(void) { slock_t *lock = (slock_t*)calloc(1, sizeof(*lock)); if (!lock) return NULL; #ifdef USE_WIN32_THREADS lock->lock = CreateMutex(NULL, FALSE, NULL); if (!lock->lock) goto error; #else if ((pthread_mutex_init(&lock->lock, NULL) < 0)) goto error; #endif return lock; error: slock_free(lock); return NULL; } /** * slock_free: * @lock : pointer to mutex object * * Frees a mutex. **/ void slock_free(slock_t *lock) { if (!lock) return; #ifdef USE_WIN32_THREADS CloseHandle(lock->lock); #else pthread_mutex_destroy(&lock->lock); #endif free(lock); } /** * slock_lock: * @lock : pointer to mutex object * * Locks a mutex. If a mutex is already locked by * another thread, the calling thread shall block until * the mutex becomes available. **/ void slock_lock(slock_t *lock) { #ifdef USE_WIN32_THREADS WaitForSingleObject(lock->lock, INFINITE); #else pthread_mutex_lock(&lock->lock); #endif } /** * slock_unlock: * @lock : pointer to mutex object * * Unlocks a mutex. **/ void slock_unlock(slock_t *lock) { #ifdef USE_WIN32_THREADS ReleaseMutex(lock->lock); #else pthread_mutex_unlock(&lock->lock); #endif } /** * scond_new: * * Creates and initializes a condition variable. Must * be manually freed. * * Returns: pointer to new condition variable on success, * otherwise NULL. **/ scond_t *scond_new(void) { bool event_created = false; scond_t *cond = (scond_t*)calloc(1, sizeof(*cond)); if (!cond) return NULL; #ifdef USE_WIN32_THREADS cond->event = CreateEvent(NULL, FALSE, FALSE, NULL); event_created = !!cond->event; #else event_created = (pthread_cond_init(&cond->cond, NULL) == 0); #endif if (!event_created) goto error; return cond; error: free(cond); return NULL; } /** * scond_free: * @cond : pointer to condition variable object * * Frees a condition variable. **/ void scond_free(scond_t *cond) { if (!cond) return; #ifdef USE_WIN32_THREADS CloseHandle(cond->event); #else pthread_cond_destroy(&cond->cond); #endif free(cond); } /** * scond_wait: * @cond : pointer to condition variable object * @lock : pointer to mutex object * * Block on a condition variable (i.e. wait on a condition). **/ void scond_wait(scond_t *cond, slock_t *lock) { #ifdef USE_WIN32_THREADS WaitForSingleObject(cond->event, 0); SignalObjectAndWait(lock->lock, cond->event, INFINITE, FALSE); slock_lock(lock); #else pthread_cond_wait(&cond->cond, &lock->lock); #endif } /** * scond_broadcast: * @cond : pointer to condition variable object * * Broadcast a condition. Unblocks all threads currently blocked * on the specified condition variable @cond. **/ int scond_broadcast(scond_t *cond) { #ifdef USE_WIN32_THREADS /* FIXME _- check how this function should differ * from scond_signal implementation. */ SetEvent(cond->event); return 0; #else return pthread_cond_broadcast(&cond->cond); #endif } /** * scond_signal: * @cond : pointer to condition variable object * * Signal a condition. Unblocks at least one of the threads currently blocked * on the specified condition variable @cond. **/ void scond_signal(scond_t *cond) { #ifdef USE_WIN32_THREADS SetEvent(cond->event); #else pthread_cond_signal(&cond->cond); #endif } /** * scond_wait_timeout: * @cond : pointer to condition variable object * @lock : pointer to mutex object * @timeout_us : timeout (in microseconds) * * Try to block on a condition variable (i.e. wait on a condition) until * @timeout_us elapses. * * Returns: false (0) if timeout elapses before condition variable is * signaled or broadcast, otherwise true (1). **/ bool scond_wait_timeout(scond_t *cond, slock_t *lock, int64_t timeout_us) { #ifdef USE_WIN32_THREADS DWORD ret; WaitForSingleObject(cond->event, 0); ret = SignalObjectAndWait(lock->lock, cond->event, (DWORD)(timeout_us) / 1000, FALSE); slock_lock(lock); return ret == WAIT_OBJECT_0; #else int ret; int64_t seconds, remainder; struct timespec now = {0}; #ifdef __MACH__ /* OSX doesn't have clock_gettime. */ clock_serv_t cclock; mach_timespec_t mts; host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock); clock_get_time(cclock, &mts); mach_port_deallocate(mach_task_self(), cclock); now.tv_sec = mts.tv_sec; now.tv_nsec = mts.tv_nsec; #elif defined(__CELLOS_LV2__) sys_time_sec_t s; sys_time_nsec_t n; sys_time_get_current_time(&s, &n); now.tv_sec = s; now.tv_nsec = n; #elif defined(__mips__) || defined(VITA) struct timeval tm; gettimeofday(&tm, NULL); now.tv_sec = tm.tv_sec; now.tv_nsec = tm.tv_usec * 1000; #elif defined(RETRO_WIN32_USE_PTHREADS) _ftime64_s(&now); #elif !defined(GEKKO) /* timeout on libogc is duration, not end time. */ clock_gettime(CLOCK_REALTIME, &now); #endif seconds = timeout_us / INT64_C(1000000); remainder = timeout_us % INT64_C(1000000); now.tv_sec += seconds; now.tv_nsec += remainder * INT64_C(1000); ret = pthread_cond_timedwait(&cond->cond, &lock->lock, &now); return (ret == 0); #endif } desmume/src/libretro-common/include/libretro_vulkan.h000664 001750 001750 00000043744 12755534123 024261 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2016 The RetroArch team * * --------------------------------------------------------------------------------------------- * The following license statement only applies to this libretro API header (libretro_vulkan.h) * --------------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef LIBRETRO_VULKAN_H__ #define LIBRETRO_VULKAN_H__ #include #include #define RETRO_HW_RENDER_INTERFACE_VULKAN_VERSION 5 #define RETRO_HW_RENDER_CONTEXT_NEGOTIATION_INTERFACE_VULKAN_VERSION 1 struct retro_vulkan_image { VkImageView image_view; VkImageLayout image_layout; VkImageViewCreateInfo create_info; }; typedef void (*retro_vulkan_set_image_t)(void *handle, const struct retro_vulkan_image *image, uint32_t num_semaphores, const VkSemaphore *semaphores, uint32_t src_queue_family); typedef uint32_t (*retro_vulkan_get_sync_index_t)(void *handle); typedef uint32_t (*retro_vulkan_get_sync_index_mask_t)(void *handle); typedef void (*retro_vulkan_set_command_buffers_t)(void *handle, uint32_t num_cmd, const VkCommandBuffer *cmd); typedef void (*retro_vulkan_wait_sync_index_t)(void *handle); typedef void (*retro_vulkan_lock_queue_t)(void *handle); typedef void (*retro_vulkan_unlock_queue_t)(void *handle); typedef void (*retro_vulkan_set_signal_semaphore_t)(void *handle, VkSemaphore semaphore); typedef const VkApplicationInfo *(*retro_vulkan_get_application_info_t)(void); struct retro_vulkan_context { VkPhysicalDevice gpu; VkDevice device; VkQueue queue; uint32_t queue_family_index; VkQueue presentation_queue; uint32_t presentation_queue_family_index; }; typedef bool (*retro_vulkan_create_device_t)( struct retro_vulkan_context *context, VkInstance instance, VkPhysicalDevice gpu, VkSurfaceKHR surface, PFN_vkGetInstanceProcAddr get_instance_proc_addr, const char **required_device_extensions, unsigned num_required_device_extensions, const char **required_device_layers, unsigned num_required_device_layers, const VkPhysicalDeviceFeatures *required_features); typedef void (*retro_vulkan_destroy_device_t)(void); /* Note on thread safety: * The Vulkan API is heavily designed around multi-threading, and * the libretro interface for it should also be threading friendly. * A core should be able to build command buffers and submit * command buffers to the GPU from any thread. */ struct retro_hw_render_context_negotiation_interface_vulkan { /* Must be set to RETRO_HW_RENDER_CONTEXT_NEGOTIATION_INTERFACE_VULKAN. */ enum retro_hw_render_context_negotiation_interface_type interface_type; /* Must be set to RETRO_HW_RENDER_CONTEXT_NEGOTIATION_INTERFACE_VULKAN_VERSION. */ unsigned interface_version; /* If non-NULL, returns a VkApplicationInfo struct that the frontend can use instead of * its "default" application info. */ retro_vulkan_get_application_info_t get_application_info; /* If non-NULL, the libretro core will choose one or more physical devices, * create one or more logical devices and create one or more queues. * The core must prepare a designated PhysicalDevice, Device, Queue and queue family index * which the frontend will use for its internal operation. * * If gpu is not VK_NULL_HANDLE, the physical device provided to the frontend must be this PhysicalDevice. * The core is still free to use other physical devices. * * The frontend will request certain extensions and layers for a device which is created. * The core must ensure that the queue and queue_family_index support GRAPHICS and COMPUTE. * * If surface is not VK_NULL_HANDLE, the core must consider presentation when creating the queues. * If presentation to "surface" is supported on the queue, presentation_queue must be equal to queue. * If not, a second queue must be provided in presentation_queue and presentation_queue_index. * If surface is not VK_NULL_HANDLE, the instance from frontend will have been created with supported for * VK_KHR_surface extension. * * The core is free to set its own queue priorities. * Device provided to frontend is owned by the frontend, but any additional device resources must be freed by core * in destroy_device callback. * * If this function returns true, a PhysicalDevice, Device and Queues are initialized. * If false, none of the above have been initialized and the frontend will attempt * to fallback to "default" device creation, as if this function was never called. */ retro_vulkan_create_device_t create_device; /* If non-NULL, this callback is called similar to context_destroy for HW_RENDER_INTERFACE. * However, it will be called even if context_reset was not called. * This can happen if the context never succeeds in being created. * destroy_device will always be called before the VkInstance * of the frontend is destroyed if create_device was called successfully so that the core has a chance of * tearing down its own device resources. * * Only auxillary resources should be freed here, i.e. resources which are not part of retro_vulkan_context. */ retro_vulkan_destroy_device_t destroy_device; }; struct retro_hw_render_interface_vulkan { /* Must be set to RETRO_HW_RENDER_INTERFACE_VULKAN. */ enum retro_hw_render_interface_type interface_type; /* Must be set to RETRO_HW_RENDER_INTERFACE_VULKAN_VERSION. */ unsigned interface_version; /* Opaque handle to the Vulkan backend in the frontend * which must be passed along to all function pointers * in this interface. * * The rationale for including a handle here (which libretro v1 * doesn't currently do in general) is: * * - Vulkan cores should be able to be freely threaded without lots of fuzz. * This would break frontends which currently rely on TLS * to deal with multiple cores loaded at the same time. * - Fixing this in general is TODO for an eventual libretro v2. */ void *handle; /* The Vulkan instance the context is using. */ VkInstance instance; /* The physical device used. */ VkPhysicalDevice gpu; /* The logical device used. */ VkDevice device; /* Allows a core to fetch all its needed symbols without having to link * against the loader itself. */ PFN_vkGetDeviceProcAddr get_device_proc_addr; PFN_vkGetInstanceProcAddr get_instance_proc_addr; /* The queue the core must use to submit data. * This queue and index must remain constant throughout the lifetime * of the context. * * This queue will be the queue that supports graphics and compute * if the device supports compute. */ VkQueue queue; unsigned queue_index; /* Before calling retro_video_refresh_t with RETRO_HW_FRAME_BUFFER_VALID, * set which image to use for this frame. * * If num_semaphores is non-zero, the frontend will wait for the * semaphores provided to be signaled before using the results further * in the pipeline. * * Semaphores provided by a single call to set_image will only be * waited for once (waiting for a semaphore resets it). * E.g. set_image, video_refresh, and then another * video_refresh without set_image, * but same image will only wait for semaphores once. * * For this reason, ownership transfer will only occur if semaphores * are waited on for a particular frame in the frontend. * * Using semaphores is optional for synchronization purposes, * but if not using * semaphores, an image memory barrier in vkCmdPipelineBarrier * should be used in the graphics_queue. * Example: * * vkCmdPipelineBarrier(cmd, * srcStageMask = VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, * dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, * image_memory_barrier = { * srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, * dstAccessMask = VK_ACCESS_SHADER_READ_BIT, * }); * * The use of pipeline barriers instead of semaphores is encouraged * as it is simpler and more fine-grained. A layout transition * must generally happen anyways which requires a * pipeline barrier. * * The image passed to set_image must have imageUsage flags set to at least * VK_IMAGE_USAGE_TRANSFER_SRC_BIT and VK_IMAGE_USAGE_SAMPLED_BIT. * The core will naturally want to use flags such as * VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT and/or * VK_IMAGE_USAGE_TRANSFER_DST_BIT depending * on how the final image is created. * * The image must also have been created with MUTABLE_FORMAT bit set if * 8-bit formats are used, so that the frontend can reinterpret sRGB * formats as it sees fit. * * Images passed to set_image should be created with TILING_OPTIMAL. * The image layout should be transitioned to either * VK_IMAGE_LAYOUT_GENERIC or VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL. * The actual image layout used must be set in image_layout. * * The image must be a 2D texture which may or not be layered * and/or mipmapped. * * The image must be suitable for linear sampling. * While the image_view is typically the only field used, * the frontend may want to reinterpret the texture as sRGB vs. * non-sRGB for example so the VkImageViewCreateInfo used to * create the image view must also be passed in. * * The data in the pointer to the image struct will not be copied * as the pNext field in create_info cannot be reliably deep-copied. * The image pointer passed to set_image must be valid until * retro_video_refresh_t has returned. * * If frame duping is used when passing NULL to retro_video_refresh_t, * the frontend is free to either use the latest image passed to * set_image or reuse the older pointer passed to set_image the * frame RETRO_HW_FRAME_BUFFER_VALID was last used. * * Essentially, the lifetime of the pointer passed to * retro_video_refresh_t should be extended if frame duping is used * so that the frontend can reuse the older pointer. * * The image itself however, must not be touched by the core until * wait_sync_index has been completed later. The frontend may perform * layout transitions on the image, so even read-only access is not defined. * The exception to read-only rule is if GENERAL layout is used for the image. * In this case, the frontend is not allowed to perform any layout transitions, * so concurrent reads from core and frontend are allowed. * * If frame duping is used, or if set_command_buffers is used, * the frontend will not wait for any semaphores. * * The src_queue_family is used to specify which queue family * the image is currently owned by. If using multiple queue families * (e.g. async compute), the frontend will need to acquire ownership of the * image before rendering with it and release the image afterwards. * * If src_queue_family is equal to the queue family (queue_index), * no ownership transfer will occur. * Similarly, if src_queue_family is VK_QUEUE_FAMILY_IGNORED, * no ownership transfer will occur. * * The frontend will always release ownership back to src_queue_family. * Waiting for frontend to complete with wait_sync_index() ensures that * the frontend has released ownership back to the application. * Note that in Vulkan, transfering ownership is a two-part process. * * Example frame: * - core releases ownership from src_queue_index to queue_index with VkImageMemoryBarrier. * - core calls set_image with src_queue_index. * - Frontend will acquire the image with src_queue_index -> queue_index as well, completing the ownership transfer. * - Frontend renders the frame. * - Frontend releases ownership with queue_index -> src_queue_index. * - Next time image is used, core must acquire ownership from queue_index ... * * Since the frontend releases ownership, we cannot necessarily dupe the frame because * the core needs to make the roundtrip of ownership transfer. */ retro_vulkan_set_image_t set_image; /* Get the current sync index for this frame which is obtained in * frontend by calling e.g. vkAcquireNextImageKHR before calling * retro_run(). * * This index will correspond to which swapchain buffer is currently * the active one. * * Knowing this index is very useful for maintaining safe asynchronous CPU * and GPU operation without stalling. * * The common pattern for synchronization is to receive fences when * submitting command buffers to Vulkan (vkQueueSubmit) and add this fence * to a list of fences for frame number get_sync_index(). * * Next time we receive the same get_sync_index(), we can wait for the * fences from before, which will usually return immediately as the * frontend will generally also avoid letting the GPU run ahead too much. * * After the fence has signaled, we know that the GPU has completed all * GPU work related to work submitted in the frame we last saw get_sync_index(). * * This means we can safely reuse or free resources allocated in this frame. * * In theory, even if we wait for the fences correctly, it is not technically * safe to write to the image we earlier passed to the frontend since we're * not waiting for the frontend GPU jobs to complete. * * The frontend will guarantee that the appropriate pipeline barrier * in graphics_queue has been used such that * VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT cannot * start until the frontend is done with the image. */ retro_vulkan_get_sync_index_t get_sync_index; /* Returns a bitmask of how many swapchain images we currently have * in the frontend. * * If bit #N is set in the return value, get_sync_index can return N. * Knowing this value is useful for preallocating per-frame management * structures ahead of time. * * While this value will typically remain constant throughout the * applications lifecycle, it may for example change if the frontend * suddently changes fullscreen state and/or latency. * * If this value ever changes, it is safe to assume that the device * is completely idle and all synchronization objects can be deleted * right away as desired. */ retro_vulkan_get_sync_index_mask_t get_sync_index_mask; /* Instead of submitting the command buffer to the queue first, the core * can pass along its command buffer to the frontend, and the frontend * will submit the command buffer together with the frontends command buffers. * * This has the advantage that the overhead of vkQueueSubmit can be * amortized into a single call. For this mode, semaphores in set_image * will be ignored, so vkCmdPipelineBarrier must be used to synchronize * the core and frontend. * * The command buffers in set_command_buffers are only executed once, * even if frame duping is used. * * If frame duping is used, set_image should be used for the frames * which should be duped instead. * * Command buffers passed to the frontend with set_command_buffers * must not actually be submitted to the GPU until retro_video_refresh_t * is called. * * The frontend must submit the command buffer before submitting any * other command buffers provided by set_command_buffers. */ retro_vulkan_set_command_buffers_t set_command_buffers; /* Waits on CPU for device activity for the current sync index to complete. * This is useful since the core will not have a relevant fence to sync with * when the frontend is submitting the command buffers. */ retro_vulkan_wait_sync_index_t wait_sync_index; /* If the core submits command buffers itself to any of the queues provided * in this interface, the core must lock and unlock the frontend from * racing on the VkQueue. * * Queue submission can happen on any thread. * Even if queue submission happens on the same thread as retro_run(), * the lock/unlock functions must still be called. * * NOTE: Queue submissions are heavy-weight. */ retro_vulkan_lock_queue_t lock_queue; retro_vulkan_unlock_queue_t unlock_queue; /* Sets a semaphore which is signaled when the image in set_image can safely be reused. * The semaphore is consumed next call to retro_video_refresh_t. * The semaphore will be signalled even for duped frames. * The semaphore will be signalled only once, so set_signal_semaphore should be called every frame. * The semaphore may be VK_NULL_HANDLE, which disables semaphore signalling for next call to retro_video_refresh_t. * * This is mostly useful to support use cases where you're rendering to a single image that * is recycled in a ping-pong fashion with the frontend to save memory (but potentially less throughput). */ retro_vulkan_set_signal_semaphore_t set_signal_semaphore; }; #endif desmume/dsv.txt000664 001750 001750 00000003400 12755534123 014702 0ustar00sergiosergio000000 000000 The desmume save file format is merely a raw save file with a FOOTER. This was chosen in order to maximize compatibility with other emulators, which tend load the savefile as-is and let the game read out of whatever range it is expecting. To assist with this, before writing the save file, desmume will pad the raw save file out to the next highest known length. Note that this may sometimes be incorrect if the savefile hasnt been written through to the end during initialization. This could cause other emulators to fail to recognize the save file. Additionally, the footer makes it easier to analyze save files, because the game's data will be at the correct addresses starting at offset 0x0000. The footer format can be identified by locating the 16Byte ascii string "|-DESMUME SAVE-|" at the end of the file. This corresponds with the following save structure: struct Footer { u32 actually_written_size; u32 padded_size; u32 save_type; //(not currently used) u32 address_size; //address bus size u32 save_size; //size parameter of the save type (not currently used) u32 version_number; //should be 0 char cookie[16]; }; note that padded_size should be where you see the end of the raw save data and the beginning of desmume-specific information, including some junk before the actual footer. actually_written_size is the highest address (plus one) written to by the game. The new desmume savefile system tries to make as few decisions as possible, which is the reason for the behavior of actually_written_size and the disuse of save_type and save_size. If few decisions are made, then few mistakes can be made. That is the idea, anyway. We'll make decisions later if we need to. save_type and save_size are reserved in case we do. desmume/src/debug.cpp000664 001750 001750 00000030437 12755534123 015740 0ustar00sergiosergio000000 000000 /* Copyright (C) 2006 Guillaume Duhamel Copyright (C) 2006-2011 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the this software. If not, see . */ #include "debug.h" #include #include #include #include "MMU.h" #include "armcpu.h" #include "instructions.h" #include "cp15.h" #include "NDSSystem.h" #include "utils/xstring.h" #include "movie.h" armcpu_t* TDebugEventData::cpu() { return procnum==0?&NDS_ARM9:&NDS_ARM7; } TDebugEventData DebugEventData; u32 debugFlag; //DEBUG CONFIGURATION const bool debug_acl = false; const bool debug_cacheMiss = false; static bool acl_check_access(u32 adr, u32 access) { //non-user modes get separate access handling, so check that here if(NDS_ARM9.CPSR.bits.mode != USR) access |= 1; if (cp15.isAccessAllowed(adr,access)==FALSE) { HandleDebugEvent(DEBUG_EVENT_ACL_EXCEPTION); } return true; } void HandleDebugEvent_ACL_Exception() { printf("ACL EXCEPTION!\n"); if(DebugEventData.memAccessType == MMU_AT_CODE) armcpu_exception(DebugEventData.cpu(),EXCEPTION_PREFETCH_ABORT); else if(DebugEventData.memAccessType == MMU_AT_DATA) armcpu_exception(DebugEventData.cpu(),EXCEPTION_DATA_ABORT); } static bool CheckRange(u32 adr, u32 min, u32 len) { return (adr>=min && adr static bool debugStatsSort(int num1, int num2) { if(which==0) { if(combinedHits[proc].arm[num2] == combinedHits[proc].arm[num1]) return false; if(combinedHits[proc].arm[num1] == 0xFFFFFFFF) return false; if(combinedHits[proc].arm[num2] == 0xFFFFFFFF) return true; return combinedHits[proc].arm[num2] < combinedHits[proc].arm[num1]; } else { if(combinedHits[proc].thumb[num2] == combinedHits[proc].thumb[num1]) return false; if(combinedHits[proc].thumb[num1] == 0xFFFFFFFF) return false; if(combinedHits[proc].thumb[num2] == 0xFFFFFFFF) return true; return combinedHits[proc].thumb[num2] < combinedHits[proc].thumb[num1]; } } void DebugStatistics::print() { //consolidate opcodes with the same names for(int i=0;i<2;i++) { combinedHits[i] = DEBUG_statistics.instructionHits[i]; for(int j=0;j<4096;j++) { if(combinedHits[i].arm[j] == 0xFFFFFFFF) continue; std::string name = arm_instruction_names[j]; for(int k=j+1;k<4096;k++) { if(combinedHits[i].arm[k] == 0xFFFFFFFF) continue; if(name == arm_instruction_names[k]) { //printf("combining %s with %d and %d\n",name.c_str(),combinedHits[i].arm[j],combinedHits[i].arm[k]); combinedHits[i].arm[j] += combinedHits[i].arm[k]; combinedHits[i].arm[k] = 0xFFFFFFFF; } } } for(int j=0;j<1024;j++) { if(combinedHits[i].thumb[j] == 0xFFFFFFFF) continue; std::string name = thumb_instruction_names[j]; for(int k=j+1;k<1024;k++) { if(combinedHits[i].thumb[k] == 0xFFFFFFFF) continue; if(name == thumb_instruction_names[k]) { //printf("combining %s with %d and %d\n",name.c_str(),combinedHits[i].arm[j],combinedHits[i].arm[k]); combinedHits[i].thumb[j] += combinedHits[i].thumb[k]; combinedHits[i].thumb[k] = 0xFFFFFFFF; } } } } InstructionHits sorts[2]; for(int i=0;i<2;i++) { for(int j=0;j<4096;j++) sorts[i].arm[j] = j; for(int j=0;j<1024;j++) sorts[i].thumb[j] = j; } std::sort(sorts[0].arm, sorts[0].arm+4096, debugStatsSort<0,0>); std::sort(sorts[0].thumb, sorts[0].thumb+1024, debugStatsSort<0,1>); std::sort(sorts[1].arm, sorts[1].arm+4096, debugStatsSort<1,0>); std::sort(sorts[1].thumb, sorts[1].thumb+1024, debugStatsSort<1,1>); for(int i=0;i<2;i++) { printf("Top arm instructions for ARM%d:\n",7+i*2); for(int j=0;j<10;j++) { int val = sorts[i].arm[j]; printf("%08d: %s\n", combinedHits[i].arm[val], arm_instruction_names[val]); } printf("Top thumb instructions for ARM%d:\n",7+i*2); for(int j=0;j<10;j++) { int val = sorts[i].thumb[j]; printf("%08d: %s\n", combinedHits[i].thumb[val], thumb_instruction_names[val]); } } } void DebugStatistics::printSequencerExecutionCounters() { for(int i=0;i<21;i++) printf("%06d ",sequencerExecutionCounters[i]); printf("\n"); } void DEBUG_reset() { //for now, just enable all debugging in developer builds #ifdef DEVELOPER debugFlag = 1; #endif DEBUG_Notify = DebugNotify(); DEBUG_statistics = DebugStatistics(); printf("DEBUG_reset: %p\n", &DebugStatistics::print); //force a reference to this function } static void DEBUG_dumpMemory_fill(EMUFILE *fp, u32 size) { static std::vector buf; buf.resize(size); memset(&buf[0],0,size); fp->fwrite(&buf[0],size); } void DEBUG_dumpMemory(EMUFILE* fp) { fp->fseek(0x000000,SEEK_SET); fp->fwrite(MMU.MAIN_MEM,0x800000); //arm9 main mem (8192K) fp->fseek(0x900000,SEEK_SET); fp->fwrite(MMU.ARM9_DTCM,0x4000); //arm9 DTCM (16K) fp->fseek(0xA00000,SEEK_SET); fp->fwrite(MMU.ARM9_ITCM,0x8000); //arm9 ITCM (32K) fp->fseek(0xB00000,SEEK_SET); fp->fwrite(MMU.ARM9_LCD,0xA4000); //LCD mem 656K fp->fseek(0xC00000,SEEK_SET); fp->fwrite(MMU.ARM9_VMEM,0x800); //OAM fp->fseek(0xD00000,SEEK_SET); fp->fwrite(MMU.ARM7_ERAM,0x10000); //arm7 WRAM (64K) fp->fseek(0xE00000,SEEK_SET); fp->fwrite(MMU.ARM7_WIRAM,0x10000); //arm7 wifi RAM ? fp->fseek(0xF00000,SEEK_SET); fp->fwrite(MMU.SWIRAM,0x8000); //arm9/arm7 shared WRAM (32KB) } //---------------------------------------------------- std::vector Logger::channels; static void defaultCallback(const Logger& logger, const char * message) { logger.getOutput() << message; } Logger::Logger() { out = &std::cout; callback = defaultCallback; flags = 0; } Logger::~Logger() { for(int i=0;i<(int)channels.size();i++) delete channels[i]; } void Logger::vprintf(const char * format, std::va_list l, const char * file, unsigned int line) { char buffer[1024]; char * cur = buffer; if (flags & Logger::FILE) cur += sprintf(cur, "%s:", file); if (flags & Logger::LINE) cur += sprintf(cur, "%d:", line); if (flags) cur += sprintf(cur, " "); ::vsnprintf(cur, 1024, format, l); callback(*this, buffer); } void Logger::setOutput(std::ostream * o) { out = o; } void Logger::setCallback(void (*cback)(const Logger& logger, const char * message)) { callback = cback; } void Logger::setFlag(unsigned int flag) { this->flags = flag; } void Logger::fixSize(unsigned int channel) { while(channel >= channels.size()) { channels.push_back(new Logger()); } } std::ostream& Logger::getOutput() const { return *out; } void Logger::log(unsigned int channel, const char * file, unsigned int line, const char * format, ...) { fixSize(channel); std::va_list l; va_start(l, format); channels[channel]->vprintf(format, l, file, line); va_end(l); } void Logger::log(unsigned int channel, const char * file, unsigned int line, std::ostream& os) { fixSize(channel); channels[channel]->setOutput(&os); } void Logger::log(unsigned int channel, const char * file, unsigned int line, unsigned int flag) { fixSize(channel); channels[channel]->setFlag(flag); } void Logger::log(unsigned int channel, const char * file, unsigned int line, void (*callback)(const Logger& logger, const char * message)) { fixSize(channel); channels[channel]->setCallback(callback); } void IdeasLog(armcpu_t* cpu) { u32 adr = cpu->R[0]; for(;;) { u8 c = _MMU_read08(cpu->proc_ID, MMU_AT_DEBUG, adr); adr++; if(!c) break; printf("%c",c); } //don't emit a newline. that is a pain in the butt. } void NocashMessage(armcpu_t* cpu, int offset) { u32 adr = cpu->instruct_adr + offset; std::string todo; for(;;) { u8 c = _MMU_read08(cpu->proc_ID, MMU_AT_DEBUG, adr); adr++; if(!c) break; todo.push_back(c); } //r0,r1,r2,...,r15 show register content (displayed as 32bit Hex number) //sp,lr,pc alias for r13,r14,r15 //scanline show current scanline number //frame show total number of frames since coldboot //totalclks show total number of clock cycles since coldboot //lastclks show number of cycles since previous lastclks (or zeroclks) //zeroclks resets the 'lastclks' counter //this is very inefficiently coded! char tmp[100]; todo = mass_replace(todo,"%sp%","%r13%"); todo = mass_replace(todo,"%lr%","%r14%"); todo = mass_replace(todo,"%pc%","%r15%"); sprintf(tmp,"%08X",cpu->R[0]); todo = mass_replace(todo,"%r0%",tmp); sprintf(tmp,"%08X",cpu->R[1]); todo = mass_replace(todo,"%r1%",tmp); sprintf(tmp,"%08X",cpu->R[2]); todo = mass_replace(todo,"%r2%",tmp); sprintf(tmp,"%08X",cpu->R[3]); todo = mass_replace(todo,"%r3%",tmp); sprintf(tmp,"%08X",cpu->R[4]); todo = mass_replace(todo,"%r4%",tmp); sprintf(tmp,"%08X",cpu->R[5]); todo = mass_replace(todo,"%r5%",tmp); sprintf(tmp,"%08X",cpu->R[6]); todo = mass_replace(todo,"%r6%",tmp); sprintf(tmp,"%08X",cpu->R[7]); todo = mass_replace(todo,"%r7%",tmp); sprintf(tmp,"%08X",cpu->R[8]); todo = mass_replace(todo,"%r8%",tmp); sprintf(tmp,"%08X",cpu->R[9]); todo = mass_replace(todo,"%r9%",tmp); sprintf(tmp,"%08X",cpu->R[10]); todo = mass_replace(todo,"%r10%",tmp); sprintf(tmp,"%08X",cpu->R[11]); todo = mass_replace(todo,"%r11%",tmp); sprintf(tmp,"%08X",cpu->R[12]); todo = mass_replace(todo,"%r12%",tmp); sprintf(tmp,"%08X",cpu->R[13]); todo = mass_replace(todo,"%r13%",tmp); sprintf(tmp,"%08X",cpu->R[14]); todo = mass_replace(todo,"%r14%",tmp); sprintf(tmp,"%08X",cpu->R[15]); todo = mass_replace(todo,"%r15%",tmp); sprintf(tmp,"%d",nds.VCount); todo = mass_replace(todo,"%scanline%",tmp); sprintf(tmp,"%d",currFrameCounter); todo = mass_replace(todo,"%frame%",tmp); sprintf(tmp,"%lld",nds_timer); todo = mass_replace(todo,"%totalclks%",tmp); printf("%s",todo.c_str()); } //------- DebugNotify DEBUG_Notify; //enable bits arent being used right now. //if you want exhaustive logging, move the print before the early return (or comment the early return) //the intent of this system is to provide a compact dialog box showing which debug notifies have been //triggered in this frame (with a glowing LED!) and which debug notifies have been triggered EVER //which can be cleared, like a clip indicator in an audio tool. //obviously all this isnt implemented yet. void DebugNotify::NextFrame() { #ifdef DEVELOPER pingBits.reset(); #endif } void DebugNotify::ReadBeyondEndOfCart(u32 addr, u32 romsize) { #ifdef DEVELOPER if(!ping(DEBUG_NOTIFY_READ_BEYOND_END_OF_CART)) return; INFO("Reading beyond end of cart! ... %08X >= %08X\n",addr,romsize); #endif } bool DebugNotify::ping(EDEBUG_NOTIFY which) { bool wasPinged = pingBits[(int)which]; pingBits[(int)which] = true; return !wasPinged; } desmume/src/utils/decrypt/000700 001750 001750 00000000000 12756420131 016727 5ustar00sergiosergio000000 000000 desmume/src/cheatSystem.h000664 001750 001750 00000007575 12755534123 016617 0ustar00sergiosergio000000 000000 /* Copyright (C) 2009-2015 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the this software. If not, see . */ #include #include #include #include #include #include "types.h" #define CHEAT_VERSION_MAJOR 2 #define CHEAT_VERSION_MINOR 0 #define MAX_CHEAT_LIST 100 #define MAX_XX_CODE 1024 #define CHEAT_FILE_MIN_FGETS_BUFFER 32768 #define CHEAT_DB_GAME_TITLE_SIZE 256 struct CHEATS_LIST { CHEATS_LIST() { memset(this,0,sizeof(*this)); type = 0xFF; } u8 type; // 0 - internal cheat system // 1 - Action Replay // 2 - Codebreakers BOOL enabled; // TODO u8 freezeType; // 0 - normal freeze // 1 - can decrease // 2 - can increase u32 code[MAX_XX_CODE][2]; char description[1024]; int num; u8 size; }; class CHEATS { private: std::vector list; u8 filename[PATH_MAX_LENGTH]; u32 currentGet; void ARparser(CHEATS_LIST& cheat); char *clearCode(char *s); public: CHEATS() : currentGet(0) { memset(filename, 0, sizeof(filename)); } ~CHEATS() {} void clear(); void init(char *path); BOOL add(u8 size, u32 address, u32 val, char *description, BOOL enabled); BOOL update(u8 size, u32 address, u32 val, char *description, BOOL enabled, u32 pos); BOOL add_AR(char *code, char *description, BOOL enabled); BOOL update_AR(char *code, char *description, BOOL enabled, u32 pos); BOOL add_AR_Direct(CHEATS_LIST cheat); BOOL add_CB(char *code, char *description, BOOL enabled); BOOL update_CB(char *code, char *description, BOOL enabled, u32 pos); BOOL remove(u32 pos); void getListReset(); BOOL getList(CHEATS_LIST *cheat); CHEATS_LIST* getListPtr(); BOOL get(CHEATS_LIST *cheat, u32 pos); CHEATS_LIST* getItemByIndex(const u32 pos); u32 getSize(); size_t getActiveCount(); void setDescription(const char *description, u32 pos); void process(); void getXXcodeString(CHEATS_LIST cheat, char *res_buf); static BOOL XXCodeFromString(CHEATS_LIST *cheatItem, const std::string codeString); static BOOL XXCodeFromString(CHEATS_LIST *cheatItem, const char *codeString); }; enum CHEATS_DB_TYPE { CHEATS_DB_R4 = 0 }; #pragma pack(push) #pragma pack(1) typedef struct FAT_R4 { u8 serial[4]; u32 CRC; u64 addr; } FAT_R4; #pragma pack(pop) class CHEATSEXPORT { private: CHEATS_DB_TYPE type; bool encrypted; FILE *fp; u32 fsize; u32 dataSize; u32 encOffset; FAT_R4 fat; bool search(); bool getCodes(); void R4decrypt(u8 *buf, u32 len, u32 n); u32 numCheats; CHEATS_LIST *cheats; u8 error; // 0 - no errors // 1 - open failed/file not found // 2 - file format is wrong (no valid header ID) // 3 - cheat not found in database // 4 - export error from database public: CHEATSEXPORT() : fp(NULL), fsize(0), dataSize(0), encOffset(0), type(CHEATS_DB_R4), encrypted(false), numCheats(0), cheats(0), CRC(0), error(0) { memset(date, 0, sizeof(date)); gametitle = (u8 *)malloc(CHEAT_DB_GAME_TITLE_SIZE); memset(gametitle, 0, CHEAT_DB_GAME_TITLE_SIZE); } ~CHEATSEXPORT() { free(gametitle); gametitle = NULL; } u8 *gametitle; u8 date[17]; u32 CRC; bool load(char *path); void close(); CHEATS_LIST *getCheats(); u32 getCheatsNum(); u8 getErrorCode() { return error; } }; extern CHEATS *cheats; desmume/src/libretro-common/net/test/net_ifinfo000755 001750 001750 00000020530 12755534123 023060 0ustar00sergiosergio000000 000000 ELF> @@˜@8@@@@@@ÀÀ@@@@Ô Ô Ø Ø `Ø ``h ð ð `ð `ÐÐ@@DDPåtdü ü @ü @DDQåtd/lib64/ld-linux-x86-64.so.2GNU GNU™°ìÆa2º—ÛüÌÕý—e„©g_* M#d B6libc.so.6__strdupreallocprintfcallocgetnameinfofreeifaddrsgetifaddrs__libc_start_mainfree__gmon_start__GLIBC_2.3GLIBC_2.2.5ii sui }À `à `è `ð `ø ````` ` HƒìH‹m H…Àtè³HƒÄÃÿ5Z ÿ%\ @ÿ%Z héàÿÿÿÿ%R héÐÿÿÿÿ%J héÀÿÿÿÿ%B hé°ÿÿÿÿ%: hé ÿÿÿÿ%2 héÿÿÿÿ%* hé€ÿÿÿÿ%" hépÿÿÿÿ% hé`ÿÿÿÿ%ª fUS¾¿Hƒìè›ÿÿÿH…ÀtVH‰ÇH‰Åèë„ÀtG1À1ÛHƒ}t+@HÁàHE¿ô @H‹PH‹01ÀèÿÿÿCH;EH‰ÃrÙH‰ïè1ÀHƒÄ[]ÃÈÿëôf.„1íI‰Ñ^H‰âHƒäðPTIÇÀà @HÇÁp @HÇÇ @è÷þÿÿôfD¸?`UH-8`HƒøH‰åv¸H…Àt]¿8`ÿàf„]Ã@f.„¾8`UHî8`HÁþH‰åH‰ðHÁè?HÆHÑþt¸H…Àt ]¿8`ÿà]ÃfD€=á uUH‰åènÿÿÿ]ÆÎ óÃ@¿è `Hƒ?u듸H…ÀtñUH‰åÿÐ]ézÿÿÿf.„H…ÿ„ATUI‰üSHƒH‹?tV1Û1íë)H‹{€?u?I‹<$HÇHÇC]I;\$H‰Ýs'HÁãHûtêH‹;€?tÆèýÿÿH‹{€?tÁèsýÿÿëºèkýÿÿ[L‰ç]A\é_ýÿÿ€óÃfDAWAVAUATI‰üUSHì(H|$HÇD$è‰ýÿÿM…ä„èƒøÿ„ßH‹\$H…Û„ç1íëDH‹H…Û„”H‹{H…ÿtëfƒ?uåHƒìE1ÉE1Àj¹¾HT$ èåüÿÿ…ÀZY…ƒDuI‹<$L‰öHÁæèýÿÿH…ÀtjH‹{HÁåI‰$L<(è½üÿÿH|$I‰I,$è¬üÿÿH‹H‰EM‰t$D‰õH…Û…pÿÿÿ@H‹|$èÖüÿÿ¸HÄ([]A\A]A^A_ÀH‹|$è®üÿÿL‰çèFþÿÿ1ÀëÑ1ÿëÃf.„@AWAVA‰ÿAUATL%V UH-V SI‰öI‰ÕL)åHƒìHÁýè§ûÿÿH…ít 1Û„L‰êL‰öD‰ÿAÿÜHƒÃH9ëuêHƒÄ[]A\A]A^A_Ãf.„óÃHƒìHƒÄÃ%s:%s ;@tûÿÿŒ$üÿÿD¤üÿÿ\¤ýÿÿ´4þÿÿätÿÿÿtäÿÿÿ¼zRx @üÿÿ*zRx $àúÿÿ FJ w€?;*3$",DèüÿÿŠKŒA†D ƒfÃDÆBÌ\tHýÿÿ2BBŽB B(ŒD0†A8ƒGà[èHðWèAàw 8A0A(B BBBH ,ÔØúÿÿuA†AƒN ] AAA DøýÿÿeBBŽE B(ŒH0†H8ƒM@r8A0A(B BBBL þÿÿp@P@ H@ ä @Ø `à `õþÿo`@ˆ@€@ ‰ È `Øp@X@ þÿÿo(@ÿÿÿoðÿÿo@ð `†@–@¦@¶@Æ@Ö@æ@ö@@GCC: (GNU) 5.3.0@@<@`@€@ˆ@@(@ X@ p@ H@ p@ @ @ä @ð @ü @@ @Ø `à `è `ð `À `È `(`8`ñÿñÿè ` Ð@"@5P@K8`Zà `p@Ø `¬ñÿ¹ñÿñÿËÐ @Ùè `ñÿåà `öð `ÿØ `ü @%È `;à @K] ø (`y8`Eä @€”­Ãâö(` 0`ð @. @Š>p @eNñ@`ü @*dy8`… @uŠ¡ µ8`Á Û0@2H H@init.ccrtstuff.c__JCR_LIST__deregister_tm_clones__do_global_dtors_auxcompleted.6945__do_global_dtors_aux_fini_array_entryframe_dummy__frame_dummy_init_array_entrynet_ifinfo.cnet_ifinfo_test.c__FRAME_END____JCR_END____init_array_end_DYNAMIC__init_array_start__GNU_EH_FRAME_HDR_GLOBAL_OFFSET_TABLE___libc_csu_finifree@@GLIBC_2.2.5_ITM_deregisterTMCloneTable_edataprintf@@GLIBC_2.2.5getnameinfo@@GLIBC_2.2.5__strdup@@GLIBC_2.2.5__libc_start_main@@GLIBC_2.2.5calloc@@GLIBC_2.2.5__data_start__gmon_start____dso_handle_IO_stdin_usednet_ifinfo_free__libc_csu_initgetifaddrs@@GLIBC_2.3realloc@@GLIBC_2.2.5__bss_startmainfreeifaddrs@@GLIBC_2.3_Jv_RegisterClasses__TMC_END___ITM_registerTMCloneTablenet_ifinfo_new.symtab.strtab.shstrtab.interp.note.ABI-tag.note.gnu.build-id.gnu.hash.dynsym.dynstr.gnu.version.gnu.version_r.rela.dyn.rela.plt.init.plt.got.text.fini.rodata.eh_frame_hdr.eh_frame.init_array.fini_array.jcr.dynamic.got.plt.data.bss.comment@#@ 1<@<$Döÿÿo`@`N €@€Vˆ@ˆ‰^ÿÿÿo@kþÿÿo(@(0zX@X„Bp@pØŽH@H‰p@p ”@ @ £ä @ä ©ð @ð ±ü @ü D¿@ @@ ”ÉØ `Ø Õà `à áè `è æð `ð ИÀ `À ïÈ `È `ø(`(þ8`808Š PP1  êdesmume/src/libretro-common/include/rhash.h000664 001750 001750 00000010551 12755534123 022152 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2016 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (rhash.h). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /* * sha1.h * * Copyright (C) 1998, 2009 * Paul E. Jones * All Rights Reserved * ***************************************************************************** * $Id: sha1.h 12 2009-06-22 19:34:25Z paulej $ ***************************************************************************** * * Description: * This class implements the Secure Hashing Standard as defined * in FIPS PUB 180-1 published April 17, 1995. * * Many of the variable names in the SHA1Context, especially the * single character names, were used because those were the names * used in the publication. * * Please read the file sha1.c for more information. * */ #ifndef __RARCH_HASH_H #define __RARCH_HASH_H #include #include #include #ifdef HAVE_CONFIG_H #include "config.h" #endif #include /** * sha256_hash: * @out : Output. * @in : Input. * @size : Size of @out. * * Hashes SHA256 and outputs a human readable string. **/ void sha256_hash(char *out, const uint8_t *in, size_t size); typedef struct SHA1Context { unsigned Message_Digest[5]; /* Message Digest (output) */ unsigned Length_Low; /* Message length in bits */ unsigned Length_High; /* Message length in bits */ unsigned char Message_Block[64]; /* 512-bit message blocks */ int Message_Block_Index; /* Index into message block array */ int Computed; /* Is the digest computed? */ int Corrupted; /* Is the message digest corruped? */ } SHA1Context; int sha1_calculate(const char *path, char *result); uint32_t djb2_calculate(const char *str); /* Any 32-bit or wider unsigned integer data type will do */ typedef unsigned int MD5_u32plus; typedef struct { MD5_u32plus lo, hi; MD5_u32plus a, b, c, d; unsigned char buffer[64]; MD5_u32plus block[16]; } MD5_CTX; /* * This is an OpenSSL-compatible implementation of the RSA Data Security, Inc. * MD5 Message-Digest Algorithm (RFC 1321). * * Homepage: * http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5 * * Author: * Alexander Peslyak, better known as Solar Designer * * This software was written by Alexander Peslyak in 2001. No copyright is * claimed, and the software is hereby placed in the public domain. * In case this attempt to disclaim copyright and place the software in the * public domain is deemed null and void, then the software is * Copyright (c) 2001 Alexander Peslyak and it is hereby released to the * general public under the following terms: * * Redistribution and use in source and binary forms, with or without * modification, are permitted. * * There's ABSOLUTELY NO WARRANTY, express or implied. * * See md5.c for more information. */ void MD5_Init(MD5_CTX *ctx); void MD5_Update(MD5_CTX *ctx, const void *data, unsigned long size); void MD5_Final(unsigned char *result, MD5_CTX *ctx); #endif desmume/src/utils/libfat/libfat_public_api.h000664 001750 001750 00000000600 12755534123 022335 0ustar00sergiosergio000000 000000 #ifndef _LIBFAT_PUBLIC_API_H_ #define _LIBFAT_PUBLIC_API_H_ #include #ifdef __cplusplus extern "C" { #endif void LIBFAT_Init(void* buffer, int size_bytes); void LIBFAT_Shutdown(void); bool LIBFAT_MkDir(const char *path); bool LIBFAT_WriteFile(const char *path, const void* data, int len); #ifdef __cplusplus } #endif #endif //_LIBFAT_PUBLIC_API_H_ desmume/src/utils/arm_arm/000700 001750 001750 00000000000 12756420131 016673 5ustar00sergiosergio000000 000000 desmume/src/000700 001750 001750 00000000000 12756420131 014115 5ustar00sergiosergio000000 000000 desmume/src/libretro-common/gfx/math/vector_2.c000664 001750 001750 00000003543 12755534123 022660 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2016 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (vector_2.c). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include #include #include float vec2_dot(const float *a, const float *b) { return (a[0]*b[0]) + (a[1]*b[1]); } float vec2_cross(const float *a, const float *b) { return (a[0]*b[1]) - (a[1]*b[0]); } void vec2_add(float *dst, const float *src) { dst[0] += src[0]; dst[1] += src[1]; } void vec2_subtract(float *dst, const float *src) { dst[0] -= src[0]; dst[1] -= src[1]; } void vec2_copy(float *dst, const float *src) { dst[0] = src[0]; dst[1] = src[1]; } desmume/src/utils/libfat/libfat_public_api.c000664 001750 001750 00000005035 12755534123 022337 0ustar00sergiosergio000000 000000 #include #include #include "libfat_public_api.h" #include "common.h" #include "disc_io.h" #include "fatfile.h" struct Instance { void* buffer; int size_bytes; struct devoptab_t* devops; }; struct Instance sInstance; struct Instance* gInstance = NULL; bool MEDIUM_STARTUP(void) { return true; } bool MEDIUM_ISINSERTED(void) { return true; } bool MEDIUM_io(bool write, sec_t sector, sec_t numSectors, void* buffer) { int todo = (int)numSectors*512; int loc = (int)sector*512; int have = gInstance->size_bytes - loc; if(todo>have) return false; if(write) memcpy((uint8_t*)gInstance->buffer + loc,buffer,todo); else memcpy(buffer,(uint8_t*)gInstance->buffer + loc,todo); return true; } bool MEDIUM_READSECTORS(sec_t sector, sec_t numSectors, void* buffer) { return MEDIUM_io(false,sector,numSectors,buffer); } bool MEDIUM_WRITESECTORS(sec_t sector, sec_t numSectors, const void* buffer) { return MEDIUM_io(true,sector,numSectors,(void*)buffer); } bool MEDIUM_CLEARSTATUS(void) { return true; } bool MEDIUM_SHUTDOWN(void) { return true; } struct DISC_INTERFACE_STRUCT discio = { 0, //unsigned long ioType ; FEATURE_MEDIUM_CANWRITE | FEATURE_MEDIUM_CANREAD, //unsigned long features ; MEDIUM_STARTUP, // FN_MEDIUM_STARTUP startup ; MEDIUM_ISINSERTED, //FN_MEDIUM_ISINSERTED isInserted ; MEDIUM_READSECTORS, //FN_MEDIUM_READSECTORS readSectors ; MEDIUM_WRITESECTORS, //FN_MEDIUM_WRITESECTORS writeSectors ; MEDIUM_CLEARSTATUS, //FN_MEDIUM_CLEARSTATUS clearStatus ; MEDIUM_SHUTDOWN, //FN_MEDIUM_SHUTDOWN shutdown ; } ; //not declared in any libfat headers...? bool fatMountSimple (const char* name, const DISC_INTERFACE* interface); void fatUnmountDirect (struct devoptab_t *devops); void LIBFAT_Init(void* buffer, int size_bytes) { gInstance = &sInstance; gInstance->buffer = buffer; gInstance->size_bytes = size_bytes; fatMountSimple("fat",&discio); gInstance->devops = GetDeviceOpTab(NULL); int zzz=9; } bool LIBFAT_MkDir(const char *path) { struct _reent r; return gInstance->devops->mkdir_r(&r,path,0) == 0; } bool LIBFAT_WriteFile(const char *path, const void* data, int len) { struct _reent r; FILE_STRUCT file; intptr_t fd = gInstance->devops->open_r(&r,&file,path,O_CREAT | O_RDWR,0); if(fd != -1) { ssize_t ret = gInstance->devops->write_r(&r, fd, (char*)data, len); gInstance->devops->close_r(&r, fd); if(ret == len) return true; } return false; } void LIBFAT_Shutdown(void) { fatUnmountDirect(gInstance->devops); gInstance = NULL; } desmume/src/libretro-common/include/formats/tga.h000664 001750 001750 00000003377 12755534123 023303 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2016 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (rtga.h). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef __LIBRETRO_SDK_FORMAT_RTGA_H__ #define __LIBRETRO_SDK_FORMAT_RTGA_H__ #include #include #ifdef HAVE_CONFIG_H #include "../../config.h" #endif #include #include RETRO_BEGIN_DECLS bool rtga_image_load_shift(uint8_t *buf, void *data, unsigned a_shift, unsigned r_shift, unsigned g_shift, unsigned b_shift); RETRO_END_DECLS #endif desmume/src/libretro-common/include/net/net_http.h000664 001750 001750 00000005370 12755534123 023463 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2016 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (net_http.h). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef _LIBRETRO_SDK_NET_HTTP_H #define _LIBRETRO_SDK_NET_HTTP_H #include #include #include #include RETRO_BEGIN_DECLS struct http_t; struct http_connection_t; struct http_connection_t *net_http_connection_new(const char *url); bool net_http_connection_iterate(struct http_connection_t *conn); bool net_http_connection_done(struct http_connection_t *conn); void net_http_connection_free(struct http_connection_t *conn); const char *net_http_connection_url(struct http_connection_t *conn); struct http_t *net_http_new(struct http_connection_t *conn); /* You can use this to call net_http_update * only when something will happen; select() it for reading. */ int net_http_fd(struct http_t *state); /* Returns true if it's done, or if something broke. * 'total' will be 0 if it's not known. */ bool net_http_update(struct http_t *state, size_t* progress, size_t* total); /* 200, 404, or whatever. */ int net_http_status(struct http_t *state); bool net_http_error(struct http_t *state); /* Returns the downloaded data. The returned buffer is owned by the * HTTP handler; it's freed by net_http_delete. * * If the status is not 20x and accept_error is false, it returns NULL. */ uint8_t* net_http_data(struct http_t *state, size_t* len, bool accept_error); /* Cleans up all memory. */ void net_http_delete(struct http_t *state); RETRO_END_DECLS #endif desmume/src/arm_jit.h000664 001750 001750 00000005146 12755534123 015743 0ustar00sergiosergio000000 000000 /* Copyright (C) 2006 yopyop Copyright (C) 2011 Loren Merritt Copyright (C) 2012-2013 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the this software. If not, see . */ #ifndef ARM_JIT #define ARM_JIT #include "types.h" #ifndef _MSC_VER #include #endif typedef u32 (FASTCALL* ArmOpCompiled)(); void arm_jit_reset(bool enable, bool suppress_msg = false); void arm_jit_close(); void arm_jit_sync(); template u32 arm_jit_compile(); #if defined(HOST_WINDOWS) || defined(DESMUME_COCOA) #define MAPPED_JIT_FUNCS #endif #ifdef MAPPED_JIT_FUNCS struct JIT_struct { // only include the memory types that code can execute from uintptr_t MAIN_MEM[16*1024*1024/2]; uintptr_t SWIRAM[0x8000/2]; uintptr_t ARM9_ITCM[0x8000/2]; uintptr_t ARM9_LCDC[0xA4000/2]; uintptr_t ARM9_BIOS[0x8000/2]; uintptr_t ARM7_BIOS[0x4000/2]; uintptr_t ARM7_ERAM[0x10000/2]; uintptr_t ARM7_WIRAM[0x10000/2]; uintptr_t ARM7_WRAM[0x40000/2]; static uintptr_t *JIT_MEM[2][0x4000]; }; extern CACHE_ALIGN JIT_struct JIT; #define JIT_COMPILED_FUNC(adr, PROCNUM) JIT.JIT_MEM[PROCNUM][((adr)&0x0FFFC000)>>14][((adr)&0x00003FFE)>>1] #define JIT_COMPILED_FUNC_PREMASKED(adr, PROCNUM, ofs) JIT.JIT_MEM[PROCNUM][(adr)>>14][(((adr)&0x00003FFE)>>1)+ofs] #define JIT_COMPILED_FUNC_KNOWNBANK(adr, bank, mask, ofs) JIT.bank[(((adr)&(mask))>>1)+ofs] #define JIT_MAPPED(adr, PROCNUM) JIT.JIT_MEM[PROCNUM][(adr)>>14] #else // actually an array of function pointers, but they fit in 32bit address space, so might as well save memory extern uintptr_t compiled_funcs[]; // there isn't anything mapped between 07000000 and 0EFFFFFF, so we can mask off bit 27 and get away with a smaller array #define JIT_COMPILED_FUNC(adr, PROCNUM) compiled_funcs[((adr) & 0x07FFFFFE) >> 1] #define JIT_COMPILED_FUNC_PREMASKED(adr, PROCNUM, ofs) JIT_COMPILED_FUNC(adr+(ofs<<1), PROCNUM) #define JIT_COMPILED_FUNC_KNOWNBANK(adr, bank, mask, ofs) JIT_COMPILED_FUNC(adr+(ofs<<1), PROCNUM) #define JIT_MAPPED(adr, PROCNUM) true #endif extern u32 saveBlockSizeJIT; #endif desmume/src/libretro-common/libco/fiber.c000664 001750 001750 00000001710 12755534123 021571 0ustar00sergiosergio000000 000000 /* libco.win (2008-01-28) authors: Nach, byuu license: public domain */ #define LIBCO_C #include #define WINVER 0x0400 #define _WIN32_WINNT 0x0400 #define WIN32_LEAN_AND_MEAN #include #ifdef __cplusplus extern "C" { #endif static thread_local cothread_t co_active_ = 0; static void __stdcall co_thunk(void *coentry) { ((void (*)(void))coentry)(); } cothread_t co_active(void) { if(!co_active_) { ConvertThreadToFiber(0); co_active_ = GetCurrentFiber(); } return co_active_; } cothread_t co_create(unsigned int heapsize, void (*coentry)(void)) { if(!co_active_) { ConvertThreadToFiber(0); co_active_ = GetCurrentFiber(); } return (cothread_t)CreateFiber(heapsize, co_thunk, (void*)coentry); } void co_delete(cothread_t cothread) { DeleteFiber(cothread); } void co_switch(cothread_t cothread) { co_active_ = cothread; SwitchToFiber(cothread); } #ifdef __cplusplus } #endif desmume/src/libretro-common/net/test/000700 001750 001750 00000000000 12756420131 020772 5ustar00sergiosergio000000 000000 desmume/src/libretro-common/include/vulkan/000700 001750 001750 00000000000 12756420131 022150 5ustar00sergiosergio000000 000000 desmume/src/libretro-common/streams/interface_stream.c000664 001750 001750 00000014006 12755534123 024405 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2016 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (interface_stream.c). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include #include #include #include struct intfstream_internal { enum intfstream_type type; struct { RFILE *fp; } file; struct { struct { uint8_t *data; unsigned size; } buf; memstream_t *fp; bool writable; } memory; }; bool intfstream_resize(intfstream_internal_t *intf, intfstream_info_t *info) { if (!intf || !info) return false; switch (intf->type) { case INTFSTREAM_FILE: break; case INTFSTREAM_MEMORY: intf->memory.buf.data = info->memory.buf.data; intf->memory.buf.size = info->memory.buf.size; memstream_set_buffer(intf->memory.buf.data, intf->memory.buf.size); break; } return true; } bool intfstream_open(intfstream_internal_t *intf, const char *path, unsigned mode, ssize_t len) { if (!intf) return false; switch (intf->type) { case INTFSTREAM_FILE: intf->file.fp = filestream_open(path, mode, len); if (!intf->file.fp) return false; break; case INTFSTREAM_MEMORY: intf->memory.fp = memstream_open(intf->memory.writable); if (!intf->memory.fp) return false; break; } return true; } int intfstream_close(intfstream_internal_t *intf) { if (!intf) return -1; switch (intf->type) { case INTFSTREAM_FILE: return filestream_close(intf->file.fp); case INTFSTREAM_MEMORY: memstream_close(intf->memory.fp); return 0; } return -1; } void *intfstream_init(intfstream_info_t *info) { intfstream_internal_t *intf = NULL; if (!info) goto error; intf = (intfstream_internal_t*)calloc(1, sizeof(*intf)); if (!intf) goto error; intf->type = info->type; switch (intf->type) { case INTFSTREAM_FILE: break; case INTFSTREAM_MEMORY: intf->memory.writable = info->memory.writable; if (!intfstream_resize(intf, info)) goto error; break; } return intf; error: if (intf) free(intf); return NULL; } int intfstream_seek(intfstream_internal_t *intf, int offset, int whence) { if (!intf) return -1; switch (intf->type) { case INTFSTREAM_FILE: return filestream_seek(intf->file.fp, offset, whence); case INTFSTREAM_MEMORY: return memstream_seek(intf->memory.fp, offset, whence); } return -1; } ssize_t intfstream_read(intfstream_internal_t *intf, void *s, size_t len) { if (!intf) return 0; switch (intf->type) { case INTFSTREAM_FILE: return filestream_read(intf->file.fp, s, len); case INTFSTREAM_MEMORY: return memstream_read(intf->memory.fp, s, len); } return 0; } ssize_t intfstream_write(intfstream_internal_t *intf, const void *s, size_t len) { if (!intf) return 0; switch (intf->type) { case INTFSTREAM_FILE: return filestream_write(intf->file.fp, s, len); case INTFSTREAM_MEMORY: return memstream_write(intf->memory.fp, s, len); } return 0; } char *intfstream_gets(intfstream_internal_t *intf, char *buffer, size_t len) { if (!intf) return NULL; switch (intf->type) { case INTFSTREAM_FILE: return filestream_gets(intf->file.fp, buffer, len); case INTFSTREAM_MEMORY: return memstream_gets(intf->memory.fp, buffer, len); } return NULL; } int intfstream_getc(intfstream_internal_t *intf) { if (!intf) return 0; switch (intf->type) { case INTFSTREAM_FILE: return filestream_getc(intf->file.fp); case INTFSTREAM_MEMORY: return memstream_getc(intf->memory.fp); } return 0; } int intfstream_tell(intfstream_internal_t *intf) { if (!intf) return -1; switch (intf->type) { case INTFSTREAM_FILE: return filestream_tell(intf->file.fp); case INTFSTREAM_MEMORY: return memstream_pos(intf->memory.fp); } return -1; } void intfstream_rewind(intfstream_internal_t *intf) { switch (intf->type) { case INTFSTREAM_FILE: filestream_rewind(intf->file.fp); break; case INTFSTREAM_MEMORY: memstream_rewind(intf->memory.fp); break; } } void intfstream_putc(intfstream_internal_t *intf, int c) { if (!intf) return; switch (intf->type) { case INTFSTREAM_FILE: filestream_putc(intf->file.fp, c); break; case INTFSTREAM_MEMORY: memstream_putc(intf->memory.fp, c); break; } } desmume/src/addons/slot1_r4.cpp000664 001750 001750 00000013115 12755534123 017563 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2015 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the this software. If not, see . */ #include "slot1comp_protocol.h" #include #include "../slot1.h" #include "../NDSSystem.h" #include "../emufile.h" class Slot1_R4 : public ISlot1Interface, public ISlot1Comp_Protocol_Client { private: EMUFILE *img; Slot1Comp_Protocol protocol; u32 write_count; u32 write_enabled; public: Slot1_R4() : img(NULL) , write_count(0) , write_enabled(0) { } virtual Slot1Info const* info() { static Slot1InfoSimple info("R4", "Slot1 R4 emulation", 0x03); return &info; } //called once when the emulator starts up, or when the device springs into existence virtual bool init() { //strange to do this here but we need to make sure its done at some point srand(time(NULL)); return true; } virtual void connect() { img = slot1_GetFatImage(); #ifdef DEBUG if(!img) INFO("slot1 fat not successfully mounted\n"); #endif protocol.reset(this); protocol.chipId = 0xFC2; protocol.gameCode = T1ReadLong((u8*)gameInfo.header.gameCode,0); } //called when the emulator disconnects the device virtual void disconnect() { img = NULL; } //called when the emulator shuts down, or when the device disappears from existence virtual void shutdown() { } virtual void write_command(u8 PROCNUM, GC_Command command) { protocol.write_command(command); } virtual void write_GCDATAIN(u8 PROCNUM, u32 val) { protocol.write_GCDATAIN(PROCNUM, val); } virtual u32 read_GCDATAIN(u8 PROCNUM) { return protocol.read_GCDATAIN(PROCNUM); } virtual void slot1client_startOperation(eSlot1Operation operation) { if(operation != eSlot1Operation_Unknown) return; u32 address; int cmd = protocol.command.bytes[0]; switch(cmd) { case 0xB0: break; case 0xB9: case 0xBA: address = (protocol.command.bytes[1] << 24) | (protocol.command.bytes[2] << 16) | (protocol.command.bytes[3] << 8) | protocol.command.bytes[4]; img->fseek(address,SEEK_SET); break; case 0xBB: write_enabled = 1; write_count = 0x80; //passthrough on purpose? case 0xBC: address = (protocol.command.bytes[1] << 24) | (protocol.command.bytes[2] << 16) | (protocol.command.bytes[3] << 8) | protocol.command.bytes[4]; img->fseek(address,SEEK_SET); break; } } virtual u32 slot1client_read_GCDATAIN(eSlot1Operation operation) { if(operation != eSlot1Operation_Unknown) return 0; u32 val; int cmd = protocol.command.bytes[0]; switch(cmd) { case 0xB0: val = (img) ? 0x1F4 : 0x1F2; break; case 0xB9: val = (rand() % 100) ? (img) ? 0x1F4 : 0x1F2 : 0; break; case 0xBB: case 0xBC: val = 0; break; case 0xBA: //INFO("Read from sd at sector %08X at adr %08X ",card.address/512,ftell(img)); img->fread(&val, 4); //INFO("val %08X\n",val); break; default: val = 0; break; } return val; } void slot1client_write_GCDATAIN(eSlot1Operation operation, u32 val) { if(operation != eSlot1Operation_Unknown) return; int cmd = protocol.command.bytes[0]; switch(cmd) { case 0xBB: { if(write_count && write_enabled) { img->fwrite(&val, 4); img->fflush(); write_count--; } break; } default: break; } } virtual void post_fakeboot(int PROCNUM) { // The BIOS leaves the card in NORMAL mode protocol.mode = eCardMode_NORMAL; } void write32_GCDATAIN(u32 val) { //bool log = false; //last_write_count = write_count; //can someone tell me ... what the hell is this doing, anyway? //seems odd to use card.command[4] for this... isnt it part of the address? if(protocol.command.bytes[4]) { // transfer is done //are you SURE this is logical? there doesnt seem to be any way for the card to signal that T1WriteLong(MMU.MMU_MEM[0][0x40], 0x1A4,val & 0x7F7FFFFF); MMU_GC_endTransfer(0); return; } int cmd = protocol.command.bytes[0]; switch(cmd) { case 0xBB: { if(write_count && write_enabled) { img->fwrite(&val, 4); img->fflush(); write_count--; } break; } default: break; } if(write_count==0) { write_enabled = 0; //transfer is done //are you SURE this is logical? there doesnt seem to be any way for the card to signal that T1WriteLong(MMU.MMU_MEM[0][0x40], 0x1A4,val & 0x7F7FFFFF); //but isnt this a different IRQ? IREQ_MC perhaps MMU_GC_endTransfer(0); } /*if(log) { INFO("WRITE CARD command: %02X%02X%02X%02X%02X%02X%02X%02X\t", card.command[0], card.command[1], card.command[2], card.command[3], card.command[4], card.command[5], card.command[6], card.command[7]); INFO("FROM: %08X\t", NDS_ARM9.instruct_adr); INFO("VAL: %08X\n", val); }*/ } }; ISlot1Interface* construct_Slot1_R4() { return new Slot1_R4(); } desmume/src/libretro-common/include/net/net_ifinfo.h000664 001750 001750 00000003361 12755534123 023754 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2016 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (net_ifinfo.h). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef _LIBRETRO_NET_IFINFO_H #define _LIBRETRO_NET_IFINFO_H #include #include #include struct net_ifinfo_entry { char *name; char *host; }; struct net_ifinfo { struct net_ifinfo_entry *entries; size_t size; }; typedef struct net_ifinfo net_ifinfo_t; void net_ifinfo_free(net_ifinfo_t *list); bool net_ifinfo_new(net_ifinfo_t *list); #endif desmume/Makefile000664 001750 001750 00000000032 12755534123 015003 0ustar00sergiosergio000000 000000 include Makefile.libretro desmume/src/libretro-common/libco/libco.c000664 001750 001750 00000001240 12755534123 021570 0ustar00sergiosergio000000 000000 /* libco auto-selection module license: public domain */ #if defined(__GNUC__) && defined(__i386__) || (defined(_MSC_VER) && defined(_M_IX86)) #include "x86.c" #elif defined(__GNUC__) && defined(__amd64__) || (defined(_MSC_VER) && defined(_M_AMD64)) #include "amd64.c" #elif defined(__GNUC__) && defined(_ARCH_PPC) #include "ppc.c" #elif defined(__GNUC__) && defined(VITA) #include "psp2.c" #elif defined(__GNUC__) && (defined(__ARM_EABI__) || defined(__arm__)) #include "armeabi.c" #elif defined(__GNUC__) #include "sjlj.c" #elif defined(_MSC_VER) #include "fiber.c" #else #error "libco: unsupported processor, compiler or operating system" #endif desmume/src/libretro-common/streams/memory_stream.c000664 001750 001750 00000010645 12755534123 023762 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2016 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (memory_stream.c). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include #include #include #include static uint8_t* g_buffer = NULL; static size_t g_size = 0; static size_t last_file_size = 0; struct memstream { uint8_t *buf; size_t size; size_t ptr; size_t max_ptr; unsigned writing; }; static void memstream_update_pos(memstream_t *stream) { if (stream->ptr > stream->max_ptr) stream->max_ptr = stream->ptr; } void memstream_set_buffer(uint8_t *buffer, size_t size) { g_buffer = buffer; g_size = size; } size_t memstream_get_last_size(void) { return last_file_size; } static void memstream_init(memstream_t *stream, uint8_t *buffer, size_t max_size, unsigned writing) { if (!stream) return; stream->buf = buffer; stream->size = max_size; stream->ptr = 0; stream->max_ptr = 0; stream->writing = writing; } memstream_t *memstream_open(unsigned writing) { memstream_t *stream; if (!g_buffer || !g_size) return NULL; stream = (memstream_t*)calloc(1, sizeof(*stream)); memstream_init(stream, g_buffer, g_size, writing); g_buffer = NULL; g_size = 0; return stream; } void memstream_close(memstream_t *stream) { if (!stream) return; last_file_size = stream->writing ? stream->max_ptr : stream->size; free(stream); } size_t memstream_read(memstream_t *stream, void *data, size_t bytes) { size_t avail = 0; if (!stream) return 0; avail = stream->size - stream->ptr; if (bytes > avail) bytes = avail; memcpy(data, stream->buf + stream->ptr, bytes); stream->ptr += bytes; memstream_update_pos(stream); return bytes; } size_t memstream_write(memstream_t *stream, const void *data, size_t bytes) { size_t avail = 0; if (!stream) return 0; avail = stream->size - stream->ptr; if (bytes > avail) bytes = avail; memcpy(stream->buf + stream->ptr, data, bytes); stream->ptr += bytes; memstream_update_pos(stream); return bytes; } int memstream_seek(memstream_t *stream, int offset, int whence) { size_t ptr; switch (whence) { case SEEK_SET: ptr = offset; break; case SEEK_CUR: ptr = stream->ptr + offset; break; case SEEK_END: ptr = (stream->writing ? stream->max_ptr : stream->size) + offset; break; default: return -1; } if (ptr <= stream->size) { stream->ptr = ptr; return 0; } return -1; } void memstream_rewind(memstream_t *stream) { memstream_seek(stream, 0L, SEEK_SET); } size_t memstream_pos(memstream_t *stream) { return stream->ptr; } char *memstream_gets(memstream_t *stream, char *buffer, size_t len) { return NULL; } int memstream_getc(memstream_t *stream) { int ret = 0; if (stream->ptr >= stream->size) return EOF; ret = stream->buf[stream->ptr++]; memstream_update_pos(stream); return ret; } void memstream_putc(memstream_t *stream, int c) { if (stream->ptr < stream->size) stream->buf[stream->ptr++] = c; memstream_update_pos(stream); } desmume/src/libretro-common/net/net_http.c000664 001750 001750 00000030440 12755534123 022027 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2016 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (net_http.c). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include #include #include #include #include #include #include enum { P_HEADER_TOP = 0, P_HEADER, P_BODY, P_BODY_CHUNKLEN, P_DONE, P_ERROR }; enum { T_FULL = 0, T_LEN, T_CHUNK }; struct http_t { int fd; int status; char part; char bodytype; bool error; size_t pos; size_t len; size_t buflen; char * data; }; struct http_connection_t { char *domain; char *location; char *urlcopy; char *scan; int port; }; static int net_http_new_socket(const char *domain, int port) { int ret; struct addrinfo *addr = NULL; int fd = socket_init((void**)&addr, port, domain, SOCKET_TYPE_STREAM); if (fd < 0) return -1; ret = socket_connect(fd, (void*)addr, true); freeaddrinfo_retro(addr); if (ret < 0) goto error; if (!socket_nonblock(fd)) goto error; return fd; error: socket_close(fd); return -1; } static void net_http_send_str(int fd, bool *error, const char *text) { if (*error) return; if (!socket_send_all_blocking(fd, text, strlen(text), true)) *error = true; } static char* urlencode(const char* url) { unsigned i; unsigned outpos = 0; unsigned outlen = 0; char *ret = NULL; for (i = 0; url[i] != '\0'; i++) { outlen++; if (url[i] == ' ') outlen += 2; } ret = (char*)malloc(outlen + 1); if (!ret) return NULL; for (i = 0; url[i]; i++) { if (url[i] == ' ') { ret[outpos++] = '%'; ret[outpos++] = '2'; ret[outpos++] = '0'; } else ret[outpos++] = url[i]; } ret[outpos] = '\0'; return ret; } struct http_connection_t *net_http_connection_new(const char *url) { char **domain = NULL; struct http_connection_t *conn = (struct http_connection_t*)calloc(1, sizeof(struct http_connection_t)); if (!conn) return NULL; conn->urlcopy = urlencode(url); if (!conn->urlcopy) goto error; if (strncmp(url, "http://", strlen("http://")) != 0) goto error; conn->scan = conn->urlcopy + strlen("http://"); domain = &conn->domain; *domain = conn->scan; return conn; error: if (conn->urlcopy) free(conn->urlcopy); conn->urlcopy = NULL; free(conn); return NULL; } bool net_http_connection_iterate(struct http_connection_t *conn) { if (!conn) return false; while (*conn->scan != '/' && *conn->scan != ':' && *conn->scan != '\0') conn->scan++; return true; } bool net_http_connection_done(struct http_connection_t *conn) { char **location = NULL; if (!conn) return false; location = &conn->location; if (*conn->scan == '\0') return false; *conn->scan = '\0'; conn->port = 80; if (*conn->scan == ':') { if (!isdigit((int)conn->scan[1])) return false; conn->port = strtoul(conn->scan + 1, &conn->scan, 10); if (*conn->scan != '/') return false; } *location = conn->scan + 1; return true; } void net_http_connection_free(struct http_connection_t *conn) { if (!conn) return; if (conn->urlcopy) free(conn->urlcopy); free(conn); } const char *net_http_connection_url(struct http_connection_t *conn) { return conn->urlcopy; } struct http_t *net_http_new(struct http_connection_t *conn) { bool error = false; int fd = -1; struct http_t *state = NULL; if (!conn) goto error; fd = net_http_new_socket(conn->domain, conn->port); if (fd < 0) goto error; error = false; /* This is a bit lazy, but it works. */ net_http_send_str(fd, &error, "GET /"); net_http_send_str(fd, &error, conn->location); net_http_send_str(fd, &error, " HTTP/1.1\r\n"); net_http_send_str(fd, &error, "Host: "); net_http_send_str(fd, &error, conn->domain); if (conn->port != 80) { char portstr[16] = {0}; snprintf(portstr, sizeof(portstr), ":%i", conn->port); net_http_send_str(fd, &error, portstr); } net_http_send_str(fd, &error, "\r\n"); net_http_send_str(fd, &error, "Connection: close\r\n"); net_http_send_str(fd, &error, "\r\n"); if (error) goto error; state = (struct http_t*)malloc(sizeof(struct http_t)); state->fd = fd; state->status = -1; state->data = NULL; state->part = P_HEADER_TOP; state->bodytype= T_FULL; state->error = false; state->pos = 0; state->len = 0; state->buflen = 512; state->data = (char*)malloc(state->buflen); if (!state->data) goto error; return state; error: if (fd >= 0) socket_close(fd); if (state) free(state); return NULL; } int net_http_fd(struct http_t *state) { if (!state) return -1; return state->fd; } bool net_http_update(struct http_t *state, size_t* progress, size_t* total) { ssize_t newlen = 0; if (!state || state->error) goto fail; if (state->part < P_BODY) { if (state->error) newlen = -1; else newlen = socket_receive_all_nonblocking(state->fd, &state->error, (uint8_t*)state->data + state->pos, state->buflen - state->pos); if (newlen < 0) goto fail; if (state->pos + newlen >= state->buflen - 64) { state->buflen *= 2; state->data = (char*)realloc(state->data, state->buflen); } state->pos += newlen; while (state->part < P_BODY) { char *dataend = state->data + state->pos; char *lineend = (char*)memchr(state->data, '\n', state->pos); if (!lineend) break; *lineend='\0'; if (lineend != state->data && lineend[-1]=='\r') lineend[-1]='\0'; if (state->part == P_HEADER_TOP) { if (strncmp(state->data, "HTTP/1.", strlen("HTTP/1."))!=0) goto fail; state->status = strtoul(state->data + strlen("HTTP/1.1 "), NULL, 10); state->part = P_HEADER; } else { if (!strncmp(state->data, "Content-Length: ", strlen("Content-Length: "))) { state->bodytype = T_LEN; state->len = strtol(state->data + strlen("Content-Length: "), NULL, 10); } if (!strcmp(state->data, "Transfer-Encoding: chunked")) state->bodytype = T_CHUNK; /* TODO: save headers somewhere */ if (state->data[0]=='\0') { state->part = P_BODY; if (state->bodytype == T_CHUNK) state->part = P_BODY_CHUNKLEN; } } memmove(state->data, lineend + 1, dataend-(lineend+1)); state->pos = (dataend-(lineend + 1)); } if (state->part >= P_BODY) { newlen = state->pos; state->pos = 0; } } if (state->part >= P_BODY && state->part < P_DONE) { if (!newlen) { if (state->error) newlen = -1; else newlen = socket_receive_all_nonblocking( state->fd, &state->error, (uint8_t*)state->data + state->pos, state->buflen - state->pos); if (newlen < 0) { if (state->bodytype == T_FULL) { state->part = P_DONE; state->data = (char*)realloc(state->data, state->len); } else goto fail; newlen=0; } if (state->pos + newlen >= state->buflen - 64) { state->buflen *= 2; state->data = (char*)realloc(state->data, state->buflen); } } parse_again: if (state->bodytype == T_CHUNK) { if (state->part == P_BODY_CHUNKLEN) { state->pos += newlen; if (state->pos - state->len >= 2) { /* * len=start of chunk including \r\n * pos=end of data */ char *fullend = state->data + state->pos; char *end = (char*)memchr(state->data + state->len + 2, '\n', state->pos - state->len - 2); if (end) { size_t chunklen = strtoul(state->data+state->len, NULL, 16); state->pos = state->len; end++; memmove(state->data+state->len, end, fullend-end); state->len = chunklen; newlen = (fullend - end); /* len=num bytes newlen=unparsed bytes after \n pos=start of chunk including \r\n */ state->part = P_BODY; if (state->len == 0) { state->part = P_DONE; state->len = state->pos; state->data = (char*)realloc(state->data, state->len); } goto parse_again; } } } else if (state->part == P_BODY) { if ((size_t)newlen >= state->len) { state->pos += state->len; newlen -= state->len; state->len = state->pos; state->part = P_BODY_CHUNKLEN; goto parse_again; } else { state->pos += newlen; state->len -= newlen; } } } else { state->pos += newlen; if (state->pos == state->len) { state->part = P_DONE; state->data = (char*)realloc(state->data, state->len); } if (state->pos > state->len) goto fail; } } if (progress) *progress = state->pos; if (total) { if (state->bodytype == T_LEN) *total=state->len; else *total=0; } return (state->part == P_DONE); fail: if (state) { state->error = true; state->part = P_ERROR; state->status = -1; } return true; } int net_http_status(struct http_t *state) { if (!state) return -1; return state->status; } uint8_t* net_http_data(struct http_t *state, size_t* len, bool accept_error) { if (!state) return NULL; if (!accept_error && net_http_error(state)) { if (len) *len=0; return NULL; } if (len) *len=state->len; return (uint8_t*)state->data; } void net_http_delete(struct http_t *state) { if (!state) return; if (state->fd >= 0) socket_close(state->fd); free(state); } bool net_http_error(struct http_t *state) { return (state->error || state->status<200 || state->status>299); } desmume/src/common.h000664 001750 001750 00000004132 12755534123 015600 0ustar00sergiosergio000000 000000 /* Copyright (C) 2008-2015 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the this software. If not, see . */ //TODO - dismantle this file #ifndef _COMMON_H_ #define _COMMON_H_ #include #include #include #include #include #include #if defined(WIN32) #define CLASSNAME "DeSmuME" #ifdef __GNUC__ #define sscanf_s sscanf #endif #else // non Windows #define sscanf_s sscanf #endif #ifdef __cplusplus extern "C" { #endif static INLINE char *integer_to_binary(uint32_t val, size_t len) { unsigned i, t; char buf[256] = {0}; for (i = len * 8, t = 0; i > 0; --i, t++) buf[i-1] = (val & (1< #include #include /* ptrdiff_t on osx */ #include #include #include #include #include #include #include #include enum { RJPEG_DEFAULT = 0, /* only used for req_comp */ RJPEG_GREY, RJPEG_GREY_ALPHA, RJPEG_RGB, RJPEG_RGB_ALPHA }; typedef struct { int (*read) (void *user,char *data,int size); /* fill 'data' with 'size' bytes. return number of bytes actually read */ void (*skip) (void *user,int n); /* skip the next 'n' bytes, or 'unget' the last -n bytes if negative */ int (*eof) (void *user); /* returns nonzero if we are at end of file/data */ } rjpeg_io_callbacks; typedef uint8_t *(*rjpeg_resample_row_func)(uint8_t *out, uint8_t *in0, uint8_t *in1, int w, int hs); typedef struct { rjpeg_resample_row_func resample; uint8_t *line0,*line1; int hs,vs; /* expansion factor in each axis */ int w_lores; /* horizontal pixels pre-expansion */ int ystep; /* how far through vertical expansion we are */ int ypos; /* which pre-expansion row we're on */ } rjpeg__resample; struct rjpeg { uint8_t *buff_data; void *empty; }; #ifdef _MSC_VER #define RJPEG_HAS_LROTL #endif #ifdef RJPEG_HAS_LROTL #define rjpeg_lrot(x,y) _lrotl(x,y) #else #define rjpeg_lrot(x,y) (((x) << (y)) | ((x) >> (32 - (y)))) #endif /* x86/x64 detection */ #if defined(__x86_64__) || defined(_M_X64) #define RJPEG__X64_TARGET #elif defined(__i386) || defined(_M_IX86) #define RJPEG__X86_TARGET #endif #if defined(__GNUC__) && (defined(RJPEG__X86_TARGET) || defined(RJPEG__X64_TARGET)) && !defined(__SSE2__) && !defined(RJPEG_NO_SIMD) /* NOTE: not clear do we actually need this for the 64-bit path? * gcc doesn't support sse2 intrinsics unless you compile with -msse2, * (but compiling with -msse2 allows the compiler to use SSE2 everywhere; * this is just broken and gcc are jerks for not fixing it properly * http://www.virtualdub.org/blog/pivot/entry.php?id=363 ) */ #define RJPEG_NO_SIMD #endif #if defined(__MINGW32__) && defined(RJPEG__X86_TARGET) && !defined(RJPEG_MINGW_ENABLE_SSE2) && !defined(RJPEG_NO_SIMD) /* Note that __MINGW32__ doesn't actually mean 32-bit, so we have to avoid RJPEG__X64_TARGET * * 32-bit MinGW wants ESP to be 16-byte aligned, but this is not in the * Windows ABI and VC++ as well as Windows DLLs don't maintain that invariant. * As a result, enabling SSE2 on 32-bit MinGW is dangerous when not * simultaneously enabling "-mstackrealign". * * See https://github.com/nothings/stb/issues/81 for more information. * * So default to no SSE2 on 32-bit MinGW. If you've read this far and added * -mstackrealign to your build settings, feel free to #define RJPEG_MINGW_ENABLE_SSE2. */ #define RJPEG_NO_SIMD #endif #if defined(__SSE2__) #include #ifdef _MSC_VER #define RJPEG_SIMD_ALIGN(type, name) __declspec(align(16)) type name #else #define RJPEG_SIMD_ALIGN(type, name) type name __attribute__((aligned(16))) #endif #endif /* ARM NEON */ #if defined(RJPEG_NO_SIMD) && defined(RJPEG_NEON) #undef RJPEG_NEON #endif #ifdef RJPEG_NEON #include /* assume GCC or Clang on ARM targets */ #define RJPEG_SIMD_ALIGN(type, name) type name __attribute__((aligned(16))) #endif #ifndef RJPEG_SIMD_ALIGN #define RJPEG_SIMD_ALIGN(type, name) type name #endif typedef struct { uint32_t img_x, img_y; int img_n, img_out_n; rjpeg_io_callbacks io; void *io_user_data; int read_from_callbacks; int buflen; uint8_t buffer_start[128]; uint8_t *img_buffer, *img_buffer_end; uint8_t *img_buffer_original; } rjpeg__context; static uint8_t *rjpeg__jpeg_load(rjpeg__context *s, unsigned *x, unsigned *y, int *comp, int req_comp); #define rjpeg__err(x,y) 0 #define rjpeg__errpf(x,y) ((float *) (rjpeg__err(x,y)?NULL:NULL)) #define rjpeg__errpuc(x,y) ((unsigned char *) (rjpeg__err(x,y)?NULL:NULL)) static int rjpeg__vertically_flip_on_load = 0; static unsigned char *rjpeg__load_flip(rjpeg__context *s, unsigned *x, unsigned *y, int *comp, int req_comp) { unsigned char *result = rjpeg__jpeg_load(s,x,y,comp,req_comp); if (rjpeg__vertically_flip_on_load && result != NULL) { int row,col,z; int w = *x, h = *y; int depth = req_comp ? req_comp : *comp; for (row = 0; row < (h>>1); row++) { for (col = 0; col < w; col++) { for (z = 0; z < depth; z++) { uint8_t temp = result[(row * w + col) * depth + z]; result[(row * w + col) * depth + z] = result[((h - row - 1) * w + col) * depth + z]; result[((h - row - 1) * w + col) * depth + z] = temp; } } } } return result; } static uint8_t *rjpeg_load_from_memory(const uint8_t *buffer, int len, unsigned *x, unsigned *y, int *comp, int req_comp) { rjpeg__context s; s.io.read = NULL; s.read_from_callbacks = 0; s.img_buffer = s.img_buffer_original = (uint8_t *) buffer; s.img_buffer_end = (uint8_t *) buffer+len; return rjpeg__load_flip(&s,x,y,comp,req_comp); } enum { RJPEG_SCAN_LOAD = 0, RJPEG_SCAN_TYPE, RJPEG_SCAN_HEADER }; static void rjpeg__refill_buffer(rjpeg__context *s) { int n = (s->io.read)(s->io_user_data,(char*)s->buffer_start,s->buflen); if (n == 0) { /* at end of file, treat same as if from memory, but need to handle case * where s->img_buffer isn't pointing to safe memory, e.g. 0-byte file */ s->read_from_callbacks = 0; s->img_buffer = s->buffer_start; s->img_buffer_end = s->buffer_start+1; *s->img_buffer = 0; } else { s->img_buffer = s->buffer_start; s->img_buffer_end = s->buffer_start + n; } } static INLINE uint8_t rjpeg__get8(rjpeg__context *s) { if (s->img_buffer < s->img_buffer_end) return *s->img_buffer++; if (s->read_from_callbacks) { rjpeg__refill_buffer(s); return *s->img_buffer++; } return 0; } static INLINE int rjpeg__at_eof(rjpeg__context *s) { if (s->io.read) { if (!(s->io.eof)(s->io_user_data)) return 0; /* if feof() is true, check if buffer = end * special case: we've only got the special * 0 character at the end */ if (s->read_from_callbacks == 0) return 1; } return s->img_buffer >= s->img_buffer_end; } static void rjpeg__skip(rjpeg__context *s, int n) { if (n < 0) { s->img_buffer = s->img_buffer_end; return; } if (s->io.read) { int blen = (int) (s->img_buffer_end - s->img_buffer); if (blen < n) { s->img_buffer = s->img_buffer_end; (s->io.skip)(s->io_user_data, n - blen); return; } } s->img_buffer += n; } static int rjpeg__get16be(rjpeg__context *s) { int z = rjpeg__get8(s); return (z << 8) + rjpeg__get8(s); } #define RJPEG__BYTECAST(x) ((uint8_t) ((x) & 255)) /* truncate int to byte without warnings */ /* huffman decoding acceleration */ #define FAST_BITS 9 /* larger handles more cases; smaller stomps less cache */ typedef struct { uint8_t fast[1 << FAST_BITS]; /* weirdly, repacking this into AoS is a 10% speed loss, instead of a win */ uint16_t code[256]; uint8_t values[256]; uint8_t size[257]; unsigned int maxcode[18]; int delta[17]; /* old 'firstsymbol' - old 'firstcode' */ } rjpeg__huffman; typedef struct { rjpeg__context *s; rjpeg__huffman huff_dc[4]; rjpeg__huffman huff_ac[4]; uint8_t dequant[4][64]; int16_t fast_ac[4][1 << FAST_BITS]; /* sizes for components, interleaved MCUs */ int img_h_max, img_v_max; int img_mcu_x, img_mcu_y; int img_mcu_w, img_mcu_h; /* definition of jpeg image component */ struct { int id; int h,v; int tq; int hd,ha; int dc_pred; int x,y,w2,h2; uint8_t *data; void *raw_data, *raw_coeff; uint8_t *linebuf; short *coeff; /* progressive only */ int coeff_w, coeff_h; /* number of 8x8 coefficient blocks */ } img_comp[4]; uint32_t code_buffer; /* jpeg entropy-coded buffer */ int code_bits; /* number of valid bits */ unsigned char marker; /* marker seen while filling entropy buffer */ int nomore; /* flag if we saw a marker so must stop */ int progressive; int spec_start; int spec_end; int succ_high; int succ_low; int eob_run; int scan_n, order[4]; int restart_interval, todo; /* kernels */ void (*idct_block_kernel)(uint8_t *out, int out_stride, short data[64]); void (*YCbCr_to_RGB_kernel)(uint8_t *out, const uint8_t *y, const uint8_t *pcb, const uint8_t *pcr, int count, int step); uint8_t *(*resample_row_hv_2_kernel)(uint8_t *out, uint8_t *in_near, uint8_t *in_far, int w, int hs); } rjpeg__jpeg; #define rjpeg__f2f(x) ((int) (((x) * 4096 + 0.5))) #define rjpeg__fsh(x) ((x) << 12) #define RJPEG__MARKER_none 0xff /* if there's a pending marker from the entropy stream, return that * otherwise, fetch from the stream and get a marker. if there's no * marker, return 0xff, which is never a valid marker value */ /* in each scan, we'll have scan_n components, and the order * of the components is specified by order[] */ #define RJPEG__RESTART(x) ((x) >= 0xd0 && (x) <= 0xd7) /* use comparisons since in some cases we handle more than one case (e.g. SOF) */ #define rjpeg__SOI(x) ((x) == 0xd8) #define rjpeg__EOI(x) ((x) == 0xd9) #define rjpeg__SOF(x) ((x) == 0xc0 || (x) == 0xc1 || (x) == 0xc2) #define rjpeg__SOS(x) ((x) == 0xda) #define rjpeg__SOF_progressive(x) ((x) == 0xc2) #define rjpeg__div4(x) ((uint8_t) ((x) >> 2)) #define rjpeg__div16(x) ((uint8_t) ((x) >> 4)) static int rjpeg__build_huffman(rjpeg__huffman *h, int *count) { int i,j,k=0,code; /* build size list for each symbol (from JPEG spec) */ for (i=0; i < 16; ++i) for (j=0; j < count[i]; ++j) h->size[k++] = (uint8_t) (i+1); h->size[k] = 0; /* compute actual symbols (from jpeg spec) */ code = 0; k = 0; for(j=1; j <= 16; ++j) { /* compute delta to add to code to compute symbol id */ h->delta[j] = k - code; if (h->size[k] == j) { while (h->size[k] == j) h->code[k++] = (uint16_t) (code++); if (code-1 >= (1 << j)) return rjpeg__err("bad code lengths","Corrupt JPEG"); } /* compute largest code + 1 for this size, preshifted as needed later */ h->maxcode[j] = code << (16-j); code <<= 1; } h->maxcode[j] = 0xffffffff; /* build non-spec acceleration table; 255 is flag for not-accelerated */ memset(h->fast, 255, 1 << FAST_BITS); for (i=0; i < k; ++i) { int s = h->size[i]; if (s <= FAST_BITS) { int c = h->code[i] << (FAST_BITS-s); int m = 1 << (FAST_BITS-s); for (j=0; j < m; ++j) h->fast[c+j] = (uint8_t) i; } } return 1; } /* build a table that decodes both magnitude and value of small ACs in * one go. */ static void rjpeg__build_fast_ac(int16_t *fast_ac, rjpeg__huffman *h) { int i; for (i=0; i < (1 << FAST_BITS); ++i) { uint8_t fast = h->fast[i]; fast_ac[i] = 0; if (fast < 255) { int rs = h->values[fast]; int run = (rs >> 4) & 15; int magbits = rs & 15; int len = h->size[fast]; if (magbits && len + magbits <= FAST_BITS) { /* magnitude code followed by receive_extend code */ int k = ((i << len) & ((1 << FAST_BITS) - 1)) >> (FAST_BITS - magbits); int m = 1 << (magbits - 1); if (k < m) k += (-1 << magbits) + 1; /* if the result is small enough, we can fit it in fast_ac table */ if (k >= -128 && k <= 127) fast_ac[i] = (int16_t) ((k << 8) + (run << 4) + (len + magbits)); } } } } static void rjpeg__grow_buffer_unsafe(rjpeg__jpeg *j) { do { int b = j->nomore ? 0 : rjpeg__get8(j->s); if (b == 0xff) { int c = rjpeg__get8(j->s); if (c != 0) { j->marker = (unsigned char) c; j->nomore = 1; return; } } j->code_buffer |= b << (24 - j->code_bits); j->code_bits += 8; } while (j->code_bits <= 24); } /* (1 << n) - 1 */ static uint32_t rjpeg__bmask[17]={0,1,3,7,15,31,63,127,255,511,1023,2047,4095,8191,16383,32767,65535}; /* decode a JPEG huffman value from the bitstream */ static INLINE int rjpeg__jpeg_huff_decode(rjpeg__jpeg *j, rjpeg__huffman *h) { unsigned int temp; int c,k; if (j->code_bits < 16) rjpeg__grow_buffer_unsafe(j); /* look at the top FAST_BITS and determine what symbol ID it is, * if the code is <= FAST_BITS */ c = (j->code_buffer >> (32 - FAST_BITS)) & ((1 << FAST_BITS)-1); k = h->fast[c]; if (k < 255) { int s = h->size[k]; if (s > j->code_bits) return -1; j->code_buffer <<= s; j->code_bits -= s; return h->values[k]; } /* naive test is to shift the code_buffer down so k bits are * valid, then test against maxcode. To speed this up, we've * preshifted maxcode left so that it has (16-k) 0s at the * end; in other words, regardless of the number of bits, it * wants to be compared against something shifted to have 16; * that way we don't need to shift inside the loop. */ temp = j->code_buffer >> 16; for (k=FAST_BITS+1 ; ; ++k) if (temp < h->maxcode[k]) break; if (k == 17) { /* error! code not found */ j->code_bits -= 16; return -1; } if (k > j->code_bits) return -1; /* convert the huffman code to the symbol id */ c = ((j->code_buffer >> (32 - k)) & rjpeg__bmask[k]) + h->delta[k]; assert((((j->code_buffer) >> (32 - h->size[c])) & rjpeg__bmask[h->size[c]]) == h->code[c]); /* convert the id to a symbol */ j->code_bits -= k; j->code_buffer <<= k; return h->values[c]; } /* bias[n] = (-1<code_bits < n) rjpeg__grow_buffer_unsafe(j); sgn = (int32_t)j->code_buffer >> 31; /* sign bit is always in MSB */ k = rjpeg_lrot(j->code_buffer, n); assert(n >= 0 && n < (int) (sizeof(rjpeg__bmask)/sizeof(*rjpeg__bmask))); j->code_buffer = k & ~rjpeg__bmask[n]; k &= rjpeg__bmask[n]; j->code_bits -= n; return k + (rjpeg__jbias[n] & ~sgn); } /* get some unsigned bits */ static INLINE int rjpeg__jpeg_get_bits(rjpeg__jpeg *j, int n) { unsigned int k; if (j->code_bits < n) rjpeg__grow_buffer_unsafe(j); k = rjpeg_lrot(j->code_buffer, n); j->code_buffer = k & ~rjpeg__bmask[n]; k &= rjpeg__bmask[n]; j->code_bits -= n; return k; } static INLINE int rjpeg__jpeg_get_bit(rjpeg__jpeg *j) { unsigned int k; if (j->code_bits < 1) rjpeg__grow_buffer_unsafe(j); k = j->code_buffer; j->code_buffer <<= 1; --j->code_bits; return k & 0x80000000; } /* given a value that's at position X in the zigzag stream, * where does it appear in the 8x8 matrix coded as row-major? */ static uint8_t rjpeg__jpeg_dezigzag[64+15] = { 0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5, 12, 19, 26, 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28, 35, 42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51, 58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63, /* let corrupt input sample past end */ 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63 }; /* decode one 64-entry block-- */ static int rjpeg__jpeg_decode_block( rjpeg__jpeg *j, short data[64], rjpeg__huffman *hdc, rjpeg__huffman *hac, int16_t *fac, int b, uint8_t *dequant) { int diff,dc,k; int t; if (j->code_bits < 16) rjpeg__grow_buffer_unsafe(j); t = rjpeg__jpeg_huff_decode(j, hdc); if (t < 0) return rjpeg__err("bad huffman code","Corrupt JPEG"); /* 0 all the ac values now so we can do it 32-bits at a time */ memset(data,0,64*sizeof(data[0])); diff = t ? rjpeg__extend_receive(j, t) : 0; dc = j->img_comp[b].dc_pred + diff; j->img_comp[b].dc_pred = dc; data[0] = (short) (dc * dequant[0]); /* decode AC components, see JPEG spec */ k = 1; do { unsigned int zig; int c,r,s; if (j->code_bits < 16) rjpeg__grow_buffer_unsafe(j); c = (j->code_buffer >> (32 - FAST_BITS)) & ((1 << FAST_BITS)-1); r = fac[c]; if (r) { /* fast-AC path */ k += (r >> 4) & 15; /* run */ s = r & 15; /* combined length */ j->code_buffer <<= s; j->code_bits -= s; /* decode into unzigzag'd location */ zig = rjpeg__jpeg_dezigzag[k++]; data[zig] = (short) ((r >> 8) * dequant[zig]); } else { int rs = rjpeg__jpeg_huff_decode(j, hac); if (rs < 0) return rjpeg__err("bad huffman code","Corrupt JPEG"); s = rs & 15; r = rs >> 4; if (s == 0) { if (rs != 0xf0) break; /* end block */ k += 16; } else { k += r; /* decode into unzigzag'd location */ zig = rjpeg__jpeg_dezigzag[k++]; data[zig] = (short) (rjpeg__extend_receive(j,s) * dequant[zig]); } } } while (k < 64); return 1; } static int rjpeg__jpeg_decode_block_prog_dc( rjpeg__jpeg *j, short data[64], rjpeg__huffman *hdc, int b) { if (j->spec_end != 0) return rjpeg__err("can't merge dc and ac", "Corrupt JPEG"); if (j->code_bits < 16) rjpeg__grow_buffer_unsafe(j); if (j->succ_high == 0) { int t; int diff,dc; /* first scan for DC coefficient, must be first */ memset(data,0,64*sizeof(data[0])); /* 0 all the ac values now */ t = rjpeg__jpeg_huff_decode(j, hdc); diff = t ? rjpeg__extend_receive(j, t) : 0; dc = j->img_comp[b].dc_pred + diff; j->img_comp[b].dc_pred = dc; data[0] = (short) (dc << j->succ_low); } else { /* refinement scan for DC coefficient */ if (rjpeg__jpeg_get_bit(j)) data[0] += (short) (1 << j->succ_low); } return 1; } static int rjpeg__jpeg_decode_block_prog_ac( rjpeg__jpeg *j, short data[64], rjpeg__huffman *hac, int16_t *fac) { int k; if (j->spec_start == 0) return rjpeg__err("can't merge dc and ac", "Corrupt JPEG"); if (j->succ_high == 0) { int shift = j->succ_low; if (j->eob_run) { --j->eob_run; return 1; } k = j->spec_start; do { unsigned int zig; int c,r,s; if (j->code_bits < 16) rjpeg__grow_buffer_unsafe(j); c = (j->code_buffer >> (32 - FAST_BITS)) & ((1 << FAST_BITS)-1); r = fac[c]; if (r) { /* fast-AC path */ k += (r >> 4) & 15; /* run */ s = r & 15; /* combined length */ j->code_buffer <<= s; j->code_bits -= s; zig = rjpeg__jpeg_dezigzag[k++]; data[zig] = (short) ((r >> 8) << shift); } else { int rs = rjpeg__jpeg_huff_decode(j, hac); if (rs < 0) return rjpeg__err("bad huffman code","Corrupt JPEG"); s = rs & 15; r = rs >> 4; if (s == 0) { if (r < 15) { j->eob_run = (1 << r); if (r) j->eob_run += rjpeg__jpeg_get_bits(j, r); --j->eob_run; break; } k += 16; } else { k += r; zig = rjpeg__jpeg_dezigzag[k++]; data[zig] = (short) (rjpeg__extend_receive(j,s) << shift); } } } while (k <= j->spec_end); } else { /* refinement scan for these AC coefficients */ short bit = (short) (1 << j->succ_low); if (j->eob_run) { --j->eob_run; for (k = j->spec_start; k <= j->spec_end; ++k) { short *p = &data[rjpeg__jpeg_dezigzag[k]]; if (*p != 0) if (rjpeg__jpeg_get_bit(j)) if ((*p & bit)==0) { if (*p > 0) *p += bit; else *p -= bit; } } } else { k = j->spec_start; do { int r,s; int rs = rjpeg__jpeg_huff_decode(j, hac); if (rs < 0) return rjpeg__err("bad huffman code","Corrupt JPEG"); s = rs & 15; r = rs >> 4; if (s == 0) { if (r < 15) { j->eob_run = (1 << r) - 1; if (r) j->eob_run += rjpeg__jpeg_get_bits(j, r); r = 64; /* force end of block */ } else { /* r=15 s=0 should write 16 0s, so we just do * a run of 15 0s and then write s (which is 0), * so we don't have to do anything special here */ } } else { if (s != 1) return rjpeg__err("bad huffman code", "Corrupt JPEG"); /* sign bit */ if (rjpeg__jpeg_get_bit(j)) s = bit; else s = -bit; } /* advance by r */ while (k <= j->spec_end) { short *p = &data[rjpeg__jpeg_dezigzag[k++]]; if (*p != 0) { if (rjpeg__jpeg_get_bit(j)) if ((*p & bit)==0) { if (*p > 0) *p += bit; else *p -= bit; } } else { if (r == 0) { *p = (short) s; break; } --r; } } } while (k <= j->spec_end); } } return 1; } /* take a -128..127 value and rjpeg__clamp it and convert to 0..255 */ static INLINE uint8_t rjpeg__clamp(int x) { /* trick to use a single test to catch both cases */ if ((unsigned int) x > 255) return 255; return (uint8_t) x; } /* derived from jidctint -- DCT_ISLOW */ #define RJPEG__IDCT_1D(s0,s1,s2,s3,s4,s5,s6,s7) \ int t0,t1,t2,t3,p1,p2,p3,p4,p5,x0,x1,x2,x3; \ p2 = s2; \ p3 = s6; \ p1 = (p2+p3) * rjpeg__f2f(0.5411961f); \ t2 = p1 + p3*rjpeg__f2f(-1.847759065f); \ t3 = p1 + p2*rjpeg__f2f( 0.765366865f); \ p2 = s0; \ p3 = s4; \ t0 = rjpeg__fsh(p2+p3); \ t1 = rjpeg__fsh(p2-p3); \ x0 = t0+t3; \ x3 = t0-t3; \ x1 = t1+t2; \ x2 = t1-t2; \ t0 = s7; \ t1 = s5; \ t2 = s3; \ t3 = s1; \ p3 = t0+t2; \ p4 = t1+t3; \ p1 = t0+t3; \ p2 = t1+t2; \ p5 = (p3+p4)*rjpeg__f2f( 1.175875602f); \ t0 = t0*rjpeg__f2f( 0.298631336f); \ t1 = t1*rjpeg__f2f( 2.053119869f); \ t2 = t2*rjpeg__f2f( 3.072711026f); \ t3 = t3*rjpeg__f2f( 1.501321110f); \ p1 = p5 + p1*rjpeg__f2f(-0.899976223f); \ p2 = p5 + p2*rjpeg__f2f(-2.562915447f); \ p3 = p3*rjpeg__f2f(-1.961570560f); \ p4 = p4*rjpeg__f2f(-0.390180644f); \ t3 += p1+p4; \ t2 += p2+p3; \ t1 += p2+p4; \ t0 += p1+p3; static void rjpeg__idct_block(uint8_t *out, int out_stride, short data[64]) { int i,val[64],*v=val; uint8_t *o = NULL; int16_t *d = data; /* columns */ for (i=0; i < 8; ++i,++d, ++v) { /* if all zeroes, shortcut -- this avoids dequantizing 0s and IDCTing */ if (d[ 8]==0 && d[16]==0 && d[24]==0 && d[32]==0 && d[40]==0 && d[48]==0 && d[56]==0) { /* no shortcut 0 seconds * (1|2|3|4|5|6|7)==0 0 seconds * all separate -0.047 seconds * 1 && 2|3 && 4|5 && 6|7: -0.047 seconds */ int dcterm = d[0] << 2; v[0] = v[8] = v[16] = v[24] = v[32] = v[40] = v[48] = v[56] = dcterm; } else { RJPEG__IDCT_1D(d[ 0],d[ 8],d[16],d[24],d[32],d[40],d[48],d[56]) /* constants scaled things up by 1<<12; let's bring them back * down, but keep 2 extra bits of precision */ x0 += 512; x1 += 512; x2 += 512; x3 += 512; v[ 0] = (x0+t3) >> 10; v[56] = (x0-t3) >> 10; v[ 8] = (x1+t2) >> 10; v[48] = (x1-t2) >> 10; v[16] = (x2+t1) >> 10; v[40] = (x2-t1) >> 10; v[24] = (x3+t0) >> 10; v[32] = (x3-t0) >> 10; } } for (i=0, v=val, o=out; i < 8; ++i,v+=8,o+=out_stride) { /* no fast case since the first 1D IDCT spread components out */ RJPEG__IDCT_1D(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7]) /* constants scaled things up by 1<<12, plus we had 1<<2 from first * loop, plus horizontal and vertical each scale by sqrt(8) so together * we've got an extra 1<<3, so 1<<17 total we need to remove. * so we want to round that, which means adding 0.5 * 1<<17, * aka 65536. Also, we'll end up with -128 to 127 that we want * to encode as 0..255 by adding 128, so we'll add that before the shift */ x0 += 65536 + (128<<17); x1 += 65536 + (128<<17); x2 += 65536 + (128<<17); x3 += 65536 + (128<<17); /* tried computing the shifts into temps, or'ing the temps to see * if any were out of range, but that was slower */ o[0] = rjpeg__clamp((x0+t3) >> 17); o[7] = rjpeg__clamp((x0-t3) >> 17); o[1] = rjpeg__clamp((x1+t2) >> 17); o[6] = rjpeg__clamp((x1-t2) >> 17); o[2] = rjpeg__clamp((x2+t1) >> 17); o[5] = rjpeg__clamp((x2-t1) >> 17); o[3] = rjpeg__clamp((x3+t0) >> 17); o[4] = rjpeg__clamp((x3-t0) >> 17); } } #if defined(__SSE2__) /* sse2 integer IDCT. not the fastest possible implementation but it * produces bit-identical results to the generic C version so it's * fully "transparent". */ static void rjpeg__idct_simd(uint8_t *out, int out_stride, short data[64]) { /* This is constructed to match our regular (generic) integer IDCT exactly. */ __m128i row0, row1, row2, row3, row4, row5, row6, row7; __m128i tmp; /* dot product constant: even elems=x, odd elems=y */ #define dct_const(x,y) _mm_setr_epi16((x),(y),(x),(y),(x),(y),(x),(y)) /* out(0) = c0[even]*x + c0[odd]*y (c0, x, y 16-bit, out 32-bit) * out(1) = c1[even]*x + c1[odd]*y */ #define dct_rot(out0,out1, x,y,c0,c1) \ __m128i c0##lo = _mm_unpacklo_epi16((x),(y)); \ __m128i c0##hi = _mm_unpackhi_epi16((x),(y)); \ __m128i out0##_l = _mm_madd_epi16(c0##lo, c0); \ __m128i out0##_h = _mm_madd_epi16(c0##hi, c0); \ __m128i out1##_l = _mm_madd_epi16(c0##lo, c1); \ __m128i out1##_h = _mm_madd_epi16(c0##hi, c1) /* out = in << 12 (in 16-bit, out 32-bit) */ #define dct_widen(out, in) \ __m128i out##_l = _mm_srai_epi32(_mm_unpacklo_epi16(_mm_setzero_si128(), (in)), 4); \ __m128i out##_h = _mm_srai_epi32(_mm_unpackhi_epi16(_mm_setzero_si128(), (in)), 4) /* wide add */ #define dct_wadd(out, a, b) \ __m128i out##_l = _mm_add_epi32(a##_l, b##_l); \ __m128i out##_h = _mm_add_epi32(a##_h, b##_h) /* wide sub */ #define dct_wsub(out, a, b) \ __m128i out##_l = _mm_sub_epi32(a##_l, b##_l); \ __m128i out##_h = _mm_sub_epi32(a##_h, b##_h) /* butterfly a/b, add bias, then shift by "s" and pack */ #define dct_bfly32o(out0, out1, a,b,bias,s) \ { \ __m128i abiased_l = _mm_add_epi32(a##_l, bias); \ __m128i abiased_h = _mm_add_epi32(a##_h, bias); \ dct_wadd(sum, abiased, b); \ dct_wsub(dif, abiased, b); \ out0 = _mm_packs_epi32(_mm_srai_epi32(sum_l, s), _mm_srai_epi32(sum_h, s)); \ out1 = _mm_packs_epi32(_mm_srai_epi32(dif_l, s), _mm_srai_epi32(dif_h, s)); \ } /* 8-bit interleave step (for transposes) */ #define dct_interleave8(a, b) \ tmp = a; \ a = _mm_unpacklo_epi8(a, b); \ b = _mm_unpackhi_epi8(tmp, b) /* 16-bit interleave step (for transposes) */ #define dct_interleave16(a, b) \ tmp = a; \ a = _mm_unpacklo_epi16(a, b); \ b = _mm_unpackhi_epi16(tmp, b) #define dct_pass(bias,shift) \ { \ /* even part */ \ dct_rot(t2e,t3e, row2,row6, rot0_0,rot0_1); \ __m128i sum04 = _mm_add_epi16(row0, row4); \ __m128i dif04 = _mm_sub_epi16(row0, row4); \ dct_widen(t0e, sum04); \ dct_widen(t1e, dif04); \ dct_wadd(x0, t0e, t3e); \ dct_wsub(x3, t0e, t3e); \ dct_wadd(x1, t1e, t2e); \ dct_wsub(x2, t1e, t2e); \ /* odd part */ \ dct_rot(y0o,y2o, row7,row3, rot2_0,rot2_1); \ dct_rot(y1o,y3o, row5,row1, rot3_0,rot3_1); \ __m128i sum17 = _mm_add_epi16(row1, row7); \ __m128i sum35 = _mm_add_epi16(row3, row5); \ dct_rot(y4o,y5o, sum17,sum35, rot1_0,rot1_1); \ dct_wadd(x4, y0o, y4o); \ dct_wadd(x5, y1o, y5o); \ dct_wadd(x6, y2o, y5o); \ dct_wadd(x7, y3o, y4o); \ dct_bfly32o(row0,row7, x0,x7,bias,shift); \ dct_bfly32o(row1,row6, x1,x6,bias,shift); \ dct_bfly32o(row2,row5, x2,x5,bias,shift); \ dct_bfly32o(row3,row4, x3,x4,bias,shift); \ } __m128i rot0_0 = dct_const(rjpeg__f2f(0.5411961f), rjpeg__f2f(0.5411961f) + rjpeg__f2f(-1.847759065f)); __m128i rot0_1 = dct_const(rjpeg__f2f(0.5411961f) + rjpeg__f2f( 0.765366865f), rjpeg__f2f(0.5411961f)); __m128i rot1_0 = dct_const(rjpeg__f2f(1.175875602f) + rjpeg__f2f(-0.899976223f), rjpeg__f2f(1.175875602f)); __m128i rot1_1 = dct_const(rjpeg__f2f(1.175875602f), rjpeg__f2f(1.175875602f) + rjpeg__f2f(-2.562915447f)); __m128i rot2_0 = dct_const(rjpeg__f2f(-1.961570560f) + rjpeg__f2f( 0.298631336f), rjpeg__f2f(-1.961570560f)); __m128i rot2_1 = dct_const(rjpeg__f2f(-1.961570560f), rjpeg__f2f(-1.961570560f) + rjpeg__f2f( 3.072711026f)); __m128i rot3_0 = dct_const(rjpeg__f2f(-0.390180644f) + rjpeg__f2f( 2.053119869f), rjpeg__f2f(-0.390180644f)); __m128i rot3_1 = dct_const(rjpeg__f2f(-0.390180644f), rjpeg__f2f(-0.390180644f) + rjpeg__f2f( 1.501321110f)); /* rounding biases in column/row passes, see rjpeg__idct_block for explanation. */ __m128i bias_0 = _mm_set1_epi32(512); __m128i bias_1 = _mm_set1_epi32(65536 + (128<<17)); /* load */ row0 = _mm_load_si128((const __m128i *) (data + 0*8)); row1 = _mm_load_si128((const __m128i *) (data + 1*8)); row2 = _mm_load_si128((const __m128i *) (data + 2*8)); row3 = _mm_load_si128((const __m128i *) (data + 3*8)); row4 = _mm_load_si128((const __m128i *) (data + 4*8)); row5 = _mm_load_si128((const __m128i *) (data + 5*8)); row6 = _mm_load_si128((const __m128i *) (data + 6*8)); row7 = _mm_load_si128((const __m128i *) (data + 7*8)); /* column pass */ dct_pass(bias_0, 10); { /* 16bit 8x8 transpose pass 1 */ dct_interleave16(row0, row4); dct_interleave16(row1, row5); dct_interleave16(row2, row6); dct_interleave16(row3, row7); /* transpose pass 2 */ dct_interleave16(row0, row2); dct_interleave16(row1, row3); dct_interleave16(row4, row6); dct_interleave16(row5, row7); /* transpose pass 3 */ dct_interleave16(row0, row1); dct_interleave16(row2, row3); dct_interleave16(row4, row5); dct_interleave16(row6, row7); } /* row pass */ dct_pass(bias_1, 17); { /* pack */ __m128i p0 = _mm_packus_epi16(row0, row1); /* a0a1a2a3...a7b0b1b2b3...b7 */ __m128i p1 = _mm_packus_epi16(row2, row3); __m128i p2 = _mm_packus_epi16(row4, row5); __m128i p3 = _mm_packus_epi16(row6, row7); /* 8bit 8x8 transpose pass 1 */ dct_interleave8(p0, p2); /* a0e0a1e1... */ dct_interleave8(p1, p3); /* c0g0c1g1... */ /* transpose pass 2 */ dct_interleave8(p0, p1); /* a0c0e0g0... */ dct_interleave8(p2, p3); /* b0d0f0h0... */ /* transpose pass 3 */ dct_interleave8(p0, p2); /* a0b0c0d0... */ dct_interleave8(p1, p3); /* a4b4c4d4... */ /* store */ _mm_storel_epi64((__m128i *) out, p0); out += out_stride; _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p0, 0x4e)); out += out_stride; _mm_storel_epi64((__m128i *) out, p2); out += out_stride; _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p2, 0x4e)); out += out_stride; _mm_storel_epi64((__m128i *) out, p1); out += out_stride; _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p1, 0x4e)); out += out_stride; _mm_storel_epi64((__m128i *) out, p3); out += out_stride; _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p3, 0x4e)); } #undef dct_const #undef dct_rot #undef dct_widen #undef dct_wadd #undef dct_wsub #undef dct_bfly32o #undef dct_interleave8 #undef dct_interleave16 #undef dct_pass } #endif #ifdef RJPEG_NEON /* NEON integer IDCT. should produce bit-identical * results to the generic C version. */ static void rjpeg__idct_simd(uint8_t *out, int out_stride, short data[64]) { int16x8_t row0, row1, row2, row3, row4, row5, row6, row7; int16x4_t rot0_0 = vdup_n_s16(rjpeg__f2f(0.5411961f)); int16x4_t rot0_1 = vdup_n_s16(rjpeg__f2f(-1.847759065f)); int16x4_t rot0_2 = vdup_n_s16(rjpeg__f2f( 0.765366865f)); int16x4_t rot1_0 = vdup_n_s16(rjpeg__f2f( 1.175875602f)); int16x4_t rot1_1 = vdup_n_s16(rjpeg__f2f(-0.899976223f)); int16x4_t rot1_2 = vdup_n_s16(rjpeg__f2f(-2.562915447f)); int16x4_t rot2_0 = vdup_n_s16(rjpeg__f2f(-1.961570560f)); int16x4_t rot2_1 = vdup_n_s16(rjpeg__f2f(-0.390180644f)); int16x4_t rot3_0 = vdup_n_s16(rjpeg__f2f( 0.298631336f)); int16x4_t rot3_1 = vdup_n_s16(rjpeg__f2f( 2.053119869f)); int16x4_t rot3_2 = vdup_n_s16(rjpeg__f2f( 3.072711026f)); int16x4_t rot3_3 = vdup_n_s16(rjpeg__f2f( 1.501321110f)); #define dct_long_mul(out, inq, coeff) \ int32x4_t out##_l = vmull_s16(vget_low_s16(inq), coeff); \ int32x4_t out##_h = vmull_s16(vget_high_s16(inq), coeff) #define dct_long_mac(out, acc, inq, coeff) \ int32x4_t out##_l = vmlal_s16(acc##_l, vget_low_s16(inq), coeff); \ int32x4_t out##_h = vmlal_s16(acc##_h, vget_high_s16(inq), coeff) #define dct_widen(out, inq) \ int32x4_t out##_l = vshll_n_s16(vget_low_s16(inq), 12); \ int32x4_t out##_h = vshll_n_s16(vget_high_s16(inq), 12) /* wide add */ #define dct_wadd(out, a, b) \ int32x4_t out##_l = vaddq_s32(a##_l, b##_l); \ int32x4_t out##_h = vaddq_s32(a##_h, b##_h) /* wide sub */ #define dct_wsub(out, a, b) \ int32x4_t out##_l = vsubq_s32(a##_l, b##_l); \ int32x4_t out##_h = vsubq_s32(a##_h, b##_h) /* butterfly a/b, then shift using "shiftop" by "s" and pack */ #define dct_bfly32o(out0,out1, a,b,shiftop,s) \ { \ dct_wadd(sum, a, b); \ dct_wsub(dif, a, b); \ out0 = vcombine_s16(shiftop(sum_l, s), shiftop(sum_h, s)); \ out1 = vcombine_s16(shiftop(dif_l, s), shiftop(dif_h, s)); \ } #define dct_pass(shiftop, shift) \ { \ /* even part */ \ int16x8_t sum26 = vaddq_s16(row2, row6); \ dct_long_mul(p1e, sum26, rot0_0); \ dct_long_mac(t2e, p1e, row6, rot0_1); \ dct_long_mac(t3e, p1e, row2, rot0_2); \ int16x8_t sum04 = vaddq_s16(row0, row4); \ int16x8_t dif04 = vsubq_s16(row0, row4); \ dct_widen(t0e, sum04); \ dct_widen(t1e, dif04); \ dct_wadd(x0, t0e, t3e); \ dct_wsub(x3, t0e, t3e); \ dct_wadd(x1, t1e, t2e); \ dct_wsub(x2, t1e, t2e); \ /* odd part */ \ int16x8_t sum15 = vaddq_s16(row1, row5); \ int16x8_t sum17 = vaddq_s16(row1, row7); \ int16x8_t sum35 = vaddq_s16(row3, row5); \ int16x8_t sum37 = vaddq_s16(row3, row7); \ int16x8_t sumodd = vaddq_s16(sum17, sum35); \ dct_long_mul(p5o, sumodd, rot1_0); \ dct_long_mac(p1o, p5o, sum17, rot1_1); \ dct_long_mac(p2o, p5o, sum35, rot1_2); \ dct_long_mul(p3o, sum37, rot2_0); \ dct_long_mul(p4o, sum15, rot2_1); \ dct_wadd(sump13o, p1o, p3o); \ dct_wadd(sump24o, p2o, p4o); \ dct_wadd(sump23o, p2o, p3o); \ dct_wadd(sump14o, p1o, p4o); \ dct_long_mac(x4, sump13o, row7, rot3_0); \ dct_long_mac(x5, sump24o, row5, rot3_1); \ dct_long_mac(x6, sump23o, row3, rot3_2); \ dct_long_mac(x7, sump14o, row1, rot3_3); \ dct_bfly32o(row0,row7, x0,x7,shiftop,shift); \ dct_bfly32o(row1,row6, x1,x6,shiftop,shift); \ dct_bfly32o(row2,row5, x2,x5,shiftop,shift); \ dct_bfly32o(row3,row4, x3,x4,shiftop,shift); \ } /* load */ row0 = vld1q_s16(data + 0*8); row1 = vld1q_s16(data + 1*8); row2 = vld1q_s16(data + 2*8); row3 = vld1q_s16(data + 3*8); row4 = vld1q_s16(data + 4*8); row5 = vld1q_s16(data + 5*8); row6 = vld1q_s16(data + 6*8); row7 = vld1q_s16(data + 7*8); /* add DC bias */ row0 = vaddq_s16(row0, vsetq_lane_s16(1024, vdupq_n_s16(0), 0)); /* column pass */ dct_pass(vrshrn_n_s32, 10); /* 16bit 8x8 transpose */ { /* these three map to a single VTRN.16, VTRN.32, and VSWP, respectively. * whether compilers actually get this is another story, sadly. */ #define dct_trn16(x, y) { int16x8x2_t t = vtrnq_s16(x, y); x = t.val[0]; y = t.val[1]; } #define dct_trn32(x, y) { int32x4x2_t t = vtrnq_s32(vreinterpretq_s32_s16(x), vreinterpretq_s32_s16(y)); x = vreinterpretq_s16_s32(t.val[0]); y = vreinterpretq_s16_s32(t.val[1]); } #define dct_trn64(x, y) { int16x8_t x0 = x; int16x8_t y0 = y; x = vcombine_s16(vget_low_s16(x0), vget_low_s16(y0)); y = vcombine_s16(vget_high_s16(x0), vget_high_s16(y0)); } /* pass 1 */ dct_trn16(row0, row1); /* a0b0a2b2a4b4a6b6 */ dct_trn16(row2, row3); dct_trn16(row4, row5); dct_trn16(row6, row7); /* pass 2 */ dct_trn32(row0, row2); /* a0b0c0d0a4b4c4d4 */ dct_trn32(row1, row3); dct_trn32(row4, row6); dct_trn32(row5, row7); /* pass 3 */ dct_trn64(row0, row4); /* a0b0c0d0e0f0g0h0 */ dct_trn64(row1, row5); dct_trn64(row2, row6); dct_trn64(row3, row7); #undef dct_trn16 #undef dct_trn32 #undef dct_trn64 } /* row pass * vrshrn_n_s32 only supports shifts up to 16, we need * 17. so do a non-rounding shift of 16 first then follow * up with a rounding shift by 1. */ dct_pass(vshrn_n_s32, 16); { /* pack and round */ uint8x8_t p0 = vqrshrun_n_s16(row0, 1); uint8x8_t p1 = vqrshrun_n_s16(row1, 1); uint8x8_t p2 = vqrshrun_n_s16(row2, 1); uint8x8_t p3 = vqrshrun_n_s16(row3, 1); uint8x8_t p4 = vqrshrun_n_s16(row4, 1); uint8x8_t p5 = vqrshrun_n_s16(row5, 1); uint8x8_t p6 = vqrshrun_n_s16(row6, 1); uint8x8_t p7 = vqrshrun_n_s16(row7, 1); /* again, these can translate into one instruction, but often don't. */ #define dct_trn8_8(x, y) { uint8x8x2_t t = vtrn_u8(x, y); x = t.val[0]; y = t.val[1]; } #define dct_trn8_16(x, y) { uint16x4x2_t t = vtrn_u16(vreinterpret_u16_u8(x), vreinterpret_u16_u8(y)); x = vreinterpret_u8_u16(t.val[0]); y = vreinterpret_u8_u16(t.val[1]); } #define dct_trn8_32(x, y) { uint32x2x2_t t = vtrn_u32(vreinterpret_u32_u8(x), vreinterpret_u32_u8(y)); x = vreinterpret_u8_u32(t.val[0]); y = vreinterpret_u8_u32(t.val[1]); } /* sadly can't use interleaved stores here since we only write * 8 bytes to each scan line! */ /* 8x8 8-bit transpose pass 1 */ dct_trn8_8(p0, p1); dct_trn8_8(p2, p3); dct_trn8_8(p4, p5); dct_trn8_8(p6, p7); /* pass 2 */ dct_trn8_16(p0, p2); dct_trn8_16(p1, p3); dct_trn8_16(p4, p6); dct_trn8_16(p5, p7); /* pass 3 */ dct_trn8_32(p0, p4); dct_trn8_32(p1, p5); dct_trn8_32(p2, p6); dct_trn8_32(p3, p7); /* store */ vst1_u8(out, p0); out += out_stride; vst1_u8(out, p1); out += out_stride; vst1_u8(out, p2); out += out_stride; vst1_u8(out, p3); out += out_stride; vst1_u8(out, p4); out += out_stride; vst1_u8(out, p5); out += out_stride; vst1_u8(out, p6); out += out_stride; vst1_u8(out, p7); #undef dct_trn8_8 #undef dct_trn8_16 #undef dct_trn8_32 } #undef dct_long_mul #undef dct_long_mac #undef dct_widen #undef dct_wadd #undef dct_wsub #undef dct_bfly32o #undef dct_pass } #endif /* RJPEG_NEON */ static uint8_t rjpeg__get_marker(rjpeg__jpeg *j) { uint8_t x; if (j->marker != RJPEG__MARKER_none) { x = j->marker; j->marker = RJPEG__MARKER_none; return x; } x = rjpeg__get8(j->s); if (x != 0xff) return RJPEG__MARKER_none; while (x == 0xff) x = rjpeg__get8(j->s); return x; } /* after a restart interval, rjpeg__jpeg_reset the entropy decoder and * the dc prediction */ static void rjpeg__jpeg_reset(rjpeg__jpeg *j) { j->code_bits = 0; j->code_buffer = 0; j->nomore = 0; j->img_comp[0].dc_pred = j->img_comp[1].dc_pred = j->img_comp[2].dc_pred = 0; j->marker = RJPEG__MARKER_none; j->todo = j->restart_interval ? j->restart_interval : 0x7fffffff; j->eob_run = 0; /* no more than 1<<31 MCUs if no restart_interal? that's plenty safe, * since we don't even allow 1<<30 pixels */ } static int rjpeg__parse_entropy_coded_data(rjpeg__jpeg *z) { rjpeg__jpeg_reset(z); if (!z->progressive) { if (z->scan_n == 1) { int i,j; RJPEG_SIMD_ALIGN(short, data[64]); int n = z->order[0]; /* non-interleaved data, we just need to process one block at a time, * in trivial scanline order * number of blocks to do just depends on how many actual "pixels" this * component has, independent of interleaved MCU blocking and such */ int w = (z->img_comp[n].x+7) >> 3; int h = (z->img_comp[n].y+7) >> 3; for (j=0; j < h; ++j) { for (i=0; i < w; ++i) { int ha = z->img_comp[n].ha; if (!rjpeg__jpeg_decode_block(z, data, z->huff_dc+z->img_comp[n].hd, z->huff_ac+ha, z->fast_ac[ha], n, z->dequant[z->img_comp[n].tq])) return 0; z->idct_block_kernel(z->img_comp[n].data+z->img_comp[n].w2*j*8+i*8, z->img_comp[n].w2, data); /* every data block is an MCU, so countdown the restart interval */ if (--z->todo <= 0) { if (z->code_bits < 24) rjpeg__grow_buffer_unsafe(z); /* if it's NOT a restart, then just bail, * so we get corrupt data rather than no data */ if (!RJPEG__RESTART(z->marker)) return 1; rjpeg__jpeg_reset(z); } } } } else { /* interleaved */ int i,j,k,x,y; RJPEG_SIMD_ALIGN(short, data[64]); for (j=0; j < z->img_mcu_y; ++j) { for (i=0; i < z->img_mcu_x; ++i) { /* scan an interleaved mcu... * process scan_n components in order */ for (k=0; k < z->scan_n; ++k) { int n = z->order[k]; /* scan out an mcu's worth of this component; * that's just determined by the basic H * and V specified for the component */ for (y=0; y < z->img_comp[n].v; ++y) { for (x=0; x < z->img_comp[n].h; ++x) { int x2 = (i*z->img_comp[n].h + x)*8; int y2 = (j*z->img_comp[n].v + y)*8; int ha = z->img_comp[n].ha; if (!rjpeg__jpeg_decode_block(z, data, z->huff_dc+z->img_comp[n].hd, z->huff_ac+ha, z->fast_ac[ha], n, z->dequant[z->img_comp[n].tq])) return 0; z->idct_block_kernel(z->img_comp[n].data+z->img_comp[n].w2*y2+x2, z->img_comp[n].w2, data); } } } /* after all interleaved components, that's an interleaved MCU, * so now count down the restart interval */ if (--z->todo <= 0) { if (z->code_bits < 24) rjpeg__grow_buffer_unsafe(z); if (!RJPEG__RESTART(z->marker)) return 1; rjpeg__jpeg_reset(z); } } } } return 1; } else { if (z->scan_n == 1) { int i,j; int n = z->order[0]; int w = (z->img_comp[n].x+7) >> 3; int h = (z->img_comp[n].y+7) >> 3; /* non-interleaved data, we just need to process one block at a time, * in trivial scanline order * number of blocks to do just depends on how many actual "pixels" this * component has, independent of interleaved MCU blocking and such */ for (j=0; j < h; ++j) { for (i=0; i < w; ++i) { short *data = z->img_comp[n].coeff + 64 * (i + j * z->img_comp[n].coeff_w); if (z->spec_start == 0) { if (!rjpeg__jpeg_decode_block_prog_dc(z, data, &z->huff_dc[z->img_comp[n].hd], n)) return 0; } else { int ha = z->img_comp[n].ha; if (!rjpeg__jpeg_decode_block_prog_ac(z, data, &z->huff_ac[ha], z->fast_ac[ha])) return 0; } /* every data block is an MCU, so countdown the restart interval */ if (--z->todo <= 0) { if (z->code_bits < 24) rjpeg__grow_buffer_unsafe(z); if (!RJPEG__RESTART(z->marker)) return 1; rjpeg__jpeg_reset(z); } } } } else { /* interleaved */ int i,j,k,x,y; for (j=0; j < z->img_mcu_y; ++j) { for (i=0; i < z->img_mcu_x; ++i) { /* scan an interleaved MCU... process scan_n components in order */ for (k=0; k < z->scan_n; ++k) { int n = z->order[k]; /* scan out an MCU's worth of this component; that's just determined * by the basic H and V specified for the component */ for (y=0; y < z->img_comp[n].v; ++y) { for (x=0; x < z->img_comp[n].h; ++x) { int x2 = (i*z->img_comp[n].h + x); int y2 = (j*z->img_comp[n].v + y); short *data = z->img_comp[n].coeff + 64 * (x2 + y2 * z->img_comp[n].coeff_w); if (!rjpeg__jpeg_decode_block_prog_dc(z, data, &z->huff_dc[z->img_comp[n].hd], n)) return 0; } } } /* after all interleaved components, that's an interleaved MCU, * so now count down the restart interval */ if (--z->todo <= 0) { if (z->code_bits < 24) rjpeg__grow_buffer_unsafe(z); if (!RJPEG__RESTART(z->marker)) return 1; rjpeg__jpeg_reset(z); } } } } return 1; } } static void rjpeg__jpeg_dequantize(short *data, uint8_t *dequant) { int i; for (i=0; i < 64; ++i) data[i] *= dequant[i]; } static void rjpeg__jpeg_finish(rjpeg__jpeg *z) { if (z->progressive) { /* dequantize and IDCT the data */ int i,j,n; for (n=0; n < z->s->img_n; ++n) { int w = (z->img_comp[n].x+7) >> 3; int h = (z->img_comp[n].y+7) >> 3; for (j=0; j < h; ++j) { for (i=0; i < w; ++i) { short *data = z->img_comp[n].coeff + 64 * (i + j * z->img_comp[n].coeff_w); rjpeg__jpeg_dequantize(data, z->dequant[z->img_comp[n].tq]); z->idct_block_kernel(z->img_comp[n].data+z->img_comp[n].w2*j*8+i*8, z->img_comp[n].w2, data); } } } } } static int rjpeg__process_marker(rjpeg__jpeg *z, int m) { int L; switch (m) { case RJPEG__MARKER_none: /* no marker found */ return rjpeg__err("expected marker","Corrupt JPEG"); case 0xDD: /* DRI - specify restart interval */ if (rjpeg__get16be(z->s) != 4) return rjpeg__err("bad DRI len","Corrupt JPEG"); z->restart_interval = rjpeg__get16be(z->s); return 1; case 0xDB: /* DQT - define quantization table */ L = rjpeg__get16be(z->s)-2; while (L > 0) { int q = rjpeg__get8(z->s); int p = q >> 4; int t = q & 15,i; if (p != 0) return rjpeg__err("bad DQT type","Corrupt JPEG"); if (t > 3) return rjpeg__err("bad DQT table","Corrupt JPEG"); for (i=0; i < 64; ++i) z->dequant[t][rjpeg__jpeg_dezigzag[i]] = rjpeg__get8(z->s); L -= 65; } return L==0; case 0xC4: /* DHT - define huffman table */ L = rjpeg__get16be(z->s)-2; while (L > 0) { int sizes[16],i,n=0; uint8_t *v = NULL; int q = rjpeg__get8(z->s); int tc = q >> 4; int th = q & 15; if (tc > 1 || th > 3) return rjpeg__err("bad DHT header","Corrupt JPEG"); for (i=0; i < 16; ++i) { sizes[i] = rjpeg__get8(z->s); n += sizes[i]; } L -= 17; if (tc == 0) { if (!rjpeg__build_huffman(z->huff_dc+th, sizes)) return 0; v = z->huff_dc[th].values; } else { if (!rjpeg__build_huffman(z->huff_ac+th, sizes)) return 0; v = z->huff_ac[th].values; } for (i=0; i < n; ++i) v[i] = rjpeg__get8(z->s); if (tc != 0) rjpeg__build_fast_ac(z->fast_ac[th], z->huff_ac + th); L -= n; } return L==0; } /* check for comment block or APP blocks */ if ((m >= 0xE0 && m <= 0xEF) || m == 0xFE) { rjpeg__skip(z->s, rjpeg__get16be(z->s)-2); return 1; } return 0; } /* after we see SOS */ static int rjpeg__process_scan_header(rjpeg__jpeg *z) { int i; int Ls = rjpeg__get16be(z->s); z->scan_n = rjpeg__get8(z->s); if (z->scan_n < 1 || z->scan_n > 4 || z->scan_n > (int) z->s->img_n) return rjpeg__err("bad SOS component count","Corrupt JPEG"); if (Ls != 6+2*z->scan_n) return rjpeg__err("bad SOS len","Corrupt JPEG"); for (i=0; i < z->scan_n; ++i) { int id = rjpeg__get8(z->s), which; int q = rjpeg__get8(z->s); for (which = 0; which < z->s->img_n; ++which) if (z->img_comp[which].id == id) break; if (which == z->s->img_n) return 0; /* no match */ z->img_comp[which].hd = q >> 4; if (z->img_comp[which].hd > 3) return rjpeg__err("bad DC huff","Corrupt JPEG"); z->img_comp[which].ha = q & 15; if (z->img_comp[which].ha > 3) return rjpeg__err("bad AC huff","Corrupt JPEG"); z->order[i] = which; } { int aa; z->spec_start = rjpeg__get8(z->s); z->spec_end = rjpeg__get8(z->s); /* should be 63, but might be 0 */ aa = rjpeg__get8(z->s); z->succ_high = (aa >> 4); z->succ_low = (aa & 15); if (z->progressive) { if ( z->spec_start > 63 || z->spec_end > 63 || z->spec_start > z->spec_end || z->succ_high > 13 || z->succ_low > 13) return rjpeg__err("bad SOS", "Corrupt JPEG"); } else { if (z->spec_start != 0) return rjpeg__err("bad SOS","Corrupt JPEG"); if (z->succ_high != 0 || z->succ_low != 0) return rjpeg__err("bad SOS","Corrupt JPEG"); z->spec_end = 63; } } return 1; } static int rjpeg__process_frame_header(rjpeg__jpeg *z, int scan) { rjpeg__context *s = z->s; int Lf,p,i,q, h_max=1,v_max=1,c; Lf = rjpeg__get16be(s); /* JPEG */ if (Lf < 11) return rjpeg__err("bad SOF len","Corrupt JPEG"); p = rjpeg__get8(s); /* JPEG baseline */ if (p != 8) return rjpeg__err("only 8-bit","JPEG format not supported: 8-bit only"); s->img_y = rjpeg__get16be(s); /* Legal, but we don't handle it--but neither does IJG */ if (s->img_y == 0) return rjpeg__err("no header height", "JPEG format not supported: delayed height"); s->img_x = rjpeg__get16be(s); if (s->img_x == 0) return rjpeg__err("0 width","Corrupt JPEG"); /* JPEG requires */ c = rjpeg__get8(s); /* JFIF requires */ if (c != 3 && c != 1) return rjpeg__err("bad component count","Corrupt JPEG"); s->img_n = c; for (i=0; i < c; ++i) { z->img_comp[i].data = NULL; z->img_comp[i].linebuf = NULL; } if (Lf != 8+3*s->img_n) return rjpeg__err("bad SOF len","Corrupt JPEG"); for (i=0; i < s->img_n; ++i) { z->img_comp[i].id = rjpeg__get8(s); if (z->img_comp[i].id != i+1) /* JFIF requires */ if (z->img_comp[i].id != i) /* some version of jpegtran outputs non-JFIF-compliant files! */ return rjpeg__err("bad component ID","Corrupt JPEG"); q = rjpeg__get8(s); z->img_comp[i].h = (q >> 4); if (!z->img_comp[i].h || z->img_comp[i].h > 4) return rjpeg__err("bad H","Corrupt JPEG"); z->img_comp[i].v = q & 15; if (!z->img_comp[i].v || z->img_comp[i].v > 4) return rjpeg__err("bad V","Corrupt JPEG"); z->img_comp[i].tq = rjpeg__get8(s); if (z->img_comp[i].tq > 3) return rjpeg__err("bad TQ","Corrupt JPEG"); } if (scan != RJPEG_SCAN_LOAD) return 1; if ((1 << 30) / s->img_x / s->img_n < s->img_y) return rjpeg__err("too large", "Image too large to decode"); for (i=0; i < s->img_n; ++i) { if (z->img_comp[i].h > h_max) h_max = z->img_comp[i].h; if (z->img_comp[i].v > v_max) v_max = z->img_comp[i].v; } /* compute interleaved MCU info */ z->img_h_max = h_max; z->img_v_max = v_max; z->img_mcu_w = h_max * 8; z->img_mcu_h = v_max * 8; z->img_mcu_x = (s->img_x + z->img_mcu_w-1) / z->img_mcu_w; z->img_mcu_y = (s->img_y + z->img_mcu_h-1) / z->img_mcu_h; for (i=0; i < s->img_n; ++i) { /* number of effective pixels (e.g. for non-interleaved MCU) */ z->img_comp[i].x = (s->img_x * z->img_comp[i].h + h_max-1) / h_max; z->img_comp[i].y = (s->img_y * z->img_comp[i].v + v_max-1) / v_max; /* to simplify generation, we'll allocate enough memory to decode * the bogus oversized data from using interleaved MCUs and their * big blocks (e.g. a 16x16 iMCU on an image of width 33); we won't * discard the extra data until colorspace conversion */ z->img_comp[i].w2 = z->img_mcu_x * z->img_comp[i].h * 8; z->img_comp[i].h2 = z->img_mcu_y * z->img_comp[i].v * 8; z->img_comp[i].raw_data = malloc(z->img_comp[i].w2 * z->img_comp[i].h2+15); if (z->img_comp[i].raw_data == NULL) { for(--i; i >= 0; --i) { free(z->img_comp[i].raw_data); z->img_comp[i].data = NULL; } return rjpeg__err("outofmem", "Out of memory"); } /* align blocks for IDCT using MMX/SSE */ z->img_comp[i].data = (uint8_t*) (((size_t) z->img_comp[i].raw_data + 15) & ~15); z->img_comp[i].linebuf = NULL; if (z->progressive) { z->img_comp[i].coeff_w = (z->img_comp[i].w2 + 7) >> 3; z->img_comp[i].coeff_h = (z->img_comp[i].h2 + 7) >> 3; z->img_comp[i].raw_coeff = malloc(z->img_comp[i].coeff_w * z->img_comp[i].coeff_h * 64 * sizeof(short) + 15); z->img_comp[i].coeff = (short*) (((size_t) z->img_comp[i].raw_coeff + 15) & ~15); } else { z->img_comp[i].coeff = 0; z->img_comp[i].raw_coeff = 0; } } return 1; } static int rjpeg__decode_jpeg_header(rjpeg__jpeg *z, int scan) { int m; z->marker = RJPEG__MARKER_none; /* initialize cached marker to empty */ m = rjpeg__get_marker(z); if (!rjpeg__SOI(m)) return rjpeg__err("no SOI","Corrupt JPEG"); if (scan == RJPEG_SCAN_TYPE) return 1; m = rjpeg__get_marker(z); while (!rjpeg__SOF(m)) { if (!rjpeg__process_marker(z,m)) return 0; m = rjpeg__get_marker(z); while (m == RJPEG__MARKER_none) { /* some files have extra padding after their blocks, so ok, we'll scan */ if (rjpeg__at_eof(z->s)) return rjpeg__err("no SOF", "Corrupt JPEG"); m = rjpeg__get_marker(z); } } z->progressive = rjpeg__SOF_progressive(m); if (!rjpeg__process_frame_header(z, scan)) return 0; return 1; } /* decode image to YCbCr format */ static int rjpeg__decode_jpeg_image(rjpeg__jpeg *j) { int m; for (m = 0; m < 4; m++) { j->img_comp[m].raw_data = NULL; j->img_comp[m].raw_coeff = NULL; } j->restart_interval = 0; if (!rjpeg__decode_jpeg_header(j, RJPEG_SCAN_LOAD)) return 0; m = rjpeg__get_marker(j); while (!rjpeg__EOI(m)) { if (rjpeg__SOS(m)) { if (!rjpeg__process_scan_header(j)) return 0; if (!rjpeg__parse_entropy_coded_data(j)) return 0; if (j->marker == RJPEG__MARKER_none ) { /* handle 0s at the end of image data from IP Kamera 9060 */ while (!rjpeg__at_eof(j->s)) { int x = rjpeg__get8(j->s); if (x == 255) { j->marker = rjpeg__get8(j->s); break; } else if (x != 0) return rjpeg__err("junk before marker", "Corrupt JPEG"); } /* if we reach eof without hitting a marker, rjpeg__get_marker() below will fail and we'll eventually return 0 */ } } else { if (!rjpeg__process_marker(j, m)) return 0; } m = rjpeg__get_marker(j); } if (j->progressive) rjpeg__jpeg_finish(j); return 1; } /* static jfif-centered resampling (across block boundaries) */ static uint8_t *rjpeg_resample_row_1(uint8_t *out, uint8_t *in_near, uint8_t *in_far, int w, int hs) { (void)out; (void)in_far; (void)w; (void)hs; return in_near; } static uint8_t* rjpeg__resample_row_v_2(uint8_t *out, uint8_t *in_near, uint8_t *in_far, int w, int hs) { /* need to generate two samples vertically for every one in input */ int i; (void)hs; for (i=0; i < w; ++i) out[i] = rjpeg__div4(3*in_near[i] + in_far[i] + 2); return out; } static uint8_t* rjpeg__resample_row_h_2(uint8_t *out, uint8_t *in_near, uint8_t *in_far, int w, int hs) { /* need to generate two samples horizontally for every one in input */ int i; uint8_t *input = in_near; if (w == 1) { /* if only one sample, can't do any interpolation */ out[0] = out[1] = input[0]; return out; } out[0] = input[0]; out[1] = rjpeg__div4(input[0]*3 + input[1] + 2); for (i=1; i < w-1; ++i) { int n = 3*input[i]+2; out[i*2+0] = rjpeg__div4(n+input[i-1]); out[i*2+1] = rjpeg__div4(n+input[i+1]); } out[i*2+0] = rjpeg__div4(input[w-2]*3 + input[w-1] + 2); out[i*2+1] = input[w-1]; (void)in_far; (void)hs; return out; } static uint8_t *rjpeg__resample_row_hv_2(uint8_t *out, uint8_t *in_near, uint8_t *in_far, int w, int hs) { /* need to generate 2x2 samples for every one in input */ int i,t0,t1; if (w == 1) { out[0] = out[1] = rjpeg__div4(3*in_near[0] + in_far[0] + 2); return out; } t1 = 3*in_near[0] + in_far[0]; out[0] = rjpeg__div4(t1+2); for (i=1; i < w; ++i) { t0 = t1; t1 = 3*in_near[i]+in_far[i]; out[i*2-1] = rjpeg__div16(3*t0 + t1 + 8); out[i*2 ] = rjpeg__div16(3*t1 + t0 + 8); } out[w*2-1] = rjpeg__div4(t1+2); (void)hs; return out; } #if defined(__SSE2__) || defined(RJPEG_NEON) static uint8_t *rjpeg__resample_row_hv_2_simd(uint8_t *out, uint8_t *in_near, uint8_t *in_far, int w, int hs) { /* need to generate 2x2 samples for every one in input */ int i=0,t0,t1; if (w == 1) { out[0] = out[1] = rjpeg__div4(3*in_near[0] + in_far[0] + 2); return out; } t1 = 3*in_near[0] + in_far[0]; /* process groups of 8 pixels for as long as we can. * note we can't handle the last pixel in a row in this loop * because we need to handle the filter boundary conditions. */ for (; i < ((w-1) & ~7); i += 8) { #if defined(__SSE2__) /* load and perform the vertical filtering pass * this uses 3*x + y = 4*x + (y - x) */ __m128i zero = _mm_setzero_si128(); __m128i farb = _mm_loadl_epi64((__m128i *) (in_far + i)); __m128i nearb = _mm_loadl_epi64((__m128i *) (in_near + i)); __m128i farw = _mm_unpacklo_epi8(farb, zero); __m128i nearw = _mm_unpacklo_epi8(nearb, zero); __m128i diff = _mm_sub_epi16(farw, nearw); __m128i nears = _mm_slli_epi16(nearw, 2); __m128i curr = _mm_add_epi16(nears, diff); /* current row */ /* horizontal filter works the same based on shifted vers of current * row. "prev" is current row shifted right by 1 pixel; we need to * insert the previous pixel value (from t1). * "next" is current row shifted left by 1 pixel, with first pixel * of next block of 8 pixels added in. */ __m128i prv0 = _mm_slli_si128(curr, 2); __m128i nxt0 = _mm_srli_si128(curr, 2); __m128i prev = _mm_insert_epi16(prv0, t1, 0); __m128i next = _mm_insert_epi16(nxt0, 3*in_near[i+8] + in_far[i+8], 7); /* horizontal filter, polyphase implementation since it's convenient: * even pixels = 3*cur + prev = cur*4 + (prev - cur) * odd pixels = 3*cur + next = cur*4 + (next - cur) * note the shared term. */ __m128i bias = _mm_set1_epi16(8); __m128i curs = _mm_slli_epi16(curr, 2); __m128i prvd = _mm_sub_epi16(prev, curr); __m128i nxtd = _mm_sub_epi16(next, curr); __m128i curb = _mm_add_epi16(curs, bias); __m128i even = _mm_add_epi16(prvd, curb); __m128i odd = _mm_add_epi16(nxtd, curb); /* interleave even and odd pixels, then undo scaling. */ __m128i int0 = _mm_unpacklo_epi16(even, odd); __m128i int1 = _mm_unpackhi_epi16(even, odd); __m128i de0 = _mm_srli_epi16(int0, 4); __m128i de1 = _mm_srli_epi16(int1, 4); /* pack and write output */ __m128i outv = _mm_packus_epi16(de0, de1); _mm_storeu_si128((__m128i *) (out + i*2), outv); #elif defined(RJPEG_NEON) /* load and perform the vertical filtering pass * this uses 3*x + y = 4*x + (y - x) */ uint8x8_t farb = vld1_u8(in_far + i); uint8x8_t nearb = vld1_u8(in_near + i); int16x8_t diff = vreinterpretq_s16_u16(vsubl_u8(farb, nearb)); int16x8_t nears = vreinterpretq_s16_u16(vshll_n_u8(nearb, 2)); int16x8_t curr = vaddq_s16(nears, diff); /* current row */ /* horizontal filter works the same based on shifted vers of current * row. "prev" is current row shifted right by 1 pixel; we need to * insert the previous pixel value (from t1). * "next" is current row shifted left by 1 pixel, with first pixel * of next block of 8 pixels added in. */ int16x8_t prv0 = vextq_s16(curr, curr, 7); int16x8_t nxt0 = vextq_s16(curr, curr, 1); int16x8_t prev = vsetq_lane_s16(t1, prv0, 0); int16x8_t next = vsetq_lane_s16(3*in_near[i+8] + in_far[i+8], nxt0, 7); /* horizontal filter, polyphase implementation since it's convenient: * even pixels = 3*cur + prev = cur*4 + (prev - cur) * odd pixels = 3*cur + next = cur*4 + (next - cur) * note the shared term. */ int16x8_t curs = vshlq_n_s16(curr, 2); int16x8_t prvd = vsubq_s16(prev, curr); int16x8_t nxtd = vsubq_s16(next, curr); int16x8_t even = vaddq_s16(curs, prvd); int16x8_t odd = vaddq_s16(curs, nxtd); /* undo scaling and round, then store with even/odd phases interleaved */ uint8x8x2_t o; o.val[0] = vqrshrun_n_s16(even, 4); o.val[1] = vqrshrun_n_s16(odd, 4); vst2_u8(out + i*2, o); #endif /* "previous" value for next iteration */ t1 = 3*in_near[i+7] + in_far[i+7]; } t0 = t1; t1 = 3*in_near[i] + in_far[i]; out[i*2] = rjpeg__div16(3*t1 + t0 + 8); for (++i; i < w; ++i) { t0 = t1; t1 = 3*in_near[i]+in_far[i]; out[i*2-1] = rjpeg__div16(3*t0 + t1 + 8); out[i*2 ] = rjpeg__div16(3*t1 + t0 + 8); } out[w*2-1] = rjpeg__div4(t1+2); (void)hs; return out; } #endif static uint8_t *rjpeg__resample_row_generic(uint8_t *out, uint8_t *in_near, uint8_t *in_far, int w, int hs) { /* resample with nearest-neighbor */ int i,j; (void)in_far; for (i=0; i < w; ++i) for (j=0; j < hs; ++j) out[i*hs+j] = in_near[i]; return out; } /* this is a reduced-precision calculation of YCbCr-to-RGB introduced * to make sure the code produces the same results in both SIMD and scalar */ #ifndef float2fixed #define float2fixed(x) (((int) ((x) * 4096.0f + 0.5f)) << 8) #endif static void rjpeg__YCbCr_to_RGB_row(uint8_t *out, const uint8_t *y, const uint8_t *pcb, const uint8_t *pcr, int count, int step) { int i; for (i=0; i < count; ++i) { int y_fixed = (y[i] << 20) + (1<<19); /* rounding */ int cr = pcr[i] - 128; int cb = pcb[i] - 128; int r = y_fixed + cr* float2fixed(1.40200f); int g = y_fixed + (cr*-float2fixed(0.71414f)) + ((cb*-float2fixed(0.34414f)) & 0xffff0000); int b = y_fixed + cb* float2fixed(1.77200f); r >>= 20; g >>= 20; b >>= 20; if ((unsigned) r > 255) r = 255; if ((unsigned) g > 255) g = 255; if ((unsigned) b > 255) b = 255; out[0] = (uint8_t)r; out[1] = (uint8_t)g; out[2] = (uint8_t)b; out[3] = 255; out += step; } } #if defined(__SSE2__) || defined(RJPEG_NEON) static void rjpeg__YCbCr_to_RGB_simd(uint8_t *out, const uint8_t *y, const uint8_t *pcb, const uint8_t *pcr, int count, int step) { int i = 0; #if defined(__SSE2__) /* step == 3 is pretty ugly on the final interleave, and i'm not convinced * it's useful in practice (you wouldn't use it for textures, for example). * so just accelerate step == 4 case. */ if (step == 4) { /* this is a fairly straightforward implementation and not super-optimized. */ __m128i signflip = _mm_set1_epi8(-0x80); __m128i cr_const0 = _mm_set1_epi16( (short) ( 1.40200f*4096.0f+0.5f)); __m128i cr_const1 = _mm_set1_epi16( - (short) ( 0.71414f*4096.0f+0.5f)); __m128i cb_const0 = _mm_set1_epi16( - (short) ( 0.34414f*4096.0f+0.5f)); __m128i cb_const1 = _mm_set1_epi16( (short) ( 1.77200f*4096.0f+0.5f)); __m128i y_bias = _mm_set1_epi8((char) (unsigned char) 128); __m128i xw = _mm_set1_epi16(255); /* alpha channel */ for (; i+7 < count; i += 8) { /* load */ __m128i y_bytes = _mm_loadl_epi64((__m128i *) (y+i)); __m128i cr_bytes = _mm_loadl_epi64((__m128i *) (pcr+i)); __m128i cb_bytes = _mm_loadl_epi64((__m128i *) (pcb+i)); __m128i cr_biased = _mm_xor_si128(cr_bytes, signflip); /* -128 */ __m128i cb_biased = _mm_xor_si128(cb_bytes, signflip); /* -128 */ /* unpack to short (and left-shift cr, cb by 8) */ __m128i yw = _mm_unpacklo_epi8(y_bias, y_bytes); __m128i crw = _mm_unpacklo_epi8(_mm_setzero_si128(), cr_biased); __m128i cbw = _mm_unpacklo_epi8(_mm_setzero_si128(), cb_biased); /* color transform */ __m128i yws = _mm_srli_epi16(yw, 4); __m128i cr0 = _mm_mulhi_epi16(cr_const0, crw); __m128i cb0 = _mm_mulhi_epi16(cb_const0, cbw); __m128i cb1 = _mm_mulhi_epi16(cbw, cb_const1); __m128i cr1 = _mm_mulhi_epi16(crw, cr_const1); __m128i rws = _mm_add_epi16(cr0, yws); __m128i gwt = _mm_add_epi16(cb0, yws); __m128i bws = _mm_add_epi16(yws, cb1); __m128i gws = _mm_add_epi16(gwt, cr1); /* descale */ __m128i rw = _mm_srai_epi16(rws, 4); __m128i bw = _mm_srai_epi16(bws, 4); __m128i gw = _mm_srai_epi16(gws, 4); /* back to byte, set up for transpose */ __m128i brb = _mm_packus_epi16(rw, bw); __m128i gxb = _mm_packus_epi16(gw, xw); /* transpose to interleave channels */ __m128i t0 = _mm_unpacklo_epi8(brb, gxb); __m128i t1 = _mm_unpackhi_epi8(brb, gxb); __m128i o0 = _mm_unpacklo_epi16(t0, t1); __m128i o1 = _mm_unpackhi_epi16(t0, t1); /* store */ _mm_storeu_si128((__m128i *) (out + 0), o0); _mm_storeu_si128((__m128i *) (out + 16), o1); out += 32; } } #endif #ifdef RJPEG_NEON /* in this version, step=3 support would be easy to add. but is there demand? */ if (step == 4) { /* this is a fairly straightforward implementation and not super-optimized. */ uint8x8_t signflip = vdup_n_u8(0x80); int16x8_t cr_const0 = vdupq_n_s16( (short) ( 1.40200f*4096.0f+0.5f)); int16x8_t cr_const1 = vdupq_n_s16( - (short) ( 0.71414f*4096.0f+0.5f)); int16x8_t cb_const0 = vdupq_n_s16( - (short) ( 0.34414f*4096.0f+0.5f)); int16x8_t cb_const1 = vdupq_n_s16( (short) ( 1.77200f*4096.0f+0.5f)); for (; i+7 < count; i += 8) { uint8x8x4_t o; /* load */ uint8x8_t y_bytes = vld1_u8(y + i); uint8x8_t cr_bytes = vld1_u8(pcr + i); uint8x8_t cb_bytes = vld1_u8(pcb + i); int8x8_t cr_biased = vreinterpret_s8_u8(vsub_u8(cr_bytes, signflip)); int8x8_t cb_biased = vreinterpret_s8_u8(vsub_u8(cb_bytes, signflip)); /* expand to s16 */ int16x8_t yws = vreinterpretq_s16_u16(vshll_n_u8(y_bytes, 4)); int16x8_t crw = vshll_n_s8(cr_biased, 7); int16x8_t cbw = vshll_n_s8(cb_biased, 7); /* color transform */ int16x8_t cr0 = vqdmulhq_s16(crw, cr_const0); int16x8_t cb0 = vqdmulhq_s16(cbw, cb_const0); int16x8_t cr1 = vqdmulhq_s16(crw, cr_const1); int16x8_t cb1 = vqdmulhq_s16(cbw, cb_const1); int16x8_t rws = vaddq_s16(yws, cr0); int16x8_t gws = vaddq_s16(vaddq_s16(yws, cb0), cr1); int16x8_t bws = vaddq_s16(yws, cb1); /* undo scaling, round, convert to byte */ o.val[0] = vqrshrun_n_s16(rws, 4); o.val[1] = vqrshrun_n_s16(gws, 4); o.val[2] = vqrshrun_n_s16(bws, 4); o.val[3] = vdup_n_u8(255); /* store, interleaving r/g/b/a */ vst4_u8(out, o); out += 8*4; } } #endif for (; i < count; ++i) { int y_fixed = (y[i] << 20) + (1<<19); /* rounding */ int cr = pcr[i] - 128; int cb = pcb[i] - 128; int r = y_fixed + cr* float2fixed(1.40200f); int g = y_fixed + cr*-float2fixed(0.71414f) + ((cb*-float2fixed(0.34414f)) & 0xffff0000); int b = y_fixed + cb* float2fixed(1.77200f); r >>= 20; g >>= 20; b >>= 20; if ((unsigned) r > 255) r = 255; if ((unsigned) g > 255) g = 255; if ((unsigned) b > 255) b = 255; out[0] = (uint8_t)r; out[1] = (uint8_t)g; out[2] = (uint8_t)b; out[3] = 255; out += step; } } #endif /* set up the kernels */ static void rjpeg__setup_jpeg(rjpeg__jpeg *j) { uint64_t mask = cpu_features_get(); (void)mask; j->idct_block_kernel = rjpeg__idct_block; j->YCbCr_to_RGB_kernel = rjpeg__YCbCr_to_RGB_row; j->resample_row_hv_2_kernel = rjpeg__resample_row_hv_2; #if defined(__SSE2__) if (mask & RETRO_SIMD_SSE2) { j->idct_block_kernel = rjpeg__idct_simd; j->YCbCr_to_RGB_kernel = rjpeg__YCbCr_to_RGB_simd; j->resample_row_hv_2_kernel = rjpeg__resample_row_hv_2_simd; } #endif #ifdef RJPEG_NEON j->idct_block_kernel = rjpeg__idct_simd; j->YCbCr_to_RGB_kernel = rjpeg__YCbCr_to_RGB_simd; j->resample_row_hv_2_kernel = rjpeg__resample_row_hv_2_simd; #endif } /* clean up the temporary component buffers */ static void rjpeg__cleanup_jpeg(rjpeg__jpeg *j) { int i; for (i=0; i < j->s->img_n; ++i) { if (j->img_comp[i].raw_data) { free(j->img_comp[i].raw_data); j->img_comp[i].raw_data = NULL; j->img_comp[i].data = NULL; } if (j->img_comp[i].raw_coeff) { free(j->img_comp[i].raw_coeff); j->img_comp[i].raw_coeff = 0; j->img_comp[i].coeff = 0; } if (j->img_comp[i].linebuf) { free(j->img_comp[i].linebuf); j->img_comp[i].linebuf = NULL; } } } static uint8_t *rjpeg_load_jpeg_image(rjpeg__jpeg *z, unsigned *out_x, unsigned *out_y, int *comp, int req_comp) { int n, decode_n; int k; unsigned int i,j; rjpeg__resample res_comp[4]; uint8_t *coutput[4] = {0}; uint8_t *output = NULL; z->s->img_n = 0; /* make rjpeg__cleanup_jpeg safe */ /* validate req_comp */ if (req_comp < 0 || req_comp > 4) return rjpeg__errpuc("bad req_comp", "Internal error"); /* load a jpeg image from whichever source, but leave in YCbCr format */ if (!rjpeg__decode_jpeg_image(z)) goto error; /* determine actual number of components to generate */ n = req_comp ? req_comp : z->s->img_n; if (z->s->img_n == 3 && n < 3) decode_n = 1; else decode_n = z->s->img_n; /* resample and color-convert */ for (k=0; k < decode_n; ++k) { rjpeg__resample *r = &res_comp[k]; /* allocate line buffer big enough for upsampling off the edges * with upsample factor of 4 */ z->img_comp[k].linebuf = (uint8_t *) malloc(z->s->img_x + 3); if (!z->img_comp[k].linebuf) goto error; r->hs = z->img_h_max / z->img_comp[k].h; r->vs = z->img_v_max / z->img_comp[k].v; r->ystep = r->vs >> 1; r->w_lores = (z->s->img_x + r->hs-1) / r->hs; r->ypos = 0; r->line0 = r->line1 = z->img_comp[k].data; r->resample = rjpeg__resample_row_generic; if (r->hs == 1 && r->vs == 1) r->resample = rjpeg_resample_row_1; else if (r->hs == 1 && r->vs == 2) r->resample = rjpeg__resample_row_v_2; else if (r->hs == 2 && r->vs == 1) r->resample = rjpeg__resample_row_h_2; else if (r->hs == 2 && r->vs == 2) r->resample = z->resample_row_hv_2_kernel; } /* can't error after this so, this is safe */ output = (uint8_t *) malloc(n * z->s->img_x * z->s->img_y + 1); if (!output) goto error; /* now go ahead and resample */ for (j=0; j < z->s->img_y; ++j) { uint8_t *out = output + n * z->s->img_x * j; for (k=0; k < decode_n; ++k) { rjpeg__resample *r = &res_comp[k]; int y_bot = r->ystep >= (r->vs >> 1); coutput[k] = r->resample(z->img_comp[k].linebuf, y_bot ? r->line1 : r->line0, y_bot ? r->line0 : r->line1, r->w_lores, r->hs); if (++r->ystep >= r->vs) { r->ystep = 0; r->line0 = r->line1; if (++r->ypos < z->img_comp[k].y) r->line1 += z->img_comp[k].w2; } } if (n >= 3) { uint8_t *y = coutput[0]; if (z->s->img_n == 3) z->YCbCr_to_RGB_kernel(out, y, coutput[1], coutput[2], z->s->img_x, n); else for (i=0; i < z->s->img_x; ++i) { out[0] = out[1] = out[2] = y[i]; out[3] = 255; /* not used if n==3 */ out += n; } } else { uint8_t *y = coutput[0]; if (n == 1) for (i=0; i < z->s->img_x; ++i) out[i] = y[i]; else for (i=0; i < z->s->img_x; ++i) *out++ = y[i], *out++ = 255; } } rjpeg__cleanup_jpeg(z); *out_x = z->s->img_x; *out_y = z->s->img_y; if (comp) *comp = z->s->img_n; /* report original components, not output */ return output; error: rjpeg__cleanup_jpeg(z); return NULL; } static unsigned char *rjpeg__jpeg_load(rjpeg__context *s, unsigned *x, unsigned *y, int *comp, int req_comp) { rjpeg__jpeg j; j.s = s; rjpeg__setup_jpeg(&j); return rjpeg_load_jpeg_image(&j, x,y,comp,req_comp); } int rjpeg_process_image(rjpeg_t *rjpeg, void **buf_data, size_t size, unsigned *width, unsigned *height) { int comp; uint32_t *img = NULL; uint32_t *pixels = NULL; unsigned size_tex = 0; if (!rjpeg) return IMAGE_PROCESS_ERROR; img = (uint32_t*)rjpeg_load_from_memory(rjpeg->buff_data, size, width, height, &comp, 4); if (!img) return IMAGE_PROCESS_ERROR; size_tex = (*width) * (*height); pixels = (uint32_t*)malloc(size_tex * sizeof(uint32_t)); if (!pixels) { free(img); return IMAGE_PROCESS_ERROR; } *buf_data = pixels; /* Convert RGBA to ARGB */ while (size_tex--) { unsigned int texel = img[size_tex]; unsigned int A = texel & 0xFF000000; unsigned int B = texel & 0x00FF0000; unsigned int G = texel & 0x0000FF00; unsigned int R = texel & 0x000000FF; ((unsigned int*)pixels)[size_tex] = A | (R << 16) | G | (B >> 16); }; free(img); return IMAGE_PROCESS_END; } bool rjpeg_set_buf_ptr(rjpeg_t *rjpeg, void *data) { if (!rjpeg) return false; rjpeg->buff_data = (uint8_t*)data; return true; } void rjpeg_free(rjpeg_t *rjpeg) { if (!rjpeg) return; free(rjpeg); } rjpeg_t *rjpeg_alloc(void) { rjpeg_t *rjpeg = (rjpeg_t*)calloc(1, sizeof(*rjpeg)); if (!rjpeg) return NULL; return rjpeg; } desmume/src/utils/bits.h000664 001750 001750 00000002152 12755534123 016411 0ustar00sergiosergio000000 000000 #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) #endif desmume/src/utils/xstring.h000664 001750 001750 00000002214 12755534123 017145 0ustar00sergiosergio000000 000000 //taken from fceux on 27-oct-2008 //subsequently modified for desmume /* Copyright (C) 2008-2009 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the this software. If not, see . */ #ifndef _STRINGUTIL_H_ #define _STRINGUTIL_H_ #include #include #include #include #include #include #include "../types.h" std::vector tokenize_str(const std::string & str,const std::string & delims); std::string stditoa(int n); std::string mass_replace(const std::string &source, const std::string &victim, const std::string &replacement); #endif desmume/src/utils/AsmJit/core/defs.h000664 001750 001750 00000046546 12755534123 020527 0ustar00sergiosergio000000 000000 // [AsmJit] // Complete JIT Assembler for C++ Language. // // [License] // Zlib - See COPYING file in this package. // [Guard] #ifndef _ASMJIT_CORE_DEFS_H #define _ASMJIT_CORE_DEFS_H // [Dependencies - AsmJit] #include "../core/build.h" // [Api-Begin] #include "../core/apibegin.h" namespace AsmJit { //! @addtogroup AsmJit_Core //! @{ // ============================================================================ // [AsmJit::Global] // ============================================================================ enum { //! @brief Invalid operand identifier. kInvalidValue = 0xFFFFFFFFU, //! @brief Minimum reserved bytes in @ref Buffer. kBufferGrow = 32U }; static const size_t kInvalidSize = (size_t)-1; // ============================================================================ // [AsmJit::kStringBuilderOpType] // ============================================================================ //! @brief String builder operation. enum kStringBuilderOpType { //! @brief Replace the current content by a given content. kStringBuilderOpSet = 0, //! @brief Append a given content to the current content. kStringBuilderOpAppend = 1 }; // ============================================================================ // [AsmJit::kStringBuilderNumType] // ============================================================================ enum kStringBuilderNumFlags { kStringBuilderNumShowSign = (1U << 0), kStringBuilderNumShowSpace = (1U << 1), kStringBuilderNumAlternate = (1U << 2), kStringBuilderNumSigned = (1U << 31) }; // ============================================================================ // [AsmJit::kLoggerOption] // ============================================================================ enum kLoggerFlag { //! @brief Whether logger is enabled or disabled. //! //! Default @c true. kLoggerIsEnabled = 0x00000001, //! @brief Whether logger is enabled and can be used. //! //! This value can be set by inherited classes to inform @c Logger that //! assigned stream (or something that can log output) is invalid. If //! @c _used is false it means that there is no logging output and AsmJit //! shouldn't use this logger (because all messages will be lost). //! //! This is designed only to optimize cases that logger exists, but its //! configured not to output messages. The API inside Logging and AsmJit //! should only check this value when needed. The API outside AsmJit should //! check only whether logging is @c _enabled. //! //! Default @c true. kLoggerIsUsed = 0x00000002, //! @brief Whether to output instructions also in binary form. kLoggerOutputBinary = 0x00000010, //! @brief Whether to output immediates as hexadecimal numbers. kLoggerOutputHexImmediate = 0x00000020, //! @brief Whether to output displacements as hexadecimal numbers. kLoggerOutputHexDisplacement = 0x00000040 }; // ============================================================================ // [AsmJit::kCpu] // ============================================================================ //! @brief Cpu vendor IDs. //! //! Cpu vendor IDs are specific for AsmJit library. Vendor ID is not directly //! read from cpuid result, instead it's based on CPU vendor string. enum kCpu { //! @brief Unknown CPU vendor. kCpuUnknown = 0, //! @brief Intel CPU vendor. kCpuIntel = 1, //! @brief AMD CPU vendor. kCpuAmd = 2, //! @brief National Semiconductor CPU vendor (applies also to Cyrix processors). kCpuNSM = 3, //! @brief Transmeta CPU vendor. kCpuTransmeta = 4, //! @brief VIA CPU vendor. kCpuVia = 5 }; // ============================================================================ // [AsmJit::kMemAllocType] // ============================================================================ //! @brief Types of allocation used by @c AsmJit::MemoryManager::alloc() method. enum kMemAllocType { //! @brief Allocate memory that can be freed by @c AsmJit::MemoryManager::free() //! method. kMemAllocFreeable = 0, //! @brief Allocate permanent memory that will be never freed. kMemAllocPermanent = 1 }; // ============================================================================ // [AsmJit::kOperandType] // ============================================================================ //! @brief Operand types that can be encoded in @c Op operand. enum kOperandType { //! @brief Operand is none, used only internally (not initialized Operand). //! //! This operand is not valid. kOperandNone = 0x00, //! @brief Operand is label. kOperandLabel = 0x01, //! @brief Operand is register. kOperandReg = 0x02, //! @brief Operand is variable. kOperandVar = 0x04, //! @brief Operand is memory. kOperandMem = 0x08, //! @brief Operand is immediate. kOperandImm = 0x10 }; // ============================================================================ // [AsmJit::kOperandMemType] // ============================================================================ //! @brief Type of memory operand. enum kOperandMemType { //! @brief Operand is combination of register(s) and displacement (native). kOperandMemNative = 0, //! @brief Operand is label. kOperandMemLabel = 1, //! @brief Operand is absolute memory location (supported mainly in 32-bit mode) kOperandMemAbsolute = 2, }; // ============================================================================ // [AsmJit::kOperandId] // ============================================================================ //! @brief Operand ID masks used to determine the operand type. enum kOperandId { //! @brief Operand id type mask (part used for operand type). kOperandIdTypeMask = 0xC0000000, //! @brief Label operand mark id. kOperandIdTypeLabel = 0x40000000, //! @brief Variable operand mark id. kOperandIdTypeVar = 0x80000000, //! @brief Operand id value mask (part used for IDs). kOperandIdValueMask = 0x3FFFFFFF }; // ============================================================================ // [AsmJit::kRegType / kRegIndex] // ============================================================================ enum { //! @brief Mask for register type. kRegTypeMask = 0xFF00, //! @brief Mask for register code (index). kRegIndexMask = 0xFF, //! @brief Invalid register index. kRegIndexInvalid = 0xFF }; // ============================================================================ // [AsmJit::kCondHint] // ============================================================================ //! @brief Condition hint. enum kCondHint { //! @brief No hint. kCondHintNone = 0x00, //! @brief Condition is likely to be taken. kCondHintLikely = 0x01, //! @brief Condition is unlikely to be taken. kCondHintUnlikely = 0x02 }; // ============================================================================ // [AsmJit::kFuncAnonymous] // ============================================================================ enum { //! @brief Maximum allowed arguments per function declaration / call. kFuncArgsMax = 32, //! @brief Invalid stack offset in function or function parameter. kFuncStackInvalid = -1 }; // ============================================================================ // [AsmJit::kFuncConv] // ============================================================================ enum kFuncConv { //! @brief Calling convention is invalid (can't be used). kFuncConvNone = 0 }; // ============================================================================ // [AsmJit::kFuncHint] // ============================================================================ //! @brief Function hints. enum kFuncHint { //! @brief Make naked function (without using ebp/erp in prolog / epilog). kFuncHintNaked = 0 }; // ============================================================================ // [AsmJit::kFuncFlags] // ============================================================================ //! @brief Function flags. enum kFuncFlags { //! @brief Whether another function is called from this function. //! //! If another function is called from this function, it's needed to prepare //! stack for it. If this member is true then it's likely that true will be //! also @c _isEspAdjusted one. kFuncFlagIsCaller = (1U << 0), //! @brief Whether the function is finished using @c Compiler::endFunc(). kFuncFlagIsFinished = (1U << 1), //! @brief Whether the function is using naked (minimal) prolog / epilog. kFuncFlagIsNaked = (1U << 2) }; // ============================================================================ // [AsmJit::kFuncArgsDirection] // ============================================================================ //! @brief Function arguments direction. enum kFuncArgsDirection { //! @brief Arguments are passed left to right. //! //! This arguments direction is unusual to C programming, it's used by pascal //! compilers and in some calling conventions by Borland compiler). kFuncArgsLTR = 0, //! @brief Arguments are passed right ro left //! //! This is default argument direction in C programming. kFuncArgsRTL = 1 }; // ============================================================================ // [AsmJit::kInstCode] // ============================================================================ enum kInstCode { //! @brief No instruction. kInstNone = 0 }; // ============================================================================ // [AsmJit::kVarAllocFlags] // ============================================================================ //! @brief Variable alloc mode. enum kVarAllocFlags { //! @brief Allocating variable to read only. //! //! Read only variables are used to optimize variable spilling. If variable //! is some time ago deallocated and it's not marked as changed (so it was //! all the life time read only) then spill is simply NOP (no mov instruction //! is generated to move it to it's home memory location). kVarAllocRead = 0x01, //! @brief Allocating variable to write only (overwrite). //! //! Overwriting means that if variable is in memory, there is no generated //! instruction to move variable from memory to register, because that //! register will be overwritten by next instruction. This is used as a //! simple optimization to improve generated code by @c Compiler. kVarAllocWrite = 0x02, //! @brief Allocating variable to read / write. //! //! Variable allocated for read / write is marked as changed. This means that //! if variable must be later spilled into memory, mov (or similar) //! instruction will be generated. kVarAllocReadWrite = 0x03, //! @brief Variable can be allocated in register. kVarAllocRegister = 0x04, //! @brief Variable can be allocated only to a special register. kVarAllocSpecial = 0x08, //! @brief Variable can be allocated in memory. kVarAllocMem = 0x10, //! @brief Unuse the variable after use. kVarAllocUnuseAfterUse = 0x20 }; // ============================================================================ // [AsmJit::kVarHint] // ============================================================================ //! @brief Variable hint (used by @ref Compiler). //! //! @sa @ref Compiler. enum kVarHint { //! @brief Alloc variable. kVarHintAlloc = 0, //! @brief Spill variable. kVarHintSpill = 1, //! @brief Save variable if modified. kVarHintSave = 2, //! @brief Save variable if modified and mark it as unused. kVarHintSaveAndUnuse = 3, //! @brief Mark variable as unused. kVarHintUnuse = 4 }; // ============================================================================ // [AsmJit::kVarPolicy] // ============================================================================ //! @brief Variable allocation method. //! //! Variable allocation method is used by compiler and it means if compiler //! should first allocate preserved registers or not. Preserved registers are //! registers that must be saved / restored by generated function. //! //! This option is for people who are calling C/C++ functions from JIT code so //! Compiler can recude generating push/pop sequences before and after call, //! respectively. enum kVarPolicy { //! @brief Allocate preserved registers first. kVarPolicyPreservedFirst = 0, //! @brief Allocate preserved registers last (default). kVarPolicyPreservedLast = 1 }; // ============================================================================ // [AsmJit::kVarState] // ============================================================================ //! @brief State of variable. //! //! @note State of variable is used only during make process and it's not //! visible to the developer. enum kVarState { //! @brief Variable is currently not used. kVarStateUnused = 0, //! @brief Variable is in register. //! //! Variable is currently allocated in register. kVarStateReg = 1, //! @brief Variable is in memory location or spilled. //! //! Variable was spilled from register to memory or variable is used for //! memory only storage. kVarStateMem = 2 }; // ============================================================================ // [AsmJit::kVarType] // ============================================================================ enum kVarType { //! @brief Invalid variable type. kVarTypeInvalid = 0xFF }; // ============================================================================ // [AsmJit::kScale] // ============================================================================ //! @brief Scale which can be used for addressing (it the target instruction //! supports it). //! //! See @c Op and addressing methods like @c byte_ptr(), @c word_ptr(), //! @c dword_ptr(), etc... enum kScale { //! @brief No scale. kScaleNone = 0, //! @brief Scale 2 times (same as shifting to left by 1). kScale2Times = 1, //! @brief Scale 4 times (same as shifting to left by 2). kScale4Times = 2, //! @brief Scale 8 times (same as shifting to left by 3). kScale8Times = 3 }; // ============================================================================ // [AsmJit::kSize] // ============================================================================ //! @brief Size of registers and pointers. enum kSize { //! @brief 1 byte size. kSizeByte = 1, //! @brief 2 bytes size. kSizeWord = 2, //! @brief 4 bytes size. kSizeDWord = 4, //! @brief 8 bytes size. kSizeQWord = 8, //! @brief 10 bytes size. kSizeTWord = 10, //! @brief 16 bytes size. kSizeDQWord = 16 }; // ============================================================================ // [AsmJit::kRelocMode] // ============================================================================ enum kRelocMode { kRelocAbsToAbs = 0, kRelocRelToAbs = 1, kRelocAbsToRel = 2, kRelocTrampoline = 3 }; // ============================================================================ // [AsmJit::kCompilerItem] // ============================================================================ //! @brief Type of @ref CompilerItem. //! //! Each @c CompilerItem contains information about its type. Compiler can //! optimize instruction stream by analyzing items and each type is hint //! for it. The most used/serialized items are instructions //! (@c kCompilerItemInst). enum kCompilerItem { //! @brief Invalid item (can't be used). kCompilerItemNone = 0, //! @brief Item is mark, see @ref CompilerMark. kCompilerItemMark, //! @brief Item is comment, see @ref CompilerComment. kCompilerItemComment, //! @brief Item is embedded data, see @ref CompilerEmbed. kCompilerItemEmbed, //! @brief Item is .align directive, see @ref CompilerAlign. kCompilerItemAlign, //! @brief Item is variable hint (alloc, spill, use, unuse), see @ref CompilerHint. kCompilerItemHint, //! @brief Item is instruction, see @ref CompilerInst. kCompilerItemInst, //! @brief Item is target, see @ref CompilerTarget. kCompilerItemTarget, //! @brief Item is function call, see @ref CompilerFuncCall. kCompilerItemFuncCall, //! @brief Item is function declaration, see @ref CompilerFuncDecl. kCompilerItemFuncDecl, //! @brief Item is an end of the function, see @ref CompilerFuncEnd. kCompilerItemFuncEnd, //! @brief Item is function return, see @ref CompilerFuncRet. kCompilerItemFuncRet }; // ============================================================================ // [AsmJit::kError] // ============================================================================ //! @brief Error codes. enum kError { //! @brief No error (success). //! //! This is default state and state you want. kErrorOk = 0, //! @brief Memory allocation error (@c ASMJIT_MALLOC returned @c NULL). kErrorNoHeapMemory = 1, //! @brief Virtual memory allocation error (@c VirtualMemory returned @c NULL). kErrorNoVirtualMemory = 2, //! @brief Unknown instruction. This happens only if instruction code is //! out of bounds. Shouldn't happen. kErrorUnknownInstruction = 3, //! @brief Illegal instruction, usually generated by AsmJit::Assembler //! class when emitting instruction opcode. If this error is generated the //! target buffer is not affected by this invalid instruction. //! //! You can also get this error code if you are under x64 (64-bit x86) and //! you tried to decode instruction using AH, BH, CH or DH register with REX //! prefix. These registers can't be accessed if REX prefix is used and AsmJit //! didn't check for this situation in intrinsics (@c Compiler takes care of //! this and rearrange registers if needed). //! //! Examples that will raise @c kErrorIllegalInstruction error (a is //! @c Assembler instance): //! //! @code //! a.mov(dword_ptr(eax), al); // Invalid address size. //! a.mov(byte_ptr(r10), ah); // Undecodable instruction (AH used with r10 //! // which can be encoded only using REX prefix) //! @endcode //! //! @note In debug mode you get assertion failure instead of setting error //! code. kErrorIllegalInstruction = 4, //! @brief Illegal addressing used (unencodable). kErrorIllegalAddressing = 5, //! @brief Short jump instruction used, but displacement is out of bounds. kErrorIllegalShortJump = 6, //! @brief No function defined. kErrorNoFunction = 7, //! @brief Function generation is not finished by using @c Compiler::endFunc() //! or something bad happened during generation related to function. This can //! be missing compiler item, etc... kErrorIncompleteFunction = 8, //! @brief Compiler can't allocate registers, because all of them are used. //! //! @note AsmJit is able to spill registers so this error really shouldn't //! happen unless all registers have priority 0 (which means never spill). kErrorNoRegisters = 9, //! @brief Compiler can't allocate one register to multiple destinations. //! //! This error can only happen using special instructions like cmpxchg8b and //! others where there are more destination operands (implicit). kErrorOverlappedRegisters = 10, //! @brief Tried to call function using incompatible argument. kErrorIncompatibleArgumentType = 11, //! @brief Incompatible return value. kErrorIncompatibleReturnType = 12, //! @brief Count of error codes by AsmJit. Can grow in future. kErrorCount }; // ============================================================================ // [AsmJit::API] // ============================================================================ //! @brief Translates error code (see @c kError) into text representation. ASMJIT_API const char* getErrorString(uint32_t error); //! @} } // AsmJit namespace // [Api-End] #include "../core/apiend.h" // [Guard] #endif // _ASMJIT_CORE_DEFS_H desmume/src/libretro-common/include/gfx/000700 001750 001750 00000000000 12756420131 021434 5ustar00sergiosergio000000 000000 desmume/src/common.c000664 001750 001750 00000026117 12755534123 015602 0ustar00sergiosergio000000 000000 /* Copyright (C) 2008-2015 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the this software. If not, see . */ //TODO - move this into ndssystem where it belongs probably #include "common.h" #include #include #include #include #include #include char *removeSpecialChars(char *s) { uint32_t i; char *buf = s; if (!s) return NULL; if (!*s) return s; for (i = 0; i < strlen(s); i++) { if (isspace((uint8_t)s[i]) && (s[i] != 0x20)) *buf = 0x20; else *buf = s[i]; buf++; } *buf = 0; return s; } static struct MAKER makerCodes[] = { { 0x3130, "Nintendo" }, { 0x3230, "Rocket Games, Ajinomoto" }, { 0x3330, "Imagineer-Zoom" }, { 0x3430, "Gray Matter?" }, { 0x3530, "Zamuse" }, { 0x3630, "Falcom" }, { 0x3730, "Enix?" }, { 0x3830, "Capcom" }, { 0x3930, "Hot B Co." }, { 0x4130, "Jaleco" }, { 0x4230, "Coconuts Japan" }, { 0x4330, "Coconuts Japan/G.X.Media" }, { 0x4430, "Micronet?" }, { 0x4530, "Technos" }, { 0x4630, "Mebio Software" }, { 0x4730, "Shouei System" }, { 0x4830, "Starfish" }, { 0x4A30, "Mitsui Fudosan/Dentsu" }, { 0x4C30, "Warashi Inc." }, { 0x4E30, "Nowpro" }, { 0x5030, "Game Village" }, { 0x3031, "?????????????" }, { 0x3231, "Infocom" }, { 0x3331, "Electronic Arts Japan" }, { 0x3531, "Cobra Team" }, { 0x3631, "Human/Field" }, { 0x3731, "KOEI" }, { 0x3831, "Hudson Soft" }, { 0x3931, "S.C.P." }, { 0x4131, "Yanoman" }, { 0x4331, "Tecmo Products" }, { 0x4431, "Japan Glary Business" }, { 0x4531, "Forum/OpenSystem" }, { 0x4631, "Virgin Games" }, { 0x4731, "SMDE" }, { 0x4A31, "Daikokudenki" }, { 0x5031, "Creatures Inc." }, { 0x5131, "TDK Deep Impresion" }, { 0x3032, "Destination Software, KSS" }, { 0x3132, "Sunsoft/Tokai Engineering??" }, { 0x3232, "POW, VR 1 Japan??" }, { 0x3332, "Micro World" }, { 0x3532, "San-X" }, { 0x3632, "Enix" }, { 0x3732, "Loriciel/Electro Brain" }, { 0x3832, "Kemco Japan" }, { 0x3932, "Seta" }, { 0x4132, "Culture Brain" }, { 0x4332, "Palsoft" }, { 0x4432, "Visit Co.,Ltd." }, { 0x4532, "Intec" }, { 0x4632, "System Sacom" }, { 0x4732, "Poppo" }, { 0x4832, "Ubisoft Japan" }, { 0x4A32, "Media Works" }, { 0x4B32, "NEC InterChannel" }, { 0x4C32, "Tam" }, { 0x4D32, "Jordan" }, { 0x4E32, "Smilesoft ???, Rocket ???" }, { 0x5132, "Mediakite" }, { 0x3033, "Viacom" }, { 0x3133, "Carrozzeria" }, { 0x3233, "Dynamic" }, { 0x3433, "Magifact" }, { 0x3533, "Hect" }, { 0x3633, "Codemasters" }, { 0x3733, "Taito/GAGA Communications" }, { 0x3833, "Laguna" }, { 0x3933, "Telstar Fun & Games, Event/Taito" }, { 0x4233, "Arcade Zone Ltd" }, { 0x4333, "Entertainment International/Empire Software?" }, { 0x4433, "Loriciel" }, { 0x4533, "Gremlin Graphics" }, { 0x4633, "K.Amusement Leasing Co." }, { 0x3034, "Seika Corp." }, { 0x3134, "Ubi Soft Entertainment" }, { 0x3234, "Sunsoft US?" }, { 0x3434, "Life Fitness" }, { 0x3634, "System 3" }, { 0x3734, "Spectrum Holobyte" }, { 0x3934, "IREM" }, { 0x4234, "Raya Systems" }, { 0x4334, "Renovation Products" }, { 0x4434, "Malibu Games" }, { 0x4634, "Eidos (was U.S. Gold <=1995)" }, { 0x4734, "Playmates Interactive?" }, { 0x4A34, "Fox Interactive" }, { 0x4B34, "Time Warner Interactive" }, { 0x5134, "Disney Interactive" }, { 0x5334, "Black Pearl" }, { 0x5534, "Advanced Productions" }, { 0x5834, "GT Interactive" }, { 0x5934, "RARE?" }, { 0x5A34, "Crave Entertainment" }, { 0x3035, "Absolute Entertainment" }, { 0x3135, "Acclaim" }, { 0x3235, "Activision" }, { 0x3335, "American Sammy" }, { 0x3435, "Take 2 Interactive (before it was GameTek)" }, { 0x3535, "Hi Tech" }, { 0x3635, "LJN LTD." }, { 0x3835, "Mattel" }, { 0x4135, "Mindscape, Red Orb Entertainment?" }, { 0x4235, "Romstar" }, { 0x4335, "Taxan" }, { 0x4435, "Midway (before it was Tradewest)" }, { 0x4635, "American Softworks" }, { 0x4735, "Majesco Sales Inc" }, { 0x4835, "3DO" }, { 0x4B35, "Hasbro" }, { 0x4C35, "NewKidCo" }, { 0x4D35, "Telegames" }, { 0x4E35, "Metro3D" }, { 0x5035, "Vatical Entertainment" }, { 0x5135, "LEGO Media" }, { 0x5335, "Xicat Interactive" }, { 0x5435, "Cryo Interactive" }, { 0x5735, "Red Storm Entertainment" }, { 0x5835, "Microids" }, { 0x5A35, "Conspiracy/Swing" }, { 0x3036, "Titus" }, { 0x3136, "Virgin Interactive" }, { 0x3236, "Maxis" }, { 0x3436, "LucasArts Entertainment" }, { 0x3736, "Ocean" }, { 0x3936, "Electronic Arts" }, { 0x4236, "Laser Beam" }, { 0x4536, "Elite Systems" }, { 0x4636, "Electro Brain" }, { 0x4736, "The Learning Company" }, { 0x4836, "BBC" }, { 0x4A36, "Software 2000" }, { 0x4C36, "BAM! Entertainment" }, { 0x4D36, "Studio 3" }, { 0x5136, "Classified Games" }, { 0x5336, "TDK Mediactive" }, { 0x5536, "DreamCatcher" }, { 0x5636, "JoWood Produtions" }, { 0x5736, "SEGA" }, { 0x5836, "Wannado Edition" }, { 0x5936, "LSP" }, { 0x5A36, "ITE Media" }, { 0x3037, "Infogrames" }, { 0x3137, "Interplay" }, { 0x3237, "JVC" }, { 0x3337, "Parker Brothers" }, { 0x3537, "Sales Curve" }, { 0x3837, "THQ" }, { 0x3937, "Accolade" }, { 0x4137, "Triffix Entertainment" }, { 0x4337, "Microprose Software" }, { 0x4437, "Universal Interactive, Sierra, Simon & Schuster?" }, { 0x4637, "Kemco" }, { 0x4737, "Rage Software" }, { 0x4837, "Encore" }, { 0x4A37, "Zoo" }, { 0x4B37, "BVM" }, { 0x4C37, "Simon & Schuster Interactive" }, { 0x4D37, "Asmik Ace Entertainment Inc./AIA" }, { 0x4E37, "Empire Interactive?" }, { 0x5137, "Jester Interactive" }, { 0x5437, "Scholastic" }, { 0x5537, "Ignition Entertainment" }, { 0x5737, "Stadlbauer" }, { 0x3038, "Misawa" }, { 0x3138, "Teichiku" }, { 0x3238, "Namco Ltd." }, { 0x3338, "LOZC" }, { 0x3438, "KOEI" }, { 0x3638, "Tokuma Shoten Intermedia" }, { 0x3738, "Tsukuda Original" }, { 0x3838, "DATAM-Polystar" }, { 0x4238, "Bulletproof Software" }, { 0x4338, "Vic Tokai Inc." }, { 0x4538, "Character Soft" }, { 0x4638, "I'Max" }, { 0x4738, "Saurus" }, { 0x4A38, "General Entertainment" }, { 0x4E38, "Success" }, { 0x5038, "SEGA Japan" }, { 0x3039, "Takara Amusement" }, { 0x3139, "Chun Soft" }, { 0x3239, "Video System, McO'River???" }, { 0x3339, "BEC" }, { 0x3539, "Varie" }, { 0x3639, "Yonezawa/S'pal" }, { 0x3739, "Kaneko" }, { 0x3939, "Victor Interactive Software, Pack in Video" }, { 0x4139, "Nichibutsu/Nihon Bussan" }, { 0x4239, "Tecmo" }, { 0x4339, "Imagineer" }, { 0x4639, "Nova" }, { 0x4739, "Den'Z" }, { 0x4839, "Bottom Up" }, { 0x4A39, "TGL" }, { 0x4C39, "Hasbro Japan?" }, { 0x4E39, "Marvelous Entertainment" }, { 0x5039, "Keynet Inc." }, { 0x5139, "Hands-On Entertainment" }, { 0x3041, "Telenet" }, { 0x3141, "Hori" }, { 0x3441, "Konami" }, { 0x3541, "K.Amusement Leasing Co." }, { 0x3641, "Kawada" }, { 0x3741, "Takara" }, { 0x3941, "Technos Japan Corp." }, { 0x4141, "JVC, Victor Musical Indutries" }, { 0x4341, "Toei Animation" }, { 0x4441, "Toho" }, { 0x4641, "Namco" }, { 0x4741, "Media Rings Corporation" }, { 0x4841, "J-Wing" }, { 0x4A41, "Pioneer LDC" }, { 0x4B41, "KID" }, { 0x4C41, "Mediafactory" }, { 0x5041, "Infogrames Hudson" }, { 0x5141, "Kiratto. Ludic Inc" }, { 0x3042, "Acclaim Japan" }, { 0x3142, "ASCII (was Nexoft?)" }, { 0x3242, "Bandai" }, { 0x3442, "Enix" }, { 0x3642, "HAL Laboratory" }, { 0x3742, "SNK" }, { 0x3942, "Pony Canyon" }, { 0x4142, "Culture Brain" }, { 0x4242, "Sunsoft" }, { 0x4342, "Toshiba EMI" }, { 0x4442, "Sony Imagesoft" }, { 0x4642, "Sammy" }, { 0x4742, "Magical" }, { 0x4842, "Visco" }, { 0x4A42, "Compile " }, { 0x4C42, "MTO Inc." }, { 0x4E42, "Sunrise Interactive" }, { 0x5042, "Global A Entertainment" }, { 0x5142, "Fuuki" }, { 0x3043, "Taito" }, { 0x3243, "Kemco" }, { 0x3343, "Square" }, { 0x3443, "Tokuma Shoten" }, { 0x3543, "Data East" }, { 0x3643, "Tonkin House (was Tokyo Shoseki)" }, { 0x3843, "Koei" }, { 0x4143, "Konami/Ultra/Palcom" }, { 0x4243, "NTVIC/VAP" }, { 0x4343, "Use Co.,Ltd." }, { 0x4443, "Meldac" }, { 0x4543, "Pony Canyon" }, { 0x4643, "Angel, Sotsu Agency/Sunrise" }, { 0x4A43, "Boss" }, { 0x4743, "Yumedia/Aroma Co., Ltd" }, { 0x4B43, "Axela/Crea-Tech?" }, { 0x4C43, "Sekaibunka-Sha, Sumire kobo?, Marigul Management Inc.?" }, { 0x4D43, "Konami Computer Entertainment Osaka" }, { 0x5043, "Enterbrain" }, { 0x3044, "Taito/Disco" }, { 0x3144, "Sofel" }, { 0x3244, "Quest, Bothtec" }, { 0x3344, "Sigma, ?????" }, { 0x3444, "Ask Kodansha" }, { 0x3644, "Naxat" }, { 0x3744, "Copya System" }, { 0x3844, "Capcom Co., Ltd." }, { 0x3944, "Banpresto" }, { 0x4144, "TOMY" }, { 0x4244, "LJN Japan" }, { 0x4444, "NCS" }, { 0x4544, "Human Entertainment" }, { 0x4644, "Altron" }, { 0x4744, "Jaleco???" }, { 0x4844, "Gaps Inc." }, { 0x4C44, "????" }, { 0x4E44, "Elf" }, { 0x3045, "Jaleco" }, { 0x3145, "????" }, { 0x3245, "Yutaka" }, { 0x3345, "Varie" }, { 0x3445, "T&ESoft" }, { 0x3545, "Epoch" }, { 0x3745, "Athena" }, { 0x3845, "Asmik" }, { 0x3945, "Natsume" }, { 0x4145, "King Records" }, { 0x4245, "Atlus" }, { 0x4345, "Epic/Sony Records" }, { 0x4545, "IGS" }, { 0x4745, "Chatnoir" }, { 0x4845, "Right Stuff" }, { 0x4C45, "Spike" }, { 0x4D45, "Konami Computer Entertainment Tokyo" }, { 0x4E45, "Alphadream Corporation" }, { 0x3046, "A Wave" }, { 0x3146, "Motown Software" }, { 0x3246, "Left Field Entertainment" }, { 0x3346, "Extreme Ent. Grp." }, { 0x3446, "TecMagik" }, { 0x3946, "Cybersoft" }, { 0x4246, "Psygnosis" }, { 0x4546, "Davidson/Western Tech." }, { 0x3147, "PCCW Japan" }, { 0x3447, "KiKi Co Ltd" }, { 0x3547, "Open Sesame Inc???" }, { 0x3647, "Sims" }, { 0x3747, "Broccoli" }, { 0x3847, "Avex" }, { 0x3947, "D3 Publisher" }, { 0x4247, "Konami Computer Entertainment Japan" }, { 0x4447, "Square-Enix" }, { 0x4849, "Yojigen" }, }; const char *getDeveloperNameByID(uint16_t id) { uint32_t i; for (i = 0; i < ARRAY_SIZE(makerCodes); i++) { if (makerCodes[i].code == id) return makerCodes[i].name; } return "Unknown"; } // =============================================================================== // Message dialogs // =============================================================================== void msgFakeInfo(const char *fmt, ...) { va_list args; va_start (args, fmt); vprintf (fmt, args); va_end (args); } bool msgFakeConfirm(const char *fmt, ...) { va_list args; va_start (args, fmt); vprintf (fmt, args); va_end (args); return true; } void msgFakeError(const char *fmt, ...) { va_list args; va_start (args, fmt); vprintf (fmt, args); va_end (args); } void msgFakeWarn(const char *fmt, ...) { va_list args; va_start (args, fmt); vprintf (fmt, args); va_end (args); } msgBoxInterface msgBoxFake = { msgFakeInfo, msgFakeConfirm, msgFakeError, msgFakeWarn, }; msgBoxInterface *msgbox = &msgBoxFake; desmume/src/instruction_tabdef.inc000664 001750 001750 00001005056 12755534123 020527 0ustar00sergiosergio000000 000000 /* Copyright (C) 2006 yopyop Copyright (C) 2007-2012 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the this software. If not, see . */ /* 0XX000X0 */ /* 0000 0000 0000 */ TABDECL(OP_AND_LSL_IMM), // OP_AND_LSL_IMM /* 0000 0000 0001 */ TABDECL(OP_AND_LSL_REG), // OP_AND_LSL_REG /* 0000 0000 0010 */ TABDECL(OP_AND_LSR_IMM), // OP_AND_LSR_IMM /* 0000 0000 0011 */ TABDECL(OP_AND_LSR_REG), // OP_AND_LSR_REG /* 0000 0000 0100 */ TABDECL(OP_AND_ASR_IMM), // OP_AND_ASR_IMM /* 0000 0000 0101 */ TABDECL(OP_AND_ASR_REG), // OP_AND_ASR_REG /* 0000 0000 0110 */ TABDECL(OP_AND_ROR_IMM), // OP_AND_ROR_IMM /* 0000 0000 0111 */ TABDECL(OP_AND_ROR_REG), // OP_AND_ROR_REG /* 0000 0000 1000 */ TABDECL(OP_AND_LSL_IMM), // OP_AND_LSL_IMM /* 0000 0000 1001 */ TABDECL(OP_MUL), // OP_MUL /* 0000 0000 1010 */ TABDECL(OP_AND_LSR_IMM), // OP_AND_LSR_IMM /* 0000 0000 1011 */ TABDECL(OP_STRH_POS_INDE_M_REG_OFF), // OP_STRH_POS_INDE_M_REG_OFF /* 0000 0000 1100 */ TABDECL(OP_AND_ASR_IMM), // OP_AND_ASR_IMM /* 0000 0000 1101 */ TABDECL(OP_LDRD_STRD_POST_INDEX), // OP_LDRD_STRD_POST_INDEX /* 0000 0000 1110 */ TABDECL(OP_AND_ROR_IMM), // OP_AND_ROR_IMM /* 0000 0000 1111 */ TABDECL(OP_LDRD_STRD_POST_INDEX), // OP_LDRD_STRD_POST_INDEX /* 0000 0001 0000 */ TABDECL(OP_AND_S_LSL_IMM), // OP_AND_S_LSL_IMM /* 0000 0001 0001 */ TABDECL(OP_AND_S_LSL_REG), // OP_AND_S_LSL_REG /* 0000 0001 0010 */ TABDECL(OP_AND_S_LSR_IMM), // OP_AND_S_LSR_IMM /* 0000 0001 0011 */ TABDECL(OP_AND_S_LSR_REG), // OP_AND_S_LSR_REG /* 0000 0001 0100 */ TABDECL(OP_AND_S_ASR_IMM), // OP_AND_S_ASR_IMM /* 0000 0001 0101 */ TABDECL(OP_AND_S_ASR_REG), // OP_AND_S_ASR_REG /* 0000 0001 0110 */ TABDECL(OP_AND_S_ROR_IMM), // OP_AND_S_ROR_IMM /* 0000 0001 0111 */ TABDECL(OP_AND_S_ROR_REG), // OP_AND_S_ROR_REG /* 0000 0001 1000 */ TABDECL(OP_AND_S_LSL_IMM), // OP_AND_S_LSL_IMM /* 0000 0001 1001 */ TABDECL(OP_MUL_S), // OP_MUL_S /* 0000 0001 1010 */ TABDECL(OP_AND_S_LSR_IMM), // OP_AND_S_LSR_IMM /* 0000 0001 1011 */ TABDECL(OP_LDRH_POS_INDE_M_REG_OFF), // OP_LDRH_POS_INDE_M_REG_OFF /* 0000 0001 1100 */ TABDECL(OP_AND_S_ASR_IMM), // OP_AND_S_ASR_IMM /* 0000 0001 1101 */ TABDECL(OP_LDRSB_POS_INDE_M_REG_OFF), // OP_LDRSB_POS_INDE_M_REG_OFF /* 0000 0001 1110 */ TABDECL(OP_AND_S_ROR_IMM), // OP_AND_S_ROR_IMM /* 0000 0001 1111 */ TABDECL(OP_LDRSH_POS_INDE_M_REG_OFF), // OP_LDRSH_POS_INDE_M_REG_OFF /* 0000 0010 0000 */ TABDECL(OP_EOR_LSL_IMM), // OP_EOR_LSL_IMM /* 0000 0010 0001 */ TABDECL(OP_EOR_LSL_REG), // OP_EOR_LSL_REG /* 0000 0010 0010 */ TABDECL(OP_EOR_LSR_IMM), // OP_EOR_LSR_IMM /* 0000 0010 0011 */ TABDECL(OP_EOR_LSR_REG), // OP_EOR_LSR_REG /* 0000 0010 0100 */ TABDECL(OP_EOR_ASR_IMM), // OP_EOR_ASR_IMM /* 0000 0010 0101 */ TABDECL(OP_EOR_ASR_REG), // OP_EOR_ASR_REG /* 0000 0010 0110 */ TABDECL(OP_EOR_ROR_IMM), // OP_EOR_ROR_IMM /* 0000 0010 0111 */ TABDECL(OP_EOR_ROR_REG), // OP_EOR_ROR_REG /* 0000 0010 1000 */ TABDECL(OP_EOR_LSL_IMM), // OP_EOR_LSL_IMM /* 0000 0010 1001 */ TABDECL(OP_MLA), // OP_MLA /* 0000 0010 1010 */ TABDECL(OP_EOR_LSR_IMM), // OP_EOR_LSR_IMM /* 0000 0010 1011 */ TABDECL(OP_UND), /* 0000 0010 1100 */ TABDECL(OP_EOR_ASR_IMM), // OP_EOR_ASR_IMM /* 0000 0010 1101 */ TABDECL(OP_UND), /* 0000 0010 1110 */ TABDECL(OP_EOR_ROR_IMM), // OP_EOR_ROR_IMM /* 0000 0010 1111 */ TABDECL(OP_UND), /* 0000 0011 0000 */ TABDECL(OP_EOR_S_LSL_IMM), // OP_EOR_S_LSL_IMM /* 0000 0011 0001 */ TABDECL(OP_EOR_S_LSL_REG), // OP_EOR_S_LSL_REG /* 0000 0011 0010 */ TABDECL(OP_EOR_S_LSR_IMM), // OP_EOR_S_LSR_IMM /* 0000 0011 0011 */ TABDECL(OP_EOR_S_LSR_REG), // OP_EOR_S_LSR_REG /* 0000 0011 0100 */ TABDECL(OP_EOR_S_ASR_IMM), // OP_EOR_S_ASR_IMM /* 0000 0011 0101 */ TABDECL(OP_EOR_S_ASR_REG), // OP_EOR_S_ASR_REG /* 0000 0011 0110 */ TABDECL(OP_EOR_S_ROR_IMM), // OP_EOR_S_ROR_IMM /* 0000 0011 0111 */ TABDECL(OP_EOR_S_ROR_REG), // OP_EOR_S_ROR_REG /* 0000 0011 1000 */ TABDECL(OP_EOR_S_LSL_IMM), // OP_EOR_S_LSL_IMM /* 0000 0011 1001 */ TABDECL(OP_MLA_S), // OP_MLA_S /* 0000 0011 1010 */ TABDECL(OP_EOR_S_LSR_IMM), // OP_EOR_S_LSR_IMM /* 0000 0011 1011 */ TABDECL(OP_UND), /* 0000 0011 1100 */ TABDECL(OP_EOR_S_ASR_IMM), // OP_EOR_S_ASR_IMM /* 0000 0011 1101 */ TABDECL(OP_UND), /* 0000 0011 1110 */ TABDECL(OP_EOR_S_ROR_IMM), // OP_EOR_S_ROR_IMM /* 0000 0011 1111 */ TABDECL(OP_UND), /* 0000 0100 0000 */ TABDECL(OP_SUB_LSL_IMM), // OP_SUB_LSL_IMM /* 0000 0100 0001 */ TABDECL(OP_SUB_LSL_REG), // OP_SUB_LSL_REG /* 0000 0100 0010 */ TABDECL(OP_SUB_LSR_IMM), // OP_SUB_LSR_IMM /* 0000 0100 0011 */ TABDECL(OP_SUB_LSR_REG), // OP_SUB_LSR_REG /* 0000 0100 0100 */ TABDECL(OP_SUB_ASR_IMM), // OP_SUB_ASR_IMM /* 0000 0100 0101 */ TABDECL(OP_SUB_ASR_REG), // OP_SUB_ASR_REG /* 0000 0100 0110 */ TABDECL(OP_SUB_ROR_IMM), // OP_SUB_ROR_IMM /* 0000 0100 0111 */ TABDECL(OP_SUB_ROR_REG), // OP_SUB_ROR_REG /* 0000 0100 1000 */ TABDECL(OP_SUB_LSL_IMM), // OP_SUB_LSL_IMM /* 0000 0100 1001 */ TABDECL(OP_UND), /* 0000 0100 1010 */ TABDECL(OP_SUB_LSR_IMM), // OP_SUB_LSR_IMM /* 0000 0100 1011 */ TABDECL(OP_STRH_POS_INDE_M_IMM_OFF), // OP_STRH_POS_INDE_M_IMM_OFF /* 0000 0100 1100 */ TABDECL(OP_SUB_ASR_IMM), // OP_SUB_ASR_IMM /* 0000 0100 1101 */ TABDECL(OP_LDRD_STRD_POST_INDEX), // OP_LDRD_STRD_POST_INDEX /* 0000 0100 1110 */ TABDECL(OP_SUB_ROR_IMM), // OP_SUB_ROR_IMM /* 0000 0100 1111 */ TABDECL(OP_LDRD_STRD_POST_INDEX), // OP_LDRD_STRD_POST_INDEX /* 0000 0101 0000 */ TABDECL(OP_SUB_S_LSL_IMM), // OP_SUB_S_LSL_IMM /* 0000 0101 0001 */ TABDECL(OP_SUB_S_LSL_REG), // OP_SUB_S_LSL_REG /* 0000 0101 0010 */ TABDECL(OP_SUB_S_LSR_IMM), // OP_SUB_S_LSR_IMM /* 0000 0101 0011 */ TABDECL(OP_SUB_S_LSR_REG), // OP_SUB_S_LSR_REG /* 0000 0101 0100 */ TABDECL(OP_SUB_S_ASR_IMM), // OP_SUB_S_ASR_IMM /* 0000 0101 0101 */ TABDECL(OP_SUB_S_ASR_REG), // OP_SUB_S_ASR_REG /* 0000 0101 0110 */ TABDECL(OP_SUB_S_ROR_IMM), // OP_SUB_S_ROR_IMM /* 0000 0101 0111 */ TABDECL(OP_SUB_S_ROR_REG), // OP_SUB_S_ROR_REG /* 0000 0101 1000 */ TABDECL(OP_SUB_S_LSL_IMM), // OP_SUB_S_LSL_IMM /* 0000 0101 1001 */ TABDECL(OP_UND), /* 0000 0101 1010 */ TABDECL(OP_SUB_S_LSR_IMM), // OP_SUB_S_LSR_IMM /* 0000 0101 1011 */ TABDECL(OP_LDRH_POS_INDE_M_IMM_OFF), // OP_LDRH_POS_INDE_M_IMM_OFF /* 0000 0101 1100 */ TABDECL(OP_SUB_S_ASR_IMM), // OP_SUB_S_ASR_IMM /* 0000 0101 1101 */ TABDECL(OP_LDRSB_POS_INDE_M_IMM_OFF), // OP_LDRSB_POS_INDE_M_IMM_OFF /* 0000 0101 1110 */ TABDECL(OP_SUB_S_ROR_IMM), // OP_SUB_S_ROR_IMM /* 0000 0101 1111 */ TABDECL(OP_LDRSH_POS_INDE_M_IMM_OFF), // OP_LDRSH_POS_INDE_M_IMM_OFF /* 0000 0110 0000 */ TABDECL(OP_RSB_LSL_IMM), // OP_RSB_LSL_IMM /* 0000 0110 0001 */ TABDECL(OP_RSB_LSL_REG), // OP_RSB_LSL_REG /* 0000 0110 0010 */ TABDECL(OP_RSB_LSR_IMM), // OP_RSB_LSR_IMM /* 0000 0110 0011 */ TABDECL(OP_RSB_LSR_REG), // OP_RSB_LSR_REG /* 0000 0110 0100 */ TABDECL(OP_RSB_ASR_IMM), // OP_RSB_ASR_IMM /* 0000 0110 0101 */ TABDECL(OP_RSB_ASR_REG), // OP_RSB_ASR_REG /* 0000 0110 0110 */ TABDECL(OP_RSB_ROR_IMM), // OP_RSB_ROR_IMM /* 0000 0110 0111 */ TABDECL(OP_RSB_ROR_REG), // OP_RSB_ROR_REG /* 0000 0110 1000 */ TABDECL(OP_RSB_LSL_IMM), // OP_RSB_LSL_IMM /* 0000 0110 1001 */ TABDECL(OP_UND), /* 0000 0110 1010 */ TABDECL(OP_RSB_LSR_IMM), // OP_RSB_LSR_IMM /* 0000 0110 1011 */ TABDECL(OP_UND), /* 0000 0110 1100 */ TABDECL(OP_RSB_ASR_IMM), // OP_RSB_ASR_IMM /* 0000 0110 1101 */ TABDECL(OP_UND), /* 0000 0110 1110 */ TABDECL(OP_RSB_ROR_IMM), // OP_RSB_ROR_IMM /* 0000 0110 1111 */ TABDECL(OP_UND), /* 0000 0111 0000 */ TABDECL(OP_RSB_S_LSL_IMM), // OP_RSB_S_LSL_IMM /* 0000 0111 0001 */ TABDECL(OP_RSB_S_LSL_REG), // OP_RSB_S_LSL_REG /* 0000 0111 0010 */ TABDECL(OP_RSB_S_LSR_IMM), // OP_RSB_S_LSR_IMM /* 0000 0111 0011 */ TABDECL(OP_RSB_S_LSR_REG), // OP_RSB_S_LSR_REG /* 0000 0111 0100 */ TABDECL(OP_RSB_S_ASR_IMM), // OP_RSB_S_ASR_IMM /* 0000 0111 0101 */ TABDECL(OP_RSB_S_ASR_REG), // OP_RSB_S_ASR_REG /* 0000 0111 0110 */ TABDECL(OP_RSB_S_ROR_IMM), // OP_RSB_S_ROR_IMM /* 0000 0111 0111 */ TABDECL(OP_RSB_S_ROR_REG), // OP_RSB_S_ROR_REG /* 0000 0111 1000 */ TABDECL(OP_RSB_S_LSL_IMM), // OP_RSB_S_LSL_IMM /* 0000 0111 1001 */ TABDECL(OP_UND), /* 0000 0111 1010 */ TABDECL(OP_RSB_S_LSR_IMM), // OP_RSB_S_LSR_IMM /* 0000 0111 1011 */ TABDECL(OP_UND), /* 0000 0111 1100 */ TABDECL(OP_RSB_S_ASR_IMM), // OP_RSB_S_ASR_IMM /* 0000 0111 1101 */ TABDECL(OP_UND), /* 0000 0111 1110 */ TABDECL(OP_RSB_S_ROR_IMM), // OP_RSB_S_ROR_IMM /* 0000 0111 1111 */ TABDECL(OP_UND), /* 0000 1000 0000 */ TABDECL(OP_ADD_LSL_IMM), // OP_ADD_LSL_IMM /* 0000 1000 0001 */ TABDECL(OP_ADD_LSL_REG), // OP_ADD_LSL_REG /* 0000 1000 0010 */ TABDECL(OP_ADD_LSR_IMM), // OP_ADD_LSR_IMM /* 0000 1000 0011 */ TABDECL(OP_ADD_LSR_REG), // OP_ADD_LSR_REG /* 0000 1000 0100 */ TABDECL(OP_ADD_ASR_IMM), // OP_ADD_ASR_IMM /* 0000 1000 0101 */ TABDECL(OP_ADD_ASR_REG), // OP_ADD_ASR_REG /* 0000 1000 0110 */ TABDECL(OP_ADD_ROR_IMM), // OP_ADD_ROR_IMM /* 0000 1000 0111 */ TABDECL(OP_ADD_ROR_REG), // OP_ADD_ROR_REG /* 0000 1000 1000 */ TABDECL(OP_ADD_LSL_IMM), // OP_ADD_LSL_IMM /* 0000 1000 1001 */ TABDECL(OP_UMULL), // OP_UMULL /* 0000 1000 1010 */ TABDECL(OP_ADD_LSR_IMM), // OP_ADD_LSR_IMM /* 0000 1000 1011 */ TABDECL(OP_STRH_POS_INDE_P_REG_OFF), // OP_STRH_POS_INDE_P_REG_OFF /* 0000 1000 1100 */ TABDECL(OP_ADD_ASR_IMM), // OP_ADD_ASR_IMM /* 0000 1000 1101 */ TABDECL(OP_LDRD_STRD_POST_INDEX), // OP_LDRD_STRD_POST_INDEX /* 0000 1000 1110 */ TABDECL(OP_ADD_ROR_IMM), // OP_ADD_ROR_IMM /* 0000 1000 1111 */ TABDECL(OP_LDRD_STRD_POST_INDEX), // OP_LDRD_STRD_POST_INDEX /* 0000 1001 0000 */ TABDECL(OP_ADD_S_LSL_IMM), // OP_ADD_S_LSL_IMM /* 0000 1001 0001 */ TABDECL(OP_ADD_S_LSL_REG), // OP_ADD_S_LSL_REG /* 0000 1001 0010 */ TABDECL(OP_ADD_S_LSR_IMM), // OP_ADD_S_LSR_IMM /* 0000 1001 0011 */ TABDECL(OP_ADD_S_LSR_REG), // OP_ADD_S_LSR_REG /* 0000 1001 0100 */ TABDECL(OP_ADD_S_ASR_IMM), // OP_ADD_S_ASR_IMM /* 0000 1001 0101 */ TABDECL(OP_ADD_S_ASR_REG), // OP_ADD_S_ASR_REG /* 0000 1001 0110 */ TABDECL(OP_ADD_S_ROR_IMM), // OP_ADD_S_ROR_IMM /* 0000 1001 0111 */ TABDECL(OP_ADD_S_ROR_REG), // OP_ADD_S_ROR_REG /* 0000 1001 1000 */ TABDECL(OP_ADD_S_LSL_IMM), // OP_ADD_S_LSL_IMM /* 0000 1001 1001 */ TABDECL(OP_UMULL_S), // OP_UMULL_S /* 0000 1001 1010 */ TABDECL(OP_ADD_S_LSR_IMM), // OP_ADD_S_LSR_IMM /* 0000 1001 1011 */ TABDECL(OP_LDRH_POS_INDE_P_REG_OFF), // OP_LDRH_POS_INDE_P_REG_OFF /* 0000 1001 1100 */ TABDECL(OP_ADD_S_ASR_IMM), // OP_ADD_S_ASR_IMM /* 0000 1001 1101 */ TABDECL(OP_LDRSB_POS_INDE_P_REG_OFF), // OP_LDRSB_POS_INDE_P_REG_OFF /* 0000 1001 1110 */ TABDECL(OP_ADD_S_ROR_IMM), // OP_ADD_S_ROR_IMM /* 0000 1001 1111 */ TABDECL(OP_LDRSH_POS_INDE_P_REG_OFF), // OP_LDRSH_POS_INDE_P_REG_OFF /* 0000 1010 0000 */ TABDECL(OP_ADC_LSL_IMM), // OP_ADC_LSL_IMM /* 0000 1010 0001 */ TABDECL(OP_ADC_LSL_REG), // OP_ADC_LSL_REG /* 0000 1010 0010 */ TABDECL(OP_ADC_LSR_IMM), // OP_ADC_LSR_IMM /* 0000 1010 0011 */ TABDECL(OP_ADC_LSR_REG), // OP_ADC_LSR_REG /* 0000 1010 0100 */ TABDECL(OP_ADC_ASR_IMM), // OP_ADC_ASR_IMM /* 0000 1010 0101 */ TABDECL(OP_ADC_ASR_REG), // OP_ADC_ASR_REG /* 0000 1010 0110 */ TABDECL(OP_ADC_ROR_IMM), // OP_ADC_ROR_IMM /* 0000 1010 0111 */ TABDECL(OP_ADC_ROR_REG), // OP_ADC_ROR_REG /* 0000 1010 1000 */ TABDECL(OP_ADC_LSL_IMM), // OP_ADC_LSL_IMM /* 0000 1010 1001 */ TABDECL(OP_UMLAL), // OP_UMLAL /* 0000 1010 1010 */ TABDECL(OP_ADC_LSR_IMM), // OP_ADC_LSR_IMM /* 0000 1010 1011 */ TABDECL(OP_UND), /* 0000 1010 1100 */ TABDECL(OP_ADC_ASR_IMM), // OP_ADC_ASR_IMM /* 0000 1010 1101 */ TABDECL(OP_UND), /* 0000 1010 1110 */ TABDECL(OP_ADC_ROR_IMM), // OP_ADC_ROR_IMM /* 0000 1010 1111 */ TABDECL(OP_UND), /* 0000 1011 0000 */ TABDECL(OP_ADC_S_LSL_IMM), // OP_ADC_S_LSL_IMM /* 0000 1011 0001 */ TABDECL(OP_ADC_S_LSL_REG), // OP_ADC_S_LSL_REG /* 0000 1011 0010 */ TABDECL(OP_ADC_S_LSR_IMM), // OP_ADC_S_LSR_IMM /* 0000 1011 0011 */ TABDECL(OP_ADC_S_LSR_REG), // OP_ADC_S_LSR_REG /* 0000 1011 0100 */ TABDECL(OP_ADC_S_ASR_IMM), // OP_ADC_S_ASR_IMM /* 0000 1011 0101 */ TABDECL(OP_ADC_S_ASR_REG), // OP_ADC_S_ASR_REG /* 0000 1011 0110 */ TABDECL(OP_ADC_S_ROR_IMM), // OP_ADC_S_ROR_IMM /* 0000 1011 0111 */ TABDECL(OP_ADC_S_ROR_REG), // OP_ADC_S_ROR_REG /* 0000 1011 1000 */ TABDECL(OP_ADC_S_LSL_IMM), // OP_ADC_S_LSL_IMM /* 0000 1011 1001 */ TABDECL(OP_UMLAL_S), // OP_UMLAL_S /* 0000 1011 1010 */ TABDECL(OP_ADC_S_LSR_IMM), // OP_ADC_S_LSR_IMM /* 0000 1011 1011 */ TABDECL(OP_UND), /* 0000 1011 1100 */ TABDECL(OP_ADC_S_ASR_IMM), // OP_ADC_S_ASR_IMM /* 0000 1011 1101 */ TABDECL(OP_UND), /* 0000 1011 1110 */ TABDECL(OP_ADC_S_ROR_IMM), // OP_ADC_S_ROR_IMM /* 0000 1011 1111 */ TABDECL(OP_UND), /* 0000 1100 0000 */ TABDECL(OP_SBC_LSL_IMM), // OP_SBC_LSL_IMM /* 0000 1100 0001 */ TABDECL(OP_SBC_LSL_REG), // OP_SBC_LSL_REG /* 0000 1100 0010 */ TABDECL(OP_SBC_LSR_IMM), // OP_SBC_LSR_IMM /* 0000 1100 0011 */ TABDECL(OP_SBC_LSR_REG), // OP_SBC_LSR_REG /* 0000 1100 0100 */ TABDECL(OP_SBC_ASR_IMM), // OP_SBC_ASR_IMM /* 0000 1100 0101 */ TABDECL(OP_SBC_ASR_REG), // OP_SBC_ASR_REG /* 0000 1100 0110 */ TABDECL(OP_SBC_ROR_IMM), // OP_SBC_ROR_IMM /* 0000 1100 0111 */ TABDECL(OP_SBC_ROR_REG), // OP_SBC_ROR_REG /* 0000 1100 1000 */ TABDECL(OP_SBC_LSL_IMM), // OP_SBC_LSL_IMM /* 0000 1100 1001 */ TABDECL(OP_SMULL), // OP_SMULL /* 0000 1100 1010 */ TABDECL(OP_SBC_LSR_IMM), // OP_SBC_LSR_IMM /* 0000 1100 1011 */ TABDECL(OP_STRH_POS_INDE_P_IMM_OFF), // OP_STRH_POS_INDE_P_IMM_OFF /* 0000 1100 1100 */ TABDECL(OP_SBC_ASR_IMM), // OP_SBC_ASR_IMM /* 0000 1100 1101 */ TABDECL(OP_LDRD_STRD_POST_INDEX), // OP_LDRD_STRD_POST_INDEX /* 0000 1100 1110 */ TABDECL(OP_SBC_ROR_IMM), // OP_SBC_ROR_IMM /* 0000 1100 1111 */ TABDECL(OP_LDRD_STRD_POST_INDEX), // OP_LDRD_STRD_POST_INDEX /* 0000 1101 0000 */ TABDECL(OP_SBC_S_LSL_IMM), // OP_SBC_S_LSL_IMM /* 0000 1101 0001 */ TABDECL(OP_SBC_S_LSL_REG), // OP_SBC_S_LSL_REG /* 0000 1101 0010 */ TABDECL(OP_SBC_S_LSR_IMM), // OP_SBC_S_LSR_IMM /* 0000 1101 0011 */ TABDECL(OP_SBC_S_LSR_REG), // OP_SBC_S_LSR_REG /* 0000 1101 0100 */ TABDECL(OP_SBC_S_ASR_IMM), // OP_SBC_S_ASR_IMM /* 0000 1101 0101 */ TABDECL(OP_SBC_S_ASR_REG), // OP_SBC_S_ASR_REG /* 0000 1101 0110 */ TABDECL(OP_SBC_S_ROR_IMM), // OP_SBC_S_ROR_IMM /* 0000 1101 0111 */ TABDECL(OP_SBC_S_ROR_REG), // OP_SBC_S_ROR_REG /* 0000 1101 1000 */ TABDECL(OP_SBC_S_LSL_IMM), // OP_SBC_S_LSL_IMM /* 0000 1101 1001 */ TABDECL(OP_SMULL_S), // OP_SMULL_S /* 0000 1101 1010 */ TABDECL(OP_SBC_S_LSR_IMM), // OP_SBC_S_LSR_IMM /* 0000 1101 1011 */ TABDECL(OP_LDRH_POS_INDE_P_IMM_OFF), // OP_LDRH_POS_INDE_P_IMM_OFF /* 0000 1101 1100 */ TABDECL(OP_SBC_S_ASR_IMM), // OP_SBC_S_ASR_IMM /* 0000 1101 1101 */ TABDECL(OP_LDRSB_POS_INDE_P_IMM_OFF), // OP_LDRSB_POS_INDE_P_IMM_OFF /* 0000 1101 1110 */ TABDECL(OP_SBC_S_ROR_IMM), // OP_SBC_S_ROR_IMM /* 0000 1101 1111 */ TABDECL(OP_LDRSH_POS_INDE_P_IMM_OFF), // OP_LDRSH_POS_INDE_P_IMM_OFF /* 0000 1110 0000 */ TABDECL(OP_RSC_LSL_IMM), // OP_RSC_LSL_IMM /* 0000 1110 0001 */ TABDECL(OP_RSC_LSL_REG), // OP_RSC_LSL_REG /* 0000 1110 0010 */ TABDECL(OP_RSC_LSR_IMM), // OP_RSC_LSR_IMM /* 0000 1110 0011 */ TABDECL(OP_RSC_LSR_REG), // OP_RSC_LSR_REG /* 0000 1110 0100 */ TABDECL(OP_RSC_ASR_IMM), // OP_RSC_ASR_IMM /* 0000 1110 0101 */ TABDECL(OP_RSC_ASR_REG), // OP_RSC_ASR_REG /* 0000 1110 0110 */ TABDECL(OP_RSC_ROR_IMM), // OP_RSC_ROR_IMM /* 0000 1110 0111 */ TABDECL(OP_RSC_ROR_REG), // OP_RSC_ROR_REG /* 0000 1110 1000 */ TABDECL(OP_RSC_LSL_IMM), // OP_RSC_LSL_IMM /* 0000 1110 1001 */ TABDECL(OP_SMLAL), // OP_SMLAL /* 0000 1110 1010 */ TABDECL(OP_RSC_LSR_IMM), // OP_RSC_LSR_IMM /* 0000 1110 1011 */ TABDECL(OP_UND), /* 0000 1110 1100 */ TABDECL(OP_RSC_ASR_IMM), // OP_RSC_ASR_IMM /* 0000 1110 1101 */ TABDECL(OP_UND), /* 0000 1110 1110 */ TABDECL(OP_RSC_ROR_IMM), // OP_RSC_ROR_IMM /* 0000 1110 1111 */ TABDECL(OP_UND), /* 0000 1111 0000 */ TABDECL(OP_RSC_S_LSL_IMM), // OP_RSC_S_LSL_IMM /* 0000 1111 0001 */ TABDECL(OP_RSC_S_LSL_REG), // OP_RSC_S_LSL_REG /* 0000 1111 0010 */ TABDECL(OP_RSC_S_LSR_IMM), // OP_RSC_S_LSR_IMM /* 0000 1111 0011 */ TABDECL(OP_RSC_S_LSR_REG), // OP_RSC_S_LSR_REG /* 0000 1111 0100 */ TABDECL(OP_RSC_S_ASR_IMM), // OP_RSC_S_ASR_IMM /* 0000 1111 0101 */ TABDECL(OP_RSC_S_ASR_REG), // OP_RSC_S_ASR_REG /* 0000 1111 0110 */ TABDECL(OP_RSC_S_ROR_IMM), // OP_RSC_S_ROR_IMM /* 0000 1111 0111 */ TABDECL(OP_RSC_S_ROR_REG), // OP_RSC_S_ROR_REG /* 0000 1111 1000 */ TABDECL(OP_RSC_S_LSL_IMM), // OP_RSC_S_LSL_IMM /* 0000 1111 1001 */ TABDECL(OP_SMLAL_S), // OP_SMLAL_S /* 0000 1111 1010 */ TABDECL(OP_RSC_S_LSR_IMM), // OP_RSC_S_LSR_IMM /* 0000 1111 1011 */ TABDECL(OP_UND), /* 0000 1111 1100 */ TABDECL(OP_RSC_S_ASR_IMM), // OP_RSC_S_ASR_IMM /* 0000 1111 1101 */ TABDECL(OP_UND), /* 0000 1111 1110 */ TABDECL(OP_RSC_S_ROR_IMM), // OP_RSC_S_ROR_IMM /* 0000 1111 1111 */ TABDECL(OP_UND), /* 0001 0000 0000 */ TABDECL(OP_MRS_CPSR), // OP_MRS_CPSR /* 0001 0000 0001 */ TABDECL(OP_UND), /* 0001 0000 0010 */ TABDECL(OP_UND), /* 0001 0000 0011 */ TABDECL(OP_UND), /* 0001 0000 0100 */ TABDECL(OP_UND), /* 0001 0000 0101 */ TABDECL(OP_QADD), // OP_QADD /* 0001 0000 0110 */ TABDECL(OP_UND), /* 0001 0000 0111 */ TABDECL(OP_UND), /* 0001 0000 1000 */ TABDECL(OP_SMLA_B_B), // OP_SMLA_B_B /* 0001 0000 1001 */ TABDECL(OP_SWP), // OP_SWP /* 0001 0000 1010 */ TABDECL(OP_SMLA_T_B), // OP_SMLA_T_B /* 0001 0000 1011 */ TABDECL(OP_STRH_M_REG_OFF), // OP_STRH_M_REG_OFF /* 0001 0000 1100 */ TABDECL(OP_SMLA_B_T), // OP_SMLA_B_T /* 0001 0000 1101 */ TABDECL(OP_LDRD_STRD_OFFSET_PRE_INDEX), // OP_LDRD_STRD_OFFSET_PRE_INDEX /* 0001 0000 1110 */ TABDECL(OP_SMLA_T_T), // OP_SMLA_T_T /* 0001 0000 1111 */ TABDECL(OP_LDRD_STRD_OFFSET_PRE_INDEX), // OP_LDRD_STRD_OFFSET_PRE_INDEX /* 0001 0001 0000 */ TABDECL(OP_TST_LSL_IMM), // OP_TST_LSL_IMM /* 0001 0001 0001 */ TABDECL(OP_TST_LSL_REG), // OP_TST_LSL_REG /* 0001 0001 0010 */ TABDECL(OP_TST_LSR_IMM), // OP_TST_LSR_IMM /* 0001 0001 0011 */ TABDECL(OP_TST_LSR_REG), // OP_TST_LSR_REG /* 0001 0001 0100 */ TABDECL(OP_TST_ASR_IMM), // OP_TST_ASR_IMM /* 0001 0001 0101 */ TABDECL(OP_TST_ASR_REG), // OP_TST_ASR_REG /* 0001 0001 0110 */ TABDECL(OP_TST_ROR_IMM), // OP_TST_ROR_IMM /* 0001 0001 0111 */ TABDECL(OP_TST_ROR_REG), // OP_TST_ROR_REG /* 0001 0001 1000 */ TABDECL(OP_TST_LSL_IMM), // OP_TST_LSL_IMM /* 0001 0001 1001 */ TABDECL(OP_UND), /* 0001 0001 1010 */ TABDECL(OP_TST_LSR_IMM), // OP_TST_LSR_IMM /* 0001 0001 1011 */ TABDECL(OP_LDRH_M_REG_OFF), // OP_LDRH_M_REG_OFF /* 0001 0001 1100 */ TABDECL(OP_TST_ASR_IMM), // OP_TST_ASR_IMM /* 0001 0001 1101 */ TABDECL(OP_LDRSB_M_REG_OFF), // OP_LDRSB_M_REG_OFF /* 0001 0001 1110 */ TABDECL(OP_TST_ROR_IMM), // OP_TST_ROR_IMM /* 0001 0001 1111 */ TABDECL(OP_LDRSH_M_REG_OFF), // OP_LDRSH_M_REG_OFF /* 0001 0010 0000 */ TABDECL(OP_MSR_CPSR), // OP_MSR_CPSR /* 0001 0010 0001 */ TABDECL(OP_BX), // OP_BX /* 0001 0010 0010 */ TABDECL(OP_UND), /* 0001 0010 0011 */ TABDECL(OP_BLX_REG), // OP_BLX_REG /* 0001 0010 0100 */ TABDECL(OP_UND), /* 0001 0010 0101 */ TABDECL(OP_QSUB), // OP_QSUB /* 0001 0010 0110 */ TABDECL(OP_UND), /* 0001 0010 0111 */ TABDECL(OP_BKPT), // OP_BKPT /* 0001 0010 1000 */ TABDECL(OP_SMLAW_B), // OP_SMLAW_B /* 0001 0010 1001 */ TABDECL(OP_UND), /* 0001 0010 1010 */ TABDECL(OP_SMULW_B), // OP_SMULW_B /* 0001 0010 1011 */ TABDECL(OP_STRH_PRE_INDE_M_REG_OFF), // OP_STRH_PRE_INDE_M_REG_OFF /* 0001 0010 1100 */ TABDECL(OP_SMLAW_T), // OP_SMLAW_T /* 0001 0010 1101 */ TABDECL(OP_LDRD_STRD_OFFSET_PRE_INDEX), // OP_LDRD_STRD_OFFSET_PRE_INDEX /* 0001 0010 1110 */ TABDECL(OP_SMULW_T), // OP_SMULW_T /* 0001 0010 1111 */ TABDECL(OP_LDRD_STRD_OFFSET_PRE_INDEX), // OP_LDRD_STRD_OFFSET_PRE_INDEX /* 0001 0011 0000 */ TABDECL(OP_TEQ_LSL_IMM), // OP_TEQ_LSL_IMM /* 0001 0011 0001 */ TABDECL(OP_TEQ_LSL_REG), // OP_TEQ_LSL_REG /* 0001 0011 0010 */ TABDECL(OP_TEQ_LSR_IMM), // OP_TEQ_LSR_IMM /* 0001 0011 0011 */ TABDECL(OP_TEQ_LSR_REG), // OP_TEQ_LSR_REG /* 0001 0011 0100 */ TABDECL(OP_TEQ_ASR_IMM), // OP_TEQ_ASR_IMM /* 0001 0011 0101 */ TABDECL(OP_TEQ_ASR_REG), // OP_TEQ_ASR_REG /* 0001 0011 0110 */ TABDECL(OP_TEQ_ROR_IMM), // OP_TEQ_ROR_IMM /* 0001 0011 0111 */ TABDECL(OP_TEQ_ROR_REG), // OP_TEQ_ROR_REG /* 0001 0011 1000 */ TABDECL(OP_TEQ_LSL_IMM), // OP_TEQ_LSL_IMM /* 0001 0011 1001 */ TABDECL(OP_UND), /* 0001 0011 1010 */ TABDECL(OP_TEQ_LSR_IMM), // OP_TEQ_LSR_IMM /* 0001 0011 1011 */ TABDECL(OP_LDRH_PRE_INDE_M_REG_OFF), // OP_LDRH_PRE_INDE_M_REG_OFF /* 0001 0011 1100 */ TABDECL(OP_TEQ_ASR_IMM), // OP_TEQ_ASR_IMM /* 0001 0011 1101 */ TABDECL(OP_LDRSB_PRE_INDE_M_REG_OFF), // OP_LDRSB_PRE_INDE_M_REG_OFF /* 0001 0011 1110 */ TABDECL(OP_TEQ_ROR_IMM), // OP_TEQ_ROR_IMM /* 0001 0011 1111 */ TABDECL(OP_LDRSH_PRE_INDE_M_REG_OFF), // OP_LDRSH_PRE_INDE_M_REG_OFF /* 0001 0100 0000 */ TABDECL(OP_MRS_SPSR), // OP_MRS_SPSR /* 0001 0100 0001 */ TABDECL(OP_UND), /* 0001 0100 0010 */ TABDECL(OP_UND), /* 0001 0100 0011 */ TABDECL(OP_UND), /* 0001 0100 0100 */ TABDECL(OP_UND), /* 0001 0100 0101 */ TABDECL(OP_QDADD), // OP_QDADD /* 0001 0100 0110 */ TABDECL(OP_UND), /* 0001 0100 0111 */ TABDECL(OP_UND), /* 0001 0100 1000 */ TABDECL(OP_SMLAL_B_B), // OP_SMLAL_B_B /* 0001 0100 1001 */ TABDECL(OP_SWPB), // OP_SWPB /* 0001 0100 1010 */ TABDECL(OP_SMLAL_T_B), // OP_SMLAL_T_B /* 0001 0100 1011 */ TABDECL(OP_STRH_M_IMM_OFF), // OP_STRH_M_IMM_OFF /* 0001 0100 1100 */ TABDECL(OP_SMLAL_B_T), // OP_SMLAL_B_T /* 0001 0100 1101 */ TABDECL(OP_LDRD_STRD_OFFSET_PRE_INDEX), // OP_LDRD_STRD_OFFSET_PRE_INDEX /* 0001 0100 1110 */ TABDECL(OP_SMLAL_T_T), // OP_SMLAL_T_T /* 0001 0100 1111 */ TABDECL(OP_LDRD_STRD_OFFSET_PRE_INDEX), // OP_LDRD_STRD_OFFSET_PRE_INDEX /* 0001 0101 0000 */ TABDECL(OP_CMP_LSL_IMM), // OP_CMP_LSL_IMM /* 0001 0101 0001 */ TABDECL(OP_CMP_LSL_REG), // OP_CMP_LSL_REG /* 0001 0101 0010 */ TABDECL(OP_CMP_LSR_IMM), // OP_CMP_LSR_IMM /* 0001 0101 0011 */ TABDECL(OP_CMP_LSR_REG), // OP_CMP_LSR_REG /* 0001 0101 0100 */ TABDECL(OP_CMP_ASR_IMM), // OP_CMP_ASR_IMM /* 0001 0101 0101 */ TABDECL(OP_CMP_ASR_REG), // OP_CMP_ASR_REG /* 0001 0101 0110 */ TABDECL(OP_CMP_ROR_IMM), // OP_CMP_ROR_IMM /* 0001 0101 0111 */ TABDECL(OP_CMP_ROR_REG), // OP_CMP_ROR_REG /* 0001 0101 1000 */ TABDECL(OP_CMP_LSL_IMM), // OP_CMP_LSL_IMM /* 0001 0101 1001 */ TABDECL(OP_UND), /* 0001 0101 1010 */ TABDECL(OP_CMP_LSR_IMM), // OP_CMP_LSR_IMM /* 0001 0101 1011 */ TABDECL(OP_LDRH_M_IMM_OFF), // OP_LDRH_M_IMM_OFF /* 0001 0101 1100 */ TABDECL(OP_CMP_ASR_IMM), // OP_CMP_ASR_IMM /* 0001 0101 1101 */ TABDECL(OP_LDRSB_M_IMM_OFF), // OP_LDRSB_M_IMM_OFF /* 0001 0101 1110 */ TABDECL(OP_CMP_ROR_IMM), // OP_CMP_ROR_IMM /* 0001 0101 1111 */ TABDECL(OP_LDRSH_M_IMM_OFF), // OP_LDRSH_M_IMM_OFF /* 0001 0110 0000 */ TABDECL(OP_MSR_SPSR), // OP_MSR_SPSR /* 0001 0110 0001 */ TABDECL(OP_CLZ), // OP_CLZ /* 0001 0110 0010 */ TABDECL(OP_UND), /* 0001 0110 0011 */ TABDECL(OP_UND), /* 0001 0110 0100 */ TABDECL(OP_UND), /* 0001 0110 0101 */ TABDECL(OP_QDSUB), // OP_QDSUB /* 0001 0110 0110 */ TABDECL(OP_UND), /* 0001 0110 0111 */ TABDECL(OP_UND), /* 0001 0110 1000 */ TABDECL(OP_SMUL_B_B), // OP_SMUL_B_B /* 0001 0110 1001 */ TABDECL(OP_UND), /* 0001 0110 1010 */ TABDECL(OP_SMUL_T_B), // OP_SMUL_T_B /* 0001 0110 1011 */ TABDECL(OP_STRH_PRE_INDE_M_IMM_OFF), // OP_STRH_PRE_INDE_M_IMM_OFF /* 0001 0110 1100 */ TABDECL(OP_SMUL_B_T), // OP_SMUL_B_T /* 0001 0110 1101 */ TABDECL(OP_LDRD_STRD_OFFSET_PRE_INDEX), // OP_LDRD_STRD_OFFSET_PRE_INDEX /* 0001 0110 1110 */ TABDECL(OP_SMUL_T_T), // OP_SMUL_T_T /* 0001 0110 1111 */ TABDECL(OP_LDRD_STRD_OFFSET_PRE_INDEX), // OP_LDRD_STRD_OFFSET_PRE_INDEX /* 0001 0111 0000 */ TABDECL(OP_CMN_LSL_IMM), // OP_CMN_LSL_IMM /* 0001 0111 0001 */ TABDECL(OP_CMN_LSL_REG), // OP_CMN_LSL_REG /* 0001 0111 0010 */ TABDECL(OP_CMN_LSR_IMM), // OP_CMN_LSR_IMM /* 0001 0111 0011 */ TABDECL(OP_CMN_LSR_REG), // OP_CMN_LSR_REG /* 0001 0111 0100 */ TABDECL(OP_CMN_ASR_IMM), // OP_CMN_ASR_IMM /* 0001 0111 0101 */ TABDECL(OP_CMN_ASR_REG), // OP_CMN_ASR_REG /* 0001 0111 0110 */ TABDECL(OP_CMN_ROR_IMM), // OP_CMN_ROR_IMM /* 0001 0111 0111 */ TABDECL(OP_CMN_ROR_REG), // OP_CMN_ROR_REG /* 0001 0111 1000 */ TABDECL(OP_CMN_LSL_IMM), // OP_CMN_LSL_IMM /* 0001 0111 1001 */ TABDECL(OP_UND), /* 0001 0111 1010 */ TABDECL(OP_CMN_LSR_IMM), // OP_CMN_LSR_IMM /* 0001 0111 1011 */ TABDECL(OP_LDRH_PRE_INDE_M_IMM_OFF), // OP_LDRH_PRE_INDE_M_IMM_OFF /* 0001 0111 1100 */ TABDECL(OP_CMN_ASR_IMM), // OP_CMN_ASR_IMM /* 0001 0111 1101 */ TABDECL(OP_LDRSB_PRE_INDE_M_IMM_OFF), // OP_LDRSB_PRE_INDE_M_IMM_OFF /* 0001 0111 1110 */ TABDECL(OP_CMN_ROR_IMM), // OP_CMN_ROR_IMM /* 0001 0111 1111 */ TABDECL(OP_LDRSH_PRE_INDE_M_IMM_OFF), // OP_LDRSH_PRE_INDE_M_IMM_OFF /* 0001 1000 0000 */ TABDECL(OP_ORR_LSL_IMM), // OP_ORR_LSL_IMM /* 0001 1000 0001 */ TABDECL(OP_ORR_LSL_REG), // OP_ORR_LSL_REG /* 0001 1000 0010 */ TABDECL(OP_ORR_LSR_IMM), // OP_ORR_LSR_IMM /* 0001 1000 0011 */ TABDECL(OP_ORR_LSR_REG), // OP_ORR_LSR_REG /* 0001 1000 0100 */ TABDECL(OP_ORR_ASR_IMM), // OP_ORR_ASR_IMM /* 0001 1000 0101 */ TABDECL(OP_ORR_ASR_REG), // OP_ORR_ASR_REG /* 0001 1000 0110 */ TABDECL(OP_ORR_ROR_IMM), // OP_ORR_ROR_IMM /* 0001 1000 0111 */ TABDECL(OP_ORR_ROR_REG), // OP_ORR_ROR_REG /* 0001 1000 1000 */ TABDECL(OP_ORR_LSL_IMM), // OP_ORR_LSL_IMM /* 0001 1000 1001 */ TABDECL(OP_STREX), // OP_STREX /* 0001 1000 1010 */ TABDECL(OP_ORR_LSR_IMM), // OP_ORR_LSR_IMM /* 0001 1000 1011 */ TABDECL(OP_STRH_P_REG_OFF), // OP_STRH_P_REG_OFF /* 0001 1000 1100 */ TABDECL(OP_ORR_ASR_IMM), // OP_ORR_ASR_IMM /* 0001 1000 1101 */ TABDECL(OP_LDRD_STRD_OFFSET_PRE_INDEX), // OP_LDRD_STRD_OFFSET_PRE_INDEX /* 0001 1000 1110 */ TABDECL(OP_ORR_ROR_IMM), // OP_ORR_ROR_IMM /* 0001 1000 1111 */ TABDECL(OP_LDRD_STRD_OFFSET_PRE_INDEX), // OP_LDRD_STRD_OFFSET_PRE_INDEX /* 0001 1001 0000 */ TABDECL(OP_ORR_S_LSL_IMM), // OP_ORR_S_LSL_IMM /* 0001 1001 0001 */ TABDECL(OP_ORR_S_LSL_REG), // OP_ORR_S_LSL_REG /* 0001 1001 0010 */ TABDECL(OP_ORR_S_LSR_IMM), // OP_ORR_S_LSR_IMM /* 0001 1001 0011 */ TABDECL(OP_ORR_S_LSR_REG), // OP_ORR_S_LSR_REG /* 0001 1001 0100 */ TABDECL(OP_ORR_S_ASR_IMM), // OP_ORR_S_ASR_IMM /* 0001 1001 0101 */ TABDECL(OP_ORR_S_ASR_REG), // OP_ORR_S_ASR_REG /* 0001 1001 0110 */ TABDECL(OP_ORR_S_ROR_IMM), // OP_ORR_S_ROR_IMM /* 0001 1001 0111 */ TABDECL(OP_ORR_S_ROR_REG), // OP_ORR_S_ROR_REG /* 0001 1001 1000 */ TABDECL(OP_ORR_S_LSL_IMM), // OP_ORR_S_LSL_IMM /* 0001 1001 1001 */ TABDECL(OP_LDREX), // OP_LDREX /* 0001 1001 1010 */ TABDECL(OP_ORR_S_LSR_IMM), // OP_ORR_S_LSR_IMM /* 0001 1001 1011 */ TABDECL(OP_LDRH_P_REG_OFF), // OP_LDRH_P_REG_OFF /* 0001 1001 1100 */ TABDECL(OP_ORR_S_ASR_IMM), // OP_ORR_S_ASR_IMM /* 0001 1001 1101 */ TABDECL(OP_LDRSB_P_REG_OFF), // OP_LDRSB_P_REG_OFF /* 0001 1001 1110 */ TABDECL(OP_ORR_S_ROR_IMM), // OP_ORR_S_ROR_IMM /* 0001 1001 1111 */ TABDECL(OP_LDRSH_P_REG_OFF), // OP_LDRSH_P_REG_OFF /* 0001 1010 0000 */ TABDECL(OP_MOV_LSL_IMM), // OP_MOV_LSL_IMM /* 0001 1010 0001 */ TABDECL(OP_MOV_LSL_REG), // OP_MOV_LSL_REG /* 0001 1010 0010 */ TABDECL(OP_MOV_LSR_IMM), // OP_MOV_LSR_IMM /* 0001 1010 0011 */ TABDECL(OP_MOV_LSR_REG), // OP_MOV_LSR_REG /* 0001 1010 0100 */ TABDECL(OP_MOV_ASR_IMM), // OP_MOV_ASR_IMM /* 0001 1010 0101 */ TABDECL(OP_MOV_ASR_REG), // OP_MOV_ASR_REG /* 0001 1010 0110 */ TABDECL(OP_MOV_ROR_IMM), // OP_MOV_ROR_IMM /* 0001 1010 0111 */ TABDECL(OP_MOV_ROR_REG), // OP_MOV_ROR_REG /* 0001 1010 1000 */ TABDECL(OP_MOV_LSL_IMM), // OP_MOV_LSL_IMM /* 0001 1010 1001 */ TABDECL(OP_UND), /* 0001 1010 1010 */ TABDECL(OP_MOV_LSR_IMM), // OP_MOV_LSR_IMM /* 0001 1010 1011 */ TABDECL(OP_STRH_PRE_INDE_P_REG_OFF), // OP_STRH_PRE_INDE_P_REG_OFF /* 0001 1010 1100 */ TABDECL(OP_MOV_ASR_IMM), // OP_MOV_ASR_IMM /* 0001 1010 1101 */ TABDECL(OP_LDRD_STRD_OFFSET_PRE_INDEX), // OP_LDRD_STRD_OFFSET_PRE_INDEX /* 0001 1010 1110 */ TABDECL(OP_MOV_ROR_IMM), // OP_MOV_ROR_IMM /* 0001 1010 1111 */ TABDECL(OP_LDRD_STRD_OFFSET_PRE_INDEX), // OP_LDRD_STRD_OFFSET_PRE_INDEX /* 0001 1011 0000 */ TABDECL(OP_MOV_S_LSL_IMM), // OP_MOV_S_LSL_IMM /* 0001 1011 0001 */ TABDECL(OP_MOV_S_LSL_REG), // OP_MOV_S_LSL_REG /* 0001 1011 0010 */ TABDECL(OP_MOV_S_LSR_IMM), // OP_MOV_S_LSR_IMM /* 0001 1011 0011 */ TABDECL(OP_MOV_S_LSR_REG), // OP_MOV_S_LSR_REG /* 0001 1011 0100 */ TABDECL(OP_MOV_S_ASR_IMM), // OP_MOV_S_ASR_IMM /* 0001 1011 0101 */ TABDECL(OP_MOV_S_ASR_REG), // OP_MOV_S_ASR_REG /* 0001 1011 0110 */ TABDECL(OP_MOV_S_ROR_IMM), // OP_MOV_S_ROR_IMM /* 0001 1011 0111 */ TABDECL(OP_MOV_S_ROR_REG), // OP_MOV_S_ROR_REG /* 0001 1011 1000 */ TABDECL(OP_MOV_S_LSL_IMM), // OP_MOV_S_LSL_IMM /* 0001 1011 1001 */ TABDECL(OP_UND), /* 0001 1011 1010 */ TABDECL(OP_MOV_S_LSR_IMM), // OP_MOV_S_LSR_IMM /* 0001 1011 1011 */ TABDECL(OP_LDRH_PRE_INDE_P_REG_OFF), // OP_LDRH_PRE_INDE_P_REG_OFF /* 0001 1011 1100 */ TABDECL(OP_MOV_S_ASR_IMM), // OP_MOV_S_ASR_IMM /* 0001 1011 1101 */ TABDECL(OP_LDRSB_PRE_INDE_P_REG_OFF), // OP_LDRSB_PRE_INDE_P_REG_OFF /* 0001 1011 1110 */ TABDECL(OP_MOV_S_ROR_IMM), // OP_MOV_S_ROR_IMM /* 0001 1011 1111 */ TABDECL(OP_LDRSH_PRE_INDE_P_REG_OFF), // OP_LDRSH_PRE_INDE_P_REG_OFF /* 0001 1100 0000 */ TABDECL(OP_BIC_LSL_IMM), // OP_BIC_LSL_IMM /* 0001 1100 0001 */ TABDECL(OP_BIC_LSL_REG), // OP_BIC_LSL_REG /* 0001 1100 0010 */ TABDECL(OP_BIC_LSR_IMM), // OP_BIC_LSR_IMM /* 0001 1100 0011 */ TABDECL(OP_BIC_LSR_REG), // OP_BIC_LSR_REG /* 0001 1100 0100 */ TABDECL(OP_BIC_ASR_IMM), // OP_BIC_ASR_IMM /* 0001 1100 0101 */ TABDECL(OP_BIC_ASR_REG), // OP_BIC_ASR_REG /* 0001 1100 0110 */ TABDECL(OP_BIC_ROR_IMM), // OP_BIC_ROR_IMM /* 0001 1100 0111 */ TABDECL(OP_BIC_ROR_REG), // OP_BIC_ROR_REG /* 0001 1100 1000 */ TABDECL(OP_BIC_LSL_IMM), // OP_BIC_LSL_IMM /* 0001 1100 1001 */ TABDECL(OP_UND), /* 0001 1100 1010 */ TABDECL(OP_BIC_LSR_IMM), // OP_BIC_LSR_IMM /* 0001 1100 1011 */ TABDECL(OP_STRH_P_IMM_OFF), // OP_STRH_P_IMM_OFF /* 0001 1100 1100 */ TABDECL(OP_BIC_ASR_IMM), // OP_BIC_ASR_IMM /* 0001 1100 1101 */ TABDECL(OP_LDRD_STRD_OFFSET_PRE_INDEX), // OP_LDRD_STRD_OFFSET_PRE_INDEX /* 0001 1100 1110 */ TABDECL(OP_BIC_ROR_IMM), // OP_BIC_ROR_IMM /* 0001 1100 1111 */ TABDECL(OP_LDRD_STRD_OFFSET_PRE_INDEX), // OP_LDRD_STRD_OFFSET_PRE_INDEX /* 0001 1101 0000 */ TABDECL(OP_BIC_S_LSL_IMM), // OP_BIC_S_LSL_IMM /* 0001 1101 0001 */ TABDECL(OP_BIC_S_LSL_REG), // OP_BIC_S_LSL_REG /* 0001 1101 0010 */ TABDECL(OP_BIC_S_LSR_IMM), // OP_BIC_S_LSR_IMM /* 0001 1101 0011 */ TABDECL(OP_BIC_S_LSR_REG), // OP_BIC_S_LSR_REG /* 0001 1101 0100 */ TABDECL(OP_BIC_S_ASR_IMM), // OP_BIC_S_ASR_IMM /* 0001 1101 0101 */ TABDECL(OP_BIC_S_ASR_REG), // OP_BIC_S_ASR_REG /* 0001 1101 0110 */ TABDECL(OP_BIC_S_ROR_IMM), // OP_BIC_S_ROR_IMM /* 0001 1101 0111 */ TABDECL(OP_BIC_S_ROR_REG), // OP_BIC_S_ROR_REG /* 0001 1101 1000 */ TABDECL(OP_BIC_S_LSL_IMM), // OP_BIC_S_LSL_IMM /* 0001 1101 1001 */ TABDECL(OP_UND), /* 0001 1101 1010 */ TABDECL(OP_BIC_S_LSR_IMM), // OP_BIC_S_LSR_IMM /* 0001 1101 1011 */ TABDECL(OP_LDRH_P_IMM_OFF), // OP_LDRH_P_IMM_OFF /* 0001 1101 1100 */ TABDECL(OP_BIC_S_ASR_IMM), // OP_BIC_S_ASR_IMM /* 0001 1101 1101 */ TABDECL(OP_LDRSB_P_IMM_OFF), // OP_LDRSB_P_IMM_OFF /* 0001 1101 1110 */ TABDECL(OP_BIC_S_ROR_IMM), // OP_BIC_S_ROR_IMM /* 0001 1101 1111 */ TABDECL(OP_LDRSH_P_IMM_OFF), // OP_LDRSH_P_IMM_OFF /* 0001 1110 0000 */ TABDECL(OP_MVN_LSL_IMM), // OP_MVN_LSL_IMM /* 0001 1110 0001 */ TABDECL(OP_MVN_LSL_REG), // OP_MVN_LSL_REG /* 0001 1110 0010 */ TABDECL(OP_MVN_LSR_IMM), // OP_MVN_LSR_IMM /* 0001 1110 0011 */ TABDECL(OP_MVN_LSR_REG), // OP_MVN_LSR_REG /* 0001 1110 0100 */ TABDECL(OP_MVN_ASR_IMM), // OP_MVN_ASR_IMM /* 0001 1110 0101 */ TABDECL(OP_MVN_ASR_REG), // OP_MVN_ASR_REG /* 0001 1110 0110 */ TABDECL(OP_MVN_ROR_IMM), // OP_MVN_ROR_IMM /* 0001 1110 0111 */ TABDECL(OP_MVN_ROR_REG), // OP_MVN_ROR_REG /* 0001 1110 1000 */ TABDECL(OP_MVN_LSL_IMM), // OP_MVN_LSL_IMM /* 0001 1110 1001 */ TABDECL(OP_UND), /* 0001 1110 1010 */ TABDECL(OP_MVN_LSR_IMM), // OP_MVN_LSR_IMM /* 0001 1110 1011 */ TABDECL(OP_STRH_PRE_INDE_P_IMM_OFF), // OP_STRH_PRE_INDE_P_IMM_OFF /* 0001 1110 1100 */ TABDECL(OP_MVN_ASR_IMM), // OP_MVN_ASR_IMM /* 0001 1110 1101 */ TABDECL(OP_LDRD_STRD_OFFSET_PRE_INDEX), // OP_LDRD_STRD_OFFSET_PRE_INDEX /* 0001 1110 1110 */ TABDECL(OP_MVN_ROR_IMM), // OP_MVN_ROR_IMM /* 0001 1110 1111 */ TABDECL(OP_LDRD_STRD_OFFSET_PRE_INDEX), // OP_LDRD_STRD_OFFSET_PRE_INDEX /* 0001 1111 0000 */ TABDECL(OP_MVN_S_LSL_IMM), // OP_MVN_S_LSL_IMM /* 0001 1111 0001 */ TABDECL(OP_MVN_S_LSL_REG), // OP_MVN_S_LSL_REG /* 0001 1111 0010 */ TABDECL(OP_MVN_S_LSR_IMM), // OP_MVN_S_LSR_IMM /* 0001 1111 0011 */ TABDECL(OP_MVN_S_LSR_REG), // OP_MVN_S_LSR_REG /* 0001 1111 0100 */ TABDECL(OP_MVN_S_ASR_IMM), // OP_MVN_S_ASR_IMM /* 0001 1111 0101 */ TABDECL(OP_MVN_S_ASR_REG), // OP_MVN_S_ASR_REG /* 0001 1111 0110 */ TABDECL(OP_MVN_S_ROR_IMM), // OP_MVN_S_ROR_IMM /* 0001 1111 0111 */ TABDECL(OP_MVN_S_ROR_REG), // OP_MVN_S_ROR_REG /* 0001 1111 1000 */ TABDECL(OP_MVN_S_LSL_IMM), // OP_MVN_S_LSL_IMM /* 0001 1111 1001 */ TABDECL(OP_UND), /* 0001 1111 1010 */ TABDECL(OP_MVN_S_LSR_IMM), // OP_MVN_S_LSR_IMM /* 0001 1111 1011 */ TABDECL(OP_LDRH_PRE_INDE_P_IMM_OFF), // OP_LDRH_PRE_INDE_P_IMM_OFF /* 0001 1111 1100 */ TABDECL(OP_MVN_S_ASR_IMM), // OP_MVN_S_ASR_IMM /* 0001 1111 1101 */ TABDECL(OP_LDRSB_PRE_INDE_P_IMM_OFF), // OP_LDRSB_PRE_INDE_P_IMM_OFF /* 0001 1111 1110 */ TABDECL(OP_MVN_S_ROR_IMM), // OP_MVN_S_ROR_IMM /* 0001 1111 1111 */ TABDECL(OP_LDRSH_PRE_INDE_P_IMM_OFF), // OP_LDRSH_PRE_INDE_P_IMM_OFF /* 0010 0000 0000 */ TABDECL(OP_AND_IMM_VAL), // OP_AND_IMM_VAL /* 0010 0000 0001 */ TABDECL(OP_AND_IMM_VAL), // OP_AND_IMM_VAL /* 0010 0000 0010 */ TABDECL(OP_AND_IMM_VAL), // OP_AND_IMM_VAL /* 0010 0000 0011 */ TABDECL(OP_AND_IMM_VAL), // OP_AND_IMM_VAL /* 0010 0000 0100 */ TABDECL(OP_AND_IMM_VAL), // OP_AND_IMM_VAL /* 0010 0000 0101 */ TABDECL(OP_AND_IMM_VAL), // OP_AND_IMM_VAL /* 0010 0000 0110 */ TABDECL(OP_AND_IMM_VAL), // OP_AND_IMM_VAL /* 0010 0000 0111 */ TABDECL(OP_AND_IMM_VAL), // OP_AND_IMM_VAL /* 0010 0000 1000 */ TABDECL(OP_AND_IMM_VAL), // OP_AND_IMM_VAL /* 0010 0000 1001 */ TABDECL(OP_AND_IMM_VAL), // OP_AND_IMM_VAL /* 0010 0000 1010 */ TABDECL(OP_AND_IMM_VAL), // OP_AND_IMM_VAL /* 0010 0000 1011 */ TABDECL(OP_AND_IMM_VAL), // OP_AND_IMM_VAL /* 0010 0000 1100 */ TABDECL(OP_AND_IMM_VAL), // OP_AND_IMM_VAL /* 0010 0000 1101 */ TABDECL(OP_AND_IMM_VAL), // OP_AND_IMM_VAL /* 0010 0000 1110 */ TABDECL(OP_AND_IMM_VAL), // OP_AND_IMM_VAL /* 0010 0000 1111 */ TABDECL(OP_AND_IMM_VAL), // OP_AND_IMM_VAL /* 0010 0001 0000 */ TABDECL(OP_AND_S_IMM_VAL), // OP_AND_S_IMM_VAL /* 0010 0001 0001 */ TABDECL(OP_AND_S_IMM_VAL), // OP_AND_S_IMM_VAL /* 0010 0001 0010 */ TABDECL(OP_AND_S_IMM_VAL), // OP_AND_S_IMM_VAL /* 0010 0001 0011 */ TABDECL(OP_AND_S_IMM_VAL), // OP_AND_S_IMM_VAL /* 0010 0001 0100 */ TABDECL(OP_AND_S_IMM_VAL), // OP_AND_S_IMM_VAL /* 0010 0001 0101 */ TABDECL(OP_AND_S_IMM_VAL), // OP_AND_S_IMM_VAL /* 0010 0001 0110 */ TABDECL(OP_AND_S_IMM_VAL), // OP_AND_S_IMM_VAL /* 0010 0001 0111 */ TABDECL(OP_AND_S_IMM_VAL), // OP_AND_S_IMM_VAL /* 0010 0001 1000 */ TABDECL(OP_AND_S_IMM_VAL), // OP_AND_S_IMM_VAL /* 0010 0001 1001 */ TABDECL(OP_AND_S_IMM_VAL), // OP_AND_S_IMM_VAL /* 0010 0001 1010 */ TABDECL(OP_AND_S_IMM_VAL), // OP_AND_S_IMM_VAL /* 0010 0001 1011 */ TABDECL(OP_AND_S_IMM_VAL), // OP_AND_S_IMM_VAL /* 0010 0001 1100 */ TABDECL(OP_AND_S_IMM_VAL), // OP_AND_S_IMM_VAL /* 0010 0001 1101 */ TABDECL(OP_AND_S_IMM_VAL), // OP_AND_S_IMM_VAL /* 0010 0001 1110 */ TABDECL(OP_AND_S_IMM_VAL), // OP_AND_S_IMM_VAL /* 0010 0001 1111 */ TABDECL(OP_AND_S_IMM_VAL), // OP_AND_S_IMM_VAL /* 0010 0010 0000 */ TABDECL(OP_EOR_IMM_VAL), // OP_EOR_IMM_VAL /* 0010 0010 0001 */ TABDECL(OP_EOR_IMM_VAL), // OP_EOR_IMM_VAL /* 0010 0010 0010 */ TABDECL(OP_EOR_IMM_VAL), // OP_EOR_IMM_VAL /* 0010 0010 0011 */ TABDECL(OP_EOR_IMM_VAL), // OP_EOR_IMM_VAL /* 0010 0010 0100 */ TABDECL(OP_EOR_IMM_VAL), // OP_EOR_IMM_VAL /* 0010 0010 0101 */ TABDECL(OP_EOR_IMM_VAL), // OP_EOR_IMM_VAL /* 0010 0010 0110 */ TABDECL(OP_EOR_IMM_VAL), // OP_EOR_IMM_VAL /* 0010 0010 0111 */ TABDECL(OP_EOR_IMM_VAL), // OP_EOR_IMM_VAL /* 0010 0010 1000 */ TABDECL(OP_EOR_IMM_VAL), // OP_EOR_IMM_VAL /* 0010 0010 1001 */ TABDECL(OP_EOR_IMM_VAL), // OP_EOR_IMM_VAL /* 0010 0010 1010 */ TABDECL(OP_EOR_IMM_VAL), // OP_EOR_IMM_VAL /* 0010 0010 1011 */ TABDECL(OP_EOR_IMM_VAL), // OP_EOR_IMM_VAL /* 0010 0010 1100 */ TABDECL(OP_EOR_IMM_VAL), // OP_EOR_IMM_VAL /* 0010 0010 1101 */ TABDECL(OP_EOR_IMM_VAL), // OP_EOR_IMM_VAL /* 0010 0010 1110 */ TABDECL(OP_EOR_IMM_VAL), // OP_EOR_IMM_VAL /* 0010 0010 1111 */ TABDECL(OP_EOR_IMM_VAL), // OP_EOR_IMM_VAL /* 0010 0011 0000 */ TABDECL(OP_EOR_S_IMM_VAL), // OP_EOR_S_IMM_VAL /* 0010 0011 0001 */ TABDECL(OP_EOR_S_IMM_VAL), // OP_EOR_S_IMM_VAL /* 0010 0011 0010 */ TABDECL(OP_EOR_S_IMM_VAL), // OP_EOR_S_IMM_VAL /* 0010 0011 0011 */ TABDECL(OP_EOR_S_IMM_VAL), // OP_EOR_S_IMM_VAL /* 0010 0011 0100 */ TABDECL(OP_EOR_S_IMM_VAL), // OP_EOR_S_IMM_VAL /* 0010 0011 0101 */ TABDECL(OP_EOR_S_IMM_VAL), // OP_EOR_S_IMM_VAL /* 0010 0011 0110 */ TABDECL(OP_EOR_S_IMM_VAL), // OP_EOR_S_IMM_VAL /* 0010 0011 0111 */ TABDECL(OP_EOR_S_IMM_VAL), // OP_EOR_S_IMM_VAL /* 0010 0011 1000 */ TABDECL(OP_EOR_S_IMM_VAL), // OP_EOR_S_IMM_VAL /* 0010 0011 1001 */ TABDECL(OP_EOR_S_IMM_VAL), // OP_EOR_S_IMM_VAL /* 0010 0011 1010 */ TABDECL(OP_EOR_S_IMM_VAL), // OP_EOR_S_IMM_VAL /* 0010 0011 1011 */ TABDECL(OP_EOR_S_IMM_VAL), // OP_EOR_S_IMM_VAL /* 0010 0011 1100 */ TABDECL(OP_EOR_S_IMM_VAL), // OP_EOR_S_IMM_VAL /* 0010 0011 1101 */ TABDECL(OP_EOR_S_IMM_VAL), // OP_EOR_S_IMM_VAL /* 0010 0011 1110 */ TABDECL(OP_EOR_S_IMM_VAL), // OP_EOR_S_IMM_VAL /* 0010 0011 1111 */ TABDECL(OP_EOR_S_IMM_VAL), // OP_EOR_S_IMM_VAL /* 0010 0100 0000 */ TABDECL(OP_SUB_IMM_VAL), // OP_SUB_IMM_VAL /* 0010 0100 0001 */ TABDECL(OP_SUB_IMM_VAL), // OP_SUB_IMM_VAL /* 0010 0100 0010 */ TABDECL(OP_SUB_IMM_VAL), // OP_SUB_IMM_VAL /* 0010 0100 0011 */ TABDECL(OP_SUB_IMM_VAL), // OP_SUB_IMM_VAL /* 0010 0100 0100 */ TABDECL(OP_SUB_IMM_VAL), // OP_SUB_IMM_VAL /* 0010 0100 0101 */ TABDECL(OP_SUB_IMM_VAL), // OP_SUB_IMM_VAL /* 0010 0100 0110 */ TABDECL(OP_SUB_IMM_VAL), // OP_SUB_IMM_VAL /* 0010 0100 0111 */ TABDECL(OP_SUB_IMM_VAL), // OP_SUB_IMM_VAL /* 0010 0100 1000 */ TABDECL(OP_SUB_IMM_VAL), // OP_SUB_IMM_VAL /* 0010 0100 1001 */ TABDECL(OP_SUB_IMM_VAL), // OP_SUB_IMM_VAL /* 0010 0100 1010 */ TABDECL(OP_SUB_IMM_VAL), // OP_SUB_IMM_VAL /* 0010 0100 1011 */ TABDECL(OP_SUB_IMM_VAL), // OP_SUB_IMM_VAL /* 0010 0100 1100 */ TABDECL(OP_SUB_IMM_VAL), // OP_SUB_IMM_VAL /* 0010 0100 1101 */ TABDECL(OP_SUB_IMM_VAL), // OP_SUB_IMM_VAL /* 0010 0100 1110 */ TABDECL(OP_SUB_IMM_VAL), // OP_SUB_IMM_VAL /* 0010 0100 1111 */ TABDECL(OP_SUB_IMM_VAL), // OP_SUB_IMM_VAL /* 0010 0101 0000 */ TABDECL(OP_SUB_S_IMM_VAL), // OP_SUB_S_IMM_VAL /* 0010 0101 0001 */ TABDECL(OP_SUB_S_IMM_VAL), // OP_SUB_S_IMM_VAL /* 0010 0101 0010 */ TABDECL(OP_SUB_S_IMM_VAL), // OP_SUB_S_IMM_VAL /* 0010 0101 0011 */ TABDECL(OP_SUB_S_IMM_VAL), // OP_SUB_S_IMM_VAL /* 0010 0101 0100 */ TABDECL(OP_SUB_S_IMM_VAL), // OP_SUB_S_IMM_VAL /* 0010 0101 0101 */ TABDECL(OP_SUB_S_IMM_VAL), // OP_SUB_S_IMM_VAL /* 0010 0101 0110 */ TABDECL(OP_SUB_S_IMM_VAL), // OP_SUB_S_IMM_VAL /* 0010 0101 0111 */ TABDECL(OP_SUB_S_IMM_VAL), // OP_SUB_S_IMM_VAL /* 0010 0101 1000 */ TABDECL(OP_SUB_S_IMM_VAL), // OP_SUB_S_IMM_VAL /* 0010 0101 1001 */ TABDECL(OP_SUB_S_IMM_VAL), // OP_SUB_S_IMM_VAL /* 0010 0101 1010 */ TABDECL(OP_SUB_S_IMM_VAL), // OP_SUB_S_IMM_VAL /* 0010 0101 1011 */ TABDECL(OP_SUB_S_IMM_VAL), // OP_SUB_S_IMM_VAL /* 0010 0101 1100 */ TABDECL(OP_SUB_S_IMM_VAL), // OP_SUB_S_IMM_VAL /* 0010 0101 1101 */ TABDECL(OP_SUB_S_IMM_VAL), // OP_SUB_S_IMM_VAL /* 0010 0101 1110 */ TABDECL(OP_SUB_S_IMM_VAL), // OP_SUB_S_IMM_VAL /* 0010 0101 1111 */ TABDECL(OP_SUB_S_IMM_VAL), // OP_SUB_S_IMM_VAL /* 0010 0110 0000 */ TABDECL(OP_RSB_IMM_VAL), // OP_RSB_IMM_VAL /* 0010 0110 0001 */ TABDECL(OP_RSB_IMM_VAL), // OP_RSB_IMM_VAL /* 0010 0110 0010 */ TABDECL(OP_RSB_IMM_VAL), // OP_RSB_IMM_VAL /* 0010 0110 0011 */ TABDECL(OP_RSB_IMM_VAL), // OP_RSB_IMM_VAL /* 0010 0110 0100 */ TABDECL(OP_RSB_IMM_VAL), // OP_RSB_IMM_VAL /* 0010 0110 0101 */ TABDECL(OP_RSB_IMM_VAL), // OP_RSB_IMM_VAL /* 0010 0110 0110 */ TABDECL(OP_RSB_IMM_VAL), // OP_RSB_IMM_VAL /* 0010 0110 0111 */ TABDECL(OP_RSB_IMM_VAL), // OP_RSB_IMM_VAL /* 0010 0110 1000 */ TABDECL(OP_RSB_IMM_VAL), // OP_RSB_IMM_VAL /* 0010 0110 1001 */ TABDECL(OP_RSB_IMM_VAL), // OP_RSB_IMM_VAL /* 0010 0110 1010 */ TABDECL(OP_RSB_IMM_VAL), // OP_RSB_IMM_VAL /* 0010 0110 1011 */ TABDECL(OP_RSB_IMM_VAL), // OP_RSB_IMM_VAL /* 0010 0110 1100 */ TABDECL(OP_RSB_IMM_VAL), // OP_RSB_IMM_VAL /* 0010 0110 1101 */ TABDECL(OP_RSB_IMM_VAL), // OP_RSB_IMM_VAL /* 0010 0110 1110 */ TABDECL(OP_RSB_IMM_VAL), // OP_RSB_IMM_VAL /* 0010 0110 1111 */ TABDECL(OP_RSB_IMM_VAL), // OP_RSB_IMM_VAL /* 0010 0111 0000 */ TABDECL(OP_RSB_S_IMM_VAL), // OP_RSB_S_IMM_VAL /* 0010 0111 0001 */ TABDECL(OP_RSB_S_IMM_VAL), // OP_RSB_S_IMM_VAL /* 0010 0111 0010 */ TABDECL(OP_RSB_S_IMM_VAL), // OP_RSB_S_IMM_VAL /* 0010 0111 0011 */ TABDECL(OP_RSB_S_IMM_VAL), // OP_RSB_S_IMM_VAL /* 0010 0111 0100 */ TABDECL(OP_RSB_S_IMM_VAL), // OP_RSB_S_IMM_VAL /* 0010 0111 0101 */ TABDECL(OP_RSB_S_IMM_VAL), // OP_RSB_S_IMM_VAL /* 0010 0111 0110 */ TABDECL(OP_RSB_S_IMM_VAL), // OP_RSB_S_IMM_VAL /* 0010 0111 0111 */ TABDECL(OP_RSB_S_IMM_VAL), // OP_RSB_S_IMM_VAL /* 0010 0111 1000 */ TABDECL(OP_RSB_S_IMM_VAL), // OP_RSB_S_IMM_VAL /* 0010 0111 1001 */ TABDECL(OP_RSB_S_IMM_VAL), // OP_RSB_S_IMM_VAL /* 0010 0111 1010 */ TABDECL(OP_RSB_S_IMM_VAL), // OP_RSB_S_IMM_VAL /* 0010 0111 1011 */ TABDECL(OP_RSB_S_IMM_VAL), // OP_RSB_S_IMM_VAL /* 0010 0111 1100 */ TABDECL(OP_RSB_S_IMM_VAL), // OP_RSB_S_IMM_VAL /* 0010 0111 1101 */ TABDECL(OP_RSB_S_IMM_VAL), // OP_RSB_S_IMM_VAL /* 0010 0111 1110 */ TABDECL(OP_RSB_S_IMM_VAL), // OP_RSB_S_IMM_VAL /* 0010 0111 1111 */ TABDECL(OP_RSB_S_IMM_VAL), // OP_RSB_S_IMM_VAL /* 0010 1000 0000 */ TABDECL(OP_ADD_IMM_VAL), // OP_ADD_IMM_VAL /* 0010 1000 0001 */ TABDECL(OP_ADD_IMM_VAL), // OP_ADD_IMM_VAL /* 0010 1000 0010 */ TABDECL(OP_ADD_IMM_VAL), // OP_ADD_IMM_VAL /* 0010 1000 0011 */ TABDECL(OP_ADD_IMM_VAL), // OP_ADD_IMM_VAL /* 0010 1000 0100 */ TABDECL(OP_ADD_IMM_VAL), // OP_ADD_IMM_VAL /* 0010 1000 0101 */ TABDECL(OP_ADD_IMM_VAL), // OP_ADD_IMM_VAL /* 0010 1000 0110 */ TABDECL(OP_ADD_IMM_VAL), // OP_ADD_IMM_VAL /* 0010 1000 0111 */ TABDECL(OP_ADD_IMM_VAL), // OP_ADD_IMM_VAL /* 0010 1000 1000 */ TABDECL(OP_ADD_IMM_VAL), // OP_ADD_IMM_VAL /* 0010 1000 1001 */ TABDECL(OP_ADD_IMM_VAL), // OP_ADD_IMM_VAL /* 0010 1000 1010 */ TABDECL(OP_ADD_IMM_VAL), // OP_ADD_IMM_VAL /* 0010 1000 1011 */ TABDECL(OP_ADD_IMM_VAL), // OP_ADD_IMM_VAL /* 0010 1000 1100 */ TABDECL(OP_ADD_IMM_VAL), // OP_ADD_IMM_VAL /* 0010 1000 1101 */ TABDECL(OP_ADD_IMM_VAL), // OP_ADD_IMM_VAL /* 0010 1000 1110 */ TABDECL(OP_ADD_IMM_VAL), // OP_ADD_IMM_VAL /* 0010 1000 1111 */ TABDECL(OP_ADD_IMM_VAL), // OP_ADD_IMM_VAL /* 0010 1001 0000 */ TABDECL(OP_ADD_S_IMM_VAL), // OP_ADD_S_IMM_VAL /* 0010 1001 0001 */ TABDECL(OP_ADD_S_IMM_VAL), // OP_ADD_S_IMM_VAL /* 0010 1001 0010 */ TABDECL(OP_ADD_S_IMM_VAL), // OP_ADD_S_IMM_VAL /* 0010 1001 0011 */ TABDECL(OP_ADD_S_IMM_VAL), // OP_ADD_S_IMM_VAL /* 0010 1001 0100 */ TABDECL(OP_ADD_S_IMM_VAL), // OP_ADD_S_IMM_VAL /* 0010 1001 0101 */ TABDECL(OP_ADD_S_IMM_VAL), // OP_ADD_S_IMM_VAL /* 0010 1001 0110 */ TABDECL(OP_ADD_S_IMM_VAL), // OP_ADD_S_IMM_VAL /* 0010 1001 0111 */ TABDECL(OP_ADD_S_IMM_VAL), // OP_ADD_S_IMM_VAL /* 0010 1001 1000 */ TABDECL(OP_ADD_S_IMM_VAL), // OP_ADD_S_IMM_VAL /* 0010 1001 1001 */ TABDECL(OP_ADD_S_IMM_VAL), // OP_ADD_S_IMM_VAL /* 0010 1001 1010 */ TABDECL(OP_ADD_S_IMM_VAL), // OP_ADD_S_IMM_VAL /* 0010 1001 1011 */ TABDECL(OP_ADD_S_IMM_VAL), // OP_ADD_S_IMM_VAL /* 0010 1001 1100 */ TABDECL(OP_ADD_S_IMM_VAL), // OP_ADD_S_IMM_VAL /* 0010 1001 1101 */ TABDECL(OP_ADD_S_IMM_VAL), // OP_ADD_S_IMM_VAL /* 0010 1001 1110 */ TABDECL(OP_ADD_S_IMM_VAL), // OP_ADD_S_IMM_VAL /* 0010 1001 1111 */ TABDECL(OP_ADD_S_IMM_VAL), // OP_ADD_S_IMM_VAL /* 0010 1010 0000 */ TABDECL(OP_ADC_IMM_VAL), // OP_ADC_IMM_VAL /* 0010 1010 0001 */ TABDECL(OP_ADC_IMM_VAL), // OP_ADC_IMM_VAL /* 0010 1010 0010 */ TABDECL(OP_ADC_IMM_VAL), // OP_ADC_IMM_VAL /* 0010 1010 0011 */ TABDECL(OP_ADC_IMM_VAL), // OP_ADC_IMM_VAL /* 0010 1010 0100 */ TABDECL(OP_ADC_IMM_VAL), // OP_ADC_IMM_VAL /* 0010 1010 0101 */ TABDECL(OP_ADC_IMM_VAL), // OP_ADC_IMM_VAL /* 0010 1010 0110 */ TABDECL(OP_ADC_IMM_VAL), // OP_ADC_IMM_VAL /* 0010 1010 0111 */ TABDECL(OP_ADC_IMM_VAL), // OP_ADC_IMM_VAL /* 0010 1010 1000 */ TABDECL(OP_ADC_IMM_VAL), // OP_ADC_IMM_VAL /* 0010 1010 1001 */ TABDECL(OP_ADC_IMM_VAL), // OP_ADC_IMM_VAL /* 0010 1010 1010 */ TABDECL(OP_ADC_IMM_VAL), // OP_ADC_IMM_VAL /* 0010 1010 1011 */ TABDECL(OP_ADC_IMM_VAL), // OP_ADC_IMM_VAL /* 0010 1010 1100 */ TABDECL(OP_ADC_IMM_VAL), // OP_ADC_IMM_VAL /* 0010 1010 1101 */ TABDECL(OP_ADC_IMM_VAL), // OP_ADC_IMM_VAL /* 0010 1010 1110 */ TABDECL(OP_ADC_IMM_VAL), // OP_ADC_IMM_VAL /* 0010 1010 1111 */ TABDECL(OP_ADC_IMM_VAL), // OP_ADC_IMM_VAL /* 0010 1011 0000 */ TABDECL(OP_ADC_S_IMM_VAL), // OP_ADC_S_IMM_VAL /* 0010 1011 0001 */ TABDECL(OP_ADC_S_IMM_VAL), // OP_ADC_S_IMM_VAL /* 0010 1011 0010 */ TABDECL(OP_ADC_S_IMM_VAL), // OP_ADC_S_IMM_VAL /* 0010 1011 0011 */ TABDECL(OP_ADC_S_IMM_VAL), // OP_ADC_S_IMM_VAL /* 0010 1011 0100 */ TABDECL(OP_ADC_S_IMM_VAL), // OP_ADC_S_IMM_VAL /* 0010 1011 0101 */ TABDECL(OP_ADC_S_IMM_VAL), // OP_ADC_S_IMM_VAL /* 0010 1011 0110 */ TABDECL(OP_ADC_S_IMM_VAL), // OP_ADC_S_IMM_VAL /* 0010 1011 0111 */ TABDECL(OP_ADC_S_IMM_VAL), // OP_ADC_S_IMM_VAL /* 0010 1011 1000 */ TABDECL(OP_ADC_S_IMM_VAL), // OP_ADC_S_IMM_VAL /* 0010 1011 1001 */ TABDECL(OP_ADC_S_IMM_VAL), // OP_ADC_S_IMM_VAL /* 0010 1011 1010 */ TABDECL(OP_ADC_S_IMM_VAL), // OP_ADC_S_IMM_VAL /* 0010 1011 1011 */ TABDECL(OP_ADC_S_IMM_VAL), // OP_ADC_S_IMM_VAL /* 0010 1011 1100 */ TABDECL(OP_ADC_S_IMM_VAL), // OP_ADC_S_IMM_VAL /* 0010 1011 1101 */ TABDECL(OP_ADC_S_IMM_VAL), // OP_ADC_S_IMM_VAL /* 0010 1011 1110 */ TABDECL(OP_ADC_S_IMM_VAL), // OP_ADC_S_IMM_VAL /* 0010 1011 1111 */ TABDECL(OP_ADC_S_IMM_VAL), // OP_ADC_S_IMM_VAL /* 0010 1100 0000 */ TABDECL(OP_SBC_IMM_VAL), // OP_SBC_IMM_VAL /* 0010 1100 0001 */ TABDECL(OP_SBC_IMM_VAL), // OP_SBC_IMM_VAL /* 0010 1100 0010 */ TABDECL(OP_SBC_IMM_VAL), // OP_SBC_IMM_VAL /* 0010 1100 0011 */ TABDECL(OP_SBC_IMM_VAL), // OP_SBC_IMM_VAL /* 0010 1100 0100 */ TABDECL(OP_SBC_IMM_VAL), // OP_SBC_IMM_VAL /* 0010 1100 0101 */ TABDECL(OP_SBC_IMM_VAL), // OP_SBC_IMM_VAL /* 0010 1100 0110 */ TABDECL(OP_SBC_IMM_VAL), // OP_SBC_IMM_VAL /* 0010 1100 0111 */ TABDECL(OP_SBC_IMM_VAL), // OP_SBC_IMM_VAL /* 0010 1100 1000 */ TABDECL(OP_SBC_IMM_VAL), // OP_SBC_IMM_VAL /* 0010 1100 1001 */ TABDECL(OP_SBC_IMM_VAL), // OP_SBC_IMM_VAL /* 0010 1100 1010 */ TABDECL(OP_SBC_IMM_VAL), // OP_SBC_IMM_VAL /* 0010 1100 1011 */ TABDECL(OP_SBC_IMM_VAL), // OP_SBC_IMM_VAL /* 0010 1100 1100 */ TABDECL(OP_SBC_IMM_VAL), // OP_SBC_IMM_VAL /* 0010 1100 1101 */ TABDECL(OP_SBC_IMM_VAL), // OP_SBC_IMM_VAL /* 0010 1100 1110 */ TABDECL(OP_SBC_IMM_VAL), // OP_SBC_IMM_VAL /* 0010 1100 1111 */ TABDECL(OP_SBC_IMM_VAL), // OP_SBC_IMM_VAL /* 0010 1101 0000 */ TABDECL(OP_SBC_S_IMM_VAL), // OP_SBC_S_IMM_VAL /* 0010 1101 0001 */ TABDECL(OP_SBC_S_IMM_VAL), // OP_SBC_S_IMM_VAL /* 0010 1101 0010 */ TABDECL(OP_SBC_S_IMM_VAL), // OP_SBC_S_IMM_VAL /* 0010 1101 0011 */ TABDECL(OP_SBC_S_IMM_VAL), // OP_SBC_S_IMM_VAL /* 0010 1101 0100 */ TABDECL(OP_SBC_S_IMM_VAL), // OP_SBC_S_IMM_VAL /* 0010 1101 0101 */ TABDECL(OP_SBC_S_IMM_VAL), // OP_SBC_S_IMM_VAL /* 0010 1101 0110 */ TABDECL(OP_SBC_S_IMM_VAL), // OP_SBC_S_IMM_VAL /* 0010 1101 0111 */ TABDECL(OP_SBC_S_IMM_VAL), // OP_SBC_S_IMM_VAL /* 0010 1101 1000 */ TABDECL(OP_SBC_S_IMM_VAL), // OP_SBC_S_IMM_VAL /* 0010 1101 1001 */ TABDECL(OP_SBC_S_IMM_VAL), // OP_SBC_S_IMM_VAL /* 0010 1101 1010 */ TABDECL(OP_SBC_S_IMM_VAL), // OP_SBC_S_IMM_VAL /* 0010 1101 1011 */ TABDECL(OP_SBC_S_IMM_VAL), // OP_SBC_S_IMM_VAL /* 0010 1101 1100 */ TABDECL(OP_SBC_S_IMM_VAL), // OP_SBC_S_IMM_VAL /* 0010 1101 1101 */ TABDECL(OP_SBC_S_IMM_VAL), // OP_SBC_S_IMM_VAL /* 0010 1101 1110 */ TABDECL(OP_SBC_S_IMM_VAL), // OP_SBC_S_IMM_VAL /* 0010 1101 1111 */ TABDECL(OP_SBC_S_IMM_VAL), // OP_SBC_S_IMM_VAL /* 0010 1110 0000 */ TABDECL(OP_RSC_IMM_VAL), // OP_RSC_IMM_VAL /* 0010 1110 0001 */ TABDECL(OP_RSC_IMM_VAL), // OP_RSC_IMM_VAL /* 0010 1110 0010 */ TABDECL(OP_RSC_IMM_VAL), // OP_RSC_IMM_VAL /* 0010 1110 0011 */ TABDECL(OP_RSC_IMM_VAL), // OP_RSC_IMM_VAL /* 0010 1110 0100 */ TABDECL(OP_RSC_IMM_VAL), // OP_RSC_IMM_VAL /* 0010 1110 0101 */ TABDECL(OP_RSC_IMM_VAL), // OP_RSC_IMM_VAL /* 0010 1110 0110 */ TABDECL(OP_RSC_IMM_VAL), // OP_RSC_IMM_VAL /* 0010 1110 0111 */ TABDECL(OP_RSC_IMM_VAL), // OP_RSC_IMM_VAL /* 0010 1110 1000 */ TABDECL(OP_RSC_IMM_VAL), // OP_RSC_IMM_VAL /* 0010 1110 1001 */ TABDECL(OP_RSC_IMM_VAL), // OP_RSC_IMM_VAL /* 0010 1110 1010 */ TABDECL(OP_RSC_IMM_VAL), // OP_RSC_IMM_VAL /* 0010 1110 1011 */ TABDECL(OP_RSC_IMM_VAL), // OP_RSC_IMM_VAL /* 0010 1110 1100 */ TABDECL(OP_RSC_IMM_VAL), // OP_RSC_IMM_VAL /* 0010 1110 1101 */ TABDECL(OP_RSC_IMM_VAL), // OP_RSC_IMM_VAL /* 0010 1110 1110 */ TABDECL(OP_RSC_IMM_VAL), // OP_RSC_IMM_VAL /* 0010 1110 1111 */ TABDECL(OP_RSC_IMM_VAL), // OP_RSC_IMM_VAL /* 0010 1111 0000 */ TABDECL(OP_RSC_S_IMM_VAL), // OP_RSC_S_IMM_VAL /* 0010 1111 0001 */ TABDECL(OP_RSC_S_IMM_VAL), // OP_RSC_S_IMM_VAL /* 0010 1111 0010 */ TABDECL(OP_RSC_S_IMM_VAL), // OP_RSC_S_IMM_VAL /* 0010 1111 0011 */ TABDECL(OP_RSC_S_IMM_VAL), // OP_RSC_S_IMM_VAL /* 0010 1111 0100 */ TABDECL(OP_RSC_S_IMM_VAL), // OP_RSC_S_IMM_VAL /* 0010 1111 0101 */ TABDECL(OP_RSC_S_IMM_VAL), // OP_RSC_S_IMM_VAL /* 0010 1111 0110 */ TABDECL(OP_RSC_S_IMM_VAL), // OP_RSC_S_IMM_VAL /* 0010 1111 0111 */ TABDECL(OP_RSC_S_IMM_VAL), // OP_RSC_S_IMM_VAL /* 0010 1111 1000 */ TABDECL(OP_RSC_S_IMM_VAL), // OP_RSC_S_IMM_VAL /* 0010 1111 1001 */ TABDECL(OP_RSC_S_IMM_VAL), // OP_RSC_S_IMM_VAL /* 0010 1111 1010 */ TABDECL(OP_RSC_S_IMM_VAL), // OP_RSC_S_IMM_VAL /* 0010 1111 1011 */ TABDECL(OP_RSC_S_IMM_VAL), // OP_RSC_S_IMM_VAL /* 0010 1111 1100 */ TABDECL(OP_RSC_S_IMM_VAL), // OP_RSC_S_IMM_VAL /* 0010 1111 1101 */ TABDECL(OP_RSC_S_IMM_VAL), // OP_RSC_S_IMM_VAL /* 0010 1111 1110 */ TABDECL(OP_RSC_S_IMM_VAL), // OP_RSC_S_IMM_VAL /* 0010 1111 1111 */ TABDECL(OP_RSC_S_IMM_VAL), // OP_RSC_S_IMM_VAL /* 0011 0000 0000 */ TABDECL(OP_UND), /* 0011 0000 0001 */ TABDECL(OP_UND), /* 0011 0000 0010 */ TABDECL(OP_UND), /* 0011 0000 0011 */ TABDECL(OP_UND), /* 0011 0000 0100 */ TABDECL(OP_UND), /* 0011 0000 0101 */ TABDECL(OP_UND), /* 0011 0000 0110 */ TABDECL(OP_UND), /* 0011 0000 0111 */ TABDECL(OP_UND), /* 0011 0000 1000 */ TABDECL(OP_UND), /* 0011 0000 1001 */ TABDECL(OP_UND), /* 0011 0000 1010 */ TABDECL(OP_UND), /* 0011 0000 1011 */ TABDECL(OP_UND), /* 0011 0000 1100 */ TABDECL(OP_UND), /* 0011 0000 1101 */ TABDECL(OP_UND), /* 0011 0000 1110 */ TABDECL(OP_UND), /* 0011 0000 1111 */ TABDECL(OP_UND), /* 0011 0001 0000 */ TABDECL(OP_TST_IMM_VAL), // OP_TST_IMM_VAL /* 0011 0001 0001 */ TABDECL(OP_TST_IMM_VAL), // OP_TST_IMM_VAL /* 0011 0001 0010 */ TABDECL(OP_TST_IMM_VAL), // OP_TST_IMM_VAL /* 0011 0001 0011 */ TABDECL(OP_TST_IMM_VAL), // OP_TST_IMM_VAL /* 0011 0001 0100 */ TABDECL(OP_TST_IMM_VAL), // OP_TST_IMM_VAL /* 0011 0001 0101 */ TABDECL(OP_TST_IMM_VAL), // OP_TST_IMM_VAL /* 0011 0001 0110 */ TABDECL(OP_TST_IMM_VAL), // OP_TST_IMM_VAL /* 0011 0001 0111 */ TABDECL(OP_TST_IMM_VAL), // OP_TST_IMM_VAL /* 0011 0001 1000 */ TABDECL(OP_TST_IMM_VAL), // OP_TST_IMM_VAL /* 0011 0001 1001 */ TABDECL(OP_TST_IMM_VAL), // OP_TST_IMM_VAL /* 0011 0001 1010 */ TABDECL(OP_TST_IMM_VAL), // OP_TST_IMM_VAL /* 0011 0001 1011 */ TABDECL(OP_TST_IMM_VAL), // OP_TST_IMM_VAL /* 0011 0001 1100 */ TABDECL(OP_TST_IMM_VAL), // OP_TST_IMM_VAL /* 0011 0001 1101 */ TABDECL(OP_TST_IMM_VAL), // OP_TST_IMM_VAL /* 0011 0001 1110 */ TABDECL(OP_TST_IMM_VAL), // OP_TST_IMM_VAL /* 0011 0001 1111 */ TABDECL(OP_TST_IMM_VAL), // OP_TST_IMM_VAL /* 0011 0010 0000 */ TABDECL(OP_MSR_CPSR_IMM_VAL), // OP_MSR_CPSR_IMM_VAL /* 0011 0010 0001 */ TABDECL(OP_MSR_CPSR_IMM_VAL), // OP_MSR_CPSR_IMM_VAL /* 0011 0010 0010 */ TABDECL(OP_MSR_CPSR_IMM_VAL), // OP_MSR_CPSR_IMM_VAL /* 0011 0010 0011 */ TABDECL(OP_MSR_CPSR_IMM_VAL), // OP_MSR_CPSR_IMM_VAL /* 0011 0010 0100 */ TABDECL(OP_MSR_CPSR_IMM_VAL), // OP_MSR_CPSR_IMM_VAL /* 0011 0010 0101 */ TABDECL(OP_MSR_CPSR_IMM_VAL), // OP_MSR_CPSR_IMM_VAL /* 0011 0010 0110 */ TABDECL(OP_MSR_CPSR_IMM_VAL), // OP_MSR_CPSR_IMM_VAL /* 0011 0010 0111 */ TABDECL(OP_MSR_CPSR_IMM_VAL), // OP_MSR_CPSR_IMM_VAL /* 0011 0010 1000 */ TABDECL(OP_MSR_CPSR_IMM_VAL), // OP_MSR_CPSR_IMM_VAL /* 0011 0010 1001 */ TABDECL(OP_MSR_CPSR_IMM_VAL), // OP_MSR_CPSR_IMM_VAL /* 0011 0010 1010 */ TABDECL(OP_MSR_CPSR_IMM_VAL), // OP_MSR_CPSR_IMM_VAL /* 0011 0010 1011 */ TABDECL(OP_MSR_CPSR_IMM_VAL), // OP_MSR_CPSR_IMM_VAL /* 0011 0010 1100 */ TABDECL(OP_MSR_CPSR_IMM_VAL), // OP_MSR_CPSR_IMM_VAL /* 0011 0010 1101 */ TABDECL(OP_MSR_CPSR_IMM_VAL), // OP_MSR_CPSR_IMM_VAL /* 0011 0010 1110 */ TABDECL(OP_MSR_CPSR_IMM_VAL), // OP_MSR_CPSR_IMM_VAL /* 0011 0010 1111 */ TABDECL(OP_MSR_CPSR_IMM_VAL), // OP_MSR_CPSR_IMM_VAL /* 0011 0011 0000 */ TABDECL(OP_TEQ_IMM_VAL), // OP_TEQ_IMM_VAL /* 0011 0011 0001 */ TABDECL(OP_TEQ_IMM_VAL), // OP_TEQ_IMM_VAL /* 0011 0011 0010 */ TABDECL(OP_TEQ_IMM_VAL), // OP_TEQ_IMM_VAL /* 0011 0011 0011 */ TABDECL(OP_TEQ_IMM_VAL), // OP_TEQ_IMM_VAL /* 0011 0011 0100 */ TABDECL(OP_TEQ_IMM_VAL), // OP_TEQ_IMM_VAL /* 0011 0011 0101 */ TABDECL(OP_TEQ_IMM_VAL), // OP_TEQ_IMM_VAL /* 0011 0011 0110 */ TABDECL(OP_TEQ_IMM_VAL), // OP_TEQ_IMM_VAL /* 0011 0011 0111 */ TABDECL(OP_TEQ_IMM_VAL), // OP_TEQ_IMM_VAL /* 0011 0011 1000 */ TABDECL(OP_TEQ_IMM_VAL), // OP_TEQ_IMM_VAL /* 0011 0011 1001 */ TABDECL(OP_TEQ_IMM_VAL), // OP_TEQ_IMM_VAL /* 0011 0011 1010 */ TABDECL(OP_TEQ_IMM_VAL), // OP_TEQ_IMM_VAL /* 0011 0011 1011 */ TABDECL(OP_TEQ_IMM_VAL), // OP_TEQ_IMM_VAL /* 0011 0011 1100 */ TABDECL(OP_TEQ_IMM_VAL), // OP_TEQ_IMM_VAL /* 0011 0011 1101 */ TABDECL(OP_TEQ_IMM_VAL), // OP_TEQ_IMM_VAL /* 0011 0011 1110 */ TABDECL(OP_TEQ_IMM_VAL), // OP_TEQ_IMM_VAL /* 0011 0011 1111 */ TABDECL(OP_TEQ_IMM_VAL), // OP_TEQ_IMM_VAL /* 0011 0100 0000 */ TABDECL(OP_UND), /* 0011 0100 0001 */ TABDECL(OP_UND), /* 0011 0100 0010 */ TABDECL(OP_UND), /* 0011 0100 0011 */ TABDECL(OP_UND), /* 0011 0100 0100 */ TABDECL(OP_UND), /* 0011 0100 0101 */ TABDECL(OP_UND), /* 0011 0100 0110 */ TABDECL(OP_UND), /* 0011 0100 0111 */ TABDECL(OP_UND), /* 0011 0100 1000 */ TABDECL(OP_UND), /* 0011 0100 1001 */ TABDECL(OP_UND), /* 0011 0100 1010 */ TABDECL(OP_UND), /* 0011 0100 1011 */ TABDECL(OP_UND), /* 0011 0100 1100 */ TABDECL(OP_UND), /* 0011 0100 1101 */ TABDECL(OP_UND), /* 0011 0100 1110 */ TABDECL(OP_UND), /* 0011 0100 1111 */ TABDECL(OP_UND), /* 0011 0101 0000 */ TABDECL(OP_CMP_IMM_VAL), // OP_CMP_IMM_VAL /* 0011 0101 0001 */ TABDECL(OP_CMP_IMM_VAL), // OP_CMP_IMM_VAL /* 0011 0101 0010 */ TABDECL(OP_CMP_IMM_VAL), // OP_CMP_IMM_VAL /* 0011 0101 0011 */ TABDECL(OP_CMP_IMM_VAL), // OP_CMP_IMM_VAL /* 0011 0101 0100 */ TABDECL(OP_CMP_IMM_VAL), // OP_CMP_IMM_VAL /* 0011 0101 0101 */ TABDECL(OP_CMP_IMM_VAL), // OP_CMP_IMM_VAL /* 0011 0101 0110 */ TABDECL(OP_CMP_IMM_VAL), // OP_CMP_IMM_VAL /* 0011 0101 0111 */ TABDECL(OP_CMP_IMM_VAL), // OP_CMP_IMM_VAL /* 0011 0101 1000 */ TABDECL(OP_CMP_IMM_VAL), // OP_CMP_IMM_VAL /* 0011 0101 1001 */ TABDECL(OP_CMP_IMM_VAL), // OP_CMP_IMM_VAL /* 0011 0101 1010 */ TABDECL(OP_CMP_IMM_VAL), // OP_CMP_IMM_VAL /* 0011 0101 1011 */ TABDECL(OP_CMP_IMM_VAL), // OP_CMP_IMM_VAL /* 0011 0101 1100 */ TABDECL(OP_CMP_IMM_VAL), // OP_CMP_IMM_VAL /* 0011 0101 1101 */ TABDECL(OP_CMP_IMM_VAL), // OP_CMP_IMM_VAL /* 0011 0101 1110 */ TABDECL(OP_CMP_IMM_VAL), // OP_CMP_IMM_VAL /* 0011 0101 1111 */ TABDECL(OP_CMP_IMM_VAL), // OP_CMP_IMM_VAL /* 0011 0110 0000 */ TABDECL(OP_MSR_SPSR_IMM_VAL), // OP_MSR_SPSR_IMM_VAL /* 0011 0110 0001 */ TABDECL(OP_MSR_SPSR_IMM_VAL), // OP_MSR_SPSR_IMM_VAL /* 0011 0110 0010 */ TABDECL(OP_MSR_SPSR_IMM_VAL), // OP_MSR_SPSR_IMM_VAL /* 0011 0110 0011 */ TABDECL(OP_MSR_SPSR_IMM_VAL), // OP_MSR_SPSR_IMM_VAL /* 0011 0110 0100 */ TABDECL(OP_MSR_SPSR_IMM_VAL), // OP_MSR_SPSR_IMM_VAL /* 0011 0110 0101 */ TABDECL(OP_MSR_SPSR_IMM_VAL), // OP_MSR_SPSR_IMM_VAL /* 0011 0110 0110 */ TABDECL(OP_MSR_SPSR_IMM_VAL), // OP_MSR_SPSR_IMM_VAL /* 0011 0110 0111 */ TABDECL(OP_MSR_SPSR_IMM_VAL), // OP_MSR_SPSR_IMM_VAL /* 0011 0110 1000 */ TABDECL(OP_MSR_SPSR_IMM_VAL), // OP_MSR_SPSR_IMM_VAL /* 0011 0110 1001 */ TABDECL(OP_MSR_SPSR_IMM_VAL), // OP_MSR_SPSR_IMM_VAL /* 0011 0110 1010 */ TABDECL(OP_MSR_SPSR_IMM_VAL), // OP_MSR_SPSR_IMM_VAL /* 0011 0110 1011 */ TABDECL(OP_MSR_SPSR_IMM_VAL), // OP_MSR_SPSR_IMM_VAL /* 0011 0110 1100 */ TABDECL(OP_MSR_SPSR_IMM_VAL), // OP_MSR_SPSR_IMM_VAL /* 0011 0110 1101 */ TABDECL(OP_MSR_SPSR_IMM_VAL), // OP_MSR_SPSR_IMM_VAL /* 0011 0110 1110 */ TABDECL(OP_MSR_SPSR_IMM_VAL), // OP_MSR_SPSR_IMM_VAL /* 0011 0110 1111 */ TABDECL(OP_MSR_SPSR_IMM_VAL), // OP_MSR_SPSR_IMM_VAL /* 0011 0111 0000 */ TABDECL(OP_CMN_IMM_VAL), // OP_CMN_IMM_VAL /* 0011 0111 0001 */ TABDECL(OP_CMN_IMM_VAL), // OP_CMN_IMM_VAL /* 0011 0111 0010 */ TABDECL(OP_CMN_IMM_VAL), // OP_CMN_IMM_VAL /* 0011 0111 0011 */ TABDECL(OP_CMN_IMM_VAL), // OP_CMN_IMM_VAL /* 0011 0111 0100 */ TABDECL(OP_CMN_IMM_VAL), // OP_CMN_IMM_VAL /* 0011 0111 0101 */ TABDECL(OP_CMN_IMM_VAL), // OP_CMN_IMM_VAL /* 0011 0111 0110 */ TABDECL(OP_CMN_IMM_VAL), // OP_CMN_IMM_VAL /* 0011 0111 0111 */ TABDECL(OP_CMN_IMM_VAL), // OP_CMN_IMM_VAL /* 0011 0111 1000 */ TABDECL(OP_CMN_IMM_VAL), // OP_CMN_IMM_VAL /* 0011 0111 1001 */ TABDECL(OP_CMN_IMM_VAL), // OP_CMN_IMM_VAL /* 0011 0111 1010 */ TABDECL(OP_CMN_IMM_VAL), // OP_CMN_IMM_VAL /* 0011 0111 1011 */ TABDECL(OP_CMN_IMM_VAL), // OP_CMN_IMM_VAL /* 0011 0111 1100 */ TABDECL(OP_CMN_IMM_VAL), // OP_CMN_IMM_VAL /* 0011 0111 1101 */ TABDECL(OP_CMN_IMM_VAL), // OP_CMN_IMM_VAL /* 0011 0111 1110 */ TABDECL(OP_CMN_IMM_VAL), // OP_CMN_IMM_VAL /* 0011 0111 1111 */ TABDECL(OP_CMN_IMM_VAL), // OP_CMN_IMM_VAL /* 0011 1000 0000 */ TABDECL(OP_ORR_IMM_VAL), // OP_ORR_IMM_VAL /* 0011 1000 0001 */ TABDECL(OP_ORR_IMM_VAL), // OP_ORR_IMM_VAL /* 0011 1000 0010 */ TABDECL(OP_ORR_IMM_VAL), // OP_ORR_IMM_VAL /* 0011 1000 0011 */ TABDECL(OP_ORR_IMM_VAL), // OP_ORR_IMM_VAL /* 0011 1000 0100 */ TABDECL(OP_ORR_IMM_VAL), // OP_ORR_IMM_VAL /* 0011 1000 0101 */ TABDECL(OP_ORR_IMM_VAL), // OP_ORR_IMM_VAL /* 0011 1000 0110 */ TABDECL(OP_ORR_IMM_VAL), // OP_ORR_IMM_VAL /* 0011 1000 0111 */ TABDECL(OP_ORR_IMM_VAL), // OP_ORR_IMM_VAL /* 0011 1000 1000 */ TABDECL(OP_ORR_IMM_VAL), // OP_ORR_IMM_VAL /* 0011 1000 1001 */ TABDECL(OP_ORR_IMM_VAL), // OP_ORR_IMM_VAL /* 0011 1000 1010 */ TABDECL(OP_ORR_IMM_VAL), // OP_ORR_IMM_VAL /* 0011 1000 1011 */ TABDECL(OP_ORR_IMM_VAL), // OP_ORR_IMM_VAL /* 0011 1000 1100 */ TABDECL(OP_ORR_IMM_VAL), // OP_ORR_IMM_VAL /* 0011 1000 1101 */ TABDECL(OP_ORR_IMM_VAL), // OP_ORR_IMM_VAL /* 0011 1000 1110 */ TABDECL(OP_ORR_IMM_VAL), // OP_ORR_IMM_VAL /* 0011 1000 1111 */ TABDECL(OP_ORR_IMM_VAL), // OP_ORR_IMM_VAL /* 0011 1001 0000 */ TABDECL(OP_ORR_S_IMM_VAL), // OP_ORR_S_IMM_VAL /* 0011 1001 0001 */ TABDECL(OP_ORR_S_IMM_VAL), // OP_ORR_S_IMM_VAL /* 0011 1001 0010 */ TABDECL(OP_ORR_S_IMM_VAL), // OP_ORR_S_IMM_VAL /* 0011 1001 0011 */ TABDECL(OP_ORR_S_IMM_VAL), // OP_ORR_S_IMM_VAL /* 0011 1001 0100 */ TABDECL(OP_ORR_S_IMM_VAL), // OP_ORR_S_IMM_VAL /* 0011 1001 0101 */ TABDECL(OP_ORR_S_IMM_VAL), // OP_ORR_S_IMM_VAL /* 0011 1001 0110 */ TABDECL(OP_ORR_S_IMM_VAL), // OP_ORR_S_IMM_VAL /* 0011 1001 0111 */ TABDECL(OP_ORR_S_IMM_VAL), // OP_ORR_S_IMM_VAL /* 0011 1001 1000 */ TABDECL(OP_ORR_S_IMM_VAL), // OP_ORR_S_IMM_VAL /* 0011 1001 1001 */ TABDECL(OP_ORR_S_IMM_VAL), // OP_ORR_S_IMM_VAL /* 0011 1001 1010 */ TABDECL(OP_ORR_S_IMM_VAL), // OP_ORR_S_IMM_VAL /* 0011 1001 1011 */ TABDECL(OP_ORR_S_IMM_VAL), // OP_ORR_S_IMM_VAL /* 0011 1001 1100 */ TABDECL(OP_ORR_S_IMM_VAL), // OP_ORR_S_IMM_VAL /* 0011 1001 1101 */ TABDECL(OP_ORR_S_IMM_VAL), // OP_ORR_S_IMM_VAL /* 0011 1001 1110 */ TABDECL(OP_ORR_S_IMM_VAL), // OP_ORR_S_IMM_VAL /* 0011 1001 1111 */ TABDECL(OP_ORR_S_IMM_VAL), // OP_ORR_S_IMM_VAL /* 0011 1010 0000 */ TABDECL(OP_MOV_IMM_VAL), // OP_MOV_IMM_VAL /* 0011 1010 0001 */ TABDECL(OP_MOV_IMM_VAL), // OP_MOV_IMM_VAL /* 0011 1010 0010 */ TABDECL(OP_MOV_IMM_VAL), // OP_MOV_IMM_VAL /* 0011 1010 0011 */ TABDECL(OP_MOV_IMM_VAL), // OP_MOV_IMM_VAL /* 0011 1010 0100 */ TABDECL(OP_MOV_IMM_VAL), // OP_MOV_IMM_VAL /* 0011 1010 0101 */ TABDECL(OP_MOV_IMM_VAL), // OP_MOV_IMM_VAL /* 0011 1010 0110 */ TABDECL(OP_MOV_IMM_VAL), // OP_MOV_IMM_VAL /* 0011 1010 0111 */ TABDECL(OP_MOV_IMM_VAL), // OP_MOV_IMM_VAL /* 0011 1010 1000 */ TABDECL(OP_MOV_IMM_VAL), // OP_MOV_IMM_VAL /* 0011 1010 1001 */ TABDECL(OP_MOV_IMM_VAL), // OP_MOV_IMM_VAL /* 0011 1010 1010 */ TABDECL(OP_MOV_IMM_VAL), // OP_MOV_IMM_VAL /* 0011 1010 1011 */ TABDECL(OP_MOV_IMM_VAL), // OP_MOV_IMM_VAL /* 0011 1010 1100 */ TABDECL(OP_MOV_IMM_VAL), // OP_MOV_IMM_VAL /* 0011 1010 1101 */ TABDECL(OP_MOV_IMM_VAL), // OP_MOV_IMM_VAL /* 0011 1010 1110 */ TABDECL(OP_MOV_IMM_VAL), // OP_MOV_IMM_VAL /* 0011 1010 1111 */ TABDECL(OP_MOV_IMM_VAL), // OP_MOV_IMM_VAL /* 0011 1011 0000 */ TABDECL(OP_MOV_S_IMM_VAL), // OP_MOV_S_IMM_VAL /* 0011 1011 0001 */ TABDECL(OP_MOV_S_IMM_VAL), // OP_MOV_S_IMM_VAL /* 0011 1011 0010 */ TABDECL(OP_MOV_S_IMM_VAL), // OP_MOV_S_IMM_VAL /* 0011 1011 0011 */ TABDECL(OP_MOV_S_IMM_VAL), // OP_MOV_S_IMM_VAL /* 0011 1011 0100 */ TABDECL(OP_MOV_S_IMM_VAL), // OP_MOV_S_IMM_VAL /* 0011 1011 0101 */ TABDECL(OP_MOV_S_IMM_VAL), // OP_MOV_S_IMM_VAL /* 0011 1011 0110 */ TABDECL(OP_MOV_S_IMM_VAL), // OP_MOV_S_IMM_VAL /* 0011 1011 0111 */ TABDECL(OP_MOV_S_IMM_VAL), // OP_MOV_S_IMM_VAL /* 0011 1011 1000 */ TABDECL(OP_MOV_S_IMM_VAL), // OP_MOV_S_IMM_VAL /* 0011 1011 1001 */ TABDECL(OP_MOV_S_IMM_VAL), // OP_MOV_S_IMM_VAL /* 0011 1011 1010 */ TABDECL(OP_MOV_S_IMM_VAL), // OP_MOV_S_IMM_VAL /* 0011 1011 1011 */ TABDECL(OP_MOV_S_IMM_VAL), // OP_MOV_S_IMM_VAL /* 0011 1011 1100 */ TABDECL(OP_MOV_S_IMM_VAL), // OP_MOV_S_IMM_VAL /* 0011 1011 1101 */ TABDECL(OP_MOV_S_IMM_VAL), // OP_MOV_S_IMM_VAL /* 0011 1011 1110 */ TABDECL(OP_MOV_S_IMM_VAL), // OP_MOV_S_IMM_VAL /* 0011 1011 1111 */ TABDECL(OP_MOV_S_IMM_VAL), // OP_MOV_S_IMM_VAL /* 0011 1100 0000 */ TABDECL(OP_BIC_IMM_VAL), // OP_BIC_IMM_VAL /* 0011 1100 0001 */ TABDECL(OP_BIC_IMM_VAL), // OP_BIC_IMM_VAL /* 0011 1100 0010 */ TABDECL(OP_BIC_IMM_VAL), // OP_BIC_IMM_VAL /* 0011 1100 0011 */ TABDECL(OP_BIC_IMM_VAL), // OP_BIC_IMM_VAL /* 0011 1100 0100 */ TABDECL(OP_BIC_IMM_VAL), // OP_BIC_IMM_VAL /* 0011 1100 0101 */ TABDECL(OP_BIC_IMM_VAL), // OP_BIC_IMM_VAL /* 0011 1100 0110 */ TABDECL(OP_BIC_IMM_VAL), // OP_BIC_IMM_VAL /* 0011 1100 0111 */ TABDECL(OP_BIC_IMM_VAL), // OP_BIC_IMM_VAL /* 0011 1100 1000 */ TABDECL(OP_BIC_IMM_VAL), // OP_BIC_IMM_VAL /* 0011 1100 1001 */ TABDECL(OP_BIC_IMM_VAL), // OP_BIC_IMM_VAL /* 0011 1100 1010 */ TABDECL(OP_BIC_IMM_VAL), // OP_BIC_IMM_VAL /* 0011 1100 1011 */ TABDECL(OP_BIC_IMM_VAL), // OP_BIC_IMM_VAL /* 0011 1100 1100 */ TABDECL(OP_BIC_IMM_VAL), // OP_BIC_IMM_VAL /* 0011 1100 1101 */ TABDECL(OP_BIC_IMM_VAL), // OP_BIC_IMM_VAL /* 0011 1100 1110 */ TABDECL(OP_BIC_IMM_VAL), // OP_BIC_IMM_VAL /* 0011 1100 1111 */ TABDECL(OP_BIC_IMM_VAL), // OP_BIC_IMM_VAL /* 0011 1101 0000 */ TABDECL(OP_BIC_S_IMM_VAL), // OP_BIC_S_IMM_VAL /* 0011 1101 0001 */ TABDECL(OP_BIC_S_IMM_VAL), // OP_BIC_S_IMM_VAL /* 0011 1101 0010 */ TABDECL(OP_BIC_S_IMM_VAL), // OP_BIC_S_IMM_VAL /* 0011 1101 0011 */ TABDECL(OP_BIC_S_IMM_VAL), // OP_BIC_S_IMM_VAL /* 0011 1101 0100 */ TABDECL(OP_BIC_S_IMM_VAL), // OP_BIC_S_IMM_VAL /* 0011 1101 0101 */ TABDECL(OP_BIC_S_IMM_VAL), // OP_BIC_S_IMM_VAL /* 0011 1101 0110 */ TABDECL(OP_BIC_S_IMM_VAL), // OP_BIC_S_IMM_VAL /* 0011 1101 0111 */ TABDECL(OP_BIC_S_IMM_VAL), // OP_BIC_S_IMM_VAL /* 0011 1101 1000 */ TABDECL(OP_BIC_S_IMM_VAL), // OP_BIC_S_IMM_VAL /* 0011 1101 1001 */ TABDECL(OP_BIC_S_IMM_VAL), // OP_BIC_S_IMM_VAL /* 0011 1101 1010 */ TABDECL(OP_BIC_S_IMM_VAL), // OP_BIC_S_IMM_VAL /* 0011 1101 1011 */ TABDECL(OP_BIC_S_IMM_VAL), // OP_BIC_S_IMM_VAL /* 0011 1101 1100 */ TABDECL(OP_BIC_S_IMM_VAL), // OP_BIC_S_IMM_VAL /* 0011 1101 1101 */ TABDECL(OP_BIC_S_IMM_VAL), // OP_BIC_S_IMM_VAL /* 0011 1101 1110 */ TABDECL(OP_BIC_S_IMM_VAL), // OP_BIC_S_IMM_VAL /* 0011 1101 1111 */ TABDECL(OP_BIC_S_IMM_VAL), // OP_BIC_S_IMM_VAL /* 0011 1110 0000 */ TABDECL(OP_MVN_IMM_VAL), // OP_MVN_IMM_VAL /* 0011 1110 0001 */ TABDECL(OP_MVN_IMM_VAL), // OP_MVN_IMM_VAL /* 0011 1110 0010 */ TABDECL(OP_MVN_IMM_VAL), // OP_MVN_IMM_VAL /* 0011 1110 0011 */ TABDECL(OP_MVN_IMM_VAL), // OP_MVN_IMM_VAL /* 0011 1110 0100 */ TABDECL(OP_MVN_IMM_VAL), // OP_MVN_IMM_VAL /* 0011 1110 0101 */ TABDECL(OP_MVN_IMM_VAL), // OP_MVN_IMM_VAL /* 0011 1110 0110 */ TABDECL(OP_MVN_IMM_VAL), // OP_MVN_IMM_VAL /* 0011 1110 0111 */ TABDECL(OP_MVN_IMM_VAL), // OP_MVN_IMM_VAL /* 0011 1110 1000 */ TABDECL(OP_MVN_IMM_VAL), // OP_MVN_IMM_VAL /* 0011 1110 1001 */ TABDECL(OP_MVN_IMM_VAL), // OP_MVN_IMM_VAL /* 0011 1110 1010 */ TABDECL(OP_MVN_IMM_VAL), // OP_MVN_IMM_VAL /* 0011 1110 1011 */ TABDECL(OP_MVN_IMM_VAL), // OP_MVN_IMM_VAL /* 0011 1110 1100 */ TABDECL(OP_MVN_IMM_VAL), // OP_MVN_IMM_VAL /* 0011 1110 1101 */ TABDECL(OP_MVN_IMM_VAL), // OP_MVN_IMM_VAL /* 0011 1110 1110 */ TABDECL(OP_MVN_IMM_VAL), // OP_MVN_IMM_VAL /* 0011 1110 1111 */ TABDECL(OP_MVN_IMM_VAL), // OP_MVN_IMM_VAL /* 0011 1111 0000 */ TABDECL(OP_MVN_S_IMM_VAL), // OP_MVN_S_IMM_VAL /* 0011 1111 0001 */ TABDECL(OP_MVN_S_IMM_VAL), // OP_MVN_S_IMM_VAL /* 0011 1111 0010 */ TABDECL(OP_MVN_S_IMM_VAL), // OP_MVN_S_IMM_VAL /* 0011 1111 0011 */ TABDECL(OP_MVN_S_IMM_VAL), // OP_MVN_S_IMM_VAL /* 0011 1111 0100 */ TABDECL(OP_MVN_S_IMM_VAL), // OP_MVN_S_IMM_VAL /* 0011 1111 0101 */ TABDECL(OP_MVN_S_IMM_VAL), // OP_MVN_S_IMM_VAL /* 0011 1111 0110 */ TABDECL(OP_MVN_S_IMM_VAL), // OP_MVN_S_IMM_VAL /* 0011 1111 0111 */ TABDECL(OP_MVN_S_IMM_VAL), // OP_MVN_S_IMM_VAL /* 0011 1111 1000 */ TABDECL(OP_MVN_S_IMM_VAL), // OP_MVN_S_IMM_VAL /* 0011 1111 1001 */ TABDECL(OP_MVN_S_IMM_VAL), // OP_MVN_S_IMM_VAL /* 0011 1111 1010 */ TABDECL(OP_MVN_S_IMM_VAL), // OP_MVN_S_IMM_VAL /* 0011 1111 1011 */ TABDECL(OP_MVN_S_IMM_VAL), // OP_MVN_S_IMM_VAL /* 0011 1111 1100 */ TABDECL(OP_MVN_S_IMM_VAL), // OP_MVN_S_IMM_VAL /* 0011 1111 1101 */ TABDECL(OP_MVN_S_IMM_VAL), // OP_MVN_S_IMM_VAL /* 0011 1111 1110 */ TABDECL(OP_MVN_S_IMM_VAL), // OP_MVN_S_IMM_VAL /* 0011 1111 1111 */ TABDECL(OP_MVN_S_IMM_VAL), // OP_MVN_S_IMM_VAL /* 0100 0000 0000 */ TABDECL(OP_STR_M_IMM_OFF_POSTIND), // OP_STR_M_IMM_OFF_POSTIND /* 0100 0000 0001 */ TABDECL(OP_STR_M_IMM_OFF_POSTIND), // OP_STR_M_IMM_OFF_POSTIND /* 0100 0000 0010 */ TABDECL(OP_STR_M_IMM_OFF_POSTIND), // OP_STR_M_IMM_OFF_POSTIND /* 0100 0000 0011 */ TABDECL(OP_STR_M_IMM_OFF_POSTIND), // OP_STR_M_IMM_OFF_POSTIND /* 0100 0000 0100 */ TABDECL(OP_STR_M_IMM_OFF_POSTIND), // OP_STR_M_IMM_OFF_POSTIND /* 0100 0000 0101 */ TABDECL(OP_STR_M_IMM_OFF_POSTIND), // OP_STR_M_IMM_OFF_POSTIND /* 0100 0000 0110 */ TABDECL(OP_STR_M_IMM_OFF_POSTIND), // OP_STR_M_IMM_OFF_POSTIND /* 0100 0000 0111 */ TABDECL(OP_STR_M_IMM_OFF_POSTIND), // OP_STR_M_IMM_OFF_POSTIND /* 0100 0000 1000 */ TABDECL(OP_STR_M_IMM_OFF_POSTIND), // OP_STR_M_IMM_OFF_POSTIND /* 0100 0000 1001 */ TABDECL(OP_STR_M_IMM_OFF_POSTIND), // OP_STR_M_IMM_OFF_POSTIND /* 0100 0000 1010 */ TABDECL(OP_STR_M_IMM_OFF_POSTIND), // OP_STR_M_IMM_OFF_POSTIND /* 0100 0000 1011 */ TABDECL(OP_STR_M_IMM_OFF_POSTIND), // OP_STR_M_IMM_OFF_POSTIND /* 0100 0000 1100 */ TABDECL(OP_STR_M_IMM_OFF_POSTIND), // OP_STR_M_IMM_OFF_POSTIND /* 0100 0000 1101 */ TABDECL(OP_STR_M_IMM_OFF_POSTIND), // OP_STR_M_IMM_OFF_POSTIND /* 0100 0000 1110 */ TABDECL(OP_STR_M_IMM_OFF_POSTIND), // OP_STR_M_IMM_OFF_POSTIND /* 0100 0000 1111 */ TABDECL(OP_STR_M_IMM_OFF_POSTIND), // OP_STR_M_IMM_OFF_POSTIND /* 0100 0001 0000 */ TABDECL(OP_LDR_M_IMM_OFF_POSTIND), // OP_LDR_M_IMM_OFF_POSTIND /* 0100 0001 0001 */ TABDECL(OP_LDR_M_IMM_OFF_POSTIND), // OP_LDR_M_IMM_OFF_POSTIND /* 0100 0001 0010 */ TABDECL(OP_LDR_M_IMM_OFF_POSTIND), // OP_LDR_M_IMM_OFF_POSTIND /* 0100 0001 0011 */ TABDECL(OP_LDR_M_IMM_OFF_POSTIND), // OP_LDR_M_IMM_OFF_POSTIND /* 0100 0001 0100 */ TABDECL(OP_LDR_M_IMM_OFF_POSTIND), // OP_LDR_M_IMM_OFF_POSTIND /* 0100 0001 0101 */ TABDECL(OP_LDR_M_IMM_OFF_POSTIND), // OP_LDR_M_IMM_OFF_POSTIND /* 0100 0001 0110 */ TABDECL(OP_LDR_M_IMM_OFF_POSTIND), // OP_LDR_M_IMM_OFF_POSTIND /* 0100 0001 0111 */ TABDECL(OP_LDR_M_IMM_OFF_POSTIND), // OP_LDR_M_IMM_OFF_POSTIND /* 0100 0001 1000 */ TABDECL(OP_LDR_M_IMM_OFF_POSTIND), // OP_LDR_M_IMM_OFF_POSTIND /* 0100 0001 1001 */ TABDECL(OP_LDR_M_IMM_OFF_POSTIND), // OP_LDR_M_IMM_OFF_POSTIND /* 0100 0001 1010 */ TABDECL(OP_LDR_M_IMM_OFF_POSTIND), // OP_LDR_M_IMM_OFF_POSTIND /* 0100 0001 1011 */ TABDECL(OP_LDR_M_IMM_OFF_POSTIND), // OP_LDR_M_IMM_OFF_POSTIND /* 0100 0001 1100 */ TABDECL(OP_LDR_M_IMM_OFF_POSTIND), // OP_LDR_M_IMM_OFF_POSTIND /* 0100 0001 1101 */ TABDECL(OP_LDR_M_IMM_OFF_POSTIND), // OP_LDR_M_IMM_OFF_POSTIND /* 0100 0001 1110 */ TABDECL(OP_LDR_M_IMM_OFF_POSTIND), // OP_LDR_M_IMM_OFF_POSTIND /* 0100 0001 1111 */ TABDECL(OP_LDR_M_IMM_OFF_POSTIND), // OP_LDR_M_IMM_OFF_POSTIND /* 0100 0010 0000 */ TABDECL(OP_STR_M_IMM_OFF_POSTIND), // OP_STR_M_IMM_OFF_POSTIND //changed from OP_UND in r3504 /* 0100 0010 0001 */ TABDECL(OP_STR_M_IMM_OFF_POSTIND), // OP_STR_M_IMM_OFF_POSTIND //changed from OP_UND in r3504 /* 0100 0010 0010 */ TABDECL(OP_STR_M_IMM_OFF_POSTIND), // OP_STR_M_IMM_OFF_POSTIND //changed from OP_UND in r3504 /* 0100 0010 0011 */ TABDECL(OP_STR_M_IMM_OFF_POSTIND), // OP_STR_M_IMM_OFF_POSTIND //changed from OP_UND in r3504 /* 0100 0010 0100 */ TABDECL(OP_STR_M_IMM_OFF_POSTIND), // OP_STR_M_IMM_OFF_POSTIND //changed from OP_UND in r3504 /* 0100 0010 0101 */ TABDECL(OP_STR_M_IMM_OFF_POSTIND), // OP_STR_M_IMM_OFF_POSTIND //changed from OP_UND in r3504 /* 0100 0010 0110 */ TABDECL(OP_STR_M_IMM_OFF_POSTIND), // OP_STR_M_IMM_OFF_POSTIND //changed from OP_UND in r3504 /* 0100 0010 0111 */ TABDECL(OP_STR_M_IMM_OFF_POSTIND), // OP_STR_M_IMM_OFF_POSTIND //changed from OP_UND in r3504 /* 0100 0010 1000 */ TABDECL(OP_STR_M_IMM_OFF_POSTIND), // OP_STR_M_IMM_OFF_POSTIND //changed from OP_UND in r3504 /* 0100 0010 1001 */ TABDECL(OP_STR_M_IMM_OFF_POSTIND), // OP_STR_M_IMM_OFF_POSTIND //changed from OP_UND in r3504 /* 0100 0010 1010 */ TABDECL(OP_STR_M_IMM_OFF_POSTIND), // OP_STR_M_IMM_OFF_POSTIND //changed from OP_UND in r3504 /* 0100 0010 1011 */ TABDECL(OP_STR_M_IMM_OFF_POSTIND), // OP_STR_M_IMM_OFF_POSTIND //changed from OP_UND in r3504 /* 0100 0010 1100 */ TABDECL(OP_STR_M_IMM_OFF_POSTIND), // OP_STR_M_IMM_OFF_POSTIND //changed from OP_UND in r3504 /* 0100 0010 1101 */ TABDECL(OP_STR_M_IMM_OFF_POSTIND), // OP_STR_M_IMM_OFF_POSTIND //changed from OP_UND in r3504 /* 0100 0010 1110 */ TABDECL(OP_STR_M_IMM_OFF_POSTIND), // OP_STR_M_IMM_OFF_POSTIND //changed from OP_UND in r3504 /* 0100 0010 1111 */ TABDECL(OP_STR_M_IMM_OFF_POSTIND), // OP_STR_M_IMM_OFF_POSTIND //changed from OP_UND in r3504 /* 0100 0011 0000 */ TABDECL(OP_LDR_M_IMM_OFF_POSTIND), // OP_LDR_M_IMM_OFF_POSTIND //changed from OP_UND in r3504 to OP_STR; changed to OP_LDR in r3510 /* 0100 0011 0001 */ TABDECL(OP_LDR_M_IMM_OFF_POSTIND), // OP_LDR_M_IMM_OFF_POSTIND //changed from OP_UND in r3504 to OP_STR; changed to OP_LDR in r3510 /* 0100 0011 0010 */ TABDECL(OP_LDR_M_IMM_OFF_POSTIND), // OP_LDR_M_IMM_OFF_POSTIND //changed from OP_UND in r3504 to OP_STR; changed to OP_LDR in r3510 /* 0100 0011 0011 */ TABDECL(OP_LDR_M_IMM_OFF_POSTIND), // OP_LDR_M_IMM_OFF_POSTIND //changed from OP_UND in r3504 to OP_STR; changed to OP_LDR in r3510 /* 0100 0011 0100 */ TABDECL(OP_LDR_M_IMM_OFF_POSTIND), // OP_LDR_M_IMM_OFF_POSTIND //changed from OP_UND in r3504 to OP_STR; changed to OP_LDR in r3510 /* 0100 0011 0101 */ TABDECL(OP_LDR_M_IMM_OFF_POSTIND), // OP_LDR_M_IMM_OFF_POSTIND //changed from OP_UND in r3504 to OP_STR; changed to OP_LDR in r3510 /* 0100 0011 0110 */ TABDECL(OP_LDR_M_IMM_OFF_POSTIND), // OP_LDR_M_IMM_OFF_POSTIND //changed from OP_UND in r3504 to OP_STR; changed to OP_LDR in r3510 /* 0100 0011 0111 */ TABDECL(OP_LDR_M_IMM_OFF_POSTIND), // OP_LDR_M_IMM_OFF_POSTIND //changed from OP_UND in r3504 to OP_STR; changed to OP_LDR in r3510 /* 0100 0011 1000 */ TABDECL(OP_LDR_M_IMM_OFF_POSTIND), // OP_LDR_M_IMM_OFF_POSTIND //changed from OP_UND in r3504 to OP_STR; changed to OP_LDR in r3510 /* 0100 0011 1001 */ TABDECL(OP_LDR_M_IMM_OFF_POSTIND), // OP_LDR_M_IMM_OFF_POSTIND //changed from OP_UND in r3504 to OP_STR; changed to OP_LDR in r3510 /* 0100 0011 1010 */ TABDECL(OP_LDR_M_IMM_OFF_POSTIND), // OP_LDR_M_IMM_OFF_POSTIND //changed from OP_UND in r3504 to OP_STR; changed to OP_LDR in r3510 /* 0100 0011 1011 */ TABDECL(OP_LDR_M_IMM_OFF_POSTIND), // OP_LDR_M_IMM_OFF_POSTIND //changed from OP_UND in r3504 to OP_STR; changed to OP_LDR in r3510 /* 0100 0011 1100 */ TABDECL(OP_LDR_M_IMM_OFF_POSTIND), // OP_LDR_M_IMM_OFF_POSTIND //changed from OP_UND in r3504 to OP_STR; changed to OP_LDR in r3510 /* 0100 0011 1101 */ TABDECL(OP_LDR_M_IMM_OFF_POSTIND), // OP_LDR_M_IMM_OFF_POSTIND //changed from OP_UND in r3504 to OP_STR; changed to OP_LDR in r3510 /* 0100 0011 1110 */ TABDECL(OP_LDR_M_IMM_OFF_POSTIND), // OP_LDR_M_IMM_OFF_POSTIND //changed from OP_UND in r3504 to OP_STR; changed to OP_LDR in r3510 /* 0100 0011 1111 */ TABDECL(OP_LDR_M_IMM_OFF_POSTIND), // OP_LDR_M_IMM_OFF_POSTIND //changed from OP_UND in r3504 to OP_STR; changed to OP_LDR in r3510 /* 0100 0100 0000 */ TABDECL(OP_STRB_M_IMM_OFF_POSTIND), // OP_STRB_M_IMM_OFF_POSTIND /* 0100 0100 0001 */ TABDECL(OP_STRB_M_IMM_OFF_POSTIND), // OP_STRB_M_IMM_OFF_POSTIND /* 0100 0100 0010 */ TABDECL(OP_STRB_M_IMM_OFF_POSTIND), // OP_STRB_M_IMM_OFF_POSTIND /* 0100 0100 0011 */ TABDECL(OP_STRB_M_IMM_OFF_POSTIND), // OP_STRB_M_IMM_OFF_POSTIND /* 0100 0100 0100 */ TABDECL(OP_STRB_M_IMM_OFF_POSTIND), // OP_STRB_M_IMM_OFF_POSTIND /* 0100 0100 0101 */ TABDECL(OP_STRB_M_IMM_OFF_POSTIND), // OP_STRB_M_IMM_OFF_POSTIND /* 0100 0100 0110 */ TABDECL(OP_STRB_M_IMM_OFF_POSTIND), // OP_STRB_M_IMM_OFF_POSTIND /* 0100 0100 0111 */ TABDECL(OP_STRB_M_IMM_OFF_POSTIND), // OP_STRB_M_IMM_OFF_POSTIND /* 0100 0100 1000 */ TABDECL(OP_STRB_M_IMM_OFF_POSTIND), // OP_STRB_M_IMM_OFF_POSTIND /* 0100 0100 1001 */ TABDECL(OP_STRB_M_IMM_OFF_POSTIND), // OP_STRB_M_IMM_OFF_POSTIND /* 0100 0100 1010 */ TABDECL(OP_STRB_M_IMM_OFF_POSTIND), // OP_STRB_M_IMM_OFF_POSTIND /* 0100 0100 1011 */ TABDECL(OP_STRB_M_IMM_OFF_POSTIND), // OP_STRB_M_IMM_OFF_POSTIND /* 0100 0100 1100 */ TABDECL(OP_STRB_M_IMM_OFF_POSTIND), // OP_STRB_M_IMM_OFF_POSTIND /* 0100 0100 1101 */ TABDECL(OP_STRB_M_IMM_OFF_POSTIND), // OP_STRB_M_IMM_OFF_POSTIND /* 0100 0100 1110 */ TABDECL(OP_STRB_M_IMM_OFF_POSTIND), // OP_STRB_M_IMM_OFF_POSTIND /* 0100 0100 1111 */ TABDECL(OP_STRB_M_IMM_OFF_POSTIND), // OP_STRB_M_IMM_OFF_POSTIND /* 0100 0101 0000 */ TABDECL(OP_LDRB_M_IMM_OFF_POSTIND), // OP_LDRB_M_IMM_OFF_POSTIND /* 0100 0101 0001 */ TABDECL(OP_LDRB_M_IMM_OFF_POSTIND), // OP_LDRB_M_IMM_OFF_POSTIND /* 0100 0101 0010 */ TABDECL(OP_LDRB_M_IMM_OFF_POSTIND), // OP_LDRB_M_IMM_OFF_POSTIND /* 0100 0101 0011 */ TABDECL(OP_LDRB_M_IMM_OFF_POSTIND), // OP_LDRB_M_IMM_OFF_POSTIND /* 0100 0101 0100 */ TABDECL(OP_LDRB_M_IMM_OFF_POSTIND), // OP_LDRB_M_IMM_OFF_POSTIND /* 0100 0101 0101 */ TABDECL(OP_LDRB_M_IMM_OFF_POSTIND), // OP_LDRB_M_IMM_OFF_POSTIND /* 0100 0101 0110 */ TABDECL(OP_LDRB_M_IMM_OFF_POSTIND), // OP_LDRB_M_IMM_OFF_POSTIND /* 0100 0101 0111 */ TABDECL(OP_LDRB_M_IMM_OFF_POSTIND), // OP_LDRB_M_IMM_OFF_POSTIND /* 0100 0101 1000 */ TABDECL(OP_LDRB_M_IMM_OFF_POSTIND), // OP_LDRB_M_IMM_OFF_POSTIND /* 0100 0101 1001 */ TABDECL(OP_LDRB_M_IMM_OFF_POSTIND), // OP_LDRB_M_IMM_OFF_POSTIND /* 0100 0101 1010 */ TABDECL(OP_LDRB_M_IMM_OFF_POSTIND), // OP_LDRB_M_IMM_OFF_POSTIND /* 0100 0101 1011 */ TABDECL(OP_LDRB_M_IMM_OFF_POSTIND), // OP_LDRB_M_IMM_OFF_POSTIND /* 0100 0101 1100 */ TABDECL(OP_LDRB_M_IMM_OFF_POSTIND), // OP_LDRB_M_IMM_OFF_POSTIND /* 0100 0101 1101 */ TABDECL(OP_LDRB_M_IMM_OFF_POSTIND), // OP_LDRB_M_IMM_OFF_POSTIND /* 0100 0101 1110 */ TABDECL(OP_LDRB_M_IMM_OFF_POSTIND), // OP_LDRB_M_IMM_OFF_POSTIND /* 0100 0101 1111 */ TABDECL(OP_LDRB_M_IMM_OFF_POSTIND), // OP_LDRB_M_IMM_OFF_POSTIND /* 0100 0110 0000 */ TABDECL(OP_STRB_M_IMM_OFF_POSTIND), // OP_STRB_M_IMM_OFF_POSTIND //changed from OP_UND in r3504 /* 0100 0110 0001 */ TABDECL(OP_STRB_M_IMM_OFF_POSTIND), // OP_STRB_M_IMM_OFF_POSTIND //changed from OP_UND in r3504 /* 0100 0110 0010 */ TABDECL(OP_STRB_M_IMM_OFF_POSTIND), // OP_STRB_M_IMM_OFF_POSTIND //changed from OP_UND in r3504 /* 0100 0110 0011 */ TABDECL(OP_STRB_M_IMM_OFF_POSTIND), // OP_STRB_M_IMM_OFF_POSTIND //changed from OP_UND in r3504 /* 0100 0110 0100 */ TABDECL(OP_STRB_M_IMM_OFF_POSTIND), // OP_STRB_M_IMM_OFF_POSTIND //changed from OP_UND in r3504 /* 0100 0110 0101 */ TABDECL(OP_STRB_M_IMM_OFF_POSTIND), // OP_STRB_M_IMM_OFF_POSTIND //changed from OP_UND in r3504 /* 0100 0110 0110 */ TABDECL(OP_STRB_M_IMM_OFF_POSTIND), // OP_STRB_M_IMM_OFF_POSTIND //changed from OP_UND in r3504 /* 0100 0110 0111 */ TABDECL(OP_STRB_M_IMM_OFF_POSTIND), // OP_STRB_M_IMM_OFF_POSTIND //changed from OP_UND in r3504 /* 0100 0110 1000 */ TABDECL(OP_STRB_M_IMM_OFF_POSTIND), // OP_STRB_M_IMM_OFF_POSTIND //changed from OP_UND in r3504 /* 0100 0110 1001 */ TABDECL(OP_STRB_M_IMM_OFF_POSTIND), // OP_STRB_M_IMM_OFF_POSTIND //changed from OP_UND in r3504 /* 0100 0110 1010 */ TABDECL(OP_STRB_M_IMM_OFF_POSTIND), // OP_STRB_M_IMM_OFF_POSTIND //changed from OP_UND in r3504 /* 0100 0110 1011 */ TABDECL(OP_STRB_M_IMM_OFF_POSTIND), // OP_STRB_M_IMM_OFF_POSTIND //changed from OP_UND in r3504 /* 0100 0110 1100 */ TABDECL(OP_STRB_M_IMM_OFF_POSTIND), // OP_STRB_M_IMM_OFF_POSTIND //changed from OP_UND in r3504 /* 0100 0110 1101 */ TABDECL(OP_STRB_M_IMM_OFF_POSTIND), // OP_STRB_M_IMM_OFF_POSTIND //changed from OP_UND in r3504 /* 0100 0110 1110 */ TABDECL(OP_STRB_M_IMM_OFF_POSTIND), // OP_STRB_M_IMM_OFF_POSTIND //changed from OP_UND in r3504 /* 0100 0110 1111 */ TABDECL(OP_STRB_M_IMM_OFF_POSTIND), // OP_STRB_M_IMM_OFF_POSTIND //changed from OP_UND in r3504 /* 0100 0111 0000 */ TABDECL(OP_LDRB_M_IMM_OFF_POSTIND), // OP_LDRB_M_IMM_OFF_POSTIND //changed from OP_UND in r3504 to OP_STRB; changed to OP_LDRB in r3510 /* 0100 0111 0001 */ TABDECL(OP_LDRB_M_IMM_OFF_POSTIND), // OP_LDRB_M_IMM_OFF_POSTIND //changed from OP_UND in r3504 to OP_STRB; changed to OP_LDRB in r3510 /* 0100 0111 0010 */ TABDECL(OP_LDRB_M_IMM_OFF_POSTIND), // OP_LDRB_M_IMM_OFF_POSTIND //changed from OP_UND in r3504 to OP_STRB; changed to OP_LDRB in r3510 /* 0100 0111 0011 */ TABDECL(OP_LDRB_M_IMM_OFF_POSTIND), // OP_LDRB_M_IMM_OFF_POSTIND //changed from OP_UND in r3504 to OP_STRB; changed to OP_LDRB in r3510 /* 0100 0111 0100 */ TABDECL(OP_LDRB_M_IMM_OFF_POSTIND), // OP_LDRB_M_IMM_OFF_POSTIND //changed from OP_UND in r3504 to OP_STRB; changed to OP_LDRB in r3510 /* 0100 0111 0101 */ TABDECL(OP_LDRB_M_IMM_OFF_POSTIND), // OP_LDRB_M_IMM_OFF_POSTIND //changed from OP_UND in r3504 to OP_STRB; changed to OP_LDRB in r3510 /* 0100 0111 0110 */ TABDECL(OP_LDRB_M_IMM_OFF_POSTIND), // OP_LDRB_M_IMM_OFF_POSTIND //changed from OP_UND in r3504 to OP_STRB; changed to OP_LDRB in r3510 /* 0100 0111 0111 */ TABDECL(OP_LDRB_M_IMM_OFF_POSTIND), // OP_LDRB_M_IMM_OFF_POSTIND //changed from OP_UND in r3504 to OP_STRB; changed to OP_LDRB in r3510 /* 0100 0111 1000 */ TABDECL(OP_LDRB_M_IMM_OFF_POSTIND), // OP_LDRB_M_IMM_OFF_POSTIND //changed from OP_UND in r3504 to OP_STRB; changed to OP_LDRB in r3510 /* 0100 0111 1001 */ TABDECL(OP_LDRB_M_IMM_OFF_POSTIND), // OP_LDRB_M_IMM_OFF_POSTIND //changed from OP_UND in r3504 to OP_STRB; changed to OP_LDRB in r3510 /* 0100 0111 1010 */ TABDECL(OP_LDRB_M_IMM_OFF_POSTIND), // OP_LDRB_M_IMM_OFF_POSTIND //changed from OP_UND in r3504 to OP_STRB; changed to OP_LDRB in r3510 /* 0100 0111 1011 */ TABDECL(OP_LDRB_M_IMM_OFF_POSTIND), // OP_LDRB_M_IMM_OFF_POSTIND //changed from OP_UND in r3504 to OP_STRB; changed to OP_LDRB in r3510 /* 0100 0111 1100 */ TABDECL(OP_LDRB_M_IMM_OFF_POSTIND), // OP_LDRB_M_IMM_OFF_POSTIND //changed from OP_UND in r3504 to OP_STRB; changed to OP_LDRB in r3510 /* 0100 0111 1101 */ TABDECL(OP_LDRB_M_IMM_OFF_POSTIND), // OP_LDRB_M_IMM_OFF_POSTIND //changed from OP_UND in r3504 to OP_STRB; changed to OP_LDRB in r3510 /* 0100 0111 1110 */ TABDECL(OP_LDRB_M_IMM_OFF_POSTIND), // OP_LDRB_M_IMM_OFF_POSTIND //changed from OP_UND in r3504 to OP_STRB; changed to OP_LDRB in r3510 /* 0100 0111 1111 */ TABDECL(OP_LDRB_M_IMM_OFF_POSTIND), // OP_LDRB_M_IMM_OFF_POSTIND //changed from OP_UND in r3504 to OP_STRB; changed to OP_LDRB in r3510 /* 0100 1000 0000 */ TABDECL(OP_STR_P_IMM_OFF_POSTIND), // OP_STR_P_IMM_OFF_POSTIND /* 0100 1000 0001 */ TABDECL(OP_STR_P_IMM_OFF_POSTIND), // OP_STR_P_IMM_OFF_POSTIND /* 0100 1000 0010 */ TABDECL(OP_STR_P_IMM_OFF_POSTIND), // OP_STR_P_IMM_OFF_POSTIND /* 0100 1000 0011 */ TABDECL(OP_STR_P_IMM_OFF_POSTIND), // OP_STR_P_IMM_OFF_POSTIND /* 0100 1000 0100 */ TABDECL(OP_STR_P_IMM_OFF_POSTIND), // OP_STR_P_IMM_OFF_POSTIND /* 0100 1000 0101 */ TABDECL(OP_STR_P_IMM_OFF_POSTIND), // OP_STR_P_IMM_OFF_POSTIND /* 0100 1000 0110 */ TABDECL(OP_STR_P_IMM_OFF_POSTIND), // OP_STR_P_IMM_OFF_POSTIND /* 0100 1000 0111 */ TABDECL(OP_STR_P_IMM_OFF_POSTIND), // OP_STR_P_IMM_OFF_POSTIND /* 0100 1000 1000 */ TABDECL(OP_STR_P_IMM_OFF_POSTIND), // OP_STR_P_IMM_OFF_POSTIND /* 0100 1000 1001 */ TABDECL(OP_STR_P_IMM_OFF_POSTIND), // OP_STR_P_IMM_OFF_POSTIND /* 0100 1000 1010 */ TABDECL(OP_STR_P_IMM_OFF_POSTIND), // OP_STR_P_IMM_OFF_POSTIND /* 0100 1000 1011 */ TABDECL(OP_STR_P_IMM_OFF_POSTIND), // OP_STR_P_IMM_OFF_POSTIND /* 0100 1000 1100 */ TABDECL(OP_STR_P_IMM_OFF_POSTIND), // OP_STR_P_IMM_OFF_POSTIND /* 0100 1000 1101 */ TABDECL(OP_STR_P_IMM_OFF_POSTIND), // OP_STR_P_IMM_OFF_POSTIND /* 0100 1000 1110 */ TABDECL(OP_STR_P_IMM_OFF_POSTIND), // OP_STR_P_IMM_OFF_POSTIND /* 0100 1000 1111 */ TABDECL(OP_STR_P_IMM_OFF_POSTIND), // OP_STR_P_IMM_OFF_POSTIND /* 0100 1001 0000 */ TABDECL(OP_LDR_P_IMM_OFF_POSTIND), // OP_LDR_P_IMM_OFF_POSTIND /* 0100 1001 0001 */ TABDECL(OP_LDR_P_IMM_OFF_POSTIND), // OP_LDR_P_IMM_OFF_POSTIND /* 0100 1001 0010 */ TABDECL(OP_LDR_P_IMM_OFF_POSTIND), // OP_LDR_P_IMM_OFF_POSTIND /* 0100 1001 0011 */ TABDECL(OP_LDR_P_IMM_OFF_POSTIND), // OP_LDR_P_IMM_OFF_POSTIND /* 0100 1001 0100 */ TABDECL(OP_LDR_P_IMM_OFF_POSTIND), // OP_LDR_P_IMM_OFF_POSTIND /* 0100 1001 0101 */ TABDECL(OP_LDR_P_IMM_OFF_POSTIND), // OP_LDR_P_IMM_OFF_POSTIND /* 0100 1001 0110 */ TABDECL(OP_LDR_P_IMM_OFF_POSTIND), // OP_LDR_P_IMM_OFF_POSTIND /* 0100 1001 0111 */ TABDECL(OP_LDR_P_IMM_OFF_POSTIND), // OP_LDR_P_IMM_OFF_POSTIND /* 0100 1001 1000 */ TABDECL(OP_LDR_P_IMM_OFF_POSTIND), // OP_LDR_P_IMM_OFF_POSTIND /* 0100 1001 1001 */ TABDECL(OP_LDR_P_IMM_OFF_POSTIND), // OP_LDR_P_IMM_OFF_POSTIND /* 0100 1001 1010 */ TABDECL(OP_LDR_P_IMM_OFF_POSTIND), // OP_LDR_P_IMM_OFF_POSTIND /* 0100 1001 1011 */ TABDECL(OP_LDR_P_IMM_OFF_POSTIND), // OP_LDR_P_IMM_OFF_POSTIND /* 0100 1001 1100 */ TABDECL(OP_LDR_P_IMM_OFF_POSTIND), // OP_LDR_P_IMM_OFF_POSTIND /* 0100 1001 1101 */ TABDECL(OP_LDR_P_IMM_OFF_POSTIND), // OP_LDR_P_IMM_OFF_POSTIND /* 0100 1001 1110 */ TABDECL(OP_LDR_P_IMM_OFF_POSTIND), // OP_LDR_P_IMM_OFF_POSTIND /* 0100 1001 1111 */ TABDECL(OP_LDR_P_IMM_OFF_POSTIND), // OP_LDR_P_IMM_OFF_POSTIND /* 0100 1010 0000 */ TABDECL(OP_STR_P_IMM_OFF_POSTIND), // OP_STR_P_IMM_OFF_POSTIND /* 0100 1010 0001 */ TABDECL(OP_STR_P_IMM_OFF_POSTIND), // OP_STR_P_IMM_OFF_POSTIND /* 0100 1010 0010 */ TABDECL(OP_STR_P_IMM_OFF_POSTIND), // OP_STR_P_IMM_OFF_POSTIND /* 0100 1010 0011 */ TABDECL(OP_STR_P_IMM_OFF_POSTIND), // OP_STR_P_IMM_OFF_POSTIND /* 0100 1010 0100 */ TABDECL(OP_STR_P_IMM_OFF_POSTIND), // OP_STR_P_IMM_OFF_POSTIND /* 0100 1010 0101 */ TABDECL(OP_STR_P_IMM_OFF_POSTIND), // OP_STR_P_IMM_OFF_POSTIND /* 0100 1010 0110 */ TABDECL(OP_STR_P_IMM_OFF_POSTIND), // OP_STR_P_IMM_OFF_POSTIND /* 0100 1010 0111 */ TABDECL(OP_STR_P_IMM_OFF_POSTIND), // OP_STR_P_IMM_OFF_POSTIND /* 0100 1010 1000 */ TABDECL(OP_STR_P_IMM_OFF_POSTIND), // OP_STR_P_IMM_OFF_POSTIND /* 0100 1010 1001 */ TABDECL(OP_STR_P_IMM_OFF_POSTIND), // OP_STR_P_IMM_OFF_POSTIND /* 0100 1010 1010 */ TABDECL(OP_STR_P_IMM_OFF_POSTIND), // OP_STR_P_IMM_OFF_POSTIND /* 0100 1010 1011 */ TABDECL(OP_STR_P_IMM_OFF_POSTIND), // OP_STR_P_IMM_OFF_POSTIND /* 0100 1010 1100 */ TABDECL(OP_STR_P_IMM_OFF_POSTIND), // OP_STR_P_IMM_OFF_POSTIND /* 0100 1010 1101 */ TABDECL(OP_STR_P_IMM_OFF_POSTIND), // OP_STR_P_IMM_OFF_POSTIND /* 0100 1010 1110 */ TABDECL(OP_STR_P_IMM_OFF_POSTIND), // OP_STR_P_IMM_OFF_POSTIND /* 0100 1010 1111 */ TABDECL(OP_STR_P_IMM_OFF_POSTIND), // OP_STR_P_IMM_OFF_POSTIND /* 0100 1011 0000 */ TABDECL(OP_LDR_P_IMM_OFF_POSTIND), // OP_LDR_P_IMM_OFF_POSTIND //changed from a POSTIND2 version in r3504 /* 0100 1011 0001 */ TABDECL(OP_LDR_P_IMM_OFF_POSTIND), // OP_LDR_P_IMM_OFF_POSTIND //changed from a POSTIND2 version in r3504 /* 0100 1011 0010 */ TABDECL(OP_LDR_P_IMM_OFF_POSTIND), // OP_LDR_P_IMM_OFF_POSTIND //changed from a POSTIND2 version in r3504 /* 0100 1011 0011 */ TABDECL(OP_LDR_P_IMM_OFF_POSTIND), // OP_LDR_P_IMM_OFF_POSTIND //changed from a POSTIND2 version in r3504 /* 0100 1011 0100 */ TABDECL(OP_LDR_P_IMM_OFF_POSTIND), // OP_LDR_P_IMM_OFF_POSTIND //changed from a POSTIND2 version in r3504 /* 0100 1011 0101 */ TABDECL(OP_LDR_P_IMM_OFF_POSTIND), // OP_LDR_P_IMM_OFF_POSTIND //changed from a POSTIND2 version in r3504 /* 0100 1011 0110 */ TABDECL(OP_LDR_P_IMM_OFF_POSTIND), // OP_LDR_P_IMM_OFF_POSTIND //changed from a POSTIND2 version in r3504 /* 0100 1011 0111 */ TABDECL(OP_LDR_P_IMM_OFF_POSTIND), // OP_LDR_P_IMM_OFF_POSTIND //changed from a POSTIND2 version in r3504 /* 0100 1011 1000 */ TABDECL(OP_LDR_P_IMM_OFF_POSTIND), // OP_LDR_P_IMM_OFF_POSTIND //changed from a POSTIND2 version in r3504 /* 0100 1011 1001 */ TABDECL(OP_LDR_P_IMM_OFF_POSTIND), // OP_LDR_P_IMM_OFF_POSTIND //changed from a POSTIND2 version in r3504 /* 0100 1011 1010 */ TABDECL(OP_LDR_P_IMM_OFF_POSTIND), // OP_LDR_P_IMM_OFF_POSTIND //changed from a POSTIND2 version in r3504 /* 0100 1011 1011 */ TABDECL(OP_LDR_P_IMM_OFF_POSTIND), // OP_LDR_P_IMM_OFF_POSTIND //changed from a POSTIND2 version in r3504 /* 0100 1011 1100 */ TABDECL(OP_LDR_P_IMM_OFF_POSTIND), // OP_LDR_P_IMM_OFF_POSTIND //changed from a POSTIND2 version in r3504 /* 0100 1011 1101 */ TABDECL(OP_LDR_P_IMM_OFF_POSTIND), // OP_LDR_P_IMM_OFF_POSTIND //changed from a POSTIND2 version in r3504 /* 0100 1011 1110 */ TABDECL(OP_LDR_P_IMM_OFF_POSTIND), // OP_LDR_P_IMM_OFF_POSTIND //changed from a POSTIND2 version in r3504 /* 0100 1011 1111 */ TABDECL(OP_LDR_P_IMM_OFF_POSTIND), // OP_LDR_P_IMM_OFF_POSTIND //changed from a POSTIND2 version in r3504 /* 0100 1100 0000 */ TABDECL(OP_STRB_P_IMM_OFF_POSTIND), // OP_STRB_P_IMM_OFF_POSTIND /* 0100 1100 0001 */ TABDECL(OP_STRB_P_IMM_OFF_POSTIND), // OP_STRB_P_IMM_OFF_POSTIND /* 0100 1100 0010 */ TABDECL(OP_STRB_P_IMM_OFF_POSTIND), // OP_STRB_P_IMM_OFF_POSTIND /* 0100 1100 0011 */ TABDECL(OP_STRB_P_IMM_OFF_POSTIND), // OP_STRB_P_IMM_OFF_POSTIND /* 0100 1100 0100 */ TABDECL(OP_STRB_P_IMM_OFF_POSTIND), // OP_STRB_P_IMM_OFF_POSTIND /* 0100 1100 0101 */ TABDECL(OP_STRB_P_IMM_OFF_POSTIND), // OP_STRB_P_IMM_OFF_POSTIND /* 0100 1100 0110 */ TABDECL(OP_STRB_P_IMM_OFF_POSTIND), // OP_STRB_P_IMM_OFF_POSTIND /* 0100 1100 0111 */ TABDECL(OP_STRB_P_IMM_OFF_POSTIND), // OP_STRB_P_IMM_OFF_POSTIND /* 0100 1100 1000 */ TABDECL(OP_STRB_P_IMM_OFF_POSTIND), // OP_STRB_P_IMM_OFF_POSTIND /* 0100 1100 1001 */ TABDECL(OP_STRB_P_IMM_OFF_POSTIND), // OP_STRB_P_IMM_OFF_POSTIND /* 0100 1100 1010 */ TABDECL(OP_STRB_P_IMM_OFF_POSTIND), // OP_STRB_P_IMM_OFF_POSTIND /* 0100 1100 1011 */ TABDECL(OP_STRB_P_IMM_OFF_POSTIND), // OP_STRB_P_IMM_OFF_POSTIND /* 0100 1100 1100 */ TABDECL(OP_STRB_P_IMM_OFF_POSTIND), // OP_STRB_P_IMM_OFF_POSTIND /* 0100 1100 1101 */ TABDECL(OP_STRB_P_IMM_OFF_POSTIND), // OP_STRB_P_IMM_OFF_POSTIND /* 0100 1100 1110 */ TABDECL(OP_STRB_P_IMM_OFF_POSTIND), // OP_STRB_P_IMM_OFF_POSTIND /* 0100 1100 1111 */ TABDECL(OP_STRB_P_IMM_OFF_POSTIND), // OP_STRB_P_IMM_OFF_POSTIND /* 0100 1101 0000 */ TABDECL(OP_LDRB_P_IMM_OFF_POSTIND), // OP_LDRB_P_IMM_OFF_POSTIND /* 0100 1101 0001 */ TABDECL(OP_LDRB_P_IMM_OFF_POSTIND), // OP_LDRB_P_IMM_OFF_POSTIND /* 0100 1101 0010 */ TABDECL(OP_LDRB_P_IMM_OFF_POSTIND), // OP_LDRB_P_IMM_OFF_POSTIND /* 0100 1101 0011 */ TABDECL(OP_LDRB_P_IMM_OFF_POSTIND), // OP_LDRB_P_IMM_OFF_POSTIND /* 0100 1101 0100 */ TABDECL(OP_LDRB_P_IMM_OFF_POSTIND), // OP_LDRB_P_IMM_OFF_POSTIND /* 0100 1101 0101 */ TABDECL(OP_LDRB_P_IMM_OFF_POSTIND), // OP_LDRB_P_IMM_OFF_POSTIND /* 0100 1101 0110 */ TABDECL(OP_LDRB_P_IMM_OFF_POSTIND), // OP_LDRB_P_IMM_OFF_POSTIND /* 0100 1101 0111 */ TABDECL(OP_LDRB_P_IMM_OFF_POSTIND), // OP_LDRB_P_IMM_OFF_POSTIND /* 0100 1101 1000 */ TABDECL(OP_LDRB_P_IMM_OFF_POSTIND), // OP_LDRB_P_IMM_OFF_POSTIND /* 0100 1101 1001 */ TABDECL(OP_LDRB_P_IMM_OFF_POSTIND), // OP_LDRB_P_IMM_OFF_POSTIND /* 0100 1101 1010 */ TABDECL(OP_LDRB_P_IMM_OFF_POSTIND), // OP_LDRB_P_IMM_OFF_POSTIND /* 0100 1101 1011 */ TABDECL(OP_LDRB_P_IMM_OFF_POSTIND), // OP_LDRB_P_IMM_OFF_POSTIND /* 0100 1101 1100 */ TABDECL(OP_LDRB_P_IMM_OFF_POSTIND), // OP_LDRB_P_IMM_OFF_POSTIND /* 0100 1101 1101 */ TABDECL(OP_LDRB_P_IMM_OFF_POSTIND), // OP_LDRB_P_IMM_OFF_POSTIND /* 0100 1101 1110 */ TABDECL(OP_LDRB_P_IMM_OFF_POSTIND), // OP_LDRB_P_IMM_OFF_POSTIND /* 0100 1101 1111 */ TABDECL(OP_LDRB_P_IMM_OFF_POSTIND), // OP_LDRB_P_IMM_OFF_POSTIND /* 0100 1110 0000 */ TABDECL(OP_STRB_P_IMM_OFF_POSTIND), // OP_STRB_P_IMM_OFF_POSTIND /* 0100 1110 0001 */ TABDECL(OP_STRB_P_IMM_OFF_POSTIND), // OP_STRB_P_IMM_OFF_POSTIND /* 0100 1110 0010 */ TABDECL(OP_STRB_P_IMM_OFF_POSTIND), // OP_STRB_P_IMM_OFF_POSTIND /* 0100 1110 0011 */ TABDECL(OP_STRB_P_IMM_OFF_POSTIND), // OP_STRB_P_IMM_OFF_POSTIND /* 0100 1110 0100 */ TABDECL(OP_STRB_P_IMM_OFF_POSTIND), // OP_STRB_P_IMM_OFF_POSTIND /* 0100 1110 0101 */ TABDECL(OP_STRB_P_IMM_OFF_POSTIND), // OP_STRB_P_IMM_OFF_POSTIND /* 0100 1110 0110 */ TABDECL(OP_STRB_P_IMM_OFF_POSTIND), // OP_STRB_P_IMM_OFF_POSTIND /* 0100 1110 0111 */ TABDECL(OP_STRB_P_IMM_OFF_POSTIND), // OP_STRB_P_IMM_OFF_POSTIND /* 0100 1110 1000 */ TABDECL(OP_STRB_P_IMM_OFF_POSTIND), // OP_STRB_P_IMM_OFF_POSTIND /* 0100 1110 1001 */ TABDECL(OP_STRB_P_IMM_OFF_POSTIND), // OP_STRB_P_IMM_OFF_POSTIND /* 0100 1110 1010 */ TABDECL(OP_STRB_P_IMM_OFF_POSTIND), // OP_STRB_P_IMM_OFF_POSTIND /* 0100 1110 1011 */ TABDECL(OP_STRB_P_IMM_OFF_POSTIND), // OP_STRB_P_IMM_OFF_POSTIND /* 0100 1110 1100 */ TABDECL(OP_STRB_P_IMM_OFF_POSTIND), // OP_STRB_P_IMM_OFF_POSTIND /* 0100 1110 1101 */ TABDECL(OP_STRB_P_IMM_OFF_POSTIND), // OP_STRB_P_IMM_OFF_POSTIND /* 0100 1110 1110 */ TABDECL(OP_STRB_P_IMM_OFF_POSTIND), // OP_STRB_P_IMM_OFF_POSTIND /* 0100 1110 1111 */ TABDECL(OP_STRB_P_IMM_OFF_POSTIND), // OP_STRB_P_IMM_OFF_POSTIND /* 0100 1111 0000 */ TABDECL(OP_LDRB_P_IMM_OFF_POSTIND), // OP_LDRB_P_IMM_OFF_POSTIND /* 0100 1111 0001 */ TABDECL(OP_LDRB_P_IMM_OFF_POSTIND), // OP_LDRB_P_IMM_OFF_POSTIND /* 0100 1111 0010 */ TABDECL(OP_LDRB_P_IMM_OFF_POSTIND), // OP_LDRB_P_IMM_OFF_POSTIND /* 0100 1111 0011 */ TABDECL(OP_LDRB_P_IMM_OFF_POSTIND), // OP_LDRB_P_IMM_OFF_POSTIND /* 0100 1111 0100 */ TABDECL(OP_LDRB_P_IMM_OFF_POSTIND), // OP_LDRB_P_IMM_OFF_POSTIND /* 0100 1111 0101 */ TABDECL(OP_LDRB_P_IMM_OFF_POSTIND), // OP_LDRB_P_IMM_OFF_POSTIND /* 0100 1111 0110 */ TABDECL(OP_LDRB_P_IMM_OFF_POSTIND), // OP_LDRB_P_IMM_OFF_POSTIND /* 0100 1111 0111 */ TABDECL(OP_LDRB_P_IMM_OFF_POSTIND), // OP_LDRB_P_IMM_OFF_POSTIND /* 0100 1111 1000 */ TABDECL(OP_LDRB_P_IMM_OFF_POSTIND), // OP_LDRB_P_IMM_OFF_POSTIND /* 0100 1111 1001 */ TABDECL(OP_LDRB_P_IMM_OFF_POSTIND), // OP_LDRB_P_IMM_OFF_POSTIND /* 0100 1111 1010 */ TABDECL(OP_LDRB_P_IMM_OFF_POSTIND), // OP_LDRB_P_IMM_OFF_POSTIND /* 0100 1111 1011 */ TABDECL(OP_LDRB_P_IMM_OFF_POSTIND), // OP_LDRB_P_IMM_OFF_POSTIND /* 0100 1111 1100 */ TABDECL(OP_LDRB_P_IMM_OFF_POSTIND), // OP_LDRB_P_IMM_OFF_POSTIND /* 0100 1111 1101 */ TABDECL(OP_LDRB_P_IMM_OFF_POSTIND), // OP_LDRB_P_IMM_OFF_POSTIND /* 0100 1111 1110 */ TABDECL(OP_LDRB_P_IMM_OFF_POSTIND), // OP_LDRB_P_IMM_OFF_POSTIND /* 0100 1111 1111 */ TABDECL(OP_LDRB_P_IMM_OFF_POSTIND), // OP_LDRB_P_IMM_OFF_POSTIND /* 0101 0000 0000 */ TABDECL(OP_STR_M_IMM_OFF), // OP_STR_M_IMM_OFF /* 0101 0000 0001 */ TABDECL(OP_STR_M_IMM_OFF), // OP_STR_M_IMM_OFF /* 0101 0000 0010 */ TABDECL(OP_STR_M_IMM_OFF), // OP_STR_M_IMM_OFF /* 0101 0000 0011 */ TABDECL(OP_STR_M_IMM_OFF), // OP_STR_M_IMM_OFF /* 0101 0000 0100 */ TABDECL(OP_STR_M_IMM_OFF), // OP_STR_M_IMM_OFF /* 0101 0000 0101 */ TABDECL(OP_STR_M_IMM_OFF), // OP_STR_M_IMM_OFF /* 0101 0000 0110 */ TABDECL(OP_STR_M_IMM_OFF), // OP_STR_M_IMM_OFF /* 0101 0000 0111 */ TABDECL(OP_STR_M_IMM_OFF), // OP_STR_M_IMM_OFF /* 0101 0000 1000 */ TABDECL(OP_STR_M_IMM_OFF), // OP_STR_M_IMM_OFF /* 0101 0000 1001 */ TABDECL(OP_STR_M_IMM_OFF), // OP_STR_M_IMM_OFF /* 0101 0000 1010 */ TABDECL(OP_STR_M_IMM_OFF), // OP_STR_M_IMM_OFF /* 0101 0000 1011 */ TABDECL(OP_STR_M_IMM_OFF), // OP_STR_M_IMM_OFF /* 0101 0000 1100 */ TABDECL(OP_STR_M_IMM_OFF), // OP_STR_M_IMM_OFF /* 0101 0000 1101 */ TABDECL(OP_STR_M_IMM_OFF), // OP_STR_M_IMM_OFF /* 0101 0000 1110 */ TABDECL(OP_STR_M_IMM_OFF), // OP_STR_M_IMM_OFF /* 0101 0000 1111 */ TABDECL(OP_STR_M_IMM_OFF), // OP_STR_M_IMM_OFF /* 0101 0001 0000 */ TABDECL(OP_LDR_M_IMM_OFF), // OP_LDR_M_IMM_OFF /* 0101 0001 0001 */ TABDECL(OP_LDR_M_IMM_OFF), // OP_LDR_M_IMM_OFF /* 0101 0001 0010 */ TABDECL(OP_LDR_M_IMM_OFF), // OP_LDR_M_IMM_OFF /* 0101 0001 0011 */ TABDECL(OP_LDR_M_IMM_OFF), // OP_LDR_M_IMM_OFF /* 0101 0001 0100 */ TABDECL(OP_LDR_M_IMM_OFF), // OP_LDR_M_IMM_OFF /* 0101 0001 0101 */ TABDECL(OP_LDR_M_IMM_OFF), // OP_LDR_M_IMM_OFF /* 0101 0001 0110 */ TABDECL(OP_LDR_M_IMM_OFF), // OP_LDR_M_IMM_OFF /* 0101 0001 0111 */ TABDECL(OP_LDR_M_IMM_OFF), // OP_LDR_M_IMM_OFF /* 0101 0001 1000 */ TABDECL(OP_LDR_M_IMM_OFF), // OP_LDR_M_IMM_OFF /* 0101 0001 1001 */ TABDECL(OP_LDR_M_IMM_OFF), // OP_LDR_M_IMM_OFF /* 0101 0001 1010 */ TABDECL(OP_LDR_M_IMM_OFF), // OP_LDR_M_IMM_OFF /* 0101 0001 1011 */ TABDECL(OP_LDR_M_IMM_OFF), // OP_LDR_M_IMM_OFF /* 0101 0001 1100 */ TABDECL(OP_LDR_M_IMM_OFF), // OP_LDR_M_IMM_OFF /* 0101 0001 1101 */ TABDECL(OP_LDR_M_IMM_OFF), // OP_LDR_M_IMM_OFF /* 0101 0001 1110 */ TABDECL(OP_LDR_M_IMM_OFF), // OP_LDR_M_IMM_OFF /* 0101 0001 1111 */ TABDECL(OP_LDR_M_IMM_OFF), // OP_LDR_M_IMM_OFF /* 0101 0010 0000 */ TABDECL(OP_STR_M_IMM_OFF_PREIND), // OP_STR_M_IMM_OFF_PREIND /* 0101 0010 0001 */ TABDECL(OP_STR_M_IMM_OFF_PREIND), // OP_STR_M_IMM_OFF_PREIND /* 0101 0010 0010 */ TABDECL(OP_STR_M_IMM_OFF_PREIND), // OP_STR_M_IMM_OFF_PREIND /* 0101 0010 0011 */ TABDECL(OP_STR_M_IMM_OFF_PREIND), // OP_STR_M_IMM_OFF_PREIND /* 0101 0010 0100 */ TABDECL(OP_STR_M_IMM_OFF_PREIND), // OP_STR_M_IMM_OFF_PREIND /* 0101 0010 0101 */ TABDECL(OP_STR_M_IMM_OFF_PREIND), // OP_STR_M_IMM_OFF_PREIND /* 0101 0010 0110 */ TABDECL(OP_STR_M_IMM_OFF_PREIND), // OP_STR_M_IMM_OFF_PREIND /* 0101 0010 0111 */ TABDECL(OP_STR_M_IMM_OFF_PREIND), // OP_STR_M_IMM_OFF_PREIND /* 0101 0010 1000 */ TABDECL(OP_STR_M_IMM_OFF_PREIND), // OP_STR_M_IMM_OFF_PREIND /* 0101 0010 1001 */ TABDECL(OP_STR_M_IMM_OFF_PREIND), // OP_STR_M_IMM_OFF_PREIND /* 0101 0010 1010 */ TABDECL(OP_STR_M_IMM_OFF_PREIND), // OP_STR_M_IMM_OFF_PREIND /* 0101 0010 1011 */ TABDECL(OP_STR_M_IMM_OFF_PREIND), // OP_STR_M_IMM_OFF_PREIND /* 0101 0010 1100 */ TABDECL(OP_STR_M_IMM_OFF_PREIND), // OP_STR_M_IMM_OFF_PREIND /* 0101 0010 1101 */ TABDECL(OP_STR_M_IMM_OFF_PREIND), // OP_STR_M_IMM_OFF_PREIND /* 0101 0010 1110 */ TABDECL(OP_STR_M_IMM_OFF_PREIND), // OP_STR_M_IMM_OFF_PREIND /* 0101 0010 1111 */ TABDECL(OP_STR_M_IMM_OFF_PREIND), // OP_STR_M_IMM_OFF_PREIND /* 0101 0011 0000 */ TABDECL(OP_LDR_M_IMM_OFF_PREIND), // OP_LDR_M_IMM_OFF_PREIND /* 0101 0011 0001 */ TABDECL(OP_LDR_M_IMM_OFF_PREIND), // OP_LDR_M_IMM_OFF_PREIND /* 0101 0011 0010 */ TABDECL(OP_LDR_M_IMM_OFF_PREIND), // OP_LDR_M_IMM_OFF_PREIND /* 0101 0011 0011 */ TABDECL(OP_LDR_M_IMM_OFF_PREIND), // OP_LDR_M_IMM_OFF_PREIND /* 0101 0011 0100 */ TABDECL(OP_LDR_M_IMM_OFF_PREIND), // OP_LDR_M_IMM_OFF_PREIND /* 0101 0011 0101 */ TABDECL(OP_LDR_M_IMM_OFF_PREIND), // OP_LDR_M_IMM_OFF_PREIND /* 0101 0011 0110 */ TABDECL(OP_LDR_M_IMM_OFF_PREIND), // OP_LDR_M_IMM_OFF_PREIND /* 0101 0011 0111 */ TABDECL(OP_LDR_M_IMM_OFF_PREIND), // OP_LDR_M_IMM_OFF_PREIND /* 0101 0011 1000 */ TABDECL(OP_LDR_M_IMM_OFF_PREIND), // OP_LDR_M_IMM_OFF_PREIND /* 0101 0011 1001 */ TABDECL(OP_LDR_M_IMM_OFF_PREIND), // OP_LDR_M_IMM_OFF_PREIND /* 0101 0011 1010 */ TABDECL(OP_LDR_M_IMM_OFF_PREIND), // OP_LDR_M_IMM_OFF_PREIND /* 0101 0011 1011 */ TABDECL(OP_LDR_M_IMM_OFF_PREIND), // OP_LDR_M_IMM_OFF_PREIND /* 0101 0011 1100 */ TABDECL(OP_LDR_M_IMM_OFF_PREIND), // OP_LDR_M_IMM_OFF_PREIND /* 0101 0011 1101 */ TABDECL(OP_LDR_M_IMM_OFF_PREIND), // OP_LDR_M_IMM_OFF_PREIND /* 0101 0011 1110 */ TABDECL(OP_LDR_M_IMM_OFF_PREIND), // OP_LDR_M_IMM_OFF_PREIND /* 0101 0011 1111 */ TABDECL(OP_LDR_M_IMM_OFF_PREIND), // OP_LDR_M_IMM_OFF_PREIND /* 0101 0100 0000 */ TABDECL(OP_STRB_M_IMM_OFF), // OP_STRB_M_IMM_OFF /* 0101 0100 0001 */ TABDECL(OP_STRB_M_IMM_OFF), // OP_STRB_M_IMM_OFF /* 0101 0100 0010 */ TABDECL(OP_STRB_M_IMM_OFF), // OP_STRB_M_IMM_OFF /* 0101 0100 0011 */ TABDECL(OP_STRB_M_IMM_OFF), // OP_STRB_M_IMM_OFF /* 0101 0100 0100 */ TABDECL(OP_STRB_M_IMM_OFF), // OP_STRB_M_IMM_OFF /* 0101 0100 0101 */ TABDECL(OP_STRB_M_IMM_OFF), // OP_STRB_M_IMM_OFF /* 0101 0100 0110 */ TABDECL(OP_STRB_M_IMM_OFF), // OP_STRB_M_IMM_OFF /* 0101 0100 0111 */ TABDECL(OP_STRB_M_IMM_OFF), // OP_STRB_M_IMM_OFF /* 0101 0100 1000 */ TABDECL(OP_STRB_M_IMM_OFF), // OP_STRB_M_IMM_OFF /* 0101 0100 1001 */ TABDECL(OP_STRB_M_IMM_OFF), // OP_STRB_M_IMM_OFF /* 0101 0100 1010 */ TABDECL(OP_STRB_M_IMM_OFF), // OP_STRB_M_IMM_OFF /* 0101 0100 1011 */ TABDECL(OP_STRB_M_IMM_OFF), // OP_STRB_M_IMM_OFF /* 0101 0100 1100 */ TABDECL(OP_STRB_M_IMM_OFF), // OP_STRB_M_IMM_OFF /* 0101 0100 1101 */ TABDECL(OP_STRB_M_IMM_OFF), // OP_STRB_M_IMM_OFF /* 0101 0100 1110 */ TABDECL(OP_STRB_M_IMM_OFF), // OP_STRB_M_IMM_OFF /* 0101 0100 1111 */ TABDECL(OP_STRB_M_IMM_OFF), // OP_STRB_M_IMM_OFF /* 0101 0101 0000 */ TABDECL(OP_LDRB_M_IMM_OFF), // OP_LDRB_M_IMM_OFF /* 0101 0101 0001 */ TABDECL(OP_LDRB_M_IMM_OFF), // OP_LDRB_M_IMM_OFF /* 0101 0101 0010 */ TABDECL(OP_LDRB_M_IMM_OFF), // OP_LDRB_M_IMM_OFF /* 0101 0101 0011 */ TABDECL(OP_LDRB_M_IMM_OFF), // OP_LDRB_M_IMM_OFF /* 0101 0101 0100 */ TABDECL(OP_LDRB_M_IMM_OFF), // OP_LDRB_M_IMM_OFF /* 0101 0101 0101 */ TABDECL(OP_LDRB_M_IMM_OFF), // OP_LDRB_M_IMM_OFF /* 0101 0101 0110 */ TABDECL(OP_LDRB_M_IMM_OFF), // OP_LDRB_M_IMM_OFF /* 0101 0101 0111 */ TABDECL(OP_LDRB_M_IMM_OFF), // OP_LDRB_M_IMM_OFF /* 0101 0101 1000 */ TABDECL(OP_LDRB_M_IMM_OFF), // OP_LDRB_M_IMM_OFF /* 0101 0101 1001 */ TABDECL(OP_LDRB_M_IMM_OFF), // OP_LDRB_M_IMM_OFF /* 0101 0101 1010 */ TABDECL(OP_LDRB_M_IMM_OFF), // OP_LDRB_M_IMM_OFF /* 0101 0101 1011 */ TABDECL(OP_LDRB_M_IMM_OFF), // OP_LDRB_M_IMM_OFF /* 0101 0101 1100 */ TABDECL(OP_LDRB_M_IMM_OFF), // OP_LDRB_M_IMM_OFF /* 0101 0101 1101 */ TABDECL(OP_LDRB_M_IMM_OFF), // OP_LDRB_M_IMM_OFF /* 0101 0101 1110 */ TABDECL(OP_LDRB_M_IMM_OFF), // OP_LDRB_M_IMM_OFF /* 0101 0101 1111 */ TABDECL(OP_LDRB_M_IMM_OFF), // OP_LDRB_M_IMM_OFF /* 0101 0110 0000 */ TABDECL(OP_STRB_M_IMM_OFF_PREIND), // OP_STRB_M_IMM_OFF_PREIND /* 0101 0110 0001 */ TABDECL(OP_STRB_M_IMM_OFF_PREIND), // OP_STRB_M_IMM_OFF_PREIND /* 0101 0110 0010 */ TABDECL(OP_STRB_M_IMM_OFF_PREIND), // OP_STRB_M_IMM_OFF_PREIND /* 0101 0110 0011 */ TABDECL(OP_STRB_M_IMM_OFF_PREIND), // OP_STRB_M_IMM_OFF_PREIND /* 0101 0110 0100 */ TABDECL(OP_STRB_M_IMM_OFF_PREIND), // OP_STRB_M_IMM_OFF_PREIND /* 0101 0110 0101 */ TABDECL(OP_STRB_M_IMM_OFF_PREIND), // OP_STRB_M_IMM_OFF_PREIND /* 0101 0110 0110 */ TABDECL(OP_STRB_M_IMM_OFF_PREIND), // OP_STRB_M_IMM_OFF_PREIND /* 0101 0110 0111 */ TABDECL(OP_STRB_M_IMM_OFF_PREIND), // OP_STRB_M_IMM_OFF_PREIND /* 0101 0110 1000 */ TABDECL(OP_STRB_M_IMM_OFF_PREIND), // OP_STRB_M_IMM_OFF_PREIND /* 0101 0110 1001 */ TABDECL(OP_STRB_M_IMM_OFF_PREIND), // OP_STRB_M_IMM_OFF_PREIND /* 0101 0110 1010 */ TABDECL(OP_STRB_M_IMM_OFF_PREIND), // OP_STRB_M_IMM_OFF_PREIND /* 0101 0110 1011 */ TABDECL(OP_STRB_M_IMM_OFF_PREIND), // OP_STRB_M_IMM_OFF_PREIND /* 0101 0110 1100 */ TABDECL(OP_STRB_M_IMM_OFF_PREIND), // OP_STRB_M_IMM_OFF_PREIND /* 0101 0110 1101 */ TABDECL(OP_STRB_M_IMM_OFF_PREIND), // OP_STRB_M_IMM_OFF_PREIND /* 0101 0110 1110 */ TABDECL(OP_STRB_M_IMM_OFF_PREIND), // OP_STRB_M_IMM_OFF_PREIND /* 0101 0110 1111 */ TABDECL(OP_STRB_M_IMM_OFF_PREIND), // OP_STRB_M_IMM_OFF_PREIND /* 0101 0111 0000 */ TABDECL(OP_LDRB_M_IMM_OFF_PREIND), // OP_LDRB_M_IMM_OFF_PREIND /* 0101 0111 0001 */ TABDECL(OP_LDRB_M_IMM_OFF_PREIND), // OP_LDRB_M_IMM_OFF_PREIND /* 0101 0111 0010 */ TABDECL(OP_LDRB_M_IMM_OFF_PREIND), // OP_LDRB_M_IMM_OFF_PREIND /* 0101 0111 0011 */ TABDECL(OP_LDRB_M_IMM_OFF_PREIND), // OP_LDRB_M_IMM_OFF_PREIND /* 0101 0111 0100 */ TABDECL(OP_LDRB_M_IMM_OFF_PREIND), // OP_LDRB_M_IMM_OFF_PREIND /* 0101 0111 0101 */ TABDECL(OP_LDRB_M_IMM_OFF_PREIND), // OP_LDRB_M_IMM_OFF_PREIND /* 0101 0111 0110 */ TABDECL(OP_LDRB_M_IMM_OFF_PREIND), // OP_LDRB_M_IMM_OFF_PREIND /* 0101 0111 0111 */ TABDECL(OP_LDRB_M_IMM_OFF_PREIND), // OP_LDRB_M_IMM_OFF_PREIND /* 0101 0111 1000 */ TABDECL(OP_LDRB_M_IMM_OFF_PREIND), // OP_LDRB_M_IMM_OFF_PREIND /* 0101 0111 1001 */ TABDECL(OP_LDRB_M_IMM_OFF_PREIND), // OP_LDRB_M_IMM_OFF_PREIND /* 0101 0111 1010 */ TABDECL(OP_LDRB_M_IMM_OFF_PREIND), // OP_LDRB_M_IMM_OFF_PREIND /* 0101 0111 1011 */ TABDECL(OP_LDRB_M_IMM_OFF_PREIND), // OP_LDRB_M_IMM_OFF_PREIND /* 0101 0111 1100 */ TABDECL(OP_LDRB_M_IMM_OFF_PREIND), // OP_LDRB_M_IMM_OFF_PREIND /* 0101 0111 1101 */ TABDECL(OP_LDRB_M_IMM_OFF_PREIND), // OP_LDRB_M_IMM_OFF_PREIND /* 0101 0111 1110 */ TABDECL(OP_LDRB_M_IMM_OFF_PREIND), // OP_LDRB_M_IMM_OFF_PREIND /* 0101 0111 1111 */ TABDECL(OP_LDRB_M_IMM_OFF_PREIND), // OP_LDRB_M_IMM_OFF_PREIND /* 0101 1000 0000 */ TABDECL(OP_STR_P_IMM_OFF), // OP_STR_P_IMM_OFF /* 0101 1000 0001 */ TABDECL(OP_STR_P_IMM_OFF), // OP_STR_P_IMM_OFF /* 0101 1000 0010 */ TABDECL(OP_STR_P_IMM_OFF), // OP_STR_P_IMM_OFF /* 0101 1000 0011 */ TABDECL(OP_STR_P_IMM_OFF), // OP_STR_P_IMM_OFF /* 0101 1000 0100 */ TABDECL(OP_STR_P_IMM_OFF), // OP_STR_P_IMM_OFF /* 0101 1000 0101 */ TABDECL(OP_STR_P_IMM_OFF), // OP_STR_P_IMM_OFF /* 0101 1000 0110 */ TABDECL(OP_STR_P_IMM_OFF), // OP_STR_P_IMM_OFF /* 0101 1000 0111 */ TABDECL(OP_STR_P_IMM_OFF), // OP_STR_P_IMM_OFF /* 0101 1000 1000 */ TABDECL(OP_STR_P_IMM_OFF), // OP_STR_P_IMM_OFF /* 0101 1000 1001 */ TABDECL(OP_STR_P_IMM_OFF), // OP_STR_P_IMM_OFF /* 0101 1000 1010 */ TABDECL(OP_STR_P_IMM_OFF), // OP_STR_P_IMM_OFF /* 0101 1000 1011 */ TABDECL(OP_STR_P_IMM_OFF), // OP_STR_P_IMM_OFF /* 0101 1000 1100 */ TABDECL(OP_STR_P_IMM_OFF), // OP_STR_P_IMM_OFF /* 0101 1000 1101 */ TABDECL(OP_STR_P_IMM_OFF), // OP_STR_P_IMM_OFF /* 0101 1000 1110 */ TABDECL(OP_STR_P_IMM_OFF), // OP_STR_P_IMM_OFF /* 0101 1000 1111 */ TABDECL(OP_STR_P_IMM_OFF), // OP_STR_P_IMM_OFF /* 0101 1001 0000 */ TABDECL(OP_LDR_P_IMM_OFF), // OP_LDR_P_IMM_OFF /* 0101 1001 0001 */ TABDECL(OP_LDR_P_IMM_OFF), // OP_LDR_P_IMM_OFF /* 0101 1001 0010 */ TABDECL(OP_LDR_P_IMM_OFF), // OP_LDR_P_IMM_OFF /* 0101 1001 0011 */ TABDECL(OP_LDR_P_IMM_OFF), // OP_LDR_P_IMM_OFF /* 0101 1001 0100 */ TABDECL(OP_LDR_P_IMM_OFF), // OP_LDR_P_IMM_OFF /* 0101 1001 0101 */ TABDECL(OP_LDR_P_IMM_OFF), // OP_LDR_P_IMM_OFF /* 0101 1001 0110 */ TABDECL(OP_LDR_P_IMM_OFF), // OP_LDR_P_IMM_OFF /* 0101 1001 0111 */ TABDECL(OP_LDR_P_IMM_OFF), // OP_LDR_P_IMM_OFF /* 0101 1001 1000 */ TABDECL(OP_LDR_P_IMM_OFF), // OP_LDR_P_IMM_OFF /* 0101 1001 1001 */ TABDECL(OP_LDR_P_IMM_OFF), // OP_LDR_P_IMM_OFF /* 0101 1001 1010 */ TABDECL(OP_LDR_P_IMM_OFF), // OP_LDR_P_IMM_OFF /* 0101 1001 1011 */ TABDECL(OP_LDR_P_IMM_OFF), // OP_LDR_P_IMM_OFF /* 0101 1001 1100 */ TABDECL(OP_LDR_P_IMM_OFF), // OP_LDR_P_IMM_OFF /* 0101 1001 1101 */ TABDECL(OP_LDR_P_IMM_OFF), // OP_LDR_P_IMM_OFF /* 0101 1001 1110 */ TABDECL(OP_LDR_P_IMM_OFF), // OP_LDR_P_IMM_OFF /* 0101 1001 1111 */ TABDECL(OP_LDR_P_IMM_OFF), // OP_LDR_P_IMM_OFF /* 0101 1010 0000 */ TABDECL(OP_STR_P_IMM_OFF_PREIND), // OP_STR_P_IMM_OFF_PREIND /* 0101 1010 0001 */ TABDECL(OP_STR_P_IMM_OFF_PREIND), // OP_STR_P_IMM_OFF_PREIND /* 0101 1010 0010 */ TABDECL(OP_STR_P_IMM_OFF_PREIND), // OP_STR_P_IMM_OFF_PREIND /* 0101 1010 0011 */ TABDECL(OP_STR_P_IMM_OFF_PREIND), // OP_STR_P_IMM_OFF_PREIND /* 0101 1010 0100 */ TABDECL(OP_STR_P_IMM_OFF_PREIND), // OP_STR_P_IMM_OFF_PREIND /* 0101 1010 0101 */ TABDECL(OP_STR_P_IMM_OFF_PREIND), // OP_STR_P_IMM_OFF_PREIND /* 0101 1010 0110 */ TABDECL(OP_STR_P_IMM_OFF_PREIND), // OP_STR_P_IMM_OFF_PREIND /* 0101 1010 0111 */ TABDECL(OP_STR_P_IMM_OFF_PREIND), // OP_STR_P_IMM_OFF_PREIND /* 0101 1010 1000 */ TABDECL(OP_STR_P_IMM_OFF_PREIND), // OP_STR_P_IMM_OFF_PREIND /* 0101 1010 1001 */ TABDECL(OP_STR_P_IMM_OFF_PREIND), // OP_STR_P_IMM_OFF_PREIND /* 0101 1010 1010 */ TABDECL(OP_STR_P_IMM_OFF_PREIND), // OP_STR_P_IMM_OFF_PREIND /* 0101 1010 1011 */ TABDECL(OP_STR_P_IMM_OFF_PREIND), // OP_STR_P_IMM_OFF_PREIND /* 0101 1010 1100 */ TABDECL(OP_STR_P_IMM_OFF_PREIND), // OP_STR_P_IMM_OFF_PREIND /* 0101 1010 1101 */ TABDECL(OP_STR_P_IMM_OFF_PREIND), // OP_STR_P_IMM_OFF_PREIND /* 0101 1010 1110 */ TABDECL(OP_STR_P_IMM_OFF_PREIND), // OP_STR_P_IMM_OFF_PREIND /* 0101 1010 1111 */ TABDECL(OP_STR_P_IMM_OFF_PREIND), // OP_STR_P_IMM_OFF_PREIND /* 0101 1011 0000 */ TABDECL(OP_LDR_P_IMM_OFF_PREIND), // OP_LDR_P_IMM_OFF_PREIND /* 0101 1011 0001 */ TABDECL(OP_LDR_P_IMM_OFF_PREIND), // OP_LDR_P_IMM_OFF_PREIND /* 0101 1011 0010 */ TABDECL(OP_LDR_P_IMM_OFF_PREIND), // OP_LDR_P_IMM_OFF_PREIND /* 0101 1011 0011 */ TABDECL(OP_LDR_P_IMM_OFF_PREIND), // OP_LDR_P_IMM_OFF_PREIND /* 0101 1011 0100 */ TABDECL(OP_LDR_P_IMM_OFF_PREIND), // OP_LDR_P_IMM_OFF_PREIND /* 0101 1011 0101 */ TABDECL(OP_LDR_P_IMM_OFF_PREIND), // OP_LDR_P_IMM_OFF_PREIND /* 0101 1011 0110 */ TABDECL(OP_LDR_P_IMM_OFF_PREIND), // OP_LDR_P_IMM_OFF_PREIND /* 0101 1011 0111 */ TABDECL(OP_LDR_P_IMM_OFF_PREIND), // OP_LDR_P_IMM_OFF_PREIND /* 0101 1011 1000 */ TABDECL(OP_LDR_P_IMM_OFF_PREIND), // OP_LDR_P_IMM_OFF_PREIND /* 0101 1011 1001 */ TABDECL(OP_LDR_P_IMM_OFF_PREIND), // OP_LDR_P_IMM_OFF_PREIND /* 0101 1011 1010 */ TABDECL(OP_LDR_P_IMM_OFF_PREIND), // OP_LDR_P_IMM_OFF_PREIND /* 0101 1011 1011 */ TABDECL(OP_LDR_P_IMM_OFF_PREIND), // OP_LDR_P_IMM_OFF_PREIND /* 0101 1011 1100 */ TABDECL(OP_LDR_P_IMM_OFF_PREIND), // OP_LDR_P_IMM_OFF_PREIND /* 0101 1011 1101 */ TABDECL(OP_LDR_P_IMM_OFF_PREIND), // OP_LDR_P_IMM_OFF_PREIND /* 0101 1011 1110 */ TABDECL(OP_LDR_P_IMM_OFF_PREIND), // OP_LDR_P_IMM_OFF_PREIND /* 0101 1011 1111 */ TABDECL(OP_LDR_P_IMM_OFF_PREIND), // OP_LDR_P_IMM_OFF_PREIND /* 0101 1100 0000 */ TABDECL(OP_STRB_P_IMM_OFF), // OP_STRB_P_IMM_OFF /* 0101 1100 0001 */ TABDECL(OP_STRB_P_IMM_OFF), // OP_STRB_P_IMM_OFF /* 0101 1100 0010 */ TABDECL(OP_STRB_P_IMM_OFF), // OP_STRB_P_IMM_OFF /* 0101 1100 0011 */ TABDECL(OP_STRB_P_IMM_OFF), // OP_STRB_P_IMM_OFF /* 0101 1100 0100 */ TABDECL(OP_STRB_P_IMM_OFF), // OP_STRB_P_IMM_OFF /* 0101 1100 0101 */ TABDECL(OP_STRB_P_IMM_OFF), // OP_STRB_P_IMM_OFF /* 0101 1100 0110 */ TABDECL(OP_STRB_P_IMM_OFF), // OP_STRB_P_IMM_OFF /* 0101 1100 0111 */ TABDECL(OP_STRB_P_IMM_OFF), // OP_STRB_P_IMM_OFF /* 0101 1100 1000 */ TABDECL(OP_STRB_P_IMM_OFF), // OP_STRB_P_IMM_OFF /* 0101 1100 1001 */ TABDECL(OP_STRB_P_IMM_OFF), // OP_STRB_P_IMM_OFF /* 0101 1100 1010 */ TABDECL(OP_STRB_P_IMM_OFF), // OP_STRB_P_IMM_OFF /* 0101 1100 1011 */ TABDECL(OP_STRB_P_IMM_OFF), // OP_STRB_P_IMM_OFF /* 0101 1100 1100 */ TABDECL(OP_STRB_P_IMM_OFF), // OP_STRB_P_IMM_OFF /* 0101 1100 1101 */ TABDECL(OP_STRB_P_IMM_OFF), // OP_STRB_P_IMM_OFF /* 0101 1100 1110 */ TABDECL(OP_STRB_P_IMM_OFF), // OP_STRB_P_IMM_OFF /* 0101 1100 1111 */ TABDECL(OP_STRB_P_IMM_OFF), // OP_STRB_P_IMM_OFF /* 0101 1101 0000 */ TABDECL(OP_LDRB_P_IMM_OFF), // OP_LDRB_P_IMM_OFF /* 0101 1101 0001 */ TABDECL(OP_LDRB_P_IMM_OFF), // OP_LDRB_P_IMM_OFF /* 0101 1101 0010 */ TABDECL(OP_LDRB_P_IMM_OFF), // OP_LDRB_P_IMM_OFF /* 0101 1101 0011 */ TABDECL(OP_LDRB_P_IMM_OFF), // OP_LDRB_P_IMM_OFF /* 0101 1101 0100 */ TABDECL(OP_LDRB_P_IMM_OFF), // OP_LDRB_P_IMM_OFF /* 0101 1101 0101 */ TABDECL(OP_LDRB_P_IMM_OFF), // OP_LDRB_P_IMM_OFF /* 0101 1101 0110 */ TABDECL(OP_LDRB_P_IMM_OFF), // OP_LDRB_P_IMM_OFF /* 0101 1101 0111 */ TABDECL(OP_LDRB_P_IMM_OFF), // OP_LDRB_P_IMM_OFF /* 0101 1101 1000 */ TABDECL(OP_LDRB_P_IMM_OFF), // OP_LDRB_P_IMM_OFF /* 0101 1101 1001 */ TABDECL(OP_LDRB_P_IMM_OFF), // OP_LDRB_P_IMM_OFF /* 0101 1101 1010 */ TABDECL(OP_LDRB_P_IMM_OFF), // OP_LDRB_P_IMM_OFF /* 0101 1101 1011 */ TABDECL(OP_LDRB_P_IMM_OFF), // OP_LDRB_P_IMM_OFF /* 0101 1101 1100 */ TABDECL(OP_LDRB_P_IMM_OFF), // OP_LDRB_P_IMM_OFF /* 0101 1101 1101 */ TABDECL(OP_LDRB_P_IMM_OFF), // OP_LDRB_P_IMM_OFF /* 0101 1101 1110 */ TABDECL(OP_LDRB_P_IMM_OFF), // OP_LDRB_P_IMM_OFF /* 0101 1101 1111 */ TABDECL(OP_LDRB_P_IMM_OFF), // OP_LDRB_P_IMM_OFF /* 0101 1110 0000 */ TABDECL(OP_STRB_P_IMM_OFF_PREIND), // OP_STRB_P_IMM_OFF_PREIND /* 0101 1110 0001 */ TABDECL(OP_STRB_P_IMM_OFF_PREIND), // OP_STRB_P_IMM_OFF_PREIND /* 0101 1110 0010 */ TABDECL(OP_STRB_P_IMM_OFF_PREIND), // OP_STRB_P_IMM_OFF_PREIND /* 0101 1110 0011 */ TABDECL(OP_STRB_P_IMM_OFF_PREIND), // OP_STRB_P_IMM_OFF_PREIND /* 0101 1110 0100 */ TABDECL(OP_STRB_P_IMM_OFF_PREIND), // OP_STRB_P_IMM_OFF_PREIND /* 0101 1110 0101 */ TABDECL(OP_STRB_P_IMM_OFF_PREIND), // OP_STRB_P_IMM_OFF_PREIND /* 0101 1110 0110 */ TABDECL(OP_STRB_P_IMM_OFF_PREIND), // OP_STRB_P_IMM_OFF_PREIND /* 0101 1110 0111 */ TABDECL(OP_STRB_P_IMM_OFF_PREIND), // OP_STRB_P_IMM_OFF_PREIND /* 0101 1110 1000 */ TABDECL(OP_STRB_P_IMM_OFF_PREIND), // OP_STRB_P_IMM_OFF_PREIND /* 0101 1110 1001 */ TABDECL(OP_STRB_P_IMM_OFF_PREIND), // OP_STRB_P_IMM_OFF_PREIND /* 0101 1110 1010 */ TABDECL(OP_STRB_P_IMM_OFF_PREIND), // OP_STRB_P_IMM_OFF_PREIND /* 0101 1110 1011 */ TABDECL(OP_STRB_P_IMM_OFF_PREIND), // OP_STRB_P_IMM_OFF_PREIND /* 0101 1110 1100 */ TABDECL(OP_STRB_P_IMM_OFF_PREIND), // OP_STRB_P_IMM_OFF_PREIND /* 0101 1110 1101 */ TABDECL(OP_STRB_P_IMM_OFF_PREIND), // OP_STRB_P_IMM_OFF_PREIND /* 0101 1110 1110 */ TABDECL(OP_STRB_P_IMM_OFF_PREIND), // OP_STRB_P_IMM_OFF_PREIND /* 0101 1110 1111 */ TABDECL(OP_STRB_P_IMM_OFF_PREIND), // OP_STRB_P_IMM_OFF_PREIND /* 0101 1111 0000 */ TABDECL(OP_LDRB_P_IMM_OFF_PREIND), // OP_LDRB_P_IMM_OFF_PREIND /* 0101 1111 0001 */ TABDECL(OP_LDRB_P_IMM_OFF_PREIND), // OP_LDRB_P_IMM_OFF_PREIND /* 0101 1111 0010 */ TABDECL(OP_LDRB_P_IMM_OFF_PREIND), // OP_LDRB_P_IMM_OFF_PREIND /* 0101 1111 0011 */ TABDECL(OP_LDRB_P_IMM_OFF_PREIND), // OP_LDRB_P_IMM_OFF_PREIND /* 0101 1111 0100 */ TABDECL(OP_LDRB_P_IMM_OFF_PREIND), // OP_LDRB_P_IMM_OFF_PREIND /* 0101 1111 0101 */ TABDECL(OP_LDRB_P_IMM_OFF_PREIND), // OP_LDRB_P_IMM_OFF_PREIND /* 0101 1111 0110 */ TABDECL(OP_LDRB_P_IMM_OFF_PREIND), // OP_LDRB_P_IMM_OFF_PREIND /* 0101 1111 0111 */ TABDECL(OP_LDRB_P_IMM_OFF_PREIND), // OP_LDRB_P_IMM_OFF_PREIND /* 0101 1111 1000 */ TABDECL(OP_LDRB_P_IMM_OFF_PREIND), // OP_LDRB_P_IMM_OFF_PREIND /* 0101 1111 1001 */ TABDECL(OP_LDRB_P_IMM_OFF_PREIND), // OP_LDRB_P_IMM_OFF_PREIND /* 0101 1111 1010 */ TABDECL(OP_LDRB_P_IMM_OFF_PREIND), // OP_LDRB_P_IMM_OFF_PREIND /* 0101 1111 1011 */ TABDECL(OP_LDRB_P_IMM_OFF_PREIND), // OP_LDRB_P_IMM_OFF_PREIND /* 0101 1111 1100 */ TABDECL(OP_LDRB_P_IMM_OFF_PREIND), // OP_LDRB_P_IMM_OFF_PREIND /* 0101 1111 1101 */ TABDECL(OP_LDRB_P_IMM_OFF_PREIND), // OP_LDRB_P_IMM_OFF_PREIND /* 0101 1111 1110 */ TABDECL(OP_LDRB_P_IMM_OFF_PREIND), // OP_LDRB_P_IMM_OFF_PREIND /* 0101 1111 1111 */ TABDECL(OP_LDRB_P_IMM_OFF_PREIND), // OP_LDRB_P_IMM_OFF_PREIND /* 0110 0000 0000 */ TABDECL(OP_STR_M_LSL_IMM_OFF_POSTIND), // OP_STR_M_LSL_IMM_OFF_POSTIND /* 0110 0000 0001 */ TABDECL(OP_UND), /* 0110 0000 0010 */ TABDECL(OP_STR_M_LSR_IMM_OFF_POSTIND), // OP_STR_M_LSR_IMM_OFF_POSTIND /* 0110 0000 0011 */ TABDECL(OP_UND), /* 0110 0000 0100 */ TABDECL(OP_STR_M_ASR_IMM_OFF_POSTIND), // OP_STR_M_ASR_IMM_OFF_POSTIND /* 0110 0000 0101 */ TABDECL(OP_UND), /* 0110 0000 0110 */ TABDECL(OP_STR_M_ROR_IMM_OFF_POSTIND), // OP_STR_M_ROR_IMM_OFF_POSTIND /* 0110 0000 0111 */ TABDECL(OP_UND), /* 0110 0000 1000 */ TABDECL(OP_STR_M_LSL_IMM_OFF_POSTIND), // OP_STR_M_LSL_IMM_OFF_POSTIND /* 0110 0000 1001 */ TABDECL(OP_UND), /* 0110 0000 1010 */ TABDECL(OP_STR_M_LSR_IMM_OFF_POSTIND), // OP_STR_M_LSR_IMM_OFF_POSTIND /* 0110 0000 1011 */ TABDECL(OP_UND), /* 0110 0000 1100 */ TABDECL(OP_STR_M_ASR_IMM_OFF_POSTIND), // OP_STR_M_ASR_IMM_OFF_POSTIND /* 0110 0000 1101 */ TABDECL(OP_UND), /* 0110 0000 1110 */ TABDECL(OP_STR_M_ROR_IMM_OFF_POSTIND), // OP_STR_M_ROR_IMM_OFF_POSTIND /* 0110 0000 1111 */ TABDECL(OP_UND), /* 0110 0001 0000 */ TABDECL(OP_LDR_M_LSL_IMM_OFF_POSTIND), // OP_LDR_M_LSL_IMM_OFF_POSTIND /* 0110 0001 0001 */ TABDECL(OP_UND), /* 0110 0001 0010 */ TABDECL(OP_LDR_M_LSR_IMM_OFF_POSTIND), // OP_LDR_M_LSR_IMM_OFF_POSTIND /* 0110 0001 0011 */ TABDECL(OP_UND), /* 0110 0001 0100 */ TABDECL(OP_LDR_M_ASR_IMM_OFF_POSTIND), // OP_LDR_M_ASR_IMM_OFF_POSTIND /* 0110 0001 0101 */ TABDECL(OP_UND), /* 0110 0001 0110 */ TABDECL(OP_LDR_M_ROR_IMM_OFF_POSTIND), // OP_LDR_M_ROR_IMM_OFF_POSTIND /* 0110 0001 0111 */ TABDECL(OP_UND), /* 0110 0001 1000 */ TABDECL(OP_LDR_M_LSL_IMM_OFF_POSTIND), // OP_LDR_M_LSL_IMM_OFF_POSTIND /* 0110 0001 1001 */ TABDECL(OP_UND), /* 0110 0001 1010 */ TABDECL(OP_LDR_M_LSR_IMM_OFF_POSTIND), // OP_LDR_M_LSR_IMM_OFF_POSTIND /* 0110 0001 1011 */ TABDECL(OP_UND), /* 0110 0001 1100 */ TABDECL(OP_LDR_M_ASR_IMM_OFF_POSTIND), // OP_LDR_M_ASR_IMM_OFF_POSTIND /* 0110 0001 1101 */ TABDECL(OP_UND), /* 0110 0001 1110 */ TABDECL(OP_LDR_M_ROR_IMM_OFF_POSTIND), // OP_LDR_M_ROR_IMM_OFF_POSTIND /* 0110 0001 1111 */ TABDECL(OP_UND), /* 0110 0010 0000 */ TABDECL(OP_STR_M_LSL_IMM_OFF_POSTIND), // OP_STR_M_LSL_IMM_OFF_POSTIND //changed from OP_UND in r3504 /* 0110 0010 0001 */ TABDECL(OP_UND), /* 0110 0010 0010 */ TABDECL(OP_STR_M_LSR_IMM_OFF_POSTIND), // OP_STR_M_LSR_IMM_OFF_POSTIND //changed from OP_UND in r3504 /* 0110 0010 0011 */ TABDECL(OP_UND), /* 0110 0010 0100 */ TABDECL(OP_STR_M_ASR_IMM_OFF_POSTIND), // OP_STR_M_ASR_IMM_OFF_POSTIND //changed from OP_UND in r3504 /* 0110 0010 0101 */ TABDECL(OP_UND), /* 0110 0010 0110 */ TABDECL(OP_STR_M_ROR_IMM_OFF_POSTIND), // OP_STR_M_ROR_IMM_OFF_POSTIND //changed from OP_UND in r3504 /* 0110 0010 0111 */ TABDECL(OP_UND), /* 0110 0010 1000 */ TABDECL(OP_STR_M_LSL_IMM_OFF_POSTIND), // OP_STR_M_LSL_IMM_OFF_POSTIND //changed from OP_UND in r3504 /* 0110 0010 1001 */ TABDECL(OP_UND), /* 0110 0010 1010 */ TABDECL(OP_STR_M_LSR_IMM_OFF_POSTIND), // OP_STR_M_LSR_IMM_OFF_POSTIND //changed from OP_UND in r3504 /* 0110 0010 1011 */ TABDECL(OP_UND), /* 0110 0010 1100 */ TABDECL(OP_STR_M_ASR_IMM_OFF_POSTIND), // OP_STR_M_ASR_IMM_OFF_POSTIND //changed from OP_UND in r3504 /* 0110 0010 1101 */ TABDECL(OP_UND), /* 0110 0010 1110 */ TABDECL(OP_STR_M_ROR_IMM_OFF_POSTIND), // OP_STR_M_ROR_IMM_OFF_POSTIND //changed from OP_UND in r3504 /* 0110 0010 1111 */ TABDECL(OP_UND), /* 0110 0011 0000 */ TABDECL(OP_LDR_M_LSL_IMM_OFF_POSTIND), // OP_LDR_M_LSL_IMM_OFF_POSTIND //changed from OP_UND in r3504 /* 0110 0011 0001 */ TABDECL(OP_UND), /* 0110 0011 0010 */ TABDECL(OP_LDR_M_LSR_IMM_OFF_POSTIND), // OP_LDR_M_LSR_IMM_OFF_POSTIND //changed from OP_UND in r3504 /* 0110 0011 0011 */ TABDECL(OP_UND), /* 0110 0011 0100 */ TABDECL(OP_LDR_M_ASR_IMM_OFF_POSTIND), // OP_LDR_M_ASR_IMM_OFF_POSTIND //changed from OP_UND in r3504 /* 0110 0011 0101 */ TABDECL(OP_UND), /* 0110 0011 0110 */ TABDECL(OP_LDR_M_ROR_IMM_OFF_POSTIND), // OP_LDR_M_ROR_IMM_OFF_POSTIND //changed from OP_UND in r3504 /* 0110 0011 0111 */ TABDECL(OP_UND), /* 0110 0011 1000 */ TABDECL(OP_LDR_M_LSL_IMM_OFF_POSTIND), // OP_LDR_M_LSL_IMM_OFF_POSTIND //changed from OP_UND in r3504 /* 0110 0011 1001 */ TABDECL(OP_UND), /* 0110 0011 1010 */ TABDECL(OP_LDR_M_LSR_IMM_OFF_POSTIND), // OP_LDR_M_LSR_IMM_OFF_POSTIND //changed from OP_UND in r3504 /* 0110 0011 1011 */ TABDECL(OP_UND), /* 0110 0011 1100 */ TABDECL(OP_LDR_M_ASR_IMM_OFF_POSTIND), // OP_LDR_M_ASR_IMM_OFF_POSTIND //changed from OP_UND in r3504 /* 0110 0011 1101 */ TABDECL(OP_UND), /* 0110 0011 1110 */ TABDECL(OP_LDR_M_ROR_IMM_OFF_POSTIND), // OP_LDR_M_ROR_IMM_OFF_POSTIND //changed from OP_UND in r3504 /* 0110 0011 1111 */ TABDECL(OP_UND), /* 0110 0100 0000 */ TABDECL(OP_STRB_M_LSL_IMM_OFF_POSTIND), // OP_STRB_M_LSL_IMM_OFF_POSTIND /* 0110 0100 0001 */ TABDECL(OP_UND), /* 0110 0100 0010 */ TABDECL(OP_STRB_M_LSR_IMM_OFF_POSTIND), // OP_STRB_M_LSR_IMM_OFF_POSTIND /* 0110 0100 0011 */ TABDECL(OP_UND), /* 0110 0100 0100 */ TABDECL(OP_STRB_M_ASR_IMM_OFF_POSTIND), // OP_STRB_M_ASR_IMM_OFF_POSTIND /* 0110 0100 0101 */ TABDECL(OP_UND), /* 0110 0100 0110 */ TABDECL(OP_STRB_M_ROR_IMM_OFF_POSTIND), // OP_STRB_M_ROR_IMM_OFF_POSTIND /* 0110 0100 0111 */ TABDECL(OP_UND), /* 0110 0100 1000 */ TABDECL(OP_STRB_M_LSL_IMM_OFF_POSTIND), // OP_STRB_M_LSL_IMM_OFF_POSTIND /* 0110 0100 1001 */ TABDECL(OP_UND), /* 0110 0100 1010 */ TABDECL(OP_STRB_M_LSR_IMM_OFF_POSTIND), // OP_STRB_M_LSR_IMM_OFF_POSTIND /* 0110 0100 1011 */ TABDECL(OP_UND), /* 0110 0100 1100 */ TABDECL(OP_STRB_M_ASR_IMM_OFF_POSTIND), // OP_STRB_M_ASR_IMM_OFF_POSTIND /* 0110 0100 1101 */ TABDECL(OP_UND), /* 0110 0100 1110 */ TABDECL(OP_STRB_M_ROR_IMM_OFF_POSTIND), // OP_STRB_M_ROR_IMM_OFF_POSTIND /* 0110 0100 1111 */ TABDECL(OP_UND), /* 0110 0101 0000 */ TABDECL(OP_LDRB_M_LSL_IMM_OFF_POSTIND), // OP_LDRB_M_LSL_IMM_OFF_POSTIND /* 0110 0101 0001 */ TABDECL(OP_UND), /* 0110 0101 0010 */ TABDECL(OP_LDRB_M_LSR_IMM_OFF_POSTIND), // OP_LDRB_M_LSR_IMM_OFF_POSTIND /* 0110 0101 0011 */ TABDECL(OP_UND), /* 0110 0101 0100 */ TABDECL(OP_LDRB_M_ASR_IMM_OFF_POSTIND), // OP_LDRB_M_ASR_IMM_OFF_POSTIND /* 0110 0101 0101 */ TABDECL(OP_UND), /* 0110 0101 0110 */ TABDECL(OP_LDRB_M_ROR_IMM_OFF_POSTIND), // OP_LDRB_M_ROR_IMM_OFF_POSTIND /* 0110 0101 0111 */ TABDECL(OP_UND), /* 0110 0101 1000 */ TABDECL(OP_LDRB_M_LSL_IMM_OFF_POSTIND), // OP_LDRB_M_LSL_IMM_OFF_POSTIND /* 0110 0101 1001 */ TABDECL(OP_UND), /* 0110 0101 1010 */ TABDECL(OP_LDRB_M_LSR_IMM_OFF_POSTIND), // OP_LDRB_M_LSR_IMM_OFF_POSTIND /* 0110 0101 1011 */ TABDECL(OP_UND), /* 0110 0101 1100 */ TABDECL(OP_LDRB_M_ASR_IMM_OFF_POSTIND), // OP_LDRB_M_ASR_IMM_OFF_POSTIND /* 0110 0101 1101 */ TABDECL(OP_UND), /* 0110 0101 1110 */ TABDECL(OP_LDRB_M_ROR_IMM_OFF_POSTIND), // OP_LDRB_M_ROR_IMM_OFF_POSTIND /* 0110 0101 1111 */ TABDECL(OP_UND), /* 0110 0110 0000 */ TABDECL(OP_STRB_M_LSL_IMM_OFF_POSTIND), // OP_STRB_M_LSL_IMM_OFF_POSTIND //changed from OP_UND in r3504 /* 0110 0110 0001 */ TABDECL(OP_UND), /* 0110 0110 0010 */ TABDECL(OP_STRB_M_LSR_IMM_OFF_POSTIND), // OP_STRB_M_LSR_IMM_OFF_POSTIND //changed from OP_UND in r3504 /* 0110 0110 0011 */ TABDECL(OP_UND), /* 0110 0110 0100 */ TABDECL(OP_STRB_M_ASR_IMM_OFF_POSTIND), // OP_STRB_M_ASR_IMM_OFF_POSTIND //changed from OP_UND in r3504 /* 0110 0110 0101 */ TABDECL(OP_UND), /* 0110 0110 0110 */ TABDECL(OP_STRB_M_ROR_IMM_OFF_POSTIND), // OP_STRB_M_ROR_IMM_OFF_POSTIND //changed from OP_UND in r3504 /* 0110 0110 0111 */ TABDECL(OP_UND), /* 0110 0110 1000 */ TABDECL(OP_STRB_M_LSL_IMM_OFF_POSTIND), // OP_STRB_M_LSL_IMM_OFF_POSTIND //changed from OP_UND in r3504 /* 0110 0110 1001 */ TABDECL(OP_UND), /* 0110 0110 1010 */ TABDECL(OP_STRB_M_LSR_IMM_OFF_POSTIND), // OP_STRB_M_LSR_IMM_OFF_POSTIND //changed from OP_UND in r3504 /* 0110 0110 1011 */ TABDECL(OP_UND), /* 0110 0110 1100 */ TABDECL(OP_STRB_M_ASR_IMM_OFF_POSTIND), // OP_STRB_M_ASR_IMM_OFF_POSTIND //changed from OP_UND in r3504 /* 0110 0110 1101 */ TABDECL(OP_UND), /* 0110 0110 1110 */ TABDECL(OP_STRB_M_ROR_IMM_OFF_POSTIND), // OP_STRB_M_ROR_IMM_OFF_POSTIND //changed from OP_UND in r3504 /* 0110 0110 1111 */ TABDECL(OP_UND), /* 0110 0111 0000 */ TABDECL(OP_LDRB_M_LSL_IMM_OFF_POSTIND), // OP_LDRB_M_LSL_IMM_OFF_POSTIND //changed from OP_UND in r3504 /* 0110 0111 0001 */ TABDECL(OP_UND), /* 0110 0111 0010 */ TABDECL(OP_LDRB_M_LSR_IMM_OFF_POSTIND), // OP_LDRB_M_LSR_IMM_OFF_POSTIND //changed from OP_UND in r3504 /* 0110 0111 0011 */ TABDECL(OP_UND), /* 0110 0111 0100 */ TABDECL(OP_LDRB_M_ASR_IMM_OFF_POSTIND), // OP_LDRB_M_ASR_IMM_OFF_POSTIND //changed from OP_UND in r3504 /* 0110 0111 0101 */ TABDECL(OP_UND), /* 0110 0111 0110 */ TABDECL(OP_LDRB_M_ROR_IMM_OFF_POSTIND), // OP_LDRB_M_ROR_IMM_OFF_POSTIND //changed from OP_UND in r3504 /* 0110 0111 0111 */ TABDECL(OP_UND), /* 0110 0111 1000 */ TABDECL(OP_LDRB_M_LSL_IMM_OFF_POSTIND), // OP_LDRB_M_LSL_IMM_OFF_POSTIND //changed from OP_UND in r3504 /* 0110 0111 1001 */ TABDECL(OP_UND), /* 0110 0111 1010 */ TABDECL(OP_LDRB_M_LSR_IMM_OFF_POSTIND), // OP_LDRB_M_LSR_IMM_OFF_POSTIND //changed from OP_UND in r3504 /* 0110 0111 1011 */ TABDECL(OP_UND), /* 0110 0111 1100 */ TABDECL(OP_LDRB_M_ASR_IMM_OFF_POSTIND), // OP_LDRB_M_ASR_IMM_OFF_POSTIND //changed from OP_UND in r3504 /* 0110 0111 1101 */ TABDECL(OP_UND), /* 0110 0111 1110 */ TABDECL(OP_LDRB_M_ROR_IMM_OFF_POSTIND), // OP_LDRB_M_ROR_IMM_OFF_POSTIND //changed from OP_UND in r3504 /* 0110 0111 1111 */ TABDECL(OP_UND), /* 0110 1000 0000 */ TABDECL(OP_STR_P_LSL_IMM_OFF_POSTIND), // OP_STR_P_LSL_IMM_OFF_POSTIND /* 0110 1000 0001 */ TABDECL(OP_UND), /* 0110 1000 0010 */ TABDECL(OP_STR_P_LSR_IMM_OFF_POSTIND), // OP_STR_P_LSR_IMM_OFF_POSTIND /* 0110 1000 0011 */ TABDECL(OP_UND), /* 0110 1000 0100 */ TABDECL(OP_STR_P_ASR_IMM_OFF_POSTIND), // OP_STR_P_ASR_IMM_OFF_POSTIND /* 0110 1000 0101 */ TABDECL(OP_UND), /* 0110 1000 0110 */ TABDECL(OP_STR_P_ROR_IMM_OFF_POSTIND), // OP_STR_P_ROR_IMM_OFF_POSTIND /* 0110 1000 0111 */ TABDECL(OP_UND), /* 0110 1000 1000 */ TABDECL(OP_STR_P_LSL_IMM_OFF_POSTIND), // OP_STR_P_LSL_IMM_OFF_POSTIND /* 0110 1000 1001 */ TABDECL(OP_UND), /* 0110 1000 1010 */ TABDECL(OP_STR_P_LSR_IMM_OFF_POSTIND), // OP_STR_P_LSR_IMM_OFF_POSTIND /* 0110 1000 1011 */ TABDECL(OP_UND), /* 0110 1000 1100 */ TABDECL(OP_STR_P_ASR_IMM_OFF_POSTIND), // OP_STR_P_ASR_IMM_OFF_POSTIND /* 0110 1000 1101 */ TABDECL(OP_UND), /* 0110 1000 1110 */ TABDECL(OP_STR_P_ROR_IMM_OFF_POSTIND), // OP_STR_P_ROR_IMM_OFF_POSTIND /* 0110 1000 1111 */ TABDECL(OP_UND), /* 0110 1001 0000 */ TABDECL(OP_LDR_P_LSL_IMM_OFF_POSTIND), // OP_LDR_P_LSL_IMM_OFF_POSTIND /* 0110 1001 0001 */ TABDECL(OP_UND), /* 0110 1001 0010 */ TABDECL(OP_LDR_P_LSR_IMM_OFF_POSTIND), // OP_LDR_P_LSR_IMM_OFF_POSTIND /* 0110 1001 0011 */ TABDECL(OP_UND), /* 0110 1001 0100 */ TABDECL(OP_LDR_P_ASR_IMM_OFF_POSTIND), // OP_LDR_P_ASR_IMM_OFF_POSTIND /* 0110 1001 0101 */ TABDECL(OP_UND), /* 0110 1001 0110 */ TABDECL(OP_LDR_P_ROR_IMM_OFF_POSTIND), // OP_LDR_P_ROR_IMM_OFF_POSTIND /* 0110 1001 0111 */ TABDECL(OP_UND), /* 0110 1001 1000 */ TABDECL(OP_LDR_P_LSL_IMM_OFF_POSTIND), // OP_LDR_P_LSL_IMM_OFF_POSTIND /* 0110 1001 1001 */ TABDECL(OP_UND), /* 0110 1001 1010 */ TABDECL(OP_LDR_P_LSR_IMM_OFF_POSTIND), // OP_LDR_P_LSR_IMM_OFF_POSTIND /* 0110 1001 1011 */ TABDECL(OP_UND), /* 0110 1001 1100 */ TABDECL(OP_LDR_P_ASR_IMM_OFF_POSTIND), // OP_LDR_P_ASR_IMM_OFF_POSTIND /* 0110 1001 1101 */ TABDECL(OP_UND), /* 0110 1001 1110 */ TABDECL(OP_LDR_P_ROR_IMM_OFF_POSTIND), // OP_LDR_P_ROR_IMM_OFF_POSTIND /* 0110 1001 1111 */ TABDECL(OP_UND), /* 0110 1010 0000 */ TABDECL(OP_STR_P_LSL_IMM_OFF_POSTIND), // OP_STR_P_LSL_IMM_OFF_POSTIND //changed from OP_UND in r3504 /* 0110 1010 0001 */ TABDECL(OP_UND), /* 0110 1010 0010 */ TABDECL(OP_STR_P_LSR_IMM_OFF_POSTIND), // OP_STR_P_LSR_IMM_OFF_POSTIND //changed from OP_UND in r3504 /* 0110 1010 0011 */ TABDECL(OP_UND), /* 0110 1010 0100 */ TABDECL(OP_STR_P_ASR_IMM_OFF_POSTIND), // OP_STR_P_ASR_IMM_OFF_POSTIND //changed from OP_UND in r3504 /* 0110 1010 0101 */ TABDECL(OP_UND), /* 0110 1010 0110 */ TABDECL(OP_STR_P_ROR_IMM_OFF_POSTIND), // OP_STR_P_ROR_IMM_OFF_POSTIND //changed from OP_UND in r3504 /* 0110 1010 0111 */ TABDECL(OP_UND), /* 0110 1010 1000 */ TABDECL(OP_STR_P_LSL_IMM_OFF_POSTIND), // OP_STR_P_LSL_IMM_OFF_POSTIND //changed from OP_UND in r3504 /* 0110 1010 1001 */ TABDECL(OP_UND), /* 0110 1010 1010 */ TABDECL(OP_STR_P_LSR_IMM_OFF_POSTIND), // OP_STR_P_LSR_IMM_OFF_POSTIND //changed from OP_UND in r3504 /* 0110 1010 1011 */ TABDECL(OP_UND), /* 0110 1010 1100 */ TABDECL(OP_STR_P_ASR_IMM_OFF_POSTIND), // OP_STR_P_ASR_IMM_OFF_POSTIND //changed from OP_UND in r3504 /* 0110 1010 1101 */ TABDECL(OP_UND), /* 0110 1010 1110 */ TABDECL(OP_STR_P_ROR_IMM_OFF_POSTIND), // OP_STR_P_ROR_IMM_OFF_POSTIND //changed from OP_UND in r3504 /* 0110 1010 1111 */ TABDECL(OP_UND), /* 0110 1011 0000 */ TABDECL(OP_LDR_P_LSL_IMM_OFF_POSTIND), // OP_LDR_P_LSL_IMM_OFF_POSTIND //changed from OP_UND in r3504 to OP_STR_P_LSL_IMM_OFF_POSTIND ; changed to OP_LDR_P_LSL_IMM_OFF_POSTIND in r3510 /* 0110 1011 0001 */ TABDECL(OP_UND), /* 0110 1011 0010 */ TABDECL(OP_LDR_P_LSR_IMM_OFF_POSTIND), // OP_LDR_P_LSL_IMM_OFF_POSTIND //changed from OP_UND in r3504 to OP_STR_P_LSR_IMM_OFF_POSTIND ; changed to OP_LDR_P_LSL_IMM_OFF_POSTIND in r3510 /* 0110 1011 0011 */ TABDECL(OP_UND), /* 0110 1011 0100 */ TABDECL(OP_LDR_P_ASR_IMM_OFF_POSTIND), // OP_LDR_P_LSL_IMM_OFF_POSTIND //changed from OP_UND in r3504 to OP_STR_P_ASR_IMM_OFF_POSTIND ; changed to OP_LDR_P_LSL_IMM_OFF_POSTIND in r3510 /* 0110 1011 0101 */ TABDECL(OP_UND), /* 0110 1011 0110 */ TABDECL(OP_LDR_P_ROR_IMM_OFF_POSTIND), // OP_LDR_P_LSL_IMM_OFF_POSTIND //changed from OP_UND in r3504 to OP_STR_P_ROR_IMM_OFF_POSTIND ; changed to OP_LDR_P_LSL_IMM_OFF_POSTIND in r3510 /* 0110 1011 0111 */ TABDECL(OP_UND), /* 0110 1011 1000 */ TABDECL(OP_LDR_P_LSL_IMM_OFF_POSTIND), // OP_LDR_P_LSL_IMM_OFF_POSTIND //changed from OP_UND in r3504 to OP_STR_P_LSL_IMM_OFF_POSTIND ; changed to OP_LDR_P_LSL_IMM_OFF_POSTIND in r3510 /* 0110 1011 1001 */ TABDECL(OP_UND), /* 0110 1011 1010 */ TABDECL(OP_LDR_P_LSR_IMM_OFF_POSTIND), // OP_LDR_P_LSL_IMM_OFF_POSTIND //changed from OP_UND in r3504 to OP_STR_P_LSR_IMM_OFF_POSTIND ; changed to OP_LDR_P_LSL_IMM_OFF_POSTIND in r3510 /* 0110 1011 1011 */ TABDECL(OP_UND), /* 0110 1011 1100 */ TABDECL(OP_LDR_P_ASR_IMM_OFF_POSTIND), // OP_LDR_P_LSL_IMM_OFF_POSTIND //changed from OP_UND in r3504 to OP_STR_P_ASR_IMM_OFF_POSTIND ; changed to OP_LDR_P_LSL_IMM_OFF_POSTIND in r3510 /* 0110 1011 1101 */ TABDECL(OP_UND), /* 0110 1011 1110 */ TABDECL(OP_LDR_P_ROR_IMM_OFF_POSTIND), // OP_LDR_P_LSL_IMM_OFF_POSTIND //changed from OP_UND in r3504 to OP_STR_P_ROR_IMM_OFF_POSTIND ; changed to OP_LDR_P_LSL_IMM_OFF_POSTIND in r3510 /* 0110 1011 1111 */ TABDECL(OP_UND), /* 0110 1100 0000 */ TABDECL(OP_STRB_P_LSL_IMM_OFF_POSTIND), // OP_STRB_P_LSL_IMM_OFF_POSTIND /* 0110 1100 0001 */ TABDECL(OP_UND), /* 0110 1100 0010 */ TABDECL(OP_STRB_P_LSR_IMM_OFF_POSTIND), // OP_STRB_P_LSR_IMM_OFF_POSTIND /* 0110 1100 0011 */ TABDECL(OP_UND), /* 0110 1100 0100 */ TABDECL(OP_STRB_P_ASR_IMM_OFF_POSTIND), // OP_STRB_P_ASR_IMM_OFF_POSTIND /* 0110 1100 0101 */ TABDECL(OP_UND), /* 0110 1100 0110 */ TABDECL(OP_STRB_P_ROR_IMM_OFF_POSTIND), // OP_STRB_P_ROR_IMM_OFF_POSTIND /* 0110 1100 0111 */ TABDECL(OP_UND), /* 0110 1100 1000 */ TABDECL(OP_STRB_P_LSL_IMM_OFF_POSTIND), // OP_STRB_P_LSL_IMM_OFF_POSTIND /* 0110 1100 1001 */ TABDECL(OP_UND), /* 0110 1100 1010 */ TABDECL(OP_STRB_P_LSR_IMM_OFF_POSTIND), // OP_STRB_P_LSR_IMM_OFF_POSTIND /* 0110 1100 1011 */ TABDECL(OP_UND), /* 0110 1100 1100 */ TABDECL(OP_STRB_P_ASR_IMM_OFF_POSTIND), // OP_STRB_P_ASR_IMM_OFF_POSTIND /* 0110 1100 1101 */ TABDECL(OP_UND), /* 0110 1100 1110 */ TABDECL(OP_STRB_P_ROR_IMM_OFF_POSTIND), // OP_STRB_P_ROR_IMM_OFF_POSTIND /* 0110 1100 1111 */ TABDECL(OP_UND), /* 0110 1101 0000 */ TABDECL(OP_LDRB_P_LSL_IMM_OFF_POSTIND), // OP_LDRB_P_LSL_IMM_OFF_POSTIND /* 0110 1101 0001 */ TABDECL(OP_UND), /* 0110 1101 0010 */ TABDECL(OP_LDRB_P_LSR_IMM_OFF_POSTIND), // OP_LDRB_P_LSR_IMM_OFF_POSTIND /* 0110 1101 0011 */ TABDECL(OP_UND), /* 0110 1101 0100 */ TABDECL(OP_LDRB_P_ASR_IMM_OFF_POSTIND), // OP_LDRB_P_ASR_IMM_OFF_POSTIND /* 0110 1101 0101 */ TABDECL(OP_UND), /* 0110 1101 0110 */ TABDECL(OP_LDRB_P_ROR_IMM_OFF_POSTIND), // OP_LDRB_P_ROR_IMM_OFF_POSTIND /* 0110 1101 0111 */ TABDECL(OP_UND), /* 0110 1101 1000 */ TABDECL(OP_LDRB_P_LSL_IMM_OFF_POSTIND), // OP_LDRB_P_LSL_IMM_OFF_POSTIND /* 0110 1101 1001 */ TABDECL(OP_UND), /* 0110 1101 1010 */ TABDECL(OP_LDRB_P_LSR_IMM_OFF_POSTIND), // OP_LDRB_P_LSR_IMM_OFF_POSTIND /* 0110 1101 1011 */ TABDECL(OP_UND), /* 0110 1101 1100 */ TABDECL(OP_LDRB_P_ASR_IMM_OFF_POSTIND), // OP_LDRB_P_ASR_IMM_OFF_POSTIND /* 0110 1101 1101 */ TABDECL(OP_UND), /* 0110 1101 1110 */ TABDECL(OP_LDRB_P_ROR_IMM_OFF_POSTIND), // OP_LDRB_P_ROR_IMM_OFF_POSTIND /* 0110 1101 1111 */ TABDECL(OP_UND), /* 0110 1110 0000 */ TABDECL(OP_STRB_P_LSL_IMM_OFF_POSTIND), // OP_STRB_P_LSL_IMM_OFF_POSTIND //changed from OP_UND in r3504 /* 0110 1110 0001 */ TABDECL(OP_UND), /* 0110 1110 0010 */ TABDECL(OP_STRB_P_LSR_IMM_OFF_POSTIND), // OP_STRB_P_LSR_IMM_OFF_POSTIND //changed from OP_UND in r3504 /* 0110 1110 0011 */ TABDECL(OP_UND), /* 0110 1110 0100 */ TABDECL(OP_STRB_P_ASR_IMM_OFF_POSTIND), // OP_STRB_P_ASR_IMM_OFF_POSTIND //changed from OP_UND in r3504 /* 0110 1110 0101 */ TABDECL(OP_UND), /* 0110 1110 0110 */ TABDECL(OP_STRB_P_ROR_IMM_OFF_POSTIND), // OP_STRB_P_ROR_IMM_OFF_POSTIND //changed from OP_UND in r3504 /* 0110 1110 0111 */ TABDECL(OP_UND), /* 0110 1110 1000 */ TABDECL(OP_STRB_P_LSL_IMM_OFF_POSTIND), // OP_STRB_P_LSL_IMM_OFF_POSTIND //changed from OP_UND in r3504 /* 0110 1110 1001 */ TABDECL(OP_UND), /* 0110 1110 1010 */ TABDECL(OP_STRB_P_LSR_IMM_OFF_POSTIND), // OP_STRB_P_LSR_IMM_OFF_POSTIND //changed from OP_UND in r3504 /* 0110 1110 1011 */ TABDECL(OP_UND), /* 0110 1110 1100 */ TABDECL(OP_STRB_P_ASR_IMM_OFF_POSTIND), // OP_STRB_P_ASR_IMM_OFF_POSTIND //changed from OP_UND in r3504 /* 0110 1110 1101 */ TABDECL(OP_UND), /* 0110 1110 1110 */ TABDECL(OP_STRB_P_ROR_IMM_OFF_POSTIND), // OP_STRB_P_ROR_IMM_OFF_POSTIND //changed from OP_UND in r3504 /* 0110 1110 1111 */ TABDECL(OP_UND), /* 0110 1111 0000 */ TABDECL(OP_LDRB_P_LSL_IMM_OFF_POSTIND), // OP_LDRB_P_LSL_IMM_OFF_POSTIND //changed from OP_UND in r3504 /* 0110 1111 0001 */ TABDECL(OP_UND), /* 0110 1111 0010 */ TABDECL(OP_LDRB_P_LSR_IMM_OFF_POSTIND), // OP_LDRB_P_LSR_IMM_OFF_POSTIND //changed from OP_UND in r3504 /* 0110 1111 0011 */ TABDECL(OP_UND), /* 0110 1111 0100 */ TABDECL(OP_LDRB_P_ASR_IMM_OFF_POSTIND), // OP_LDRB_P_ASR_IMM_OFF_POSTIND //changed from OP_UND in r3504 /* 0110 1111 0101 */ TABDECL(OP_UND), /* 0110 1111 0110 */ TABDECL(OP_LDRB_P_ROR_IMM_OFF_POSTIND), // OP_LDRB_P_ROR_IMM_OFF_POSTIND //changed from OP_UND in r3504 /* 0110 1111 0111 */ TABDECL(OP_UND), /* 0110 1111 1000 */ TABDECL(OP_LDRB_P_LSL_IMM_OFF_POSTIND), // OP_LDRB_P_LSL_IMM_OFF_POSTIND //changed from OP_UND in r3504 /* 0110 1111 1001 */ TABDECL(OP_UND), /* 0110 1111 1010 */ TABDECL(OP_LDRB_P_LSR_IMM_OFF_POSTIND), // OP_LDRB_P_LSR_IMM_OFF_POSTIND //changed from OP_UND in r3504 /* 0110 1111 1011 */ TABDECL(OP_UND), /* 0110 1111 1100 */ TABDECL(OP_LDRB_P_ASR_IMM_OFF_POSTIND), // OP_LDRB_P_ASR_IMM_OFF_POSTIND //changed from OP_UND in r3504 /* 0110 1111 1101 */ TABDECL(OP_UND), /* 0110 1111 1110 */ TABDECL(OP_LDRB_P_ROR_IMM_OFF_POSTIND), // OP_LDRB_P_ROR_IMM_OFF_POSTIND //changed from OP_UND in r3504 /* 0110 1111 1111 */ TABDECL(OP_UND), /* 0111 0000 0000 */ TABDECL(OP_STR_M_LSL_IMM_OFF), // OP_STR_M_LSL_IMM_OFF /* 0111 0000 0001 */ TABDECL(OP_UND), /* 0111 0000 0010 */ TABDECL(OP_STR_M_LSR_IMM_OFF), // OP_STR_M_LSR_IMM_OFF /* 0111 0000 0011 */ TABDECL(OP_UND), /* 0111 0000 0100 */ TABDECL(OP_STR_M_ASR_IMM_OFF), // OP_STR_M_ASR_IMM_OFF /* 0111 0000 0101 */ TABDECL(OP_UND), /* 0111 0000 0110 */ TABDECL(OP_STR_M_ROR_IMM_OFF), // OP_STR_M_ROR_IMM_OFF /* 0111 0000 0111 */ TABDECL(OP_UND), /* 0111 0000 1000 */ TABDECL(OP_STR_M_LSL_IMM_OFF), // OP_STR_M_LSL_IMM_OFF /* 0111 0000 1001 */ TABDECL(OP_UND), /* 0111 0000 1010 */ TABDECL(OP_STR_M_LSR_IMM_OFF), // OP_STR_M_LSR_IMM_OFF /* 0111 0000 1011 */ TABDECL(OP_UND), /* 0111 0000 1100 */ TABDECL(OP_STR_M_ASR_IMM_OFF), // OP_STR_M_ASR_IMM_OFF /* 0111 0000 1101 */ TABDECL(OP_UND), /* 0111 0000 1110 */ TABDECL(OP_STR_M_ROR_IMM_OFF), // OP_STR_M_ROR_IMM_OFF /* 0111 0000 1111 */ TABDECL(OP_UND), /* 0111 0001 0000 */ TABDECL(OP_LDR_M_LSL_IMM_OFF), // OP_LDR_M_LSL_IMM_OFF /* 0111 0001 0001 */ TABDECL(OP_UND), /* 0111 0001 0010 */ TABDECL(OP_LDR_M_LSR_IMM_OFF), // OP_LDR_M_LSR_IMM_OFF /* 0111 0001 0011 */ TABDECL(OP_UND), /* 0111 0001 0100 */ TABDECL(OP_LDR_M_ASR_IMM_OFF), // OP_LDR_M_ASR_IMM_OFF /* 0111 0001 0101 */ TABDECL(OP_UND), /* 0111 0001 0110 */ TABDECL(OP_LDR_M_ROR_IMM_OFF), // OP_LDR_M_ROR_IMM_OFF /* 0111 0001 0111 */ TABDECL(OP_UND), /* 0111 0001 1000 */ TABDECL(OP_LDR_M_LSL_IMM_OFF), // OP_LDR_M_LSL_IMM_OFF /* 0111 0001 1001 */ TABDECL(OP_UND), /* 0111 0001 1010 */ TABDECL(OP_LDR_M_LSR_IMM_OFF), // OP_LDR_M_LSR_IMM_OFF /* 0111 0001 1011 */ TABDECL(OP_UND), /* 0111 0001 1100 */ TABDECL(OP_LDR_M_ASR_IMM_OFF), // OP_LDR_M_ASR_IMM_OFF /* 0111 0001 1101 */ TABDECL(OP_UND), /* 0111 0001 1110 */ TABDECL(OP_LDR_M_ROR_IMM_OFF), // OP_LDR_M_ROR_IMM_OFF /* 0111 0001 1111 */ TABDECL(OP_UND), /* 0111 0010 0000 */ TABDECL(OP_STR_M_LSL_IMM_OFF_PREIND), // OP_STR_M_LSL_IMM_OFF_PREIND /* 0111 0010 0001 */ TABDECL(OP_UND), /* 0111 0010 0010 */ TABDECL(OP_STR_M_LSR_IMM_OFF_PREIND), // OP_STR_M_LSR_IMM_OFF_PREIND /* 0111 0010 0011 */ TABDECL(OP_UND), /* 0111 0010 0100 */ TABDECL(OP_STR_M_ASR_IMM_OFF_PREIND), // OP_STR_M_ASR_IMM_OFF_PREIND /* 0111 0010 0101 */ TABDECL(OP_UND), /* 0111 0010 0110 */ TABDECL(OP_STR_M_ROR_IMM_OFF_PREIND), // OP_STR_M_ROR_IMM_OFF_PREIND /* 0111 0010 0111 */ TABDECL(OP_UND), /* 0111 0010 1000 */ TABDECL(OP_STR_M_LSL_IMM_OFF_PREIND), // OP_STR_M_LSL_IMM_OFF_PREIND /* 0111 0010 1001 */ TABDECL(OP_UND), /* 0111 0010 1010 */ TABDECL(OP_STR_M_LSR_IMM_OFF_PREIND), // OP_STR_M_LSR_IMM_OFF_PREIND /* 0111 0010 1011 */ TABDECL(OP_UND), /* 0111 0010 1100 */ TABDECL(OP_STR_M_ASR_IMM_OFF_PREIND), // OP_STR_M_ASR_IMM_OFF_PREIND /* 0111 0010 1101 */ TABDECL(OP_UND), /* 0111 0010 1110 */ TABDECL(OP_STR_M_ROR_IMM_OFF_PREIND), // OP_STR_M_ROR_IMM_OFF_PREIND /* 0111 0010 1111 */ TABDECL(OP_UND), /* 0111 0011 0000 */ TABDECL(OP_LDR_M_LSL_IMM_OFF_PREIND), // OP_LDR_M_LSL_IMM_OFF_PREIND /* 0111 0011 0001 */ TABDECL(OP_UND), /* 0111 0011 0010 */ TABDECL(OP_LDR_M_LSR_IMM_OFF_PREIND), // OP_LDR_M_LSR_IMM_OFF_PREIND /* 0111 0011 0011 */ TABDECL(OP_UND), /* 0111 0011 0100 */ TABDECL(OP_LDR_M_ASR_IMM_OFF_PREIND), // OP_LDR_M_ASR_IMM_OFF_PREIND /* 0111 0011 0101 */ TABDECL(OP_UND), /* 0111 0011 0110 */ TABDECL(OP_LDR_M_ROR_IMM_OFF_PREIND), // OP_LDR_M_ROR_IMM_OFF_PREIND /* 0111 0011 0111 */ TABDECL(OP_UND), /* 0111 0011 1000 */ TABDECL(OP_LDR_M_LSL_IMM_OFF_PREIND), // OP_LDR_M_LSL_IMM_OFF_PREIND /* 0111 0011 1001 */ TABDECL(OP_UND), /* 0111 0011 1010 */ TABDECL(OP_LDR_M_LSR_IMM_OFF_PREIND), // OP_LDR_M_LSR_IMM_OFF_PREIND /* 0111 0011 1011 */ TABDECL(OP_UND), /* 0111 0011 1100 */ TABDECL(OP_LDR_M_ASR_IMM_OFF_PREIND), // OP_LDR_M_ASR_IMM_OFF_PREIND /* 0111 0011 1101 */ TABDECL(OP_UND), /* 0111 0011 1110 */ TABDECL(OP_LDR_M_ROR_IMM_OFF_PREIND), // OP_LDR_M_ROR_IMM_OFF_PREIND /* 0111 0011 1111 */ TABDECL(OP_UND), /* 0111 0100 0000 */ TABDECL(OP_STRB_M_LSL_IMM_OFF), // OP_STRB_M_LSL_IMM_OFF /* 0111 0100 0001 */ TABDECL(OP_UND), /* 0111 0100 0010 */ TABDECL(OP_STRB_M_LSR_IMM_OFF), // OP_STRB_M_LSR_IMM_OFF /* 0111 0100 0011 */ TABDECL(OP_UND), /* 0111 0100 0100 */ TABDECL(OP_STRB_M_ASR_IMM_OFF), // OP_STRB_M_ASR_IMM_OFF /* 0111 0100 0101 */ TABDECL(OP_UND), /* 0111 0100 0110 */ TABDECL(OP_STRB_M_ROR_IMM_OFF), // OP_STRB_M_ROR_IMM_OFF /* 0111 0100 0111 */ TABDECL(OP_UND), /* 0111 0100 1000 */ TABDECL(OP_STRB_M_LSL_IMM_OFF), // OP_STRB_M_LSL_IMM_OFF /* 0111 0100 1001 */ TABDECL(OP_UND), /* 0111 0100 1010 */ TABDECL(OP_STRB_M_LSR_IMM_OFF), // OP_STRB_M_LSR_IMM_OFF /* 0111 0100 1011 */ TABDECL(OP_UND), /* 0111 0100 1100 */ TABDECL(OP_STRB_M_ASR_IMM_OFF), // OP_STRB_M_ASR_IMM_OFF /* 0111 0100 1101 */ TABDECL(OP_UND), /* 0111 0100 1110 */ TABDECL(OP_STRB_M_ROR_IMM_OFF), // OP_STRB_M_ROR_IMM_OFF /* 0111 0100 1111 */ TABDECL(OP_UND), /* 0111 0101 0000 */ TABDECL(OP_LDRB_M_LSL_IMM_OFF), // OP_LDRB_M_LSL_IMM_OFF /* 0111 0101 0001 */ TABDECL(OP_UND), /* 0111 0101 0010 */ TABDECL(OP_LDRB_M_LSR_IMM_OFF), // OP_LDRB_M_LSR_IMM_OFF /* 0111 0101 0011 */ TABDECL(OP_UND), /* 0111 0101 0100 */ TABDECL(OP_LDRB_M_ASR_IMM_OFF), // OP_LDRB_M_ASR_IMM_OFF /* 0111 0101 0101 */ TABDECL(OP_UND), /* 0111 0101 0110 */ TABDECL(OP_LDRB_M_ROR_IMM_OFF), // OP_LDRB_M_ROR_IMM_OFF /* 0111 0101 0111 */ TABDECL(OP_UND), /* 0111 0101 1000 */ TABDECL(OP_LDRB_M_LSL_IMM_OFF), // OP_LDRB_M_LSL_IMM_OFF /* 0111 0101 1001 */ TABDECL(OP_UND), /* 0111 0101 1010 */ TABDECL(OP_LDRB_M_LSR_IMM_OFF), // OP_LDRB_M_LSR_IMM_OFF /* 0111 0101 1011 */ TABDECL(OP_UND), /* 0111 0101 1100 */ TABDECL(OP_LDRB_M_ASR_IMM_OFF), // OP_LDRB_M_ASR_IMM_OFF /* 0111 0101 1101 */ TABDECL(OP_UND), /* 0111 0101 1110 */ TABDECL(OP_LDRB_M_ROR_IMM_OFF), // OP_LDRB_M_ROR_IMM_OFF /* 0111 0101 1111 */ TABDECL(OP_UND), /* 0111 0110 0000 */ TABDECL(OP_STRB_M_LSL_IMM_OFF_PREIND), // OP_STRB_M_LSL_IMM_OFF_PREIND /* 0111 0110 0001 */ TABDECL(OP_UND), /* 0111 0110 0010 */ TABDECL(OP_STRB_M_LSR_IMM_OFF_PREIND), // OP_STRB_M_LSR_IMM_OFF_PREIND /* 0111 0110 0011 */ TABDECL(OP_UND), /* 0111 0110 0100 */ TABDECL(OP_STRB_M_ASR_IMM_OFF_PREIND), // OP_STRB_M_ASR_IMM_OFF_PREIND /* 0111 0110 0101 */ TABDECL(OP_UND), /* 0111 0110 0110 */ TABDECL(OP_STRB_M_ROR_IMM_OFF_PREIND), // OP_STRB_M_ROR_IMM_OFF_PREIND /* 0111 0110 0111 */ TABDECL(OP_UND), /* 0111 0110 1000 */ TABDECL(OP_STRB_M_LSL_IMM_OFF_PREIND), // OP_STRB_M_LSL_IMM_OFF_PREIND /* 0111 0110 1001 */ TABDECL(OP_UND), /* 0111 0110 1010 */ TABDECL(OP_STRB_M_LSR_IMM_OFF_PREIND), // OP_STRB_M_LSR_IMM_OFF_PREIND /* 0111 0110 1011 */ TABDECL(OP_UND), /* 0111 0110 1100 */ TABDECL(OP_STRB_M_ASR_IMM_OFF_PREIND), // OP_STRB_M_ASR_IMM_OFF_PREIND /* 0111 0110 1101 */ TABDECL(OP_UND), /* 0111 0110 1110 */ TABDECL(OP_STRB_M_ROR_IMM_OFF_PREIND), // OP_STRB_M_ROR_IMM_OFF_PREIND /* 0111 0110 1111 */ TABDECL(OP_UND), /* 0111 0111 0000 */ TABDECL(OP_LDRB_M_LSL_IMM_OFF_PREIND), // OP_LDRB_M_LSL_IMM_OFF_PREIND /* 0111 0111 0001 */ TABDECL(OP_UND), /* 0111 0111 0010 */ TABDECL(OP_LDRB_M_LSR_IMM_OFF_PREIND), // OP_LDRB_M_LSR_IMM_OFF_PREIND /* 0111 0111 0011 */ TABDECL(OP_UND), /* 0111 0111 0100 */ TABDECL(OP_LDRB_M_ASR_IMM_OFF_PREIND), // OP_LDRB_M_ASR_IMM_OFF_PREIND /* 0111 0111 0101 */ TABDECL(OP_UND), /* 0111 0111 0110 */ TABDECL(OP_LDRB_M_ROR_IMM_OFF_PREIND), // OP_LDRB_M_ROR_IMM_OFF_PREIND /* 0111 0111 0111 */ TABDECL(OP_UND), /* 0111 0111 1000 */ TABDECL(OP_LDRB_M_LSL_IMM_OFF_PREIND), // OP_LDRB_M_LSL_IMM_OFF_PREIND /* 0111 0111 1001 */ TABDECL(OP_UND), /* 0111 0111 1010 */ TABDECL(OP_LDRB_M_LSR_IMM_OFF_PREIND), // OP_LDRB_M_LSR_IMM_OFF_PREIND /* 0111 0111 1011 */ TABDECL(OP_UND), /* 0111 0111 1100 */ TABDECL(OP_LDRB_M_ASR_IMM_OFF_PREIND), // OP_LDRB_M_ASR_IMM_OFF_PREIND /* 0111 0111 1101 */ TABDECL(OP_UND), /* 0111 0111 1110 */ TABDECL(OP_LDRB_M_ROR_IMM_OFF_PREIND), // OP_LDRB_M_ROR_IMM_OFF_PREIND /* 0111 0111 1111 */ TABDECL(OP_UND), /* 0111 1000 0000 */ TABDECL(OP_STR_P_LSL_IMM_OFF), // OP_STR_P_LSL_IMM_OFF /* 0111 1000 0001 */ TABDECL(OP_UND), /* 0111 1000 0010 */ TABDECL(OP_STR_P_LSR_IMM_OFF), // OP_STR_P_LSR_IMM_OFF /* 0111 1000 0011 */ TABDECL(OP_UND), /* 0111 1000 0100 */ TABDECL(OP_STR_P_ASR_IMM_OFF), // OP_STR_P_ASR_IMM_OFF /* 0111 1000 0101 */ TABDECL(OP_UND), /* 0111 1000 0110 */ TABDECL(OP_STR_P_ROR_IMM_OFF), // OP_STR_P_ROR_IMM_OFF /* 0111 1000 0111 */ TABDECL(OP_UND), /* 0111 1000 1000 */ TABDECL(OP_STR_P_LSL_IMM_OFF), // OP_STR_P_LSL_IMM_OFF /* 0111 1000 1001 */ TABDECL(OP_UND), /* 0111 1000 1010 */ TABDECL(OP_STR_P_LSR_IMM_OFF), // OP_STR_P_LSR_IMM_OFF /* 0111 1000 1011 */ TABDECL(OP_UND), /* 0111 1000 1100 */ TABDECL(OP_STR_P_ASR_IMM_OFF), // OP_STR_P_ASR_IMM_OFF /* 0111 1000 1101 */ TABDECL(OP_UND), /* 0111 1000 1110 */ TABDECL(OP_STR_P_ROR_IMM_OFF), // OP_STR_P_ROR_IMM_OFF /* 0111 1000 1111 */ TABDECL(OP_UND), /* 0111 1001 0000 */ TABDECL(OP_LDR_P_LSL_IMM_OFF), // OP_LDR_P_LSL_IMM_OFF /* 0111 1001 0001 */ TABDECL(OP_UND), /* 0111 1001 0010 */ TABDECL(OP_LDR_P_LSR_IMM_OFF), // OP_LDR_P_LSR_IMM_OFF /* 0111 1001 0011 */ TABDECL(OP_UND), /* 0111 1001 0100 */ TABDECL(OP_LDR_P_ASR_IMM_OFF), // OP_LDR_P_ASR_IMM_OFF /* 0111 1001 0101 */ TABDECL(OP_UND), /* 0111 1001 0110 */ TABDECL(OP_LDR_P_ROR_IMM_OFF), // OP_LDR_P_ROR_IMM_OFF /* 0111 1001 0111 */ TABDECL(OP_UND), /* 0111 1001 1000 */ TABDECL(OP_LDR_P_LSL_IMM_OFF), // OP_LDR_P_LSL_IMM_OFF /* 0111 1001 1001 */ TABDECL(OP_UND), /* 0111 1001 1010 */ TABDECL(OP_LDR_P_LSR_IMM_OFF), // OP_LDR_P_LSR_IMM_OFF /* 0111 1001 1011 */ TABDECL(OP_UND), /* 0111 1001 1100 */ TABDECL(OP_LDR_P_ASR_IMM_OFF), // OP_LDR_P_ASR_IMM_OFF /* 0111 1001 1101 */ TABDECL(OP_UND), /* 0111 1001 1110 */ TABDECL(OP_LDR_P_ROR_IMM_OFF), // OP_LDR_P_ROR_IMM_OFF /* 0111 1001 1111 */ TABDECL(OP_UND), /* 0111 1010 0000 */ TABDECL(OP_STR_P_LSL_IMM_OFF_PREIND), // OP_STR_P_LSL_IMM_OFF_PREIND /* 0111 1010 0001 */ TABDECL(OP_UND), /* 0111 1010 0010 */ TABDECL(OP_STR_P_LSR_IMM_OFF_PREIND), // OP_STR_P_LSR_IMM_OFF_PREIND /* 0111 1010 0011 */ TABDECL(OP_UND), /* 0111 1010 0100 */ TABDECL(OP_STR_P_ASR_IMM_OFF_PREIND), // OP_STR_P_ASR_IMM_OFF_PREIND /* 0111 1010 0101 */ TABDECL(OP_UND), /* 0111 1010 0110 */ TABDECL(OP_STR_P_ROR_IMM_OFF_PREIND), // OP_STR_P_ROR_IMM_OFF_PREIND /* 0111 1010 0111 */ TABDECL(OP_UND), /* 0111 1010 1000 */ TABDECL(OP_STR_P_LSL_IMM_OFF_PREIND), // OP_STR_P_LSL_IMM_OFF_PREIND /* 0111 1010 1001 */ TABDECL(OP_UND), /* 0111 1010 1010 */ TABDECL(OP_STR_P_LSR_IMM_OFF_PREIND), // OP_STR_P_LSR_IMM_OFF_PREIND /* 0111 1010 1011 */ TABDECL(OP_UND), /* 0111 1010 1100 */ TABDECL(OP_STR_P_ASR_IMM_OFF_PREIND), // OP_STR_P_ASR_IMM_OFF_PREIND /* 0111 1010 1101 */ TABDECL(OP_UND), /* 0111 1010 1110 */ TABDECL(OP_STR_P_ROR_IMM_OFF_PREIND), // OP_STR_P_ROR_IMM_OFF_PREIND /* 0111 1010 1111 */ TABDECL(OP_UND), /* 0111 1011 0000 */ TABDECL(OP_LDR_P_LSL_IMM_OFF_PREIND), // OP_LDR_P_LSL_IMM_OFF_PREIND /* 0111 1011 0001 */ TABDECL(OP_UND), /* 0111 1011 0010 */ TABDECL(OP_LDR_P_LSR_IMM_OFF_PREIND), // OP_LDR_P_LSR_IMM_OFF_PREIND /* 0111 1011 0011 */ TABDECL(OP_UND), /* 0111 1011 0100 */ TABDECL(OP_LDR_P_ASR_IMM_OFF_PREIND), // OP_LDR_P_ASR_IMM_OFF_PREIND /* 0111 1011 0101 */ TABDECL(OP_UND), /* 0111 1011 0110 */ TABDECL(OP_LDR_P_ROR_IMM_OFF_PREIND), // OP_LDR_P_ROR_IMM_OFF_PREIND /* 0111 1011 0111 */ TABDECL(OP_UND), /* 0111 1011 1000 */ TABDECL(OP_LDR_P_LSL_IMM_OFF_PREIND), // OP_LDR_P_LSL_IMM_OFF_PREIND /* 0111 1011 1001 */ TABDECL(OP_UND), /* 0111 1011 1010 */ TABDECL(OP_LDR_P_LSR_IMM_OFF_PREIND), // OP_LDR_P_LSR_IMM_OFF_PREIND /* 0111 1011 1011 */ TABDECL(OP_UND), /* 0111 1011 1100 */ TABDECL(OP_LDR_P_ASR_IMM_OFF_PREIND), // OP_LDR_P_ASR_IMM_OFF_PREIND /* 0111 1011 1101 */ TABDECL(OP_UND), /* 0111 1011 1110 */ TABDECL(OP_LDR_P_ROR_IMM_OFF_PREIND), // OP_LDR_P_ROR_IMM_OFF_PREIND /* 0111 1011 1111 */ TABDECL(OP_UND), /* 0111 1100 0000 */ TABDECL(OP_STRB_P_LSL_IMM_OFF), // OP_STRB_P_LSL_IMM_OFF /* 0111 1100 0001 */ TABDECL(OP_UND), /* 0111 1100 0010 */ TABDECL(OP_STRB_P_LSR_IMM_OFF), // OP_STRB_P_LSR_IMM_OFF /* 0111 1100 0011 */ TABDECL(OP_UND), /* 0111 1100 0100 */ TABDECL(OP_STRB_P_ASR_IMM_OFF), // OP_STRB_P_ASR_IMM_OFF /* 0111 1100 0101 */ TABDECL(OP_UND), /* 0111 1100 0110 */ TABDECL(OP_STRB_P_ROR_IMM_OFF), // OP_STRB_P_ROR_IMM_OFF /* 0111 1100 0111 */ TABDECL(OP_UND), /* 0111 1100 1000 */ TABDECL(OP_STRB_P_LSL_IMM_OFF), // OP_STRB_P_LSL_IMM_OFF /* 0111 1100 1001 */ TABDECL(OP_UND), /* 0111 1100 1010 */ TABDECL(OP_STRB_P_LSR_IMM_OFF), // OP_STRB_P_LSR_IMM_OFF /* 0111 1100 1011 */ TABDECL(OP_UND), /* 0111 1100 1100 */ TABDECL(OP_STRB_P_ASR_IMM_OFF), // OP_STRB_P_ASR_IMM_OFF /* 0111 1100 1101 */ TABDECL(OP_UND), /* 0111 1100 1110 */ TABDECL(OP_STRB_P_ROR_IMM_OFF), // OP_STRB_P_ROR_IMM_OFF /* 0111 1100 1111 */ TABDECL(OP_UND), /* 0111 1101 0000 */ TABDECL(OP_LDRB_P_LSL_IMM_OFF), // OP_LDRB_P_LSL_IMM_OFF /* 0111 1101 0001 */ TABDECL(OP_UND), /* 0111 1101 0010 */ TABDECL(OP_LDRB_P_LSR_IMM_OFF), // OP_LDRB_P_LSR_IMM_OFF /* 0111 1101 0011 */ TABDECL(OP_UND), /* 0111 1101 0100 */ TABDECL(OP_LDRB_P_ASR_IMM_OFF), // OP_LDRB_P_ASR_IMM_OFF /* 0111 1101 0101 */ TABDECL(OP_UND), /* 0111 1101 0110 */ TABDECL(OP_LDRB_P_ROR_IMM_OFF), // OP_LDRB_P_ROR_IMM_OFF /* 0111 1101 0111 */ TABDECL(OP_UND), /* 0111 1101 1000 */ TABDECL(OP_LDRB_P_LSL_IMM_OFF), // OP_LDRB_P_LSL_IMM_OFF /* 0111 1101 1001 */ TABDECL(OP_UND), /* 0111 1101 1010 */ TABDECL(OP_LDRB_P_LSR_IMM_OFF), // OP_LDRB_P_LSR_IMM_OFF /* 0111 1101 1011 */ TABDECL(OP_UND), /* 0111 1101 1100 */ TABDECL(OP_LDRB_P_ASR_IMM_OFF), // OP_LDRB_P_ASR_IMM_OFF /* 0111 1101 1101 */ TABDECL(OP_UND), /* 0111 1101 1110 */ TABDECL(OP_LDRB_P_ROR_IMM_OFF), // OP_LDRB_P_ROR_IMM_OFF /* 0111 1101 1111 */ TABDECL(OP_UND), /* 0111 1110 0000 */ TABDECL(OP_STRB_P_LSL_IMM_OFF_PREIND), // OP_STRB_P_LSL_IMM_OFF_PREIND /* 0111 1110 0001 */ TABDECL(OP_UND), /* 0111 1110 0010 */ TABDECL(OP_STRB_P_LSR_IMM_OFF_PREIND), // OP_STRB_P_LSR_IMM_OFF_PREIND /* 0111 1110 0011 */ TABDECL(OP_UND), /* 0111 1110 0100 */ TABDECL(OP_STRB_P_ASR_IMM_OFF_PREIND), // OP_STRB_P_ASR_IMM_OFF_PREIND /* 0111 1110 0101 */ TABDECL(OP_UND), /* 0111 1110 0110 */ TABDECL(OP_STRB_P_ROR_IMM_OFF_PREIND), // OP_STRB_P_ROR_IMM_OFF_PREIND /* 0111 1110 0111 */ TABDECL(OP_UND), /* 0111 1110 1000 */ TABDECL(OP_STRB_P_LSL_IMM_OFF_PREIND), // OP_STRB_P_LSL_IMM_OFF_PREIND /* 0111 1110 1001 */ TABDECL(OP_UND), /* 0111 1110 1010 */ TABDECL(OP_STRB_P_LSR_IMM_OFF_PREIND), // OP_STRB_P_LSR_IMM_OFF_PREIND /* 0111 1110 1011 */ TABDECL(OP_UND), /* 0111 1110 1100 */ TABDECL(OP_STRB_P_ASR_IMM_OFF_PREIND), // OP_STRB_P_ASR_IMM_OFF_PREIND /* 0111 1110 1101 */ TABDECL(OP_UND), /* 0111 1110 1110 */ TABDECL(OP_STRB_P_ROR_IMM_OFF_PREIND), // OP_STRB_P_ROR_IMM_OFF_PREIND /* 0111 1110 1111 */ TABDECL(OP_UND), /* 0111 1111 0000 */ TABDECL(OP_LDRB_P_LSL_IMM_OFF_PREIND), // OP_LDRB_P_LSL_IMM_OFF_PREIND /* 0111 1111 0001 */ TABDECL(OP_UND), /* 0111 1111 0010 */ TABDECL(OP_LDRB_P_LSR_IMM_OFF_PREIND), // OP_LDRB_P_LSR_IMM_OFF_PREIND /* 0111 1111 0011 */ TABDECL(OP_UND), /* 0111 1111 0100 */ TABDECL(OP_LDRB_P_ASR_IMM_OFF_PREIND), // OP_LDRB_P_ASR_IMM_OFF_PREIND /* 0111 1111 0101 */ TABDECL(OP_UND), /* 0111 1111 0110 */ TABDECL(OP_LDRB_P_ROR_IMM_OFF_PREIND), // OP_LDRB_P_ROR_IMM_OFF_PREIND /* 0111 1111 0111 */ TABDECL(OP_UND), /* 0111 1111 1000 */ TABDECL(OP_LDRB_P_LSL_IMM_OFF_PREIND), // OP_LDRB_P_LSL_IMM_OFF_PREIND /* 0111 1111 1001 */ TABDECL(OP_UND), /* 0111 1111 1010 */ TABDECL(OP_LDRB_P_LSR_IMM_OFF_PREIND), // OP_LDRB_P_LSR_IMM_OFF_PREIND /* 0111 1111 1011 */ TABDECL(OP_UND), /* 0111 1111 1100 */ TABDECL(OP_LDRB_P_ASR_IMM_OFF_PREIND), // OP_LDRB_P_ASR_IMM_OFF_PREIND /* 0111 1111 1101 */ TABDECL(OP_UND), /* 0111 1111 1110 */ TABDECL(OP_LDRB_P_ROR_IMM_OFF_PREIND), // OP_LDRB_P_ROR_IMM_OFF_PREIND /* 0111 1111 1111 */ TABDECL(OP_UND), /* 1000 0000 0000 */ TABDECL(OP_STMDA), // OP_STMDA /* 1000 0000 0001 */ TABDECL(OP_STMDA), // OP_STMDA /* 1000 0000 0010 */ TABDECL(OP_STMDA), // OP_STMDA /* 1000 0000 0011 */ TABDECL(OP_STMDA), // OP_STMDA /* 1000 0000 0100 */ TABDECL(OP_STMDA), // OP_STMDA /* 1000 0000 0101 */ TABDECL(OP_STMDA), // OP_STMDA /* 1000 0000 0110 */ TABDECL(OP_STMDA), // OP_STMDA /* 1000 0000 0111 */ TABDECL(OP_STMDA), // OP_STMDA /* 1000 0000 1000 */ TABDECL(OP_STMDA), // OP_STMDA /* 1000 0000 1001 */ TABDECL(OP_STMDA), // OP_STMDA /* 1000 0000 1010 */ TABDECL(OP_STMDA), // OP_STMDA /* 1000 0000 1011 */ TABDECL(OP_STMDA), // OP_STMDA /* 1000 0000 1100 */ TABDECL(OP_STMDA), // OP_STMDA /* 1000 0000 1101 */ TABDECL(OP_STMDA), // OP_STMDA /* 1000 0000 1110 */ TABDECL(OP_STMDA), // OP_STMDA /* 1000 0000 1111 */ TABDECL(OP_STMDA), // OP_STMDA /* 1000 0001 0000 */ TABDECL(OP_LDMDA), // OP_LDMDA /* 1000 0001 0001 */ TABDECL(OP_LDMDA), // OP_LDMDA /* 1000 0001 0010 */ TABDECL(OP_LDMDA), // OP_LDMDA /* 1000 0001 0011 */ TABDECL(OP_LDMDA), // OP_LDMDA /* 1000 0001 0100 */ TABDECL(OP_LDMDA), // OP_LDMDA /* 1000 0001 0101 */ TABDECL(OP_LDMDA), // OP_LDMDA /* 1000 0001 0110 */ TABDECL(OP_LDMDA), // OP_LDMDA /* 1000 0001 0111 */ TABDECL(OP_LDMDA), // OP_LDMDA /* 1000 0001 1000 */ TABDECL(OP_LDMDA), // OP_LDMDA /* 1000 0001 1001 */ TABDECL(OP_LDMDA), // OP_LDMDA /* 1000 0001 1010 */ TABDECL(OP_LDMDA), // OP_LDMDA /* 1000 0001 1011 */ TABDECL(OP_LDMDA), // OP_LDMDA /* 1000 0001 1100 */ TABDECL(OP_LDMDA), // OP_LDMDA /* 1000 0001 1101 */ TABDECL(OP_LDMDA), // OP_LDMDA /* 1000 0001 1110 */ TABDECL(OP_LDMDA), // OP_LDMDA /* 1000 0001 1111 */ TABDECL(OP_LDMDA), // OP_LDMDA /* 1000 0010 0000 */ TABDECL(OP_STMDA_W), // OP_STMDA_W /* 1000 0010 0001 */ TABDECL(OP_STMDA_W), // OP_STMDA_W /* 1000 0010 0010 */ TABDECL(OP_STMDA_W), // OP_STMDA_W /* 1000 0010 0011 */ TABDECL(OP_STMDA_W), // OP_STMDA_W /* 1000 0010 0100 */ TABDECL(OP_STMDA_W), // OP_STMDA_W /* 1000 0010 0101 */ TABDECL(OP_STMDA_W), // OP_STMDA_W /* 1000 0010 0110 */ TABDECL(OP_STMDA_W), // OP_STMDA_W /* 1000 0010 0111 */ TABDECL(OP_STMDA_W), // OP_STMDA_W /* 1000 0010 1000 */ TABDECL(OP_STMDA_W), // OP_STMDA_W /* 1000 0010 1001 */ TABDECL(OP_STMDA_W), // OP_STMDA_W /* 1000 0010 1010 */ TABDECL(OP_STMDA_W), // OP_STMDA_W /* 1000 0010 1011 */ TABDECL(OP_STMDA_W), // OP_STMDA_W /* 1000 0010 1100 */ TABDECL(OP_STMDA_W), // OP_STMDA_W /* 1000 0010 1101 */ TABDECL(OP_STMDA_W), // OP_STMDA_W /* 1000 0010 1110 */ TABDECL(OP_STMDA_W), // OP_STMDA_W /* 1000 0010 1111 */ TABDECL(OP_STMDA_W), // OP_STMDA_W /* 1000 0011 0000 */ TABDECL(OP_LDMDA_W), // OP_LDMDA_W /* 1000 0011 0001 */ TABDECL(OP_LDMDA_W), // OP_LDMDA_W /* 1000 0011 0010 */ TABDECL(OP_LDMDA_W), // OP_LDMDA_W /* 1000 0011 0011 */ TABDECL(OP_LDMDA_W), // OP_LDMDA_W /* 1000 0011 0100 */ TABDECL(OP_LDMDA_W), // OP_LDMDA_W /* 1000 0011 0101 */ TABDECL(OP_LDMDA_W), // OP_LDMDA_W /* 1000 0011 0110 */ TABDECL(OP_LDMDA_W), // OP_LDMDA_W /* 1000 0011 0111 */ TABDECL(OP_LDMDA_W), // OP_LDMDA_W /* 1000 0011 1000 */ TABDECL(OP_LDMDA_W), // OP_LDMDA_W /* 1000 0011 1001 */ TABDECL(OP_LDMDA_W), // OP_LDMDA_W /* 1000 0011 1010 */ TABDECL(OP_LDMDA_W), // OP_LDMDA_W /* 1000 0011 1011 */ TABDECL(OP_LDMDA_W), // OP_LDMDA_W /* 1000 0011 1100 */ TABDECL(OP_LDMDA_W), // OP_LDMDA_W /* 1000 0011 1101 */ TABDECL(OP_LDMDA_W), // OP_LDMDA_W /* 1000 0011 1110 */ TABDECL(OP_LDMDA_W), // OP_LDMDA_W /* 1000 0011 1111 */ TABDECL(OP_LDMDA_W), // OP_LDMDA_W /* 1000 0100 0000 */ TABDECL(OP_STMDA2), // OP_STMDA2 /* 1000 0100 0001 */ TABDECL(OP_STMDA2), // OP_STMDA2 /* 1000 0100 0010 */ TABDECL(OP_STMDA2), // OP_STMDA2 /* 1000 0100 0011 */ TABDECL(OP_STMDA2), // OP_STMDA2 /* 1000 0100 0100 */ TABDECL(OP_STMDA2), // OP_STMDA2 /* 1000 0100 0101 */ TABDECL(OP_STMDA2), // OP_STMDA2 /* 1000 0100 0110 */ TABDECL(OP_STMDA2), // OP_STMDA2 /* 1000 0100 0111 */ TABDECL(OP_STMDA2), // OP_STMDA2 /* 1000 0100 1000 */ TABDECL(OP_STMDA2), // OP_STMDA2 /* 1000 0100 1001 */ TABDECL(OP_STMDA2), // OP_STMDA2 /* 1000 0100 1010 */ TABDECL(OP_STMDA2), // OP_STMDA2 /* 1000 0100 1011 */ TABDECL(OP_STMDA2), // OP_STMDA2 /* 1000 0100 1100 */ TABDECL(OP_STMDA2), // OP_STMDA2 /* 1000 0100 1101 */ TABDECL(OP_STMDA2), // OP_STMDA2 /* 1000 0100 1110 */ TABDECL(OP_STMDA2), // OP_STMDA2 /* 1000 0100 1111 */ TABDECL(OP_STMDA2), // OP_STMDA2 /* 1000 0101 0000 */ TABDECL(OP_LDMDA2), // OP_LDMDA2 /* 1000 0101 0001 */ TABDECL(OP_LDMDA2), // OP_LDMDA2 /* 1000 0101 0010 */ TABDECL(OP_LDMDA2), // OP_LDMDA2 /* 1000 0101 0011 */ TABDECL(OP_LDMDA2), // OP_LDMDA2 /* 1000 0101 0100 */ TABDECL(OP_LDMDA2), // OP_LDMDA2 /* 1000 0101 0101 */ TABDECL(OP_LDMDA2), // OP_LDMDA2 /* 1000 0101 0110 */ TABDECL(OP_LDMDA2), // OP_LDMDA2 /* 1000 0101 0111 */ TABDECL(OP_LDMDA2), // OP_LDMDA2 /* 1000 0101 1000 */ TABDECL(OP_LDMDA2), // OP_LDMDA2 /* 1000 0101 1001 */ TABDECL(OP_LDMDA2), // OP_LDMDA2 /* 1000 0101 1010 */ TABDECL(OP_LDMDA2), // OP_LDMDA2 /* 1000 0101 1011 */ TABDECL(OP_LDMDA2), // OP_LDMDA2 /* 1000 0101 1100 */ TABDECL(OP_LDMDA2), // OP_LDMDA2 /* 1000 0101 1101 */ TABDECL(OP_LDMDA2), // OP_LDMDA2 /* 1000 0101 1110 */ TABDECL(OP_LDMDA2), // OP_LDMDA2 /* 1000 0101 1111 */ TABDECL(OP_LDMDA2), // OP_LDMDA2 /* 1000 0110 0000 */ TABDECL(OP_STMDA2_W), // OP_STMDA2_W /* 1000 0110 0001 */ TABDECL(OP_STMDA2_W), // OP_STMDA2_W /* 1000 0110 0010 */ TABDECL(OP_STMDA2_W), // OP_STMDA2_W /* 1000 0110 0011 */ TABDECL(OP_STMDA2_W), // OP_STMDA2_W /* 1000 0110 0100 */ TABDECL(OP_STMDA2_W), // OP_STMDA2_W /* 1000 0110 0101 */ TABDECL(OP_STMDA2_W), // OP_STMDA2_W /* 1000 0110 0110 */ TABDECL(OP_STMDA2_W), // OP_STMDA2_W /* 1000 0110 0111 */ TABDECL(OP_STMDA2_W), // OP_STMDA2_W /* 1000 0110 1000 */ TABDECL(OP_STMDA2_W), // OP_STMDA2_W /* 1000 0110 1001 */ TABDECL(OP_STMDA2_W), // OP_STMDA2_W /* 1000 0110 1010 */ TABDECL(OP_STMDA2_W), // OP_STMDA2_W /* 1000 0110 1011 */ TABDECL(OP_STMDA2_W), // OP_STMDA2_W /* 1000 0110 1100 */ TABDECL(OP_STMDA2_W), // OP_STMDA2_W /* 1000 0110 1101 */ TABDECL(OP_STMDA2_W), // OP_STMDA2_W /* 1000 0110 1110 */ TABDECL(OP_STMDA2_W), // OP_STMDA2_W /* 1000 0110 1111 */ TABDECL(OP_STMDA2_W), // OP_STMDA2_W /* 1000 0111 0000 */ TABDECL(OP_LDMDA2_W), // OP_LDMDA2_W /* 1000 0111 0001 */ TABDECL(OP_LDMDA2_W), // OP_LDMDA2_W /* 1000 0111 0010 */ TABDECL(OP_LDMDA2_W), // OP_LDMDA2_W /* 1000 0111 0011 */ TABDECL(OP_LDMDA2_W), // OP_LDMDA2_W /* 1000 0111 0100 */ TABDECL(OP_LDMDA2_W), // OP_LDMDA2_W /* 1000 0111 0101 */ TABDECL(OP_LDMDA2_W), // OP_LDMDA2_W /* 1000 0111 0110 */ TABDECL(OP_LDMDA2_W), // OP_LDMDA2_W /* 1000 0111 0111 */ TABDECL(OP_LDMDA2_W), // OP_LDMDA2_W /* 1000 0111 1000 */ TABDECL(OP_LDMDA2_W), // OP_LDMDA2_W /* 1000 0111 1001 */ TABDECL(OP_LDMDA2_W), // OP_LDMDA2_W /* 1000 0111 1010 */ TABDECL(OP_LDMDA2_W), // OP_LDMDA2_W /* 1000 0111 1011 */ TABDECL(OP_LDMDA2_W), // OP_LDMDA2_W /* 1000 0111 1100 */ TABDECL(OP_LDMDA2_W), // OP_LDMDA2_W /* 1000 0111 1101 */ TABDECL(OP_LDMDA2_W), // OP_LDMDA2_W /* 1000 0111 1110 */ TABDECL(OP_LDMDA2_W), // OP_LDMDA2_W /* 1000 0111 1111 */ TABDECL(OP_LDMDA2_W), // OP_LDMDA2_W /* 1000 1000 0000 */ TABDECL(OP_STMIA), // OP_STMIA /* 1000 1000 0001 */ TABDECL(OP_STMIA), // OP_STMIA /* 1000 1000 0010 */ TABDECL(OP_STMIA), // OP_STMIA /* 1000 1000 0011 */ TABDECL(OP_STMIA), // OP_STMIA /* 1000 1000 0100 */ TABDECL(OP_STMIA), // OP_STMIA /* 1000 1000 0101 */ TABDECL(OP_STMIA), // OP_STMIA /* 1000 1000 0110 */ TABDECL(OP_STMIA), // OP_STMIA /* 1000 1000 0111 */ TABDECL(OP_STMIA), // OP_STMIA /* 1000 1000 1000 */ TABDECL(OP_STMIA), // OP_STMIA /* 1000 1000 1001 */ TABDECL(OP_STMIA), // OP_STMIA /* 1000 1000 1010 */ TABDECL(OP_STMIA), // OP_STMIA /* 1000 1000 1011 */ TABDECL(OP_STMIA), // OP_STMIA /* 1000 1000 1100 */ TABDECL(OP_STMIA), // OP_STMIA /* 1000 1000 1101 */ TABDECL(OP_STMIA), // OP_STMIA /* 1000 1000 1110 */ TABDECL(OP_STMIA), // OP_STMIA /* 1000 1000 1111 */ TABDECL(OP_STMIA), // OP_STMIA /* 1000 1001 0000 */ TABDECL(OP_LDMIA), // OP_LDMIA /* 1000 1001 0001 */ TABDECL(OP_LDMIA), // OP_LDMIA /* 1000 1001 0010 */ TABDECL(OP_LDMIA), // OP_LDMIA /* 1000 1001 0011 */ TABDECL(OP_LDMIA), // OP_LDMIA /* 1000 1001 0100 */ TABDECL(OP_LDMIA), // OP_LDMIA /* 1000 1001 0101 */ TABDECL(OP_LDMIA), // OP_LDMIA /* 1000 1001 0110 */ TABDECL(OP_LDMIA), // OP_LDMIA /* 1000 1001 0111 */ TABDECL(OP_LDMIA), // OP_LDMIA /* 1000 1001 1000 */ TABDECL(OP_LDMIA), // OP_LDMIA /* 1000 1001 1001 */ TABDECL(OP_LDMIA), // OP_LDMIA /* 1000 1001 1010 */ TABDECL(OP_LDMIA), // OP_LDMIA /* 1000 1001 1011 */ TABDECL(OP_LDMIA), // OP_LDMIA /* 1000 1001 1100 */ TABDECL(OP_LDMIA), // OP_LDMIA /* 1000 1001 1101 */ TABDECL(OP_LDMIA), // OP_LDMIA /* 1000 1001 1110 */ TABDECL(OP_LDMIA), // OP_LDMIA /* 1000 1001 1111 */ TABDECL(OP_LDMIA), // OP_LDMIA /* 1000 1010 0000 */ TABDECL(OP_STMIA_W), // OP_STMIA_W /* 1000 1010 0001 */ TABDECL(OP_STMIA_W), // OP_STMIA_W /* 1000 1010 0010 */ TABDECL(OP_STMIA_W), // OP_STMIA_W /* 1000 1010 0011 */ TABDECL(OP_STMIA_W), // OP_STMIA_W /* 1000 1010 0100 */ TABDECL(OP_STMIA_W), // OP_STMIA_W /* 1000 1010 0101 */ TABDECL(OP_STMIA_W), // OP_STMIA_W /* 1000 1010 0110 */ TABDECL(OP_STMIA_W), // OP_STMIA_W /* 1000 1010 0111 */ TABDECL(OP_STMIA_W), // OP_STMIA_W /* 1000 1010 1000 */ TABDECL(OP_STMIA_W), // OP_STMIA_W /* 1000 1010 1001 */ TABDECL(OP_STMIA_W), // OP_STMIA_W /* 1000 1010 1010 */ TABDECL(OP_STMIA_W), // OP_STMIA_W /* 1000 1010 1011 */ TABDECL(OP_STMIA_W), // OP_STMIA_W /* 1000 1010 1100 */ TABDECL(OP_STMIA_W), // OP_STMIA_W /* 1000 1010 1101 */ TABDECL(OP_STMIA_W), // OP_STMIA_W /* 1000 1010 1110 */ TABDECL(OP_STMIA_W), // OP_STMIA_W /* 1000 1010 1111 */ TABDECL(OP_STMIA_W), // OP_STMIA_W /* 1000 1011 0000 */ TABDECL(OP_LDMIA_W), // OP_LDMIA_W /* 1000 1011 0001 */ TABDECL(OP_LDMIA_W), // OP_LDMIA_W /* 1000 1011 0010 */ TABDECL(OP_LDMIA_W), // OP_LDMIA_W /* 1000 1011 0011 */ TABDECL(OP_LDMIA_W), // OP_LDMIA_W /* 1000 1011 0100 */ TABDECL(OP_LDMIA_W), // OP_LDMIA_W /* 1000 1011 0101 */ TABDECL(OP_LDMIA_W), // OP_LDMIA_W /* 1000 1011 0110 */ TABDECL(OP_LDMIA_W), // OP_LDMIA_W /* 1000 1011 0111 */ TABDECL(OP_LDMIA_W), // OP_LDMIA_W /* 1000 1011 1000 */ TABDECL(OP_LDMIA_W), // OP_LDMIA_W /* 1000 1011 1001 */ TABDECL(OP_LDMIA_W), // OP_LDMIA_W /* 1000 1011 1010 */ TABDECL(OP_LDMIA_W), // OP_LDMIA_W /* 1000 1011 1011 */ TABDECL(OP_LDMIA_W), // OP_LDMIA_W /* 1000 1011 1100 */ TABDECL(OP_LDMIA_W), // OP_LDMIA_W /* 1000 1011 1101 */ TABDECL(OP_LDMIA_W), // OP_LDMIA_W /* 1000 1011 1110 */ TABDECL(OP_LDMIA_W), // OP_LDMIA_W /* 1000 1011 1111 */ TABDECL(OP_LDMIA_W), // OP_LDMIA_W /* 1000 1100 0000 */ TABDECL(OP_STMIA2), // OP_STMIA2 /* 1000 1100 0001 */ TABDECL(OP_STMIA2), // OP_STMIA2 /* 1000 1100 0010 */ TABDECL(OP_STMIA2), // OP_STMIA2 /* 1000 1100 0011 */ TABDECL(OP_STMIA2), // OP_STMIA2 /* 1000 1100 0100 */ TABDECL(OP_STMIA2), // OP_STMIA2 /* 1000 1100 0101 */ TABDECL(OP_STMIA2), // OP_STMIA2 /* 1000 1100 0110 */ TABDECL(OP_STMIA2), // OP_STMIA2 /* 1000 1100 0111 */ TABDECL(OP_STMIA2), // OP_STMIA2 /* 1000 1100 1000 */ TABDECL(OP_STMIA2), // OP_STMIA2 /* 1000 1100 1001 */ TABDECL(OP_STMIA2), // OP_STMIA2 /* 1000 1100 1010 */ TABDECL(OP_STMIA2), // OP_STMIA2 /* 1000 1100 1011 */ TABDECL(OP_STMIA2), // OP_STMIA2 /* 1000 1100 1100 */ TABDECL(OP_STMIA2), // OP_STMIA2 /* 1000 1100 1101 */ TABDECL(OP_STMIA2), // OP_STMIA2 /* 1000 1100 1110 */ TABDECL(OP_STMIA2), // OP_STMIA2 /* 1000 1100 1111 */ TABDECL(OP_STMIA2), // OP_STMIA2 /* 1000 1101 0000 */ TABDECL(OP_LDMIA2), // OP_LDMIA2 /* 1000 1101 0001 */ TABDECL(OP_LDMIA2), // OP_LDMIA2 /* 1000 1101 0010 */ TABDECL(OP_LDMIA2), // OP_LDMIA2 /* 1000 1101 0011 */ TABDECL(OP_LDMIA2), // OP_LDMIA2 /* 1000 1101 0100 */ TABDECL(OP_LDMIA2), // OP_LDMIA2 /* 1000 1101 0101 */ TABDECL(OP_LDMIA2), // OP_LDMIA2 /* 1000 1101 0110 */ TABDECL(OP_LDMIA2), // OP_LDMIA2 /* 1000 1101 0111 */ TABDECL(OP_LDMIA2), // OP_LDMIA2 /* 1000 1101 1000 */ TABDECL(OP_LDMIA2), // OP_LDMIA2 /* 1000 1101 1001 */ TABDECL(OP_LDMIA2), // OP_LDMIA2 /* 1000 1101 1010 */ TABDECL(OP_LDMIA2), // OP_LDMIA2 /* 1000 1101 1011 */ TABDECL(OP_LDMIA2), // OP_LDMIA2 /* 1000 1101 1100 */ TABDECL(OP_LDMIA2), // OP_LDMIA2 /* 1000 1101 1101 */ TABDECL(OP_LDMIA2), // OP_LDMIA2 /* 1000 1101 1110 */ TABDECL(OP_LDMIA2), // OP_LDMIA2 /* 1000 1101 1111 */ TABDECL(OP_LDMIA2), // OP_LDMIA2 /* 1000 1110 0000 */ TABDECL(OP_STMIA2_W), // OP_STMIA2_W /* 1000 1110 0001 */ TABDECL(OP_STMIA2_W), // OP_STMIA2_W /* 1000 1110 0010 */ TABDECL(OP_STMIA2_W), // OP_STMIA2_W /* 1000 1110 0011 */ TABDECL(OP_STMIA2_W), // OP_STMIA2_W /* 1000 1110 0100 */ TABDECL(OP_STMIA2_W), // OP_STMIA2_W /* 1000 1110 0101 */ TABDECL(OP_STMIA2_W), // OP_STMIA2_W /* 1000 1110 0110 */ TABDECL(OP_STMIA2_W), // OP_STMIA2_W /* 1000 1110 0111 */ TABDECL(OP_STMIA2_W), // OP_STMIA2_W /* 1000 1110 1000 */ TABDECL(OP_STMIA2_W), // OP_STMIA2_W /* 1000 1110 1001 */ TABDECL(OP_STMIA2_W), // OP_STMIA2_W /* 1000 1110 1010 */ TABDECL(OP_STMIA2_W), // OP_STMIA2_W /* 1000 1110 1011 */ TABDECL(OP_STMIA2_W), // OP_STMIA2_W /* 1000 1110 1100 */ TABDECL(OP_STMIA2_W), // OP_STMIA2_W /* 1000 1110 1101 */ TABDECL(OP_STMIA2_W), // OP_STMIA2_W /* 1000 1110 1110 */ TABDECL(OP_STMIA2_W), // OP_STMIA2_W /* 1000 1110 1111 */ TABDECL(OP_STMIA2_W), // OP_STMIA2_W /* 1000 1111 0000 */ TABDECL(OP_LDMIA2_W), // OP_LDMIA2_W /* 1000 1111 0001 */ TABDECL(OP_LDMIA2_W), // OP_LDMIA2_W /* 1000 1111 0010 */ TABDECL(OP_LDMIA2_W), // OP_LDMIA2_W /* 1000 1111 0011 */ TABDECL(OP_LDMIA2_W), // OP_LDMIA2_W /* 1000 1111 0100 */ TABDECL(OP_LDMIA2_W), // OP_LDMIA2_W /* 1000 1111 0101 */ TABDECL(OP_LDMIA2_W), // OP_LDMIA2_W /* 1000 1111 0110 */ TABDECL(OP_LDMIA2_W), // OP_LDMIA2_W /* 1000 1111 0111 */ TABDECL(OP_LDMIA2_W), // OP_LDMIA2_W /* 1000 1111 1000 */ TABDECL(OP_LDMIA2_W), // OP_LDMIA2_W /* 1000 1111 1001 */ TABDECL(OP_LDMIA2_W), // OP_LDMIA2_W /* 1000 1111 1010 */ TABDECL(OP_LDMIA2_W), // OP_LDMIA2_W /* 1000 1111 1011 */ TABDECL(OP_LDMIA2_W), // OP_LDMIA2_W /* 1000 1111 1100 */ TABDECL(OP_LDMIA2_W), // OP_LDMIA2_W /* 1000 1111 1101 */ TABDECL(OP_LDMIA2_W), // OP_LDMIA2_W /* 1000 1111 1110 */ TABDECL(OP_LDMIA2_W), // OP_LDMIA2_W /* 1000 1111 1111 */ TABDECL(OP_LDMIA2_W), // OP_LDMIA2_W /* 1001 0000 0000 */ TABDECL(OP_STMDB), // OP_STMDB /* 1001 0000 0001 */ TABDECL(OP_STMDB), // OP_STMDB /* 1001 0000 0010 */ TABDECL(OP_STMDB), // OP_STMDB /* 1001 0000 0011 */ TABDECL(OP_STMDB), // OP_STMDB /* 1001 0000 0100 */ TABDECL(OP_STMDB), // OP_STMDB /* 1001 0000 0101 */ TABDECL(OP_STMDB), // OP_STMDB /* 1001 0000 0110 */ TABDECL(OP_STMDB), // OP_STMDB /* 1001 0000 0111 */ TABDECL(OP_STMDB), // OP_STMDB /* 1001 0000 1000 */ TABDECL(OP_STMDB), // OP_STMDB /* 1001 0000 1001 */ TABDECL(OP_STMDB), // OP_STMDB /* 1001 0000 1010 */ TABDECL(OP_STMDB), // OP_STMDB /* 1001 0000 1011 */ TABDECL(OP_STMDB), // OP_STMDB /* 1001 0000 1100 */ TABDECL(OP_STMDB), // OP_STMDB /* 1001 0000 1101 */ TABDECL(OP_STMDB), // OP_STMDB /* 1001 0000 1110 */ TABDECL(OP_STMDB), // OP_STMDB /* 1001 0000 1111 */ TABDECL(OP_STMDB), // OP_STMDB /* 1001 0001 0000 */ TABDECL(OP_LDMDB), // OP_LDMDB /* 1001 0001 0001 */ TABDECL(OP_LDMDB), // OP_LDMDB /* 1001 0001 0010 */ TABDECL(OP_LDMDB), // OP_LDMDB /* 1001 0001 0011 */ TABDECL(OP_LDMDB), // OP_LDMDB /* 1001 0001 0100 */ TABDECL(OP_LDMDB), // OP_LDMDB /* 1001 0001 0101 */ TABDECL(OP_LDMDB), // OP_LDMDB /* 1001 0001 0110 */ TABDECL(OP_LDMDB), // OP_LDMDB /* 1001 0001 0111 */ TABDECL(OP_LDMDB), // OP_LDMDB /* 1001 0001 1000 */ TABDECL(OP_LDMDB), // OP_LDMDB /* 1001 0001 1001 */ TABDECL(OP_LDMDB), // OP_LDMDB /* 1001 0001 1010 */ TABDECL(OP_LDMDB), // OP_LDMDB /* 1001 0001 1011 */ TABDECL(OP_LDMDB), // OP_LDMDB /* 1001 0001 1100 */ TABDECL(OP_LDMDB), // OP_LDMDB /* 1001 0001 1101 */ TABDECL(OP_LDMDB), // OP_LDMDB /* 1001 0001 1110 */ TABDECL(OP_LDMDB), // OP_LDMDB /* 1001 0001 1111 */ TABDECL(OP_LDMDB), // OP_LDMDB /* 1001 0010 0000 */ TABDECL(OP_STMDB_W), // OP_STMDB_W /* 1001 0010 0001 */ TABDECL(OP_STMDB_W), // OP_STMDB_W /* 1001 0010 0010 */ TABDECL(OP_STMDB_W), // OP_STMDB_W /* 1001 0010 0011 */ TABDECL(OP_STMDB_W), // OP_STMDB_W /* 1001 0010 0100 */ TABDECL(OP_STMDB_W), // OP_STMDB_W /* 1001 0010 0101 */ TABDECL(OP_STMDB_W), // OP_STMDB_W /* 1001 0010 0110 */ TABDECL(OP_STMDB_W), // OP_STMDB_W /* 1001 0010 0111 */ TABDECL(OP_STMDB_W), // OP_STMDB_W /* 1001 0010 1000 */ TABDECL(OP_STMDB_W), // OP_STMDB_W /* 1001 0010 1001 */ TABDECL(OP_STMDB_W), // OP_STMDB_W /* 1001 0010 1010 */ TABDECL(OP_STMDB_W), // OP_STMDB_W /* 1001 0010 1011 */ TABDECL(OP_STMDB_W), // OP_STMDB_W /* 1001 0010 1100 */ TABDECL(OP_STMDB_W), // OP_STMDB_W /* 1001 0010 1101 */ TABDECL(OP_STMDB_W), // OP_STMDB_W /* 1001 0010 1110 */ TABDECL(OP_STMDB_W), // OP_STMDB_W /* 1001 0010 1111 */ TABDECL(OP_STMDB_W), // OP_STMDB_W /* 1001 0011 0000 */ TABDECL(OP_LDMDB_W), // OP_LDMDB_W /* 1001 0011 0001 */ TABDECL(OP_LDMDB_W), // OP_LDMDB_W /* 1001 0011 0010 */ TABDECL(OP_LDMDB_W), // OP_LDMDB_W /* 1001 0011 0011 */ TABDECL(OP_LDMDB_W), // OP_LDMDB_W /* 1001 0011 0100 */ TABDECL(OP_LDMDB_W), // OP_LDMDB_W /* 1001 0011 0101 */ TABDECL(OP_LDMDB_W), // OP_LDMDB_W /* 1001 0011 0110 */ TABDECL(OP_LDMDB_W), // OP_LDMDB_W /* 1001 0011 0111 */ TABDECL(OP_LDMDB_W), // OP_LDMDB_W /* 1001 0011 1000 */ TABDECL(OP_LDMDB_W), // OP_LDMDB_W /* 1001 0011 1001 */ TABDECL(OP_LDMDB_W), // OP_LDMDB_W /* 1001 0011 1010 */ TABDECL(OP_LDMDB_W), // OP_LDMDB_W /* 1001 0011 1011 */ TABDECL(OP_LDMDB_W), // OP_LDMDB_W /* 1001 0011 1100 */ TABDECL(OP_LDMDB_W), // OP_LDMDB_W /* 1001 0011 1101 */ TABDECL(OP_LDMDB_W), // OP_LDMDB_W /* 1001 0011 1110 */ TABDECL(OP_LDMDB_W), // OP_LDMDB_W /* 1001 0011 1111 */ TABDECL(OP_LDMDB_W), // OP_LDMDB_W /* 1001 0100 0000 */ TABDECL(OP_STMDB2), // OP_STMDB2 /* 1001 0100 0001 */ TABDECL(OP_STMDB2), // OP_STMDB2 /* 1001 0100 0010 */ TABDECL(OP_STMDB2), // OP_STMDB2 /* 1001 0100 0011 */ TABDECL(OP_STMDB2), // OP_STMDB2 /* 1001 0100 0100 */ TABDECL(OP_STMDB2), // OP_STMDB2 /* 1001 0100 0101 */ TABDECL(OP_STMDB2), // OP_STMDB2 /* 1001 0100 0110 */ TABDECL(OP_STMDB2), // OP_STMDB2 /* 1001 0100 0111 */ TABDECL(OP_STMDB2), // OP_STMDB2 /* 1001 0100 1000 */ TABDECL(OP_STMDB2), // OP_STMDB2 /* 1001 0100 1001 */ TABDECL(OP_STMDB2), // OP_STMDB2 /* 1001 0100 1010 */ TABDECL(OP_STMDB2), // OP_STMDB2 /* 1001 0100 1011 */ TABDECL(OP_STMDB2), // OP_STMDB2 /* 1001 0100 1100 */ TABDECL(OP_STMDB2), // OP_STMDB2 /* 1001 0100 1101 */ TABDECL(OP_STMDB2), // OP_STMDB2 /* 1001 0100 1110 */ TABDECL(OP_STMDB2), // OP_STMDB2 /* 1001 0100 1111 */ TABDECL(OP_STMDB2), // OP_STMDB2 /* 1001 0101 0000 */ TABDECL(OP_LDMDB2), // OP_LDMDB2 /* 1001 0101 0001 */ TABDECL(OP_LDMDB2), // OP_LDMDB2 /* 1001 0101 0010 */ TABDECL(OP_LDMDB2), // OP_LDMDB2 /* 1001 0101 0011 */ TABDECL(OP_LDMDB2), // OP_LDMDB2 /* 1001 0101 0100 */ TABDECL(OP_LDMDB2), // OP_LDMDB2 /* 1001 0101 0101 */ TABDECL(OP_LDMDB2), // OP_LDMDB2 /* 1001 0101 0110 */ TABDECL(OP_LDMDB2), // OP_LDMDB2 /* 1001 0101 0111 */ TABDECL(OP_LDMDB2), // OP_LDMDB2 /* 1001 0101 1000 */ TABDECL(OP_LDMDB2), // OP_LDMDB2 /* 1001 0101 1001 */ TABDECL(OP_LDMDB2), // OP_LDMDB2 /* 1001 0101 1010 */ TABDECL(OP_LDMDB2), // OP_LDMDB2 /* 1001 0101 1011 */ TABDECL(OP_LDMDB2), // OP_LDMDB2 /* 1001 0101 1100 */ TABDECL(OP_LDMDB2), // OP_LDMDB2 /* 1001 0101 1101 */ TABDECL(OP_LDMDB2), // OP_LDMDB2 /* 1001 0101 1110 */ TABDECL(OP_LDMDB2), // OP_LDMDB2 /* 1001 0101 1111 */ TABDECL(OP_LDMDB2), // OP_LDMDB2 /* 1001 0110 0000 */ TABDECL(OP_STMDB2_W), // OP_STMDB2_W /* 1001 0110 0001 */ TABDECL(OP_STMDB2_W), // OP_STMDB2_W /* 1001 0110 0010 */ TABDECL(OP_STMDB2_W), // OP_STMDB2_W /* 1001 0110 0011 */ TABDECL(OP_STMDB2_W), // OP_STMDB2_W /* 1001 0110 0100 */ TABDECL(OP_STMDB2_W), // OP_STMDB2_W /* 1001 0110 0101 */ TABDECL(OP_STMDB2_W), // OP_STMDB2_W /* 1001 0110 0110 */ TABDECL(OP_STMDB2_W), // OP_STMDB2_W /* 1001 0110 0111 */ TABDECL(OP_STMDB2_W), // OP_STMDB2_W /* 1001 0110 1000 */ TABDECL(OP_STMDB2_W), // OP_STMDB2_W /* 1001 0110 1001 */ TABDECL(OP_STMDB2_W), // OP_STMDB2_W /* 1001 0110 1010 */ TABDECL(OP_STMDB2_W), // OP_STMDB2_W /* 1001 0110 1011 */ TABDECL(OP_STMDB2_W), // OP_STMDB2_W /* 1001 0110 1100 */ TABDECL(OP_STMDB2_W), // OP_STMDB2_W /* 1001 0110 1101 */ TABDECL(OP_STMDB2_W), // OP_STMDB2_W /* 1001 0110 1110 */ TABDECL(OP_STMDB2_W), // OP_STMDB2_W /* 1001 0110 1111 */ TABDECL(OP_STMDB2_W), // OP_STMDB2_W /* 1001 0111 0000 */ TABDECL(OP_LDMDB2_W), // OP_LDMDB2_W /* 1001 0111 0001 */ TABDECL(OP_LDMDB2_W), // OP_LDMDB2_W /* 1001 0111 0010 */ TABDECL(OP_LDMDB2_W), // OP_LDMDB2_W /* 1001 0111 0011 */ TABDECL(OP_LDMDB2_W), // OP_LDMDB2_W /* 1001 0111 0100 */ TABDECL(OP_LDMDB2_W), // OP_LDMDB2_W /* 1001 0111 0101 */ TABDECL(OP_LDMDB2_W), // OP_LDMDB2_W /* 1001 0111 0110 */ TABDECL(OP_LDMDB2_W), // OP_LDMDB2_W /* 1001 0111 0111 */ TABDECL(OP_LDMDB2_W), // OP_LDMDB2_W /* 1001 0111 1000 */ TABDECL(OP_LDMDB2_W), // OP_LDMDB2_W /* 1001 0111 1001 */ TABDECL(OP_LDMDB2_W), // OP_LDMDB2_W /* 1001 0111 1010 */ TABDECL(OP_LDMDB2_W), // OP_LDMDB2_W /* 1001 0111 1011 */ TABDECL(OP_LDMDB2_W), // OP_LDMDB2_W /* 1001 0111 1100 */ TABDECL(OP_LDMDB2_W), // OP_LDMDB2_W /* 1001 0111 1101 */ TABDECL(OP_LDMDB2_W), // OP_LDMDB2_W /* 1001 0111 1110 */ TABDECL(OP_LDMDB2_W), // OP_LDMDB2_W /* 1001 0111 1111 */ TABDECL(OP_LDMDB2_W), // OP_LDMDB2_W /* 1001 1000 0000 */ TABDECL(OP_STMIB), // OP_STMIB /* 1001 1000 0001 */ TABDECL(OP_STMIB), // OP_STMIB /* 1001 1000 0010 */ TABDECL(OP_STMIB), // OP_STMIB /* 1001 1000 0011 */ TABDECL(OP_STMIB), // OP_STMIB /* 1001 1000 0100 */ TABDECL(OP_STMIB), // OP_STMIB /* 1001 1000 0101 */ TABDECL(OP_STMIB), // OP_STMIB /* 1001 1000 0110 */ TABDECL(OP_STMIB), // OP_STMIB /* 1001 1000 0111 */ TABDECL(OP_STMIB), // OP_STMIB /* 1001 1000 1000 */ TABDECL(OP_STMIB), // OP_STMIB /* 1001 1000 1001 */ TABDECL(OP_STMIB), // OP_STMIB /* 1001 1000 1010 */ TABDECL(OP_STMIB), // OP_STMIB /* 1001 1000 1011 */ TABDECL(OP_STMIB), // OP_STMIB /* 1001 1000 1100 */ TABDECL(OP_STMIB), // OP_STMIB /* 1001 1000 1101 */ TABDECL(OP_STMIB), // OP_STMIB /* 1001 1000 1110 */ TABDECL(OP_STMIB), // OP_STMIB /* 1001 1000 1111 */ TABDECL(OP_STMIB), // OP_STMIB /* 1001 1001 0000 */ TABDECL(OP_LDMIB), // OP_LDMIB /* 1001 1001 0001 */ TABDECL(OP_LDMIB), // OP_LDMIB /* 1001 1001 0010 */ TABDECL(OP_LDMIB), // OP_LDMIB /* 1001 1001 0011 */ TABDECL(OP_LDMIB), // OP_LDMIB /* 1001 1001 0100 */ TABDECL(OP_LDMIB), // OP_LDMIB /* 1001 1001 0101 */ TABDECL(OP_LDMIB), // OP_LDMIB /* 1001 1001 0110 */ TABDECL(OP_LDMIB), // OP_LDMIB /* 1001 1001 0111 */ TABDECL(OP_LDMIB), // OP_LDMIB /* 1001 1001 1000 */ TABDECL(OP_LDMIB), // OP_LDMIB /* 1001 1001 1001 */ TABDECL(OP_LDMIB), // OP_LDMIB /* 1001 1001 1010 */ TABDECL(OP_LDMIB), // OP_LDMIB /* 1001 1001 1011 */ TABDECL(OP_LDMIB), // OP_LDMIB /* 1001 1001 1100 */ TABDECL(OP_LDMIB), // OP_LDMIB /* 1001 1001 1101 */ TABDECL(OP_LDMIB), // OP_LDMIB /* 1001 1001 1110 */ TABDECL(OP_LDMIB), // OP_LDMIB /* 1001 1001 1111 */ TABDECL(OP_LDMIB), // OP_LDMIB /* 1001 1010 0000 */ TABDECL(OP_STMIB_W), // OP_STMIB_W /* 1001 1010 0001 */ TABDECL(OP_STMIB_W), // OP_STMIB_W /* 1001 1010 0010 */ TABDECL(OP_STMIB_W), // OP_STMIB_W /* 1001 1010 0011 */ TABDECL(OP_STMIB_W), // OP_STMIB_W /* 1001 1010 0100 */ TABDECL(OP_STMIB_W), // OP_STMIB_W /* 1001 1010 0101 */ TABDECL(OP_STMIB_W), // OP_STMIB_W /* 1001 1010 0110 */ TABDECL(OP_STMIB_W), // OP_STMIB_W /* 1001 1010 0111 */ TABDECL(OP_STMIB_W), // OP_STMIB_W /* 1001 1010 1000 */ TABDECL(OP_STMIB_W), // OP_STMIB_W /* 1001 1010 1001 */ TABDECL(OP_STMIB_W), // OP_STMIB_W /* 1001 1010 1010 */ TABDECL(OP_STMIB_W), // OP_STMIB_W /* 1001 1010 1011 */ TABDECL(OP_STMIB_W), // OP_STMIB_W /* 1001 1010 1100 */ TABDECL(OP_STMIB_W), // OP_STMIB_W /* 1001 1010 1101 */ TABDECL(OP_STMIB_W), // OP_STMIB_W /* 1001 1010 1110 */ TABDECL(OP_STMIB_W), // OP_STMIB_W /* 1001 1010 1111 */ TABDECL(OP_STMIB_W), // OP_STMIB_W /* 1001 1011 0000 */ TABDECL(OP_LDMIB_W), // OP_LDMIB_W /* 1001 1011 0001 */ TABDECL(OP_LDMIB_W), // OP_LDMIB_W /* 1001 1011 0010 */ TABDECL(OP_LDMIB_W), // OP_LDMIB_W /* 1001 1011 0011 */ TABDECL(OP_LDMIB_W), // OP_LDMIB_W /* 1001 1011 0100 */ TABDECL(OP_LDMIB_W), // OP_LDMIB_W /* 1001 1011 0101 */ TABDECL(OP_LDMIB_W), // OP_LDMIB_W /* 1001 1011 0110 */ TABDECL(OP_LDMIB_W), // OP_LDMIB_W /* 1001 1011 0111 */ TABDECL(OP_LDMIB_W), // OP_LDMIB_W /* 1001 1011 1000 */ TABDECL(OP_LDMIB_W), // OP_LDMIB_W /* 1001 1011 1001 */ TABDECL(OP_LDMIB_W), // OP_LDMIB_W /* 1001 1011 1010 */ TABDECL(OP_LDMIB_W), // OP_LDMIB_W /* 1001 1011 1011 */ TABDECL(OP_LDMIB_W), // OP_LDMIB_W /* 1001 1011 1100 */ TABDECL(OP_LDMIB_W), // OP_LDMIB_W /* 1001 1011 1101 */ TABDECL(OP_LDMIB_W), // OP_LDMIB_W /* 1001 1011 1110 */ TABDECL(OP_LDMIB_W), // OP_LDMIB_W /* 1001 1011 1111 */ TABDECL(OP_LDMIB_W), // OP_LDMIB_W /* 1001 1100 0000 */ TABDECL(OP_STMIB2), // OP_STMIB2 /* 1001 1100 0001 */ TABDECL(OP_STMIB2), // OP_STMIB2 /* 1001 1100 0010 */ TABDECL(OP_STMIB2), // OP_STMIB2 /* 1001 1100 0011 */ TABDECL(OP_STMIB2), // OP_STMIB2 /* 1001 1100 0100 */ TABDECL(OP_STMIB2), // OP_STMIB2 /* 1001 1100 0101 */ TABDECL(OP_STMIB2), // OP_STMIB2 /* 1001 1100 0110 */ TABDECL(OP_STMIB2), // OP_STMIB2 /* 1001 1100 0111 */ TABDECL(OP_STMIB2), // OP_STMIB2 /* 1001 1100 1000 */ TABDECL(OP_STMIB2), // OP_STMIB2 /* 1001 1100 1001 */ TABDECL(OP_STMIB2), // OP_STMIB2 /* 1001 1100 1010 */ TABDECL(OP_STMIB2), // OP_STMIB2 /* 1001 1100 1011 */ TABDECL(OP_STMIB2), // OP_STMIB2 /* 1001 1100 1100 */ TABDECL(OP_STMIB2), // OP_STMIB2 /* 1001 1100 1101 */ TABDECL(OP_STMIB2), // OP_STMIB2 /* 1001 1100 1110 */ TABDECL(OP_STMIB2), // OP_STMIB2 /* 1001 1100 1111 */ TABDECL(OP_STMIB2), // OP_STMIB2 /* 1001 1101 0000 */ TABDECL(OP_LDMIB2), // OP_LDMIB2 /* 1001 1101 0001 */ TABDECL(OP_LDMIB2), // OP_LDMIB2 /* 1001 1101 0010 */ TABDECL(OP_LDMIB2), // OP_LDMIB2 /* 1001 1101 0011 */ TABDECL(OP_LDMIB2), // OP_LDMIB2 /* 1001 1101 0100 */ TABDECL(OP_LDMIB2), // OP_LDMIB2 /* 1001 1101 0101 */ TABDECL(OP_LDMIB2), // OP_LDMIB2 /* 1001 1101 0110 */ TABDECL(OP_LDMIB2), // OP_LDMIB2 /* 1001 1101 0111 */ TABDECL(OP_LDMIB2), // OP_LDMIB2 /* 1001 1101 1000 */ TABDECL(OP_LDMIB2), // OP_LDMIB2 /* 1001 1101 1001 */ TABDECL(OP_LDMIB2), // OP_LDMIB2 /* 1001 1101 1010 */ TABDECL(OP_LDMIB2), // OP_LDMIB2 /* 1001 1101 1011 */ TABDECL(OP_LDMIB2), // OP_LDMIB2 /* 1001 1101 1100 */ TABDECL(OP_LDMIB2), // OP_LDMIB2 /* 1001 1101 1101 */ TABDECL(OP_LDMIB2), // OP_LDMIB2 /* 1001 1101 1110 */ TABDECL(OP_LDMIB2), // OP_LDMIB2 /* 1001 1101 1111 */ TABDECL(OP_LDMIB2), // OP_LDMIB2 /* 1001 1110 0000 */ TABDECL(OP_STMIB2_W), // OP_STMIB2_W /* 1001 1110 0001 */ TABDECL(OP_STMIB2_W), // OP_STMIB2_W /* 1001 1110 0010 */ TABDECL(OP_STMIB2_W), // OP_STMIB2_W /* 1001 1110 0011 */ TABDECL(OP_STMIB2_W), // OP_STMIB2_W /* 1001 1110 0100 */ TABDECL(OP_STMIB2_W), // OP_STMIB2_W /* 1001 1110 0101 */ TABDECL(OP_STMIB2_W), // OP_STMIB2_W /* 1001 1110 0110 */ TABDECL(OP_STMIB2_W), // OP_STMIB2_W /* 1001 1110 0111 */ TABDECL(OP_STMIB2_W), // OP_STMIB2_W /* 1001 1110 1000 */ TABDECL(OP_STMIB2_W), // OP_STMIB2_W /* 1001 1110 1001 */ TABDECL(OP_STMIB2_W), // OP_STMIB2_W /* 1001 1110 1010 */ TABDECL(OP_STMIB2_W), // OP_STMIB2_W /* 1001 1110 1011 */ TABDECL(OP_STMIB2_W), // OP_STMIB2_W /* 1001 1110 1100 */ TABDECL(OP_STMIB2_W), // OP_STMIB2_W /* 1001 1110 1101 */ TABDECL(OP_STMIB2_W), // OP_STMIB2_W /* 1001 1110 1110 */ TABDECL(OP_STMIB2_W), // OP_STMIB2_W /* 1001 1110 1111 */ TABDECL(OP_STMIB2_W), // OP_STMIB2_W /* 1001 1111 0000 */ TABDECL(OP_LDMIB2_W), // OP_LDMIB2_W /* 1001 1111 0001 */ TABDECL(OP_LDMIB2_W), // OP_LDMIB2_W /* 1001 1111 0010 */ TABDECL(OP_LDMIB2_W), // OP_LDMIB2_W /* 1001 1111 0011 */ TABDECL(OP_LDMIB2_W), // OP_LDMIB2_W /* 1001 1111 0100 */ TABDECL(OP_LDMIB2_W), // OP_LDMIB2_W /* 1001 1111 0101 */ TABDECL(OP_LDMIB2_W), // OP_LDMIB2_W /* 1001 1111 0110 */ TABDECL(OP_LDMIB2_W), // OP_LDMIB2_W /* 1001 1111 0111 */ TABDECL(OP_LDMIB2_W), // OP_LDMIB2_W /* 1001 1111 1000 */ TABDECL(OP_LDMIB2_W), // OP_LDMIB2_W /* 1001 1111 1001 */ TABDECL(OP_LDMIB2_W), // OP_LDMIB2_W /* 1001 1111 1010 */ TABDECL(OP_LDMIB2_W), // OP_LDMIB2_W /* 1001 1111 1011 */ TABDECL(OP_LDMIB2_W), // OP_LDMIB2_W /* 1001 1111 1100 */ TABDECL(OP_LDMIB2_W), // OP_LDMIB2_W /* 1001 1111 1101 */ TABDECL(OP_LDMIB2_W), // OP_LDMIB2_W /* 1001 1111 1110 */ TABDECL(OP_LDMIB2_W), // OP_LDMIB2_W /* 1001 1111 1111 */ TABDECL(OP_LDMIB2_W), // OP_LDMIB2_W /* 1010 0000 0000 */ TABDECL(OP_B), // OP_B /* 1010 0000 0001 */ TABDECL(OP_B), // OP_B /* 1010 0000 0010 */ TABDECL(OP_B), // OP_B /* 1010 0000 0011 */ TABDECL(OP_B), // OP_B /* 1010 0000 0100 */ TABDECL(OP_B), // OP_B /* 1010 0000 0101 */ TABDECL(OP_B), // OP_B /* 1010 0000 0110 */ TABDECL(OP_B), // OP_B /* 1010 0000 0111 */ TABDECL(OP_B), // OP_B /* 1010 0000 1000 */ TABDECL(OP_B), // OP_B /* 1010 0000 1001 */ TABDECL(OP_B), // OP_B /* 1010 0000 1010 */ TABDECL(OP_B), // OP_B /* 1010 0000 1011 */ TABDECL(OP_B), // OP_B /* 1010 0000 1100 */ TABDECL(OP_B), // OP_B /* 1010 0000 1101 */ TABDECL(OP_B), // OP_B /* 1010 0000 1110 */ TABDECL(OP_B), // OP_B /* 1010 0000 1111 */ TABDECL(OP_B), // OP_B /* 1010 0001 0000 */ TABDECL(OP_B), // OP_B /* 1010 0001 0001 */ TABDECL(OP_B), // OP_B /* 1010 0001 0010 */ TABDECL(OP_B), // OP_B /* 1010 0001 0011 */ TABDECL(OP_B), // OP_B /* 1010 0001 0100 */ TABDECL(OP_B), // OP_B /* 1010 0001 0101 */ TABDECL(OP_B), // OP_B /* 1010 0001 0110 */ TABDECL(OP_B), // OP_B /* 1010 0001 0111 */ TABDECL(OP_B), // OP_B /* 1010 0001 1000 */ TABDECL(OP_B), // OP_B /* 1010 0001 1001 */ TABDECL(OP_B), // OP_B /* 1010 0001 1010 */ TABDECL(OP_B), // OP_B /* 1010 0001 1011 */ TABDECL(OP_B), // OP_B /* 1010 0001 1100 */ TABDECL(OP_B), // OP_B /* 1010 0001 1101 */ TABDECL(OP_B), // OP_B /* 1010 0001 1110 */ TABDECL(OP_B), // OP_B /* 1010 0001 1111 */ TABDECL(OP_B), // OP_B /* 1010 0010 0000 */ TABDECL(OP_B), // OP_B /* 1010 0010 0001 */ TABDECL(OP_B), // OP_B /* 1010 0010 0010 */ TABDECL(OP_B), // OP_B /* 1010 0010 0011 */ TABDECL(OP_B), // OP_B /* 1010 0010 0100 */ TABDECL(OP_B), // OP_B /* 1010 0010 0101 */ TABDECL(OP_B), // OP_B /* 1010 0010 0110 */ TABDECL(OP_B), // OP_B /* 1010 0010 0111 */ TABDECL(OP_B), // OP_B /* 1010 0010 1000 */ TABDECL(OP_B), // OP_B /* 1010 0010 1001 */ TABDECL(OP_B), // OP_B /* 1010 0010 1010 */ TABDECL(OP_B), // OP_B /* 1010 0010 1011 */ TABDECL(OP_B), // OP_B /* 1010 0010 1100 */ TABDECL(OP_B), // OP_B /* 1010 0010 1101 */ TABDECL(OP_B), // OP_B /* 1010 0010 1110 */ TABDECL(OP_B), // OP_B /* 1010 0010 1111 */ TABDECL(OP_B), // OP_B /* 1010 0011 0000 */ TABDECL(OP_B), // OP_B /* 1010 0011 0001 */ TABDECL(OP_B), // OP_B /* 1010 0011 0010 */ TABDECL(OP_B), // OP_B /* 1010 0011 0011 */ TABDECL(OP_B), // OP_B /* 1010 0011 0100 */ TABDECL(OP_B), // OP_B /* 1010 0011 0101 */ TABDECL(OP_B), // OP_B /* 1010 0011 0110 */ TABDECL(OP_B), // OP_B /* 1010 0011 0111 */ TABDECL(OP_B), // OP_B /* 1010 0011 1000 */ TABDECL(OP_B), // OP_B /* 1010 0011 1001 */ TABDECL(OP_B), // OP_B /* 1010 0011 1010 */ TABDECL(OP_B), // OP_B /* 1010 0011 1011 */ TABDECL(OP_B), // OP_B /* 1010 0011 1100 */ TABDECL(OP_B), // OP_B /* 1010 0011 1101 */ TABDECL(OP_B), // OP_B /* 1010 0011 1110 */ TABDECL(OP_B), // OP_B /* 1010 0011 1111 */ TABDECL(OP_B), // OP_B /* 1010 0100 0000 */ TABDECL(OP_B), // OP_B /* 1010 0100 0001 */ TABDECL(OP_B), // OP_B /* 1010 0100 0010 */ TABDECL(OP_B), // OP_B /* 1010 0100 0011 */ TABDECL(OP_B), // OP_B /* 1010 0100 0100 */ TABDECL(OP_B), // OP_B /* 1010 0100 0101 */ TABDECL(OP_B), // OP_B /* 1010 0100 0110 */ TABDECL(OP_B), // OP_B /* 1010 0100 0111 */ TABDECL(OP_B), // OP_B /* 1010 0100 1000 */ TABDECL(OP_B), // OP_B /* 1010 0100 1001 */ TABDECL(OP_B), // OP_B /* 1010 0100 1010 */ TABDECL(OP_B), // OP_B /* 1010 0100 1011 */ TABDECL(OP_B), // OP_B /* 1010 0100 1100 */ TABDECL(OP_B), // OP_B /* 1010 0100 1101 */ TABDECL(OP_B), // OP_B /* 1010 0100 1110 */ TABDECL(OP_B), // OP_B /* 1010 0100 1111 */ TABDECL(OP_B), // OP_B /* 1010 0101 0000 */ TABDECL(OP_B), // OP_B /* 1010 0101 0001 */ TABDECL(OP_B), // OP_B /* 1010 0101 0010 */ TABDECL(OP_B), // OP_B /* 1010 0101 0011 */ TABDECL(OP_B), // OP_B /* 1010 0101 0100 */ TABDECL(OP_B), // OP_B /* 1010 0101 0101 */ TABDECL(OP_B), // OP_B /* 1010 0101 0110 */ TABDECL(OP_B), // OP_B /* 1010 0101 0111 */ TABDECL(OP_B), // OP_B /* 1010 0101 1000 */ TABDECL(OP_B), // OP_B /* 1010 0101 1001 */ TABDECL(OP_B), // OP_B /* 1010 0101 1010 */ TABDECL(OP_B), // OP_B /* 1010 0101 1011 */ TABDECL(OP_B), // OP_B /* 1010 0101 1100 */ TABDECL(OP_B), // OP_B /* 1010 0101 1101 */ TABDECL(OP_B), // OP_B /* 1010 0101 1110 */ TABDECL(OP_B), // OP_B /* 1010 0101 1111 */ TABDECL(OP_B), // OP_B /* 1010 0110 0000 */ TABDECL(OP_B), // OP_B /* 1010 0110 0001 */ TABDECL(OP_B), // OP_B /* 1010 0110 0010 */ TABDECL(OP_B), // OP_B /* 1010 0110 0011 */ TABDECL(OP_B), // OP_B /* 1010 0110 0100 */ TABDECL(OP_B), // OP_B /* 1010 0110 0101 */ TABDECL(OP_B), // OP_B /* 1010 0110 0110 */ TABDECL(OP_B), // OP_B /* 1010 0110 0111 */ TABDECL(OP_B), // OP_B /* 1010 0110 1000 */ TABDECL(OP_B), // OP_B /* 1010 0110 1001 */ TABDECL(OP_B), // OP_B /* 1010 0110 1010 */ TABDECL(OP_B), // OP_B /* 1010 0110 1011 */ TABDECL(OP_B), // OP_B /* 1010 0110 1100 */ TABDECL(OP_B), // OP_B /* 1010 0110 1101 */ TABDECL(OP_B), // OP_B /* 1010 0110 1110 */ TABDECL(OP_B), // OP_B /* 1010 0110 1111 */ TABDECL(OP_B), // OP_B /* 1010 0111 0000 */ TABDECL(OP_B), // OP_B /* 1010 0111 0001 */ TABDECL(OP_B), // OP_B /* 1010 0111 0010 */ TABDECL(OP_B), // OP_B /* 1010 0111 0011 */ TABDECL(OP_B), // OP_B /* 1010 0111 0100 */ TABDECL(OP_B), // OP_B /* 1010 0111 0101 */ TABDECL(OP_B), // OP_B /* 1010 0111 0110 */ TABDECL(OP_B), // OP_B /* 1010 0111 0111 */ TABDECL(OP_B), // OP_B /* 1010 0111 1000 */ TABDECL(OP_B), // OP_B /* 1010 0111 1001 */ TABDECL(OP_B), // OP_B /* 1010 0111 1010 */ TABDECL(OP_B), // OP_B /* 1010 0111 1011 */ TABDECL(OP_B), // OP_B /* 1010 0111 1100 */ TABDECL(OP_B), // OP_B /* 1010 0111 1101 */ TABDECL(OP_B), // OP_B /* 1010 0111 1110 */ TABDECL(OP_B), // OP_B /* 1010 0111 1111 */ TABDECL(OP_B), // OP_B /* 1010 1000 0000 */ TABDECL(OP_B), // OP_B /* 1010 1000 0001 */ TABDECL(OP_B), // OP_B /* 1010 1000 0010 */ TABDECL(OP_B), // OP_B /* 1010 1000 0011 */ TABDECL(OP_B), // OP_B /* 1010 1000 0100 */ TABDECL(OP_B), // OP_B /* 1010 1000 0101 */ TABDECL(OP_B), // OP_B /* 1010 1000 0110 */ TABDECL(OP_B), // OP_B /* 1010 1000 0111 */ TABDECL(OP_B), // OP_B /* 1010 1000 1000 */ TABDECL(OP_B), // OP_B /* 1010 1000 1001 */ TABDECL(OP_B), // OP_B /* 1010 1000 1010 */ TABDECL(OP_B), // OP_B /* 1010 1000 1011 */ TABDECL(OP_B), // OP_B /* 1010 1000 1100 */ TABDECL(OP_B), // OP_B /* 1010 1000 1101 */ TABDECL(OP_B), // OP_B /* 1010 1000 1110 */ TABDECL(OP_B), // OP_B /* 1010 1000 1111 */ TABDECL(OP_B), // OP_B /* 1010 1001 0000 */ TABDECL(OP_B), // OP_B /* 1010 1001 0001 */ TABDECL(OP_B), // OP_B /* 1010 1001 0010 */ TABDECL(OP_B), // OP_B /* 1010 1001 0011 */ TABDECL(OP_B), // OP_B /* 1010 1001 0100 */ TABDECL(OP_B), // OP_B /* 1010 1001 0101 */ TABDECL(OP_B), // OP_B /* 1010 1001 0110 */ TABDECL(OP_B), // OP_B /* 1010 1001 0111 */ TABDECL(OP_B), // OP_B /* 1010 1001 1000 */ TABDECL(OP_B), // OP_B /* 1010 1001 1001 */ TABDECL(OP_B), // OP_B /* 1010 1001 1010 */ TABDECL(OP_B), // OP_B /* 1010 1001 1011 */ TABDECL(OP_B), // OP_B /* 1010 1001 1100 */ TABDECL(OP_B), // OP_B /* 1010 1001 1101 */ TABDECL(OP_B), // OP_B /* 1010 1001 1110 */ TABDECL(OP_B), // OP_B /* 1010 1001 1111 */ TABDECL(OP_B), // OP_B /* 1010 1010 0000 */ TABDECL(OP_B), // OP_B /* 1010 1010 0001 */ TABDECL(OP_B), // OP_B /* 1010 1010 0010 */ TABDECL(OP_B), // OP_B /* 1010 1010 0011 */ TABDECL(OP_B), // OP_B /* 1010 1010 0100 */ TABDECL(OP_B), // OP_B /* 1010 1010 0101 */ TABDECL(OP_B), // OP_B /* 1010 1010 0110 */ TABDECL(OP_B), // OP_B /* 1010 1010 0111 */ TABDECL(OP_B), // OP_B /* 1010 1010 1000 */ TABDECL(OP_B), // OP_B /* 1010 1010 1001 */ TABDECL(OP_B), // OP_B /* 1010 1010 1010 */ TABDECL(OP_B), // OP_B /* 1010 1010 1011 */ TABDECL(OP_B), // OP_B /* 1010 1010 1100 */ TABDECL(OP_B), // OP_B /* 1010 1010 1101 */ TABDECL(OP_B), // OP_B /* 1010 1010 1110 */ TABDECL(OP_B), // OP_B /* 1010 1010 1111 */ TABDECL(OP_B), // OP_B /* 1010 1011 0000 */ TABDECL(OP_B), // OP_B /* 1010 1011 0001 */ TABDECL(OP_B), // OP_B /* 1010 1011 0010 */ TABDECL(OP_B), // OP_B /* 1010 1011 0011 */ TABDECL(OP_B), // OP_B /* 1010 1011 0100 */ TABDECL(OP_B), // OP_B /* 1010 1011 0101 */ TABDECL(OP_B), // OP_B /* 1010 1011 0110 */ TABDECL(OP_B), // OP_B /* 1010 1011 0111 */ TABDECL(OP_B), // OP_B /* 1010 1011 1000 */ TABDECL(OP_B), // OP_B /* 1010 1011 1001 */ TABDECL(OP_B), // OP_B /* 1010 1011 1010 */ TABDECL(OP_B), // OP_B /* 1010 1011 1011 */ TABDECL(OP_B), // OP_B /* 1010 1011 1100 */ TABDECL(OP_B), // OP_B /* 1010 1011 1101 */ TABDECL(OP_B), // OP_B /* 1010 1011 1110 */ TABDECL(OP_B), // OP_B /* 1010 1011 1111 */ TABDECL(OP_B), // OP_B /* 1010 1100 0000 */ TABDECL(OP_B), // OP_B /* 1010 1100 0001 */ TABDECL(OP_B), // OP_B /* 1010 1100 0010 */ TABDECL(OP_B), // OP_B /* 1010 1100 0011 */ TABDECL(OP_B), // OP_B /* 1010 1100 0100 */ TABDECL(OP_B), // OP_B /* 1010 1100 0101 */ TABDECL(OP_B), // OP_B /* 1010 1100 0110 */ TABDECL(OP_B), // OP_B /* 1010 1100 0111 */ TABDECL(OP_B), // OP_B /* 1010 1100 1000 */ TABDECL(OP_B), // OP_B /* 1010 1100 1001 */ TABDECL(OP_B), // OP_B /* 1010 1100 1010 */ TABDECL(OP_B), // OP_B /* 1010 1100 1011 */ TABDECL(OP_B), // OP_B /* 1010 1100 1100 */ TABDECL(OP_B), // OP_B /* 1010 1100 1101 */ TABDECL(OP_B), // OP_B /* 1010 1100 1110 */ TABDECL(OP_B), // OP_B /* 1010 1100 1111 */ TABDECL(OP_B), // OP_B /* 1010 1101 0000 */ TABDECL(OP_B), // OP_B /* 1010 1101 0001 */ TABDECL(OP_B), // OP_B /* 1010 1101 0010 */ TABDECL(OP_B), // OP_B /* 1010 1101 0011 */ TABDECL(OP_B), // OP_B /* 1010 1101 0100 */ TABDECL(OP_B), // OP_B /* 1010 1101 0101 */ TABDECL(OP_B), // OP_B /* 1010 1101 0110 */ TABDECL(OP_B), // OP_B /* 1010 1101 0111 */ TABDECL(OP_B), // OP_B /* 1010 1101 1000 */ TABDECL(OP_B), // OP_B /* 1010 1101 1001 */ TABDECL(OP_B), // OP_B /* 1010 1101 1010 */ TABDECL(OP_B), // OP_B /* 1010 1101 1011 */ TABDECL(OP_B), // OP_B /* 1010 1101 1100 */ TABDECL(OP_B), // OP_B /* 1010 1101 1101 */ TABDECL(OP_B), // OP_B /* 1010 1101 1110 */ TABDECL(OP_B), // OP_B /* 1010 1101 1111 */ TABDECL(OP_B), // OP_B /* 1010 1110 0000 */ TABDECL(OP_B), // OP_B /* 1010 1110 0001 */ TABDECL(OP_B), // OP_B /* 1010 1110 0010 */ TABDECL(OP_B), // OP_B /* 1010 1110 0011 */ TABDECL(OP_B), // OP_B /* 1010 1110 0100 */ TABDECL(OP_B), // OP_B /* 1010 1110 0101 */ TABDECL(OP_B), // OP_B /* 1010 1110 0110 */ TABDECL(OP_B), // OP_B /* 1010 1110 0111 */ TABDECL(OP_B), // OP_B /* 1010 1110 1000 */ TABDECL(OP_B), // OP_B /* 1010 1110 1001 */ TABDECL(OP_B), // OP_B /* 1010 1110 1010 */ TABDECL(OP_B), // OP_B /* 1010 1110 1011 */ TABDECL(OP_B), // OP_B /* 1010 1110 1100 */ TABDECL(OP_B), // OP_B /* 1010 1110 1101 */ TABDECL(OP_B), // OP_B /* 1010 1110 1110 */ TABDECL(OP_B), // OP_B /* 1010 1110 1111 */ TABDECL(OP_B), // OP_B /* 1010 1111 0000 */ TABDECL(OP_B), // OP_B /* 1010 1111 0001 */ TABDECL(OP_B), // OP_B /* 1010 1111 0010 */ TABDECL(OP_B), // OP_B /* 1010 1111 0011 */ TABDECL(OP_B), // OP_B /* 1010 1111 0100 */ TABDECL(OP_B), // OP_B /* 1010 1111 0101 */ TABDECL(OP_B), // OP_B /* 1010 1111 0110 */ TABDECL(OP_B), // OP_B /* 1010 1111 0111 */ TABDECL(OP_B), // OP_B /* 1010 1111 1000 */ TABDECL(OP_B), // OP_B /* 1010 1111 1001 */ TABDECL(OP_B), // OP_B /* 1010 1111 1010 */ TABDECL(OP_B), // OP_B /* 1010 1111 1011 */ TABDECL(OP_B), // OP_B /* 1010 1111 1100 */ TABDECL(OP_B), // OP_B /* 1010 1111 1101 */ TABDECL(OP_B), // OP_B /* 1010 1111 1110 */ TABDECL(OP_B), // OP_B /* 1010 1111 1111 */ TABDECL(OP_B), // OP_B /* 1011 0000 0000 */ TABDECL(OP_BL), // OP_BL /* 1011 0000 0001 */ TABDECL(OP_BL), // OP_BL /* 1011 0000 0010 */ TABDECL(OP_BL), // OP_BL /* 1011 0000 0011 */ TABDECL(OP_BL), // OP_BL /* 1011 0000 0100 */ TABDECL(OP_BL), // OP_BL /* 1011 0000 0101 */ TABDECL(OP_BL), // OP_BL /* 1011 0000 0110 */ TABDECL(OP_BL), // OP_BL /* 1011 0000 0111 */ TABDECL(OP_BL), // OP_BL /* 1011 0000 1000 */ TABDECL(OP_BL), // OP_BL /* 1011 0000 1001 */ TABDECL(OP_BL), // OP_BL /* 1011 0000 1010 */ TABDECL(OP_BL), // OP_BL /* 1011 0000 1011 */ TABDECL(OP_BL), // OP_BL /* 1011 0000 1100 */ TABDECL(OP_BL), // OP_BL /* 1011 0000 1101 */ TABDECL(OP_BL), // OP_BL /* 1011 0000 1110 */ TABDECL(OP_BL), // OP_BL /* 1011 0000 1111 */ TABDECL(OP_BL), // OP_BL /* 1011 0001 0000 */ TABDECL(OP_BL), // OP_BL /* 1011 0001 0001 */ TABDECL(OP_BL), // OP_BL /* 1011 0001 0010 */ TABDECL(OP_BL), // OP_BL /* 1011 0001 0011 */ TABDECL(OP_BL), // OP_BL /* 1011 0001 0100 */ TABDECL(OP_BL), // OP_BL /* 1011 0001 0101 */ TABDECL(OP_BL), // OP_BL /* 1011 0001 0110 */ TABDECL(OP_BL), // OP_BL /* 1011 0001 0111 */ TABDECL(OP_BL), // OP_BL /* 1011 0001 1000 */ TABDECL(OP_BL), // OP_BL /* 1011 0001 1001 */ TABDECL(OP_BL), // OP_BL /* 1011 0001 1010 */ TABDECL(OP_BL), // OP_BL /* 1011 0001 1011 */ TABDECL(OP_BL), // OP_BL /* 1011 0001 1100 */ TABDECL(OP_BL), // OP_BL /* 1011 0001 1101 */ TABDECL(OP_BL), // OP_BL /* 1011 0001 1110 */ TABDECL(OP_BL), // OP_BL /* 1011 0001 1111 */ TABDECL(OP_BL), // OP_BL /* 1011 0010 0000 */ TABDECL(OP_BL), // OP_BL /* 1011 0010 0001 */ TABDECL(OP_BL), // OP_BL /* 1011 0010 0010 */ TABDECL(OP_BL), // OP_BL /* 1011 0010 0011 */ TABDECL(OP_BL), // OP_BL /* 1011 0010 0100 */ TABDECL(OP_BL), // OP_BL /* 1011 0010 0101 */ TABDECL(OP_BL), // OP_BL /* 1011 0010 0110 */ TABDECL(OP_BL), // OP_BL /* 1011 0010 0111 */ TABDECL(OP_BL), // OP_BL /* 1011 0010 1000 */ TABDECL(OP_BL), // OP_BL /* 1011 0010 1001 */ TABDECL(OP_BL), // OP_BL /* 1011 0010 1010 */ TABDECL(OP_BL), // OP_BL /* 1011 0010 1011 */ TABDECL(OP_BL), // OP_BL /* 1011 0010 1100 */ TABDECL(OP_BL), // OP_BL /* 1011 0010 1101 */ TABDECL(OP_BL), // OP_BL /* 1011 0010 1110 */ TABDECL(OP_BL), // OP_BL /* 1011 0010 1111 */ TABDECL(OP_BL), // OP_BL /* 1011 0011 0000 */ TABDECL(OP_BL), // OP_BL /* 1011 0011 0001 */ TABDECL(OP_BL), // OP_BL /* 1011 0011 0010 */ TABDECL(OP_BL), // OP_BL /* 1011 0011 0011 */ TABDECL(OP_BL), // OP_BL /* 1011 0011 0100 */ TABDECL(OP_BL), // OP_BL /* 1011 0011 0101 */ TABDECL(OP_BL), // OP_BL /* 1011 0011 0110 */ TABDECL(OP_BL), // OP_BL /* 1011 0011 0111 */ TABDECL(OP_BL), // OP_BL /* 1011 0011 1000 */ TABDECL(OP_BL), // OP_BL /* 1011 0011 1001 */ TABDECL(OP_BL), // OP_BL /* 1011 0011 1010 */ TABDECL(OP_BL), // OP_BL /* 1011 0011 1011 */ TABDECL(OP_BL), // OP_BL /* 1011 0011 1100 */ TABDECL(OP_BL), // OP_BL /* 1011 0011 1101 */ TABDECL(OP_BL), // OP_BL /* 1011 0011 1110 */ TABDECL(OP_BL), // OP_BL /* 1011 0011 1111 */ TABDECL(OP_BL), // OP_BL /* 1011 0100 0000 */ TABDECL(OP_BL), // OP_BL /* 1011 0100 0001 */ TABDECL(OP_BL), // OP_BL /* 1011 0100 0010 */ TABDECL(OP_BL), // OP_BL /* 1011 0100 0011 */ TABDECL(OP_BL), // OP_BL /* 1011 0100 0100 */ TABDECL(OP_BL), // OP_BL /* 1011 0100 0101 */ TABDECL(OP_BL), // OP_BL /* 1011 0100 0110 */ TABDECL(OP_BL), // OP_BL /* 1011 0100 0111 */ TABDECL(OP_BL), // OP_BL /* 1011 0100 1000 */ TABDECL(OP_BL), // OP_BL /* 1011 0100 1001 */ TABDECL(OP_BL), // OP_BL /* 1011 0100 1010 */ TABDECL(OP_BL), // OP_BL /* 1011 0100 1011 */ TABDECL(OP_BL), // OP_BL /* 1011 0100 1100 */ TABDECL(OP_BL), // OP_BL /* 1011 0100 1101 */ TABDECL(OP_BL), // OP_BL /* 1011 0100 1110 */ TABDECL(OP_BL), // OP_BL /* 1011 0100 1111 */ TABDECL(OP_BL), // OP_BL /* 1011 0101 0000 */ TABDECL(OP_BL), // OP_BL /* 1011 0101 0001 */ TABDECL(OP_BL), // OP_BL /* 1011 0101 0010 */ TABDECL(OP_BL), // OP_BL /* 1011 0101 0011 */ TABDECL(OP_BL), // OP_BL /* 1011 0101 0100 */ TABDECL(OP_BL), // OP_BL /* 1011 0101 0101 */ TABDECL(OP_BL), // OP_BL /* 1011 0101 0110 */ TABDECL(OP_BL), // OP_BL /* 1011 0101 0111 */ TABDECL(OP_BL), // OP_BL /* 1011 0101 1000 */ TABDECL(OP_BL), // OP_BL /* 1011 0101 1001 */ TABDECL(OP_BL), // OP_BL /* 1011 0101 1010 */ TABDECL(OP_BL), // OP_BL /* 1011 0101 1011 */ TABDECL(OP_BL), // OP_BL /* 1011 0101 1100 */ TABDECL(OP_BL), // OP_BL /* 1011 0101 1101 */ TABDECL(OP_BL), // OP_BL /* 1011 0101 1110 */ TABDECL(OP_BL), // OP_BL /* 1011 0101 1111 */ TABDECL(OP_BL), // OP_BL /* 1011 0110 0000 */ TABDECL(OP_BL), // OP_BL /* 1011 0110 0001 */ TABDECL(OP_BL), // OP_BL /* 1011 0110 0010 */ TABDECL(OP_BL), // OP_BL /* 1011 0110 0011 */ TABDECL(OP_BL), // OP_BL /* 1011 0110 0100 */ TABDECL(OP_BL), // OP_BL /* 1011 0110 0101 */ TABDECL(OP_BL), // OP_BL /* 1011 0110 0110 */ TABDECL(OP_BL), // OP_BL /* 1011 0110 0111 */ TABDECL(OP_BL), // OP_BL /* 1011 0110 1000 */ TABDECL(OP_BL), // OP_BL /* 1011 0110 1001 */ TABDECL(OP_BL), // OP_BL /* 1011 0110 1010 */ TABDECL(OP_BL), // OP_BL /* 1011 0110 1011 */ TABDECL(OP_BL), // OP_BL /* 1011 0110 1100 */ TABDECL(OP_BL), // OP_BL /* 1011 0110 1101 */ TABDECL(OP_BL), // OP_BL /* 1011 0110 1110 */ TABDECL(OP_BL), // OP_BL /* 1011 0110 1111 */ TABDECL(OP_BL), // OP_BL /* 1011 0111 0000 */ TABDECL(OP_BL), // OP_BL /* 1011 0111 0001 */ TABDECL(OP_BL), // OP_BL /* 1011 0111 0010 */ TABDECL(OP_BL), // OP_BL /* 1011 0111 0011 */ TABDECL(OP_BL), // OP_BL /* 1011 0111 0100 */ TABDECL(OP_BL), // OP_BL /* 1011 0111 0101 */ TABDECL(OP_BL), // OP_BL /* 1011 0111 0110 */ TABDECL(OP_BL), // OP_BL /* 1011 0111 0111 */ TABDECL(OP_BL), // OP_BL /* 1011 0111 1000 */ TABDECL(OP_BL), // OP_BL /* 1011 0111 1001 */ TABDECL(OP_BL), // OP_BL /* 1011 0111 1010 */ TABDECL(OP_BL), // OP_BL /* 1011 0111 1011 */ TABDECL(OP_BL), // OP_BL /* 1011 0111 1100 */ TABDECL(OP_BL), // OP_BL /* 1011 0111 1101 */ TABDECL(OP_BL), // OP_BL /* 1011 0111 1110 */ TABDECL(OP_BL), // OP_BL /* 1011 0111 1111 */ TABDECL(OP_BL), // OP_BL /* 1011 1000 0000 */ TABDECL(OP_BL), // OP_BL /* 1011 1000 0001 */ TABDECL(OP_BL), // OP_BL /* 1011 1000 0010 */ TABDECL(OP_BL), // OP_BL /* 1011 1000 0011 */ TABDECL(OP_BL), // OP_BL /* 1011 1000 0100 */ TABDECL(OP_BL), // OP_BL /* 1011 1000 0101 */ TABDECL(OP_BL), // OP_BL /* 1011 1000 0110 */ TABDECL(OP_BL), // OP_BL /* 1011 1000 0111 */ TABDECL(OP_BL), // OP_BL /* 1011 1000 1000 */ TABDECL(OP_BL), // OP_BL /* 1011 1000 1001 */ TABDECL(OP_BL), // OP_BL /* 1011 1000 1010 */ TABDECL(OP_BL), // OP_BL /* 1011 1000 1011 */ TABDECL(OP_BL), // OP_BL /* 1011 1000 1100 */ TABDECL(OP_BL), // OP_BL /* 1011 1000 1101 */ TABDECL(OP_BL), // OP_BL /* 1011 1000 1110 */ TABDECL(OP_BL), // OP_BL /* 1011 1000 1111 */ TABDECL(OP_BL), // OP_BL /* 1011 1001 0000 */ TABDECL(OP_BL), // OP_BL /* 1011 1001 0001 */ TABDECL(OP_BL), // OP_BL /* 1011 1001 0010 */ TABDECL(OP_BL), // OP_BL /* 1011 1001 0011 */ TABDECL(OP_BL), // OP_BL /* 1011 1001 0100 */ TABDECL(OP_BL), // OP_BL /* 1011 1001 0101 */ TABDECL(OP_BL), // OP_BL /* 1011 1001 0110 */ TABDECL(OP_BL), // OP_BL /* 1011 1001 0111 */ TABDECL(OP_BL), // OP_BL /* 1011 1001 1000 */ TABDECL(OP_BL), // OP_BL /* 1011 1001 1001 */ TABDECL(OP_BL), // OP_BL /* 1011 1001 1010 */ TABDECL(OP_BL), // OP_BL /* 1011 1001 1011 */ TABDECL(OP_BL), // OP_BL /* 1011 1001 1100 */ TABDECL(OP_BL), // OP_BL /* 1011 1001 1101 */ TABDECL(OP_BL), // OP_BL /* 1011 1001 1110 */ TABDECL(OP_BL), // OP_BL /* 1011 1001 1111 */ TABDECL(OP_BL), // OP_BL /* 1011 1010 0000 */ TABDECL(OP_BL), // OP_BL /* 1011 1010 0001 */ TABDECL(OP_BL), // OP_BL /* 1011 1010 0010 */ TABDECL(OP_BL), // OP_BL /* 1011 1010 0011 */ TABDECL(OP_BL), // OP_BL /* 1011 1010 0100 */ TABDECL(OP_BL), // OP_BL /* 1011 1010 0101 */ TABDECL(OP_BL), // OP_BL /* 1011 1010 0110 */ TABDECL(OP_BL), // OP_BL /* 1011 1010 0111 */ TABDECL(OP_BL), // OP_BL /* 1011 1010 1000 */ TABDECL(OP_BL), // OP_BL /* 1011 1010 1001 */ TABDECL(OP_BL), // OP_BL /* 1011 1010 1010 */ TABDECL(OP_BL), // OP_BL /* 1011 1010 1011 */ TABDECL(OP_BL), // OP_BL /* 1011 1010 1100 */ TABDECL(OP_BL), // OP_BL /* 1011 1010 1101 */ TABDECL(OP_BL), // OP_BL /* 1011 1010 1110 */ TABDECL(OP_BL), // OP_BL /* 1011 1010 1111 */ TABDECL(OP_BL), // OP_BL /* 1011 1011 0000 */ TABDECL(OP_BL), // OP_BL /* 1011 1011 0001 */ TABDECL(OP_BL), // OP_BL /* 1011 1011 0010 */ TABDECL(OP_BL), // OP_BL /* 1011 1011 0011 */ TABDECL(OP_BL), // OP_BL /* 1011 1011 0100 */ TABDECL(OP_BL), // OP_BL /* 1011 1011 0101 */ TABDECL(OP_BL), // OP_BL /* 1011 1011 0110 */ TABDECL(OP_BL), // OP_BL /* 1011 1011 0111 */ TABDECL(OP_BL), // OP_BL /* 1011 1011 1000 */ TABDECL(OP_BL), // OP_BL /* 1011 1011 1001 */ TABDECL(OP_BL), // OP_BL /* 1011 1011 1010 */ TABDECL(OP_BL), // OP_BL /* 1011 1011 1011 */ TABDECL(OP_BL), // OP_BL /* 1011 1011 1100 */ TABDECL(OP_BL), // OP_BL /* 1011 1011 1101 */ TABDECL(OP_BL), // OP_BL /* 1011 1011 1110 */ TABDECL(OP_BL), // OP_BL /* 1011 1011 1111 */ TABDECL(OP_BL), // OP_BL /* 1011 1100 0000 */ TABDECL(OP_BL), // OP_BL /* 1011 1100 0001 */ TABDECL(OP_BL), // OP_BL /* 1011 1100 0010 */ TABDECL(OP_BL), // OP_BL /* 1011 1100 0011 */ TABDECL(OP_BL), // OP_BL /* 1011 1100 0100 */ TABDECL(OP_BL), // OP_BL /* 1011 1100 0101 */ TABDECL(OP_BL), // OP_BL /* 1011 1100 0110 */ TABDECL(OP_BL), // OP_BL /* 1011 1100 0111 */ TABDECL(OP_BL), // OP_BL /* 1011 1100 1000 */ TABDECL(OP_BL), // OP_BL /* 1011 1100 1001 */ TABDECL(OP_BL), // OP_BL /* 1011 1100 1010 */ TABDECL(OP_BL), // OP_BL /* 1011 1100 1011 */ TABDECL(OP_BL), // OP_BL /* 1011 1100 1100 */ TABDECL(OP_BL), // OP_BL /* 1011 1100 1101 */ TABDECL(OP_BL), // OP_BL /* 1011 1100 1110 */ TABDECL(OP_BL), // OP_BL /* 1011 1100 1111 */ TABDECL(OP_BL), // OP_BL /* 1011 1101 0000 */ TABDECL(OP_BL), // OP_BL /* 1011 1101 0001 */ TABDECL(OP_BL), // OP_BL /* 1011 1101 0010 */ TABDECL(OP_BL), // OP_BL /* 1011 1101 0011 */ TABDECL(OP_BL), // OP_BL /* 1011 1101 0100 */ TABDECL(OP_BL), // OP_BL /* 1011 1101 0101 */ TABDECL(OP_BL), // OP_BL /* 1011 1101 0110 */ TABDECL(OP_BL), // OP_BL /* 1011 1101 0111 */ TABDECL(OP_BL), // OP_BL /* 1011 1101 1000 */ TABDECL(OP_BL), // OP_BL /* 1011 1101 1001 */ TABDECL(OP_BL), // OP_BL /* 1011 1101 1010 */ TABDECL(OP_BL), // OP_BL /* 1011 1101 1011 */ TABDECL(OP_BL), // OP_BL /* 1011 1101 1100 */ TABDECL(OP_BL), // OP_BL /* 1011 1101 1101 */ TABDECL(OP_BL), // OP_BL /* 1011 1101 1110 */ TABDECL(OP_BL), // OP_BL /* 1011 1101 1111 */ TABDECL(OP_BL), // OP_BL /* 1011 1110 0000 */ TABDECL(OP_BL), // OP_BL /* 1011 1110 0001 */ TABDECL(OP_BL), // OP_BL /* 1011 1110 0010 */ TABDECL(OP_BL), // OP_BL /* 1011 1110 0011 */ TABDECL(OP_BL), // OP_BL /* 1011 1110 0100 */ TABDECL(OP_BL), // OP_BL /* 1011 1110 0101 */ TABDECL(OP_BL), // OP_BL /* 1011 1110 0110 */ TABDECL(OP_BL), // OP_BL /* 1011 1110 0111 */ TABDECL(OP_BL), // OP_BL /* 1011 1110 1000 */ TABDECL(OP_BL), // OP_BL /* 1011 1110 1001 */ TABDECL(OP_BL), // OP_BL /* 1011 1110 1010 */ TABDECL(OP_BL), // OP_BL /* 1011 1110 1011 */ TABDECL(OP_BL), // OP_BL /* 1011 1110 1100 */ TABDECL(OP_BL), // OP_BL /* 1011 1110 1101 */ TABDECL(OP_BL), // OP_BL /* 1011 1110 1110 */ TABDECL(OP_BL), // OP_BL /* 1011 1110 1111 */ TABDECL(OP_BL), // OP_BL /* 1011 1111 0000 */ TABDECL(OP_BL), // OP_BL /* 1011 1111 0001 */ TABDECL(OP_BL), // OP_BL /* 1011 1111 0010 */ TABDECL(OP_BL), // OP_BL /* 1011 1111 0011 */ TABDECL(OP_BL), // OP_BL /* 1011 1111 0100 */ TABDECL(OP_BL), // OP_BL /* 1011 1111 0101 */ TABDECL(OP_BL), // OP_BL /* 1011 1111 0110 */ TABDECL(OP_BL), // OP_BL /* 1011 1111 0111 */ TABDECL(OP_BL), // OP_BL /* 1011 1111 1000 */ TABDECL(OP_BL), // OP_BL /* 1011 1111 1001 */ TABDECL(OP_BL), // OP_BL /* 1011 1111 1010 */ TABDECL(OP_BL), // OP_BL /* 1011 1111 1011 */ TABDECL(OP_BL), // OP_BL /* 1011 1111 1100 */ TABDECL(OP_BL), // OP_BL /* 1011 1111 1101 */ TABDECL(OP_BL), // OP_BL /* 1011 1111 1110 */ TABDECL(OP_BL), // OP_BL /* 1011 1111 1111 */ TABDECL(OP_BL), // OP_BL /* 1100 0000 0000 */ TABDECL(OP_STC_OPTION), // OP_STC_OPTION /* 1100 0000 0001 */ TABDECL(OP_STC_OPTION), // OP_STC_OPTION /* 1100 0000 0010 */ TABDECL(OP_STC_OPTION), // OP_STC_OPTION /* 1100 0000 0011 */ TABDECL(OP_STC_OPTION), // OP_STC_OPTION /* 1100 0000 0100 */ TABDECL(OP_STC_OPTION), // OP_STC_OPTION /* 1100 0000 0101 */ TABDECL(OP_STC_OPTION), // OP_STC_OPTION /* 1100 0000 0110 */ TABDECL(OP_STC_OPTION), // OP_STC_OPTION /* 1100 0000 0111 */ TABDECL(OP_STC_OPTION), // OP_STC_OPTION /* 1100 0000 1000 */ TABDECL(OP_STC_OPTION), // OP_STC_OPTION /* 1100 0000 1001 */ TABDECL(OP_STC_OPTION), // OP_STC_OPTION /* 1100 0000 1010 */ TABDECL(OP_STC_OPTION), // OP_STC_OPTION /* 1100 0000 1011 */ TABDECL(OP_STC_OPTION), // OP_STC_OPTION /* 1100 0000 1100 */ TABDECL(OP_STC_OPTION), // OP_STC_OPTION /* 1100 0000 1101 */ TABDECL(OP_STC_OPTION), // OP_STC_OPTION /* 1100 0000 1110 */ TABDECL(OP_STC_OPTION), // OP_STC_OPTION /* 1100 0000 1111 */ TABDECL(OP_STC_OPTION), // OP_STC_OPTION /* 1100 0001 0000 */ TABDECL(OP_LDC_OPTION), // OP_LDC_OPTION /* 1100 0001 0001 */ TABDECL(OP_LDC_OPTION), // OP_LDC_OPTION /* 1100 0001 0010 */ TABDECL(OP_LDC_OPTION), // OP_LDC_OPTION /* 1100 0001 0011 */ TABDECL(OP_LDC_OPTION), // OP_LDC_OPTION /* 1100 0001 0100 */ TABDECL(OP_LDC_OPTION), // OP_LDC_OPTION /* 1100 0001 0101 */ TABDECL(OP_LDC_OPTION), // OP_LDC_OPTION /* 1100 0001 0110 */ TABDECL(OP_LDC_OPTION), // OP_LDC_OPTION /* 1100 0001 0111 */ TABDECL(OP_LDC_OPTION), // OP_LDC_OPTION /* 1100 0001 1000 */ TABDECL(OP_LDC_OPTION), // OP_LDC_OPTION /* 1100 0001 1001 */ TABDECL(OP_LDC_OPTION), // OP_LDC_OPTION /* 1100 0001 1010 */ TABDECL(OP_LDC_OPTION), // OP_LDC_OPTION /* 1100 0001 1011 */ TABDECL(OP_LDC_OPTION), // OP_LDC_OPTION /* 1100 0001 1100 */ TABDECL(OP_LDC_OPTION), // OP_LDC_OPTION /* 1100 0001 1101 */ TABDECL(OP_LDC_OPTION), // OP_LDC_OPTION /* 1100 0001 1110 */ TABDECL(OP_LDC_OPTION), // OP_LDC_OPTION /* 1100 0001 1111 */ TABDECL(OP_LDC_OPTION), // OP_LDC_OPTION /* 1100 0010 0000 */ TABDECL(OP_STC_M_POSTIND), // OP_STC_M_POSTIND /* 1100 0010 0001 */ TABDECL(OP_STC_M_POSTIND), // OP_STC_M_POSTIND /* 1100 0010 0010 */ TABDECL(OP_STC_M_POSTIND), // OP_STC_M_POSTIND /* 1100 0010 0011 */ TABDECL(OP_STC_M_POSTIND), // OP_STC_M_POSTIND /* 1100 0010 0100 */ TABDECL(OP_STC_M_POSTIND), // OP_STC_M_POSTIND /* 1100 0010 0101 */ TABDECL(OP_STC_M_POSTIND), // OP_STC_M_POSTIND /* 1100 0010 0110 */ TABDECL(OP_STC_M_POSTIND), // OP_STC_M_POSTIND /* 1100 0010 0111 */ TABDECL(OP_STC_M_POSTIND), // OP_STC_M_POSTIND /* 1100 0010 1000 */ TABDECL(OP_STC_M_POSTIND), // OP_STC_M_POSTIND /* 1100 0010 1001 */ TABDECL(OP_STC_M_POSTIND), // OP_STC_M_POSTIND /* 1100 0010 1010 */ TABDECL(OP_STC_M_POSTIND), // OP_STC_M_POSTIND /* 1100 0010 1011 */ TABDECL(OP_STC_M_POSTIND), // OP_STC_M_POSTIND /* 1100 0010 1100 */ TABDECL(OP_STC_M_POSTIND), // OP_STC_M_POSTIND /* 1100 0010 1101 */ TABDECL(OP_STC_M_POSTIND), // OP_STC_M_POSTIND /* 1100 0010 1110 */ TABDECL(OP_STC_M_POSTIND), // OP_STC_M_POSTIND /* 1100 0010 1111 */ TABDECL(OP_STC_M_POSTIND), // OP_STC_M_POSTIND /* 1100 0011 0000 */ TABDECL(OP_LDC_M_POSTIND), // OP_LDC_M_POSTIND /* 1100 0011 0001 */ TABDECL(OP_LDC_M_POSTIND), // OP_LDC_M_POSTIND /* 1100 0011 0010 */ TABDECL(OP_LDC_M_POSTIND), // OP_LDC_M_POSTIND /* 1100 0011 0011 */ TABDECL(OP_LDC_M_POSTIND), // OP_LDC_M_POSTIND /* 1100 0011 0100 */ TABDECL(OP_LDC_M_POSTIND), // OP_LDC_M_POSTIND /* 1100 0011 0101 */ TABDECL(OP_LDC_M_POSTIND), // OP_LDC_M_POSTIND /* 1100 0011 0110 */ TABDECL(OP_LDC_M_POSTIND), // OP_LDC_M_POSTIND /* 1100 0011 0111 */ TABDECL(OP_LDC_M_POSTIND), // OP_LDC_M_POSTIND /* 1100 0011 1000 */ TABDECL(OP_LDC_M_POSTIND), // OP_LDC_M_POSTIND /* 1100 0011 1001 */ TABDECL(OP_LDC_M_POSTIND), // OP_LDC_M_POSTIND /* 1100 0011 1010 */ TABDECL(OP_LDC_M_POSTIND), // OP_LDC_M_POSTIND /* 1100 0011 1011 */ TABDECL(OP_LDC_M_POSTIND), // OP_LDC_M_POSTIND /* 1100 0011 1100 */ TABDECL(OP_LDC_M_POSTIND), // OP_LDC_M_POSTIND /* 1100 0011 1101 */ TABDECL(OP_LDC_M_POSTIND), // OP_LDC_M_POSTIND /* 1100 0011 1110 */ TABDECL(OP_LDC_M_POSTIND), // OP_LDC_M_POSTIND /* 1100 0011 1111 */ TABDECL(OP_LDC_M_POSTIND), // OP_LDC_M_POSTIND /* 1100 0100 0000 */ TABDECL(OP_STC_OPTION), // OP_STC_OPTION /* 1100 0100 0001 */ TABDECL(OP_STC_OPTION), // OP_STC_OPTION /* 1100 0100 0010 */ TABDECL(OP_STC_OPTION), // OP_STC_OPTION /* 1100 0100 0011 */ TABDECL(OP_STC_OPTION), // OP_STC_OPTION /* 1100 0100 0100 */ TABDECL(OP_STC_OPTION), // OP_STC_OPTION /* 1100 0100 0101 */ TABDECL(OP_STC_OPTION), // OP_STC_OPTION /* 1100 0100 0110 */ TABDECL(OP_STC_OPTION), // OP_STC_OPTION /* 1100 0100 0111 */ TABDECL(OP_STC_OPTION), // OP_STC_OPTION /* 1100 0100 1000 */ TABDECL(OP_STC_OPTION), // OP_STC_OPTION /* 1100 0100 1001 */ TABDECL(OP_STC_OPTION), // OP_STC_OPTION /* 1100 0100 1010 */ TABDECL(OP_STC_OPTION), // OP_STC_OPTION /* 1100 0100 1011 */ TABDECL(OP_STC_OPTION), // OP_STC_OPTION /* 1100 0100 1100 */ TABDECL(OP_STC_OPTION), // OP_STC_OPTION /* 1100 0100 1101 */ TABDECL(OP_STC_OPTION), // OP_STC_OPTION /* 1100 0100 1110 */ TABDECL(OP_STC_OPTION), // OP_STC_OPTION /* 1100 0100 1111 */ TABDECL(OP_STC_OPTION), // OP_STC_OPTION /* 1100 0101 0000 */ TABDECL(OP_LDC_OPTION), // OP_LDC_OPTION /* 1100 0101 0001 */ TABDECL(OP_LDC_OPTION), // OP_LDC_OPTION /* 1100 0101 0010 */ TABDECL(OP_LDC_OPTION), // OP_LDC_OPTION /* 1100 0101 0011 */ TABDECL(OP_LDC_OPTION), // OP_LDC_OPTION /* 1100 0101 0100 */ TABDECL(OP_LDC_OPTION), // OP_LDC_OPTION /* 1100 0101 0101 */ TABDECL(OP_LDC_OPTION), // OP_LDC_OPTION /* 1100 0101 0110 */ TABDECL(OP_LDC_OPTION), // OP_LDC_OPTION /* 1100 0101 0111 */ TABDECL(OP_LDC_OPTION), // OP_LDC_OPTION /* 1100 0101 1000 */ TABDECL(OP_LDC_OPTION), // OP_LDC_OPTION /* 1100 0101 1001 */ TABDECL(OP_LDC_OPTION), // OP_LDC_OPTION /* 1100 0101 1010 */ TABDECL(OP_LDC_OPTION), // OP_LDC_OPTION /* 1100 0101 1011 */ TABDECL(OP_LDC_OPTION), // OP_LDC_OPTION /* 1100 0101 1100 */ TABDECL(OP_LDC_OPTION), // OP_LDC_OPTION /* 1100 0101 1101 */ TABDECL(OP_LDC_OPTION), // OP_LDC_OPTION /* 1100 0101 1110 */ TABDECL(OP_LDC_OPTION), // OP_LDC_OPTION /* 1100 0101 1111 */ TABDECL(OP_LDC_OPTION), // OP_LDC_OPTION /* 1100 0110 0000 */ TABDECL(OP_STC_M_POSTIND), // OP_STC_M_POSTIND /* 1100 0110 0001 */ TABDECL(OP_STC_M_POSTIND), // OP_STC_M_POSTIND /* 1100 0110 0010 */ TABDECL(OP_STC_M_POSTIND), // OP_STC_M_POSTIND /* 1100 0110 0011 */ TABDECL(OP_STC_M_POSTIND), // OP_STC_M_POSTIND /* 1100 0110 0100 */ TABDECL(OP_STC_M_POSTIND), // OP_STC_M_POSTIND /* 1100 0110 0101 */ TABDECL(OP_STC_M_POSTIND), // OP_STC_M_POSTIND /* 1100 0110 0110 */ TABDECL(OP_STC_M_POSTIND), // OP_STC_M_POSTIND /* 1100 0110 0111 */ TABDECL(OP_STC_M_POSTIND), // OP_STC_M_POSTIND /* 1100 0110 1000 */ TABDECL(OP_STC_M_POSTIND), // OP_STC_M_POSTIND /* 1100 0110 1001 */ TABDECL(OP_STC_M_POSTIND), // OP_STC_M_POSTIND /* 1100 0110 1010 */ TABDECL(OP_STC_M_POSTIND), // OP_STC_M_POSTIND /* 1100 0110 1011 */ TABDECL(OP_STC_M_POSTIND), // OP_STC_M_POSTIND /* 1100 0110 1100 */ TABDECL(OP_STC_M_POSTIND), // OP_STC_M_POSTIND /* 1100 0110 1101 */ TABDECL(OP_STC_M_POSTIND), // OP_STC_M_POSTIND /* 1100 0110 1110 */ TABDECL(OP_STC_M_POSTIND), // OP_STC_M_POSTIND /* 1100 0110 1111 */ TABDECL(OP_STC_M_POSTIND), // OP_STC_M_POSTIND /* 1100 0111 0000 */ TABDECL(OP_LDC_M_POSTIND), // OP_LDC_M_POSTIND /* 1100 0111 0001 */ TABDECL(OP_LDC_M_POSTIND), // OP_LDC_M_POSTIND /* 1100 0111 0010 */ TABDECL(OP_LDC_M_POSTIND), // OP_LDC_M_POSTIND /* 1100 0111 0011 */ TABDECL(OP_LDC_M_POSTIND), // OP_LDC_M_POSTIND /* 1100 0111 0100 */ TABDECL(OP_LDC_M_POSTIND), // OP_LDC_M_POSTIND /* 1100 0111 0101 */ TABDECL(OP_LDC_M_POSTIND), // OP_LDC_M_POSTIND /* 1100 0111 0110 */ TABDECL(OP_LDC_M_POSTIND), // OP_LDC_M_POSTIND /* 1100 0111 0111 */ TABDECL(OP_LDC_M_POSTIND), // OP_LDC_M_POSTIND /* 1100 0111 1000 */ TABDECL(OP_LDC_M_POSTIND), // OP_LDC_M_POSTIND /* 1100 0111 1001 */ TABDECL(OP_LDC_M_POSTIND), // OP_LDC_M_POSTIND /* 1100 0111 1010 */ TABDECL(OP_LDC_M_POSTIND), // OP_LDC_M_POSTIND /* 1100 0111 1011 */ TABDECL(OP_LDC_M_POSTIND), // OP_LDC_M_POSTIND /* 1100 0111 1100 */ TABDECL(OP_LDC_M_POSTIND), // OP_LDC_M_POSTIND /* 1100 0111 1101 */ TABDECL(OP_LDC_M_POSTIND), // OP_LDC_M_POSTIND /* 1100 0111 1110 */ TABDECL(OP_LDC_M_POSTIND), // OP_LDC_M_POSTIND /* 1100 0111 1111 */ TABDECL(OP_LDC_M_POSTIND), // OP_LDC_M_POSTIND /* 1100 1000 0000 */ TABDECL(OP_STC_OPTION), // OP_STC_OPTION /* 1100 1000 0001 */ TABDECL(OP_STC_OPTION), // OP_STC_OPTION /* 1100 1000 0010 */ TABDECL(OP_STC_OPTION), // OP_STC_OPTION /* 1100 1000 0011 */ TABDECL(OP_STC_OPTION), // OP_STC_OPTION /* 1100 1000 0100 */ TABDECL(OP_STC_OPTION), // OP_STC_OPTION /* 1100 1000 0101 */ TABDECL(OP_STC_OPTION), // OP_STC_OPTION /* 1100 1000 0110 */ TABDECL(OP_STC_OPTION), // OP_STC_OPTION /* 1100 1000 0111 */ TABDECL(OP_STC_OPTION), // OP_STC_OPTION /* 1100 1000 1000 */ TABDECL(OP_STC_OPTION), // OP_STC_OPTION /* 1100 1000 1001 */ TABDECL(OP_STC_OPTION), // OP_STC_OPTION /* 1100 1000 1010 */ TABDECL(OP_STC_OPTION), // OP_STC_OPTION /* 1100 1000 1011 */ TABDECL(OP_STC_OPTION), // OP_STC_OPTION /* 1100 1000 1100 */ TABDECL(OP_STC_OPTION), // OP_STC_OPTION /* 1100 1000 1101 */ TABDECL(OP_STC_OPTION), // OP_STC_OPTION /* 1100 1000 1110 */ TABDECL(OP_STC_OPTION), // OP_STC_OPTION /* 1100 1000 1111 */ TABDECL(OP_STC_OPTION), // OP_STC_OPTION /* 1100 1001 0000 */ TABDECL(OP_LDC_OPTION), // OP_LDC_OPTION /* 1100 1001 0001 */ TABDECL(OP_LDC_OPTION), // OP_LDC_OPTION /* 1100 1001 0010 */ TABDECL(OP_LDC_OPTION), // OP_LDC_OPTION /* 1100 1001 0011 */ TABDECL(OP_LDC_OPTION), // OP_LDC_OPTION /* 1100 1001 0100 */ TABDECL(OP_LDC_OPTION), // OP_LDC_OPTION /* 1100 1001 0101 */ TABDECL(OP_LDC_OPTION), // OP_LDC_OPTION /* 1100 1001 0110 */ TABDECL(OP_LDC_OPTION), // OP_LDC_OPTION /* 1100 1001 0111 */ TABDECL(OP_LDC_OPTION), // OP_LDC_OPTION /* 1100 1001 1000 */ TABDECL(OP_LDC_OPTION), // OP_LDC_OPTION /* 1100 1001 1001 */ TABDECL(OP_LDC_OPTION), // OP_LDC_OPTION /* 1100 1001 1010 */ TABDECL(OP_LDC_OPTION), // OP_LDC_OPTION /* 1100 1001 1011 */ TABDECL(OP_LDC_OPTION), // OP_LDC_OPTION /* 1100 1001 1100 */ TABDECL(OP_LDC_OPTION), // OP_LDC_OPTION /* 1100 1001 1101 */ TABDECL(OP_LDC_OPTION), // OP_LDC_OPTION /* 1100 1001 1110 */ TABDECL(OP_LDC_OPTION), // OP_LDC_OPTION /* 1100 1001 1111 */ TABDECL(OP_LDC_OPTION), // OP_LDC_OPTION /* 1100 1010 0000 */ TABDECL(OP_STC_P_POSTIND), // OP_STC_P_POSTIND /* 1100 1010 0001 */ TABDECL(OP_STC_P_POSTIND), // OP_STC_P_POSTIND /* 1100 1010 0010 */ TABDECL(OP_STC_P_POSTIND), // OP_STC_P_POSTIND /* 1100 1010 0011 */ TABDECL(OP_STC_P_POSTIND), // OP_STC_P_POSTIND /* 1100 1010 0100 */ TABDECL(OP_STC_P_POSTIND), // OP_STC_P_POSTIND /* 1100 1010 0101 */ TABDECL(OP_STC_P_POSTIND), // OP_STC_P_POSTIND /* 1100 1010 0110 */ TABDECL(OP_STC_P_POSTIND), // OP_STC_P_POSTIND /* 1100 1010 0111 */ TABDECL(OP_STC_P_POSTIND), // OP_STC_P_POSTIND /* 1100 1010 1000 */ TABDECL(OP_STC_P_POSTIND), // OP_STC_P_POSTIND /* 1100 1010 1001 */ TABDECL(OP_STC_P_POSTIND), // OP_STC_P_POSTIND /* 1100 1010 1010 */ TABDECL(OP_STC_P_POSTIND), // OP_STC_P_POSTIND /* 1100 1010 1011 */ TABDECL(OP_STC_P_POSTIND), // OP_STC_P_POSTIND /* 1100 1010 1100 */ TABDECL(OP_STC_P_POSTIND), // OP_STC_P_POSTIND /* 1100 1010 1101 */ TABDECL(OP_STC_P_POSTIND), // OP_STC_P_POSTIND /* 1100 1010 1110 */ TABDECL(OP_STC_P_POSTIND), // OP_STC_P_POSTIND /* 1100 1010 1111 */ TABDECL(OP_STC_P_POSTIND), // OP_STC_P_POSTIND /* 1100 1011 0000 */ TABDECL(OP_LDC_P_POSTIND), // OP_LDC_P_POSTIND /* 1100 1011 0001 */ TABDECL(OP_LDC_P_POSTIND), // OP_LDC_P_POSTIND /* 1100 1011 0010 */ TABDECL(OP_LDC_P_POSTIND), // OP_LDC_P_POSTIND /* 1100 1011 0011 */ TABDECL(OP_LDC_P_POSTIND), // OP_LDC_P_POSTIND /* 1100 1011 0100 */ TABDECL(OP_LDC_P_POSTIND), // OP_LDC_P_POSTIND /* 1100 1011 0101 */ TABDECL(OP_LDC_P_POSTIND), // OP_LDC_P_POSTIND /* 1100 1011 0110 */ TABDECL(OP_LDC_P_POSTIND), // OP_LDC_P_POSTIND /* 1100 1011 0111 */ TABDECL(OP_LDC_P_POSTIND), // OP_LDC_P_POSTIND /* 1100 1011 1000 */ TABDECL(OP_LDC_P_POSTIND), // OP_LDC_P_POSTIND /* 1100 1011 1001 */ TABDECL(OP_LDC_P_POSTIND), // OP_LDC_P_POSTIND /* 1100 1011 1010 */ TABDECL(OP_LDC_P_POSTIND), // OP_LDC_P_POSTIND /* 1100 1011 1011 */ TABDECL(OP_LDC_P_POSTIND), // OP_LDC_P_POSTIND /* 1100 1011 1100 */ TABDECL(OP_LDC_P_POSTIND), // OP_LDC_P_POSTIND /* 1100 1011 1101 */ TABDECL(OP_LDC_P_POSTIND), // OP_LDC_P_POSTIND /* 1100 1011 1110 */ TABDECL(OP_LDC_P_POSTIND), // OP_LDC_P_POSTIND /* 1100 1011 1111 */ TABDECL(OP_LDC_P_POSTIND), // OP_LDC_P_POSTIND /* 1100 1100 0000 */ TABDECL(OP_STC_OPTION), // OP_STC_OPTION /* 1100 1100 0001 */ TABDECL(OP_STC_OPTION), // OP_STC_OPTION /* 1100 1100 0010 */ TABDECL(OP_STC_OPTION), // OP_STC_OPTION /* 1100 1100 0011 */ TABDECL(OP_STC_OPTION), // OP_STC_OPTION /* 1100 1100 0100 */ TABDECL(OP_STC_OPTION), // OP_STC_OPTION /* 1100 1100 0101 */ TABDECL(OP_STC_OPTION), // OP_STC_OPTION /* 1100 1100 0110 */ TABDECL(OP_STC_OPTION), // OP_STC_OPTION /* 1100 1100 0111 */ TABDECL(OP_STC_OPTION), // OP_STC_OPTION /* 1100 1100 1000 */ TABDECL(OP_STC_OPTION), // OP_STC_OPTION /* 1100 1100 1001 */ TABDECL(OP_STC_OPTION), // OP_STC_OPTION /* 1100 1100 1010 */ TABDECL(OP_STC_OPTION), // OP_STC_OPTION /* 1100 1100 1011 */ TABDECL(OP_STC_OPTION), // OP_STC_OPTION /* 1100 1100 1100 */ TABDECL(OP_STC_OPTION), // OP_STC_OPTION /* 1100 1100 1101 */ TABDECL(OP_STC_OPTION), // OP_STC_OPTION /* 1100 1100 1110 */ TABDECL(OP_STC_OPTION), // OP_STC_OPTION /* 1100 1100 1111 */ TABDECL(OP_STC_OPTION), // OP_STC_OPTION /* 1100 1101 0000 */ TABDECL(OP_LDC_OPTION), // OP_LDC_OPTION /* 1100 1101 0001 */ TABDECL(OP_LDC_OPTION), // OP_LDC_OPTION /* 1100 1101 0010 */ TABDECL(OP_LDC_OPTION), // OP_LDC_OPTION /* 1100 1101 0011 */ TABDECL(OP_LDC_OPTION), // OP_LDC_OPTION /* 1100 1101 0100 */ TABDECL(OP_LDC_OPTION), // OP_LDC_OPTION /* 1100 1101 0101 */ TABDECL(OP_LDC_OPTION), // OP_LDC_OPTION /* 1100 1101 0110 */ TABDECL(OP_LDC_OPTION), // OP_LDC_OPTION /* 1100 1101 0111 */ TABDECL(OP_LDC_OPTION), // OP_LDC_OPTION /* 1100 1101 1000 */ TABDECL(OP_LDC_OPTION), // OP_LDC_OPTION /* 1100 1101 1001 */ TABDECL(OP_LDC_OPTION), // OP_LDC_OPTION /* 1100 1101 1010 */ TABDECL(OP_LDC_OPTION), // OP_LDC_OPTION /* 1100 1101 1011 */ TABDECL(OP_LDC_OPTION), // OP_LDC_OPTION /* 1100 1101 1100 */ TABDECL(OP_LDC_OPTION), // OP_LDC_OPTION /* 1100 1101 1101 */ TABDECL(OP_LDC_OPTION), // OP_LDC_OPTION /* 1100 1101 1110 */ TABDECL(OP_LDC_OPTION), // OP_LDC_OPTION /* 1100 1101 1111 */ TABDECL(OP_LDC_OPTION), // OP_LDC_OPTION /* 1100 1110 0000 */ TABDECL(OP_STC_P_POSTIND), // OP_STC_P_POSTIND /* 1100 1110 0001 */ TABDECL(OP_STC_P_POSTIND), // OP_STC_P_POSTIND /* 1100 1110 0010 */ TABDECL(OP_STC_P_POSTIND), // OP_STC_P_POSTIND /* 1100 1110 0011 */ TABDECL(OP_STC_P_POSTIND), // OP_STC_P_POSTIND /* 1100 1110 0100 */ TABDECL(OP_STC_P_POSTIND), // OP_STC_P_POSTIND /* 1100 1110 0101 */ TABDECL(OP_STC_P_POSTIND), // OP_STC_P_POSTIND /* 1100 1110 0110 */ TABDECL(OP_STC_P_POSTIND), // OP_STC_P_POSTIND /* 1100 1110 0111 */ TABDECL(OP_STC_P_POSTIND), // OP_STC_P_POSTIND /* 1100 1110 1000 */ TABDECL(OP_STC_P_POSTIND), // OP_STC_P_POSTIND /* 1100 1110 1001 */ TABDECL(OP_STC_P_POSTIND), // OP_STC_P_POSTIND /* 1100 1110 1010 */ TABDECL(OP_STC_P_POSTIND), // OP_STC_P_POSTIND /* 1100 1110 1011 */ TABDECL(OP_STC_P_POSTIND), // OP_STC_P_POSTIND /* 1100 1110 1100 */ TABDECL(OP_STC_P_POSTIND), // OP_STC_P_POSTIND /* 1100 1110 1101 */ TABDECL(OP_STC_P_POSTIND), // OP_STC_P_POSTIND /* 1100 1110 1110 */ TABDECL(OP_STC_P_POSTIND), // OP_STC_P_POSTIND /* 1100 1110 1111 */ TABDECL(OP_STC_P_POSTIND), // OP_STC_P_POSTIND /* 1100 1111 0000 */ TABDECL(OP_LDC_P_POSTIND), // OP_LDC_P_POSTIND /* 1100 1111 0001 */ TABDECL(OP_LDC_P_POSTIND), // OP_LDC_P_POSTIND /* 1100 1111 0010 */ TABDECL(OP_LDC_P_POSTIND), // OP_LDC_P_POSTIND /* 1100 1111 0011 */ TABDECL(OP_LDC_P_POSTIND), // OP_LDC_P_POSTIND /* 1100 1111 0100 */ TABDECL(OP_LDC_P_POSTIND), // OP_LDC_P_POSTIND /* 1100 1111 0101 */ TABDECL(OP_LDC_P_POSTIND), // OP_LDC_P_POSTIND /* 1100 1111 0110 */ TABDECL(OP_LDC_P_POSTIND), // OP_LDC_P_POSTIND /* 1100 1111 0111 */ TABDECL(OP_LDC_P_POSTIND), // OP_LDC_P_POSTIND /* 1100 1111 1000 */ TABDECL(OP_LDC_P_POSTIND), // OP_LDC_P_POSTIND /* 1100 1111 1001 */ TABDECL(OP_LDC_P_POSTIND), // OP_LDC_P_POSTIND /* 1100 1111 1010 */ TABDECL(OP_LDC_P_POSTIND), // OP_LDC_P_POSTIND /* 1100 1111 1011 */ TABDECL(OP_LDC_P_POSTIND), // OP_LDC_P_POSTIND /* 1100 1111 1100 */ TABDECL(OP_LDC_P_POSTIND), // OP_LDC_P_POSTIND /* 1100 1111 1101 */ TABDECL(OP_LDC_P_POSTIND), // OP_LDC_P_POSTIND /* 1100 1111 1110 */ TABDECL(OP_LDC_P_POSTIND), // OP_LDC_P_POSTIND /* 1100 1111 1111 */ TABDECL(OP_LDC_P_POSTIND), // OP_LDC_P_POSTIND /* 1101 0000 0000 */ TABDECL(OP_STC_M_IMM_OFF), // OP_STC_M_IMM_OFF /* 1101 0000 0001 */ TABDECL(OP_STC_M_IMM_OFF), // OP_STC_M_IMM_OFF /* 1101 0000 0010 */ TABDECL(OP_STC_M_IMM_OFF), // OP_STC_M_IMM_OFF /* 1101 0000 0011 */ TABDECL(OP_STC_M_IMM_OFF), // OP_STC_M_IMM_OFF /* 1101 0000 0100 */ TABDECL(OP_STC_M_IMM_OFF), // OP_STC_M_IMM_OFF /* 1101 0000 0101 */ TABDECL(OP_STC_M_IMM_OFF), // OP_STC_M_IMM_OFF /* 1101 0000 0110 */ TABDECL(OP_STC_M_IMM_OFF), // OP_STC_M_IMM_OFF /* 1101 0000 0111 */ TABDECL(OP_STC_M_IMM_OFF), // OP_STC_M_IMM_OFF /* 1101 0000 1000 */ TABDECL(OP_STC_M_IMM_OFF), // OP_STC_M_IMM_OFF /* 1101 0000 1001 */ TABDECL(OP_STC_M_IMM_OFF), // OP_STC_M_IMM_OFF /* 1101 0000 1010 */ TABDECL(OP_STC_M_IMM_OFF), // OP_STC_M_IMM_OFF /* 1101 0000 1011 */ TABDECL(OP_STC_M_IMM_OFF), // OP_STC_M_IMM_OFF /* 1101 0000 1100 */ TABDECL(OP_STC_M_IMM_OFF), // OP_STC_M_IMM_OFF /* 1101 0000 1101 */ TABDECL(OP_STC_M_IMM_OFF), // OP_STC_M_IMM_OFF /* 1101 0000 1110 */ TABDECL(OP_STC_M_IMM_OFF), // OP_STC_M_IMM_OFF /* 1101 0000 1111 */ TABDECL(OP_STC_M_IMM_OFF), // OP_STC_M_IMM_OFF /* 1101 0001 0000 */ TABDECL(OP_LDC_M_IMM_OFF), // OP_LDC_M_IMM_OFF /* 1101 0001 0001 */ TABDECL(OP_LDC_M_IMM_OFF), // OP_LDC_M_IMM_OFF /* 1101 0001 0010 */ TABDECL(OP_LDC_M_IMM_OFF), // OP_LDC_M_IMM_OFF /* 1101 0001 0011 */ TABDECL(OP_LDC_M_IMM_OFF), // OP_LDC_M_IMM_OFF /* 1101 0001 0100 */ TABDECL(OP_LDC_M_IMM_OFF), // OP_LDC_M_IMM_OFF /* 1101 0001 0101 */ TABDECL(OP_LDC_M_IMM_OFF), // OP_LDC_M_IMM_OFF /* 1101 0001 0110 */ TABDECL(OP_LDC_M_IMM_OFF), // OP_LDC_M_IMM_OFF /* 1101 0001 0111 */ TABDECL(OP_LDC_M_IMM_OFF), // OP_LDC_M_IMM_OFF /* 1101 0001 1000 */ TABDECL(OP_LDC_M_IMM_OFF), // OP_LDC_M_IMM_OFF /* 1101 0001 1001 */ TABDECL(OP_LDC_M_IMM_OFF), // OP_LDC_M_IMM_OFF /* 1101 0001 1010 */ TABDECL(OP_LDC_M_IMM_OFF), // OP_LDC_M_IMM_OFF /* 1101 0001 1011 */ TABDECL(OP_LDC_M_IMM_OFF), // OP_LDC_M_IMM_OFF /* 1101 0001 1100 */ TABDECL(OP_LDC_M_IMM_OFF), // OP_LDC_M_IMM_OFF /* 1101 0001 1101 */ TABDECL(OP_LDC_M_IMM_OFF), // OP_LDC_M_IMM_OFF /* 1101 0001 1110 */ TABDECL(OP_LDC_M_IMM_OFF), // OP_LDC_M_IMM_OFF /* 1101 0001 1111 */ TABDECL(OP_LDC_M_IMM_OFF), // OP_LDC_M_IMM_OFF /* 1101 0010 0000 */ TABDECL(OP_STC_M_PREIND), // OP_STC_M_PREIND /* 1101 0010 0001 */ TABDECL(OP_STC_M_PREIND), // OP_STC_M_PREIND /* 1101 0010 0010 */ TABDECL(OP_STC_M_PREIND), // OP_STC_M_PREIND /* 1101 0010 0011 */ TABDECL(OP_STC_M_PREIND), // OP_STC_M_PREIND /* 1101 0010 0100 */ TABDECL(OP_STC_M_PREIND), // OP_STC_M_PREIND /* 1101 0010 0101 */ TABDECL(OP_STC_M_PREIND), // OP_STC_M_PREIND /* 1101 0010 0110 */ TABDECL(OP_STC_M_PREIND), // OP_STC_M_PREIND /* 1101 0010 0111 */ TABDECL(OP_STC_M_PREIND), // OP_STC_M_PREIND /* 1101 0010 1000 */ TABDECL(OP_STC_M_PREIND), // OP_STC_M_PREIND /* 1101 0010 1001 */ TABDECL(OP_STC_M_PREIND), // OP_STC_M_PREIND /* 1101 0010 1010 */ TABDECL(OP_STC_M_PREIND), // OP_STC_M_PREIND /* 1101 0010 1011 */ TABDECL(OP_STC_M_PREIND), // OP_STC_M_PREIND /* 1101 0010 1100 */ TABDECL(OP_STC_M_PREIND), // OP_STC_M_PREIND /* 1101 0010 1101 */ TABDECL(OP_STC_M_PREIND), // OP_STC_M_PREIND /* 1101 0010 1110 */ TABDECL(OP_STC_M_PREIND), // OP_STC_M_PREIND /* 1101 0010 1111 */ TABDECL(OP_STC_M_PREIND), // OP_STC_M_PREIND /* 1101 0011 0000 */ TABDECL(OP_LDC_M_PREIND), // OP_LDC_M_PREIND /* 1101 0011 0001 */ TABDECL(OP_LDC_M_PREIND), // OP_LDC_M_PREIND /* 1101 0011 0010 */ TABDECL(OP_LDC_M_PREIND), // OP_LDC_M_PREIND /* 1101 0011 0011 */ TABDECL(OP_LDC_M_PREIND), // OP_LDC_M_PREIND /* 1101 0011 0100 */ TABDECL(OP_LDC_M_PREIND), // OP_LDC_M_PREIND /* 1101 0011 0101 */ TABDECL(OP_LDC_M_PREIND), // OP_LDC_M_PREIND /* 1101 0011 0110 */ TABDECL(OP_LDC_M_PREIND), // OP_LDC_M_PREIND /* 1101 0011 0111 */ TABDECL(OP_LDC_M_PREIND), // OP_LDC_M_PREIND /* 1101 0011 1000 */ TABDECL(OP_LDC_M_PREIND), // OP_LDC_M_PREIND /* 1101 0011 1001 */ TABDECL(OP_LDC_M_PREIND), // OP_LDC_M_PREIND /* 1101 0011 1010 */ TABDECL(OP_LDC_M_PREIND), // OP_LDC_M_PREIND /* 1101 0011 1011 */ TABDECL(OP_LDC_M_PREIND), // OP_LDC_M_PREIND /* 1101 0011 1100 */ TABDECL(OP_LDC_M_PREIND), // OP_LDC_M_PREIND /* 1101 0011 1101 */ TABDECL(OP_LDC_M_PREIND), // OP_LDC_M_PREIND /* 1101 0011 1110 */ TABDECL(OP_LDC_M_PREIND), // OP_LDC_M_PREIND /* 1101 0011 1111 */ TABDECL(OP_LDC_M_PREIND), // OP_LDC_M_PREIND /* 1101 0100 0000 */ TABDECL(OP_STC_M_IMM_OFF), // OP_STC_M_IMM_OFF /* 1101 0100 0001 */ TABDECL(OP_STC_M_IMM_OFF), // OP_STC_M_IMM_OFF /* 1101 0100 0010 */ TABDECL(OP_STC_M_IMM_OFF), // OP_STC_M_IMM_OFF /* 1101 0100 0011 */ TABDECL(OP_STC_M_IMM_OFF), // OP_STC_M_IMM_OFF /* 1101 0100 0100 */ TABDECL(OP_STC_M_IMM_OFF), // OP_STC_M_IMM_OFF /* 1101 0100 0101 */ TABDECL(OP_STC_M_IMM_OFF), // OP_STC_M_IMM_OFF /* 1101 0100 0110 */ TABDECL(OP_STC_M_IMM_OFF), // OP_STC_M_IMM_OFF /* 1101 0100 0111 */ TABDECL(OP_STC_M_IMM_OFF), // OP_STC_M_IMM_OFF /* 1101 0100 1000 */ TABDECL(OP_STC_M_IMM_OFF), // OP_STC_M_IMM_OFF /* 1101 0100 1001 */ TABDECL(OP_STC_M_IMM_OFF), // OP_STC_M_IMM_OFF /* 1101 0100 1010 */ TABDECL(OP_STC_M_IMM_OFF), // OP_STC_M_IMM_OFF /* 1101 0100 1011 */ TABDECL(OP_STC_M_IMM_OFF), // OP_STC_M_IMM_OFF /* 1101 0100 1100 */ TABDECL(OP_STC_M_IMM_OFF), // OP_STC_M_IMM_OFF /* 1101 0100 1101 */ TABDECL(OP_STC_M_IMM_OFF), // OP_STC_M_IMM_OFF /* 1101 0100 1110 */ TABDECL(OP_STC_M_IMM_OFF), // OP_STC_M_IMM_OFF /* 1101 0100 1111 */ TABDECL(OP_STC_M_IMM_OFF), // OP_STC_M_IMM_OFF /* 1101 0101 0000 */ TABDECL(OP_LDC_M_IMM_OFF), // OP_LDC_M_IMM_OFF /* 1101 0101 0001 */ TABDECL(OP_LDC_M_IMM_OFF), // OP_LDC_M_IMM_OFF /* 1101 0101 0010 */ TABDECL(OP_LDC_M_IMM_OFF), // OP_LDC_M_IMM_OFF /* 1101 0101 0011 */ TABDECL(OP_LDC_M_IMM_OFF), // OP_LDC_M_IMM_OFF /* 1101 0101 0100 */ TABDECL(OP_LDC_M_IMM_OFF), // OP_LDC_M_IMM_OFF /* 1101 0101 0101 */ TABDECL(OP_LDC_M_IMM_OFF), // OP_LDC_M_IMM_OFF /* 1101 0101 0110 */ TABDECL(OP_LDC_M_IMM_OFF), // OP_LDC_M_IMM_OFF /* 1101 0101 0111 */ TABDECL(OP_LDC_M_IMM_OFF), // OP_LDC_M_IMM_OFF /* 1101 0101 1000 */ TABDECL(OP_LDC_M_IMM_OFF), // OP_LDC_M_IMM_OFF /* 1101 0101 1001 */ TABDECL(OP_LDC_M_IMM_OFF), // OP_LDC_M_IMM_OFF /* 1101 0101 1010 */ TABDECL(OP_LDC_M_IMM_OFF), // OP_LDC_M_IMM_OFF /* 1101 0101 1011 */ TABDECL(OP_LDC_M_IMM_OFF), // OP_LDC_M_IMM_OFF /* 1101 0101 1100 */ TABDECL(OP_LDC_M_IMM_OFF), // OP_LDC_M_IMM_OFF /* 1101 0101 1101 */ TABDECL(OP_LDC_M_IMM_OFF), // OP_LDC_M_IMM_OFF /* 1101 0101 1110 */ TABDECL(OP_LDC_M_IMM_OFF), // OP_LDC_M_IMM_OFF /* 1101 0101 1111 */ TABDECL(OP_LDC_M_IMM_OFF), // OP_LDC_M_IMM_OFF /* 1101 0110 0000 */ TABDECL(OP_STC_M_PREIND), // OP_STC_M_PREIND /* 1101 0110 0001 */ TABDECL(OP_STC_M_PREIND), // OP_STC_M_PREIND /* 1101 0110 0010 */ TABDECL(OP_STC_M_PREIND), // OP_STC_M_PREIND /* 1101 0110 0011 */ TABDECL(OP_STC_M_PREIND), // OP_STC_M_PREIND /* 1101 0110 0100 */ TABDECL(OP_STC_M_PREIND), // OP_STC_M_PREIND /* 1101 0110 0101 */ TABDECL(OP_STC_M_PREIND), // OP_STC_M_PREIND /* 1101 0110 0110 */ TABDECL(OP_STC_M_PREIND), // OP_STC_M_PREIND /* 1101 0110 0111 */ TABDECL(OP_STC_M_PREIND), // OP_STC_M_PREIND /* 1101 0110 1000 */ TABDECL(OP_STC_M_PREIND), // OP_STC_M_PREIND /* 1101 0110 1001 */ TABDECL(OP_STC_M_PREIND), // OP_STC_M_PREIND /* 1101 0110 1010 */ TABDECL(OP_STC_M_PREIND), // OP_STC_M_PREIND /* 1101 0110 1011 */ TABDECL(OP_STC_M_PREIND), // OP_STC_M_PREIND /* 1101 0110 1100 */ TABDECL(OP_STC_M_PREIND), // OP_STC_M_PREIND /* 1101 0110 1101 */ TABDECL(OP_STC_M_PREIND), // OP_STC_M_PREIND /* 1101 0110 1110 */ TABDECL(OP_STC_M_PREIND), // OP_STC_M_PREIND /* 1101 0110 1111 */ TABDECL(OP_STC_M_PREIND), // OP_STC_M_PREIND /* 1101 0111 0000 */ TABDECL(OP_LDC_M_PREIND), // OP_LDC_M_PREIND /* 1101 0111 0001 */ TABDECL(OP_LDC_M_PREIND), // OP_LDC_M_PREIND /* 1101 0111 0010 */ TABDECL(OP_LDC_M_PREIND), // OP_LDC_M_PREIND /* 1101 0111 0011 */ TABDECL(OP_LDC_M_PREIND), // OP_LDC_M_PREIND /* 1101 0111 0100 */ TABDECL(OP_LDC_M_PREIND), // OP_LDC_M_PREIND /* 1101 0111 0101 */ TABDECL(OP_LDC_M_PREIND), // OP_LDC_M_PREIND /* 1101 0111 0110 */ TABDECL(OP_LDC_M_PREIND), // OP_LDC_M_PREIND /* 1101 0111 0111 */ TABDECL(OP_LDC_M_PREIND), // OP_LDC_M_PREIND /* 1101 0111 1000 */ TABDECL(OP_LDC_M_PREIND), // OP_LDC_M_PREIND /* 1101 0111 1001 */ TABDECL(OP_LDC_M_PREIND), // OP_LDC_M_PREIND /* 1101 0111 1010 */ TABDECL(OP_LDC_M_PREIND), // OP_LDC_M_PREIND /* 1101 0111 1011 */ TABDECL(OP_LDC_M_PREIND), // OP_LDC_M_PREIND /* 1101 0111 1100 */ TABDECL(OP_LDC_M_PREIND), // OP_LDC_M_PREIND /* 1101 0111 1101 */ TABDECL(OP_LDC_M_PREIND), // OP_LDC_M_PREIND /* 1101 0111 1110 */ TABDECL(OP_LDC_M_PREIND), // OP_LDC_M_PREIND /* 1101 0111 1111 */ TABDECL(OP_LDC_M_PREIND), // OP_LDC_M_PREIND /* 1101 1000 0000 */ TABDECL(OP_STC_P_IMM_OFF), // OP_STC_P_IMM_OFF /* 1101 1000 0001 */ TABDECL(OP_STC_P_IMM_OFF), // OP_STC_P_IMM_OFF /* 1101 1000 0010 */ TABDECL(OP_STC_P_IMM_OFF), // OP_STC_P_IMM_OFF /* 1101 1000 0011 */ TABDECL(OP_STC_P_IMM_OFF), // OP_STC_P_IMM_OFF /* 1101 1000 0100 */ TABDECL(OP_STC_P_IMM_OFF), // OP_STC_P_IMM_OFF /* 1101 1000 0101 */ TABDECL(OP_STC_P_IMM_OFF), // OP_STC_P_IMM_OFF /* 1101 1000 0110 */ TABDECL(OP_STC_P_IMM_OFF), // OP_STC_P_IMM_OFF /* 1101 1000 0111 */ TABDECL(OP_STC_P_IMM_OFF), // OP_STC_P_IMM_OFF /* 1101 1000 1000 */ TABDECL(OP_STC_P_IMM_OFF), // OP_STC_P_IMM_OFF /* 1101 1000 1001 */ TABDECL(OP_STC_P_IMM_OFF), // OP_STC_P_IMM_OFF /* 1101 1000 1010 */ TABDECL(OP_STC_P_IMM_OFF), // OP_STC_P_IMM_OFF /* 1101 1000 1011 */ TABDECL(OP_STC_P_IMM_OFF), // OP_STC_P_IMM_OFF /* 1101 1000 1100 */ TABDECL(OP_STC_P_IMM_OFF), // OP_STC_P_IMM_OFF /* 1101 1000 1101 */ TABDECL(OP_STC_P_IMM_OFF), // OP_STC_P_IMM_OFF /* 1101 1000 1110 */ TABDECL(OP_STC_P_IMM_OFF), // OP_STC_P_IMM_OFF /* 1101 1000 1111 */ TABDECL(OP_STC_P_IMM_OFF), // OP_STC_P_IMM_OFF /* 1101 1001 0000 */ TABDECL(OP_LDC_P_IMM_OFF), // OP_LDC_P_IMM_OFF /* 1101 1001 0001 */ TABDECL(OP_LDC_P_IMM_OFF), // OP_LDC_P_IMM_OFF /* 1101 1001 0010 */ TABDECL(OP_LDC_P_IMM_OFF), // OP_LDC_P_IMM_OFF /* 1101 1001 0011 */ TABDECL(OP_LDC_P_IMM_OFF), // OP_LDC_P_IMM_OFF /* 1101 1001 0100 */ TABDECL(OP_LDC_P_IMM_OFF), // OP_LDC_P_IMM_OFF /* 1101 1001 0101 */ TABDECL(OP_LDC_P_IMM_OFF), // OP_LDC_P_IMM_OFF /* 1101 1001 0110 */ TABDECL(OP_LDC_P_IMM_OFF), // OP_LDC_P_IMM_OFF /* 1101 1001 0111 */ TABDECL(OP_LDC_P_IMM_OFF), // OP_LDC_P_IMM_OFF /* 1101 1001 1000 */ TABDECL(OP_LDC_P_IMM_OFF), // OP_LDC_P_IMM_OFF /* 1101 1001 1001 */ TABDECL(OP_LDC_P_IMM_OFF), // OP_LDC_P_IMM_OFF /* 1101 1001 1010 */ TABDECL(OP_LDC_P_IMM_OFF), // OP_LDC_P_IMM_OFF /* 1101 1001 1011 */ TABDECL(OP_LDC_P_IMM_OFF), // OP_LDC_P_IMM_OFF /* 1101 1001 1100 */ TABDECL(OP_LDC_P_IMM_OFF), // OP_LDC_P_IMM_OFF /* 1101 1001 1101 */ TABDECL(OP_LDC_P_IMM_OFF), // OP_LDC_P_IMM_OFF /* 1101 1001 1110 */ TABDECL(OP_LDC_P_IMM_OFF), // OP_LDC_P_IMM_OFF /* 1101 1001 1111 */ TABDECL(OP_LDC_P_IMM_OFF), // OP_LDC_P_IMM_OFF /* 1101 1010 0000 */ TABDECL(OP_STC_P_PREIND), // OP_STC_P_PREIND /* 1101 1010 0001 */ TABDECL(OP_STC_P_PREIND), // OP_STC_P_PREIND /* 1101 1010 0010 */ TABDECL(OP_STC_P_PREIND), // OP_STC_P_PREIND /* 1101 1010 0011 */ TABDECL(OP_STC_P_PREIND), // OP_STC_P_PREIND /* 1101 1010 0100 */ TABDECL(OP_STC_P_PREIND), // OP_STC_P_PREIND /* 1101 1010 0101 */ TABDECL(OP_STC_P_PREIND), // OP_STC_P_PREIND /* 1101 1010 0110 */ TABDECL(OP_STC_P_PREIND), // OP_STC_P_PREIND /* 1101 1010 0111 */ TABDECL(OP_STC_P_PREIND), // OP_STC_P_PREIND /* 1101 1010 1000 */ TABDECL(OP_STC_P_PREIND), // OP_STC_P_PREIND /* 1101 1010 1001 */ TABDECL(OP_STC_P_PREIND), // OP_STC_P_PREIND /* 1101 1010 1010 */ TABDECL(OP_STC_P_PREIND), // OP_STC_P_PREIND /* 1101 1010 1011 */ TABDECL(OP_STC_P_PREIND), // OP_STC_P_PREIND /* 1101 1010 1100 */ TABDECL(OP_STC_P_PREIND), // OP_STC_P_PREIND /* 1101 1010 1101 */ TABDECL(OP_STC_P_PREIND), // OP_STC_P_PREIND /* 1101 1010 1110 */ TABDECL(OP_STC_P_PREIND), // OP_STC_P_PREIND /* 1101 1010 1111 */ TABDECL(OP_STC_P_PREIND), // OP_STC_P_PREIND /* 1101 1011 0000 */ TABDECL(OP_LDC_P_PREIND), // OP_LDC_P_PREIND /* 1101 1011 0001 */ TABDECL(OP_LDC_P_PREIND), // OP_LDC_P_PREIND /* 1101 1011 0010 */ TABDECL(OP_LDC_P_PREIND), // OP_LDC_P_PREIND /* 1101 1011 0011 */ TABDECL(OP_LDC_P_PREIND), // OP_LDC_P_PREIND /* 1101 1011 0100 */ TABDECL(OP_LDC_P_PREIND), // OP_LDC_P_PREIND /* 1101 1011 0101 */ TABDECL(OP_LDC_P_PREIND), // OP_LDC_P_PREIND /* 1101 1011 0110 */ TABDECL(OP_LDC_P_PREIND), // OP_LDC_P_PREIND /* 1101 1011 0111 */ TABDECL(OP_LDC_P_PREIND), // OP_LDC_P_PREIND /* 1101 1011 1000 */ TABDECL(OP_LDC_P_PREIND), // OP_LDC_P_PREIND /* 1101 1011 1001 */ TABDECL(OP_LDC_P_PREIND), // OP_LDC_P_PREIND /* 1101 1011 1010 */ TABDECL(OP_LDC_P_PREIND), // OP_LDC_P_PREIND /* 1101 1011 1011 */ TABDECL(OP_LDC_P_PREIND), // OP_LDC_P_PREIND /* 1101 1011 1100 */ TABDECL(OP_LDC_P_PREIND), // OP_LDC_P_PREIND /* 1101 1011 1101 */ TABDECL(OP_LDC_P_PREIND), // OP_LDC_P_PREIND /* 1101 1011 1110 */ TABDECL(OP_LDC_P_PREIND), // OP_LDC_P_PREIND /* 1101 1011 1111 */ TABDECL(OP_LDC_P_PREIND), // OP_LDC_P_PREIND /* 1101 1100 0000 */ TABDECL(OP_STC_P_IMM_OFF), // OP_STC_P_IMM_OFF /* 1101 1100 0001 */ TABDECL(OP_STC_P_IMM_OFF), // OP_STC_P_IMM_OFF /* 1101 1100 0010 */ TABDECL(OP_STC_P_IMM_OFF), // OP_STC_P_IMM_OFF /* 1101 1100 0011 */ TABDECL(OP_STC_P_IMM_OFF), // OP_STC_P_IMM_OFF /* 1101 1100 0100 */ TABDECL(OP_STC_P_IMM_OFF), // OP_STC_P_IMM_OFF /* 1101 1100 0101 */ TABDECL(OP_STC_P_IMM_OFF), // OP_STC_P_IMM_OFF /* 1101 1100 0110 */ TABDECL(OP_STC_P_IMM_OFF), // OP_STC_P_IMM_OFF /* 1101 1100 0111 */ TABDECL(OP_STC_P_IMM_OFF), // OP_STC_P_IMM_OFF /* 1101 1100 1000 */ TABDECL(OP_STC_P_IMM_OFF), // OP_STC_P_IMM_OFF /* 1101 1100 1001 */ TABDECL(OP_STC_P_IMM_OFF), // OP_STC_P_IMM_OFF /* 1101 1100 1010 */ TABDECL(OP_STC_P_IMM_OFF), // OP_STC_P_IMM_OFF /* 1101 1100 1011 */ TABDECL(OP_STC_P_IMM_OFF), // OP_STC_P_IMM_OFF /* 1101 1100 1100 */ TABDECL(OP_STC_P_IMM_OFF), // OP_STC_P_IMM_OFF /* 1101 1100 1101 */ TABDECL(OP_STC_P_IMM_OFF), // OP_STC_P_IMM_OFF /* 1101 1100 1110 */ TABDECL(OP_STC_P_IMM_OFF), // OP_STC_P_IMM_OFF /* 1101 1100 1111 */ TABDECL(OP_STC_P_IMM_OFF), // OP_STC_P_IMM_OFF /* 1101 1101 0000 */ TABDECL(OP_LDC_P_IMM_OFF), // OP_LDC_P_IMM_OFF /* 1101 1101 0001 */ TABDECL(OP_LDC_P_IMM_OFF), // OP_LDC_P_IMM_OFF /* 1101 1101 0010 */ TABDECL(OP_LDC_P_IMM_OFF), // OP_LDC_P_IMM_OFF /* 1101 1101 0011 */ TABDECL(OP_LDC_P_IMM_OFF), // OP_LDC_P_IMM_OFF /* 1101 1101 0100 */ TABDECL(OP_LDC_P_IMM_OFF), // OP_LDC_P_IMM_OFF /* 1101 1101 0101 */ TABDECL(OP_LDC_P_IMM_OFF), // OP_LDC_P_IMM_OFF /* 1101 1101 0110 */ TABDECL(OP_LDC_P_IMM_OFF), // OP_LDC_P_IMM_OFF /* 1101 1101 0111 */ TABDECL(OP_LDC_P_IMM_OFF), // OP_LDC_P_IMM_OFF /* 1101 1101 1000 */ TABDECL(OP_LDC_P_IMM_OFF), // OP_LDC_P_IMM_OFF /* 1101 1101 1001 */ TABDECL(OP_LDC_P_IMM_OFF), // OP_LDC_P_IMM_OFF /* 1101 1101 1010 */ TABDECL(OP_LDC_P_IMM_OFF), // OP_LDC_P_IMM_OFF /* 1101 1101 1011 */ TABDECL(OP_LDC_P_IMM_OFF), // OP_LDC_P_IMM_OFF /* 1101 1101 1100 */ TABDECL(OP_LDC_P_IMM_OFF), // OP_LDC_P_IMM_OFF /* 1101 1101 1101 */ TABDECL(OP_LDC_P_IMM_OFF), // OP_LDC_P_IMM_OFF /* 1101 1101 1110 */ TABDECL(OP_LDC_P_IMM_OFF), // OP_LDC_P_IMM_OFF /* 1101 1101 1111 */ TABDECL(OP_LDC_P_IMM_OFF), // OP_LDC_P_IMM_OFF /* 1101 1110 0000 */ TABDECL(OP_STC_P_PREIND), // OP_STC_P_PREIND /* 1101 1110 0001 */ TABDECL(OP_STC_P_PREIND), // OP_STC_P_PREIND /* 1101 1110 0010 */ TABDECL(OP_STC_P_PREIND), // OP_STC_P_PREIND /* 1101 1110 0011 */ TABDECL(OP_STC_P_PREIND), // OP_STC_P_PREIND /* 1101 1110 0100 */ TABDECL(OP_STC_P_PREIND), // OP_STC_P_PREIND /* 1101 1110 0101 */ TABDECL(OP_STC_P_PREIND), // OP_STC_P_PREIND /* 1101 1110 0110 */ TABDECL(OP_STC_P_PREIND), // OP_STC_P_PREIND /* 1101 1110 0111 */ TABDECL(OP_STC_P_PREIND), // OP_STC_P_PREIND /* 1101 1110 1000 */ TABDECL(OP_STC_P_PREIND), // OP_STC_P_PREIND /* 1101 1110 1001 */ TABDECL(OP_STC_P_PREIND), // OP_STC_P_PREIND /* 1101 1110 1010 */ TABDECL(OP_STC_P_PREIND), // OP_STC_P_PREIND /* 1101 1110 1011 */ TABDECL(OP_STC_P_PREIND), // OP_STC_P_PREIND /* 1101 1110 1100 */ TABDECL(OP_STC_P_PREIND), // OP_STC_P_PREIND /* 1101 1110 1101 */ TABDECL(OP_STC_P_PREIND), // OP_STC_P_PREIND /* 1101 1110 1110 */ TABDECL(OP_STC_P_PREIND), // OP_STC_P_PREIND /* 1101 1110 1111 */ TABDECL(OP_STC_P_PREIND), // OP_STC_P_PREIND /* 1101 1111 0000 */ TABDECL(OP_LDC_P_PREIND), // OP_LDC_P_PREIND /* 1101 1111 0001 */ TABDECL(OP_LDC_P_PREIND), // OP_LDC_P_PREIND /* 1101 1111 0010 */ TABDECL(OP_LDC_P_PREIND), // OP_LDC_P_PREIND /* 1101 1111 0011 */ TABDECL(OP_LDC_P_PREIND), // OP_LDC_P_PREIND /* 1101 1111 0100 */ TABDECL(OP_LDC_P_PREIND), // OP_LDC_P_PREIND /* 1101 1111 0101 */ TABDECL(OP_LDC_P_PREIND), // OP_LDC_P_PREIND /* 1101 1111 0110 */ TABDECL(OP_LDC_P_PREIND), // OP_LDC_P_PREIND /* 1101 1111 0111 */ TABDECL(OP_LDC_P_PREIND), // OP_LDC_P_PREIND /* 1101 1111 1000 */ TABDECL(OP_LDC_P_PREIND), // OP_LDC_P_PREIND /* 1101 1111 1001 */ TABDECL(OP_LDC_P_PREIND), // OP_LDC_P_PREIND /* 1101 1111 1010 */ TABDECL(OP_LDC_P_PREIND), // OP_LDC_P_PREIND /* 1101 1111 1011 */ TABDECL(OP_LDC_P_PREIND), // OP_LDC_P_PREIND /* 1101 1111 1100 */ TABDECL(OP_LDC_P_PREIND), // OP_LDC_P_PREIND /* 1101 1111 1101 */ TABDECL(OP_LDC_P_PREIND), // OP_LDC_P_PREIND /* 1101 1111 1110 */ TABDECL(OP_LDC_P_PREIND), // OP_LDC_P_PREIND /* 1101 1111 1111 */ TABDECL(OP_LDC_P_PREIND), // OP_LDC_P_PREIND /* 1110 0000 0000 */ TABDECL(OP_CDP), // OP_CDP /* 1110 0000 0001 */ TABDECL(OP_MCR), // OP_MCR /* 1110 0000 0010 */ TABDECL(OP_CDP), // OP_CDP /* 1110 0000 0011 */ TABDECL(OP_MCR), // OP_MCR /* 1110 0000 0100 */ TABDECL(OP_CDP), // OP_CDP /* 1110 0000 0101 */ TABDECL(OP_MCR), // OP_MCR /* 1110 0000 0110 */ TABDECL(OP_CDP), // OP_CDP /* 1110 0000 0111 */ TABDECL(OP_MCR), // OP_MCR /* 1110 0000 1000 */ TABDECL(OP_CDP), // OP_CDP /* 1110 0000 1001 */ TABDECL(OP_MCR), // OP_MCR /* 1110 0000 1010 */ TABDECL(OP_CDP), // OP_CDP /* 1110 0000 1011 */ TABDECL(OP_MCR), // OP_MCR /* 1110 0000 1100 */ TABDECL(OP_CDP), // OP_CDP /* 1110 0000 1101 */ TABDECL(OP_MCR), // OP_MCR /* 1110 0000 1110 */ TABDECL(OP_CDP), // OP_CDP /* 1110 0000 1111 */ TABDECL(OP_MCR), // OP_MCR /* 1110 0001 0000 */ TABDECL(OP_CDP), // OP_CDP /* 1110 0001 0001 */ TABDECL(OP_MRC), // OP_MRC /* 1110 0001 0010 */ TABDECL(OP_CDP), // OP_CDP /* 1110 0001 0011 */ TABDECL(OP_MRC), // OP_MRC /* 1110 0001 0100 */ TABDECL(OP_CDP), // OP_CDP /* 1110 0001 0101 */ TABDECL(OP_MRC), // OP_MRC /* 1110 0001 0110 */ TABDECL(OP_CDP), // OP_CDP /* 1110 0001 0111 */ TABDECL(OP_MRC), // OP_MRC /* 1110 0001 1000 */ TABDECL(OP_CDP), // OP_CDP /* 1110 0001 1001 */ TABDECL(OP_MRC), // OP_MRC /* 1110 0001 1010 */ TABDECL(OP_CDP), // OP_CDP /* 1110 0001 1011 */ TABDECL(OP_MRC), // OP_MRC /* 1110 0001 1100 */ TABDECL(OP_CDP), // OP_CDP /* 1110 0001 1101 */ TABDECL(OP_MRC), // OP_MRC /* 1110 0001 1110 */ TABDECL(OP_CDP), // OP_CDP /* 1110 0001 1111 */ TABDECL(OP_MRC), // OP_MRC /* 1110 0010 0000 */ TABDECL(OP_CDP), // OP_CDP /* 1110 0010 0001 */ TABDECL(OP_MCR), // OP_MCR /* 1110 0010 0010 */ TABDECL(OP_CDP), // OP_CDP /* 1110 0010 0011 */ TABDECL(OP_MCR), // OP_MCR /* 1110 0010 0100 */ TABDECL(OP_CDP), // OP_CDP /* 1110 0010 0101 */ TABDECL(OP_MCR), // OP_MCR /* 1110 0010 0110 */ TABDECL(OP_CDP), // OP_CDP /* 1110 0010 0111 */ TABDECL(OP_MCR), // OP_MCR /* 1110 0010 1000 */ TABDECL(OP_CDP), // OP_CDP /* 1110 0010 1001 */ TABDECL(OP_MCR), // OP_MCR /* 1110 0010 1010 */ TABDECL(OP_CDP), // OP_CDP /* 1110 0010 1011 */ TABDECL(OP_MCR), // OP_MCR /* 1110 0010 1100 */ TABDECL(OP_CDP), // OP_CDP /* 1110 0010 1101 */ TABDECL(OP_MCR), // OP_MCR /* 1110 0010 1110 */ TABDECL(OP_CDP), // OP_CDP /* 1110 0010 1111 */ TABDECL(OP_MCR), // OP_MCR /* 1110 0011 0000 */ TABDECL(OP_CDP), // OP_CDP /* 1110 0011 0001 */ TABDECL(OP_MRC), // OP_MRC /* 1110 0011 0010 */ TABDECL(OP_CDP), // OP_CDP /* 1110 0011 0011 */ TABDECL(OP_MRC), // OP_MRC /* 1110 0011 0100 */ TABDECL(OP_CDP), // OP_CDP /* 1110 0011 0101 */ TABDECL(OP_MRC), // OP_MRC /* 1110 0011 0110 */ TABDECL(OP_CDP), // OP_CDP /* 1110 0011 0111 */ TABDECL(OP_MRC), // OP_MRC /* 1110 0011 1000 */ TABDECL(OP_CDP), // OP_CDP /* 1110 0011 1001 */ TABDECL(OP_MRC), // OP_MRC /* 1110 0011 1010 */ TABDECL(OP_CDP), // OP_CDP /* 1110 0011 1011 */ TABDECL(OP_MRC), // OP_MRC /* 1110 0011 1100 */ TABDECL(OP_CDP), // OP_CDP /* 1110 0011 1101 */ TABDECL(OP_MRC), // OP_MRC /* 1110 0011 1110 */ TABDECL(OP_CDP), // OP_CDP /* 1110 0011 1111 */ TABDECL(OP_MRC), // OP_MRC /* 1110 0100 0000 */ TABDECL(OP_CDP), // OP_CDP /* 1110 0100 0001 */ TABDECL(OP_MCR), // OP_MCR /* 1110 0100 0010 */ TABDECL(OP_CDP), // OP_CDP /* 1110 0100 0011 */ TABDECL(OP_MCR), // OP_MCR /* 1110 0100 0100 */ TABDECL(OP_CDP), // OP_CDP /* 1110 0100 0101 */ TABDECL(OP_MCR), // OP_MCR /* 1110 0100 0110 */ TABDECL(OP_CDP), // OP_CDP /* 1110 0100 0111 */ TABDECL(OP_MCR), // OP_MCR /* 1110 0100 1000 */ TABDECL(OP_CDP), // OP_CDP /* 1110 0100 1001 */ TABDECL(OP_MCR), // OP_MCR /* 1110 0100 1010 */ TABDECL(OP_CDP), // OP_CDP /* 1110 0100 1011 */ TABDECL(OP_MCR), // OP_MCR /* 1110 0100 1100 */ TABDECL(OP_CDP), // OP_CDP /* 1110 0100 1101 */ TABDECL(OP_MCR), // OP_MCR /* 1110 0100 1110 */ TABDECL(OP_CDP), // OP_CDP /* 1110 0100 1111 */ TABDECL(OP_MCR), // OP_MCR /* 1110 0101 0000 */ TABDECL(OP_CDP), // OP_CDP /* 1110 0101 0001 */ TABDECL(OP_MRC), // OP_MRC /* 1110 0101 0010 */ TABDECL(OP_CDP), // OP_CDP /* 1110 0101 0011 */ TABDECL(OP_MRC), // OP_MRC /* 1110 0101 0100 */ TABDECL(OP_CDP), // OP_CDP /* 1110 0101 0101 */ TABDECL(OP_MRC), // OP_MRC /* 1110 0101 0110 */ TABDECL(OP_CDP), // OP_CDP /* 1110 0101 0111 */ TABDECL(OP_MRC), // OP_MRC /* 1110 0101 1000 */ TABDECL(OP_CDP), // OP_CDP /* 1110 0101 1001 */ TABDECL(OP_MRC), // OP_MRC /* 1110 0101 1010 */ TABDECL(OP_CDP), // OP_CDP /* 1110 0101 1011 */ TABDECL(OP_MRC), // OP_MRC /* 1110 0101 1100 */ TABDECL(OP_CDP), // OP_CDP /* 1110 0101 1101 */ TABDECL(OP_MRC), // OP_MRC /* 1110 0101 1110 */ TABDECL(OP_CDP), // OP_CDP /* 1110 0101 1111 */ TABDECL(OP_MRC), // OP_MRC /* 1110 0110 0000 */ TABDECL(OP_CDP), // OP_CDP /* 1110 0110 0001 */ TABDECL(OP_MCR), // OP_MCR /* 1110 0110 0010 */ TABDECL(OP_CDP), // OP_CDP /* 1110 0110 0011 */ TABDECL(OP_MCR), // OP_MCR /* 1110 0110 0100 */ TABDECL(OP_CDP), // OP_CDP /* 1110 0110 0101 */ TABDECL(OP_MCR), // OP_MCR /* 1110 0110 0110 */ TABDECL(OP_CDP), // OP_CDP /* 1110 0110 0111 */ TABDECL(OP_MCR), // OP_MCR /* 1110 0110 1000 */ TABDECL(OP_CDP), // OP_CDP /* 1110 0110 1001 */ TABDECL(OP_MCR), // OP_MCR /* 1110 0110 1010 */ TABDECL(OP_CDP), // OP_CDP /* 1110 0110 1011 */ TABDECL(OP_MCR), // OP_MCR /* 1110 0110 1100 */ TABDECL(OP_CDP), // OP_CDP /* 1110 0110 1101 */ TABDECL(OP_MCR), // OP_MCR /* 1110 0110 1110 */ TABDECL(OP_CDP), // OP_CDP /* 1110 0110 1111 */ TABDECL(OP_MCR), // OP_MCR /* 1110 0111 0000 */ TABDECL(OP_CDP), // OP_CDP /* 1110 0111 0001 */ TABDECL(OP_MRC), // OP_MRC /* 1110 0111 0010 */ TABDECL(OP_CDP), // OP_CDP /* 1110 0111 0011 */ TABDECL(OP_MRC), // OP_MRC /* 1110 0111 0100 */ TABDECL(OP_CDP), // OP_CDP /* 1110 0111 0101 */ TABDECL(OP_MRC), // OP_MRC /* 1110 0111 0110 */ TABDECL(OP_CDP), // OP_CDP /* 1110 0111 0111 */ TABDECL(OP_MRC), // OP_MRC /* 1110 0111 1000 */ TABDECL(OP_CDP), // OP_CDP /* 1110 0111 1001 */ TABDECL(OP_MRC), // OP_MRC /* 1110 0111 1010 */ TABDECL(OP_CDP), // OP_CDP /* 1110 0111 1011 */ TABDECL(OP_MRC), // OP_MRC /* 1110 0111 1100 */ TABDECL(OP_CDP), // OP_CDP /* 1110 0111 1101 */ TABDECL(OP_MRC), // OP_MRC /* 1110 0111 1110 */ TABDECL(OP_CDP), // OP_CDP /* 1110 0111 1111 */ TABDECL(OP_MRC), // OP_MRC /* 1110 1000 0000 */ TABDECL(OP_CDP), // OP_CDP /* 1110 1000 0001 */ TABDECL(OP_MCR), // OP_MCR /* 1110 1000 0010 */ TABDECL(OP_CDP), // OP_CDP /* 1110 1000 0011 */ TABDECL(OP_MCR), // OP_MCR /* 1110 1000 0100 */ TABDECL(OP_CDP), // OP_CDP /* 1110 1000 0101 */ TABDECL(OP_MCR), // OP_MCR /* 1110 1000 0110 */ TABDECL(OP_CDP), // OP_CDP /* 1110 1000 0111 */ TABDECL(OP_MCR), // OP_MCR /* 1110 1000 1000 */ TABDECL(OP_CDP), // OP_CDP /* 1110 1000 1001 */ TABDECL(OP_MCR), // OP_MCR /* 1110 1000 1010 */ TABDECL(OP_CDP), // OP_CDP /* 1110 1000 1011 */ TABDECL(OP_MCR), // OP_MCR /* 1110 1000 1100 */ TABDECL(OP_CDP), // OP_CDP /* 1110 1000 1101 */ TABDECL(OP_MCR), // OP_MCR /* 1110 1000 1110 */ TABDECL(OP_CDP), // OP_CDP /* 1110 1000 1111 */ TABDECL(OP_MCR), // OP_MCR /* 1110 1001 0000 */ TABDECL(OP_CDP), // OP_CDP /* 1110 1001 0001 */ TABDECL(OP_MRC), // OP_MRC /* 1110 1001 0010 */ TABDECL(OP_CDP), // OP_CDP /* 1110 1001 0011 */ TABDECL(OP_MRC), // OP_MRC /* 1110 1001 0100 */ TABDECL(OP_CDP), // OP_CDP /* 1110 1001 0101 */ TABDECL(OP_MRC), // OP_MRC /* 1110 1001 0110 */ TABDECL(OP_CDP), // OP_CDP /* 1110 1001 0111 */ TABDECL(OP_MRC), // OP_MRC /* 1110 1001 1000 */ TABDECL(OP_CDP), // OP_CDP /* 1110 1001 1001 */ TABDECL(OP_MRC), // OP_MRC /* 1110 1001 1010 */ TABDECL(OP_CDP), // OP_CDP /* 1110 1001 1011 */ TABDECL(OP_MRC), // OP_MRC /* 1110 1001 1100 */ TABDECL(OP_CDP), // OP_CDP /* 1110 1001 1101 */ TABDECL(OP_MRC), // OP_MRC /* 1110 1001 1110 */ TABDECL(OP_CDP), // OP_CDP /* 1110 1001 1111 */ TABDECL(OP_MRC), // OP_MRC /* 1110 1010 0000 */ TABDECL(OP_CDP), // OP_CDP /* 1110 1010 0001 */ TABDECL(OP_MCR), // OP_MCR /* 1110 1010 0010 */ TABDECL(OP_CDP), // OP_CDP /* 1110 1010 0011 */ TABDECL(OP_MCR), // OP_MCR /* 1110 1010 0100 */ TABDECL(OP_CDP), // OP_CDP /* 1110 1010 0101 */ TABDECL(OP_MCR), // OP_MCR /* 1110 1010 0110 */ TABDECL(OP_CDP), // OP_CDP /* 1110 1010 0111 */ TABDECL(OP_MCR), // OP_MCR /* 1110 1010 1000 */ TABDECL(OP_CDP), // OP_CDP /* 1110 1010 1001 */ TABDECL(OP_MCR), // OP_MCR /* 1110 1010 1010 */ TABDECL(OP_CDP), // OP_CDP /* 1110 1010 1011 */ TABDECL(OP_MCR), // OP_MCR /* 1110 1010 1100 */ TABDECL(OP_CDP), // OP_CDP /* 1110 1010 1101 */ TABDECL(OP_MCR), // OP_MCR /* 1110 1010 1110 */ TABDECL(OP_CDP), // OP_CDP /* 1110 1010 1111 */ TABDECL(OP_MCR), // OP_MCR /* 1110 1011 0000 */ TABDECL(OP_CDP), // OP_CDP /* 1110 1011 0001 */ TABDECL(OP_MRC), // OP_MRC /* 1110 1011 0010 */ TABDECL(OP_CDP), // OP_CDP /* 1110 1011 0011 */ TABDECL(OP_MRC), // OP_MRC /* 1110 1011 0100 */ TABDECL(OP_CDP), // OP_CDP /* 1110 1011 0101 */ TABDECL(OP_MRC), // OP_MRC /* 1110 1011 0110 */ TABDECL(OP_CDP), // OP_CDP /* 1110 1011 0111 */ TABDECL(OP_MRC), // OP_MRC /* 1110 1011 1000 */ TABDECL(OP_CDP), // OP_CDP /* 1110 1011 1001 */ TABDECL(OP_MRC), // OP_MRC /* 1110 1011 1010 */ TABDECL(OP_CDP), // OP_CDP /* 1110 1011 1011 */ TABDECL(OP_MRC), // OP_MRC /* 1110 1011 1100 */ TABDECL(OP_CDP), // OP_CDP /* 1110 1011 1101 */ TABDECL(OP_MRC), // OP_MRC /* 1110 1011 1110 */ TABDECL(OP_CDP), // OP_CDP /* 1110 1011 1111 */ TABDECL(OP_MRC), // OP_MRC /* 1110 1100 0000 */ TABDECL(OP_CDP), // OP_CDP /* 1110 1100 0001 */ TABDECL(OP_MCR), // OP_MCR /* 1110 1100 0010 */ TABDECL(OP_CDP), // OP_CDP /* 1110 1100 0011 */ TABDECL(OP_MCR), // OP_MCR /* 1110 1100 0100 */ TABDECL(OP_CDP), // OP_CDP /* 1110 1100 0101 */ TABDECL(OP_MCR), // OP_MCR /* 1110 1100 0110 */ TABDECL(OP_CDP), // OP_CDP /* 1110 1100 0111 */ TABDECL(OP_MCR), // OP_MCR /* 1110 1100 1000 */ TABDECL(OP_CDP), // OP_CDP /* 1110 1100 1001 */ TABDECL(OP_MCR), // OP_MCR /* 1110 1100 1010 */ TABDECL(OP_CDP), // OP_CDP /* 1110 1100 1011 */ TABDECL(OP_MCR), // OP_MCR /* 1110 1100 1100 */ TABDECL(OP_CDP), // OP_CDP /* 1110 1100 1101 */ TABDECL(OP_MCR), // OP_MCR /* 1110 1100 1110 */ TABDECL(OP_CDP), // OP_CDP /* 1110 1100 1111 */ TABDECL(OP_MCR), // OP_MCR /* 1110 1101 0000 */ TABDECL(OP_CDP), // OP_CDP /* 1110 1101 0001 */ TABDECL(OP_MRC), // OP_MRC /* 1110 1101 0010 */ TABDECL(OP_CDP), // OP_CDP /* 1110 1101 0011 */ TABDECL(OP_MRC), // OP_MRC /* 1110 1101 0100 */ TABDECL(OP_CDP), // OP_CDP /* 1110 1101 0101 */ TABDECL(OP_MRC), // OP_MRC /* 1110 1101 0110 */ TABDECL(OP_CDP), // OP_CDP /* 1110 1101 0111 */ TABDECL(OP_MRC), // OP_MRC /* 1110 1101 1000 */ TABDECL(OP_CDP), // OP_CDP /* 1110 1101 1001 */ TABDECL(OP_MRC), // OP_MRC /* 1110 1101 1010 */ TABDECL(OP_CDP), // OP_CDP /* 1110 1101 1011 */ TABDECL(OP_MRC), // OP_MRC /* 1110 1101 1100 */ TABDECL(OP_CDP), // OP_CDP /* 1110 1101 1101 */ TABDECL(OP_MRC), // OP_MRC /* 1110 1101 1110 */ TABDECL(OP_CDP), // OP_CDP /* 1110 1101 1111 */ TABDECL(OP_MRC), // OP_MRC /* 1110 1110 0000 */ TABDECL(OP_CDP), // OP_CDP /* 1110 1110 0001 */ TABDECL(OP_MCR), // OP_MCR /* 1110 1110 0010 */ TABDECL(OP_CDP), // OP_CDP /* 1110 1110 0011 */ TABDECL(OP_MCR), // OP_MCR /* 1110 1110 0100 */ TABDECL(OP_CDP), // OP_CDP /* 1110 1110 0101 */ TABDECL(OP_MCR), // OP_MCR /* 1110 1110 0110 */ TABDECL(OP_CDP), // OP_CDP /* 1110 1110 0111 */ TABDECL(OP_MCR), // OP_MCR /* 1110 1110 1000 */ TABDECL(OP_CDP), // OP_CDP /* 1110 1110 1001 */ TABDECL(OP_MCR), // OP_MCR /* 1110 1110 1010 */ TABDECL(OP_CDP), // OP_CDP /* 1110 1110 1011 */ TABDECL(OP_MCR), // OP_MCR /* 1110 1110 1100 */ TABDECL(OP_CDP), // OP_CDP /* 1110 1110 1101 */ TABDECL(OP_MCR), // OP_MCR /* 1110 1110 1110 */ TABDECL(OP_CDP), // OP_CDP /* 1110 1110 1111 */ TABDECL(OP_MCR), // OP_MCR /* 1110 1111 0000 */ TABDECL(OP_CDP), // OP_CDP /* 1110 1111 0001 */ TABDECL(OP_MRC), // OP_MRC /* 1110 1111 0010 */ TABDECL(OP_CDP), // OP_CDP /* 1110 1111 0011 */ TABDECL(OP_MRC), // OP_MRC /* 1110 1111 0100 */ TABDECL(OP_CDP), // OP_CDP /* 1110 1111 0101 */ TABDECL(OP_MRC), // OP_MRC /* 1110 1111 0110 */ TABDECL(OP_CDP), // OP_CDP /* 1110 1111 0111 */ TABDECL(OP_MRC), // OP_MRC /* 1110 1111 1000 */ TABDECL(OP_CDP), // OP_CDP /* 1110 1111 1001 */ TABDECL(OP_MRC), // OP_MRC /* 1110 1111 1010 */ TABDECL(OP_CDP), // OP_CDP /* 1110 1111 1011 */ TABDECL(OP_MRC), // OP_MRC /* 1110 1111 1100 */ TABDECL(OP_CDP), // OP_CDP /* 1110 1111 1101 */ TABDECL(OP_MRC), // OP_MRC /* 1110 1111 1110 */ TABDECL(OP_CDP), // OP_CDP /* 1110 1111 1111 */ TABDECL(OP_MRC), // OP_MRC /* 1111 0000 0000 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0000 0001 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0000 0010 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0000 0011 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0000 0100 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0000 0101 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0000 0110 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0000 0111 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0000 1000 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0000 1001 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0000 1010 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0000 1011 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0000 1100 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0000 1101 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0000 1110 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0000 1111 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0001 0000 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0001 0001 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0001 0010 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0001 0011 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0001 0100 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0001 0101 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0001 0110 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0001 0111 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0001 1000 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0001 1001 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0001 1010 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0001 1011 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0001 1100 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0001 1101 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0001 1110 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0001 1111 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0010 0000 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0010 0001 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0010 0010 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0010 0011 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0010 0100 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0010 0101 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0010 0110 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0010 0111 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0010 1000 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0010 1001 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0010 1010 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0010 1011 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0010 1100 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0010 1101 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0010 1110 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0010 1111 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0011 0000 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0011 0001 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0011 0010 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0011 0011 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0011 0100 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0011 0101 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0011 0110 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0011 0111 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0011 1000 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0011 1001 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0011 1010 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0011 1011 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0011 1100 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0011 1101 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0011 1110 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0011 1111 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0100 0000 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0100 0001 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0100 0010 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0100 0011 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0100 0100 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0100 0101 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0100 0110 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0100 0111 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0100 1000 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0100 1001 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0100 1010 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0100 1011 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0100 1100 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0100 1101 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0100 1110 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0100 1111 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0101 0000 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0101 0001 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0101 0010 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0101 0011 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0101 0100 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0101 0101 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0101 0110 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0101 0111 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0101 1000 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0101 1001 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0101 1010 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0101 1011 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0101 1100 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0101 1101 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0101 1110 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0101 1111 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0110 0000 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0110 0001 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0110 0010 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0110 0011 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0110 0100 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0110 0101 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0110 0110 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0110 0111 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0110 1000 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0110 1001 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0110 1010 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0110 1011 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0110 1100 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0110 1101 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0110 1110 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0110 1111 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0111 0000 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0111 0001 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0111 0010 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0111 0011 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0111 0100 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0111 0101 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0111 0110 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0111 0111 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0111 1000 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0111 1001 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0111 1010 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0111 1011 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0111 1100 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0111 1101 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0111 1110 */ TABDECL(OP_SWI), // OP_SWI /* 1111 0111 1111 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1000 0000 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1000 0001 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1000 0010 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1000 0011 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1000 0100 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1000 0101 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1000 0110 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1000 0111 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1000 1000 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1000 1001 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1000 1010 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1000 1011 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1000 1100 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1000 1101 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1000 1110 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1000 1111 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1001 0000 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1001 0001 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1001 0010 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1001 0011 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1001 0100 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1001 0101 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1001 0110 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1001 0111 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1001 1000 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1001 1001 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1001 1010 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1001 1011 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1001 1100 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1001 1101 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1001 1110 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1001 1111 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1010 0000 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1010 0001 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1010 0010 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1010 0011 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1010 0100 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1010 0101 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1010 0110 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1010 0111 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1010 1000 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1010 1001 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1010 1010 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1010 1011 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1010 1100 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1010 1101 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1010 1110 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1010 1111 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1011 0000 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1011 0001 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1011 0010 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1011 0011 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1011 0100 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1011 0101 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1011 0110 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1011 0111 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1011 1000 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1011 1001 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1011 1010 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1011 1011 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1011 1100 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1011 1101 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1011 1110 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1011 1111 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1100 0000 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1100 0001 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1100 0010 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1100 0011 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1100 0100 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1100 0101 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1100 0110 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1100 0111 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1100 1000 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1100 1001 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1100 1010 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1100 1011 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1100 1100 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1100 1101 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1100 1110 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1100 1111 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1101 0000 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1101 0001 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1101 0010 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1101 0011 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1101 0100 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1101 0101 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1101 0110 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1101 0111 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1101 1000 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1101 1001 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1101 1010 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1101 1011 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1101 1100 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1101 1101 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1101 1110 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1101 1111 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1110 0000 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1110 0001 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1110 0010 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1110 0011 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1110 0100 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1110 0101 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1110 0110 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1110 0111 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1110 1000 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1110 1001 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1110 1010 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1110 1011 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1110 1100 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1110 1101 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1110 1110 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1110 1111 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1111 0000 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1111 0001 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1111 0010 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1111 0011 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1111 0100 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1111 0101 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1111 0110 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1111 0111 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1111 1000 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1111 1001 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1111 1010 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1111 1011 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1111 1100 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1111 1101 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1111 1110 */ TABDECL(OP_SWI), // OP_SWI /* 1111 1111 1111 */ TABDECL(OP_SWI), // OP_SWI desmume/src/libretro-common/glsym/rglgen.py000755 001750 001750 00000011067 12755534123 022240 0ustar00sergiosergio000000 000000 #!/usr/bin/env python3 """ License statement applies to this file (glgen.py) only. """ """ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. """ import sys import os import re banned_ext = [ 'AMD', 'APPLE', 'NV', 'NVX', 'ATI', '3DLABS', 'SUN', 'SGI', 'SGIX', 'SGIS', 'INTEL', '3DFX', 'IBM', 'MESA', 'GREMEDY', 'OML', 'PGI', 'I3D', 'INGL', 'MTX', 'QCOM', 'IMG', 'ANGLE', 'SUNX', 'INGR' ] def noext(sym): for ext in banned_ext: if sym.endswith(ext): return False return True def find_gl_symbols(lines): typedefs = [] syms = [] for line in lines: m = re.search(r'^typedef.+PFN(\S+)PROC.+$', line) g = re.search(r'^.+(gl\S+)\W*\(.+\).*$', line) if m and noext(m.group(1)): typedefs.append(m.group(0).replace('PFN', 'RGLSYM').replace('GLDEBUGPROC', 'RGLGENGLDEBUGPROC')) if g and noext(g.group(1)): syms.append(g.group(1)) return (typedefs, syms) def generate_defines(gl_syms): res = [] for line in gl_syms: res.append('#define {} __rglgen_{}'.format(line, line)) return res def generate_declarations(gl_syms): return ['RGLSYM' + x.upper() + 'PROC ' + '__rglgen_' + x + ';' for x in gl_syms] def generate_macros(gl_syms): return [' SYM(' + x.replace('gl', '') + '),' for x in gl_syms] def dump(f, lines): f.write('\n'.join(lines)) f.write('\n\n') if __name__ == '__main__': if len(sys.argv) > 4: for banned in sys.argv[4:]: banned_ext.append(banned) with open(sys.argv[1], 'r') as f: lines = f.readlines() typedefs, syms = find_gl_symbols(lines) overrides = generate_defines(syms) declarations = generate_declarations(syms) externs = ['extern ' + x for x in declarations] macros = generate_macros(syms) with open(sys.argv[2], 'w') as f: f.write('#ifndef RGLGEN_DECL_H__\n') f.write('#define RGLGEN_DECL_H__\n') f.write('#ifdef __cplusplus\n') f.write('extern "C" {\n') f.write('#endif\n') f.write('#ifdef GL_APIENTRY\n') f.write('typedef void (GL_APIENTRY *RGLGENGLDEBUGPROC)(GLenum, GLenum, GLuint, GLenum, GLsizei, const GLchar*, GLvoid*);\n') f.write('#else\n') f.write('#ifndef APIENTRY\n') f.write('#define APIENTRY\n') f.write('#endif\n') f.write('#ifndef APIENTRYP\n') f.write('#define APIENTRYP APIENTRY *\n') f.write('#endif\n') f.write('typedef void (APIENTRY *RGLGENGLDEBUGPROCARB)(GLenum, GLenum, GLuint, GLenum, GLsizei, const GLchar*, GLvoid*);\n') f.write('typedef void (APIENTRY *RGLGENGLDEBUGPROC)(GLenum, GLenum, GLuint, GLenum, GLsizei, const GLchar*, GLvoid*);\n') f.write('#endif\n') f.write('#ifndef GL_OES_EGL_image\n') f.write('typedef void *GLeglImageOES;\n') f.write('#endif\n') f.write('#if !defined(GL_OES_fixed_point) && !defined(HAVE_OPENGLES2)\n') f.write('typedef GLint GLfixed;\n') f.write('#endif\n') dump(f, typedefs) dump(f, overrides) dump(f, externs) f.write('struct rglgen_sym_map { const char *sym; void *ptr; };\n') f.write('extern const struct rglgen_sym_map rglgen_symbol_map[];\n') f.write('#ifdef __cplusplus\n') f.write('}\n') f.write('#endif\n') f.write('#endif\n') with open(sys.argv[3], 'w') as f: f.write('#include "glsym/glsym.h"\n') f.write('#include \n') f.write('#define SYM(x) { "gl" #x, &(gl##x) }\n') f.write('const struct rglgen_sym_map rglgen_symbol_map[] = {\n') dump(f, macros) f.write(' { NULL, NULL },\n') f.write('};\n') dump(f, declarations) desmume/src/utils/AsmJit/core/000700 001750 001750 00000000000 12756420131 017374 5ustar00sergiosergio000000 000000 desmume/src/libretro-common/lists/dir_list.c000664 001750 001750 00000015240 12755534123 022364 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2016 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (dir_list.c). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include #include #include #include #include #include #include static int qstrcmp_plain(const void *a_, const void *b_) { const struct string_list_elem *a = (const struct string_list_elem*)a_; const struct string_list_elem *b = (const struct string_list_elem*)b_; return strcasecmp(a->data, b->data); } static int qstrcmp_dir(const void *a_, const void *b_) { const struct string_list_elem *a = (const struct string_list_elem*)a_; const struct string_list_elem *b = (const struct string_list_elem*)b_; int a_type = a->attr.i; int b_type = b->attr.i; /* Sort directories before files. */ if (a_type != b_type) return b_type - a_type; return strcasecmp(a->data, b->data); } /** * dir_list_sort: * @list : pointer to the directory listing. * @dir_first : move the directories in the listing to the top? * * Sorts a directory listing. * **/ void dir_list_sort(struct string_list *list, bool dir_first) { if (list) qsort(list->elems, list->size, sizeof(struct string_list_elem), dir_first ? qstrcmp_dir : qstrcmp_plain); } /** * dir_list_free: * @list : pointer to the directory listing * * Frees a directory listing. * **/ void dir_list_free(struct string_list *list) { string_list_free(list); } /** * parse_dir_entry: * @name : name of the directory listing entry. * @file_path : file path of the directory listing entry. * @is_dir : is the directory listing a directory? * @include_dirs : include directories as part of the finished directory listing? * @include_compressed : Include compressed files, even if not part of ext_list. * @list : pointer to directory listing. * @ext_list : pointer to allowed file extensions listing. * @file_ext : file extension of the directory listing entry. * * Parses a directory listing. * * Returns: zero on success, -1 on error, 1 if we should * continue to the next entry in the directory listing. **/ static int parse_dir_entry(const char *name, char *file_path, bool is_dir, bool include_dirs, bool include_compressed, struct string_list *list, struct string_list *ext_list, const char *file_ext) { union string_list_elem_attr attr; bool is_compressed_file = false; bool supported_by_core = false; attr.i = RARCH_FILETYPE_UNSET; if (!is_dir) { is_compressed_file = path_is_compressed_file(file_path); if (string_list_find_elem_prefix(ext_list, ".", file_ext)) supported_by_core = true; } if (!include_dirs && is_dir) return 1; if (!strcmp(name, ".") || !strcmp(name, "..")) return 1; if (!is_dir && ext_list && ((!is_compressed_file && !supported_by_core) || (!supported_by_core && !include_compressed))) return 1; if (is_dir) attr.i = RARCH_DIRECTORY; if (is_compressed_file) attr.i = RARCH_COMPRESSED_ARCHIVE; /* The order of these ifs is important. * If the file format is explicitly supported by the libretro-core, we * need to immediately load it and not designate it as a compressed file. * * Example: .zip could be supported as a image by the core and as a * compressed_file. In that case, we have to interpret it as a image. * * */ if (supported_by_core) attr.i = RARCH_PLAIN_FILE; if (!string_list_append(list, file_path, attr)) return -1; return 0; } /** * dir_list_new: * @dir : directory path. * @ext : allowed extensions of file directory entries to include. * @include_dirs : include directories as part of the finished directory listing? * @include_compressed : Only include files which match ext. Do not try to match compressed files, etc. * * Create a directory listing. * * Returns: pointer to a directory listing of type 'struct string_list *' on success, * NULL in case of error. Has to be freed manually. **/ struct string_list *dir_list_new(const char *dir, const char *ext, bool include_dirs, bool include_compressed) { struct RDIR *entry = NULL; struct string_list *ext_list = NULL; struct string_list *list = NULL; if (!(list = string_list_new())) return NULL; if (ext) ext_list = string_split(ext, "|"); entry = retro_opendir(dir); if (!entry) goto error; if (retro_dirent_error(entry)) goto error; while (retro_readdir(entry)) { bool is_dir = false; char file_path[PATH_MAX_LENGTH] = {0}; int ret = 0; const char *name = retro_dirent_get_name(entry); const char *file_ext = path_get_extension(name); fill_pathname_join(file_path, dir, name, sizeof(file_path)); is_dir = retro_dirent_is_dir(entry, file_path); ret = parse_dir_entry(name, file_path, is_dir, include_dirs, include_compressed, list, ext_list, file_ext); if (ret == -1) goto error; if (ret == 1) continue; } retro_closedir(entry); string_list_free(ext_list); return list; error: retro_closedir(entry); string_list_free(list); string_list_free(ext_list); return NULL; } desmume/src/libretro-common/libco/000700 001750 001750 00000000000 12756420131 020315 5ustar00sergiosergio000000 000000 desmume/src/utils/arm_arm/arm_jit.cpp000664 001750 001750 00000131205 12755534123 021050 0ustar00sergiosergio000000 000000 /* Copyright (C) 2006 yopyop Copyright (C) 2011 Loren Merritt Copyright (C) 2012 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the this software. If not, see . */ #include "types.h" #ifdef HAVE_JIT #include #include #include #include "arm_gen.h" #include "reg_manager.h" using namespace arm_gen; #include "instructions.h" #include "instruction_attributes.h" #include "MMU.h" #include "MMU_timing.h" #include "arm_jit.h" #include "bios.h" #include "armcpu.h" #include "../bits.h" u32 saveBlockSizeJIT = 0; #ifdef MAPPED_JIT_FUNCS CACHE_ALIGN JIT_struct JIT; uintptr_t *JIT_struct::JIT_MEM[2][0x4000] = {{0}}; static uintptr_t *JIT_MEM[2][32] = { //arm9 { /* 0X*/ DUP2(JIT.ARM9_ITCM), /* 1X*/ DUP2(JIT.ARM9_ITCM), // mirror /* 2X*/ DUP2(JIT.MAIN_MEM), /* 3X*/ DUP2(JIT.SWIRAM), /* 4X*/ DUP2(NULL), /* 5X*/ DUP2(NULL), /* 6X*/ NULL, JIT.ARM9_LCDC, // Plain ARM9-CPU Access (LCDC mode) (max 656KB) /* 7X*/ DUP2(NULL), /* 8X*/ DUP2(NULL), /* 9X*/ DUP2(NULL), /* AX*/ DUP2(NULL), /* BX*/ DUP2(NULL), /* CX*/ DUP2(NULL), /* DX*/ DUP2(NULL), /* EX*/ DUP2(NULL), /* FX*/ DUP2(JIT.ARM9_BIOS) }, //arm7 { /* 0X*/ DUP2(JIT.ARM7_BIOS), /* 1X*/ DUP2(NULL), /* 2X*/ DUP2(JIT.MAIN_MEM), /* 3X*/ JIT.SWIRAM, JIT.ARM7_ERAM, /* 4X*/ NULL, JIT.ARM7_WIRAM, /* 5X*/ DUP2(NULL), /* 6X*/ JIT.ARM7_WRAM, // VRAM allocated as Work RAM to ARM7 (max. 256K) NULL, /* 7X*/ DUP2(NULL), /* 8X*/ DUP2(NULL), /* 9X*/ DUP2(NULL), /* AX*/ DUP2(NULL), /* BX*/ DUP2(NULL), /* CX*/ DUP2(NULL), /* DX*/ DUP2(NULL), /* EX*/ DUP2(NULL), /* FX*/ DUP2(NULL) } }; static u32 JIT_MASK[2][32] = { //arm9 { /* 0X*/ DUP2(0x00007FFF), /* 1X*/ DUP2(0x00007FFF), /* 2X*/ DUP2(0x003FFFFF), // FIXME _MMU_MAIN_MEM_MASK /* 3X*/ DUP2(0x00007FFF), /* 4X*/ DUP2(0x00000000), /* 5X*/ DUP2(0x00000000), /* 6X*/ 0x00000000, 0x000FFFFF, /* 7X*/ DUP2(0x00000000), /* 8X*/ DUP2(0x00000000), /* 9X*/ DUP2(0x00000000), /* AX*/ DUP2(0x00000000), /* BX*/ DUP2(0x00000000), /* CX*/ DUP2(0x00000000), /* DX*/ DUP2(0x00000000), /* EX*/ DUP2(0x00000000), /* FX*/ DUP2(0x00007FFF) }, //arm7 { /* 0X*/ DUP2(0x00003FFF), /* 1X*/ DUP2(0x00000000), /* 2X*/ DUP2(0x003FFFFF), /* 3X*/ 0x00007FFF, 0x0000FFFF, /* 4X*/ 0x00000000, 0x0000FFFF, /* 5X*/ DUP2(0x00000000), /* 6X*/ 0x0003FFFF, 0x00000000, /* 7X*/ DUP2(0x00000000), /* 8X*/ DUP2(0x00000000), /* 9X*/ DUP2(0x00000000), /* AX*/ DUP2(0x00000000), /* BX*/ DUP2(0x00000000), /* CX*/ DUP2(0x00000000), /* DX*/ DUP2(0x00000000), /* EX*/ DUP2(0x00000000), /* FX*/ DUP2(0x00000000) } }; static void init_jit_mem() { static bool inited = false; if(inited) return; inited = true; for(int proc=0; proc<2; proc++) for(int i=0; i<0x4000; i++) JIT.JIT_MEM[proc][i] = JIT_MEM[proc][i>>9] + (((i<<14) & JIT_MASK[proc][i>>9]) >> 1); } #else DS_ALIGN(4096) uintptr_t compiled_funcs[1<<26] = {0}; #endif template static u32 FASTCALL OP_DECODE() { u32 cycles; u32 adr = ARMPROC.instruct_adr; if(thumb) { ARMPROC.next_instruction = adr + 2; ARMPROC.R[15] = adr + 4; u32 opcode = _MMU_read16(adr); //_armlog(PROCNUM, adr, opcode); cycles = thumb_instructions_set[PROCNUM][opcode>>6](opcode); } else { ARMPROC.next_instruction = adr + 4; ARMPROC.R[15] = adr + 8; u32 opcode = _MMU_read32(adr); //_armlog(PROCNUM, adr, opcode); if(CONDITION(opcode) == 0xE || TEST_COND(CONDITION(opcode), CODE(opcode), ARMPROC.CPSR)) cycles = arm_instructions_set[PROCNUM][INSTRUCTION_INDEX(opcode)](opcode); else cycles = 1; } ARMPROC.instruct_adr = ARMPROC.next_instruction; return cycles; } static const ArmOpCompiled op_decode[2][2] = { OP_DECODE<0,0>, OP_DECODE<0,1>, OP_DECODE<1,0>, OP_DECODE<1,1> }; enum OP_RESULT { OPR_CONTINUE, OPR_INTERPRET, OPR_BRANCHED, OPR_RESULT_SIZE = 2147483647 }; #define OPR_RESULT(result, cycles) (OP_RESULT)((result) | ((cycles) << 16)); #define OPR_RESULT_CYCLES(result) ((result >> 16)) #define OPR_RESULT_ACTION(result) ((result & 0xFF)) typedef OP_RESULT (*ArmOpCompiler)(uint32_t pc, uint32_t opcode); static const uint32_t INSTRUCTION_COUNT = 0xC0000; static code_pool* block; static register_manager* regman; static u8 recompile_counts[(1<<26)/16]; const reg_t RCPU = 12; const reg_t RCYC = 4; static uint32_t block_procnum; /////// // HELPERS /////// static bool emu_status_dirty; static bool bit(uint32_t value, uint32_t bit) { return value & (1 << bit); } static uint32_t bit(uint32_t value, uint32_t first, uint32_t count) { return (value >> first) & ((1 << count) - 1); } static uint32_t bit_write(uint32_t value, uint32_t first, uint32_t count, uint32_t insert) { uint32_t result = value & ~(((1 << count) - 1) << first); return result | (insert << first); } static void load_status(reg_t scratch) { block->ldr(scratch, RCPU, mem2::imm(offsetof(armcpu_t, CPSR))); block->set_status(scratch); } static void write_status(reg_t scratch) { if (emu_status_dirty) { block->get_status(scratch); block->mov(scratch, alu2::reg_shift_imm(scratch, LSR, 24)); block->strb(scratch, RCPU, mem2::imm(offsetof(armcpu_t, CPSR) + 3)); emu_status_dirty = false; } } static void mark_status_dirty() { emu_status_dirty = true; } static void call(reg_t reg) { write_status(3); block->blx(reg); const unsigned PROCNUM = block_procnum; block->load_constant(RCPU, (uint32_t)&ARMPROC); load_status(3); } static void change_mode(bool thumb) { block->ldr(0, RCPU, mem2::imm(offsetof(armcpu_t, CPSR))); if (!thumb) { block->bic(0, alu2::imm(1 << 5)); } else { block->orr(0, alu2::imm(1 << 5)); } block->str(0, RCPU, mem2::imm(offsetof(armcpu_t, CPSR))); } static void change_mode_reg(reg_t reg, reg_t scratch, reg_t scratch2) { block->and_(scratch2, reg, alu2::imm(1)); block->ldr(scratch, RCPU, mem2::imm(offsetof(armcpu_t, CPSR))); block->bic(scratch, alu2::imm(scratch2 << 5)); block->orr(scratch, alu2::reg_shift_imm(scratch2, LSL, 5)); block->str(scratch, RCPU, mem2::imm(offsetof(armcpu_t, CPSR))); } template static void arm_jit_prefetch(uint32_t pc, uint32_t opcode, bool thumb) { const uint32_t imask = thumb ? 0xFFFFFFFE : 0xFFFFFFFC; const uint32_t isize = thumb ? 2 : 4; block->load_constant(0, pc & imask); block->str(0, RCPU, mem2::imm(offsetof(armcpu_t, instruct_adr))); block->add(0, alu2::imm(isize)); block->str(0, RCPU, mem2::imm(offsetof(armcpu_t, next_instruction))); block->add(0, alu2::imm(isize)); block->str(0, RCPU, mem2::imm(offsetof(armcpu_t, R) + 4 * 15)); block->load_constant(0, opcode); block->str(0, RCPU, mem2::imm(offsetof(armcpu_t, instruction))); } ///////// /// ARM ///////// static OP_RESULT ARM_OP_PATCH_DELEGATE(uint32_t pc, uint32_t opcode, int AT16, int AT12, int AT8, int AT0, bool S, uint32_t CYC) { const reg_t at16 = bit(opcode, 16, 4); const reg_t at12 = bit(opcode, 12, 4); const reg_t at8 = bit(opcode, 8, 4); const reg_t at0 = bit(opcode, 0, 4); if ((AT16 && (at16 == 0xF)) || (AT12 && (at12 == 0xF)) || (AT8 && (at8 == 0xF)) || (AT0 && (at0 == 0xF))) return OPR_INTERPRET; const uint32_t weak_tag = (bit(opcode, 28, 4) == AL) ? 0x10 : 0; int32_t reg_list[4]; reg_list[0] = (AT16) ? (int32_t)(at16 | ((AT16 == 2) ? weak_tag : 0)) : -1; reg_list[1] = (AT12) ? (int32_t)(at12 | ((AT12 == 2) ? weak_tag : 0)) : -1; reg_list[2] = (AT8 ) ? (int32_t)(at8 | ((AT8 == 2) ? weak_tag : 0)) : -1; reg_list[3] = (AT0 ) ? (int32_t)(at0 | ((AT0 == 2) ? weak_tag : 0)) : -1; regman->get(4, reg_list); opcode = AT16 ? bit_write(opcode, 16, 4, reg_list[0]) : opcode; opcode = AT12 ? bit_write(opcode, 12, 4, reg_list[1]) : opcode; opcode = AT8 ? bit_write(opcode, 8, 4, reg_list[2]) : opcode; opcode = AT0 ? bit_write(opcode, 0, 4, reg_list[3]) : opcode; block->insert_raw_instruction(opcode); if (S) mark_status_dirty(); if (AT16 & 2) regman->mark_dirty(reg_list[0]); if (AT12 & 2) regman->mark_dirty(reg_list[1]); if (AT8 & 2) regman->mark_dirty(reg_list[2]); if (AT0 & 2) regman->mark_dirty(reg_list[3]); return OPR_RESULT(OPR_CONTINUE, CYC); } template static OP_RESULT ARM_OP_PATCH(uint32_t pc, uint32_t opcode) { return ARM_OP_PATCH_DELEGATE(pc, opcode, AT16, AT12, AT8, AT0, S, CYC); } #define ARM_ALU_OP_DEF(T, D, N, S) \ static const ArmOpCompiler ARM_OP_##T##_LSL_IMM = ARM_OP_PATCH; \ static const ArmOpCompiler ARM_OP_##T##_LSL_REG = ARM_OP_PATCH; \ static const ArmOpCompiler ARM_OP_##T##_LSR_IMM = ARM_OP_PATCH; \ static const ArmOpCompiler ARM_OP_##T##_LSR_REG = ARM_OP_PATCH; \ static const ArmOpCompiler ARM_OP_##T##_ASR_IMM = ARM_OP_PATCH; \ static const ArmOpCompiler ARM_OP_##T##_ASR_REG = ARM_OP_PATCH; \ static const ArmOpCompiler ARM_OP_##T##_ROR_IMM = ARM_OP_PATCH; \ static const ArmOpCompiler ARM_OP_##T##_ROR_REG = ARM_OP_PATCH; \ static const ArmOpCompiler ARM_OP_##T##_IMM_VAL = ARM_OP_PATCH ARM_ALU_OP_DEF(AND , 2, 1, false); ARM_ALU_OP_DEF(AND_S, 2, 1, true); ARM_ALU_OP_DEF(EOR , 2, 1, false); ARM_ALU_OP_DEF(EOR_S, 2, 1, true); ARM_ALU_OP_DEF(SUB , 2, 1, false); ARM_ALU_OP_DEF(SUB_S, 2, 1, true); ARM_ALU_OP_DEF(RSB , 2, 1, false); ARM_ALU_OP_DEF(RSB_S, 2, 1, true); ARM_ALU_OP_DEF(ADD , 2, 1, false); ARM_ALU_OP_DEF(ADD_S, 2, 1, true); ARM_ALU_OP_DEF(ADC , 2, 1, false); ARM_ALU_OP_DEF(ADC_S, 2, 1, true); ARM_ALU_OP_DEF(SBC , 2, 1, false); ARM_ALU_OP_DEF(SBC_S, 2, 1, true); ARM_ALU_OP_DEF(RSC , 2, 1, false); ARM_ALU_OP_DEF(RSC_S, 2, 1, true); ARM_ALU_OP_DEF(TST , 0, 1, true); ARM_ALU_OP_DEF(TEQ , 0, 1, true); ARM_ALU_OP_DEF(CMP , 0, 1, true); ARM_ALU_OP_DEF(CMN , 0, 1, true); ARM_ALU_OP_DEF(ORR , 2, 1, false); ARM_ALU_OP_DEF(ORR_S, 2, 1, true); ARM_ALU_OP_DEF(MOV , 2, 0, false); ARM_ALU_OP_DEF(MOV_S, 2, 0, true); ARM_ALU_OP_DEF(BIC , 2, 1, false); ARM_ALU_OP_DEF(BIC_S, 2, 1, true); ARM_ALU_OP_DEF(MVN , 2, 0, false); ARM_ALU_OP_DEF(MVN_S, 2, 0, true); // HACK: multiply cycles are wrong #define ARM_OP_MUL ARM_OP_PATCH<2, 0, 1, 1, false, 3> #define ARM_OP_MUL_S ARM_OP_PATCH<2, 0, 1, 1, true, 3> #define ARM_OP_MLA ARM_OP_PATCH<2, 1, 1, 1, false, 4> #define ARM_OP_MLA_S ARM_OP_PATCH<2, 1, 1, 1, true, 4> #define ARM_OP_UMULL ARM_OP_PATCH<2, 2, 1, 1, false, 4> #define ARM_OP_UMULL_S ARM_OP_PATCH<2, 2, 1, 1, true, 4> #define ARM_OP_UMLAL ARM_OP_PATCH<3, 3, 1, 1, false, 5> #define ARM_OP_UMLAL_S ARM_OP_PATCH<3, 3, 1, 1, true, 5> #define ARM_OP_SMULL ARM_OP_PATCH<2, 2, 1, 1, false, 4> #define ARM_OP_SMULL_S ARM_OP_PATCH<2, 2, 1, 1, true, 4> #define ARM_OP_SMLAL ARM_OP_PATCH<3, 3, 1, 1, false, 5> #define ARM_OP_SMLAL_S ARM_OP_PATCH<3, 3, 1, 1, true, 5> #define ARM_OP_SMUL_B_B ARM_OP_PATCH<2, 0, 1, 1, true, 2> #define ARM_OP_SMUL_T_B ARM_OP_PATCH<2, 0, 1, 1, true, 2> #define ARM_OP_SMUL_B_T ARM_OP_PATCH<2, 0, 1, 1, true, 2> #define ARM_OP_SMUL_T_T ARM_OP_PATCH<2, 0, 1, 1, true, 2> #define ARM_OP_SMLA_B_B ARM_OP_PATCH<2, 1, 1, 1, true, 2> #define ARM_OP_SMLA_T_B ARM_OP_PATCH<2, 1, 1, 1, true, 2> #define ARM_OP_SMLA_B_T ARM_OP_PATCH<2, 1, 1, 1, true, 2> #define ARM_OP_SMLA_T_T ARM_OP_PATCH<2, 1, 1, 1, true, 2> #define ARM_OP_SMULW_B ARM_OP_PATCH<2, 0, 1, 1, true, 2> #define ARM_OP_SMULW_T ARM_OP_PATCH<2, 0, 1, 1, true, 2> #define ARM_OP_SMLAW_B ARM_OP_PATCH<2, 1, 1, 1, true, 2> #define ARM_OP_SMLAW_T ARM_OP_PATCH<2, 1, 1, 1, true, 2> #define ARM_OP_SMLAL_B_B ARM_OP_PATCH<3, 3, 1, 1, true, 2> #define ARM_OP_SMLAL_T_B ARM_OP_PATCH<3, 3, 1, 1, true, 2> #define ARM_OP_SMLAL_B_T ARM_OP_PATCH<3, 3, 1, 1, true, 2> #define ARM_OP_SMLAL_T_T ARM_OP_PATCH<3, 3, 1, 1, true, 2> #define ARM_OP_QADD ARM_OP_PATCH<1, 2, 0, 1, true, 2> #define ARM_OP_QSUB ARM_OP_PATCH<1, 2, 0, 1, true, 2> #define ARM_OP_QDADD ARM_OP_PATCH<1, 2, 0, 1, true, 2> #define ARM_OP_QDSUB ARM_OP_PATCH<1, 2, 0, 1, true, 2> #define ARM_OP_CLZ ARM_OP_PATCH<0, 2, 0, 1, false, 2> //////// // Need versions of these functions with exported symbol u8 _MMU_read08_9(u32 addr) { return _MMU_read08<0>(addr); } u8 _MMU_read08_7(u32 addr) { return _MMU_read08<1>(addr); } u16 _MMU_read16_9(u32 addr) { return _MMU_read16<0>(addr & 0xFFFFFFFE); } u16 _MMU_read16_7(u32 addr) { return _MMU_read16<1>(addr & 0xFFFFFFFE); } u32 _MMU_read32_9(u32 addr) { return ::ROR(_MMU_read32<0>(addr & 0xFFFFFFFC), 8 * (addr & 3)); } u32 _MMU_read32_7(u32 addr) { return ::ROR(_MMU_read32<1>(addr & 0xFFFFFFFC), 8 * (addr & 3)); } void _MMU_write08_9(u32 addr, u8 val) { _MMU_write08<0>(addr, val); } void _MMU_write08_7(u32 addr, u8 val) { _MMU_write08<1>(addr, val); } void _MMU_write16_9(u32 addr, u16 val) { _MMU_write16<0>(addr & 0xFFFFFFFE, val); } void _MMU_write16_7(u32 addr, u16 val) { _MMU_write16<1>(addr & 0xFFFFFFFE, val); } void _MMU_write32_9(u32 addr, u32 val) { _MMU_write32<0>(addr & 0xFFFFFFFC, val); } void _MMU_write32_7(u32 addr, u32 val) { _MMU_write32<1>(addr & 0xFFFFFFFC, val); } static const uint32_t mem_funcs[12] = { (uint32_t)_MMU_read08_9 , (uint32_t)_MMU_read08_7, (uint32_t)_MMU_write08_9, (uint32_t)_MMU_write08_7, (uint32_t)_MMU_read16_9, (uint32_t)_MMU_read16_7, (uint32_t)_MMU_write16_9, (uint32_t)_MMU_write16_7, (uint32_t)_MMU_read32_9, (uint32_t)_MMU_read32_7, (uint32_t)_MMU_write32_9, (uint32_t)_MMU_write32_7 }; static OP_RESULT ARM_OP_MEM(uint32_t pc, const uint32_t opcode) { const AG_COND cond = (AG_COND)bit(opcode, 28, 4); const bool has_reg_offset = bit(opcode, 25); const bool has_pre_index = bit(opcode, 24); const bool has_up_bit = bit(opcode, 23); const bool has_byte_bit = bit(opcode, 22); const bool has_write_back = bit(opcode, 21); const bool has_load = bit(opcode, 20); const reg_t rn = bit(opcode, 16, 4); const reg_t rd = bit(opcode, 12, 4); const reg_t rm = bit(opcode, 0, 4); if (rn == 0xF || rd == 0xF || (has_reg_offset && (rm == 0xF))) return OPR_INTERPRET; int32_t regs[3] = { rd | (((cond == AL) && has_load) ? 0x10 : 0), rn, has_reg_offset ? (int32_t)rm : -1 }; regman->get(3, regs); const reg_t dest = regs[0]; const reg_t base = regs[1]; const reg_t offs = has_reg_offset ? regs[2] : 3; // HACK: This needs to done manually here as we can't branch over the generated code write_status(3); if (cond != AL) { block->b("run", cond); block->b("skip"); block->set_label("run"); } // Put the indexed address in R3 if (has_reg_offset) { const AG_ALU_SHIFT st = (AG_ALU_SHIFT)bit(opcode, 5, 2); const uint32_t imm = bit(opcode, 7, 5); if (has_up_bit) block->add(3, base, alu2::reg_shift_imm(offs, st, imm)); else block->sub(3, base, alu2::reg_shift_imm(offs, st, imm)); } else { block->load_constant(3, opcode & 0xFFF); if (has_up_bit) block->add(3, base, alu2::reg(3)); else block->sub(3, base, alu2::reg(3)); } // Load EA block->mov(0, alu2::reg((has_pre_index ? (reg_t)3 : base))); // Do Writeback if ((!has_pre_index) || has_write_back) { block->mov(base, alu2::reg(3)); regman->mark_dirty(base); } // DO if (!has_load) { if (has_byte_bit) { block->uxtb(1, dest); } else { block->mov(1, alu2::reg(dest)); } } uint32_t func_idx = block_procnum | (has_load ? 0 : 2) | (has_byte_bit ? 0 : 8); block->load_constant(2, mem_funcs[func_idx]); call(2); if (has_load) { if (has_byte_bit) { block->uxtb(dest, 0); } else { block->mov(dest, alu2::reg(0)); } regman->mark_dirty(dest); } if (cond != AL) { block->set_label("skip"); block->resolve_label("run"); block->resolve_label("skip"); } // TODO: return OPR_RESULT(OPR_CONTINUE, 3); } #define ARM_MEM_OP_DEF2(T, Q) \ static const ArmOpCompiler ARM_OP_##T##_M_LSL_##Q = ARM_OP_MEM; \ static const ArmOpCompiler ARM_OP_##T##_P_LSL_##Q = ARM_OP_MEM; \ static const ArmOpCompiler ARM_OP_##T##_M_LSR_##Q = ARM_OP_MEM; \ static const ArmOpCompiler ARM_OP_##T##_P_LSR_##Q = ARM_OP_MEM; \ static const ArmOpCompiler ARM_OP_##T##_M_ASR_##Q = ARM_OP_MEM; \ static const ArmOpCompiler ARM_OP_##T##_P_ASR_##Q = ARM_OP_MEM; \ static const ArmOpCompiler ARM_OP_##T##_M_ROR_##Q = ARM_OP_MEM; \ static const ArmOpCompiler ARM_OP_##T##_P_ROR_##Q = ARM_OP_MEM; \ static const ArmOpCompiler ARM_OP_##T##_M_##Q = ARM_OP_MEM; \ static const ArmOpCompiler ARM_OP_##T##_P_##Q = ARM_OP_MEM #define ARM_MEM_OP_DEF(T) \ ARM_MEM_OP_DEF2(T, IMM_OFF_PREIND); \ ARM_MEM_OP_DEF2(T, IMM_OFF); \ ARM_MEM_OP_DEF2(T, IMM_OFF_POSTIND) ARM_MEM_OP_DEF(STR); ARM_MEM_OP_DEF(LDR); ARM_MEM_OP_DEF(STRB); ARM_MEM_OP_DEF(LDRB); // static OP_RESULT ARM_OP_MEM_HALF(uint32_t pc, uint32_t opcode) { const AG_COND cond = (AG_COND)bit(opcode, 28, 4); const bool has_pre_index = bit(opcode, 24); const bool has_up_bit = bit(opcode, 23); const bool has_imm_offset = bit(opcode, 22); const bool has_write_back = bit(opcode, 21); const bool has_load = bit(opcode, 20); const uint32_t op = bit(opcode, 5, 2); const reg_t rn = bit(opcode, 16, 4); const reg_t rd = bit(opcode, 12, 4); const reg_t rm = bit(opcode, 0, 4); if (rn == 0xF || rd == 0xF || (!has_imm_offset && (rm == 0xF))) return OPR_INTERPRET; int32_t regs[3] = { rd | (((cond == AL) && has_load) ? 0x10 : 0), rn, (!has_imm_offset) ? (int32_t)rm : -1 }; regman->get(3, regs); const reg_t dest = regs[0]; const reg_t base = regs[1]; const reg_t offs = (!has_imm_offset) ? regs[2] : 0; // HACK: This needs to done manually here as we can't branch over the generated code write_status(3); if (cond != AL) { block->b("run", cond); block->b("skip"); block->set_label("run"); } // Put the indexed address in R3 if (!has_imm_offset) { if (has_up_bit) block->add(3, base, alu2::reg(offs)); else block->sub(3, base, alu2::reg(offs)); } else { block->load_constant(3, (opcode & 0xF) | ((opcode >> 4) & 0xF0)); if (has_up_bit) block->add(3, base, alu2::reg(3)); else block->sub(3, base, alu2::reg(3)); } // Load EA block->mov(0, alu2::reg((has_pre_index ? (reg_t)3 : base))); // Do Writeback if ((!has_pre_index) || has_write_back) { block->mov(base, alu2::reg(3)); regman->mark_dirty(base); } // DO if (!has_load) { switch (op) { case 1: block->uxth(1, dest); break; case 2: block->sxtb(1, dest); break; case 3: block->sxth(1, dest); break; } } uint32_t func_idx = block_procnum | (has_load ? 0 : 2) | ((op == 2) ? 0 : 4); block->load_constant(2, mem_funcs[func_idx]); call(2); if (has_load) { switch (op) { case 1: block->uxth(dest, 0); break; case 2: block->sxtb(dest, 0); break; case 3: block->sxth(dest, 0); break; } regman->mark_dirty(dest); } if (cond != AL) { block->set_label("skip"); block->resolve_label("run"); block->resolve_label("skip"); } // TODO: return OPR_RESULT(OPR_CONTINUE, 3); } #define ARM_MEM_HALF_OP_DEF2(T, P) \ static const ArmOpCompiler ARM_OP_##T##_##P##M_REG_OFF = ARM_OP_MEM_HALF; \ static const ArmOpCompiler ARM_OP_##T##_##P##P_REG_OFF = ARM_OP_MEM_HALF; \ static const ArmOpCompiler ARM_OP_##T##_##P##M_IMM_OFF = ARM_OP_MEM_HALF; \ static const ArmOpCompiler ARM_OP_##T##_##P##P_IMM_OFF = ARM_OP_MEM_HALF #define ARM_MEM_HALF_OP_DEF(T) \ ARM_MEM_HALF_OP_DEF2(T, POS_INDE_); \ ARM_MEM_HALF_OP_DEF2(T, ); \ ARM_MEM_HALF_OP_DEF2(T, PRE_INDE_) ARM_MEM_HALF_OP_DEF(STRH); ARM_MEM_HALF_OP_DEF(LDRH); ARM_MEM_HALF_OP_DEF(STRSB); ARM_MEM_HALF_OP_DEF(LDRSB); ARM_MEM_HALF_OP_DEF(STRSH); ARM_MEM_HALF_OP_DEF(LDRSH); // #define SIGNEXTEND_24(i) (((s32)i<<8)>>8) static OP_RESULT ARM_OP_B_BL(uint32_t pc, uint32_t opcode) { const AG_COND cond = (AG_COND)bit(opcode, 28, 4); const bool has_link = bit(opcode, 24); const bool unconditional = (cond == AL || cond == EGG); int32_t regs[1] = { (has_link || cond == EGG) ? 14 : -1 }; regman->get(1, regs); uint32_t dest = (pc + 8 + (SIGNEXTEND_24(bit(opcode, 0, 24)) << 2)); if (!unconditional) { block->load_constant(0, pc + 4); block->b("run", cond); block->b("skip"); block->set_label("run"); } if (cond == EGG) { change_mode(true); if (has_link) { dest += 2; } } if (has_link || cond == EGG) { block->load_constant(regs[0], pc + 4); regman->mark_dirty(regs[0]); } block->load_constant(0, dest); if (!unconditional) { block->set_label("skip"); block->resolve_label("run"); block->resolve_label("skip"); } block->str(0, RCPU, mem2::imm(offsetof(armcpu_t, instruct_adr))); // TODO: Timing return OPR_RESULT(OPR_BRANCHED, 3); } #define ARM_OP_B ARM_OP_B_BL #define ARM_OP_BL ARM_OP_B_BL //// #define ARM_OP_LDRD_STRD_POST_INDEX 0 #define ARM_OP_LDRD_STRD_OFFSET_PRE_INDEX 0 #define ARM_OP_MRS_CPSR 0 #define ARM_OP_SWP 0 #define ARM_OP_MSR_CPSR 0 #define ARM_OP_BX 0 #define ARM_OP_BLX_REG 0 #define ARM_OP_BKPT 0 #define ARM_OP_MRS_SPSR 0 #define ARM_OP_SWPB 0 #define ARM_OP_MSR_SPSR 0 #define ARM_OP_STREX 0 #define ARM_OP_LDREX 0 #define ARM_OP_MSR_CPSR_IMM_VAL 0 #define ARM_OP_MSR_SPSR_IMM_VAL 0 #define ARM_OP_STMDA 0 #define ARM_OP_LDMDA 0 #define ARM_OP_STMDA_W 0 #define ARM_OP_LDMDA_W 0 #define ARM_OP_STMDA2 0 #define ARM_OP_LDMDA2 0 #define ARM_OP_STMDA2_W 0 #define ARM_OP_LDMDA2_W 0 #define ARM_OP_STMIA 0 #define ARM_OP_LDMIA 0 #define ARM_OP_STMIA_W 0 #define ARM_OP_LDMIA_W 0 #define ARM_OP_STMIA2 0 #define ARM_OP_LDMIA2 0 #define ARM_OP_STMIA2_W 0 #define ARM_OP_LDMIA2_W 0 #define ARM_OP_STMDB 0 #define ARM_OP_LDMDB 0 #define ARM_OP_STMDB_W 0 #define ARM_OP_LDMDB_W 0 #define ARM_OP_STMDB2 0 #define ARM_OP_LDMDB2 0 #define ARM_OP_STMDB2_W 0 #define ARM_OP_LDMDB2_W 0 #define ARM_OP_STMIB 0 #define ARM_OP_LDMIB 0 #define ARM_OP_STMIB_W 0 #define ARM_OP_LDMIB_W 0 #define ARM_OP_STMIB2 0 #define ARM_OP_LDMIB2 0 #define ARM_OP_STMIB2_W 0 #define ARM_OP_LDMIB2_W 0 #define ARM_OP_STC_OPTION 0 #define ARM_OP_LDC_OPTION 0 #define ARM_OP_STC_M_POSTIND 0 #define ARM_OP_LDC_M_POSTIND 0 #define ARM_OP_STC_P_POSTIND 0 #define ARM_OP_LDC_P_POSTIND 0 #define ARM_OP_STC_M_IMM_OFF 0 #define ARM_OP_LDC_M_IMM_OFF 0 #define ARM_OP_STC_M_PREIND 0 #define ARM_OP_LDC_M_PREIND 0 #define ARM_OP_STC_P_IMM_OFF 0 #define ARM_OP_LDC_P_IMM_OFF 0 #define ARM_OP_STC_P_PREIND 0 #define ARM_OP_LDC_P_PREIND 0 #define ARM_OP_CDP 0 #define ARM_OP_MCR 0 #define ARM_OP_MRC 0 #define ARM_OP_SWI 0 #define ARM_OP_UND 0 static const ArmOpCompiler arm_instruction_compilers[4096] = { #define TABDECL(x) ARM_##x #include "instruction_tabdef.inc" #undef TABDECL }; //////// // THUMB //////// static OP_RESULT THUMB_OP_SHIFT(uint32_t pc, uint32_t opcode) { const uint32_t rd = bit(opcode, 0, 3); const uint32_t rs = bit(opcode, 3, 3); const uint32_t imm = bit(opcode, 6, 5); const AG_ALU_SHIFT op = (AG_ALU_SHIFT)bit(opcode, 11, 2); int32_t regs[2] = { rd | 0x10, rs }; regman->get(2, regs); const reg_t nrd = regs[0]; const reg_t nrs = regs[1]; block->movs(nrd, alu2::reg_shift_imm(nrs, op, imm)); mark_status_dirty(); regman->mark_dirty(nrd); return OPR_RESULT(OPR_CONTINUE, 1); } static OP_RESULT THUMB_OP_ADDSUB_REGIMM(uint32_t pc, uint32_t opcode) { const uint32_t rd = bit(opcode, 0, 3); const uint32_t rs = bit(opcode, 3, 3); const AG_ALU_OP op = bit(opcode, 9) ? SUBS : ADDS; const bool arg_type = bit(opcode, 10); const uint32_t arg = bit(opcode, 6, 3); int32_t regs[3] = { rd | 0x10, rs, (!arg_type) ? arg : -1 }; regman->get(3, regs); const reg_t nrd = regs[0]; const reg_t nrs = regs[1]; if (arg_type) // Immediate { block->alu_op(op, nrd, nrs, alu2::imm(arg)); mark_status_dirty(); } else { block->alu_op(op, nrd, nrs, alu2::reg(regs[2])); mark_status_dirty(); } regman->mark_dirty(nrd); return OPR_RESULT(OPR_CONTINUE, 1); } static OP_RESULT THUMB_OP_MCAS_IMM8(uint32_t pc, uint32_t opcode) { const reg_t rd = bit(opcode, 8, 3); const uint32_t op = bit(opcode, 11, 2); const uint32_t imm = bit(opcode, 0, 8); int32_t regs[1] = { rd }; regman->get(1, regs); const reg_t nrd = regs[0]; switch (op) { case 0: block->alu_op(MOVS, nrd, nrd, alu2::imm(imm)); break; case 1: block->alu_op(CMP , nrd, nrd, alu2::imm(imm)); break; case 2: block->alu_op(ADDS, nrd, nrd, alu2::imm(imm)); break; case 3: block->alu_op(SUBS, nrd, nrd, alu2::imm(imm)); break; } mark_status_dirty(); if (op != 1) // Don't keep the result of a CMP instruction { regman->mark_dirty(nrd); } return OPR_RESULT(OPR_CONTINUE, 1); } static OP_RESULT THUMB_OP_ALU(uint32_t pc, uint32_t opcode) { const uint32_t rd = bit(opcode, 0, 3); const uint32_t rs = bit(opcode, 3, 3); const uint32_t op = bit(opcode, 6, 4); bool need_writeback = false; if (op == 13) // TODO: The MULS is interpreted for now { return OPR_INTERPRET; } int32_t regs[2] = { rd, rs }; regman->get(2, regs); const reg_t nrd = regs[0]; const reg_t nrs = regs[1]; switch (op) { case 0: block->ands(nrd, alu2::reg(nrs)); break; case 1: block->eors(nrd, alu2::reg(nrs)); break; case 5: block->adcs(nrd, alu2::reg(nrs)); break; case 6: block->sbcs(nrd, alu2::reg(nrs)); break; case 8: block->tst (nrd, alu2::reg(nrs)); break; case 10: block->cmp (nrd, alu2::reg(nrs)); break; case 11: block->cmn (nrd, alu2::reg(nrs)); break; case 12: block->orrs(nrd, alu2::reg(nrs)); break; case 14: block->bics(nrd, alu2::reg(nrs)); break; case 15: block->mvns(nrd, alu2::reg(nrs)); break; case 2: block->movs(nrd, alu2::reg_shift_reg(nrd, LSL, nrs)); break; case 3: block->movs(nrd, alu2::reg_shift_reg(nrd, LSR, nrs)); break; case 4: block->movs(nrd, alu2::reg_shift_reg(nrd, ASR, nrs)); break; case 7: block->movs(nrd, alu2::reg_shift_reg(nrd, arm_gen::ROR, nrs)); break; case 9: block->rsbs(nrd, nrs, alu2::imm(0)); break; } mark_status_dirty(); static const bool op_wb[16] = { 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1 }; if (op_wb[op]) { regman->mark_dirty(nrd); } return OPR_RESULT(OPR_CONTINUE, 1); } static OP_RESULT THUMB_OP_SPE(uint32_t pc, uint32_t opcode) { const uint32_t rd = bit(opcode, 0, 3) + (bit(opcode, 7) ? 8 : 0); const uint32_t rs = bit(opcode, 3, 4); const uint32_t op = bit(opcode, 8, 2); if (rd == 0xF || rs == 0xF) { return OPR_INTERPRET; } int32_t regs[2] = { rd, rs }; regman->get(2, regs); const reg_t nrd = regs[0]; const reg_t nrs = regs[1]; switch (op) { case 0: block->add(nrd, alu2::reg(nrs)); break; case 1: block->cmp(nrd, alu2::reg(nrs)); break; case 2: block->mov(nrd, alu2::reg(nrs)); break; } if (op != 1) { regman->mark_dirty(nrd); } else { mark_status_dirty(); } return OPR_RESULT(OPR_CONTINUE, 1); } static OP_RESULT THUMB_OP_MEMORY_DELEGATE(uint32_t pc, uint32_t opcode, bool LOAD, uint32_t SIZE, uint32_t EXTEND, bool REG_OFFSET) { const uint32_t rd = bit(opcode, 0, 3); const uint32_t rb = bit(opcode, 3, 3); const uint32_t ro = bit(opcode, 6, 3); const uint32_t off = bit(opcode, 6, 5); int32_t regs[3] = { rd | (LOAD ? 0x10 : 0), rb, REG_OFFSET ? ro : -1}; regman->get(3, regs); const reg_t dest = regs[0]; const reg_t base = regs[1]; // Calc EA if (REG_OFFSET) { const reg_t offset = regs[2]; block->mov(0, alu2::reg(base)); block->add(0, alu2::reg(offset)); } else { block->add(0, base, alu2::imm(off << SIZE)); } // Load access function block->load_constant(2, mem_funcs[(SIZE << 2) + (LOAD ? 0 : 2) + block_procnum]); if (!LOAD) { block->mov(1, alu2::reg(dest)); } call(2); if (LOAD) { if (EXTEND) { if (SIZE == 0) { block->sxtb(dest, 0); } else { block->sxth(dest, 0); } } else { block->mov(dest, alu2::reg(0)); } regman->mark_dirty(dest); } // TODO return OPR_RESULT(OPR_CONTINUE, 3); } // SIZE: 0=8, 1=16, 2=32 template static OP_RESULT THUMB_OP_MEMORY(uint32_t pc, uint32_t opcode) { return THUMB_OP_MEMORY_DELEGATE(pc, opcode, LOAD, SIZE, EXTEND, REG_OFFSET); } static OP_RESULT THUMB_OP_LDR_PCREL(uint32_t pc, uint32_t opcode) { const uint32_t offset = bit(opcode, 0, 8); const reg_t rd = bit(opcode, 8, 3); int32_t regs[1] = { rd | 0x10 }; regman->get(1, regs); const reg_t dest = regs[0]; block->load_constant(0, ((pc + 4) & ~2) + (offset << 2)); block->load_constant(2, mem_funcs[8 + block_procnum]); call(2); block->mov(dest, alu2::reg(0)); regman->mark_dirty(dest); return OPR_RESULT(OPR_CONTINUE, 3); } static OP_RESULT THUMB_OP_STR_SPREL(uint32_t pc, uint32_t opcode) { const uint32_t offset = bit(opcode, 0, 8); const reg_t rd = bit(opcode, 8, 3); int32_t regs[2] = { rd, 13 }; regman->get(2, regs); const reg_t src = regs[0]; const reg_t base = regs[1]; block->add(0, base, alu2::imm_rol(offset, 2)); block->mov(1, alu2::reg(src)); block->load_constant(2, mem_funcs[10 + block_procnum]); call(2); return OPR_RESULT(OPR_CONTINUE, 3); } static OP_RESULT THUMB_OP_LDR_SPREL(uint32_t pc, uint32_t opcode) { const uint32_t offset = bit(opcode, 0, 8); const reg_t rd = bit(opcode, 8, 3); int32_t regs[2] = { rd | 0x10, 13 }; regman->get(2, regs); const reg_t dest = regs[0]; const reg_t base = regs[1]; block->add(0, base, alu2::imm_rol(offset, 2)); block->load_constant(2, mem_funcs[8 + block_procnum]); call(2); block->mov(dest, alu2::reg(0)); regman->mark_dirty(dest); return OPR_RESULT(OPR_CONTINUE, 3); } static OP_RESULT THUMB_OP_B_COND(uint32_t pc, uint32_t opcode) { const AG_COND cond = (AG_COND)bit(opcode, 8, 4); block->load_constant(0, pc + 2); block->load_constant(0, (pc + 4) + ((u32)((s8)(opcode&0xFF))<<1), cond); block->str(0, RCPU, mem2::imm(offsetof(armcpu_t, instruct_adr))); block->add(RCYC, alu2::imm(2), cond); return OPR_RESULT(OPR_BRANCHED, 1); } static OP_RESULT THUMB_OP_B_UNCOND(uint32_t pc, uint32_t opcode) { int32_t offs = (opcode & 0x7FF) | (bit(opcode, 10) ? 0xFFFFF800 : 0); block->load_constant(0, pc + 4 + (offs << 1)); block->str(0, RCPU, mem2::imm(offsetof(armcpu_t, instruct_adr))); return OPR_RESULT(OPR_BRANCHED, 3); } static OP_RESULT THUMB_OP_ADJUST_SP(uint32_t pc, uint32_t opcode) { const uint32_t offs = bit(opcode, 0, 7); int32_t regs[1] = { 13 }; regman->get(1, regs); const reg_t sp = regs[0]; if (bit(opcode, 7)) block->sub(sp, alu2::imm_rol(offs, 2)); else block->add(sp, alu2::imm_rol(offs, 2)); regman->mark_dirty(sp); return OPR_RESULT(OPR_CONTINUE, 1); } static OP_RESULT THUMB_OP_ADD_2PC(uint32_t pc, uint32_t opcode) { const uint32_t offset = bit(opcode, 0, 8); const reg_t rd = bit(opcode, 8, 3); int32_t regs[1] = { rd | 0x10 }; regman->get(1, regs); const reg_t dest = regs[0]; block->load_constant(dest, ((pc + 4) & 0xFFFFFFFC) + (offset << 2)); regman->mark_dirty(dest); return OPR_RESULT(OPR_CONTINUE, 1); } static OP_RESULT THUMB_OP_ADD_2SP(uint32_t pc, uint32_t opcode) { const uint32_t offset = bit(opcode, 0, 8); const reg_t rd = bit(opcode, 8, 3); int32_t regs[2] = { 13, rd | 0x10 }; regman->get(2, regs); const reg_t sp = regs[0]; const reg_t dest = regs[1]; block->add(dest, sp, alu2::imm_rol(offset, 2)); regman->mark_dirty(dest); return OPR_RESULT(OPR_CONTINUE, 1); } static OP_RESULT THUMB_OP_BX_BLX_THUMB(uint32_t pc, uint32_t opcode) { const reg_t rm = bit(opcode, 3, 4); const bool link = bit(opcode, 7); if (rm == 15) return OPR_INTERPRET; block->load_constant(0, pc + 4); int32_t regs[2] = { link ? 14 : -1, (rm != 15) ? (int32_t)rm : -1 }; regman->get(2, regs); if (link) { const reg_t lr = regs[0]; block->sub(lr, 0, alu2::imm(1)); regman->mark_dirty(lr); } reg_t target = regs[1]; change_mode_reg(target, 2, 3); block->bic(0, target, alu2::imm(1)); block->str(0, RCPU, mem2::imm(offsetof(armcpu_t, instruct_adr))); return OPR_RESULT(OPR_BRANCHED, 3); } #if 1 #define THUMB_OP_BL_LONG 0 #else static OP_RESULT THUMB_OP_BL_LONG(uint32_t pc, uint32_t opcode) { static const uint32_t op = bit(opcode, 11, 5); int32_t offset = bit(opcode, 0, 11); reg_t lr = regman->get(14, op == 0x1E); if (op == 0x1E) { offset |= (offset & 0x400) ? 0xFFFFF800 : 0; block->load_constant(lr, (pc + 4) + (offset << 12)); } else { block->load_constant(0, offset << 1); block->add(0, lr, alu2::reg(0)); block->str(0, RCPU, mem2::imm(offsetof(armcpu_t, instruct_adr))); block->load_constant(lr, pc + 3); if (op != 0x1F) { change_mode(false); } } regman->mark_dirty(lr); if (op == 0x1E) { return OPR_RESULT(OPR_CONTINUE, 1); } else { return OPR_RESULT(OPR_BRANCHED, (op == 0x1F) ? 3 : 4); } } #endif #define THUMB_OP_INTERPRET 0 #define THUMB_OP_UND_THUMB THUMB_OP_INTERPRET #define THUMB_OP_LSL THUMB_OP_SHIFT #define THUMB_OP_LSL_0 THUMB_OP_SHIFT #define THUMB_OP_LSR THUMB_OP_SHIFT #define THUMB_OP_LSR_0 THUMB_OP_SHIFT #define THUMB_OP_ASR THUMB_OP_SHIFT #define THUMB_OP_ASR_0 THUMB_OP_SHIFT #define THUMB_OP_ADD_REG THUMB_OP_ADDSUB_REGIMM #define THUMB_OP_SUB_REG THUMB_OP_ADDSUB_REGIMM #define THUMB_OP_ADD_IMM3 THUMB_OP_ADDSUB_REGIMM #define THUMB_OP_SUB_IMM3 THUMB_OP_ADDSUB_REGIMM #define THUMB_OP_MOV_IMM8 THUMB_OP_MCAS_IMM8 #define THUMB_OP_CMP_IMM8 THUMB_OP_MCAS_IMM8 #define THUMB_OP_ADD_IMM8 THUMB_OP_MCAS_IMM8 #define THUMB_OP_SUB_IMM8 THUMB_OP_MCAS_IMM8 #define THUMB_OP_AND THUMB_OP_ALU #define THUMB_OP_EOR THUMB_OP_ALU #define THUMB_OP_LSL_REG THUMB_OP_ALU #define THUMB_OP_LSR_REG THUMB_OP_ALU #define THUMB_OP_ASR_REG THUMB_OP_ALU #define THUMB_OP_ADC_REG THUMB_OP_ALU #define THUMB_OP_SBC_REG THUMB_OP_ALU #define THUMB_OP_ROR_REG THUMB_OP_ALU #define THUMB_OP_TST THUMB_OP_ALU #define THUMB_OP_NEG THUMB_OP_ALU #define THUMB_OP_CMP THUMB_OP_ALU #define THUMB_OP_CMN THUMB_OP_ALU #define THUMB_OP_ORR THUMB_OP_ALU #define THUMB_OP_MUL_REG THUMB_OP_INTERPRET #define THUMB_OP_BIC THUMB_OP_ALU #define THUMB_OP_MVN THUMB_OP_ALU #define THUMB_OP_ADD_SPE THUMB_OP_SPE #define THUMB_OP_CMP_SPE THUMB_OP_SPE #define THUMB_OP_MOV_SPE THUMB_OP_SPE #define THUMB_OP_ADJUST_P_SP THUMB_OP_ADJUST_SP #define THUMB_OP_ADJUST_M_SP THUMB_OP_ADJUST_SP #define THUMB_OP_LDRB_REG_OFF THUMB_OP_MEMORY #define THUMB_OP_LDRH_REG_OFF THUMB_OP_MEMORY #define THUMB_OP_LDR_REG_OFF THUMB_OP_MEMORY #define THUMB_OP_STRB_REG_OFF THUMB_OP_MEMORY #define THUMB_OP_STRH_REG_OFF THUMB_OP_MEMORY #define THUMB_OP_STR_REG_OFF THUMB_OP_MEMORY #define THUMB_OP_LDRB_IMM_OFF THUMB_OP_MEMORY #define THUMB_OP_LDRH_IMM_OFF THUMB_OP_MEMORY #define THUMB_OP_LDR_IMM_OFF THUMB_OP_MEMORY #define THUMB_OP_STRB_IMM_OFF THUMB_OP_MEMORY #define THUMB_OP_STRH_IMM_OFF THUMB_OP_MEMORY #define THUMB_OP_STR_IMM_OFF THUMB_OP_MEMORY #define THUMB_OP_LDRSB_REG_OFF THUMB_OP_MEMORY #define THUMB_OP_LDRSH_REG_OFF THUMB_OP_MEMORY #define THUMB_OP_BX_THUMB THUMB_OP_BX_BLX_THUMB #define THUMB_OP_BLX_THUMB THUMB_OP_BX_BLX_THUMB #define THUMB_OP_BL_10 THUMB_OP_BL_LONG #define THUMB_OP_BL_11 THUMB_OP_BL_LONG #define THUMB_OP_BLX THUMB_OP_BL_LONG // UNDEFINED OPS #define THUMB_OP_PUSH THUMB_OP_INTERPRET #define THUMB_OP_PUSH_LR THUMB_OP_INTERPRET #define THUMB_OP_POP THUMB_OP_INTERPRET #define THUMB_OP_POP_PC THUMB_OP_INTERPRET #define THUMB_OP_BKPT_THUMB THUMB_OP_INTERPRET #define THUMB_OP_STMIA_THUMB THUMB_OP_INTERPRET #define THUMB_OP_LDMIA_THUMB THUMB_OP_INTERPRET #define THUMB_OP_SWI_THUMB THUMB_OP_INTERPRET static const ArmOpCompiler thumb_instruction_compilers[1024] = { #define TABDECL(x) THUMB_##x #include "thumb_tabdef.inc" #undef TABDECL }; // ============================================================================================= IMM //----------------------------------------------------------------------------- // Compiler //----------------------------------------------------------------------------- static u32 instr_attributes(bool thumb, u32 opcode) { return thumb ? thumb_attributes[opcode>>6] : instruction_attributes[INSTRUCTION_INDEX(opcode)]; } static bool instr_is_branch(bool thumb, u32 opcode) { u32 x = instr_attributes(thumb, opcode); if(thumb) return (x & BRANCH_ALWAYS) || ((x & BRANCH_POS0) && ((opcode&7) | ((opcode>>4)&8)) == 15) || (x & BRANCH_SWI) || (x & JIT_BYPASS); else return (x & BRANCH_ALWAYS) || ((x & BRANCH_POS12) && REG_POS(opcode,12) == 15) || ((x & BRANCH_LDM) && BIT15(opcode)) || (x & BRANCH_SWI) || (x & JIT_BYPASS); } template static ArmOpCompiled compile_basicblock() { block_procnum = PROCNUM; const bool thumb = ARMPROC.CPSR.bits.T == 1; const u32 base = ARMPROC.instruct_adr; const u32 isize = thumb ? 2 : 4; uint32_t pc = base; bool compiled_op = true; bool has_ended = false; uint32_t constant_cycles = 0; // NOTE: Expected register usage // R5 = Pointer to ARMPROC // R6 = Cycle counter regman->reset(); block->push(0x4DF0); block->load_constant(RCPU, (uint32_t)&ARMPROC); block->load_constant(RCYC, 0); load_status(3); for (uint32_t i = 0; i < CommonSettings.jit_max_block_size && !has_ended; i ++, pc += isize) { uint32_t opcode = thumb ? _MMU_read16(pc) : _MMU_read32(pc); ArmOpCompiler compiler = thumb ? thumb_instruction_compilers[opcode >> 6] : arm_instruction_compilers[INSTRUCTION_INDEX(opcode)]; int result = compiler ? compiler(pc, opcode) : OPR_INTERPRET; constant_cycles += OPR_RESULT_CYCLES(result); switch (OPR_RESULT_ACTION(result)) { case OPR_INTERPRET: { if (compiled_op) { arm_jit_prefetch(pc, opcode, thumb); compiled_op = false; } regman->flush_all(); regman->reset(); block->load_constant(0, (uint32_t)&armcpu_exec); call(0); block->add(RCYC, alu2::reg(0)); has_ended = has_ended || instr_is_branch(thumb, opcode); break; } case OPR_BRANCHED: { has_ended = true; compiled_op = false; break; } case OPR_CONTINUE: { compiled_op = true; break; } } } if (compiled_op) { block->load_constant(0, pc); block->str(0, RCPU, mem2::imm(offsetof(armcpu_t, instruct_adr))); } write_status(3); regman->flush_all(); regman->reset(); block->load_constant(1, constant_cycles); block->add(0, 1, alu2::reg(RCYC)); block->pop(0x8DF0); void* fn_ptr = block->fn_pointer(); JIT_COMPILED_FUNC(base, PROCNUM) = (uintptr_t)fn_ptr; return (ArmOpCompiled)fn_ptr; } template u32 arm_jit_compile() { u32 adr = ARMPROC.instruct_adr; u32 mask_adr = (adr & 0x07FFFFFE) >> 4; if(((recompile_counts[mask_adr >> 1] >> 4*(mask_adr & 1)) & 0xF) > 8) { ArmOpCompiled f = op_decode[PROCNUM][ARMPROC.CPSR.bits.T]; JIT_COMPILED_FUNC(adr, PROCNUM) = (uintptr_t)f; return f(); } recompile_counts[mask_adr >> 1] += 1 << 4*(mask_adr & 1); if (block->instructions_remaining() < 1000) { arm_jit_reset(true); } return compile_basicblock()(); } template u32 arm_jit_compile<0>(); template u32 arm_jit_compile<1>(); void arm_jit_reset(bool enable, bool suppress_msg) { if (!suppress_msg) printf("CPU mode: %s\n", enable?"JIT":"Interpreter"); saveBlockSizeJIT = CommonSettings.jit_max_block_size; if (enable) { printf("JIT: max block size %d instruction(s)\n", CommonSettings.jit_max_block_size); #ifdef MAPPED_JIT_FUNCS #define JITFREE(x) memset(x,0,sizeof(x)); JITFREE(JIT.MAIN_MEM); JITFREE(JIT.SWIRAM); JITFREE(JIT.ARM9_ITCM); JITFREE(JIT.ARM9_LCDC); JITFREE(JIT.ARM9_BIOS); JITFREE(JIT.ARM7_BIOS); JITFREE(JIT.ARM7_ERAM); JITFREE(JIT.ARM7_WIRAM); JITFREE(JIT.ARM7_WRAM); #undef JITFREE memset(recompile_counts, 0, sizeof(recompile_counts)); init_jit_mem(); #else for(int i=0; i #ifdef __cplusplus extern "C" { #endif extern PFN_vkCreateInstance vulkan_symbol_wrapper_vkCreateInstance; #define vkCreateInstance vulkan_symbol_wrapper_vkCreateInstance extern PFN_vkEnumerateInstanceExtensionProperties vulkan_symbol_wrapper_vkEnumerateInstanceExtensionProperties; #define vkEnumerateInstanceExtensionProperties vulkan_symbol_wrapper_vkEnumerateInstanceExtensionProperties extern PFN_vkEnumerateInstanceLayerProperties vulkan_symbol_wrapper_vkEnumerateInstanceLayerProperties; #define vkEnumerateInstanceLayerProperties vulkan_symbol_wrapper_vkEnumerateInstanceLayerProperties extern PFN_vkDestroyInstance vulkan_symbol_wrapper_vkDestroyInstance; #define vkDestroyInstance vulkan_symbol_wrapper_vkDestroyInstance extern PFN_vkEnumeratePhysicalDevices vulkan_symbol_wrapper_vkEnumeratePhysicalDevices; #define vkEnumeratePhysicalDevices vulkan_symbol_wrapper_vkEnumeratePhysicalDevices extern PFN_vkGetPhysicalDeviceFeatures vulkan_symbol_wrapper_vkGetPhysicalDeviceFeatures; #define vkGetPhysicalDeviceFeatures vulkan_symbol_wrapper_vkGetPhysicalDeviceFeatures extern PFN_vkGetPhysicalDeviceFormatProperties vulkan_symbol_wrapper_vkGetPhysicalDeviceFormatProperties; #define vkGetPhysicalDeviceFormatProperties vulkan_symbol_wrapper_vkGetPhysicalDeviceFormatProperties extern PFN_vkGetPhysicalDeviceImageFormatProperties vulkan_symbol_wrapper_vkGetPhysicalDeviceImageFormatProperties; #define vkGetPhysicalDeviceImageFormatProperties vulkan_symbol_wrapper_vkGetPhysicalDeviceImageFormatProperties extern PFN_vkGetPhysicalDeviceProperties vulkan_symbol_wrapper_vkGetPhysicalDeviceProperties; #define vkGetPhysicalDeviceProperties vulkan_symbol_wrapper_vkGetPhysicalDeviceProperties extern PFN_vkGetPhysicalDeviceQueueFamilyProperties vulkan_symbol_wrapper_vkGetPhysicalDeviceQueueFamilyProperties; #define vkGetPhysicalDeviceQueueFamilyProperties vulkan_symbol_wrapper_vkGetPhysicalDeviceQueueFamilyProperties extern PFN_vkGetPhysicalDeviceMemoryProperties vulkan_symbol_wrapper_vkGetPhysicalDeviceMemoryProperties; #define vkGetPhysicalDeviceMemoryProperties vulkan_symbol_wrapper_vkGetPhysicalDeviceMemoryProperties extern PFN_vkGetDeviceProcAddr vulkan_symbol_wrapper_vkGetDeviceProcAddr; #define vkGetDeviceProcAddr vulkan_symbol_wrapper_vkGetDeviceProcAddr extern PFN_vkCreateDevice vulkan_symbol_wrapper_vkCreateDevice; #define vkCreateDevice vulkan_symbol_wrapper_vkCreateDevice extern PFN_vkDestroyDevice vulkan_symbol_wrapper_vkDestroyDevice; #define vkDestroyDevice vulkan_symbol_wrapper_vkDestroyDevice extern PFN_vkEnumerateDeviceExtensionProperties vulkan_symbol_wrapper_vkEnumerateDeviceExtensionProperties; #define vkEnumerateDeviceExtensionProperties vulkan_symbol_wrapper_vkEnumerateDeviceExtensionProperties extern PFN_vkEnumerateDeviceLayerProperties vulkan_symbol_wrapper_vkEnumerateDeviceLayerProperties; #define vkEnumerateDeviceLayerProperties vulkan_symbol_wrapper_vkEnumerateDeviceLayerProperties extern PFN_vkGetDeviceQueue vulkan_symbol_wrapper_vkGetDeviceQueue; #define vkGetDeviceQueue vulkan_symbol_wrapper_vkGetDeviceQueue extern PFN_vkQueueSubmit vulkan_symbol_wrapper_vkQueueSubmit; #define vkQueueSubmit vulkan_symbol_wrapper_vkQueueSubmit extern PFN_vkQueueWaitIdle vulkan_symbol_wrapper_vkQueueWaitIdle; #define vkQueueWaitIdle vulkan_symbol_wrapper_vkQueueWaitIdle extern PFN_vkDeviceWaitIdle vulkan_symbol_wrapper_vkDeviceWaitIdle; #define vkDeviceWaitIdle vulkan_symbol_wrapper_vkDeviceWaitIdle extern PFN_vkAllocateMemory vulkan_symbol_wrapper_vkAllocateMemory; #define vkAllocateMemory vulkan_symbol_wrapper_vkAllocateMemory extern PFN_vkFreeMemory vulkan_symbol_wrapper_vkFreeMemory; #define vkFreeMemory vulkan_symbol_wrapper_vkFreeMemory extern PFN_vkMapMemory vulkan_symbol_wrapper_vkMapMemory; #define vkMapMemory vulkan_symbol_wrapper_vkMapMemory extern PFN_vkUnmapMemory vulkan_symbol_wrapper_vkUnmapMemory; #define vkUnmapMemory vulkan_symbol_wrapper_vkUnmapMemory extern PFN_vkFlushMappedMemoryRanges vulkan_symbol_wrapper_vkFlushMappedMemoryRanges; #define vkFlushMappedMemoryRanges vulkan_symbol_wrapper_vkFlushMappedMemoryRanges extern PFN_vkInvalidateMappedMemoryRanges vulkan_symbol_wrapper_vkInvalidateMappedMemoryRanges; #define vkInvalidateMappedMemoryRanges vulkan_symbol_wrapper_vkInvalidateMappedMemoryRanges extern PFN_vkGetDeviceMemoryCommitment vulkan_symbol_wrapper_vkGetDeviceMemoryCommitment; #define vkGetDeviceMemoryCommitment vulkan_symbol_wrapper_vkGetDeviceMemoryCommitment extern PFN_vkBindBufferMemory vulkan_symbol_wrapper_vkBindBufferMemory; #define vkBindBufferMemory vulkan_symbol_wrapper_vkBindBufferMemory extern PFN_vkBindImageMemory vulkan_symbol_wrapper_vkBindImageMemory; #define vkBindImageMemory vulkan_symbol_wrapper_vkBindImageMemory extern PFN_vkGetBufferMemoryRequirements vulkan_symbol_wrapper_vkGetBufferMemoryRequirements; #define vkGetBufferMemoryRequirements vulkan_symbol_wrapper_vkGetBufferMemoryRequirements extern PFN_vkGetImageMemoryRequirements vulkan_symbol_wrapper_vkGetImageMemoryRequirements; #define vkGetImageMemoryRequirements vulkan_symbol_wrapper_vkGetImageMemoryRequirements extern PFN_vkGetImageSparseMemoryRequirements vulkan_symbol_wrapper_vkGetImageSparseMemoryRequirements; #define vkGetImageSparseMemoryRequirements vulkan_symbol_wrapper_vkGetImageSparseMemoryRequirements extern PFN_vkGetPhysicalDeviceSparseImageFormatProperties vulkan_symbol_wrapper_vkGetPhysicalDeviceSparseImageFormatProperties; #define vkGetPhysicalDeviceSparseImageFormatProperties vulkan_symbol_wrapper_vkGetPhysicalDeviceSparseImageFormatProperties extern PFN_vkQueueBindSparse vulkan_symbol_wrapper_vkQueueBindSparse; #define vkQueueBindSparse vulkan_symbol_wrapper_vkQueueBindSparse extern PFN_vkCreateFence vulkan_symbol_wrapper_vkCreateFence; #define vkCreateFence vulkan_symbol_wrapper_vkCreateFence extern PFN_vkDestroyFence vulkan_symbol_wrapper_vkDestroyFence; #define vkDestroyFence vulkan_symbol_wrapper_vkDestroyFence extern PFN_vkResetFences vulkan_symbol_wrapper_vkResetFences; #define vkResetFences vulkan_symbol_wrapper_vkResetFences extern PFN_vkGetFenceStatus vulkan_symbol_wrapper_vkGetFenceStatus; #define vkGetFenceStatus vulkan_symbol_wrapper_vkGetFenceStatus extern PFN_vkWaitForFences vulkan_symbol_wrapper_vkWaitForFences; #define vkWaitForFences vulkan_symbol_wrapper_vkWaitForFences extern PFN_vkCreateSemaphore vulkan_symbol_wrapper_vkCreateSemaphore; #define vkCreateSemaphore vulkan_symbol_wrapper_vkCreateSemaphore extern PFN_vkDestroySemaphore vulkan_symbol_wrapper_vkDestroySemaphore; #define vkDestroySemaphore vulkan_symbol_wrapper_vkDestroySemaphore extern PFN_vkCreateEvent vulkan_symbol_wrapper_vkCreateEvent; #define vkCreateEvent vulkan_symbol_wrapper_vkCreateEvent extern PFN_vkDestroyEvent vulkan_symbol_wrapper_vkDestroyEvent; #define vkDestroyEvent vulkan_symbol_wrapper_vkDestroyEvent extern PFN_vkGetEventStatus vulkan_symbol_wrapper_vkGetEventStatus; #define vkGetEventStatus vulkan_symbol_wrapper_vkGetEventStatus extern PFN_vkSetEvent vulkan_symbol_wrapper_vkSetEvent; #define vkSetEvent vulkan_symbol_wrapper_vkSetEvent extern PFN_vkResetEvent vulkan_symbol_wrapper_vkResetEvent; #define vkResetEvent vulkan_symbol_wrapper_vkResetEvent extern PFN_vkCreateQueryPool vulkan_symbol_wrapper_vkCreateQueryPool; #define vkCreateQueryPool vulkan_symbol_wrapper_vkCreateQueryPool extern PFN_vkDestroyQueryPool vulkan_symbol_wrapper_vkDestroyQueryPool; #define vkDestroyQueryPool vulkan_symbol_wrapper_vkDestroyQueryPool extern PFN_vkGetQueryPoolResults vulkan_symbol_wrapper_vkGetQueryPoolResults; #define vkGetQueryPoolResults vulkan_symbol_wrapper_vkGetQueryPoolResults extern PFN_vkCreateBuffer vulkan_symbol_wrapper_vkCreateBuffer; #define vkCreateBuffer vulkan_symbol_wrapper_vkCreateBuffer extern PFN_vkDestroyBuffer vulkan_symbol_wrapper_vkDestroyBuffer; #define vkDestroyBuffer vulkan_symbol_wrapper_vkDestroyBuffer extern PFN_vkCreateBufferView vulkan_symbol_wrapper_vkCreateBufferView; #define vkCreateBufferView vulkan_symbol_wrapper_vkCreateBufferView extern PFN_vkDestroyBufferView vulkan_symbol_wrapper_vkDestroyBufferView; #define vkDestroyBufferView vulkan_symbol_wrapper_vkDestroyBufferView extern PFN_vkCreateImage vulkan_symbol_wrapper_vkCreateImage; #define vkCreateImage vulkan_symbol_wrapper_vkCreateImage extern PFN_vkDestroyImage vulkan_symbol_wrapper_vkDestroyImage; #define vkDestroyImage vulkan_symbol_wrapper_vkDestroyImage extern PFN_vkGetImageSubresourceLayout vulkan_symbol_wrapper_vkGetImageSubresourceLayout; #define vkGetImageSubresourceLayout vulkan_symbol_wrapper_vkGetImageSubresourceLayout extern PFN_vkCreateImageView vulkan_symbol_wrapper_vkCreateImageView; #define vkCreateImageView vulkan_symbol_wrapper_vkCreateImageView extern PFN_vkDestroyImageView vulkan_symbol_wrapper_vkDestroyImageView; #define vkDestroyImageView vulkan_symbol_wrapper_vkDestroyImageView extern PFN_vkCreateShaderModule vulkan_symbol_wrapper_vkCreateShaderModule; #define vkCreateShaderModule vulkan_symbol_wrapper_vkCreateShaderModule extern PFN_vkDestroyShaderModule vulkan_symbol_wrapper_vkDestroyShaderModule; #define vkDestroyShaderModule vulkan_symbol_wrapper_vkDestroyShaderModule extern PFN_vkCreatePipelineCache vulkan_symbol_wrapper_vkCreatePipelineCache; #define vkCreatePipelineCache vulkan_symbol_wrapper_vkCreatePipelineCache extern PFN_vkDestroyPipelineCache vulkan_symbol_wrapper_vkDestroyPipelineCache; #define vkDestroyPipelineCache vulkan_symbol_wrapper_vkDestroyPipelineCache extern PFN_vkGetPipelineCacheData vulkan_symbol_wrapper_vkGetPipelineCacheData; #define vkGetPipelineCacheData vulkan_symbol_wrapper_vkGetPipelineCacheData extern PFN_vkMergePipelineCaches vulkan_symbol_wrapper_vkMergePipelineCaches; #define vkMergePipelineCaches vulkan_symbol_wrapper_vkMergePipelineCaches extern PFN_vkCreateGraphicsPipelines vulkan_symbol_wrapper_vkCreateGraphicsPipelines; #define vkCreateGraphicsPipelines vulkan_symbol_wrapper_vkCreateGraphicsPipelines extern PFN_vkCreateComputePipelines vulkan_symbol_wrapper_vkCreateComputePipelines; #define vkCreateComputePipelines vulkan_symbol_wrapper_vkCreateComputePipelines extern PFN_vkDestroyPipeline vulkan_symbol_wrapper_vkDestroyPipeline; #define vkDestroyPipeline vulkan_symbol_wrapper_vkDestroyPipeline extern PFN_vkCreatePipelineLayout vulkan_symbol_wrapper_vkCreatePipelineLayout; #define vkCreatePipelineLayout vulkan_symbol_wrapper_vkCreatePipelineLayout extern PFN_vkDestroyPipelineLayout vulkan_symbol_wrapper_vkDestroyPipelineLayout; #define vkDestroyPipelineLayout vulkan_symbol_wrapper_vkDestroyPipelineLayout extern PFN_vkCreateSampler vulkan_symbol_wrapper_vkCreateSampler; #define vkCreateSampler vulkan_symbol_wrapper_vkCreateSampler extern PFN_vkDestroySampler vulkan_symbol_wrapper_vkDestroySampler; #define vkDestroySampler vulkan_symbol_wrapper_vkDestroySampler extern PFN_vkCreateDescriptorSetLayout vulkan_symbol_wrapper_vkCreateDescriptorSetLayout; #define vkCreateDescriptorSetLayout vulkan_symbol_wrapper_vkCreateDescriptorSetLayout extern PFN_vkDestroyDescriptorSetLayout vulkan_symbol_wrapper_vkDestroyDescriptorSetLayout; #define vkDestroyDescriptorSetLayout vulkan_symbol_wrapper_vkDestroyDescriptorSetLayout extern PFN_vkCreateDescriptorPool vulkan_symbol_wrapper_vkCreateDescriptorPool; #define vkCreateDescriptorPool vulkan_symbol_wrapper_vkCreateDescriptorPool extern PFN_vkDestroyDescriptorPool vulkan_symbol_wrapper_vkDestroyDescriptorPool; #define vkDestroyDescriptorPool vulkan_symbol_wrapper_vkDestroyDescriptorPool extern PFN_vkResetDescriptorPool vulkan_symbol_wrapper_vkResetDescriptorPool; #define vkResetDescriptorPool vulkan_symbol_wrapper_vkResetDescriptorPool extern PFN_vkAllocateDescriptorSets vulkan_symbol_wrapper_vkAllocateDescriptorSets; #define vkAllocateDescriptorSets vulkan_symbol_wrapper_vkAllocateDescriptorSets extern PFN_vkFreeDescriptorSets vulkan_symbol_wrapper_vkFreeDescriptorSets; #define vkFreeDescriptorSets vulkan_symbol_wrapper_vkFreeDescriptorSets extern PFN_vkUpdateDescriptorSets vulkan_symbol_wrapper_vkUpdateDescriptorSets; #define vkUpdateDescriptorSets vulkan_symbol_wrapper_vkUpdateDescriptorSets extern PFN_vkCreateFramebuffer vulkan_symbol_wrapper_vkCreateFramebuffer; #define vkCreateFramebuffer vulkan_symbol_wrapper_vkCreateFramebuffer extern PFN_vkDestroyFramebuffer vulkan_symbol_wrapper_vkDestroyFramebuffer; #define vkDestroyFramebuffer vulkan_symbol_wrapper_vkDestroyFramebuffer extern PFN_vkCreateRenderPass vulkan_symbol_wrapper_vkCreateRenderPass; #define vkCreateRenderPass vulkan_symbol_wrapper_vkCreateRenderPass extern PFN_vkDestroyRenderPass vulkan_symbol_wrapper_vkDestroyRenderPass; #define vkDestroyRenderPass vulkan_symbol_wrapper_vkDestroyRenderPass extern PFN_vkGetRenderAreaGranularity vulkan_symbol_wrapper_vkGetRenderAreaGranularity; #define vkGetRenderAreaGranularity vulkan_symbol_wrapper_vkGetRenderAreaGranularity extern PFN_vkCreateCommandPool vulkan_symbol_wrapper_vkCreateCommandPool; #define vkCreateCommandPool vulkan_symbol_wrapper_vkCreateCommandPool extern PFN_vkDestroyCommandPool vulkan_symbol_wrapper_vkDestroyCommandPool; #define vkDestroyCommandPool vulkan_symbol_wrapper_vkDestroyCommandPool extern PFN_vkResetCommandPool vulkan_symbol_wrapper_vkResetCommandPool; #define vkResetCommandPool vulkan_symbol_wrapper_vkResetCommandPool extern PFN_vkAllocateCommandBuffers vulkan_symbol_wrapper_vkAllocateCommandBuffers; #define vkAllocateCommandBuffers vulkan_symbol_wrapper_vkAllocateCommandBuffers extern PFN_vkFreeCommandBuffers vulkan_symbol_wrapper_vkFreeCommandBuffers; #define vkFreeCommandBuffers vulkan_symbol_wrapper_vkFreeCommandBuffers extern PFN_vkBeginCommandBuffer vulkan_symbol_wrapper_vkBeginCommandBuffer; #define vkBeginCommandBuffer vulkan_symbol_wrapper_vkBeginCommandBuffer extern PFN_vkEndCommandBuffer vulkan_symbol_wrapper_vkEndCommandBuffer; #define vkEndCommandBuffer vulkan_symbol_wrapper_vkEndCommandBuffer extern PFN_vkResetCommandBuffer vulkan_symbol_wrapper_vkResetCommandBuffer; #define vkResetCommandBuffer vulkan_symbol_wrapper_vkResetCommandBuffer extern PFN_vkCmdBindPipeline vulkan_symbol_wrapper_vkCmdBindPipeline; #define vkCmdBindPipeline vulkan_symbol_wrapper_vkCmdBindPipeline extern PFN_vkCmdSetViewport vulkan_symbol_wrapper_vkCmdSetViewport; #define vkCmdSetViewport vulkan_symbol_wrapper_vkCmdSetViewport extern PFN_vkCmdSetScissor vulkan_symbol_wrapper_vkCmdSetScissor; #define vkCmdSetScissor vulkan_symbol_wrapper_vkCmdSetScissor extern PFN_vkCmdSetLineWidth vulkan_symbol_wrapper_vkCmdSetLineWidth; #define vkCmdSetLineWidth vulkan_symbol_wrapper_vkCmdSetLineWidth extern PFN_vkCmdSetDepthBias vulkan_symbol_wrapper_vkCmdSetDepthBias; #define vkCmdSetDepthBias vulkan_symbol_wrapper_vkCmdSetDepthBias extern PFN_vkCmdSetBlendConstants vulkan_symbol_wrapper_vkCmdSetBlendConstants; #define vkCmdSetBlendConstants vulkan_symbol_wrapper_vkCmdSetBlendConstants extern PFN_vkCmdSetDepthBounds vulkan_symbol_wrapper_vkCmdSetDepthBounds; #define vkCmdSetDepthBounds vulkan_symbol_wrapper_vkCmdSetDepthBounds extern PFN_vkCmdSetStencilCompareMask vulkan_symbol_wrapper_vkCmdSetStencilCompareMask; #define vkCmdSetStencilCompareMask vulkan_symbol_wrapper_vkCmdSetStencilCompareMask extern PFN_vkCmdSetStencilWriteMask vulkan_symbol_wrapper_vkCmdSetStencilWriteMask; #define vkCmdSetStencilWriteMask vulkan_symbol_wrapper_vkCmdSetStencilWriteMask extern PFN_vkCmdSetStencilReference vulkan_symbol_wrapper_vkCmdSetStencilReference; #define vkCmdSetStencilReference vulkan_symbol_wrapper_vkCmdSetStencilReference extern PFN_vkCmdBindDescriptorSets vulkan_symbol_wrapper_vkCmdBindDescriptorSets; #define vkCmdBindDescriptorSets vulkan_symbol_wrapper_vkCmdBindDescriptorSets extern PFN_vkCmdBindIndexBuffer vulkan_symbol_wrapper_vkCmdBindIndexBuffer; #define vkCmdBindIndexBuffer vulkan_symbol_wrapper_vkCmdBindIndexBuffer extern PFN_vkCmdBindVertexBuffers vulkan_symbol_wrapper_vkCmdBindVertexBuffers; #define vkCmdBindVertexBuffers vulkan_symbol_wrapper_vkCmdBindVertexBuffers extern PFN_vkCmdDraw vulkan_symbol_wrapper_vkCmdDraw; #define vkCmdDraw vulkan_symbol_wrapper_vkCmdDraw extern PFN_vkCmdDrawIndexed vulkan_symbol_wrapper_vkCmdDrawIndexed; #define vkCmdDrawIndexed vulkan_symbol_wrapper_vkCmdDrawIndexed extern PFN_vkCmdDrawIndirect vulkan_symbol_wrapper_vkCmdDrawIndirect; #define vkCmdDrawIndirect vulkan_symbol_wrapper_vkCmdDrawIndirect extern PFN_vkCmdDrawIndexedIndirect vulkan_symbol_wrapper_vkCmdDrawIndexedIndirect; #define vkCmdDrawIndexedIndirect vulkan_symbol_wrapper_vkCmdDrawIndexedIndirect extern PFN_vkCmdDispatch vulkan_symbol_wrapper_vkCmdDispatch; #define vkCmdDispatch vulkan_symbol_wrapper_vkCmdDispatch extern PFN_vkCmdDispatchIndirect vulkan_symbol_wrapper_vkCmdDispatchIndirect; #define vkCmdDispatchIndirect vulkan_symbol_wrapper_vkCmdDispatchIndirect extern PFN_vkCmdCopyBuffer vulkan_symbol_wrapper_vkCmdCopyBuffer; #define vkCmdCopyBuffer vulkan_symbol_wrapper_vkCmdCopyBuffer extern PFN_vkCmdCopyImage vulkan_symbol_wrapper_vkCmdCopyImage; #define vkCmdCopyImage vulkan_symbol_wrapper_vkCmdCopyImage extern PFN_vkCmdBlitImage vulkan_symbol_wrapper_vkCmdBlitImage; #define vkCmdBlitImage vulkan_symbol_wrapper_vkCmdBlitImage extern PFN_vkCmdCopyBufferToImage vulkan_symbol_wrapper_vkCmdCopyBufferToImage; #define vkCmdCopyBufferToImage vulkan_symbol_wrapper_vkCmdCopyBufferToImage extern PFN_vkCmdCopyImageToBuffer vulkan_symbol_wrapper_vkCmdCopyImageToBuffer; #define vkCmdCopyImageToBuffer vulkan_symbol_wrapper_vkCmdCopyImageToBuffer extern PFN_vkCmdUpdateBuffer vulkan_symbol_wrapper_vkCmdUpdateBuffer; #define vkCmdUpdateBuffer vulkan_symbol_wrapper_vkCmdUpdateBuffer extern PFN_vkCmdFillBuffer vulkan_symbol_wrapper_vkCmdFillBuffer; #define vkCmdFillBuffer vulkan_symbol_wrapper_vkCmdFillBuffer extern PFN_vkCmdClearColorImage vulkan_symbol_wrapper_vkCmdClearColorImage; #define vkCmdClearColorImage vulkan_symbol_wrapper_vkCmdClearColorImage extern PFN_vkCmdClearDepthStencilImage vulkan_symbol_wrapper_vkCmdClearDepthStencilImage; #define vkCmdClearDepthStencilImage vulkan_symbol_wrapper_vkCmdClearDepthStencilImage extern PFN_vkCmdClearAttachments vulkan_symbol_wrapper_vkCmdClearAttachments; #define vkCmdClearAttachments vulkan_symbol_wrapper_vkCmdClearAttachments extern PFN_vkCmdResolveImage vulkan_symbol_wrapper_vkCmdResolveImage; #define vkCmdResolveImage vulkan_symbol_wrapper_vkCmdResolveImage extern PFN_vkCmdSetEvent vulkan_symbol_wrapper_vkCmdSetEvent; #define vkCmdSetEvent vulkan_symbol_wrapper_vkCmdSetEvent extern PFN_vkCmdResetEvent vulkan_symbol_wrapper_vkCmdResetEvent; #define vkCmdResetEvent vulkan_symbol_wrapper_vkCmdResetEvent extern PFN_vkCmdWaitEvents vulkan_symbol_wrapper_vkCmdWaitEvents; #define vkCmdWaitEvents vulkan_symbol_wrapper_vkCmdWaitEvents extern PFN_vkCmdPipelineBarrier vulkan_symbol_wrapper_vkCmdPipelineBarrier; #define vkCmdPipelineBarrier vulkan_symbol_wrapper_vkCmdPipelineBarrier extern PFN_vkCmdBeginQuery vulkan_symbol_wrapper_vkCmdBeginQuery; #define vkCmdBeginQuery vulkan_symbol_wrapper_vkCmdBeginQuery extern PFN_vkCmdEndQuery vulkan_symbol_wrapper_vkCmdEndQuery; #define vkCmdEndQuery vulkan_symbol_wrapper_vkCmdEndQuery extern PFN_vkCmdResetQueryPool vulkan_symbol_wrapper_vkCmdResetQueryPool; #define vkCmdResetQueryPool vulkan_symbol_wrapper_vkCmdResetQueryPool extern PFN_vkCmdWriteTimestamp vulkan_symbol_wrapper_vkCmdWriteTimestamp; #define vkCmdWriteTimestamp vulkan_symbol_wrapper_vkCmdWriteTimestamp extern PFN_vkCmdCopyQueryPoolResults vulkan_symbol_wrapper_vkCmdCopyQueryPoolResults; #define vkCmdCopyQueryPoolResults vulkan_symbol_wrapper_vkCmdCopyQueryPoolResults extern PFN_vkCmdPushConstants vulkan_symbol_wrapper_vkCmdPushConstants; #define vkCmdPushConstants vulkan_symbol_wrapper_vkCmdPushConstants extern PFN_vkCmdBeginRenderPass vulkan_symbol_wrapper_vkCmdBeginRenderPass; #define vkCmdBeginRenderPass vulkan_symbol_wrapper_vkCmdBeginRenderPass extern PFN_vkCmdNextSubpass vulkan_symbol_wrapper_vkCmdNextSubpass; #define vkCmdNextSubpass vulkan_symbol_wrapper_vkCmdNextSubpass extern PFN_vkCmdEndRenderPass vulkan_symbol_wrapper_vkCmdEndRenderPass; #define vkCmdEndRenderPass vulkan_symbol_wrapper_vkCmdEndRenderPass extern PFN_vkCmdExecuteCommands vulkan_symbol_wrapper_vkCmdExecuteCommands; #define vkCmdExecuteCommands vulkan_symbol_wrapper_vkCmdExecuteCommands extern PFN_vkDestroySurfaceKHR vulkan_symbol_wrapper_vkDestroySurfaceKHR; #define vkDestroySurfaceKHR vulkan_symbol_wrapper_vkDestroySurfaceKHR extern PFN_vkGetPhysicalDeviceSurfaceSupportKHR vulkan_symbol_wrapper_vkGetPhysicalDeviceSurfaceSupportKHR; #define vkGetPhysicalDeviceSurfaceSupportKHR vulkan_symbol_wrapper_vkGetPhysicalDeviceSurfaceSupportKHR extern PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR vulkan_symbol_wrapper_vkGetPhysicalDeviceSurfaceCapabilitiesKHR; #define vkGetPhysicalDeviceSurfaceCapabilitiesKHR vulkan_symbol_wrapper_vkGetPhysicalDeviceSurfaceCapabilitiesKHR extern PFN_vkGetPhysicalDeviceSurfaceFormatsKHR vulkan_symbol_wrapper_vkGetPhysicalDeviceSurfaceFormatsKHR; #define vkGetPhysicalDeviceSurfaceFormatsKHR vulkan_symbol_wrapper_vkGetPhysicalDeviceSurfaceFormatsKHR extern PFN_vkGetPhysicalDeviceSurfacePresentModesKHR vulkan_symbol_wrapper_vkGetPhysicalDeviceSurfacePresentModesKHR; #define vkGetPhysicalDeviceSurfacePresentModesKHR vulkan_symbol_wrapper_vkGetPhysicalDeviceSurfacePresentModesKHR extern PFN_vkCreateSwapchainKHR vulkan_symbol_wrapper_vkCreateSwapchainKHR; #define vkCreateSwapchainKHR vulkan_symbol_wrapper_vkCreateSwapchainKHR extern PFN_vkDestroySwapchainKHR vulkan_symbol_wrapper_vkDestroySwapchainKHR; #define vkDestroySwapchainKHR vulkan_symbol_wrapper_vkDestroySwapchainKHR extern PFN_vkGetSwapchainImagesKHR vulkan_symbol_wrapper_vkGetSwapchainImagesKHR; #define vkGetSwapchainImagesKHR vulkan_symbol_wrapper_vkGetSwapchainImagesKHR extern PFN_vkAcquireNextImageKHR vulkan_symbol_wrapper_vkAcquireNextImageKHR; #define vkAcquireNextImageKHR vulkan_symbol_wrapper_vkAcquireNextImageKHR extern PFN_vkQueuePresentKHR vulkan_symbol_wrapper_vkQueuePresentKHR; #define vkQueuePresentKHR vulkan_symbol_wrapper_vkQueuePresentKHR extern PFN_vkGetPhysicalDeviceDisplayPropertiesKHR vulkan_symbol_wrapper_vkGetPhysicalDeviceDisplayPropertiesKHR; #define vkGetPhysicalDeviceDisplayPropertiesKHR vulkan_symbol_wrapper_vkGetPhysicalDeviceDisplayPropertiesKHR extern PFN_vkGetPhysicalDeviceDisplayPlanePropertiesKHR vulkan_symbol_wrapper_vkGetPhysicalDeviceDisplayPlanePropertiesKHR; #define vkGetPhysicalDeviceDisplayPlanePropertiesKHR vulkan_symbol_wrapper_vkGetPhysicalDeviceDisplayPlanePropertiesKHR extern PFN_vkGetDisplayPlaneSupportedDisplaysKHR vulkan_symbol_wrapper_vkGetDisplayPlaneSupportedDisplaysKHR; #define vkGetDisplayPlaneSupportedDisplaysKHR vulkan_symbol_wrapper_vkGetDisplayPlaneSupportedDisplaysKHR extern PFN_vkGetDisplayModePropertiesKHR vulkan_symbol_wrapper_vkGetDisplayModePropertiesKHR; #define vkGetDisplayModePropertiesKHR vulkan_symbol_wrapper_vkGetDisplayModePropertiesKHR extern PFN_vkCreateDisplayModeKHR vulkan_symbol_wrapper_vkCreateDisplayModeKHR; #define vkCreateDisplayModeKHR vulkan_symbol_wrapper_vkCreateDisplayModeKHR extern PFN_vkGetDisplayPlaneCapabilitiesKHR vulkan_symbol_wrapper_vkGetDisplayPlaneCapabilitiesKHR; #define vkGetDisplayPlaneCapabilitiesKHR vulkan_symbol_wrapper_vkGetDisplayPlaneCapabilitiesKHR extern PFN_vkCreateDisplayPlaneSurfaceKHR vulkan_symbol_wrapper_vkCreateDisplayPlaneSurfaceKHR; #define vkCreateDisplayPlaneSurfaceKHR vulkan_symbol_wrapper_vkCreateDisplayPlaneSurfaceKHR extern PFN_vkCreateSharedSwapchainsKHR vulkan_symbol_wrapper_vkCreateSharedSwapchainsKHR; #define vkCreateSharedSwapchainsKHR vulkan_symbol_wrapper_vkCreateSharedSwapchainsKHR extern PFN_vkCreateDebugReportCallbackEXT vulkan_symbol_wrapper_vkCreateDebugReportCallbackEXT; #define vkCreateDebugReportCallbackEXT vulkan_symbol_wrapper_vkCreateDebugReportCallbackEXT extern PFN_vkDestroyDebugReportCallbackEXT vulkan_symbol_wrapper_vkDestroyDebugReportCallbackEXT; #define vkDestroyDebugReportCallbackEXT vulkan_symbol_wrapper_vkDestroyDebugReportCallbackEXT extern PFN_vkDebugReportMessageEXT vulkan_symbol_wrapper_vkDebugReportMessageEXT; #define vkDebugReportMessageEXT vulkan_symbol_wrapper_vkDebugReportMessageEXT extern PFN_vkDebugMarkerSetObjectTagEXT vulkan_symbol_wrapper_vkDebugMarkerSetObjectTagEXT; #define vkDebugMarkerSetObjectTagEXT vulkan_symbol_wrapper_vkDebugMarkerSetObjectTagEXT extern PFN_vkDebugMarkerSetObjectNameEXT vulkan_symbol_wrapper_vkDebugMarkerSetObjectNameEXT; #define vkDebugMarkerSetObjectNameEXT vulkan_symbol_wrapper_vkDebugMarkerSetObjectNameEXT extern PFN_vkCmdDebugMarkerBeginEXT vulkan_symbol_wrapper_vkCmdDebugMarkerBeginEXT; #define vkCmdDebugMarkerBeginEXT vulkan_symbol_wrapper_vkCmdDebugMarkerBeginEXT extern PFN_vkCmdDebugMarkerEndEXT vulkan_symbol_wrapper_vkCmdDebugMarkerEndEXT; #define vkCmdDebugMarkerEndEXT vulkan_symbol_wrapper_vkCmdDebugMarkerEndEXT extern PFN_vkCmdDebugMarkerInsertEXT vulkan_symbol_wrapper_vkCmdDebugMarkerInsertEXT; #define vkCmdDebugMarkerInsertEXT vulkan_symbol_wrapper_vkCmdDebugMarkerInsertEXT void vulkan_symbol_wrapper_init(PFN_vkGetInstanceProcAddr get_instance_proc_addr); PFN_vkGetInstanceProcAddr vulkan_symbol_wrapper_instance_proc_addr(void); VkBool32 vulkan_symbol_wrapper_load_global_symbols(void); VkBool32 vulkan_symbol_wrapper_load_core_instance_symbols(VkInstance instance); VkBool32 vulkan_symbol_wrapper_load_core_symbols(VkInstance instance); VkBool32 vulkan_symbol_wrapper_load_core_device_symbols(VkDevice device); VkBool32 vulkan_symbol_wrapper_load_instance_symbol(VkInstance instance, const char *name, PFN_vkVoidFunction *ppSymbol); VkBool32 vulkan_symbol_wrapper_load_device_symbol(VkDevice device, const char *name, PFN_vkVoidFunction *ppSymbol); #define VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, name, pfn) vulkan_symbol_wrapper_load_instance_symbol(instance, name, (PFN_vkVoidFunction*) &(pfn)) #define VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_EXTENSION_SYMBOL(instance, name) vulkan_symbol_wrapper_load_instance_symbol(instance, #name, (PFN_vkVoidFunction*) & name) #define VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, name, pfn) vulkan_symbol_wrapper_load_device_symbol(device, name, (PFN_vkVoidFunction*) &(pfn)) #define VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_EXTENSION_SYMBOL(device, name) vulkan_symbol_wrapper_load_device_symbol(device, #name, (PFN_vkVoidFunction*) & name) #ifdef __cplusplus } #endif #endif desmume/src/libretro-common/utils/udp-test.c000664 001750 001750 00000002257 12755534123 022326 0ustar00sergiosergio000000 000000 /* public domain */ /* gcc -o udptest udp-test.c */ /* will send "RETROPAD RIGHT" indefinely to player 1 to send to player 2 change port to 55401 and so on */ #include #include #include #include #include #define SERVER "127.0.0.1" #define PORT 55400 void die(char *s) { perror(s); exit(1); } int main(void) { struct sockaddr_in si_other; int s, i, slen=sizeof(si_other); if ( (s=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) { die("socket"); } memset((char *) &si_other, 0, sizeof(si_other)); si_other.sin_family = AF_INET; si_other.sin_port = htons(PORT); if (inet_aton(SERVER , &si_other.sin_addr) == 0) { fprintf(stderr, "inet_aton() failed\n"); exit(1); } while(1) { char message[10]="128"; //send the message if (sendto(s, message, strlen(message) , 0 , (struct sockaddr *) &si_other, slen)==-1) { die("sendto()"); } /* sleep for 1 frame (60hz) */ usleep(16*1000); } close(s); return 0; }desmume/src/libretro-common/include/math/000700 001750 001750 00000000000 12756420131 021601 5ustar00sergiosergio000000 000000 desmume/src/libretro-common/include/utils/000700 001750 001750 00000000000 12756420131 022010 5ustar00sergiosergio000000 000000 desmume/src/libretro-common/include/queues/message_queue.h000664 001750 001750 00000005631 12755534123 025207 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2016 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (message_queue.h). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef __LIBRETRO_SDK_MSG_QUEUE_H #define __LIBRETRO_SDK_MSG_QUEUE_H #include #include RETRO_BEGIN_DECLS typedef struct msg_queue msg_queue_t; /** * msg_queue_new: * @size : maximum size of message * * Creates a message queue with maximum size different messages. * * Returns: NULL if allocation error, pointer to a message queue * if successful. Has to be freed manually. **/ msg_queue_t *msg_queue_new(size_t size); /** * msg_queue_push: * @queue : pointer to queue object * @msg : message to add to the queue * @prio : priority level of the message * @duration : how many times the message can be pulled * before it vanishes (E.g. show a message for * 3 seconds @ 60fps = 180 duration). * * Push a new message onto the queue. **/ void msg_queue_push(msg_queue_t *queue, const char *msg, unsigned prio, unsigned duration); /** * msg_queue_pull: * @queue : pointer to queue object * * Pulls highest priority message in queue. * * Returns: NULL if no message in queue, otherwise a string * containing the message. **/ const char *msg_queue_pull(msg_queue_t *queue); /** * msg_queue_clear: * @queue : pointer to queue object * * Clears out everything in the queue. **/ void msg_queue_clear(msg_queue_t *queue); /** * msg_queue_free: * @queue : pointer to queue object * * Frees message queue.. **/ void msg_queue_free(msg_queue_t *queue); RETRO_END_DECLS #endif desmume/src/libretro-common/include/memmap.h000664 001750 001750 00000003762 12755534123 022327 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2016 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (memmap.h). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef _LIBRETRO_MEMMAP_H #define _LIBRETRO_MEMMAP_H #if defined(__CELLOS_LV2__) || defined(PSP) || defined(GEKKO) || defined(VITA) || defined(_XBOX) || defined(_3DS) /* No mman available */ #elif defined(_WIN32) && !defined(_XBOX) #include #include #include #else #define HAVE_MMAN #include #endif #if !defined(HAVE_MMAN) || defined(_WIN32) void* mmap(void *addr, size_t len, int mmap_prot, int mmap_flags, int fildes, size_t off); int munmap(void *addr, size_t len); int mprotect(void *addr, size_t len, int prot); #endif int memsync(void *start, void *end); int memprotect(void *addr, size_t len); #endif desmume/src/libretro-common/include/lists/string_list.h000664 001750 001750 00000010737 12755534123 024552 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2016 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (string_list.h). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef __LIBRETRO_SDK_STRING_LIST_H #define __LIBRETRO_SDK_STRING_LIST_H #include #include #include #include RETRO_BEGIN_DECLS union string_list_elem_attr { bool b; int i; void *p; }; struct string_list_elem { char *data; union string_list_elem_attr attr; }; struct string_list { struct string_list_elem *elems; size_t size; size_t cap; }; /** * string_list_find_elem: * @list : pointer to string list * @elem : element to find inside the string list. * * Searches for an element (@elem) inside the string list. * * Returns: true (1) if element could be found, otherwise false (0). */ int string_list_find_elem(const struct string_list *list, const char *elem); /** * string_list_find_elem_prefix: * @list : pointer to string list * @prefix : prefix to append to @elem * @elem : element to find inside the string list. * * Searches for an element (@elem) inside the string list. Will * also search for the same element prefixed by @prefix. * * Returns: true (1) if element could be found, otherwise false (0). */ bool string_list_find_elem_prefix(const struct string_list *list, const char *prefix, const char *elem); /** * string_split: * @str : string to turn into a string list * @delim : delimiter character to use for splitting the string. * * Creates a new string list based on string @str, delimited by @delim. * * Returns: new string list if successful, otherwise NULL. */ struct string_list *string_split(const char *str, const char *delim); /** * string_list_new: * * Creates a new string list. Has to be freed manually. * * Returns: new string list if successful, otherwise NULL. */ struct string_list *string_list_new(void); /** * string_list_append: * @list : pointer to string list * @elem : element to add to the string list * @attr : attributes of new element. * * Appends a new element to the string list. * * Returns: true (1) if successful, otherwise false (0). **/ bool string_list_append(struct string_list *list, const char *elem, union string_list_elem_attr attr); /** * string_list_free * @list : pointer to string list object * * Frees a string list. */ void string_list_free(struct string_list *list); /** * string_list_join_concat: * @buffer : buffer that @list will be joined to. * @size : length of @buffer. * @list : pointer to string list. * @delim : delimiter character for @list. * * A string list will be joined/concatenated as a * string to @buffer, delimited by @delim. */ void string_list_join_concat(char *buffer, size_t size, const struct string_list *list, const char *sep); /** * string_list_set: * @list : pointer to string list * @idx : index of element in string list * @str : value for the element. * * Set value of element inside string list. **/ void string_list_set(struct string_list *list, unsigned idx, const char *str); RETRO_END_DECLS #endif desmume/src/utils/decrypt/header.cpp000664 001750 001750 00000052725 12755534123 020720 0ustar00sergiosergio000000 000000 //taken from ndstool //http://devkitpro.svn.sourceforge.net/viewvc/devkitpro/trunk/tools/nds/ndstool/source/header.cpp?revision=3063 /* header.cpp - this file is part of DeSmuME * * Copyright (C) 2005-2006 Rafael Vuijk * * This file is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This file is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ #include "header.h" //#include "ndstool.h" //#include "banner.h" //#include "sha1.h" //#include "crc.h" //#include "bigint.h" //#include "arm7_sha1_homebrew.h" //#include "arm7_sha1_nintendo.h" //#include "encryption.h" // ///* // * Data // */ //unsigned char publicKeyNintendo[] = //{ // 0x9E, 0xC1, 0xCC, 0xC0, 0x4A, 0x6B, 0xD0, 0xA0, 0x6D, 0x62, 0xED, 0x5F, 0x15, 0x67, 0x87, 0x12, // 0xE6, 0xF4, 0x77, 0x1F, 0xD8, 0x5C, 0x81, 0xCE, 0x0C, 0xD0, 0x22, 0x31, 0xF5, 0x89, 0x08, 0xF5, // 0xBE, 0x04, 0xCB, 0xC1, 0x4F, 0x63, 0xD9, 0x5A, 0x98, 0xFF, 0xEB, 0x36, 0x0F, 0x9C, 0x5D, 0xAD, // 0x15, 0xB9, 0x99, 0xFB, 0xC6, 0x86, 0x2C, 0x0A, 0x0C, 0xFC, 0xE6, 0x86, 0x03, 0x60, 0xD4, 0x87, // 0x28, 0xD5, 0x66, 0x42, 0x9C, 0xF7, 0x04, 0x14, 0x4E, 0x6F, 0x73, 0x20, 0xC3, 0x3E, 0x3F, 0xF5, // 0x82, 0x2E, 0x78, 0x18, 0xD6, 0xCD, 0xD5, 0xC2, 0xDC, 0xAA, 0x1D, 0x34, 0x91, 0xEC, 0x99, 0xC9, // 0xF7, 0xBF, 0xBF, 0xA0, 0x0E, 0x1E, 0xF0, 0x25, 0xF8, 0x66, 0x17, 0x54, 0x34, 0x28, 0x2D, 0x28, // 0xA3, 0xAE, 0xF0, 0xA9, 0xFA, 0x3A, 0x70, 0x56, 0xD2, 0x34, 0xA9, 0xC5, 0x9E, 0x5D, 0xF5, 0xE1, //}; // ///* // * CalcHeaderCRC // */ //unsigned short CalcHeaderCRC(Header &header) //{ // return CalcCrc16((unsigned char *)&header, 0x15E); //} // ///* // * CalcLogoCRC // */ //unsigned short CalcLogoCRC(Header &header) //{ // return CalcCrc16((unsigned char *)&header + 0xC0, 156); //} // /* * DetectRomType */ int DetectRomType(const Header &header, char *secure) { const u64 data = LE_TO_LOCAL_64(*(u64 *)secure); //this is attempting to check for an utterly invalid nds header if(header.unitcode > 3) return ROMTYPE_INVALID; if (header.arm9_rom_offset < 0x4000) return ROMTYPE_HOMEBREW; else if (data == 0x0000000000000000ULL) return ROMTYPE_MULTIBOOT; else if (data == 0xE7FFDEFFE7FFDEFFULL) return ROMTYPE_NDSDUMPED; //TODO //for (int i=0x200; i<0x4000; i++) // if (romdata[i]) return ROMTYPE_MASKROM; // found something odd ;) return ROMTYPE_ENCRSECURE; } ///* // * CalcSecureAreaCRC // */ //unsigned short CalcSecureAreaCRC(bool encrypt) //{ // fseek(fNDS, 0x4000, SEEK_SET); // unsigned char data[0x4000]; // fread(data, 1, 0x4000, fNDS); // if (encrypt) encrypt_arm9(*(u32 *)header.gamecode, data); // return CalcCrc16(data, 0x4000); //} // ///* // * CalcSecurityDataCRC // */ //unsigned short CalcSecurityDataCRC() //{ // fseek(fNDS, 0x1000, SEEK_SET); // unsigned char data[0x2000]; // fread(data, 1, 0x2000, fNDS); // return CalcCrc16(data, 0x2000); //} // ///* // * CalcSegment3CRC // */ //unsigned short CalcSegment3CRC() //{ // fseek(fNDS, 0x3000, SEEK_SET); // unsigned char data[0x1000]; // fread(data, 1, 0x1000, fNDS); // for (int i=0; i<0x1000; i+=2) // swap bytes // { // unsigned char t = data[i+1]; data[i+1] = data[i]; data[i] = t; // } // return CalcCcitt16(data, 0x1000); // why would they use CRC16-CCITT ? //} // ///* // * FixHeaderCRC // */ //void FixHeaderCRC(char *ndsfilename) //{ // fNDS = fopen(ndsfilename, "r+b"); // if (!fNDS) { fprintf(stderr, "Cannot open file '%s'.\n", ndsfilename); exit(1); } // fread(&header, 512, 1, fNDS); // header.header_crc = CalcHeaderCRC(header); // fseek(fNDS, 0, SEEK_SET); // fwrite(&header, 512, 1, fNDS); // fclose(fNDS); //} // ///* // * ShowHeaderInfo // */ //void ShowHeaderInfo(Header &header, int romType, unsigned int length = 0x200) //{ // printf("0x00\t%-25s\t", "Game title"); // // for (unsigned int i=0; i= 2) // { // printf("{ DS Download Play(TM) / Wireless MultiBoot header information:\n"); // ShowHeaderInfo(*(Header *)(buf + 0x20), romType, 0x160); // printf("}\n"); // } // } // else // { // fseek(fNDS, 0, SEEK_SET); // fread(buf, 1, sizeof(buf), fNDS); // sha1_hash(buf, 0x160, &m_sha1); // } // sha1_end(header_sha1, &m_sha1); //} // ///* // * Arm9Sha1Multiboot // */ //void Arm9Sha1Multiboot(FILE *fNDS, unsigned char *arm9_sha1) //{ // sha1_ctx m_sha1; // sha1_begin(&m_sha1); // fseek(fNDS, header.arm9_rom_offset, SEEK_SET); // unsigned int len = header.arm9_size; // unsigned char *buf = new unsigned char [len]; // fread(buf, 1, len, fNDS); // //printf("%u\n", len); // sha1_hash(buf, len, &m_sha1); // delete [] buf; // sha1_end(arm9_sha1, &m_sha1); //} // ///* // * Arm9Sha1ClearedOutArea // */ //void Arm9Sha1ClearedOutArea(FILE *fNDS, unsigned char *arm9_sha1) //{ // sha1_ctx m_sha1; // sha1_begin(&m_sha1); // fseek(fNDS, header.arm9_rom_offset, SEEK_SET); // unsigned int len = header.arm9_size; // unsigned char *buf = new unsigned char [len]; // // int len1 = (0x5000 - header.arm9_rom_offset); // e.g. 0x5000 - 0x4000 = 0x1000 // int len3 = header.arm9_size - (0x7000 - header.arm9_rom_offset); // e.g. 0x10000 - (0x7000 - 0x4000) = 0xD000 // int len2 = header.arm9_size - len1 - len3; // e.g. 0x10000 - 0x1000 - 0xD000 = 0x2000 // if (len1 > 0) fread(buf, 1, len1, fNDS); // if (len2 > 0) { memset(buf + len1, 0, len2); fseek(fNDS, len2, SEEK_CUR); } // gets cleared for security? // if (len3 > 0) fread(buf + len1 + len2, 1, len3, fNDS); //// printf("%X %X %X\n", len1, len2, len3); // //// memset(buf, 0, 0x800); // clear "secure area" too // // sha1_hash(buf, len, &m_sha1); // delete [] buf; // sha1_end(arm9_sha1, &m_sha1); //} // ///* // * Arm7Sha1 // */ //void Arm7Sha1(FILE *fNDS, unsigned char *arm7_sha1) //{ // sha1_ctx m_sha1; // sha1_begin(&m_sha1); // fseek(fNDS, header.arm7_rom_offset, SEEK_SET); // unsigned int len = header.arm7_size; // unsigned char *buf = new unsigned char [len]; // fread(buf, 1, len, fNDS); // //printf("%u\n", len); // sha1_hash(buf, len, &m_sha1); // delete [] buf; // sha1_end(arm7_sha1, &m_sha1); //} // ///* // * CompareSha1WithList // */ //int CompareSha1WithList(unsigned char *arm7_sha1, const unsigned char *text, unsigned int textSize) //{ // while (1) // { // //printf("\n"); // for (int i=0; i '9') ? ((*text - 'A') & 7) + 10 : *text - '0'); // text++; // } // //printf("%02X", b); // if (b != arm7_sha1[i]) break; else if (i == 19) return 0; // } // while (*text && (*text >= ' ')) text++; // line end // while (*text && (*text < ' ')) text++; // new line // } //} // ///* // * HashAndCompareWithList // * -1=error, 0=match, 1=no match // */ //int HashAndCompareWithList(char *filename, unsigned char sha1[]) //{ // FILE *f = fopen(filename, "rb"); // if (!f) return -1; // sha1_ctx m_sha1; // sha1_begin(&m_sha1); // unsigned char buf[1024]; // unsigned int r; // do // { // r = fread(buf, 1, 1024, f); // sha1_hash(buf, r, &m_sha1); // } while (r > 0); // fclose(f); // sha1_end(sha1, &m_sha1); // if (CompareSha1WithList(sha1, arm7_sha1_homebrew, arm7_sha1_homebrew_size)) return 1; // not yet in list // return 0; //} // ///* // * strsepc // */ //char *strsepc(char **s, char d) //{ // char *r = *s; // for (char *p = *s; ; p++) // { // if (*p == 0) { *s = p; break; } // if (*p == d) { *s = p+1; *p = 0; break; } // } // return r; //} // ///* // * RomListInfo // */ //void RomListInfo(unsigned int crc32_match) //{ // if (!romlistfilename) return; // FILE *fRomList = fopen(romlistfilename, "rt"); // if (!fRomList) { fprintf(stderr, "Cannot open file '%s'.\n", romlistfilename); exit(1); } // char s[1024]; // while (fgets(s, 1024, fRomList)) // empty, title, title, title, title, filename, CRC32 // { // char *p = s; // if (strlen(strsepc(&p, '\xAC')) == 0) // { // char *title = strsepc(&p, '\xAC'); // unsigned int index = strtoul(title, 0, 10); // title += 7; // char *b1 = strchr(title, '('); // char *b2 = b1 ? strchr(b1+1, ')') : 0; // char *b3 = b2 ? strchr(b2+1, '(') : 0; // char *b4 = b3 ? strchr(b3+1, ')') : 0; // char *group = 0; // if (b1 + 2 == b2) if (b3 && b4) { *b3 = 0; *b4 = 0; group = b3+1; } // remove release group name // strsepc(&p, '\xAC'); strsepc(&p, '\xAC'); // strsepc(&p, '\xAC'); strsepc(&p, '\xAC'); // unsigned long crc32 = strtoul(strsepc(&p, '\xAC'), 0, 16); // if (crc32 == crc32_match) // { // printf("Release index: \t%u\n", index); // printf("Release title: \t%s\n", title); // printf("Release group: \t%s\n", group ? group : ""); // } // //for (int i=0; i<10; i++) printf("%d %s\n", i, strsepc(&p, '\xAC')); // } // } //} // ///* // * ShowVerboseInfo // */ //void ShowVerboseInfo(FILE *fNDS, Header &header, int romType) //{ // // calculate SHA1 of ARM7 binary // unsigned char arm7_sha1[SHA1_DIGEST_SIZE]; // Arm7Sha1(fNDS, arm7_sha1); // // // find signature data // unsigned_int signature_id = 0; // fseek(fNDS, header.application_end_offset, SEEK_SET); // fread(&signature_id, sizeof(signature_id), 1, fNDS); // if (signature_id != 0x00016361) // { // fseek(fNDS, header.application_end_offset - 136, SEEK_SET); // try again // fread(&signature_id, sizeof(signature_id), 1, fNDS); // } // if (signature_id == 0x00016361) // { // printf("\n"); // // unsigned char signature[128]; // fread(signature, 1, sizeof(signature), fNDS); // // unsigned char sha_parts[3*SHA1_DIGEST_SIZE + 4]; // fread(sha_parts + 3*SHA1_DIGEST_SIZE, 4, 1, fNDS); // some number // // //printf("%08X\n", *(unsigned int *)(sha_parts + 3*SHA1_DIGEST_SIZE)); // // unsigned char header_sha1[SHA1_DIGEST_SIZE]; // HeaderSha1(fNDS, header_sha1, romType); // memcpy(sha_parts + 0*SHA1_DIGEST_SIZE, header_sha1, SHA1_DIGEST_SIZE); // // unsigned char arm9_sha1[SHA1_DIGEST_SIZE]; // if (romType == ROMTYPE_MULTIBOOT) // { // Arm9Sha1Multiboot(fNDS, arm9_sha1); // } // else // { // Arm9Sha1ClearedOutArea(fNDS, arm9_sha1); // } // memcpy(sha_parts + 1*SHA1_DIGEST_SIZE, arm9_sha1, SHA1_DIGEST_SIZE); // // memcpy(sha_parts + 2*SHA1_DIGEST_SIZE, arm7_sha1, SHA1_DIGEST_SIZE); // // unsigned char sha_final[SHA1_DIGEST_SIZE]; // { // sha1_ctx m_sha1; // sha1_begin(&m_sha1); // unsigned int len = sizeof(sha_parts); // unsigned char *buf = sha_parts; // sha1_hash(buf, len, &m_sha1); // sha1_end(sha_final, &m_sha1); // } // // // calculate SHA1 from signature // unsigned char sha1_from_sig[SHA1_DIGEST_SIZE]; // { // BigInt _signature; // _signature.Set(signature, sizeof(signature)); // //printf("signature: "); _signature.print(); // // BigInt _publicKey; // _publicKey.Set(publicKeyNintendo, sizeof(publicKeyNintendo)); // //printf("public key: "); _publicKey.print(); // // BigInt big_sha1; // big_sha1.PowMod(_signature, _publicKey); // //printf("big_sha1: "); big_sha1.print(); // big_sha1.Get(sha1_from_sig, sizeof(sha1_from_sig)); // } // // bool ok = (memcmp(sha_final, sha1_from_sig, SHA1_DIGEST_SIZE) == 0); // printf("DS Download Play(TM) / Wireless MultiBoot signature: %s\n", ok ? "OK" : "INVALID"); // if (!ok) // { // printf("header hash: \t"); for (int i=0; i 0) // { // crc32 = CalcCrc32(buf, r, crc32); // } // crc32 = ~crc32; // delete [] buf; // // printf("\nFile CRC32: \t%08X\n", (unsigned int)crc32); // RomListInfo(crc32); // } // // // ROM dumper 1.0 bad data // { // unsigned char buf[0x200]; // fseek(fNDS, 0x7E00, SEEK_SET); // fread(buf, 1, 0x200, fNDS); // unsigned long crc32 = ~CalcCrc32(buf, 0x200); // printf("\nSMT dumper v1.0 corruption check: \t%s\n", (crc32 == 0x7E8B456F) ? "CORRUPTED" : "OK"); // } // // // Verify ARM7 SHA1 hash against known default binaries // int bKnownArm7 = 0; // { // printf("\nARM7 binary hash : \t"); for (int i=0; i= 0x04000000)) // { // printf("\nWARNING! ARM7 RAM address does not point to shared memory!\n"); // } // // // check ARM7 entry address // if ((header.arm7_entry_address < header.arm7_ram_address) || // (header.arm7_entry_address > header.arm7_ram_address + header.arm7_size)) // { // printf("\nWARNING! ARM7 entry address points outside of ARM7 binary!\n"); // } //} // ///* // * ShowInfo // */ //void ShowInfo(char *ndsfilename) //{ // fNDS = fopen(ndsfilename, "rb"); // if (!fNDS) { fprintf(stderr, "Cannot open file '%s'.\n", ndsfilename); exit(1); } // fread(&header, 512, 1, fNDS); // // int romType = DetectRomType(); // // printf("Header information:\n"); // ShowHeaderInfo(header, romType); // // // banner info // if (header.banner_offset) // { // Banner banner; // fseek(fNDS, header.banner_offset, SEEK_SET); // if (fread(&banner, 1, sizeof(banner), fNDS)) // { // unsigned short banner_crc = CalcBannerCRC(banner); // printf("\n"); // printf("Banner CRC: \t0x%04X (%s)\n", (int)banner.crc, (banner_crc == banner.crc) ? "OK" : "INVALID"); // // for (int language=1; language<=1; language++) // { // int line = 1; // bool nextline = true; // for (int i=0; i<128; i++) // { // unsigned short c = banner.title[language][i]; // if (c >= 128) c = '_'; // if (c == 0x00) { printf("\n"); break; } // if (c == 0x0A) // { // nextline = true; // } // else // { // if (nextline) // { // if (line != 1) printf("\n"); // printf("%s banner text, line %d:", bannerLanguages[language], line); // for (unsigned int i=0; i<11 - strlen(bannerLanguages[language]); i++) putchar(' '); // printf("\t"); // nextline = false; // line++; // } // putchar(c); // } // } // } // } // } // // // ARM9 footer // fseek(fNDS, header.arm9_rom_offset + header.arm9_size, SEEK_SET); // unsigned_int nitrocode; // if (fread(&nitrocode, sizeof(nitrocode), 1, fNDS) && (nitrocode == 0xDEC00621)) // { // printf("\n"); // printf("ARM9 footer found.\n"); // unsigned_int x; // fread(&x, sizeof(x), 1, fNDS); // fread(&x, sizeof(x), 1, fNDS); // } // // // show security CRCs // if (romType >= ROMTYPE_NDSDUMPED) // { // printf("\n"); // unsigned short securitydata_crc = CalcSecurityDataCRC(); // printf("Security data CRC (0x1000-0x2FFF) 0x%04X\n", (int)securitydata_crc); // unsigned short segment3_crc = CalcSegment3CRC(); // printf("Segment3 CRC (0x3000-0x3FFF) 0x%04X (%s)\n", (int)segment3_crc, (segment3_crc == 0x0254) ? "OK" : "INVALID"); // } // // // more information // if (verbose >= 1) // { // ShowVerboseInfo(fNDS, header, romType); // } // // fclose(fNDS); //} desmume/src/utils/libfat/filetime.h000664 001750 001750 00000003436 12755534123 020515 0ustar00sergiosergio000000 000000 /* filetime.h Conversion of file time and date values to various other types Copyright (c) 2006 Michael "Chishm" Chisholm Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. 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. 3. The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. */ #ifndef _FILETIME_H #define _FILETIME_H #include "common.h" #include #ifdef __cplusplus extern "C" { #endif uint16_t _FAT_filetime_getTimeFromRTC (void); uint16_t _FAT_filetime_getDateFromRTC (void); time_t _FAT_filetime_to_time_t (uint16_t t, uint16_t d); #ifdef __cplusplus } #endif #endif // _FILETIME_H desmume/src/MMU.cpp000664 001750 001750 00000472754 12755534123 015324 0ustar00sergiosergio000000 000000 /* Copyright (C) 2006 yopyop Copyright (C) 2007 shash Copyright (C) 2007-2015 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the this software. If not, see . */ #include #include #include #include #include #include #include "utils/bits.h" #include "armcpu.h" #include "common.h" #include "debug.h" #include "driver.h" #include "NDSSystem.h" #include "cp15.h" #include "wifi.h" #include "registers.h" #include "render3D.h" #include "FIFO.h" #include "gfx3d.h" #include "rtc.h" #include "mc.h" #include "slot1.h" #include "slot2.h" #include "mic.h" #include "movie.h" #include "readwrite.h" #include "MMU_timing.h" #include "firmware.h" #include "encrypt.h" #include "GPU.h" #include "SPU.h" //TODO - do we need these here? _KEY2 key2; //http://home.utah.edu/~nahaj/factoring/isqrt.c.html static u64 isqrt (u64 x) { u64 squaredbit, remainder, root; if (x<1) return 0; /* Load the binary constant 01 00 00 ... 00, where the number * of zero bits to the right of the single one bit * is even, and the one bit is as far left as is consistant * with that condition.) */ squaredbit = (u64) ((((u64) ~0LL) >> 1) & ~(((u64) ~0LL) >> 2)); /* This portable load replaces the loop that used to be * here, and was donated by legalize@xmission.com */ /* Form bits of the answer. */ remainder = x; root = 0; while (squaredbit > 0) { if (remainder >= (squaredbit | root)) { remainder -= (squaredbit | root); root >>= 1; root |= squaredbit; } else { root >>= 1; } squaredbit >>= 2; } return root; } u32 partie = 1; u32 _MMU_MAIN_MEM_MASK = 0x3FFFFF; u32 _MMU_MAIN_MEM_MASK16 = 0x3FFFFF & ~1; u32 _MMU_MAIN_MEM_MASK32 = 0x3FFFFF & ~3; //#define _MMU_DEBUG #ifdef _MMU_DEBUG #include void mmu_log_debug_ARM9(u32 adr, const char *fmt, ...) { if (adr < 0x4000000) return; // if (adr > 0x4100014) return; //#if 1 if (adr >= 0x4000000 && adr <= 0x400006E) return; // Display Engine A if (adr >= 0x40000B0 && adr <= 0x4000134) return; // DMA, Timers and Keypad if (adr >= 0x4000180 && adr <= 0x40001BC) return; // IPC/ROM if (adr >= 0x4000204 && adr <= 0x400024A) return; // Memory & IRQ control if (adr >= 0x4000280 && adr <= 0x4000306) return; // Maths if (adr >= 0x4000320 && adr <= 0x40006A3) return; // 3D dispaly engine if (adr >= 0x4001000 && adr <= 0x400106E) return; // Display Engine B if (adr >= 0x4100000 && adr <= 0x4100014) return; // IPC/ROM //#endif va_list list; char msg[512]; memset(msg,0,512); va_start(list,fmt); _vsnprintf(msg,511,fmt,list); va_end(list); } void mmu_log_debug_ARM7(u32 adr, const char *fmt, ...) { if (adr < 0x4000004) return; if (adr > 0x4808FFF) return; #if 1 if (adr >= 0x4000004 && adr < 0x4000180) return; // ARM7 I/O Map if (adr >= 0x4000180 && adr <= 0x40001C4) return; // IPC/ROM if (adr >= 0x4000204 && adr <= 0x400030C) return; // Memory and IRQ Control if (adr >= 0x4000400 && adr <= 0x400051E) return; // Sound Registers if (adr >= 0x4100000 && adr <= 0x4100014) return; // IPC/ROM if (adr >= 0x4800000 && adr <= 0x4808FFF) return; // WLAN Registers #endif va_list list; char msg[512]; memset(msg,0,512); va_start(list,fmt); _vsnprintf(msg,511,fmt,list); va_end(list); } #else #define mmu_log_debug_ARM9(...) #define mmu_log_debug_ARM7(...) #endif //#define LOG_CARD //#define LOG_GPU //#define LOG_DMA //#define LOG_DMA2 //#define LOG_DIV MMU_struct MMU; MMU_struct_new MMU_new; MMU_struct_timing MMU_timing; u8 * MMU_struct::MMU_MEM[2][256] = { //arm9 { /* 0X*/ DUP16(MMU.ARM9_ITCM), /* 1X*/ //DUP16(MMU.ARM9_ITCM) /* 1X*/ DUP16(MMU.UNUSED_RAM), /* 2X*/ DUP16(MMU.MAIN_MEM), /* 3X*/ DUP16(MMU.SWIRAM), /* 4X*/ DUP16(MMU.ARM9_REG), /* 5X*/ DUP16(MMU.ARM9_VMEM), /* 6X*/ DUP16(MMU.ARM9_LCD), /* 7X*/ DUP16(MMU.ARM9_OAM), /* 8X*/ DUP16(NULL), /* 9X*/ DUP16(NULL), /* AX*/ DUP16(MMU.UNUSED_RAM), /* BX*/ DUP16(MMU.UNUSED_RAM), /* CX*/ DUP16(MMU.UNUSED_RAM), /* DX*/ DUP16(MMU.UNUSED_RAM), /* EX*/ DUP16(MMU.UNUSED_RAM), /* FX*/ DUP16(MMU.ARM9_BIOS) }, //arm7 { /* 0X*/ DUP16(MMU.ARM7_BIOS), /* 1X*/ DUP16(MMU.UNUSED_RAM), /* 2X*/ DUP16(MMU.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(MMU.ARM9_LCD), /* 7X*/ DUP16(MMU.UNUSED_RAM), /* 8X*/ DUP16(NULL), /* 9X*/ DUP16(NULL), /* AX*/ DUP16(MMU.UNUSED_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_struct::MMU_MASK[2][256] = { //arm9 { /* 0X*/ DUP16(0x00007FFF), /* 1X*/ //DUP16(0x00007FFF) /* 1X*/ DUP16(0x00000003), /* 2X*/ DUP16(0x003FFFFF), /* 3X*/ DUP16(0x00007FFF), /* 4X*/ DUP16(0x00FFFFFF), /* 5X*/ DUP16(0x000007FF), /* 6X*/ DUP16(0x00FFFFFF), /* 7X*/ DUP16(0x000007FF), /* 8X*/ DUP16(0x00000003), /* 9X*/ DUP16(0x00000003), /* AX*/ DUP16(0x00000003), /* BX*/ DUP16(0x00000003), /* CX*/ DUP16(0x00000003), /* DX*/ DUP16(0x00000003), /* EX*/ DUP16(0x00000003), /* FX*/ DUP16(0x00007FFF) }, //arm7 { /* 0X*/ DUP16(0x00003FFF), /* 1X*/ DUP16(0x00000003), /* 2X*/ DUP16(0x003FFFFF), /* 3X*/ DUP8(0x00007FFF), DUP8(0x0000FFFF), /* 4X*/ DUP8(0x00FFFFFF), DUP8(0x0000FFFF), /* 5X*/ DUP16(0x00000003), /* 6X*/ DUP16(0x00FFFFFF), /* 7X*/ DUP16(0x00000003), /* 8X*/ DUP16(0x00000003), /* 9X*/ DUP16(0x00000003), /* AX*/ DUP16(0x00000003), /* BX*/ DUP16(0x00000003), /* CX*/ DUP16(0x00000003), /* DX*/ DUP16(0x00000003), /* EX*/ DUP16(0x00000003), /* FX*/ DUP16(0x00000003) } }; // this logic was moved to MMU_timing.h //CACHE_ALIGN //TWaitState MMU_struct::MMU_WAIT16[2][16] = { // { 1, 1, 1, 1, 1, 1, 1, 1, 5, 5, 5, 1, 1, 1, 1, 1 }, //arm9 // { 1, 1, 1, 1, 1, 1, 1, 1, 5, 5, 5, 1, 1, 1, 1, 1 }, //arm7 //}; // //CACHE_ALIGN //TWaitState MMU_struct::MMU_WAIT32[2][16] = { // { 1, 1, 1, 1, 1, 2, 2, 1, 8, 8, 5, 1, 1, 1, 1, 1 }, //arm9 // { 1, 1, 1, 1, 1, 1, 1, 1, 8, 8, 5, 1, 1, 1, 1, 1 }, //arm7 //}; ////////////////////////////////////////////////////////////// //------------- //VRAM MEMORY MAPPING //------------- //(Everything is mapped through to ARM9_LCD in blocks of 16KB) //for all of the below, values = 41 indicate unmapped memory #define VRAM_PAGE_UNMAPPED 41 #define VRAM_LCDC_PAGES 41 u8 vram_lcdc_map[VRAM_LCDC_PAGES]; //in the range of 0x06000000 - 0x06800000 in 16KB pages (the ARM9 vram mappable area) //this maps to 16KB pages in the LCDC buffer which is what will actually contain the data u8 vram_arm9_map[VRAM_ARM9_PAGES]; //this chooses which banks are mapped in the 128K banks starting at 0x06000000 in ARM7 u8 vram_arm7_map[2]; //-----> //consider these later, for better recordkeeping, instead of using the u8* in MMU ////for each 128KB texture slot, this maps to a 16KB starting page in the LCDC buffer //#define VRAM_TEX_SLOTS 4 //u8 vram_tex_map[VRAM_TEX_SLOTS]; // ////for each 16KB tex palette slot, this maps to a 16KB starting page in the LCDC buffer //#define VRAM_TEX_PALETTE_SLOTS 6 //u8 vram_tex_palette_map[VRAM_TEX_PALETTE_SLOTS]; //<--------- void MMU_VRAM_unmap_all(); struct TVramBankInfo { u8 page_addr, num_pages; }; static const TVramBankInfo vram_bank_info[VRAM_BANKS] = { {0,8}, {8,8}, {16,8}, {24,8}, {32,4}, {36,1}, {37,1}, {38,2}, {40,1} }; //this is to remind you that the LCDC mapping returns a strange value (not 0x06800000) as you would expect //in order to play nicely with the MMU address and mask tables #define LCDC_HACKY_LOCATION 0x06000000 #define ARM7_HACKY_IWRAM_LOCATION 0x03800000 #define ARM7_HACKY_SIWRAM_LOCATION 0x03000000 //maps an ARM9 BG/OBJ or LCDC address into an LCDC address, and informs the caller of whether it isn't mapped //TODO - in cases where this does some mapping work, we could bypass the logic at the end of the _read* and _write* routines //this is a good optimization to consider //NOTE - this whole approach is probably fundamentally wrong. //according to dasShiny research, its possible to map multiple banks to the same addresses. something more sophisticated would be needed. //however, it hasnt proven necessary yet for any known test case. template static FORCEINLINE u32 MMU_LCDmap(u32 addr, bool& unmapped, bool& restricted) { unmapped = false; restricted = false; //this will track whether 8bit writes are allowed //handle SIWRAM and non-shared IWRAM in here too, since it is quite similar to vram. //in fact it is probably implemented with the same pieces of hardware. //its sort of like arm7 non-shared IWRAM is lowest priority, and then SIWRAM goes on top. //however, we implement it differently than vram in emulator for historical reasons. //instead of keeping a page map like we do vram, we just have a list of all possible page maps (there are only 4 each for arm9 and arm7) if(addr >= 0x03000000 && addr < 0x04000000) { //blocks 0,1,2,3 is arm7 non-shared IWRAM and blocks 4,5 is SIWRAM, and block 8 is un-mapped zeroes int iwram_block_16k; int iwram_offset = addr & 0x3FFF; addr &= 0x00FFFFFF; if(PROCNUM == ARMCPU_ARM7) { static const int arm7_siwram_blocks[2][4][4] = { { {0,1,2,3}, //WRAMCNT = 0 -> map to IWRAM {4,4,4,4}, //WRAMCNT = 1 -> map to SIWRAM block 0 {5,5,5,5}, //WRAMCNT = 2 -> map to SIWRAM block 1 {4,5,4,5}, //WRAMCNT = 3 -> map to SIWRAM blocks 0,1 }, //high region; always maps to non-shared IWRAM { {0,1,2,3}, {0,1,2,3}, {0,1,2,3}, {0,1,2,3} } }; int region = (addr >> 23)&1; int block = (addr >> 14)&3; assert(region<2); assert(block<4); iwram_block_16k = arm7_siwram_blocks[region][MMU.WRAMCNT][block]; } //PROCNUM == ARMCPU_ARM7 else { //PROCNUM == ARMCPU_ARM9 static const int arm9_siwram_blocks[4][4] = { {4,5,4,5}, //WRAMCNT = 0 -> map to SIWRAM blocks 0,1 {5,5,5,5}, //WRAMCNT = 1 -> map to SIWRAM block 1 {4,4,4,4}, //WRAMCNT = 2 -> map to SIWRAM block 0 {8,8,8,8}, //WRAMCNT = 3 -> unmapped }; int block = (addr >> 14)&3; assert(block<4); iwram_block_16k = arm9_siwram_blocks[MMU.WRAMCNT][block]; } switch(iwram_block_16k>>2) { case 0: //arm7 non-shared IWRAM return ARM7_HACKY_IWRAM_LOCATION + (iwram_block_16k<<14) + iwram_offset; case 1: //SIWRAM return ARM7_HACKY_SIWRAM_LOCATION + ((iwram_block_16k&3)<<14) + iwram_offset; case 2: //zeroes CASE2: unmapped = true; return 0; default: assert(false); //how did this happen? goto CASE2; } } //in case the address is entirely outside of the interesting VRAM ranges if(addr < 0x06000000) return addr; if(addr >= 0x07000000) return addr; /* shared wram mapping for arm7 */ if(PROCNUM==ARMCPU_ARM7) { //necessary? not sure //addr &= 0x3FFFF; //addr += 0x06000000; u32 ofs = addr & 0x1FFFF; u32 bank = (addr >> 17)&1; if(vram_arm7_map[bank] == VRAM_PAGE_UNMAPPED) { unmapped = true; return 0; } return LCDC_HACKY_LOCATION + (vram_arm7_map[bank]<<14) + ofs; } restricted = true; //handle LCD memory mirroring //TODO - this is gross! this should be renovated if the vram mapping is ever done in a more sophisticated way taking into account dasShiny research if(addr>=0x068A4000) addr = 0x06800000 + //(addr%0xA4000); //yuck!! is this even how it mirrors? but we have to keep from overrunning the buffer somehow (addr&0x80000); //just as likely to be right (I have no clue how it should work) but faster. u32 vram_page; u32 ofs = addr & 0x3FFF; //return addresses in LCDC range if(addr>=0x06800000) { //already in LCDC range. just look it up to see whether it is unmapped vram_page = (addr>>14)&63; assert(vram_page>14)&(VRAM_ARM9_PAGES-1); assert(vram_page= VRAM_BANK_H) block++; u8 VRAMBankCnt = T1ReadByte(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x240 + block); //do nothing if the bank isnt enabled u8 en = VRAMBankCnt & 0x80; if(!en) return; int mst,ofs=0; switch(bank) { case VRAM_BANK_A: case VRAM_BANK_B: mst = VRAMBankCnt & 3; ofs = (VRAMBankCnt>>3) & 3; switch(mst) { case 0: //LCDC vramConfiguration.banks[bank].purpose = VramConfiguration::LCDC; MMU_vram_lcdc(bank); break; case 1: //ABG vramConfiguration.banks[bank].purpose = VramConfiguration::ABG; MMU_vram_arm9(bank,VRAM_PAGE_ABG+ofs*8); break; case 2: //AOBJ vramConfiguration.banks[bank].purpose = VramConfiguration::AOBJ; switch(ofs) { case 0: case 1: MMU_vram_arm9(bank,VRAM_PAGE_AOBJ+ofs*8); break; default: break; } break; case 3: //texture vramConfiguration.banks[bank].purpose = VramConfiguration::TEX; MMU.texInfo.textureSlotAddr[ofs] = MMU_vram_physical(vram_bank_info[bank].page_addr); break; default: goto unsupported_mst; } break; case VRAM_BANK_C: case VRAM_BANK_D: mst = VRAMBankCnt & 7; ofs = (VRAMBankCnt>>3) & 3; switch(mst) { case 0: //LCDC vramConfiguration.banks[bank].purpose = VramConfiguration::LCDC; MMU_vram_lcdc(bank); break; case 1: //ABG vramConfiguration.banks[bank].purpose = VramConfiguration::ABG; MMU_vram_arm9(bank,VRAM_PAGE_ABG+ofs*8); break; case 2: //arm7 vramConfiguration.banks[bank].purpose = VramConfiguration::ARM7; if(bank == 2) T1WriteByte(MMU.MMU_MEM[ARMCPU_ARM7][0x40], 0x240, T1ReadByte(MMU.MMU_MEM[ARMCPU_ARM7][0x40], 0x240) | 1); if(bank == 3) T1WriteByte(MMU.MMU_MEM[ARMCPU_ARM7][0x40], 0x240, T1ReadByte(MMU.MMU_MEM[ARMCPU_ARM7][0x40], 0x240) | 2); //printf("DING!\n"); switch(ofs) { case 0: case 1: vram_arm7_map[ofs] = vram_bank_info[bank].page_addr; break; default: break; } break; case 3: //texture vramConfiguration.banks[bank].purpose = VramConfiguration::TEX; MMU.texInfo.textureSlotAddr[ofs] = MMU_vram_physical(vram_bank_info[bank].page_addr); break; case 4: //BGB or BOBJ if(bank == VRAM_BANK_C) { vramConfiguration.banks[bank].purpose = VramConfiguration::BBG; MMU_vram_arm9(bank,VRAM_PAGE_BBG); //BBG } else { vramConfiguration.banks[bank].purpose = VramConfiguration::BOBJ; MMU_vram_arm9(bank,VRAM_PAGE_BOBJ); //BOBJ } break; default: goto unsupported_mst; } break; case VRAM_BANK_E: mst = VRAMBankCnt & 7; switch(mst) { case 0: //LCDC vramConfiguration.banks[bank].purpose = VramConfiguration::LCDC; MMU_vram_lcdc(bank); break; case 1: //ABG vramConfiguration.banks[bank].purpose = VramConfiguration::ABG; MMU_vram_arm9(bank,VRAM_PAGE_ABG); break; case 2: //AOBJ vramConfiguration.banks[bank].purpose = VramConfiguration::AOBJ; MMU_vram_arm9(bank,VRAM_PAGE_AOBJ); break; case 3: //texture palette vramConfiguration.banks[bank].purpose = VramConfiguration::TEXPAL; MMU.texInfo.texPalSlot[0] = MMU_vram_physical(vram_bank_info[bank].page_addr); MMU.texInfo.texPalSlot[1] = MMU_vram_physical(vram_bank_info[bank].page_addr+1); MMU.texInfo.texPalSlot[2] = MMU_vram_physical(vram_bank_info[bank].page_addr+2); MMU.texInfo.texPalSlot[3] = MMU_vram_physical(vram_bank_info[bank].page_addr+3); break; case 4: //A BG extended palette vramConfiguration.banks[bank].purpose = VramConfiguration::ABGEXTPAL; MMU.ExtPal[0][0] = MMU_vram_physical(vram_bank_info[bank].page_addr); MMU.ExtPal[0][1] = MMU.ExtPal[0][0] + ADDRESS_STEP_8KB; MMU.ExtPal[0][2] = MMU.ExtPal[0][1] + ADDRESS_STEP_8KB; MMU.ExtPal[0][3] = MMU.ExtPal[0][2] + ADDRESS_STEP_8KB; break; default: goto unsupported_mst; } break; case VRAM_BANK_F: case VRAM_BANK_G: { mst = VRAMBankCnt & 7; ofs = (VRAMBankCnt>>3) & 3; const int pageofslut[] = {0,1,4,5}; const int pageofs = pageofslut[ofs]; switch(mst) { case 0: //LCDC vramConfiguration.banks[bank].purpose = VramConfiguration::LCDC; MMU_vram_lcdc(bank); break; case 1: //ABG vramConfiguration.banks[bank].purpose = VramConfiguration::ABG; MMU_vram_arm9(bank,VRAM_PAGE_ABG+pageofs); MMU_vram_arm9(bank,VRAM_PAGE_ABG+pageofs+2); //unexpected mirroring (required by spyro eternal night) break; case 2: //AOBJ vramConfiguration.banks[bank].purpose = VramConfiguration::AOBJ; MMU_vram_arm9(bank,VRAM_PAGE_AOBJ+pageofs); MMU_vram_arm9(bank,VRAM_PAGE_AOBJ+pageofs+2); //unexpected mirroring - I have no proof, but it is inferred from the ABG above break; case 3: //texture palette vramConfiguration.banks[bank].purpose = VramConfiguration::TEXPAL; MMU.texInfo.texPalSlot[pageofs] = MMU_vram_physical(vram_bank_info[bank].page_addr); break; case 4: //A BG extended palette switch(ofs) { case 0: case 1: vramConfiguration.banks[bank].purpose = VramConfiguration::ABGEXTPAL; MMU.ExtPal[0][ofs*2] = MMU_vram_physical(vram_bank_info[bank].page_addr); MMU.ExtPal[0][ofs*2+1] = MMU.ExtPal[0][ofs*2] + ADDRESS_STEP_8KB; break; default: vramConfiguration.banks[bank].purpose = VramConfiguration::INVALID; break; } break; case 5: //A OBJ extended palette vramConfiguration.banks[bank].purpose = VramConfiguration::AOBJEXTPAL; MMU.ObjExtPal[0][0] = MMU_vram_physical(vram_bank_info[bank].page_addr); MMU.ObjExtPal[0][1] = MMU.ObjExtPal[0][1] + ADDRESS_STEP_8KB; break; default: goto unsupported_mst; } break; } case VRAM_BANK_H: mst = VRAMBankCnt & 3; switch(mst) { case 0: //LCDC vramConfiguration.banks[bank].purpose = VramConfiguration::LCDC; MMU_vram_lcdc(bank); break; case 1: //BBG vramConfiguration.banks[bank].purpose = VramConfiguration::BBG; MMU_vram_arm9(bank,VRAM_PAGE_BBG); MMU_vram_arm9(bank,VRAM_PAGE_BBG + 4); //unexpected mirroring break; case 2: //B BG extended palette vramConfiguration.banks[bank].purpose = VramConfiguration::BBGEXTPAL; MMU.ExtPal[1][0] = MMU_vram_physical(vram_bank_info[bank].page_addr); MMU.ExtPal[1][1] = MMU.ExtPal[1][0] + ADDRESS_STEP_8KB; MMU.ExtPal[1][2] = MMU.ExtPal[1][1] + ADDRESS_STEP_8KB; MMU.ExtPal[1][3] = MMU.ExtPal[1][2] + ADDRESS_STEP_8KB; break; default: goto unsupported_mst; } break; case VRAM_BANK_I: mst = VRAMBankCnt & 3; switch(mst) { case 0: //LCDC vramConfiguration.banks[bank].purpose = VramConfiguration::LCDC; MMU_vram_lcdc(bank); break; case 1: //BBG vramConfiguration.banks[bank].purpose = VramConfiguration::BBG; MMU_vram_arm9(bank,VRAM_PAGE_BBG+2); MMU_vram_arm9(bank,VRAM_PAGE_BBG+3); //unexpected mirroring break; case 2: //BOBJ vramConfiguration.banks[bank].purpose = VramConfiguration::BOBJ; MMU_vram_arm9(bank,VRAM_PAGE_BOBJ); MMU_vram_arm9(bank,VRAM_PAGE_BOBJ+1); //FF3 end scene (lens flare sprite) needs this as it renders a sprite off the end of the 16KB and back around break; case 3: //B OBJ extended palette vramConfiguration.banks[bank].purpose = VramConfiguration::BOBJEXTPAL; MMU.ObjExtPal[1][0] = MMU_vram_physical(vram_bank_info[bank].page_addr); MMU.ObjExtPal[1][1] = MMU.ObjExtPal[1][1] + ADDRESS_STEP_8KB; break; default: goto unsupported_mst; } break; } vramConfiguration.banks[bank].ofs = ofs; return; unsupported_mst: vramConfiguration.banks[bank].purpose = VramConfiguration::INVALID; } void MMU_VRAM_unmap_all() { vramConfiguration.clear(); vram_arm7_map[0] = VRAM_PAGE_UNMAPPED; vram_arm7_map[1] = VRAM_PAGE_UNMAPPED; for(int i=0;iVramReconfigureSignal(); } //------------------------------- //set up arm9 mirrorings //these are probably not entirely accurate. more study will be necessary. //in general, we find that it is not uncommon at all for games to accidentally do this. // //being able to easily do these experiments was one of the primary motivations for this remake of the vram mapping system //see the "unexpected mirroring" comments above for some more mirroring //so far "unexpected mirrorings" are tested by combining these games: //despereaux - storybook subtitles //NSMB - world map sub screen //drill spirits EU - mission select (just for control purposes, as it doesnt use H or I) //... //note that the "unexpected mirroring" items above may at some point rely on being executed in a certain order. //(sequentially A..I) const int types[] = {VRAM_PAGE_ABG,VRAM_PAGE_BBG,VRAM_PAGE_AOBJ,VRAM_PAGE_BOBJ}; const int sizes[] = {32,8,16,8}; for(int t=0;t<4;t++) { //the idea here is to pad out the mirrored space with copies of the mappable area, //without respect to what is mapped within that mappable area. //we hope that this is correct in all cases //required for driller spirits in mission select (mapping is simple A,B,C,D to each purpose) const int size = sizes[t]; const int mask = size-1; const int type = types[t]; for(int i=size;i<128;i++) { const int page = type + i; vram_arm9_map[page] = vram_arm9_map[type+(i&mask)]; } //attempt #1: screen corruption in drill spirits EU //it seems like these shouldnt pad out 128K banks (space beyond those should have remained unmapped) //int mirrorMask = -1; //int type = types[t]; ////if(type==VRAM_PAGE_BOBJ) continue; //if(type==VRAM_PAGE_AOBJ) continue; //for(int i=0;i<128;i++) //{ // int page = type + i; // if(vram_arm9_map[page] == VRAM_PAGE_UNMAPPED) // { // if(i==0) break; //can't mirror anything if theres nothing mapped! // if(mirrorMask == -1) // mirrorMask = i-1; // vram_arm9_map[page] = vram_arm9_map[type+(i&mirrorMask)]; // } //} } //------------------------------- } ////////////////////////////////////////////////////////////// //end vram ////////////////////////////////////////////////////////////// void MMU_Init(void) { LOG("MMU init\n"); memset(&MMU, 0, sizeof(MMU_struct)); //MMU.DTCMRegion = 0x027C0000; //even though apps may change dtcm immediately upon startup, this is the correct hardware starting value: MMU.DTCMRegion = 0x08000000; MMU.ITCMRegion = 0x00000000; IPC_FIFOinit(ARMCPU_ARM9); IPC_FIFOinit(ARMCPU_ARM7); GFX_PIPEclear(); GFX_FIFOclear(); DISP_FIFOinit(); mc_init(&MMU.fw, MC_TYPE_FLASH); /* init fw device */ mc_alloc(&MMU.fw, NDS_FW_SIZE_V1); MMU.fw.fp = NULL; MMU.fw.isFirmware = true; rtcInit(); slot1_Init(); slot2_Init(); Mic_Init(); } void MMU_DeInit(void) { LOG("MMU deinit\n"); if (MMU.fw.fp) fclose(MMU.fw.fp); mc_free(&MMU.fw); slot1_Shutdown(); slot2_Shutdown(); Mic_DeInit(); } void MMU_Reset() { memset(MMU.ARM9_DTCM, 0, sizeof(MMU.ARM9_DTCM)); memset(MMU.ARM9_ITCM, 0, sizeof(MMU.ARM9_ITCM)); memset(MMU.ARM9_LCD, 0, sizeof(MMU.ARM9_LCD)); memset(MMU.ARM9_OAM, 0, sizeof(MMU.ARM9_OAM)); memset(MMU.ARM9_REG, 0, sizeof(MMU.ARM9_REG)); memset(MMU.ARM9_VMEM, 0, sizeof(MMU.ARM9_VMEM)); memset(MMU.MAIN_MEM, 0, sizeof(MMU.MAIN_MEM)); memset(MMU.blank_memory, 0, sizeof(MMU.blank_memory)); memset(MMU.UNUSED_RAM, 0, sizeof(MMU.UNUSED_RAM)); memset(MMU.MORE_UNUSED_RAM, 0, sizeof(MMU.UNUSED_RAM)); memset(MMU.ARM7_ERAM, 0, sizeof(MMU.ARM7_ERAM)); memset(MMU.ARM7_REG, 0, sizeof(MMU.ARM7_REG)); memset(MMU.ARM7_WIRAM, 0, sizeof(MMU.ARM7_WIRAM)); memset(MMU.SWIRAM, 0, sizeof(MMU.SWIRAM)); IPC_FIFOinit(ARMCPU_ARM9); IPC_FIFOinit(ARMCPU_ARM7); GFX_PIPEclear(); GFX_FIFOclear(); DISP_FIFOinit(); MMU.DTCMRegion = 0x027C0000; MMU.ITCMRegion = 0x00000000; 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_bits, 0, sizeof(u32) * 2); memset(MMU.reg_IF_pending, 0, sizeof(u32) * 2); memset(&MMU.dscard, 0, sizeof(MMU.dscard)); MMU.divRunning = 0; MMU.divResult = 0; MMU.divMod = 0; MMU.divCycles = 0; MMU.sqrtRunning = 0; MMU.sqrtResult = 0; MMU.sqrtCycles = 0; MMU.SPI_CNT = 0; MMU.AUX_SPI_CNT = 0; reconstruct(&key2); MMU.WRAMCNT = 0; // Enable the sound speakers T1WriteWord(MMU.ARM7_REG, 0x304, 0x0001); MMU_VRAM_unmap_all(); MMU.powerMan_CntReg = 0x00; MMU.powerMan_CntRegWritten = FALSE; MMU.powerMan_Reg[0] = 0x0B; MMU.powerMan_Reg[1] = 0x00; MMU.powerMan_Reg[2] = 0x01; MMU.powerMan_Reg[3] = 0x00; rtcInit(); partie = 1; slot1_Reset(); slot2_Reset(); Mic_Reset(); MMU.gfx3dCycles = 0; MMU.dscard[0].transfer_count = 0; MMU.dscard[0].mode = eCardMode_RAW; MMU.dscard[1].transfer_count = 0; MMU.dscard[1].mode = eCardMode_RAW; reconstruct(&MMU_new); MMU_timing.arm7codeFetch.Reset(); MMU_timing.arm7dataFetch.Reset(); MMU_timing.arm9codeFetch.Reset(); MMU_timing.arm9dataFetch.Reset(); MMU_timing.arm9codeCache.Reset(); MMU_timing.arm9dataCache.Reset(); } void SetupMMU(bool debugConsole, bool dsi) { if(debugConsole) _MMU_MAIN_MEM_MASK = 0x7FFFFF; else _MMU_MAIN_MEM_MASK = 0x3FFFFF; if(dsi) _MMU_MAIN_MEM_MASK = 0xFFFFFF; _MMU_MAIN_MEM_MASK16 = _MMU_MAIN_MEM_MASK & ~1; _MMU_MAIN_MEM_MASK32 = _MMU_MAIN_MEM_MASK & ~3; } static void execsqrt() { u32 ret; u8 mode = MMU_new.sqrt.mode; MMU_new.sqrt.busy = 1; if (mode) { u64 v = T1ReadQuad(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x2B8); ret = (u32)isqrt(v); } else { u32 v = T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x2B8); ret = (u32)isqrt(v); } //clear the result while the sqrt unit is busy //todo - is this right? is it reasonable? T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x2B4, 0); MMU.sqrtCycles = nds_timer + 26; MMU.sqrtResult = ret; MMU.sqrtRunning = TRUE; NDS_Reschedule(); } static void execdiv() { s64 num,den; s64 res,mod; u8 mode = MMU_new.div.mode; MMU_new.div.busy = 1; MMU_new.div.div0 = 0; switch(mode) { case 0: // 32/32 num = (s64) (s32) T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x290); den = (s64) (s32) T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x298); MMU.divCycles = nds_timer + 36; break; case 1: // 64/32 case 3: //gbatek says this is same as mode 1 num = (s64) T1ReadQuad(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x290); den = (s64) (s32) T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x298); MMU.divCycles = nds_timer + 68; break; case 2: // 64/64 default: num = (s64) T1ReadQuad(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x290); den = (s64) T1ReadQuad(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x298); MMU.divCycles = nds_timer + 68; break; } if(den==0) { res = ((num < 0) ? 1 : -1); mod = num; // the DIV0 flag in DIVCNT is set only if the full 64bit DIV_DENOM value is zero, even in 32bit mode if ((u64)T1ReadQuad(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x298) == 0) MMU_new.div.div0 = 1; } else { res = num / den; mod = num % den; } DIVLOG("DIV %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[ARMCPU_ARM9][0x40], 0x2A0, 0); T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x2A4, 0); T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x2A8, 0); T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x2AC, 0); MMU.divResult = res; MMU.divMod = mod; MMU.divRunning = TRUE; NDS_Reschedule(); } DSI_TSC::DSI_TSC() { for(int i=0;i>1)&0x7F; read_flag = val&1; state = 1; return read16(); case 1: if(read_flag) { } else { registers[reg_selection] = (u8)val; } ret = read16(); reg_selection++; reg_selection &= 0x7F; return ret; } return 0; } u16 DSI_TSC::read16() { u8 page = registers[0]; switch(page) { case 3: //page 3 switch(reg_selection) { case 9: if(nds.isTouch) return 0; return 0x40; case 14: if(nds.isTouch) return 0; return 0x02; } break; case 252: //page 252 switch(reg_selection) { //high byte of X: case 1: case 3: case 5: case 7: case 9: return (nds.scr_touchX>>8)&0xFF; //low byte of X: case 2: case 4: case 6: case 8: case 10: return nds.scr_touchX&0xFF; //high byte of Y: case 11: case 13: case 15: case 17: case 19: return (nds.scr_touchY>>8)&0xFF; //low byte of Y: case 12: case 14: case 16: case 18: case 20: return nds.scr_touchY&0xFF; default: break; } break; } //unknown page or register return 0xFF; } bool DSI_TSC::save_state(EMUFILE* os) { u32 version = 0; write32le(version,os); write8le(reg_selection,os); write8le(read_flag,os); write32le(state,os); write32le(readcount,os); for(int i=0;i>0)&0xFF; bytes[6] = (buf[0]>>8)&0xFF; bytes[5] = (buf[0]>>16)&0xFF; bytes[4] = (buf[0]>>24)&0xFF; bytes[3] = (buf[1]>>0)&0xFF; bytes[2] = (buf[1]>>8)&0xFF; bytes[1] = (buf[1]>>16)&0xFF; bytes[0] = (buf[1]>>24)&0xFF; } template void FASTCALL MMU_writeToGCControl(u32 val) { int dbsize = (val>>24)&7; static int gcctr=0; GCLOG("[GC] [%07d] GCControl: %08X (dbsize:%d)\n",gcctr,val,dbsize); gcctr++; GCBUS_Controller& card = MMU.dscard[PROCNUM]; //....pick apart the fields.... int keylength = (val&0x1FFF); //key1length high gcromctrl[21:16] ?? u8 key2_encryptdata = (val>>13)&1; u8 bit15 = (val>>14)&1; u8 key2_applyseed = (val>>15)&1; //write only strobe //key1length high gcromctrl[21:16] ?? u8 key2_encryptcommand = (val>>22)&1; //bit 23 read only status int blocksize_field = (val>>24)&7; u8 clockrate = (val>>27)&1; u8 secureareamode = (val>>28)&1; //RESB bit 29? u8 wr = (val>>30)&1; u8 start = (val>>31)&1; //doubles as busy on read static const int blocksize_table[] = {0,0x200,0x400,0x800,0x1000,0x2000,0x4000,4}; int blocksize = blocksize_table[blocksize_field]; //store written value, without bit 31 and bit 23 set (those will be patched in as operations proceed) //T1WriteLong(MMU.MMU_MEM[PROCNUM][0x40], 0x1A4, val & 0x7F7FFFFF); //if this operation has been triggered by strobing that bit, run it if (key2_applyseed) key2.applySeed(PROCNUM); //pluck out the command registers into a more convenient format GC_Command rawcmd = *(GC_Command*)&MMU.MMU_MEM[PROCNUM][0x40][0x1A8]; //when writing a 1 to the start bit, a command runs. //the command is transferred to the GC during the next 8 clocks if(start) { GCLOG("[GC] command:"); rawcmd.print(); slot1_device->write_command(PROCNUM, rawcmd); /*INFO("WRITE: %02X%02X%02X%02X%02X%02X%02X%02X ", rawcmd.bytes[0], rawcmd.bytes[1], rawcmd.bytes[2], rawcmd.bytes[3], rawcmd.bytes[4], rawcmd.bytes[5], rawcmd.bytes[6], rawcmd.bytes[7]); INFO("FROM: %08X ", (PROCNUM ? NDS_ARM7:NDS_ARM9).instruct_adr); INFO("1A4: %08X ", val); INFO("SIZE: %08X\n", blocksize);*/ } else { T1WriteLong(MMU.MMU_MEM[PROCNUM][0x40], 0x1A4, val & 0x7F7FFFFF); GCLOG("SCUTTLE????\n"); return; } //the transfer size is determined by the specification here in GCROMCTRL, not any logic private to the card. card.transfer_count = blocksize; //if there was nothing to be done here, go ahead and flag it as done if(card.transfer_count == 0) { MMU_GC_endTransfer(PROCNUM); return; } val |= 0x00800000; T1WriteLong(MMU.MMU_MEM[PROCNUM][0x40], 0x1A4, val); // Launch DMA if start flag was set to "DS Cart" triggerDma(EDMAMode_Card); } /*template u32 FASTCALL MMU_readFromGCControl() { return T1ReadLong(MMU.MMU_MEM[0][0x40], 0x1A4); }*/ template u32 MMU_readFromGC() { GCBUS_Controller& card = MMU.dscard[PROCNUM]; //???? return the latched / last read value instead perhaps? if(card.transfer_count == 0) return 0; u32 val = slot1_device->read_GCDATAIN(PROCNUM); //update transfer counter and complete the transfer if necessary card.transfer_count -= 4; if(card.transfer_count <= 0) MMU_GC_endTransfer(PROCNUM); return val; } template void MMU_writeToGC(u32 val) { GCBUS_Controller& card = MMU.dscard[PROCNUM]; slot1_device->write_GCDATAIN(PROCNUM,val); //update transfer counter and complete the transfer if necessary card.transfer_count -= 4; if(card.transfer_count <= 0) MMU_GC_endTransfer(PROCNUM); } // ====================================================================== REG_SPIxxx static void CalculateTouchPressure(int pressurePercent, u16 &z1, u16& z2) { bool touch = nds.isTouch!=0; if(!touch) { z1 = z2 = 0; return; } int y = nds.scr_touchY; int x = nds.scr_touchX; float u = (x/256.0f); float v = (y/192.0f); //these coefficients float fPressurePercent = pressurePercent/100.0f; //z1 goes up as pressure goes up { float b0 = (96-80)*fPressurePercent + 80; float b1 = (970-864)*fPressurePercent + 864; float b2 = (192-136)*fPressurePercent + 136; float b3 = (1560-1100)*fPressurePercent + 1100; z1 = (u16)(int)(b0 + (b1-b0)*u + (b2-b0)*v + (b3-b2-b1+b0)*u*v); } //z2 goes down as pressure goes up { float b0=(1976-2300)*fPressurePercent + 2300; float b1=(2360-2600)*fPressurePercent + 2600; float b2=(3840-3900)*fPressurePercent + 3900; float b3=(3912-3950)*fPressurePercent + 3950; z2 = (u16)(int)(b0 + (b1-b0)*u + (b2-b0)*v + (b3-b2-b1+b0)*u*v); } } void FASTCALL MMU_writeToSPIData(u16 val) { enum PM_Bits //from libnds { PM_SOUND_AMP = BIT(0) , /*!< \brief Power the sound hardware (needed to hear stuff in GBA mode too) */ PM_SOUND_MUTE = BIT(1), /*!< \brief Mute the main speakers, headphone output will still work. */ PM_BACKLIGHT_BOTTOM = BIT(2), /*!< \brief Enable the top backlight if set */ PM_BACKLIGHT_TOP = BIT(3) , /*!< \brief Enable the bottom backlight if set */ PM_SYSTEM_PWR = BIT(6) /*!< \brief Turn the power *off* if set */ }; if (val !=0) MMU.SPI_CMD = val; u16 spicnt = T1ReadWord(MMU.MMU_MEM[ARMCPU_ARM7][(REG_SPICNT >> 20) & 0xff], REG_SPICNT & 0xfff); int device = (spicnt >> 8) & 0x3; int baudrate = spicnt & 0x3; switch(device) { case SPI_DEVICE_POWERMAN: if (!MMU.powerMan_CntRegWritten) { MMU.powerMan_CntReg = (val & 0xFF); MMU.powerMan_CntRegWritten = TRUE; } else { u16 reg = MMU.powerMan_CntReg & 0x7F; reg &= 0x7; if(reg==5 || reg==6 || reg==7) reg = 4; //(let's start with emulating a DS lite, since it is the more complex case) if(MMU.powerMan_CntReg & 0x80) { //read val = MMU.powerMan_Reg[reg]; } else { //write MMU.powerMan_Reg[reg] = (u8)val; //our totally pathetic register handling, only the one thing we've wanted so far if(MMU.powerMan_Reg[0]&PM_SYSTEM_PWR) { printf("SYSTEM POWERED OFF VIA ARM7 SPI POWER DEVICE\n"); printf("Did your main() return?\n"); emu_halt(); } } MMU.powerMan_CntRegWritten = FALSE; } break; case SPI_DEVICE_FIRMWARE: if(baudrate != SPI_BAUDRATE_4MHZ) // check SPI baudrate (must be 4mhz) { printf("Wrong SPI baud rate for firmware access\n"); val = 0; } else val = fw_transfer(&MMU.fw, (u8)val); break; case SPI_DEVICE_TOUCHSCREEN: { if(nds.Is_DSI()) { //pass data to TSC val = MMU_new.dsi_tsc.write16(val); //apply reset command if appropriate if(!BIT11(MMU.SPI_CNT)) MMU_new.dsi_tsc.reset_command(); break; } int channel = (MMU.SPI_CMD&0x70)>>4; switch(channel) { case TSC_MEASURE_TEMP1: if(spicnt & 0x800) { if(partie) { val = ((716<<3)&0x7FF); partie = 0; break; } val = (716>>5); partie = 1; break; } val = ((716<<3)&0x7FF); partie = 1; break; case TSC_MEASURE_TEMP2: if(spicnt & 0x800) { if(partie) { val = ((865<<3)&0x7FF); partie = 0; break; } val = (865>>5); partie = 1; break; } val = ((865<<3)&0x7FF); partie = 1; break; case TSC_MEASURE_Y: //counter the number of adc touch coord reads and jitter it after a while to simulate a shaky human hand or multiple reads //this is actually important for some games.. seemingly due to bugs. nds.adc_jitterctr++; if(nds.adc_jitterctr == 25) { nds.adc_jitterctr = 0; if (nds.stylusJitter) { nds.adc_touchY ^= 16; nds.adc_touchX ^= 16; } } if(MMU.SPI_CNT&(1<<11)) { if(partie) { val = (nds.adc_touchY<<3) & 0xFF; partie = 0; break; } val = (nds.adc_touchY>>5) & 0xFF; partie = 1; break; } val = (nds.adc_touchY<<3)&0xFF; partie = 1; break; case TSC_MEASURE_Z1: //Z1 { //used for pressure calculation - must be nonzero or else some softwares will think the stylus is up. //something is wrong in here and some of these LSB dont make it back to libnds... whatever. u16 scratch; CalculateTouchPressure(CommonSettings.StylusPressure,val,scratch); if(spicnt & 0x800) { if(partie) { val = ((val<<3)&0x7FF); partie = 0; break; } val = (val>>5); partie = 1; break; } val = ((val<<3)&0x7FF); partie = 1; break; } case TSC_MEASURE_Z2: //Z2 { //used for pressure calculation - must be nonzero or else some softwares will think the stylus is up. //something is wrong in here and some of these LSB dont make it back to libnds... whatever. u16 scratch; CalculateTouchPressure(CommonSettings.StylusPressure,scratch,val); if(spicnt & 0x800) { if(partie) { val = ((val<<3)&0x7FF); partie = 0; break; } val = (val>>5); partie = 1; break; } val = ((val<<3)&0x7FF); partie = 1; break; } case TSC_MEASURE_X: if(spicnt & 0x800) { if(partie) { val = (nds.adc_touchX << 3) & 0xFF; partie = 0; break; } val = (nds.adc_touchX>>5) & 0xFF; partie = 1; break; } val = (nds.adc_touchX<<3) & 0xFF; partie = 1; break; case TSC_MEASURE_AUX: if(!(val & 0x80)) val = (Mic_ReadSample() & 0xFF); else val = 0; break; } break; } case 3 : // NOTICE: Device 3 of SPI is reserved (unused and unusable) break; } T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM7][(REG_SPIDATA >> 20) & 0xff], REG_SPIDATA & 0xfff, val & 0x00FF); } // ====================================================================== REG_SPIxxx END //does some validation on the game's choice of IF value, correcting it if necessary static void validateIF_arm9() { } template static void REG_IF_WriteByte(u32 addr, u8 val) { //the following bits are generated from logic and should not be affected here //Bit 21 NDS9 only: Geometry Command FIFO //arm9: IF &= ~0x00200000; //arm7: IF &= ~0x00000000; //UPDATE IN setIF() ALSO!!!!!!!!!!!!!!!! //UPDATE IN mmu_loadstate ALSO!!!!!!!!!!!! if (addr==2) { if(PROCNUM==ARMCPU_ARM9) val &= ~0x20; else val &= ~0x00; } //ZERO 01-dec-2010 : I am no longer sure this approach is correct.. it proved to be wrong for IPC fifo....... //it seems as if IF bits should always be cached (only the user can clear them) MMU.reg_IF_bits[PROCNUM] &= (~(((u32)val)<<(addr<<3))); NDS_Reschedule(); } template static void REG_IF_WriteWord(u32 addr,u16 val) { REG_IF_WriteByte(addr,val&0xFF); REG_IF_WriteByte(addr+1,(val>>8)&0xFF); } template static void REG_IF_WriteLong(u32 val) { REG_IF_WriteByte(0,val&0xFF); REG_IF_WriteByte(1,(val>>8)&0xFF); REG_IF_WriteByte(2,(val>>16)&0xFF); REG_IF_WriteByte(3,(val>>24)&0xFF); } template u32 MMU_struct::gen_IF() { u32 IF = reg_IF_bits[PROCNUM]; if(PROCNUM==ARMCPU_ARM9) { //according to gbatek, these flags are forced on until the condition is removed. //no proof of this though... switch(MMU_new.gxstat.gxfifo_irq) { case 0: //never break; case 1: //less than half full if(MMU_new.gxstat.fifo_low) IF |= IRQ_MASK_ARM9_GXFIFO; break; case 2: //empty if(MMU_new.gxstat.fifo_empty) IF |= IRQ_MASK_ARM9_GXFIFO; break; case 3: //reserved/unknown break; } } return IF; } static void writereg_DISP3DCNT(const int size, const u32 adr, const u32 val) { //UGH. rewrite this shite to use individual values and reconstruct the return value instead of packing things in this !@#)ing register //nanostray2 cutscene will test this vs old desmumes by using some kind of 32bit access for setting up this reg for cutscenes switch(size) { case 8: switch(adr) { case REG_DISPA_DISP3DCNT: MMU.reg_DISP3DCNT_bits &= 0xFFFFFF00; MMU.reg_DISP3DCNT_bits |= val; gfx3d_Control(MMU.reg_DISP3DCNT_bits); break; case REG_DISPA_DISP3DCNT+1: { u32 myval = (val & ~0x30) | (~val & ((MMU.reg_DISP3DCNT_bits>>8) & 0x30)); // bits 12,13 are ack bits myval &= 0x7F; //top bit isnt connected MMU.reg_DISP3DCNT_bits = MMU.reg_DISP3DCNT_bits&0xFFFF00FF; MMU.reg_DISP3DCNT_bits |= (myval<<8); gfx3d_Control(MMU.reg_DISP3DCNT_bits); } break; } break; case 16: case 32: writereg_DISP3DCNT(8,adr,val&0xFF); writereg_DISP3DCNT(8,adr+1,(val>>8)&0xFF); break; } } static u32 readreg_DISP3DCNT(const int size, const u32 adr) { //UGH. rewrite this shite to use individual values and reconstruct the return value instead of packing things in this !@#)ing register switch(size) { case 8: switch(adr) { case REG_DISPA_DISP3DCNT: return MMU.reg_DISP3DCNT_bits & 0xFF; case REG_DISPA_DISP3DCNT+1: return ((MMU.reg_DISP3DCNT_bits)>>8)& 0xFF; } break; case 16: case 32: return readreg_DISP3DCNT(8,adr)|(readreg_DISP3DCNT(8,adr+1)<<8); } assert(false); return 0; } static u32 readreg_POWCNT1(const int size, const u32 adr) { switch(size) { case 8: switch(adr) { case REG_POWCNT1: { u8 ret = 0; ret |= nds.power1.lcd?BIT(0):0; ret |= nds.power1.gpuMain?BIT(1):0; ret |= nds.power1.gfx3d_render?BIT(2):0; ret |= nds.power1.gfx3d_geometry?BIT(3):0; return ret; } case REG_POWCNT1+1: { u8 ret = 0; ret |= nds.power1.gpuSub?BIT(1):0; ret |= nds.power1.dispswap?BIT(7):0; return ret; } default: return 0; } case 16: case 32: return readreg_POWCNT1(8,adr)|(readreg_POWCNT1(8,adr+1)<<8); } assert(false); return 0; } static void writereg_POWCNT1(const int size, const u32 adr, const u32 val) { switch(size) { case 8: switch(adr) { case REG_POWCNT1: nds.power1.lcd = BIT0(val); nds.power1.gpuMain = BIT1(val); nds.power1.gfx3d_render = BIT2(val); nds.power1.gfx3d_geometry = BIT3(val); break; case REG_POWCNT1+1: nds.power1.gpuSub = BIT1(val); nds.power1.dispswap = BIT7(val); if(nds.power1.dispswap) { //printf("Main core on top (vcount=%d)\n",nds.VCount); GPU->GetDisplayMain()->SetEngineByID(GPUEngineID_Main); GPU->GetDisplayTouch()->SetEngineByID(GPUEngineID_Sub); } else { //printf("Main core on bottom (vcount=%d)\n",nds.VCount); GPU->GetDisplayMain()->SetEngineByID(GPUEngineID_Sub); GPU->GetDisplayTouch()->SetEngineByID(GPUEngineID_Main); } break; } break; case 16: case 32: writereg_POWCNT1(8,adr,val&0xFF); writereg_POWCNT1(8,adr+1,(val>>8)&0xFF); break; } } static INLINE void MMU_IPCSync(u8 proc, u32 val) { //INFO("IPC%s sync 0x%04X (0x%02X|%02X)\n", proc?"7":"9", val, val >> 8, val & 0xFF); u32 sync_l = T1ReadLong(MMU.MMU_MEM[proc][0x40], 0x180) & 0xFFFF; u32 sync_r = T1ReadLong(MMU.MMU_MEM[proc^1][0x40], 0x180) & 0xFFFF; sync_l = ( sync_l & 0x000F ) | ( val & 0x0F00 ); sync_r = ( sync_r & 0x6F00 ) | ( (val >> 8) & 0x000F ); sync_l |= val & 0x6000; if(nds.ensataEmulation && proc==1 && nds.ensataIpcSyncCounter<9) { u32 iteration = (val&0x0F00)>>8; if(iteration==8-nds.ensataIpcSyncCounter) nds.ensataIpcSyncCounter++; else printf("ERROR: ENSATA IPC SYNC HACK FAILED; BAD THINGS MAY HAPPEN\n"); //for some reason, the arm9 doesn't handshake when ensata is detected. //so we complete the protocol here, which is to mirror the values 8..0 back to //the arm7 as they are written by the arm7 sync_r &= 0xF0FF; sync_r |= (iteration<<8); sync_l &= 0xFFF0; sync_l |= iteration; } T1WriteLong(MMU.MMU_MEM[proc][0x40], 0x180, sync_l); T1WriteLong(MMU.MMU_MEM[proc^1][0x40], 0x180, sync_r); if ((sync_l & IPCSYNC_IRQ_SEND) && (sync_r & IPCSYNC_IRQ_RECV)) NDS_makeIrq(proc^1, IRQ_BIT_IPCSYNC); NDS_Reschedule(); } static INLINE u16 read_timer(int proc, int timerIndex) { //chained timers are always up to date if(MMU.timerMODE[proc][timerIndex] == 0xFFFF) return MMU.timer[proc][timerIndex]; //sometimes a timer will be read when it is not enabled. //we should have the value cached if(!MMU.timerON[proc][timerIndex]) return MMU.timer[proc][timerIndex]; //for unchained timers, we do not keep the timer up to date. its value will need to be calculated here s32 diff = (s32)(nds.timerCycle[proc][timerIndex] - nds_timer); assert(diff>=0); #if 0 if(diff<0) printf("NEW EMULOOP BAD NEWS PLEASE REPORT: TIME READ DIFF < 0 (%d) (%d) (%d)\n",diff,timerIndex,MMU.timerMODE[proc][timerIndex]); #endif s32 units = diff / (1<65536) { printf("NEW EMULOOP BAD NEWS PLEASE REPORT: UNITS %d:%d = %d\n",proc,timerIndex,units); ret = 0; } else ret = 65535 - units; return ret; } static INLINE void write_timer(int proc, int timerIndex, u16 val) { #if 0 int mask = ((val&0x80)>>7) << timerIndex; MMU.CheckTimers = (MMU.CheckTimers & (~mask)) | mask; #endif if(val&0x80) MMU.timer[proc][timerIndex] = MMU.timerReload[proc][timerIndex]; else { if(MMU.timerON[proc][timerIndex]) //read the timer value one last time MMU.timer[proc][timerIndex] = read_timer(proc,timerIndex); } MMU.timerON[proc][timerIndex] = val & 0x80; switch(val&7) { case 0 : MMU.timerMODE[proc][timerIndex] = 0+1; break; case 1 : MMU.timerMODE[proc][timerIndex] = 6+1; break; case 2 : MMU.timerMODE[proc][timerIndex] = 8+1; break; case 3 : MMU.timerMODE[proc][timerIndex] = 10+1; break; default : MMU.timerMODE[proc][timerIndex] = 0xFFFF; break; } int remain = 65536 - MMU.timerReload[proc][timerIndex]; nds.timerCycle[proc][timerIndex] = nds_timer + (remain<=255) ret |= BIT(24); //fifo full if(gxFIFO.size<128) ret |= BIT(25); //fifo half if(gxFIFO.size==0) ret |= BIT(26); //fifo empty //determine busy flag. //if we're waiting for a flush, we're busy if(isSwapBuffers) ret |= BIT(27); //if fifo is nonempty, we're busy if(gxFIFO.size!=0) ret |= BIT(27); //printf("[%d] %d %d %d\n",currFrameCounter,se,sb,gxFIFO.size!=0); ret |= ((gxfifo_irq & 0x3) << 30); //user's irq flags //printf("vc=%03d Returning gxstat read: %08X (isSwapBuffers=%d)\n",nds.VCount,ret,isSwapBuffers); //ret = (2 << 8); //INFO("gxSTAT 0x%08X (proj %i, pos %i)\n", ret, _hack_getMatrixStackLevel(1), _hack_getMatrixStackLevel(2)); return ret; } void TGXSTAT::write32(const u32 val) { gxfifo_irq = (val>>30)&3; if(BIT15(val)) { // Writing "1" to Bit15 does reset the Error Flag (Bit15), // and additionally resets the Projection Stack Pointer (Bit13) mtxStack[0].position = 0; se = 0; //clear stack error flag } //printf("gxstat write: %08X while gxfifo.size=%d\n",val,gxFIFO.size); //if (val & (1<<29)) // clear? (only in homebrew?) //{ // GFX_PIPEclear(); // GFX_FIFOclear(); // return; //} } void TGXSTAT::savestate(EMUFILE *f) { write32le(1,f); //version write8le(tb,f); write8le(tr,f); write8le(se,f); write8le(gxfifo_irq,f); write8le(sb,f); } bool TGXSTAT::loadstate(EMUFILE *f) { u32 version; if(read32le(&version,f) != 1) return false; if(version > 1) return false; read8le(&tb,f); read8le(&tr,f); read8le(&se,f); read8le(&gxfifo_irq,f); if (version >= 1) read8le(&sb,f); return true; } //this could be inlined... void MMU_struct_new::write_dma(const int proc, const int size, const u32 _adr, const u32 val) { //printf("%08lld -- write_dma: %d %d %08X %08X\n",nds_timer,proc,size,_adr,val); const u32 adr = _adr - _REG_DMA_CONTROL_MIN; const u32 chan = adr/12; const u32 regnum = (adr - chan*12)>>2; MMU_new.dma[proc][chan].regs[regnum]->write(size,adr,val); } //this could be inlined... u32 MMU_struct_new::read_dma(const int proc, const int size, const u32 _adr) { const u32 adr = _adr - _REG_DMA_CONTROL_MIN; const u32 chan = adr/12; const u32 regnum = (adr - chan*12)>>2; const u32 temp = MMU_new.dma[proc][chan].regs[regnum]->read(size,adr); //printf("%08lld -- read_dma: %d %d %08X = %08X\n",nds_timer,proc,size,_adr,temp); return temp; } bool MMU_struct_new::is_dma(const u32 adr) { return adr >= _REG_DMA_CONTROL_MIN && adr <= _REG_DMA_CONTROL_MAX; } MMU_struct_new::MMU_struct_new() { for(int i=0;i<2;i++) for(int j=0;j<4;j++) { dma[i][j].procnum = i; dma[i][j].chan = j; } } void DivController::savestate(EMUFILE* os) { write8le(&mode,os); write8le(&busy,os); write8le(&div0,os); } bool DivController::loadstate(EMUFILE* is, int version) { int ret = 1; ret &= read8le(&mode,is); ret &= read8le(&busy,is); ret &= read8le(&div0,is); return ret==1; } void SqrtController::savestate(EMUFILE* os) { write8le(&mode,os); write8le(&busy,os); } bool SqrtController::loadstate(EMUFILE* is, int version) { int ret=1; ret &= read8le(&mode,is); ret &= read8le(&busy,is); return ret==1; } bool DmaController::loadstate(EMUFILE* f) { u32 version; if(read32le(&version,f) != 1) return false; if(version >1) return false; read8le(&enable,f); read8le(&irq,f); read8le(&repeatMode,f); read8le(&_startmode,f); read8le(&userEnable,f); read32le(&wordcount,f); u8 temp; read8le(&temp,f); startmode = (EDMAMode)temp; read8le(&temp,f); bitWidth = (EDMABitWidth)temp; read8le(&temp,f); sar = (EDMASourceUpdate)temp; read8le(&temp,f); dar = (EDMADestinationUpdate)temp; read32le(&saddr,f); read32le(&daddr,f); read32le(&dmaCheck,f); read32le(&running,f); read32le(&paused,f); read32le(&triggered,f); read64le(&nextEvent,f); if(version==1) { read32le(&saddr_user,f); read32le(&daddr_user,f); } return true; } void DmaController::savestate(EMUFILE *f) { write32le(1,f); //version write8le(enable,f); write8le(irq,f); write8le(repeatMode,f); write8le(_startmode,f); write8le(userEnable,f); write32le(wordcount,f); write8le(startmode,f); write8le(bitWidth,f); write8le(sar,f); write8le(dar,f); write32le(saddr,f); write32le(daddr,f); write32le(dmaCheck,f); write32le(running,f); write32le(paused,f); write32le(triggered,f); write64le(nextEvent,f); write32le(saddr_user,f); write32le(daddr_user,f); } void DmaController::write32(const u32 val) { if(running) { //desp triggers this a lot. figure out whats going on //printf("thats weird..user edited dma control while it was running\n"); } wordcount = val&0x1FFFFF; u8 wasRepeatMode = repeatMode; u8 wasEnable = enable; u32 valhi = val>>16; dar = (EDMADestinationUpdate)((valhi>>5)&3); sar = (EDMASourceUpdate)((valhi>>7)&3); repeatMode = BIT9(valhi); bitWidth = (EDMABitWidth)BIT10(valhi); _startmode = (valhi>>11)&7; if(procnum==ARMCPU_ARM7) _startmode &= 6; irq = BIT14(valhi); enable = BIT15(valhi); //printf("ARM%c DMA%d WRITE %08X count %08X, %08X -> %08X\n", procnum?'7':'9', chan, val, wordcount, saddr_user, daddr_user); //if(irq) printf("!!!!!!!!!!!!IRQ!!!!!!!!!!!!!\n"); //make sure we don't get any old triggers if(!wasEnable && enable) triggered = FALSE; if(enable) { //address registers are reloaded from user's settings whenever dma is enabled //this is tested well by contra4 classic games, which use this to hdma scroll registers //specifically in the fit-screen mode. saddr = saddr_user; daddr = daddr_user; } //printf("dma %d,%d set to startmode %d with wordcount set to: %08X\n",procnum,chan,_startmode,wordcount); if (enable && procnum==1 && (!(chan&1)) && _startmode==6) printf("!!!---!!! WIFI DMA: %08X TO %08X, %i WORDS !!!---!!!\n", saddr, daddr, wordcount); //analyze enabling and startmode. //note that we only do this if the dma was freshly enabled. //we should probably also only be latching these other regs in that case too.. //but for now just this one will do (otherwise the dma repeat stop procedure (in this case the ff4 title menu load with gamecard dma) will fail) //if(!running) enable = userEnable; //if we were previously in a triggered mode, and were already enabled, //then don't re-trigger now. this is rather confusing.. //we really only want to auto-trigger gxfifo and immediate modes. //but we don't know what mode we're in yet. //so this is our workaround //(otherwise the dma repeat stop procedure (in this case the ff4 title menu load with gamecard dma) will fail) bool doNotStart = false; if(startmode != EDMAMode_Immediate && startmode != EDMAMode_GXFifo && wasEnable) doNotStart = true; //this dma may need to trigger now, so give it a chance //if(!(wasRepeatMode && !repeatMode)) //this was an older test if(!doNotStart) doSchedule(); driver->DEBUG_UpdateIORegView(BaseDriver::EDEBUG_IOREG_DMA); } void DmaController::exec() { //this function runs when the DMA ends. the dma start actually queues this event after some kind of guess as to how long the DMA should take //printf("ARM%c DMA%d execute, count %08X, mode %d%s\n", procnum?'7':'9', chan, wordcount, startmode, running?" - RUNNING":""); //we'll need to unfreeze the arm9 bus now if(procnum==ARMCPU_ARM9) nds.freezeBus &= ~(1<<(chan+1)); dmaCheck = FALSE; if(running) { switch(startmode) { case EDMAMode_GXFifo: //this dma mode won't finish always its job when it gets signalled //sometimes it will have words left to transfer. //if(!paused) printf("gxfifo dma ended with %d remaining\n",wordcount); //only print this once if(wordcount>0) { doPause(); break; } default: doStop(); driver->DEBUG_UpdateIORegView(BaseDriver::EDEBUG_IOREG_DMA); return; } } if(enable) { //analyze startmode (this only gets latched when a dma begins) if(procnum==ARMCPU_ARM9) startmode = (EDMAMode)_startmode; else { //arm7 startmode analysis: static const EDMAMode lookup[] = {EDMAMode_Immediate,EDMAMode_VBlank,EDMAMode_Card,EDMAMode7_Wifi}; //arm7 has a slightly different startmode encoding startmode = lookup[_startmode>>1]; if(startmode == EDMAMode7_Wifi && (chan==1 || chan==3)) startmode = EDMAMode7_GBASlot; } //make it run, if it is triggered //but first, scan for triggering conditions switch(startmode) { case EDMAMode_Immediate: triggered = TRUE; break; case EDMAMode_GXFifo: if(gxFIFO.size<=127) triggered = TRUE; break; default: break; } if(triggered) { //if(procnum==0) printf("vc=%03d %08lld trig type %d dma#%d w/words %d at src:%08X dst:%08X gxf:%d",nds.VCount,nds_timer,startmode,chan,wordcount,saddr,daddr,gxFIFO.size); running = TRUE; paused = FALSE; if(procnum == ARMCPU_ARM9) doCopy(); else doCopy(); //printf(";%d\n",gxFIFO.size); } } driver->DEBUG_UpdateIORegView(BaseDriver::EDEBUG_IOREG_DMA); } template void DmaController::doCopy() { //generate a copy count depending on various copy mode's behavior u32 todo = wordcount; u32 sz = (bitWidth==EDMABitWidth_16)?2:4; u32 dstinc = 0, srcinc = 0; if(PROCNUM == ARMCPU_ARM9) if(todo == 0) todo = 0x200000; //according to gbatek.. we've verified this behaviour on the arm7 if(startmode == EDMAMode_MemDisplay) { todo = 128; //this is a hack. maybe an alright one though. it should be 4 words at a time. this is a whole scanline //apparently this dma turns off after it finishes a frame if(nds.VCount==191) enable = 0; } if(startmode == EDMAMode_Card) todo = MMU.dscard[PROCNUM].transfer_count / sz; if(startmode == EDMAMode_GXFifo) todo = std::min(todo,(u32)112); //determine how we're going to copy bool bogarted = false; switch(dar) { case EDMADestinationUpdate_Increment : dstinc = sz; break; case EDMADestinationUpdate_Decrement : dstinc = (u32)-(s32)sz; break; case EDMADestinationUpdate_Fixed : dstinc = 0; break; case EDMADestinationUpdate_IncrementReload : dstinc = sz; break; default: bogarted = true; break; } switch(sar) { case EDMASourceUpdate_Increment : srcinc = sz; break; case EDMASourceUpdate_Decrement : srcinc = (u32)-(s32)sz; break; case EDMASourceUpdate_Fixed : srcinc = 0; break; case EDMASourceUpdate_Invalid : bogarted = true; break; default: bogarted = true; break; } //need to figure out what to do about this if(bogarted) { printf("YOUR GAME IS BOGARTED!!! PLEASE REPORT!!!\n"); assert(false); return; } u32 src = saddr; u32 dst = daddr; //if these do not use MMU_AT_DMA and the corresponding code in the read/write routines, //then danny phantom title screen will be filled with a garbage char which is made by //dmaing from 0x00000000 to 0x06000000 //TODO - these might be losing out a lot by not going through the templated version anymore. //we might make another function to do just the raw copy op which can use them with checks //outside the loop int time_elapsed = 0; if(sz==4) { for(s32 i=(s32)todo; i>0; i--) { time_elapsed += _MMU_accesstime(src,true); time_elapsed += _MMU_accesstime(dst,true); u32 temp = _MMU_read32(procnum,MMU_AT_DMA,src); _MMU_write32(procnum,MMU_AT_DMA,dst, temp); dst += dstinc; src += srcinc; } } else { for(s32 i=(s32)todo; i>0; i--) { time_elapsed += _MMU_accesstime(src,true); time_elapsed += _MMU_accesstime(dst,true); u16 temp = _MMU_read16(procnum,MMU_AT_DMA,src); _MMU_write16(procnum,MMU_AT_DMA,dst, temp); dst += dstinc; src += srcinc; } } //printf("ARM%c dma of size %d from 0x%08X to 0x%08X took %d cycles\n",PROCNUM==0?'9':'7',todo*sz,saddr,daddr,time_elapsed); //reschedule an event for the end of this dma, and figure out how much it cost us doSchedule(); nextEvent += time_elapsed; //freeze the ARM9 bus for the duration of this DMA //thats not entirely accurate if(procnum==ARMCPU_ARM9) nds.freezeBus |= (1<<(chan+1)); //write back the addresses saddr = src; if(dar != EDMADestinationUpdate_IncrementReload) //but dont write back dst if we were supposed to reload daddr = dst; if(!repeatMode) { if(startmode == EDMAMode_Card) wordcount = 0; else wordcount -= todo; } } void triggerDma(EDMAMode mode) { MACRODO2(0, { const int i=X; MACRODO4(0, { const int j=X; MMU_new.dma[i][j].tryTrigger(mode); }); }); } void DmaController::tryTrigger(EDMAMode mode) { if(startmode != mode) return; if(!enable) return; //hmm dont trigger it if its already running! //but paused things need triggers to continue if(running && !paused) return; triggered = TRUE; doSchedule(); } void DmaController::doSchedule() { dmaCheck = TRUE; nextEvent = nds_timer; NDS_RescheduleDMA(); } void DmaController::doPause() { triggered = FALSE; paused = TRUE; } void DmaController::doStop() { //if(procnum==0) printf("%08lld stop type %d dma#%d\n",nds_timer,startmode,chan); running = FALSE; if(!repeatMode) enable = FALSE; if(irq) NDS_makeIrq(procnum,IRQ_BIT_DMA_0+chan); } u32 DmaController::read32() { u32 ret = 0; ret |= enable<<31; ret |= irq<<30; ret |= _startmode<<27; ret |= bitWidth<<26; ret |= repeatMode<<25; ret |= sar<<23; ret |= dar<<21; ret |= wordcount; //printf("dma %d,%d READ %08X\n",procnum,chan,ret); return ret; } static INLINE void write_auxspicnt(const int PROCNUM, const int size, const int adr, const int val) { u16 oldCnt = MMU.AUX_SPI_CNT; switch(size) { case 16: MMU.AUX_SPI_CNT = val; break; case 8: T1WriteByte((u8*)&MMU.AUX_SPI_CNT, adr, val); break; } bool csOld = (oldCnt & (1 << 6))?true:false; bool cs = (MMU.AUX_SPI_CNT & (1 << 6))?true:false; bool spi = (MMU.AUX_SPI_CNT & (1 << 13))?true:false; if ((!cs && csOld) || (spi && (oldCnt == 0) && !cs)) { //printf("MMU%c: CS changed from HIGH to LOW *****\n", PROCNUM?'7':'9'); slot1_device->auxspi_reset(PROCNUM); } //printf("MMU%c: cnt %04X, old %04X\n", PROCNUM?'7':'9', MMU.AUX_SPI_CNT, oldCnt); } template bool validateIORegsWrite(u32 addr, u8 size, u32 val) { if (PROCNUM == ARMCPU_ARM9) { switch (addr & 0x0FFFFFFC) { // Display Engine A case REG_DISPA_DISPCNT: case REG_DISPA_DISPSTAT: case REG_DISPA_VCOUNT: // same as GBA... case REG_DISPA_BG0CNT: case REG_DISPA_BG1CNT: case REG_DISPA_BG2CNT: case REG_DISPA_BG3CNT: case REG_DISPA_BG0HOFS: case REG_DISPA_BG0VOFS: case REG_DISPA_BG1HOFS: case REG_DISPA_BG1VOFS: case REG_DISPA_BG2HOFS: case REG_DISPA_BG2VOFS: case REG_DISPA_BG3HOFS: case REG_DISPA_BG3VOFS: case REG_DISPA_BG2PA: case REG_DISPA_BG2PB: case REG_DISPA_BG2PC: case REG_DISPA_BG2PD: case REG_DISPA_BG2XL: case REG_DISPA_BG2XH: case REG_DISPA_BG2YL: case REG_DISPA_BG2YH: case REG_DISPA_BG3PA: case REG_DISPA_BG3PB: case REG_DISPA_BG3PC: case REG_DISPA_BG3PD: case REG_DISPA_BG3XL: case REG_DISPA_BG3XH: case REG_DISPA_BG3YL: case REG_DISPA_BG3YH: case REG_DISPA_WIN0H: case REG_DISPA_WIN1H: case REG_DISPA_WIN0V: case REG_DISPA_WIN1V: case REG_DISPA_WININ: case REG_DISPA_WINOUT: case REG_DISPA_MOSAIC: case REG_DISPA_BLDCNT: case REG_DISPA_BLDALPHA: case REG_DISPA_BLDY: // ...GBA case REG_DISPA_DISP3DCNT: case REG_DISPA_DISPCAPCNT: case REG_DISPA_DISPMMEMFIFO: case REG_DISPA_MASTERBRIGHT: // DMA case REG_DMA0SAD: case REG_DMA0DAD: case REG_DMA0CNTL: case REG_DMA0CNTH: case REG_DMA1SAD: case REG_DMA1DAD: case REG_DMA1CNTL: case REG_DMA2SAD: case REG_DMA2DAD: case REG_DMA2CNTL: case REG_DMA2CNTH: case REG_DMA3SAD: case REG_DMA3DAD: case REG_DMA3CNTL: case REG_DMA3CNTH: case REG_DMA0FILL: case REG_DMA1FILL: case REG_DMA2FILL: case REG_DMA3FILL: // Timers case REG_TM0CNTL: case REG_TM0CNTH: case REG_TM1CNTL: case REG_TM1CNTH: case REG_TM2CNTL: case REG_TM2CNTH: case REG_TM3CNTL: case REG_TM3CNTH: // Keypad Input case REG_KEYINPUT: case REG_KEYCNT: // IPC case REG_IPCSYNC: case REG_IPCFIFOCNT: case REG_IPCFIFOSEND: // ROM case REG_AUXSPICNT: case REG_AUXSPIDATA: case REG_GCROMCTRL: case REG_GCCMDOUT + 0x00: case REG_GCCMDOUT + 0x04: case REG_ENCSEED0L: case REG_ENCSEED1L: case REG_ENCSEED0H: case REG_ENCSEED1H: // Memory/IRQ case REG_EXMEMCNT: case REG_IME: case REG_IE: case REG_IF: case REG_VRAMCNTA: case REG_VRAMCNTB: case REG_VRAMCNTC: case REG_VRAMCNTD: case REG_VRAMCNTE: case REG_VRAMCNTF: case REG_VRAMCNTG: case REG_WRAMCNT: case REG_VRAMCNTH: case REG_VRAMCNTI: // Math case REG_DIVCNT: case REG_DIVNUMER + 0x00: case REG_DIVNUMER + 0x04: case REG_DIVDENOM + 0x00: case REG_DIVDENOM + 0x04: case REG_DIVRESULT + 0x00: case REG_DIVRESULT + 0x04: case REG_DIVREMRESULT + 0x00: case REG_DIVREMRESULT + 0x04: case REG_SQRTCNT: case REG_SQRTRESULT: case REG_SQRTPARAM + 0x00: case REG_SQRTPARAM + 0x04: // Other case REG_POSTFLG: case REG_HALTCNT: case REG_POWCNT1: //R case eng_3D_RDLINES_COUNT: // 3D =============================================================== case eng_3D_EDGE_COLOR + 0x00: case eng_3D_EDGE_COLOR + 0x04: case eng_3D_EDGE_COLOR + 0x08: case eng_3D_EDGE_COLOR + 0x0C: case eng_3D_ALPHA_TEST_REF: case eng_3D_CLEAR_COLOR: case eng_3D_CLEAR_DEPTH: case eng_3D_CLRIMAGE_OFFSET: case eng_3D_FOG_COLOR: case eng_3D_FOG_OFFSET: case eng_3D_FOG_TABLE + 0x00: case eng_3D_FOG_TABLE + 0x04: case eng_3D_FOG_TABLE + 0x08: case eng_3D_FOG_TABLE + 0x0C: case eng_3D_FOG_TABLE + 0x10: case eng_3D_FOG_TABLE + 0x14: case eng_3D_FOG_TABLE + 0x18: case eng_3D_FOG_TABLE + 0x1C: case eng_3D_TOON_TABLE + 0x00: case eng_3D_TOON_TABLE + 0x04: case eng_3D_TOON_TABLE + 0x08: case eng_3D_TOON_TABLE + 0x0C: case eng_3D_TOON_TABLE + 0x10: case eng_3D_TOON_TABLE + 0x14: case eng_3D_TOON_TABLE + 0x18: case eng_3D_TOON_TABLE + 0x1C: case eng_3D_TOON_TABLE + 0x20: case eng_3D_TOON_TABLE + 0x24: case eng_3D_TOON_TABLE + 0x28: case eng_3D_TOON_TABLE + 0x2C: case eng_3D_TOON_TABLE + 0x30: case eng_3D_TOON_TABLE + 0x34: case eng_3D_TOON_TABLE + 0x38: case eng_3D_TOON_TABLE + 0x3C: case eng_3D_GXFIFO + 0x00: case eng_3D_GXFIFO + 0x04: case eng_3D_GXFIFO + 0x08: case eng_3D_GXFIFO + 0x0C: case eng_3D_GXFIFO + 0x10: case eng_3D_GXFIFO + 0x14: case eng_3D_GXFIFO + 0x18: case eng_3D_GXFIFO + 0x1C: case eng_3D_GXFIFO + 0x20: case eng_3D_GXFIFO + 0x24: case eng_3D_GXFIFO + 0x28: case eng_3D_GXFIFO + 0x2C: case eng_3D_GXFIFO + 0x30: case eng_3D_GXFIFO + 0x34: case eng_3D_GXFIFO + 0x38: case eng_3D_GXFIFO + 0x3C: // 3d commands case cmd_3D_MTX_MODE: case cmd_3D_MTX_PUSH: case cmd_3D_MTX_POP: case cmd_3D_MTX_STORE: case cmd_3D_MTX_RESTORE: case cmd_3D_MTX_IDENTITY: case cmd_3D_MTX_LOAD_4x4: case cmd_3D_MTX_LOAD_4x3: case cmd_3D_MTX_MULT_4x4: case cmd_3D_MTX_MULT_4x3: case cmd_3D_MTX_MULT_3x3: case cmd_3D_MTX_SCALE: case cmd_3D_MTX_TRANS: case cmd_3D_COLOR: case cmd_3D_NORMA: case cmd_3D_TEXCOORD: case cmd_3D_VTX_16: case cmd_3D_VTX_10: case cmd_3D_VTX_XY: case cmd_3D_VTX_XZ: case cmd_3D_VTX_YZ: case cmd_3D_VTX_DIFF: case cmd_3D_POLYGON_ATTR: case cmd_3D_TEXIMAGE_PARAM: case cmd_3D_PLTT_BASE: case cmd_3D_DIF_AMB: case cmd_3D_SPE_EMI: case cmd_3D_LIGHT_VECTOR: case cmd_3D_LIGHT_COLOR: case cmd_3D_SHININESS: case cmd_3D_BEGIN_VTXS: case cmd_3D_END_VTXS: case cmd_3D_SWAP_BUFFERS: case cmd_3D_VIEWPORT: case cmd_3D_BOX_TEST: case cmd_3D_POS_TEST: case cmd_3D_VEC_TEST: case eng_3D_GXSTAT: //R case eng_3D_RAM_COUNT: case eng_3D_DISP_1DOT_DEPTH: //R case eng_3D_POS_RESULT + 0x00: case eng_3D_POS_RESULT + 0x04: case eng_3D_POS_RESULT + 0x08: case eng_3D_POS_RESULT + 0x0C: //R case eng_3D_VEC_RESULT + 0x00: case eng_3D_VEC_RESULT + 0x04: //R case eng_3D_CLIPMTX_RESULT + 0x00: case eng_3D_CLIPMTX_RESULT + 0x04: case eng_3D_CLIPMTX_RESULT + 0x08: case eng_3D_CLIPMTX_RESULT + 0x0C: //R case eng_3D_CLIPMTX_RESULT + 0x10: case eng_3D_CLIPMTX_RESULT + 0x14: case eng_3D_CLIPMTX_RESULT + 0x18: case eng_3D_CLIPMTX_RESULT + 0x1C: //R case eng_3D_CLIPMTX_RESULT + 0x20: case eng_3D_CLIPMTX_RESULT + 0x24: case eng_3D_CLIPMTX_RESULT + 0x28: case eng_3D_CLIPMTX_RESULT + 0x2C: //R case eng_3D_CLIPMTX_RESULT + 0x30: case eng_3D_CLIPMTX_RESULT + 0x34: case eng_3D_CLIPMTX_RESULT + 0x38: case eng_3D_CLIPMTX_RESULT + 0x3C: //R case eng_3D_VECMTX_RESULT + 0x00: case eng_3D_VECMTX_RESULT + 0x04: case eng_3D_VECMTX_RESULT + 0x08: case eng_3D_VECMTX_RESULT + 0x0C: //R case eng_3D_VECMTX_RESULT + 0x20: // 0x04001xxx case REG_DISPB_DISPCNT: // same as GBA... case REG_DISPB_BG0CNT: case REG_DISPB_BG1CNT: case REG_DISPB_BG2CNT: case REG_DISPB_BG3CNT: case REG_DISPB_BG0HOFS: case REG_DISPB_BG0VOFS: case REG_DISPB_BG1HOFS: case REG_DISPB_BG1VOFS: case REG_DISPB_BG2HOFS: case REG_DISPB_BG2VOFS: case REG_DISPB_BG3HOFS: case REG_DISPB_BG3VOFS: case REG_DISPB_BG2PA: case REG_DISPB_BG2PB: case REG_DISPB_BG2PC: case REG_DISPB_BG2PD: case REG_DISPB_BG2XL: case REG_DISPB_BG2XH: case REG_DISPB_BG2YL: case REG_DISPB_BG2YH: case REG_DISPB_BG3PA: case REG_DISPB_BG3PB: case REG_DISPB_BG3PC: case REG_DISPB_BG3PD: case REG_DISPB_BG3XL: case REG_DISPB_BG3XH: case REG_DISPB_BG3YL: case REG_DISPB_BG3YH: case REG_DISPB_WIN0H: case REG_DISPB_WIN1H: case REG_DISPB_WIN0V: case REG_DISPB_WIN1V: case REG_DISPB_WININ: case REG_DISPB_WINOUT: case REG_DISPB_MOSAIC: case REG_DISPB_BLDCNT: case REG_DISPB_BLDALPHA: case REG_DISPB_BLDY: // ...GBA case REG_DISPB_MASTERBRIGHT: // 0x04100000 case REG_IPCFIFORECV: case REG_GCDATAIN: //printf("MMU9 write%02d to register %08Xh = %08Xh (PC:%08X)\n", size, addr, val, ARMPROC.instruct_adr); return true; default: #ifdef DEVELOPER printf("MMU9 write%02d to undefined register %08Xh = %08Xh (PC:%08X)\n", size, addr, val, ARMPROC.instruct_adr); #endif return false; } } // ARM7 if (PROCNUM == ARMCPU_ARM7) { switch (addr & 0x0FFFFFFC) { case REG_DISPA_DISPSTAT: case REG_DISPA_VCOUNT: // DMA case REG_DMA0SAD: case REG_DMA0DAD: case REG_DMA0CNTL: case REG_DMA0CNTH: case REG_DMA1SAD: case REG_DMA1DAD: case REG_DMA1CNTL: case REG_DMA2SAD: case REG_DMA2DAD: case REG_DMA2CNTL: case REG_DMA2CNTH: case REG_DMA3SAD: case REG_DMA3DAD: case REG_DMA3CNTL: case REG_DMA3CNTH: case REG_DMA0FILL: case REG_DMA1FILL: case REG_DMA2FILL: case REG_DMA3FILL: // Timers case REG_TM0CNTL: case REG_TM0CNTH: case REG_TM1CNTL: case REG_TM1CNTH: case REG_TM2CNTL: case REG_TM2CNTH: case REG_TM3CNTL: case REG_TM3CNTH: // SIO/Keypad Input/RTC case REG_SIODATA32: case REG_SIOCNT: case REG_KEYINPUT: case REG_KEYCNT: case REG_RCNT: case REG_EXTKEYIN: case REG_RTC: // IPC case REG_IPCSYNC: case REG_IPCFIFOCNT: case REG_IPCFIFOSEND: // ROM case REG_AUXSPICNT: case REG_AUXSPIDATA: case REG_GCROMCTRL: case REG_GCCMDOUT: case REG_GCCMDOUT + 4: case REG_ENCSEED0L: case REG_ENCSEED1L: case REG_ENCSEED0H: case REG_ENCSEED1H: case REG_SPICNT: case REG_SPIDATA: // Memory/IRQ case REG_EXMEMCNT: case REG_IME: case REG_IE: case REG_IF: case REG_VRAMSTAT: case REG_WRAMSTAT: // Other case REG_POSTFLG: case REG_HALTCNT: case REG_POWCNT2: case REG_BIOSPROT: // Sound // 0x04100000 - IPC case REG_IPCFIFORECV: case REG_GCDATAIN: //printf("MMU7 write%02d to register %08Xh = %08Xh (PC:%08X)\n", size, addr, val, ARMPROC.instruct_adr); return true; default: #ifdef DEVELOPER printf("MMU7 write%02d to undefined register %08Xh = %08Xh (PC:%08X)\n", size, addr, val, ARMPROC.instruct_adr); #endif break; } } return false; } #define VALIDATE_IO_REGS_READ(PROC, SIZE) ; //================================================================================================== ARM9 * //========================================================================================================= //========================================================================================================= //================================================= MMU write 08 void FASTCALL _MMU_ARM9_write08(u32 adr, u8 val) { adr &= 0x0FFFFFFF; mmu_log_debug_ARM9(adr, "(write08) 0x%02X", val); if(adr < 0x02000000) { #ifdef HAVE_JIT JIT_COMPILED_FUNC_KNOWNBANK(adr, ARM9_ITCM, 0x7FFF, 0) = 0; #endif T1WriteByte(MMU.ARM9_ITCM, adr & 0x7FFF, val); return; } if (slot2_write(adr, val)) return; //block 8bit writes to OAM and palette memory if ((adr & 0x0F000000) == 0x07000000) return; if ((adr & 0x0F000000) == 0x05000000) return; // Address is an IO register if ((adr >> 24) == 4) { if (!validateIORegsWrite(adr, 8, val)) return; // TODO: add pal reg if (nds.power1.gpuMain == 0) if ((adr >= 0x04000008) && (adr <= 0x0400005F)) return; if (nds.power1.gpuSub == 0) if ((adr >= 0x04001008) && (adr <= 0x0400105F)) return; if (nds.power1.gfx3d_geometry == 0) if ((adr >= 0x04000400) && (adr <= 0x040006FF)) return; if (nds.power1.gfx3d_render == 0) if ((adr >= 0x04000320) && (adr <= 0x040003FF)) return; if(MMU_new.is_dma(adr)) { MMU_new.write_dma(ARMCPU_ARM9,8,adr,val); return; } GPUEngineA *mainEngine = GPU->GetEngineMain(); GPUEngineB *subEngine = GPU->GetEngineSub(); /* fog table: only write bottom 7 bits */ if ( (adr >= (eng_3D_FOG_TABLE+0x00)) && (adr <= (eng_3D_FOG_TABLE+0x1F)) ) { val &= 0x7F; } else { if ( (adr >= (eng_3D_CLEAR_COLOR+0)) && (adr <= (eng_3D_CLEAR_COLOR+3)) ) { T1WriteByte((u8*)&gfx3d.state.clearColor,adr-eng_3D_CLEAR_COLOR,val); } else { switch(adr) { case REG_SQRTCNT: printf("ERROR 8bit SQRTCNT WRITE\n"); return; case REG_SQRTCNT+1: printf("ERROR 8bit SQRTCNT1 WRITE\n"); return; case REG_SQRTCNT+2: printf("ERROR 8bit SQRTCNT2 WRITE\n"); return; case REG_SQRTCNT+3: printf("ERROR 8bit SQRTCNT3 WRITE\n"); return; #if 1 case REG_DIVCNT: printf("ERROR 8bit DIVCNT WRITE\n"); return; case REG_DIVCNT+1: printf("ERROR 8bit DIVCNT+1 WRITE\n"); return; case REG_DIVCNT+2: printf("ERROR 8bit DIVCNT+2 WRITE\n"); return; case REG_DIVCNT+3: printf("ERROR 8bit DIVCNT+3 WRITE\n"); return; #endif //ensata putchar port case 0x04FFF000: if(nds.ensataEmulation) { printf("%c",val); fflush(stdout); } break; case eng_3D_GXSTAT: MMU_new.gxstat.write(8,adr,val); break; case REG_DISPA_WIN0H: mainEngine->SetWIN0_H1(val); break ; case REG_DISPA_WIN0H+1: mainEngine->SetWIN0_H0(val); break ; case REG_DISPA_WIN1H: mainEngine->SetWIN1_H1(val); break ; case REG_DISPA_WIN1H+1: mainEngine->SetWIN1_H0(val); break ; case REG_DISPB_WIN0H: subEngine->SetWIN0_H1(val); break ; case REG_DISPB_WIN0H+1: subEngine->SetWIN0_H0(val); break ; case REG_DISPB_WIN1H: subEngine->SetWIN1_H1(val); break ; case REG_DISPB_WIN1H+1: subEngine->SetWIN1_H0(val); break ; case REG_DISPA_WIN0V: mainEngine->SetWIN0_V1(val) ; break ; case REG_DISPA_WIN0V+1: mainEngine->SetWIN0_V0(val) ; break ; case REG_DISPA_WIN1V: mainEngine->SetWIN1_V1(val) ; break ; case REG_DISPA_WIN1V+1: mainEngine->SetWIN1_V0(val) ; break ; case REG_DISPB_WIN0V: subEngine->SetWIN0_V1(val); break ; case REG_DISPB_WIN0V+1: subEngine->SetWIN0_V0(val); break ; case REG_DISPB_WIN1V: subEngine->SetWIN1_V1(val); break ; case REG_DISPB_WIN1V+1: subEngine->SetWIN1_V0(val); break ; case REG_DISPA_WININ: mainEngine->SetWININ0(val); break ; case REG_DISPA_WININ+1: mainEngine->SetWININ1(val); break ; case REG_DISPA_WINOUT: mainEngine->SetWINOUT(val); break ; case REG_DISPA_WINOUT+1: mainEngine->SetWINOBJ(val); break ; case REG_DISPB_WININ: subEngine->SetWININ0(val); break ; case REG_DISPB_WININ+1: subEngine->SetWININ1(val); break ; case REG_DISPB_WINOUT: subEngine->SetWINOUT(val); break ; case REG_DISPB_WINOUT+1: subEngine->SetWINOBJ(val); break ; case REG_DISPA_BLDCNT: mainEngine->SetBLDCNT_HIGH(val); break; case REG_DISPA_BLDCNT+1: mainEngine->SetBLDCNT_LOW(val); break; case REG_DISPB_BLDCNT: subEngine->SetBLDCNT_HIGH(val); break; case REG_DISPB_BLDCNT+1: subEngine->SetBLDCNT_LOW(val); break; case REG_DISPA_BLDALPHA: mainEngine->SetBLDALPHA_EVA(val); break; case REG_DISPA_BLDALPHA+1: mainEngine->SetBLDALPHA_EVB(val); break; case REG_DISPB_BLDALPHA: subEngine->SetBLDALPHA_EVA(val); break; case REG_DISPB_BLDALPHA+1: subEngine->SetBLDALPHA_EVB(val); break; case REG_DISPA_BLDY: mainEngine->SetBLDY_EVY(val); break ; case REG_DISPB_BLDY: subEngine->SetBLDY_EVY(val); break; case REG_AUXSPICNT: case REG_AUXSPICNT+1: write_auxspicnt(ARMCPU_ARM9, 8, adr & 1, val); return; case REG_AUXSPIDATA: { //if(val!=0) MMU.AUX_SPI_CMD = val & 0xFF; //zero 20-aug-2013 - this seems pointless u8 spidata = slot1_device->auxspi_transaction(ARMCPU_ARM9,(u8)val); T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM9][(REG_AUXSPIDATA >> 20) & 0xff], REG_AUXSPIDATA & 0xfff, spidata); MMU.AUX_SPI_CNT &= ~0x80; //remove busy flag return; } case REG_POWCNT1: writereg_POWCNT1(8,adr,val); break; case REG_DISPA_DISP3DCNT: case REG_DISPA_DISP3DCNT+1: writereg_DISP3DCNT(8,adr,val); return; case REG_IF: REG_IF_WriteByte(0,val); break; case REG_IF+1: REG_IF_WriteByte(1,val); break; case REG_IF+2: REG_IF_WriteByte(2,val); break; case REG_IF+3: REG_IF_WriteByte(3,val); break; case REG_VRAMCNTA: case REG_VRAMCNTB: case REG_VRAMCNTC: case REG_VRAMCNTD: case REG_VRAMCNTE: case REG_VRAMCNTF: case REG_VRAMCNTG: case REG_WRAMCNT: case REG_VRAMCNTH: case REG_VRAMCNTI: MMU_VRAMmapControl(adr-REG_VRAMCNTA, val); break; case REG_DISPA_DISPMMEMFIFO: DISP_FIFOsend(val); return; #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 } } } MMU.MMU_MEM[ARMCPU_ARM9][adr>>20][adr&MMU.MMU_MASK[ARMCPU_ARM9][adr>>20]]=val; return; } bool unmapped, restricted; adr = MMU_LCDmap(adr, unmapped, restricted); if(unmapped) return; if(restricted) return; //block 8bit vram writes #ifdef HAVE_JIT if (JIT_MAPPED(adr, ARMCPU_ARM9)) JIT_COMPILED_FUNC_PREMASKED(adr, ARMCPU_ARM9, 0) = 0; #endif // Removed the &0xFF as they are implicit with the adr&0x0FFFFFFF [shash] MMU.MMU_MEM[ARMCPU_ARM9][adr>>20][adr&MMU.MMU_MASK[ARMCPU_ARM9][adr>>20]]=val; } //================================================= MMU ARM9 write 16 void FASTCALL _MMU_ARM9_write16(u32 adr, u16 val) { adr &= 0x0FFFFFFE; mmu_log_debug_ARM9(adr, "(write16) 0x%04X", val); if (adr < 0x02000000) { #ifdef HAVE_JIT JIT_COMPILED_FUNC_KNOWNBANK(adr, ARM9_ITCM, 0x7FFF, 0) = 0; #endif T1WriteWord(MMU.ARM9_ITCM, adr & 0x7FFF, val); return; } if (slot2_write(adr, val)) return; // Address is an IO register if ((adr >> 24) == 4) { if (!validateIORegsWrite(adr, 16, val)) return; // TODO: add pal reg if (nds.power1.gpuMain == 0) if ((adr >= 0x04000008) && (adr <= 0x0400005F)) return; if (nds.power1.gpuSub == 0) if ((adr >= 0x04001008) && (adr <= 0x0400105F)) return; if (nds.power1.gfx3d_geometry == 0) if ((adr >= 0x04000400) && (adr <= 0x040006FF)) return; if (nds.power1.gfx3d_render == 0) if ((adr >= 0x04000320) && (adr <= 0x040003FF)) return; if(MMU_new.is_dma(adr)) { MMU_new.write_dma(ARMCPU_ARM9,16,adr,val); return; } switch (adr >> 4) { //toon table case 0x0400038: case 0x0400039: case 0x040003A: case 0x040003B: ((u16 *)(MMU.MMU_MEM[ARMCPU_ARM9][0x40]))[(adr & 0xFFF)>>1] = val; gfx3d_UpdateToonTable((adr & 0x3F) >> 1, val); return; } GPUEngineA *mainEngine = GPU->GetEngineMain(); GPUEngineB *subEngine = GPU->GetEngineSub(); // Address is an IO register switch(adr) { case eng_3D_GXSTAT: MMU_new.gxstat.write(16,adr,val); break; //fog table: only write bottom 7 bits case eng_3D_FOG_TABLE+0x00: case eng_3D_FOG_TABLE+0x02: case eng_3D_FOG_TABLE+0x04: case eng_3D_FOG_TABLE+0x06: case eng_3D_FOG_TABLE+0x08: case eng_3D_FOG_TABLE+0x0A: case eng_3D_FOG_TABLE+0x0C: case eng_3D_FOG_TABLE+0x0E: case eng_3D_FOG_TABLE+0x10: case eng_3D_FOG_TABLE+0x12: case eng_3D_FOG_TABLE+0x14: case eng_3D_FOG_TABLE+0x16: case eng_3D_FOG_TABLE+0x18: case eng_3D_FOG_TABLE+0x1A: case eng_3D_FOG_TABLE+0x1C: case eng_3D_FOG_TABLE+0x1E: val &= 0x7F7F; break; case REG_DISPA_BG2XL: mainEngine->setAffineStartWord(2,0,val,0); break; case REG_DISPA_BG2XH: mainEngine->setAffineStartWord(2,0,val,1); break; case REG_DISPA_BG2YL: mainEngine->setAffineStartWord(2,1,val,0); break; case REG_DISPA_BG2YH: mainEngine->setAffineStartWord(2,1,val,1); break; case REG_DISPA_BG3XL: mainEngine->setAffineStartWord(3,0,val,0); break; case REG_DISPA_BG3XH: mainEngine->setAffineStartWord(3,0,val,1); break; case REG_DISPA_BG3YL: mainEngine->setAffineStartWord(3,1,val,0); break; case REG_DISPA_BG3YH: mainEngine->setAffineStartWord(3,1,val,1); break; case REG_DISPB_BG2XL: subEngine->setAffineStartWord(2,0,val,0); break; case REG_DISPB_BG2XH: subEngine->setAffineStartWord(2,0,val,1); break; case REG_DISPB_BG2YL: subEngine->setAffineStartWord(2,1,val,0); break; case REG_DISPB_BG2YH: subEngine->setAffineStartWord(2,1,val,1); break; case REG_DISPB_BG3XL: subEngine->setAffineStartWord(3,0,val,0); break; case REG_DISPB_BG3XH: subEngine->setAffineStartWord(3,0,val,1); break; case REG_DISPB_BG3YL: subEngine->setAffineStartWord(3,1,val,0); break; case REG_DISPB_BG3YH: subEngine->setAffineStartWord(3,1,val,1); break; case REG_DISPA_DISP3DCNT: writereg_DISP3DCNT(16,adr,val); return; // Alpha test reference value - Parameters:1 case eng_3D_ALPHA_TEST_REF: ((u16 *)(MMU.MMU_MEM[ARMCPU_ARM9][0x40]))[0x340>>1] = val; gfx3d_glAlphaFunc(val); return; case eng_3D_CLEAR_COLOR: case eng_3D_CLEAR_COLOR+2: T1WriteWord((u8*)&gfx3d.state.clearColor,adr-eng_3D_CLEAR_COLOR,val); break; // Clear background depth setup - Parameters:2 case eng_3D_CLEAR_DEPTH: ((u16 *)(MMU.MMU_MEM[ARMCPU_ARM9][0x40]))[0x354>>1] = val; gfx3d_glClearDepth(val); return; // Fog Color - Parameters:4b case eng_3D_FOG_COLOR: ((u16 *)(MMU.MMU_MEM[ARMCPU_ARM9][0x40]))[0x358>>1] = val; gfx3d_glFogColor(val); return; case eng_3D_FOG_OFFSET: ((u32 *)(MMU.MMU_MEM[ARMCPU_ARM9][0x40]))[0x35C>>1] = val; gfx3d_glFogOffset(val); return; case REG_DIVCNT: MMU_new.div.write16(val); execdiv(); return; #if 1 case REG_DIVNUMER: case REG_DIVNUMER+2: case REG_DIVNUMER+4: printf("DIV: 16 write NUMER %08X. PLEASE REPORT! \n", val); break; case REG_DIVDENOM: case REG_DIVDENOM+2: case REG_DIVDENOM+4: printf("DIV: 16 write DENOM %08X. PLEASE REPORT! \n", val); break; #endif case REG_SQRTCNT: MMU_new.sqrt.write16(val); execsqrt(); return; case REG_DISPA_BLDCNT: mainEngine->SetBLDCNT(val); break ; case REG_DISPB_BLDCNT: subEngine->SetBLDCNT(val); break ; case REG_DISPA_BLDALPHA: mainEngine->SetBLDALPHA(val); break ; case REG_DISPB_BLDALPHA: subEngine->SetBLDALPHA(val); break ; case REG_DISPA_BLDY: mainEngine->SetBLDY_EVY(val); break ; case REG_DISPB_BLDY: subEngine->SetBLDY_EVY(val); break; case REG_DISPA_MASTERBRIGHT: mainEngine->SetMasterBrightness(val); break; /* case REG_DISPA_MOSAIC: GPU_setMOSAIC(MainScreen.gpu,val) ; break ; case REG_DISPB_MOSAIC: GPU_setMOSAIC(SubScreen.gpu,val) ; break ; */ //case REG_DISPA_BG0HOFS: // GPU_setBGxHOFS(0, MainScreen.gpu, val); // break; //case REG_DISPA_BG0VOFS: // GPU_setBGxVOFS(0, MainScreen.gpu, val); // break; //case REG_DISPA_BG1HOFS: // GPU_setBGxHOFS(1, MainScreen.gpu, val); // break; //case REG_DISPA_BG1VOFS: // GPU_setBGxVOFS(1, MainScreen.gpu, val); // break; //case REG_DISPA_BG2HOFS: // GPU_setBGxHOFS(2, MainScreen.gpu, val); // break; //case REG_DISPA_BG2VOFS: // GPU_setBGxVOFS(2, MainScreen.gpu, val); // break; //case REG_DISPA_BG3HOFS: // GPU_setBGxHOFS(3, MainScreen.gpu, val); // break; //case REG_DISPA_BG3VOFS: // GPU_setBGxVOFS(3, MainScreen.gpu, val); // break; case REG_DISPA_WIN0H: mainEngine->SetWIN0_H(val); break ; case REG_DISPA_WIN1H: mainEngine->SetWIN1_H(val); break ; case REG_DISPB_WIN0H: subEngine->SetWIN0_H(val); break ; case REG_DISPB_WIN1H: subEngine->SetWIN1_H(val); break ; case REG_DISPA_WIN0V: mainEngine->SetWIN0_V(val); break ; case REG_DISPA_WIN1V: mainEngine->SetWIN1_V(val); break ; case REG_DISPB_WIN0V: subEngine->SetWIN0_V(val); break ; case REG_DISPB_WIN1V: subEngine->SetWIN1_V(val); break ; case REG_DISPA_WININ: mainEngine->SetWININ(val); break ; case REG_DISPA_WINOUT: mainEngine->SetWINOUT16(val); break ; /* case REG_DISPB_BG0HOFS: GPU_setBGxHOFS(0, SubScreen.gpu, val); break; case REG_DISPB_BG0VOFS: GPU_setBGxVOFS(0, SubScreen.gpu, val); break; case REG_DISPB_BG1HOFS: GPU_setBGxHOFS(1, SubScreen.gpu, val); break; case REG_DISPB_BG1VOFS: GPU_setBGxVOFS(1, SubScreen.gpu, val); break; case REG_DISPB_BG2HOFS: GPU_setBGxHOFS(2, SubScreen.gpu, val); break; case REG_DISPB_BG2VOFS: GPU_setBGxVOFS(2, SubScreen.gpu, val); break; case REG_DISPB_BG3HOFS: GPU_setBGxHOFS(3, SubScreen.gpu, val); break; case REG_DISPB_BG3VOFS: GPU_setBGxVOFS(3, SubScreen.gpu, val); break;*/ case REG_DISPB_WININ: subEngine->SetWININ(val); break ; case REG_DISPB_WINOUT: subEngine->SetWINOUT16(val); break ; case REG_DISPB_MASTERBRIGHT: subEngine->SetMasterBrightness(val); break; case REG_POWCNT1: writereg_POWCNT1(16,adr,val); return; case REG_EXMEMCNT: { u16 remote_proc = T1ReadWord(MMU.MMU_MEM[ARMCPU_ARM7][0x40], 0x204); T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x204, val); T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM7][0x40], 0x204, (val & 0xFF80) | (remote_proc & 0x7F)); return; } case REG_AUXSPICNT: write_auxspicnt(ARMCPU_ARM9, 16, 0, val); return; case REG_AUXSPIDATA: { //if(val!=0) MMU.AUX_SPI_CMD = val & 0xFF; //zero 20-aug-2013 - this seems pointless u8 spidata = slot1_device->auxspi_transaction(ARMCPU_ARM9,(u8)val); T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM9][(REG_AUXSPIDATA >> 20) & 0xff], REG_AUXSPIDATA & 0xfff, spidata); MMU.AUX_SPI_CNT &= ~0x80; //remove busy flag return; } case REG_DISPA_BG0CNT : //GPULOG("MAIN BG0 SETPROP 16B %08X\r\n", val); mainEngine->SetBGProp(0, val); T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x8, val); return; case REG_DISPA_BG1CNT : //GPULOG("MAIN BG1 SETPROP 16B %08X\r\n", val); mainEngine->SetBGProp(1, val); T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0xA, val); return; case REG_DISPA_BG2CNT : //GPULOG("MAIN BG2 SETPROP 16B %08X\r\n", val); mainEngine->SetBGProp(2, val); T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0xC, val); return; case REG_DISPA_BG3CNT : //GPULOG("MAIN BG3 SETPROP 16B %08X\r\n", val); mainEngine->SetBGProp(3, val); T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0xE, val); return; case REG_DISPB_BG0CNT : //GPULOG("SUB BG0 SETPROP 16B %08X\r\n", val); subEngine->SetBGProp(0, val); T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x1008, val); return; case REG_DISPB_BG1CNT : //GPULOG("SUB BG1 SETPROP 16B %08X\r\n", val); subEngine->SetBGProp(1, val); T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x100A, val); return; case REG_DISPB_BG2CNT : //GPULOG("SUB BG2 SETPROP 16B %08X\r\n", val); subEngine->SetBGProp(2, val); T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x100C, val); return; case REG_DISPB_BG3CNT : //GPULOG("SUB BG3 SETPROP 16B %08X\r\n", val); subEngine->SetBGProp(3, val); T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x100E, val); return; case REG_VRAMCNTA: case REG_VRAMCNTC: case REG_VRAMCNTE: case REG_VRAMCNTG: case REG_VRAMCNTH: MMU_VRAMmapControl(adr-REG_VRAMCNTA, val & 0xFF); MMU_VRAMmapControl(adr-REG_VRAMCNTA+1, val >> 8); break; case REG_IME: NDS_Reschedule(); MMU.reg_IME[ARMCPU_ARM9] = val & 0x01; T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x208, val); return; case REG_IE : NDS_Reschedule(); MMU.reg_IE[ARMCPU_ARM9] = (MMU.reg_IE[ARMCPU_ARM9]&0xFFFF0000) | val; return; case REG_IE + 2 : NDS_Reschedule(); MMU.reg_IE[ARMCPU_ARM9] = (MMU.reg_IE[ARMCPU_ARM9]&0xFFFF) | (((u32)val)<<16); return; case REG_IF: REG_IF_WriteWord(0,val); return; case REG_IF+2: REG_IF_WriteWord(2,val); return; case REG_IPCSYNC: MMU_IPCSync(ARMCPU_ARM9, val); return; case REG_IPCFIFOCNT: IPC_FIFOcnt(ARMCPU_ARM9, val); return; case REG_TM0CNTL : case REG_TM1CNTL : case REG_TM2CNTL : case REG_TM3CNTL : MMU.timerReload[ARMCPU_ARM9][(adr>>2)&3] = val; return; case REG_TM0CNTH : case REG_TM1CNTH : case REG_TM2CNTH : case REG_TM3CNTH : { int timerIndex = ((adr-2)>>2)&0x3; write_timer(ARMCPU_ARM9, timerIndex, val); return; } case REG_DISPA_DISPCNT : { u32 v = (T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0) & 0xFFFF0000) | val; mainEngine->SetVideoProp(v); T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0, v); return; } case REG_DISPA_DISPCNT+2 : { u32 v = (T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0) & 0xFFFF) | ((u32) val << 16); mainEngine->SetVideoProp(v); T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0, v); } return; case REG_DISPA_DISPCAPCNT : { u32 v = (T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x64) & 0xFFFF0000) | val; mainEngine->SetDISPCAPCNT(v); T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x64, v); return; } case REG_DISPA_DISPCAPCNT + 2: { u32 v = (T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x64) & 0xFFFF) | ((u32)val << 16); mainEngine->SetDISPCAPCNT(v); T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x64, v); return; } case REG_DISPB_DISPCNT : { u32 v = (T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x1000) & 0xFFFF0000) | val; subEngine->SetVideoProp(v); T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x1000, v); return; } case REG_DISPB_DISPCNT+2 : { //emu_halt(); u32 v = (T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x1000) & 0xFFFF) | ((u32) val << 16); subEngine->SetVideoProp(v); T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x1000, v); return; } case REG_DISPA_DISPMMEMFIFO: { DISP_FIFOsend(val); return; } case REG_GCROMCTRL : MMU_writeToGCControl( (T1ReadLong(MMU.MMU_MEM[0][0x40], 0x1A4) & 0xFFFF0000) | val); return; case REG_GCROMCTRL+2 : MMU_writeToGCControl( (T1ReadLong(MMU.MMU_MEM[0][0x40], 0x1A4) & 0xFFFF) | ((u32) val << 16)); return; } T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM9][adr>>20], adr&MMU.MMU_MASK[ARMCPU_ARM9][adr>>20], val); return; } bool unmapped, restricted; adr = MMU_LCDmap(adr, unmapped, restricted); if(unmapped) return; #ifdef HAVE_JIT if (JIT_MAPPED(adr, ARMCPU_ARM9)) JIT_COMPILED_FUNC_PREMASKED(adr, ARMCPU_ARM9, 0) = 0; #endif // Removed the &0xFF as they are implicit with the adr&0x0FFFFFFF [shash] T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM9][adr>>20], adr&MMU.MMU_MASK[ARMCPU_ARM9][adr>>20], val); } //================================================= MMU ARM9 write 32 void FASTCALL _MMU_ARM9_write32(u32 adr, u32 val) { adr &= 0x0FFFFFFC; mmu_log_debug_ARM9(adr, "(write32) 0x%08X", val); if(adr<0x02000000) { #ifdef HAVE_JIT JIT_COMPILED_FUNC_KNOWNBANK(adr, ARM9_ITCM, 0x7FFF, 0) = 0; JIT_COMPILED_FUNC_KNOWNBANK(adr, ARM9_ITCM, 0x7FFF, 1) = 0; #endif T1WriteLong(MMU.ARM9_ITCM, adr & 0x7FFF, val); return ; } if (slot2_write(adr, val)) return; #if 0 if ((adr & 0xFF800000) == 0x04800000) { // access to non regular hw registers // return to not overwrite valid data return ; } #endif // Address is an IO register if ((adr >> 24) == 4) { if (!validateIORegsWrite(adr, 32, val)) return; /* TODO: add pal reg */ if (nds.power1.gpuMain == 0) if ((adr >= 0x04000008) && (adr <= 0x0400005F)) return; if (nds.power1.gpuSub == 0) if ((adr >= 0x04001008) && (adr <= 0x0400105F)) return; if (nds.power1.gfx3d_geometry == 0) if ((adr >= 0x04000400) && (adr <= 0x040006FF)) return; if (nds.power1.gfx3d_render == 0) if ((adr >= 0x04000320) && (adr <= 0x040003FF)) return; // MightyMax: no need to do several ifs, when only one can happen // switch/case instead // both comparison >=,< per if can be replaced by one bit comparison since // they are 2^4 aligned and 2^4n wide // this looks ugly but should reduce load on register writes, they are done as // lookups by the compiler switch (adr >> 4) { case 0x400033: //edge color table ((u32 *)(MMU.MMU_MEM[ARMCPU_ARM9][0x40]))[(adr & 0xFFF) >> 2] = val; return; case 0x400038: case 0x400039: case 0x40003A: case 0x40003B: //toon table ((u32 *)(MMU.MMU_MEM[ARMCPU_ARM9][0x40]))[(adr & 0xFFF) >> 2] = val; gfx3d_UpdateToonTable((adr & 0x3F) >> 1, val); return; case 0x400040: case 0x400041: case 0x400042: case 0x400043: // FIFO Commands ((u32 *)(MMU.MMU_MEM[ARMCPU_ARM9][0x40]))[(adr & 0xFFF) >> 2] = val; gfx3d_sendCommandToFIFO(val); return; case 0x400044: case 0x400045: case 0x400046: case 0x400047: case 0x400048: case 0x400049: case 0x40004A: case 0x40004B: case 0x40004C: case 0x40004D: case 0x40004E: case 0x40004F: case 0x400050: case 0x400051: case 0x400052: case 0x400053: case 0x400054: case 0x400055: case 0x400056: case 0x400057: case 0x400058: case 0x400059: case 0x40005A: case 0x40005B: case 0x40005C: // Individual Commands if (gxFIFO.size > 254) nds.freezeBus |= 1; ((u32 *)(MMU.MMU_MEM[ARMCPU_ARM9][0x40]))[(adr & 0xFFF) >> 2] = val; gfx3d_sendCommand(adr, val); return; default: break; } if(MMU_new.is_dma(adr)) { MMU_new.write_dma(ARMCPU_ARM9,32,adr,val); return; } GPUEngineA *mainEngine = GPU->GetEngineMain(); GPUEngineB *subEngine = GPU->GetEngineSub(); switch(adr) { case REG_SQRTCNT: MMU_new.sqrt.write16((u16)val); return; case REG_DIVCNT: MMU_new.div.write16((u16)val); return; case REG_POWCNT1: writereg_POWCNT1(32,adr,val); break; //fog table: only write bottom 7 bits case eng_3D_FOG_TABLE+0x00: case eng_3D_FOG_TABLE+0x04: case eng_3D_FOG_TABLE+0x08: case eng_3D_FOG_TABLE+0x0C: case eng_3D_FOG_TABLE+0x10: case eng_3D_FOG_TABLE+0x14: case eng_3D_FOG_TABLE+0x18: case eng_3D_FOG_TABLE+0x1C: val &= 0x7F7F7F7F; break; //ensata handshaking port? case 0x04FFF010: if(nds.ensataEmulation && nds.ensataHandshake == ENSATA_HANDSHAKE_ack && val == 0x13579bdf) nds.ensataHandshake = ENSATA_HANDSHAKE_confirm; if(nds.ensataEmulation && nds.ensataHandshake == ENSATA_HANDSHAKE_confirm && val == 0xfdb97531) { printf("ENSATA HANDSHAKE COMPLETE\n"); nds.ensataHandshake = ENSATA_HANDSHAKE_complete; } break; //todo - these are usually write only regs (these and 1000 more) //shouldnt we block them from getting written? ugh case eng_3D_CLIPMTX_RESULT: if(nds.ensataEmulation && nds.ensataHandshake == ENSATA_HANDSHAKE_none && val==0x2468ace0) { printf("ENSATA HANDSHAKE BEGIN\n"); nds.ensataHandshake = ENSATA_HANDSHAKE_query; } break; case eng_3D_GXSTAT: MMU_new.gxstat.write32(val); break; case REG_DISPA_BG2XL: mainEngine->setAffineStart(2,0,val); return; case REG_DISPA_BG2YL: mainEngine->setAffineStart(2,1,val); return; case REG_DISPB_BG2XL: subEngine->setAffineStart(2,0,val); return; case REG_DISPB_BG2YL: subEngine->setAffineStart(2,1,val); return; case REG_DISPA_BG3XL: mainEngine->setAffineStart(3,0,val); return; case REG_DISPA_BG3YL: mainEngine->setAffineStart(3,1,val); return; case REG_DISPB_BG3XL: subEngine->setAffineStart(3,0,val); return; case REG_DISPB_BG3YL: subEngine->setAffineStart(3,1,val); return; // Alpha test reference value - Parameters:1 case eng_3D_ALPHA_TEST_REF: { ((u32 *)(MMU.MMU_MEM[ARMCPU_ARM9][0x40]))[0x340>>2] = val; gfx3d_glAlphaFunc(val); return; } case eng_3D_CLEAR_COLOR: T1WriteLong((u8*)&gfx3d.state.clearColor,0,val); break; // Clear background depth setup - Parameters:2 case eng_3D_CLEAR_DEPTH: { ((u32 *)(MMU.MMU_MEM[ARMCPU_ARM9][0x40]))[0x354>>2] = val; gfx3d_glClearDepth(val); return; } // Fog Color - Parameters:4b case 0x04000358: { ((u32 *)(MMU.MMU_MEM[ARMCPU_ARM9][0x40]))[0x358>>2] = val; gfx3d_glFogColor(val); return; } case 0x0400035C: { ((u32 *)(MMU.MMU_MEM[ARMCPU_ARM9][0x40]))[0x35C>>2] = val; gfx3d_glFogOffset(val); return; } //case REG_DISPA_BG0HOFS: // GPU_setBGxHOFS(0, MainScreen.gpu, val&0xFFFF); // GPU_setBGxVOFS(0, MainScreen.gpu, (val>>16)); // break; case REG_DISPA_WININ: { mainEngine->SetWININ(val & 0xFFFF) ; mainEngine->SetWINOUT16((val >> 16) & 0xFFFF) ; break; } case REG_DISPB_WININ: { subEngine->SetWININ(val & 0xFFFF) ; subEngine->SetWINOUT16((val >> 16) & 0xFFFF) ; break; } case REG_DISPA_WIN0H: { mainEngine->SetWIN0_H(val & 0xFFFF); mainEngine->SetWIN1_H(val >> 16); break; } case REG_DISPA_WIN0V: { mainEngine->SetWIN0_V(val & 0xFFFF); mainEngine->SetWIN1_V(val >> 16); break; } case REG_DISPB_WIN0H: { subEngine->SetWIN0_H(val & 0xFFFF); subEngine->SetWIN1_H(val >> 16); break; } case REG_DISPB_WIN0V: { subEngine->SetWIN0_V(val & 0xFFFF); subEngine->SetWIN1_V(val >> 16); break; } case REG_DISPA_MASTERBRIGHT: mainEngine->SetMasterBrightness(val & 0xFFFF); break; case REG_DISPB_MASTERBRIGHT: subEngine->SetMasterBrightness(val & 0xFFFF); break; case REG_DISPA_BLDCNT: { mainEngine->SetBLDCNT(val & 0xFFFF); mainEngine->SetBLDALPHA(val >> 16); break; } case REG_DISPB_BLDCNT: { subEngine->SetBLDCNT(val & 0xFFFF); subEngine->SetBLDALPHA(val >> 16); break; } case REG_DISPA_BLDY: mainEngine->SetBLDY_EVY(val & 0xFFFF); break ; case REG_DISPB_BLDY: subEngine->SetBLDY_EVY(val & 0xFFFF); break; case REG_DISPA_DISPCNT : mainEngine->SetVideoProp(val); //GPULOG("MAIN INIT 32B %08X\r\n", val); T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0, val); return; case REG_DISPB_DISPCNT : subEngine->SetVideoProp(val); //GPULOG("SUB INIT 32B %08X\r\n", val); T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x1000, val); return; case REG_VRAMCNTA: case REG_VRAMCNTE: MMU_VRAMmapControl(adr-REG_VRAMCNTA, val & 0xFF); MMU_VRAMmapControl(adr-REG_VRAMCNTA+1, (val >> 8) & 0xFF); MMU_VRAMmapControl(adr-REG_VRAMCNTA+2, (val >> 16) & 0xFF); MMU_VRAMmapControl(adr-REG_VRAMCNTA+3, (val >> 24) & 0xFF); break; case REG_VRAMCNTH: MMU_VRAMmapControl(adr-REG_VRAMCNTA, val & 0xFF); MMU_VRAMmapControl(adr-REG_VRAMCNTA+1, (val >> 8) & 0xFF); break; case REG_IME : NDS_Reschedule(); MMU.reg_IME[ARMCPU_ARM9] = val & 0x01; T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x208, val); return; case REG_IE : NDS_Reschedule(); MMU.reg_IE[ARMCPU_ARM9] = val; return; case REG_IF: REG_IF_WriteLong(val); return; case REG_TM0CNTL: case REG_TM1CNTL: case REG_TM2CNTL: case REG_TM3CNTL: { int timerIndex = (adr>>2)&0x3; MMU.timerReload[ARMCPU_ARM9][timerIndex] = (u16)val; T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM9][0x40], adr & 0xFFF, val); write_timer(ARMCPU_ARM9, timerIndex, val>>16); return; } case REG_DIVNUMER: T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x290, val); execdiv(); return; case REG_DIVNUMER+4: T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x294, val); execdiv(); return; case REG_DIVDENOM : { T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x298, val); execdiv(); return; } case REG_DIVDENOM+4 : { T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x29C, val); execdiv(); return; } case REG_SQRTPARAM : { T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x2B8, val); execsqrt(); return; } case REG_SQRTPARAM+4 : T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x2BC, val); execsqrt(); return; case REG_IPCSYNC: MMU_IPCSync(ARMCPU_ARM9, val); return; case REG_IPCFIFOCNT: IPC_FIFOcnt(ARMCPU_ARM9, val); return; case REG_IPCFIFOSEND: IPC_FIFOsend(ARMCPU_ARM9, val); return; case REG_GCROMCTRL : MMU_writeToGCControl(val); return; case REG_DISPA_DISPCAPCNT : //INFO("MMU write32: REG_DISPA_DISPCAPCNT 0x%X\n", val); mainEngine->SetDISPCAPCNT(val); T1WriteLong(MMU.ARM9_REG, 0x64, val); return; case REG_DISPA_BG0CNT : mainEngine->SetBGProp(0, (val & 0xFFFF)); mainEngine->SetBGProp(1, (val >> 16)); //if((val>>16)==0x400) emu_halt(); T1WriteLong(MMU.ARM9_REG, 8, val); return; case REG_DISPA_BG2CNT : mainEngine->SetBGProp(2, (val & 0xFFFF)); mainEngine->SetBGProp(3, (val >> 16)); T1WriteLong(MMU.ARM9_REG, 0xC, val); return; case REG_DISPB_BG0CNT : subEngine->SetBGProp(0, (val & 0xFFFF)); subEngine->SetBGProp(1, (val >> 16)); T1WriteLong(MMU.ARM9_REG, 0x1008, val); return; case REG_DISPB_BG2CNT : subEngine->SetBGProp(2, (val & 0xFFFF)); subEngine->SetBGProp(3, (val >> 16)); T1WriteLong(MMU.ARM9_REG, 0x100C, val); return; case REG_DISPA_DISPMMEMFIFO: { DISP_FIFOsend(val); return; } case REG_DISPA_DISP3DCNT: writereg_DISP3DCNT(32,adr,val); return; case REG_GCDATAIN: MMU_writeToGC(val); return; } T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][adr>>20], adr & MMU.MMU_MASK[ARMCPU_ARM9][adr>>20], val); return; } bool unmapped, restricted; adr = MMU_LCDmap(adr, unmapped, restricted); if(unmapped) return; #ifdef HAVE_JIT if (JIT_MAPPED(adr, ARMCPU_ARM9)) { JIT_COMPILED_FUNC_PREMASKED(adr, ARMCPU_ARM9, 0) = 0; JIT_COMPILED_FUNC_PREMASKED(adr, ARMCPU_ARM9, 1) = 0; } #endif // Removed the &0xFF as they are implicit with the adr&0x0FFFFFFF [shash] T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][adr>>20], adr&MMU.MMU_MASK[ARMCPU_ARM9][adr>>20], val); } //================================================= MMU ARM9 read 08 u8 FASTCALL _MMU_ARM9_read08(u32 adr) { adr &= 0x0FFFFFFF; #ifdef _MMU_DEBUG mmu_log_debug_ARM9(adr, "(read08) 0x%02X", MMU.MMU_MEM[ARMCPU_ARM9][(adr>>20)&0xFF][adr&MMU.MMU_MASK[ARMCPU_ARM9][(adr>>20)&0xFF]]); #endif if(adr<0x02000000) return T1ReadByte(MMU.ARM9_ITCM, adr&0x7FFF); u8 slot2_val; if (slot2_read(adr, slot2_val)) return slot2_val; // Address is an IO register if ((adr >> 24) == 4) { VALIDATE_IO_REGS_READ(ARMCPU_ARM9, 8); if(MMU_new.is_dma(adr)) return MMU_new.read_dma(ARMCPU_ARM9,8,adr); switch(adr) { case REG_IF: return MMU.gen_IF(); case REG_IF+1: return (MMU.gen_IF()>>8); case REG_IF+2: return (MMU.gen_IF()>>16); case REG_IF+3: return (MMU.gen_IF()>>24); case REG_WRAMCNT: return MMU.WRAMCNT; case REG_DISPA_DISPSTAT: break; case REG_DISPA_DISPSTAT+1: break; case REG_DISPx_VCOUNT: return nds.VCount & 0xFF; case REG_DISPx_VCOUNT+1: return (nds.VCount>>8) & 0xFF; case REG_SQRTCNT: return (MMU_new.sqrt.read16() & 0xFF); case REG_SQRTCNT+1: return ((MMU_new.sqrt.read16()>>8) & 0xFF); //sqrtcnt isnt big enough for these to exist. but they'd probably return 0 so its ok case REG_SQRTCNT+2: printf("ERROR 8bit SQRTCNT+2 READ\n"); return 0; case REG_SQRTCNT+3: printf("ERROR 8bit SQRTCNT+3 READ\n"); return 0; //these aren't readable case REG_DISPA_BG0HOFS: case REG_DISPA_BG0HOFS+1: case REG_DISPA_BG1HOFS: case REG_DISPA_BG1HOFS+1: case REG_DISPA_BG2HOFS: case REG_DISPA_BG2HOFS+1: case REG_DISPA_BG3HOFS: case REG_DISPA_BG3HOFS+1: case REG_DISPB_BG0HOFS: case REG_DISPB_BG0HOFS+1: case REG_DISPB_BG1HOFS: case REG_DISPB_BG1HOFS+1: case REG_DISPB_BG2HOFS: case REG_DISPB_BG2HOFS+1: case REG_DISPB_BG3HOFS: case REG_DISPB_BG3HOFS+1: case REG_DISPA_BG0VOFS: case REG_DISPA_BG0VOFS+1: case REG_DISPA_BG1VOFS: case REG_DISPA_BG1VOFS+1: case REG_DISPA_BG2VOFS: case REG_DISPA_BG2VOFS+1: case REG_DISPA_BG3VOFS: case REG_DISPA_BG3VOFS+1: case REG_DISPB_BG0VOFS: case REG_DISPB_BG0VOFS+1: case REG_DISPB_BG1VOFS: case REG_DISPB_BG1VOFS+1: case REG_DISPB_BG2VOFS: case REG_DISPB_BG2VOFS+1: case REG_DISPB_BG3VOFS: case REG_DISPB_BG3VOFS+1: return 0; //Nostalgia's options menu requires that these work case REG_DIVCNT: return (MMU_new.div.read16() & 0xFF); case REG_DIVCNT+1: return ((MMU_new.div.read16()>>8) & 0xFF); //divcnt isnt big enough for these to exist. but they'd probably return 0 so its ok case REG_DIVCNT+2: printf("ERROR 8bit DIVCNT+2 READ\n"); return 0; case REG_DIVCNT+3: printf("ERROR 8bit DIVCNT+3 READ\n"); return 0; //fog table: write only case eng_3D_FOG_TABLE+0x00: case eng_3D_FOG_TABLE+0x01: case eng_3D_FOG_TABLE+0x02: case eng_3D_FOG_TABLE+0x03: case eng_3D_FOG_TABLE+0x04: case eng_3D_FOG_TABLE+0x05: case eng_3D_FOG_TABLE+0x06: case eng_3D_FOG_TABLE+0x07: case eng_3D_FOG_TABLE+0x08: case eng_3D_FOG_TABLE+0x09: case eng_3D_FOG_TABLE+0x0A: case eng_3D_FOG_TABLE+0x0B: case eng_3D_FOG_TABLE+0x0C: case eng_3D_FOG_TABLE+0x0D: case eng_3D_FOG_TABLE+0x0E: case eng_3D_FOG_TABLE+0x0F: case eng_3D_FOG_TABLE+0x10: case eng_3D_FOG_TABLE+0x11: case eng_3D_FOG_TABLE+0x12: case eng_3D_FOG_TABLE+0x13: case eng_3D_FOG_TABLE+0x14: case eng_3D_FOG_TABLE+0x15: case eng_3D_FOG_TABLE+0x16: case eng_3D_FOG_TABLE+0x17: case eng_3D_FOG_TABLE+0x18: case eng_3D_FOG_TABLE+0x19: case eng_3D_FOG_TABLE+0x1A: case eng_3D_FOG_TABLE+0x1B: case eng_3D_FOG_TABLE+0x1C: case eng_3D_FOG_TABLE+0x1D: case eng_3D_FOG_TABLE+0x1E: case eng_3D_FOG_TABLE+0x1F: return 0; case REG_POWCNT1: case REG_POWCNT1+1: case REG_POWCNT1+2: case REG_POWCNT1+3: return readreg_POWCNT1(8,adr); case eng_3D_GXSTAT: return MMU_new.gxstat.read(8,adr); case REG_DISPA_DISP3DCNT: return readreg_DISP3DCNT(8,adr); case REG_DISPA_DISP3DCNT+1: return readreg_DISP3DCNT(8,adr); case REG_DISPA_DISP3DCNT+2: return readreg_DISP3DCNT(8,adr); case REG_DISPA_DISP3DCNT+3: return readreg_DISP3DCNT(8,adr); case REG_KEYINPUT: break; } } bool unmapped, restricted; adr = MMU_LCDmap(adr, unmapped, restricted); if(unmapped) return 0; return MMU.MMU_MEM[ARMCPU_ARM9][(adr>>20)&0xFF][adr&MMU.MMU_MASK[ARMCPU_ARM9][(adr>>20)&0xFF]]; } //================================================= MMU ARM9 read 16 u16 FASTCALL _MMU_ARM9_read16(u32 adr) { adr &= 0x0FFFFFFE; #ifdef _MMU_DEBUG mmu_log_debug_ARM9(adr, "(read16) 0x%04X", T1ReadWord_guaranteedAligned(MMU.MMU_MEM[ARMCPU_ARM9][adr >> 20], adr & MMU.MMU_MASK[ARMCPU_ARM9][adr >> 20])); #endif if(adr<0x02000000) return T1ReadWord_guaranteedAligned(MMU.ARM9_ITCM, adr & 0x7FFE); u16 slot2_val; if (slot2_read(adr, slot2_val)) return slot2_val; // Address is an IO register if ((adr >> 24) == 4) { VALIDATE_IO_REGS_READ(ARMCPU_ARM9, 16); if(MMU_new.is_dma(adr)) return MMU_new.read_dma(ARMCPU_ARM9,16,adr); switch(adr) { case REG_DISPA_DISPSTAT: break; //these aren't readable case REG_DISPA_BG0HOFS: case REG_DISPA_BG1HOFS: case REG_DISPA_BG2HOFS: case REG_DISPA_BG3HOFS: case REG_DISPB_BG0HOFS: case REG_DISPB_BG1HOFS: case REG_DISPB_BG2HOFS: case REG_DISPB_BG3HOFS: case REG_DISPA_BG0VOFS: case REG_DISPA_BG1VOFS: case REG_DISPA_BG2VOFS: case REG_DISPA_BG3VOFS: case REG_DISPB_BG0VOFS: case REG_DISPB_BG1VOFS: case REG_DISPB_BG2VOFS: case REG_DISPB_BG3VOFS: return 0; case REG_SQRTCNT: return MMU_new.sqrt.read16(); //sqrtcnt isnt big enough for this to exist. but it'd probably return 0 so its ok case REG_SQRTCNT+2: printf("ERROR 16bit SQRTCNT+2 READ\n"); return 0; case REG_DIVCNT: return MMU_new.div.read16(); //divcnt isnt big enough for this to exist. but it'd probably return 0 so its ok case REG_DIVCNT+2: printf("ERROR 16bit DIVCNT+2 READ\n"); return 0; case eng_3D_GXSTAT: return MMU_new.gxstat.read(16,adr); case REG_DISPA_VCOUNT: if(nds.ensataEmulation && nds.ensataHandshake == ENSATA_HANDSHAKE_query) { nds.ensataHandshake = ENSATA_HANDSHAKE_ack; return 270; } return nds.VCount; // ============================================= 3D case eng_3D_RAM_COUNT: return 0; //almost worthless for now //return (gfx3d_GetNumPolys()); case eng_3D_RAM_COUNT+2: return 0; //almost worthless for now //return (gfx3d_GetNumVertex()); // ============================================= 3D end case REG_IME : return (u16)MMU.reg_IME[ARMCPU_ARM9]; case REG_IE : return (u16)MMU.reg_IE[ARMCPU_ARM9]; case REG_IE + 2 : return (u16)(MMU.reg_IE[ARMCPU_ARM9]>>16); case REG_IF: return MMU.gen_IF(); case REG_IF+2: return MMU.gen_IF()>>16; case REG_TM0CNTL : case REG_TM1CNTL : case REG_TM2CNTL : case REG_TM3CNTL : return read_timer(ARMCPU_ARM9,(adr&0xF)>>2); case REG_AUXSPICNT: return MMU.AUX_SPI_CNT; case REG_POWCNT1: case REG_POWCNT1+2: return readreg_POWCNT1(16,adr); case REG_DISPA_DISP3DCNT: return readreg_DISP3DCNT(16,adr); case REG_DISPA_DISP3DCNT+2: return readreg_DISP3DCNT(16,adr); case REG_KEYINPUT: break; //fog table: write only case eng_3D_FOG_TABLE+0x00: case eng_3D_FOG_TABLE+0x02: case eng_3D_FOG_TABLE+0x04: case eng_3D_FOG_TABLE+0x06: case eng_3D_FOG_TABLE+0x08: case eng_3D_FOG_TABLE+0x0A: case eng_3D_FOG_TABLE+0x0C: case eng_3D_FOG_TABLE+0x0E: case eng_3D_FOG_TABLE+0x10: case eng_3D_FOG_TABLE+0x12: case eng_3D_FOG_TABLE+0x14: case eng_3D_FOG_TABLE+0x16: case eng_3D_FOG_TABLE+0x18: case eng_3D_FOG_TABLE+0x1A: case eng_3D_FOG_TABLE+0x1C: case eng_3D_FOG_TABLE+0x1E: return 0; } return T1ReadWord_guaranteedAligned(MMU.MMU_MEM[ARMCPU_ARM9][adr>>20], adr & MMU.MMU_MASK[ARMCPU_ARM9][adr>>20]); } bool unmapped, restricted; adr = MMU_LCDmap(adr,unmapped, restricted); if(unmapped) return 0; // Removed the &0xFF as they are implicit with the adr&0x0FFFFFFF return T1ReadWord_guaranteedAligned(MMU.MMU_MEM[ARMCPU_ARM9][adr >> 20], adr & MMU.MMU_MASK[ARMCPU_ARM9][adr >> 20]); } //================================================= MMU ARM9 read 32 u32 FASTCALL _MMU_ARM9_read32(u32 adr) { adr &= 0x0FFFFFFC; #ifdef _MMU_DEBUG mmu_log_debug_ARM9(adr, "(read32) 0x%08X", T1ReadLong_guaranteedAligned(MMU.MMU_MEM[ARMCPU_ARM9][adr >> 20], adr & MMU.MMU_MASK[ARMCPU_ARM9][adr>>20])); #endif if(adr<0x02000000) return T1ReadLong_guaranteedAligned(MMU.ARM9_ITCM, adr&0x7FFC); u32 slot2_val; if (slot2_read(adr, slot2_val)) return slot2_val; // Address is an IO register if ((adr >> 24) == 4) { VALIDATE_IO_REGS_READ(ARMCPU_ARM9, 32); if(MMU_new.is_dma(adr)) return MMU_new.read_dma(ARMCPU_ARM9,32,adr); switch(adr) { case REG_DSIMODE: if(!nds.Is_DSI()) break; return 1; case 0x04004008: if(!nds.Is_DSI()) break; return 0x8000; //these aren't readable. //note: ratatouille stage 3 begins testing this.. it will write a 256, then read it, and if it reads back a 256, the 3d display will be scrolled invisibly. it needs to read a 0 to cause an unscrolled 3d display. case REG_DISPA_BG0HOFS: case REG_DISPA_BG1HOFS: case REG_DISPA_BG2HOFS: case REG_DISPA_BG3HOFS: case REG_DISPB_BG0HOFS: case REG_DISPB_BG1HOFS: case REG_DISPB_BG2HOFS: case REG_DISPB_BG3HOFS: return 0; case REG_DISPA_DISPSTAT: break; case REG_DISPx_VCOUNT: return nds.VCount; //despite these being 16bit regs, //Dolphin Island Underwater Adventures uses this amidst seemingly reasonable divs so we're going to emulate it. //well, it's pretty reasonable to read them as 32bits though, isnt it? case REG_DIVCNT: return MMU_new.div.read16(); case REG_SQRTCNT: return MMU_new.sqrt.read16(); //I guess we'll do this also //fog table: write only case eng_3D_FOG_TABLE+0x00: case eng_3D_FOG_TABLE+0x04: case eng_3D_FOG_TABLE+0x08: case eng_3D_FOG_TABLE+0x0C: case eng_3D_FOG_TABLE+0x10: case eng_3D_FOG_TABLE+0x14: case eng_3D_FOG_TABLE+0x18: case eng_3D_FOG_TABLE+0x1C: return 0; case eng_3D_CLIPMTX_RESULT: case eng_3D_CLIPMTX_RESULT+4: case eng_3D_CLIPMTX_RESULT+8: case eng_3D_CLIPMTX_RESULT+12: case eng_3D_CLIPMTX_RESULT+16: case eng_3D_CLIPMTX_RESULT+20: case eng_3D_CLIPMTX_RESULT+24: case eng_3D_CLIPMTX_RESULT+28: case eng_3D_CLIPMTX_RESULT+32: case eng_3D_CLIPMTX_RESULT+36: case eng_3D_CLIPMTX_RESULT+40: case eng_3D_CLIPMTX_RESULT+44: case eng_3D_CLIPMTX_RESULT+48: case eng_3D_CLIPMTX_RESULT+52: case eng_3D_CLIPMTX_RESULT+56: case eng_3D_CLIPMTX_RESULT+60: { //LOG("4000640h..67Fh - CLIPMTX_RESULT - Read Current Clip Coordinates Matrix (R)"); return gfx3d_GetClipMatrix((adr-0x04000640)/4); } case eng_3D_VECMTX_RESULT: case eng_3D_VECMTX_RESULT+4: case eng_3D_VECMTX_RESULT+8: case eng_3D_VECMTX_RESULT+12: case eng_3D_VECMTX_RESULT+16: case eng_3D_VECMTX_RESULT+20: case eng_3D_VECMTX_RESULT+24: case eng_3D_VECMTX_RESULT+28: case eng_3D_VECMTX_RESULT+32: { //LOG("4000680h..6A3h - VECMTX_RESULT - Read Current Directional Vector Matrix (R)"); return gfx3d_GetDirectionalMatrix((adr-0x04000680)/4); } case eng_3D_RAM_COUNT: { return (gfx3d_GetNumPolys()) | ((gfx3d_GetNumVertex()) << 16); //LOG ("read32 - RAM_COUNT -> 0x%X", ((u32 *)(MMU.MMU_MEM[ARMCPU_ARM9][(adr>>20)&0xFF]))[(adr&MMU.MMU_MASK[ARMCPU_ARM9][(adr>>20)&0xFF])>>2]); } case eng_3D_POS_RESULT: case eng_3D_POS_RESULT+4: case eng_3D_POS_RESULT+8: case eng_3D_POS_RESULT+12: { return gfx3d_glGetPosRes((adr & 0xF) >> 2); } case eng_3D_GXSTAT: return MMU_new.gxstat.read(32,adr); // ======================================== 3D end case REG_IME : return MMU.reg_IME[ARMCPU_ARM9]; case REG_IE : return MMU.reg_IE[ARMCPU_ARM9]; case REG_IF: return MMU.gen_IF(); case REG_IPCFIFORECV : return IPC_FIFOrecv(ARMCPU_ARM9); case REG_TM0CNTL : case REG_TM1CNTL : case REG_TM2CNTL : case REG_TM3CNTL : { u32 val = T1ReadWord(MMU.MMU_MEM[ARMCPU_ARM9][0x40], (adr + 2) & 0xFFF); return MMU.timer[ARMCPU_ARM9][(adr&0xF)>>2] | (val<<16); } case REG_GCDATAIN: return MMU_readFromGC(); case REG_POWCNT1: return readreg_POWCNT1(32,adr); case REG_DISPA_DISP3DCNT: return readreg_DISP3DCNT(32,adr); case REG_KEYINPUT: break; } return T1ReadLong_guaranteedAligned(MMU.MMU_MEM[ARMCPU_ARM9][adr>>20], adr & MMU.MMU_MASK[ARMCPU_ARM9][adr>>20]); } bool unmapped, restricted; adr = MMU_LCDmap(adr,unmapped, restricted); if(unmapped) return 0; // Removed the &0xFF as they are implicit with the adr&0x0FFFFFFF [zeromus, inspired by shash] return T1ReadLong_guaranteedAligned(MMU.MMU_MEM[ARMCPU_ARM9][adr >> 20], adr & MMU.MMU_MASK[ARMCPU_ARM9][adr>>20]); } //================================================================================================== ARM7 * //========================================================================================================= //========================================================================================================= //================================================= MMU ARM7 write 08 void FASTCALL _MMU_ARM7_write08(u32 adr, u8 val) { adr &= 0x0FFFFFFF; #ifdef _MMU_DEBUG mmu_log_debug_ARM7(adr, "(write08) 0x%02X", val); #endif if (adr < 0x02000000) return; //can't write to bios or entire area below main memory if (slot2_write(adr, val)) return; if (SPU_core->isSPU(adr)) { SPU_WriteByte(adr, val); return; } if ((adr & 0xFFFF0000) == 0x04800000) { /* is wifi hardware, dont intermix with regular hardware registers */ // 8-bit writes to wifi I/O and RAM are ignored // Reference: http://nocash.emubase.de/gbatek.htm#dswifiiomap return; } // Address is an IO register if ((adr >> 24) == 4) { if (!validateIORegsWrite(adr, 8, val)) return; if(MMU_new.is_dma(adr)) { MMU_new.write_dma(ARMCPU_ARM7,8,adr,val); return; } switch(adr) { case REG_IF: REG_IF_WriteByte(0,val); break; case REG_IF+1: REG_IF_WriteByte(1,val); break; case REG_IF+2: REG_IF_WriteByte(2,val); break; case REG_IF+3: REG_IF_WriteByte(3,val); break; case REG_POSTFLG: //printf("ARM7: write POSTFLG %02X PC:0x%08X\n", val, NDS_ARM7.instruct_adr); //The NDS7 register can be written to only from code executed in BIOS. if (NDS_ARM7.instruct_adr > 0x3FFF) return; #ifdef HAVE_JIT // hack for firmware boot in JIT mode if (CommonSettings.UseExtFirmware && CommonSettings.BootFromFirmware && firmware->loaded() && val == 1) CommonSettings.jit_max_block_size = saveBlockSizeJIT; #endif break; case REG_HALTCNT: { //printf("ARM7: Halt 0x%02X IME %02X, IE 0x%08X, IF 0x%08X PC 0x%08X\n", val, MMU.reg_IME[1], MMU.reg_IE[1], MMU.reg_IF_bits[1], NDS_ARM7.instruct_adr); switch(val) { //case 0x10: printf("GBA mode unsupported\n"); break; case 0xC0: NDS_Sleep(); break; case 0x80: armcpu_Wait4IRQ(&NDS_ARM7); break; default: break; } break; } case REG_RTC: rtcWrite(val); return; case REG_AUXSPICNT: case REG_AUXSPICNT+1: write_auxspicnt(ARMCPU_ARM7, 8, adr & 1, val); return; case REG_AUXSPIDATA: { //if(val!=0) MMU.AUX_SPI_CMD = val & 0xFF; //zero 20-aug-2013 - this seems pointless u8 spidata = slot1_device->auxspi_transaction(ARMCPU_ARM7,(u8)val); T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM7][(REG_AUXSPIDATA >> 20) & 0xff], REG_AUXSPIDATA & 0xfff, spidata); MMU.AUX_SPI_CNT &= ~0x80; //remove busy flag return; } case REG_SPIDATA: // CrazyMax: 27 May 2013: BIOS write 8bit commands to flash controller when load firmware header // into RAM at 0x027FF830 MMU_writeToSPIData(val); return; } MMU.MMU_MEM[ARMCPU_ARM7][adr>>20][adr&MMU.MMU_MASK[ARMCPU_ARM7][adr>>20]]=val; return; } bool unmapped, restricted; adr = MMU_LCDmap(adr,unmapped, restricted); if(unmapped) return; #ifdef HAVE_JIT if (JIT_MAPPED(adr, ARMCPU_ARM7)) JIT_COMPILED_FUNC_PREMASKED(adr, ARMCPU_ARM7, 0) = 0; #endif // Removed the &0xFF as they are implicit with the adr&0x0FFFFFFF [shash] MMU.MMU_MEM[ARMCPU_ARM7][adr>>20][adr&MMU.MMU_MASK[ARMCPU_ARM7][adr>>20]]=val; } //================================================= MMU ARM7 write 16 void FASTCALL _MMU_ARM7_write16(u32 adr, u16 val) { adr &= 0x0FFFFFFE; #ifdef _MMU_DEBUG mmu_log_debug_ARM7(adr, "(write16) 0x%04X", val); #endif if (adr < 0x02000000) return; //can't write to bios or entire area below main memory if (slot2_write(adr, val)) return; if (SPU_core->isSPU(adr)) { SPU_WriteWord(adr, val); return; } //wifi mac access if ((adr & 0xFFFF0000) == 0x04800000) { WIFI_write16(adr,val); T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM7][0x48], adr&MMU.MMU_MASK[ARMCPU_ARM7][0x48], val); return; } // Address is an IO register if ((adr >> 24) == 4) { if (!validateIORegsWrite(adr, 16, val)) return; if(MMU_new.is_dma(adr)) { MMU_new.write_dma(ARMCPU_ARM7,16,adr,val); return; } //Address is an IO register switch(adr) { case REG_DISPA_VCOUNT: if (nds.VCount >= 202 && nds.VCount <= 212) { printf("VCOUNT set to %i (previous value %i)\n", val, nds.VCount); nds.VCount = val; } else printf("Attempt to set VCOUNT while not within 202-212 (%i), ignored\n", nds.VCount); return; case REG_RTC: rtcWrite(val); break; case REG_EXMEMCNT: { u16 remote_proc = T1ReadWord(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x204); T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM7][0x40], 0x204, (val & 0x7F) | (remote_proc & 0xFF80)); } return; case REG_EXTKEYIN: //readonly return; case REG_POWCNT2: nds.power2.speakers = BIT0(val); nds.power2.wifi = BIT1(val); return; case REG_AUXSPICNT: write_auxspicnt(ARMCPU_ARM7, 16, 0, val); return; case REG_AUXSPIDATA: { //if(val!=0) MMU.AUX_SPI_CMD = val & 0xFF; //zero 20-aug-2013 - this seems pointless u8 spidata = slot1_device->auxspi_transaction(ARMCPU_ARM7,(u8)val); T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM7][(REG_AUXSPIDATA >> 20) & 0xff], REG_AUXSPIDATA & 0xfff, spidata); MMU.AUX_SPI_CNT &= ~0x80; //remove busy flag return; } case REG_SPICNT : { int reset_firmware = 1; if ( ((MMU.SPI_CNT >> 8) & 0x3) == 1) { if ( ((val >> 8) & 0x3) == 1) { if ( BIT11(MMU.SPI_CNT)) { // select held reset_firmware = 0; } } } //MMU.fw.com == 0; // reset fw device communication if ( reset_firmware) { // reset fw device communication fw_reset_com(&MMU.fw); } MMU.SPI_CNT = val; T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM7][(REG_SPICNT >> 20) & 0xff], REG_SPICNT & 0xfff, val); } return; case REG_SPIDATA : MMU_writeToSPIData(val); return; /* NOTICE: Perhaps we have to use gbatek-like reg names instead of libnds-like ones ...*/ case REG_IME : NDS_Reschedule(); MMU.reg_IME[ARMCPU_ARM7] = val & 0x01; T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM7][0x40], 0x208, val); return; case REG_IE : NDS_Reschedule(); MMU.reg_IE[ARMCPU_ARM7] = (MMU.reg_IE[ARMCPU_ARM7]&0xFFFF0000) | val; return; case REG_IE + 2 : NDS_Reschedule(); //emu_halt(); MMU.reg_IE[ARMCPU_ARM7] = (MMU.reg_IE[ARMCPU_ARM7]&0xFFFF) | (((u32)val)<<16); return; case REG_IF: REG_IF_WriteWord(0,val); return; case REG_IF+2: REG_IF_WriteWord(2,val); return; case REG_IPCSYNC: MMU_IPCSync(ARMCPU_ARM7, val); return; case REG_IPCFIFOCNT: IPC_FIFOcnt(ARMCPU_ARM7, val); return; case REG_TM0CNTL : case REG_TM1CNTL : case REG_TM2CNTL : case REG_TM3CNTL : MMU.timerReload[ARMCPU_ARM7][(adr>>2)&3] = val; return; case REG_TM0CNTH : case REG_TM1CNTH : case REG_TM2CNTH : case REG_TM3CNTH : { int timerIndex = ((adr-2)>>2)&0x3; write_timer(ARMCPU_ARM7, timerIndex, val); return; } case REG_GCROMCTRL : MMU_writeToGCControl( (T1ReadLong(MMU.MMU_MEM[1][0x40], 0x1A4) & 0xFFFF0000) | val); return; case REG_GCROMCTRL+2 : MMU_writeToGCControl( (T1ReadLong(MMU.MMU_MEM[1][0x40], 0x1A4) & 0xFFFF) | ((u32) val << 16)); return; } T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM7][adr>>20], adr&MMU.MMU_MASK[ARMCPU_ARM7][adr>>20], val); return; } bool unmapped, restricted; adr = MMU_LCDmap(adr,unmapped, restricted); if(unmapped) return; #ifdef HAVE_JIT if (JIT_MAPPED(adr, ARMCPU_ARM7)) JIT_COMPILED_FUNC_PREMASKED(adr, ARMCPU_ARM7, 0) = 0; #endif // Removed the &0xFF as they are implicit with the adr&0x0FFFFFFF [shash] T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM7][adr>>20], adr&MMU.MMU_MASK[ARMCPU_ARM7][adr>>20], val); } //================================================= MMU ARM7 write 32 void FASTCALL _MMU_ARM7_write32(u32 adr, u32 val) { adr &= 0x0FFFFFFC; #ifdef _MMU_DEBUG mmu_log_debug_ARM7(adr, "(write32) 0x%08X", val); #endif if (adr < 0x02000000) return; //can't write to bios or entire area below main memory if (slot2_write(adr, val)) return; if (SPU_core->isSPU(adr)) { SPU_WriteLong(adr, val); return; } if ((adr & 0xFFFF0000) == 0x04800000) { WIFI_write16(adr, val & 0xFFFF); WIFI_write16(adr+2, val >> 16); T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM7][0x48], adr&MMU.MMU_MASK[ARMCPU_ARM7][0x48], val); return; } // Address is an IO register if ((adr >> 24) == 4) { if (!validateIORegsWrite(adr, 32, val)) return; if(MMU_new.is_dma(adr)) { MMU_new.write_dma(ARMCPU_ARM7,32,adr,val); return; } switch(adr) { case REG_RTC: rtcWrite((u16)val); break; case REG_IME : NDS_Reschedule(); MMU.reg_IME[ARMCPU_ARM7] = val & 0x01; T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM7][0x40], 0x208, val); return; case REG_IE : NDS_Reschedule(); MMU.reg_IE[ARMCPU_ARM7] = val; return; case REG_IF: REG_IF_WriteLong(val); return; case REG_TM0CNTL: case REG_TM1CNTL: case REG_TM2CNTL: case REG_TM3CNTL: { int timerIndex = (adr>>2)&0x3; MMU.timerReload[ARMCPU_ARM7][timerIndex] = (u16)val; T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM7][0x40], adr & 0xFFF, val); write_timer(ARMCPU_ARM7, timerIndex, val>>16); return; } case REG_IPCSYNC: MMU_IPCSync(ARMCPU_ARM7, val); return; case REG_IPCFIFOCNT: IPC_FIFOcnt(ARMCPU_ARM7, val); return; case REG_IPCFIFOSEND: IPC_FIFOsend(ARMCPU_ARM7, val); return; case REG_GCROMCTRL : MMU_writeToGCControl(val); return; case REG_GCDATAIN: MMU_writeToGC(val); return; } T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM7][adr>>20], adr & MMU.MMU_MASK[ARMCPU_ARM7][adr>>20], val); return; } bool unmapped, restricted; adr = MMU_LCDmap(adr,unmapped, restricted); if(unmapped) return; #ifdef HAVE_JIT if (JIT_MAPPED(adr, ARMCPU_ARM7)) { JIT_COMPILED_FUNC_PREMASKED(adr, ARMCPU_ARM7, 0) = 0; JIT_COMPILED_FUNC_PREMASKED(adr, ARMCPU_ARM7, 1) = 0; } #endif // Removed the &0xFF as they are implicit with the adr&0x0FFFFFFF [shash] T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM7][adr>>20], adr&MMU.MMU_MASK[ARMCPU_ARM7][adr>>20], val); } //================================================= MMU ARM7 read 08 u8 FASTCALL _MMU_ARM7_read08(u32 adr) { adr &= 0x0FFFFFFF; #ifdef _MMU_DEBUG mmu_log_debug_ARM7(adr, "(read08) 0x%02X", MMU.MMU_MEM[ARMCPU_ARM7][(adr>>20)&0xFF][adr&MMU.MMU_MASK[ARMCPU_ARM7][(adr>>20)&0xFF]]); #endif if (adr < 0x4000) { //the ARM7 bios can't be read by instructions outside of itself. //TODO - use REG_BIOSPROT //How accurate is this? our instruct_adr may not be exactly what the hardware uses (may use something +/- 0x08 or so) //This may be inaccurate at the very edge cases. if (NDS_ARM7.instruct_adr > 0x3FFF) return 0xFF; } // wifi mac access if ((adr & 0xFFFF0000) == 0x04800000) { if (adr & 1) return (WIFI_read16(adr-1) >> 8) & 0xFF; return WIFI_read16(adr) & 0xFF; } u8 slot2_val; if (slot2_read(adr, slot2_val)) return slot2_val; if (SPU_core->isSPU(adr)) return SPU_ReadByte(adr); /* Address is an IO register */ if ((adr >> 24) == 4) { VALIDATE_IO_REGS_READ(ARMCPU_ARM7, 8); if(MMU_new.is_dma(adr)) return MMU_new.read_dma(ARMCPU_ARM7,8,adr); switch(adr) { case REG_RTC: return (u8)rtcRead(); case REG_IF: return MMU.gen_IF(); case REG_IF+1: return (MMU.gen_IF()>>8); case REG_IF+2: return (MMU.gen_IF()>>16); case REG_IF+3: return (MMU.gen_IF()>>24); case REG_DISPx_VCOUNT: return nds.VCount&0xFF; case REG_DISPx_VCOUNT+1: return (nds.VCount>>8)&0xFF; case REG_WRAMSTAT: return MMU.WRAMCNT; } return MMU.MMU_MEM[ARMCPU_ARM7][adr>>20][adr&MMU.MMU_MASK[ARMCPU_ARM7][adr>>20]]; } bool unmapped, restricted; adr = MMU_LCDmap(adr,unmapped, restricted); if(unmapped) return 0; return MMU.MMU_MEM[ARMCPU_ARM7][adr>>20][adr&MMU.MMU_MASK[ARMCPU_ARM7][adr>>20]]; } //================================================= MMU ARM7 read 16 u16 FASTCALL _MMU_ARM7_read16(u32 adr) { adr &= 0x0FFFFFFE; #ifdef _MMU_DEBUG mmu_log_debug_ARM7(adr, "(read16) 0x%04X", T1ReadWord(MMU.MMU_MEM[ARMCPU_ARM7][(adr>>20)&0xFF], adr & MMU.MMU_MASK[ARMCPU_ARM7][(adr>>20)&0xFF])); #endif if (adr < 0x4000) { if (NDS_ARM7.instruct_adr > 0x3FFF) return 0xFFFF; } //wifi mac access if ((adr & 0xFFFF0000) == 0x04800000) return WIFI_read16(adr) ; u16 slot2_val; if (slot2_read(adr, slot2_val)) return slot2_val; if (SPU_core->isSPU(adr)) return SPU_ReadWord(adr); // Address is an IO register if ((adr >> 24) == 4) { VALIDATE_IO_REGS_READ(ARMCPU_ARM7, 16); if(MMU_new.is_dma(adr)) return MMU_new.read_dma(ARMCPU_ARM7,16,adr); switch(adr) { case REG_POWCNT2: { u16 ret = 0; ret |= nds.power2.speakers?BIT(0):0; ret |= nds.power2.wifi?BIT(1):0; return ret; } case REG_DISPx_VCOUNT: return nds.VCount; case REG_RTC: return rtcRead(); case REG_IME: return (u16)MMU.reg_IME[ARMCPU_ARM7]; case REG_IE: return (u16)MMU.reg_IE[ARMCPU_ARM7]; case REG_IE + 2: return (u16)(MMU.reg_IE[ARMCPU_ARM7]>>16); case REG_IF: return MMU.gen_IF(); case REG_IF+2: return MMU.gen_IF()>>16; case REG_TM0CNTL : case REG_TM1CNTL : case REG_TM2CNTL : case REG_TM3CNTL : return read_timer(ARMCPU_ARM7,(adr&0xF)>>2); case REG_VRAMSTAT: /* make sure WRAMSTAT is stashed and then fallthrough to return the value from memory. i know, gross. */ T1WriteByte(MMU.MMU_MEM[ARMCPU_ARM7][0x40], 0x241, MMU.WRAMCNT); break; case REG_AUXSPICNT: return MMU.AUX_SPI_CNT; case REG_KEYINPUT: /*here is an example of what not to do: *since the arm7 polls this (and EXTKEYIN) every frame, we shouldnt count this as an input check */ break; case REG_EXTKEYIN: { //this is gross. we should generate this whole reg instead of poking it in ndssystem u16 ret = MMU.ARM7_REG[0x136]; if(nds.isTouch) ret &= ~64; else ret |= 64; return ret; } } return T1ReadWord_guaranteedAligned(MMU.MMU_MEM[ARMCPU_ARM7][adr>>20], adr & MMU.MMU_MASK[ARMCPU_ARM7][adr>>20]); } bool unmapped, restricted; adr = MMU_LCDmap(adr,unmapped, restricted); if(unmapped) return 0; /* Returns data from memory */ /* Removed the &0xFF as they are implicit with the adr&0x0FFFFFFF */ return T1ReadWord_guaranteedAligned(MMU.MMU_MEM[ARMCPU_ARM7][adr >> 20], adr & MMU.MMU_MASK[ARMCPU_ARM7][adr >> 20]); } //================================================= MMU ARM7 read 32 u32 FASTCALL _MMU_ARM7_read32(u32 adr) { adr &= 0x0FFFFFFC; #ifdef _MMU_DEBUG mmu_log_debug_ARM7(adr, "(read32) 0x%08X", T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM7][(adr>>20)&0xFF], adr & MMU.MMU_MASK[ARMCPU_ARM7][(adr>>20)&0xFF])); #endif if (adr < 0x4000) { //the ARM7 bios can't be read by instructions outside of itself. //TODO - use REG_BIOSPROT //How accurate is this? our instruct_adr may not be exactly what the hardware uses (may use something +/- 0x08 or so) //This may be inaccurate at the very edge cases. if (NDS_ARM7.instruct_adr > 0x3FFF) return 0xFFFFFFFF; } //wifi mac access if ((adr & 0xFFFF0000) == 0x04800000) return (WIFI_read16(adr) | (WIFI_read16(adr+2) << 16)); u32 slot2_val; if (slot2_read(adr, slot2_val)) return slot2_val; if (SPU_core->isSPU(adr)) return SPU_ReadLong(adr); /* Address is an IO register */ if ((adr >> 24) == 4) { VALIDATE_IO_REGS_READ(ARMCPU_ARM7, 32); if(MMU_new.is_dma(adr)) return MMU_new.read_dma(ARMCPU_ARM7,32,adr); switch(adr) { case REG_RTC: return (u32)rtcRead(); case REG_DISPx_VCOUNT: return nds.VCount; case REG_IME : return MMU.reg_IME[ARMCPU_ARM7]; case REG_IE : return MMU.reg_IE[ARMCPU_ARM7]; case REG_IF: return MMU.gen_IF(); case REG_IPCFIFORECV : return IPC_FIFOrecv(ARMCPU_ARM7); case REG_TM0CNTL : case REG_TM1CNTL : case REG_TM2CNTL : case REG_TM3CNTL : { u32 val = T1ReadWord(MMU.MMU_MEM[ARMCPU_ARM7][0x40], (adr + 2) & 0xFFF); return MMU.timer[ARMCPU_ARM7][(adr&0xF)>>2] | (val<<16); } #if 0 case REG_GCROMCTRL: return MMU_readFromGCControl(); #endif case REG_GCDATAIN: return MMU_readFromGC(); case REG_VRAMSTAT: /* make sure WRAMSTAT is stashed and then fallthrough return the value from memory. i know, gross. */ T1WriteByte(MMU.MMU_MEM[ARMCPU_ARM7][0x40], 0x241, MMU.WRAMCNT); break; } return T1ReadLong_guaranteedAligned(MMU.MMU_MEM[ARMCPU_ARM7][adr>>20], adr & MMU.MMU_MASK[ARMCPU_ARM7][adr>>20]); } bool unmapped, restricted; adr = MMU_LCDmap(adr,unmapped, restricted); if(unmapped) return 0; /* Returns data from memory * Removed the &0xFF as they are implicit with the adr&0x0FFFFFFF [zeromus, inspired by shash] */ return T1ReadLong_guaranteedAligned(MMU.MMU_MEM[ARMCPU_ARM7][adr >> 20], adr & MMU.MMU_MASK[ARMCPU_ARM7][adr >> 20]); } //========================================================================================================= u32 FASTCALL MMU_read32(u32 proc, u32 adr) { retro_assert((adr&3)==0); if(proc==0) return _MMU_ARM9_read32(adr); return _MMU_ARM7_read32(adr); } u16 FASTCALL MMU_read16(u32 proc, u32 adr) { retro_assert((adr&1)==0); if(proc==0) return _MMU_ARM9_read16(adr); return _MMU_ARM7_read16(adr); } u8 FASTCALL MMU_read8(u32 proc, u32 adr) { if(proc==0) return _MMU_ARM9_read08(adr); return _MMU_ARM7_read08(adr); } void FASTCALL MMU_write32(u32 proc, u32 adr, u32 val) { retro_assert((adr&3)==0); if(proc==0) _MMU_ARM9_write32(adr, val); else _MMU_ARM7_write32(adr,val); } void FASTCALL MMU_write16(u32 proc, u32 adr, u16 val) { retro_assert((adr&1)==0); if(proc==0) _MMU_ARM9_write16(adr, val); else _MMU_ARM7_write16(adr,val); } void FASTCALL MMU_write8(u32 proc, u32 adr, u8 val) { if(proc==0) _MMU_ARM9_write08(adr, val); else _MMU_ARM7_write08(adr,val); } void FASTCALL MMU_DumpMemBlock(u8 proc, u32 address, u32 size, u8 *buffer) { u32 i; u32 curaddr; for(i = 0, curaddr = address; i < size; i++, curaddr++) buffer[i] = _MMU_read08(proc,MMU_AT_DEBUG,curaddr); } //these templates needed to be instantiated manually template u32 MMU_struct::gen_IF(); template u32 MMU_struct::gen_IF(); //////////////////////////////////////////////////////////// //function pointer handlers for gdb stub stuff static u16 FASTCALL arm9_prefetch16( void *data, u32 adr) { return _MMU_read16(adr); } static u32 FASTCALL arm9_prefetch32( void *data, u32 adr) { return _MMU_read32(adr); } static u8 FASTCALL arm9_read8( void *data, u32 adr) { return _MMU_read08(adr); } static u16 FASTCALL arm9_read16( void *data, u32 adr) { return _MMU_read16(adr); } static u32 FASTCALL arm9_read32( void *data, u32 adr) { return _MMU_read32(adr); } static void FASTCALL arm9_write8(void *data, u32 adr, u8 val) { _MMU_write08(adr, val); } static void FASTCALL arm9_write16(void *data, u32 adr, u16 val) { _MMU_write16(adr, val); } static void FASTCALL arm9_write32(void *data, u32 adr, u32 val) { _MMU_write32(adr, val); } static u16 FASTCALL arm7_prefetch16( void *data, u32 adr) { return _MMU_read16(adr); } static u32 FASTCALL arm7_prefetch32( void *data, u32 adr) { return _MMU_read32(adr); } static u8 FASTCALL arm7_read8( void *data, u32 adr) { return _MMU_read08(adr); } static u16 FASTCALL arm7_read16( void *data, u32 adr) { return _MMU_read16(adr); } static u32 FASTCALL arm7_read32( void *data, u32 adr) { return _MMU_read32(adr); } static void FASTCALL arm7_write8(void *data, u32 adr, u8 val) { _MMU_write08(adr, val); } static void FASTCALL arm7_write16(void *data, u32 adr, u16 val) { _MMU_write16(adr, val); } static void FASTCALL arm7_write32(void *data, u32 adr, u32 val) { _MMU_write32(adr, val); } /* * the base memory interfaces */ const armcpu_memory_iface arm9_base_memory_iface = { arm9_prefetch32, arm9_prefetch16, arm9_read8, arm9_read16, arm9_read32, arm9_write8, arm9_write16, arm9_write32, NULL }; const armcpu_memory_iface arm7_base_memory_iface = { arm7_prefetch32, arm7_prefetch16, arm7_read8, arm7_read16, arm7_read32, arm7_write8, arm7_write16, arm7_write32, NULL }; /* * The direct memory interface for the ARM9. * This avoids the ARM9 protection unit when accessing * memory. */ const armcpu_memory_iface arm9_direct_memory_iface = { NULL, NULL, arm9_read8, arm9_read16, arm9_read32, arm9_write8, arm9_write16, arm9_write32, NULL }; desmume/src/gfx3d.h000664 001750 001750 00000053411 12755534123 015327 0ustar00sergiosergio000000 000000 /* Copyright (C) 2006 yopyop Copyright (C) 2008-2015 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the this software. If not, see . */ #ifndef _GFX3D_H_ #define _GFX3D_H_ #include #include #include #include "types.h" #include "GPU.h" class EMUFILE; //geometry engine command numbers #define GFX3D_NOP 0x00 #define GFX3D_MTX_MODE 0x10 #define GFX3D_MTX_PUSH 0x11 #define GFX3D_MTX_POP 0x12 #define GFX3D_MTX_STORE 0x13 #define GFX3D_MTX_RESTORE 0x14 #define GFX3D_MTX_IDENTITY 0x15 #define GFX3D_MTX_LOAD_4x4 0x16 #define GFX3D_MTX_LOAD_4x3 0x17 #define GFX3D_MTX_MULT_4x4 0x18 #define GFX3D_MTX_MULT_4x3 0x19 #define GFX3D_MTX_MULT_3x3 0x1A #define GFX3D_MTX_SCALE 0x1B #define GFX3D_MTX_TRANS 0x1C #define GFX3D_COLOR 0x20 #define GFX3D_NORMAL 0x21 #define GFX3D_TEXCOORD 0x22 #define GFX3D_VTX_16 0x23 #define GFX3D_VTX_10 0x24 #define GFX3D_XY 0x25 #define GFX3D_XZ 0x26 #define GFX3D_YZ 0x27 #define GFX3D_DIFF 0x28 #define GFX3D_POLYGON_ATTR 0x29 #define GFX3D_TEXIMAGE_PARAM 0x2A #define GFX3D_PLTT_BASE 0x2B #define GFX3D_DIF_AMB 0x30 #define GFX3D_SPE_EMI 0x31 #define GFX3D_LIGHT_VECTOR 0x32 #define GFX3D_LIGHT_COLOR 0x33 #define GFX3D_SHININESS 0x34 #define GFX3D_BEGIN_VTXS 0x40 #define GFX3D_END_VTXS 0x41 #define GFX3D_SWAP_BUFFERS 0x50 #define GFX3D_VIEWPORT 0x60 #define GFX3D_BOX_TEST 0x70 #define GFX3D_POS_TEST 0x71 #define GFX3D_VEC_TEST 0x72 #define GFX3D_NOP_NOARG_HACK 0xDD //produce a 32bpp color from a ds RGB15, using a table #define RGB15TO32_NOALPHA(col) ( color_15bit_to_24bit[col&0x7FFF] ) //produce a 32bpp color from a ds RGB15 plus an 8bit alpha, using a table #ifdef MSB_FIRST #define RGB15TO32(col,alpha8) ( (alpha8) | color_15bit_to_24bit[(col)&0x7FFF] ) #else #define RGB15TO32(col,alpha8) ( ((alpha8)<<24) | color_15bit_to_24bit[(col)&0x7FFF] ) #endif //produce a 5555 32bit color from a ds RGB15 plus an 5bit alpha #ifdef MSB_FIRST #define RGB15TO5555(col,alpha5) ( (alpha5) | ((((col) & 0x7C00)>>10)<<8) | ((((col) & 0x03E0)>>5)<<16) | (((col) & 0x001F)<<24) ) #else #define RGB15TO5555(col,alpha5) ( ((alpha5)<<24) | ((((col) & 0x7C00)>>10)<<16) | ((((col) & 0x03E0)>>5)<<8) | ((col) & 0x001F) ) #endif //produce a 6665 32bit color from a ds RGB15 plus an 5bit alpha inline u32 RGB15TO6665(u16 col, u8 alpha5) { const u16 r = (col&0x001F)>>0; const u16 g = (col&0x03E0)>>5; const u16 b = (col&0x7C00)>>10; #ifdef MSB_FIRST const u32 ret = alpha5 | (((b<<1)+1)<<8) | (((g<<1)+1)<<16) | (((r<<1)+1)<<24); #else const u32 ret = (alpha5<<24) | (((b<<1)+1)<<16) | (((g<<1)+1)<<8) | ((r<<1)+1); #endif return ret; } //produce a 24bpp color from a ds RGB15, using a table #define RGB15TO24_REVERSE(col) ( color_15bit_to_24bit_reverse[(col)&0x7FFF] ) //produce a 16bpp color from a ds RGB15, using a table #define RGB15TO16_REVERSE(col) ( color_15bit_to_16bit_reverse[(col)&0x7FFF] ) //produce a 15bpp color from individual 5bit components #define R5G5B5TORGB15(r,g,b) ( (r) | ((g)<<5) | ((b)<<10) ) //produce a 16bpp color from individual 5bit components #define R6G6B6TORGB15(r,g,b) ( ((r)>>1) | (((g)&0x3E)<<4) | (((b)&0x3E)<<9) ) #define GFX3D_5TO6(x) ((x)?(((x)<<1)+1):0) // 15-bit to 24-bit depth formula from http://nocash.emubase.de/gbatek.htm#ds3drearplane #define DS_DEPTH15TO24(depth) ( dsDepthExtend_15bit_to_24bit[(depth) & 0x7FFF] ) // MATRIX MODES enum MatrixMode { MATRIXMODE_PROJECTION = 0, MATRIXMODE_POSITION = 1, MATRIXMODE_POSITION_VECTOR = 2, MATRIXMODE_TEXTURE = 3 }; // POLYGON PRIMITIVE TYPES enum PolygonPrimitiveType { GFX3D_TRIANGLES = 0, GFX3D_QUADS = 1, GFX3D_TRIANGLE_STRIP = 2, GFX3D_QUAD_STRIP = 3, GFX3D_TRIANGLES_LINE = 4, GFX3D_QUADS_LINE = 5, GFX3D_TRIANGLE_STRIP_LINE = 6, GFX3D_QUAD_STRIP_LINE = 7 }; // POLYGON MODES enum PolygonMode { POLYGON_MODE_MODULATE = 0, POLYGON_MODE_DECAL = 1, POLYGON_MODE_TOONHIGHLIGHT = 2, POLYGON_MODE_SHADOW = 3 }; // POLYGON TYPES enum PolygonType { POLYGON_TYPE_TRIANGLE = 3, POLYGON_TYPE_QUAD = 4 }; // POLYGON ATTRIBUTES - BIT LOCATIONS enum { POLYGON_ATTR_ENABLE_LIGHT0_BIT = 0, POLYGON_ATTR_ENABLE_LIGHT1_BIT = 1, POLYGON_ATTR_ENABLE_LIGHT2_BIT = 2, POLYGON_ATTR_ENABLE_LIGHT3_BIT = 3, POLYGON_ATTR_MODE_BIT = 4, // Bits 4 - 5 POLYGON_ATTR_ENABLE_BACK_SURFACE_BIT = 6, POLYGON_ATTR_ENABLE_FRONT_SURFACE_BIT = 7, // Bits 8 - 10 unused POLYGON_ATTR_ENABLE_ALPHA_DEPTH_WRITE_BIT = 11, POLYGON_ATTR_ENABLE_RENDER_ON_FAR_PLANE_INTERSECT_BIT = 12, POLYGON_ATTR_ENABLE_ONE_DOT_RENDER_BIT = 13, POLYGON_ATTR_ENABLE_DEPTH_EQUAL_TEST_BIT = 14, POLYGON_ATTR_ENABLE_FOG_BIT = 15, POLYGON_ATTR_ALPHA_BIT = 16, // Bits 16 - 20 // Bits 21 - 23 unused POLYGON_ATTR_POLYGON_ID_BIT = 24, // Bits 24 - 29 // Bits 30 - 31 unused }; // POLYGON ATTRIBUTES - BIT MASKS enum { POLYGON_ATTR_ENABLE_LIGHT0_MASK = 0x01 << POLYGON_ATTR_ENABLE_LIGHT0_BIT, POLYGON_ATTR_ENABLE_LIGHT1_MASK = 0x01 << POLYGON_ATTR_ENABLE_LIGHT1_BIT, POLYGON_ATTR_ENABLE_LIGHT2_MASK = 0x01 << POLYGON_ATTR_ENABLE_LIGHT2_BIT, POLYGON_ATTR_ENABLE_LIGHT3_MASK = 0x01 << POLYGON_ATTR_ENABLE_LIGHT3_BIT, POLYGON_ATTR_MODE_MASK = 0x03 << POLYGON_ATTR_MODE_BIT, POLYGON_ATTR_ENABLE_BACK_SURFACE_MASK = 0x01 << POLYGON_ATTR_ENABLE_BACK_SURFACE_BIT, POLYGON_ATTR_ENABLE_FRONT_SURFACE_MASK = 0x01 << POLYGON_ATTR_ENABLE_FRONT_SURFACE_BIT, POLYGON_ATTR_ENABLE_ALPHA_DEPTH_WRITE_MASK = 0x01 << POLYGON_ATTR_ENABLE_ALPHA_DEPTH_WRITE_BIT, POLYGON_ATTR_ENABLE_RENDER_ON_FAR_PLANE_INTERSECT_MASK = 0x01 << POLYGON_ATTR_ENABLE_RENDER_ON_FAR_PLANE_INTERSECT_BIT, POLYGON_ATTR_ENABLE_ONE_DOT_RENDER_MASK = 0x01 << POLYGON_ATTR_ENABLE_ONE_DOT_RENDER_BIT, POLYGON_ATTR_ENABLE_DEPTH_EQUAL_TEST_MASK = 0x01 << POLYGON_ATTR_ENABLE_DEPTH_EQUAL_TEST_BIT, POLYGON_ATTR_ENABLE_FOG_MASK = 0x01 << POLYGON_ATTR_ENABLE_FOG_BIT, POLYGON_ATTR_ALPHA_MASK = 0x1F << POLYGON_ATTR_ALPHA_BIT, POLYGON_ATTR_POLYGON_ID_MASK = 0x3F << POLYGON_ATTR_POLYGON_ID_BIT }; // TEXTURE PARAMETERS - BIT LOCATIONS enum { TEXTURE_PARAM_VRAM_OFFSET_BIT = 0, // Bits 0 - 15 TEXTURE_PARAM_ENABLE_REPEAT_S_BIT = 16, TEXTURE_PARAM_ENABLE_REPEAT_T_BIT = 17, TEXTURE_PARAM_ENABLE_MIRRORED_REPEAT_S_BIT = 18, TEXTURE_PARAM_ENABLE_MIRRORED_REPEAT_T_BIT = 19, TEXTURE_PARAM_SIZE_S_BIT = 20, // Bits 20 - 22 TEXTURE_PARAM_SIZE_T_BIT = 23, // Bits 23 - 25 TEXTURE_PARAM_FORMAT_BIT = 26, // Bits 26 - 28 TEXTURE_PARAM_ENABLE_TRANSPARENT_COLOR0_BIT = 29, TEXTURE_PARAM_COORD_TRANSFORM_MODE_BIT = 30 // Bits 30 - 31 }; // TEXTURE PARAMETERS - BIT MASKS enum { TEXTURE_PARAM_VRAM_OFFSET_MASK = 0xFFFF << TEXTURE_PARAM_VRAM_OFFSET_BIT, TEXTURE_PARAM_ENABLE_REPEAT_S_MASK = 0x01 << TEXTURE_PARAM_ENABLE_REPEAT_S_BIT, TEXTURE_PARAM_ENABLE_REPEAT_T_MASK = 0x01 << TEXTURE_PARAM_ENABLE_REPEAT_T_BIT, TEXTURE_PARAM_ENABLE_MIRRORED_REPEAT_S_MASK = 0x01 << TEXTURE_PARAM_ENABLE_MIRRORED_REPEAT_S_BIT, TEXTURE_PARAM_ENABLE_MIRRORED_REPEAT_T_MASK = 0x01 << TEXTURE_PARAM_ENABLE_MIRRORED_REPEAT_T_BIT, TEXTURE_PARAM_SIZE_S_MASK = 0x07 << TEXTURE_PARAM_SIZE_S_BIT, TEXTURE_PARAM_SIZE_T_MASK = 0x07 << TEXTURE_PARAM_SIZE_T_BIT, TEXTURE_PARAM_FORMAT_MASK = 0x07 << TEXTURE_PARAM_FORMAT_BIT, TEXTURE_PARAM_ENABLE_TRANSPARENT_COLOR0_MASK = 0x01 << TEXTURE_PARAM_ENABLE_TRANSPARENT_COLOR0_BIT, TEXTURE_PARAM_COORD_TRANSFORM_MODE_MASK = 0x03 << TEXTURE_PARAM_COORD_TRANSFORM_MODE_BIT }; // TEXTURE PARAMETERS - FORMAT ID enum { TEXMODE_NONE = 0, TEXMODE_A3I5 = 1, TEXMODE_I2 = 2, TEXMODE_I4 = 3, TEXMODE_I8 = 4, TEXMODE_4X4 = 5, TEXMODE_A5I3 = 6, TEXMODE_16BPP = 7 }; enum PolygonShadingMode { PolygonShadingMode_Toon = 0, PolygonShadingMode_Highlight = 1 }; void gfx3d_init(); void gfx3d_deinit(); void gfx3d_reset(); typedef struct { u8 enableLightFlags; bool enableLight0; bool enableLight1; bool enableLight2; bool enableLight3; PolygonMode polygonMode; u8 surfaceCullingMode; bool enableRenderBackSurface; bool enableRenderFrontSurface; bool enableAlphaDepthWrite; bool enableRenderOnFarPlaneIntersect; bool enableRenderOneDot; bool enableDepthEqualTest; bool enableRenderFog; bool isWireframe; bool isOpaque; bool isTranslucent; u8 alpha; u8 polygonID; } PolygonAttributes; typedef struct { u16 VRAMOffset; bool enableRepeatS; bool enableRepeatT; bool enableMirroredRepeatS; bool enableMirroredRepeatT; u8 sizeS; u8 sizeT; u8 texFormat; bool enableTransparentColor0; u8 coordTransformMode; } PolygonTexParams; struct POLY { PolygonType type; //tri or quad PolygonPrimitiveType vtxFormat; u16 vertIndexes[4]; //up to four verts can be referenced by this poly u32 polyAttr, texParam, texPalette; //the hardware rendering params u32 viewport; float miny, maxy; void setVertIndexes(int a, int b, int c, int d=-1) { vertIndexes[0] = a; vertIndexes[1] = b; vertIndexes[2] = c; if(d != -1) { vertIndexes[3] = d; type = POLYGON_TYPE_QUAD; } else type = POLYGON_TYPE_TRIANGLE; } u8 getAttributeEnableLightFlags() const { return ((polyAttr & (POLYGON_ATTR_ENABLE_LIGHT0_MASK | POLYGON_ATTR_ENABLE_LIGHT1_MASK | POLYGON_ATTR_ENABLE_LIGHT2_MASK | POLYGON_ATTR_ENABLE_LIGHT3_MASK)) >> POLYGON_ATTR_ENABLE_LIGHT0_BIT); } bool getAttributeEnableLight0() const { return ((polyAttr & POLYGON_ATTR_ENABLE_LIGHT0_MASK) > 0); } bool getAttributeEnableLight1() const { return ((polyAttr & POLYGON_ATTR_ENABLE_LIGHT1_MASK) > 0); } bool getAttributeEnableLight2() const { return ((polyAttr & POLYGON_ATTR_ENABLE_LIGHT2_MASK) > 0); } bool getAttributeEnableLight3() const { return ((polyAttr & POLYGON_ATTR_ENABLE_LIGHT3_MASK) > 0); } PolygonMode getAttributePolygonMode() const { return (PolygonMode)((polyAttr & POLYGON_ATTR_MODE_MASK) >> POLYGON_ATTR_MODE_BIT); } u8 getAttributeEnableFaceCullingFlags() const { return ((polyAttr & (POLYGON_ATTR_ENABLE_BACK_SURFACE_MASK | POLYGON_ATTR_ENABLE_FRONT_SURFACE_MASK)) >> POLYGON_ATTR_ENABLE_BACK_SURFACE_BIT); } bool getAttributeEnableBackSurface() const { return ((polyAttr & POLYGON_ATTR_ENABLE_BACK_SURFACE_MASK) > 0); } bool getAttributeEnableFrontSurface() const { return ((polyAttr & POLYGON_ATTR_ENABLE_FRONT_SURFACE_MASK) > 0); } bool getAttributeEnableAlphaDepthWrite() const { return ((polyAttr & POLYGON_ATTR_ENABLE_ALPHA_DEPTH_WRITE_MASK) > 0); } bool getAttributeEnableRenderOnFarPlaneIntersect() const { return ((polyAttr & POLYGON_ATTR_ENABLE_RENDER_ON_FAR_PLANE_INTERSECT_MASK) > 0); } bool getAttributeEnableOneDotRender() const { return ((polyAttr & POLYGON_ATTR_ENABLE_ONE_DOT_RENDER_MASK) > 0); } bool getAttributeEnableDepthEqualTest() const { return ((polyAttr & POLYGON_ATTR_ENABLE_DEPTH_EQUAL_TEST_MASK) > 0); } bool getAttributeEnableFog() const { return ((polyAttr & POLYGON_ATTR_ENABLE_FOG_MASK) > 0); } u8 getAttributeAlpha() const { return ((polyAttr & POLYGON_ATTR_ALPHA_MASK) >> POLYGON_ATTR_ALPHA_BIT); } u8 getAttributePolygonID() const { return ((polyAttr & POLYGON_ATTR_POLYGON_ID_MASK) >> POLYGON_ATTR_POLYGON_ID_BIT); } PolygonAttributes getAttributes() const { PolygonAttributes theAttr; theAttr.enableLightFlags = this->getAttributeEnableLightFlags(); theAttr.enableLight0 = this->getAttributeEnableLight0(); theAttr.enableLight1 = this->getAttributeEnableLight1(); theAttr.enableLight2 = this->getAttributeEnableLight2(); theAttr.enableLight3 = this->getAttributeEnableLight3(); theAttr.polygonMode = this->getAttributePolygonMode(); theAttr.surfaceCullingMode = this->getAttributeEnableFaceCullingFlags(); theAttr.enableRenderBackSurface = this->getAttributeEnableBackSurface(); theAttr.enableRenderFrontSurface = this->getAttributeEnableFrontSurface(); theAttr.enableAlphaDepthWrite = this->getAttributeEnableAlphaDepthWrite(); theAttr.enableRenderOnFarPlaneIntersect = this->getAttributeEnableRenderOnFarPlaneIntersect(); theAttr.enableRenderOneDot = this->getAttributeEnableOneDotRender(); theAttr.enableDepthEqualTest = this->getAttributeEnableDepthEqualTest(); theAttr.enableRenderFog = this->getAttributeEnableFog(); theAttr.alpha = this->getAttributeAlpha(); theAttr.isWireframe = this->isWireframe(); theAttr.isOpaque = this->isOpaque(); theAttr.isTranslucent = this->isTranslucent(); theAttr.polygonID = this->getAttributePolygonID(); return theAttr; } u16 getTexParamVRAMOffset() const { return ((texParam & TEXTURE_PARAM_VRAM_OFFSET_MASK) >> TEXTURE_PARAM_VRAM_OFFSET_BIT); } bool getTexParamEnableRepeatS() const { return ((texParam & TEXTURE_PARAM_ENABLE_REPEAT_S_MASK) > 0); } bool getTexParamEnableRepeatT() const { return ((texParam & TEXTURE_PARAM_ENABLE_REPEAT_T_MASK) > 0); } bool getTexParamEnableMirroredRepeatS() const { return ((texParam & TEXTURE_PARAM_ENABLE_MIRRORED_REPEAT_S_MASK) > 0); } bool getTexParamEnableMirroredRepeatT() const { return ((texParam & TEXTURE_PARAM_ENABLE_MIRRORED_REPEAT_T_MASK) > 0); } u8 getTexParamSizeS() const { return ((texParam & TEXTURE_PARAM_SIZE_S_MASK) >> TEXTURE_PARAM_SIZE_S_BIT); } u8 getTexParamSizeT() const { return ((texParam & TEXTURE_PARAM_SIZE_T_MASK) >> TEXTURE_PARAM_SIZE_T_BIT); } u8 getTexParamTexFormat() const { return ((texParam & TEXTURE_PARAM_FORMAT_MASK) >> TEXTURE_PARAM_FORMAT_BIT); } bool getTexParamEnableTransparentColor0() const { return ((texParam & TEXTURE_PARAM_ENABLE_TRANSPARENT_COLOR0_MASK) > 0); } u8 getTexParamCoordTransformMode() const { return ((texParam & TEXTURE_PARAM_COORD_TRANSFORM_MODE_MASK) >> TEXTURE_PARAM_COORD_TRANSFORM_MODE_BIT); } PolygonTexParams getTexParams() const { PolygonTexParams theTexParams; theTexParams.VRAMOffset = this->getTexParamVRAMOffset(); theTexParams.enableRepeatS = this->getTexParamEnableRepeatS(); theTexParams.enableRepeatT = this->getTexParamEnableRepeatT(); theTexParams.enableMirroredRepeatS = this->getTexParamEnableMirroredRepeatS(); theTexParams.enableMirroredRepeatT = this->getTexParamEnableMirroredRepeatT(); theTexParams.sizeS = this->getTexParamSizeS(); theTexParams.sizeT = this->getTexParamSizeT(); theTexParams.texFormat = this->getTexParamTexFormat(); theTexParams.enableTransparentColor0 = this->getTexParamEnableTransparentColor0(); theTexParams.coordTransformMode = this->getTexParamCoordTransformMode(); return theTexParams; } bool isWireframe() const { return (this->getAttributeAlpha() == 0); } bool isOpaque() const { return (this->getAttributeAlpha() == 31); } bool isTranslucent() const { // First, check if the polygon is wireframe or opaque. // If neither, then it must be translucent. if (!this->isWireframe() && !this->isOpaque()) { return true; } // Also check for translucent texture format. u8 texFormat = this->getTexParamTexFormat(); //a5i3 or a3i5 -> translucent if(texFormat == TEXMODE_A3I5 || texFormat == TEXMODE_A5I3) return true; return false; } void save(EMUFILE* os); void load(EMUFILE* is); }; #define POLYLIST_SIZE 20000 struct POLYLIST { POLY list[POLYLIST_SIZE]; int count; }; //just a vert with a 4 float position struct VERT_POS4f { union { float coord[4]; struct { float x,y,z,w; }; struct { float x,y,z,w; } position; }; void set_coord(float x, float y, float z, float w) { this->x = x; this->y = y; this->z = z; this->w = w; } }; //dont use SSE optimized matrix instructions in here, things might not be aligned //we havent padded this because the sheer bulk of data leaves things running faster without the extra bloat struct VERT { // Align to 16 for SSE instructions to work union { float coord[4]; struct { float x,y,z,w; }; } CACHE_ALIGN; union { float texcoord[2]; struct { float u,v; }; } CACHE_ALIGN; void set_coord(float x, float y, float z, float w) { this->x = x; this->y = y; this->z = z; this->w = w; } void set_coord(float* coords) { x = coords[0]; y = coords[1]; z = coords[2]; w = coords[3]; } float fcolor[3]; u8 color[3]; void color_to_float() { fcolor[0] = color[0]; fcolor[1] = color[1]; fcolor[2] = color[2]; } void save(EMUFILE* os); void load(EMUFILE* is); }; #define VERTLIST_SIZE (POLYLIST_SIZE * 4) struct VERTLIST { VERT list[VERTLIST_SIZE]; int count; }; #define INDEXLIST_SIZE (POLYLIST_SIZE * 4) struct INDEXLIST { int list[INDEXLIST_SIZE]; }; struct VIEWPORT { u8 x, y; u16 width, height; void decode(u32 v); }; //ok, imagine the plane that cuts diagonally across a cube such that it clips //out to be a hexagon. within that plane, draw a quad such that it cuts off //four corners of the hexagon, and you will observe a decagon #define MAX_CLIPPED_VERTS 10 class GFX3D_Clipper { public: struct TClippedPoly { PolygonType type; //otherwise known as "count" of verts POLY *poly; VERT clipVerts[MAX_CLIPPED_VERTS]; }; //the entry point for poly clipping template void clipPoly(const POLY &poly, const VERT **verts); //the output of clipping operations goes into here. //be sure you init it before clipping! TClippedPoly *clippedPolys; size_t clippedPolyCounter; void reset() { clippedPolyCounter=0; } private: TClippedPoly tempClippedPoly; TClippedPoly outClippedPoly; FORCEINLINE void clipSegmentVsPlane(VERT** verts, const int coord, int which); FORCEINLINE void clipPolyVsPlane(const int coord, int which); }; //used to communicate state to the renderer struct GFX3D_State { GFX3D_State() : enableTexturing(true) , enableAlphaTest(true) , enableAlphaBlending(true) , enableAntialiasing(false) , enableEdgeMarking(false) , enableClearImage(false) , enableFog(false) , enableFogAlphaOnly(false) , shading(PolygonShadingMode_Toon) , alphaTestRef(0) , activeFlushCommand(0) , pendingFlushCommand(0) , clearDepth(1) , clearColor(0) , fogColor(0) , fogOffset(0) , fogShift(0) , invalidateToon(true) { for(u32 i=0;i kErrorCount) error = kErrorCount; return errorMessage[error]; } } // AsmJit // [Api-End] #include "../core/apiend.h" desmume/src/libretro-common/include/lists/000700 001750 001750 00000000000 12756420131 022006 5ustar00sergiosergio000000 000000 desmume/src/utils/arm_arm/arm_gen.h000664 001750 001750 00000025762 12755534123 020512 0ustar00sergiosergio000000 000000 #ifndef ARM_GEN_H_LR #define ARM_GEN_H_LR #include #include #if defined(VITA) # include #endif namespace arm_gen { template struct Constraint { public: Constraint(uint32_t val) : value(val) { assert(val < MAX); } operator uint32_t() const { return value; } private: const uint32_t value; }; struct reg_t : public Constraint<16> { public: reg_t(uint32_t num) : Constraint<16>(num) { } }; // Do NOT reorder these enums enum AG_COND { EQ, NE, CS, CC, MI, PL, VS, VC, HI, LS, GE, LT, GT, LE, AL, EGG, CONDINVALID }; enum AG_ALU_OP { AND, ANDS, EOR, EORS, SUB, SUBS, RSB, RSBS, ADD, ADDS, ADC, ADCS, SBC, SBCS, RSC, RSCS, XX1, TST , XX2, TEQ , XX3, CMP , XX4, CMN , ORR, ORRS, MOV, MOVS, BIC, BICS, MVN, MVNS, OPINVALID }; enum AG_MEM_OP { STR, LDR, STRB, LDRB, MEMINVALID }; enum AG_MEM_FLAGS { POST_INDEX = 1 << 24, NEGATE_OFFSET = 1 << 23, WRITE_BACK = 1 << 21, MEM_NONE = 0 }; enum AG_ALU_SHIFT { LSL, LSR, ASR, ROR, SHIFTINVALID }; struct alu2 { private: alu2(uint32_t val) : encoding(val) { } public: static alu2 reg_shift_reg(reg_t rm, AG_ALU_SHIFT type, reg_t rs) { return alu2(rm | (type << 5) | 0x10 | (rs << 8)); } static alu2 reg_shift_imm(reg_t rm, AG_ALU_SHIFT type, uint32_t imm) { return alu2(rm | (type << 5) | (imm << 7)); } static alu2 imm_ror(uint32_t val, uint32_t ror) { return alu2((1 << 25) | ((ror / 2) << 8) | val); } static alu2 imm_rol(uint32_t val, uint32_t rol) { return imm_ror(val, (32 - rol) & 0x1F); } static alu2 reg(reg_t rm) { return reg_shift_imm(rm, LSL, 0); } static alu2 imm(uint8_t val) { return imm_ror(val, 0); } const uint32_t encoding; }; struct mem2 { private: mem2(uint32_t val) : encoding(val) { } public: static mem2 reg_shift_imm(reg_t rm, AG_ALU_SHIFT type, uint32_t imm) { return mem2((1 << 25) | rm | (type << 5) | (imm << 7)); } static mem2 reg(reg_t rm) { return reg_shift_imm(rm, LSL, 0); } static mem2 imm(uint32_t val) { return mem2(val); } const uint32_t encoding; }; // 80 Columns be damned class code_pool { public: code_pool(uint32_t instruction_count); ~code_pool(); uint32_t instructions_remaining() const { return instruction_count - next_instruction; } void* fn_pointer(); // Relocs void set_label(const char* name); void resolve_label(const char* name); // Code Gen: Generic void insert_instruction(uint32_t op, AG_COND cond = AL); void insert_raw_instruction(uint32_t op); // Code Gen: ALU void alu_op(AG_ALU_OP op, reg_t rd, reg_t rn, const alu2& arg, AG_COND cond = AL); void and_(reg_t rd, reg_t rn, const alu2& arg, AG_COND cond = AL) { alu_op(AND , rd, rn, arg, cond); } void and_(reg_t rd, const alu2& arg, AG_COND cond = AL) { alu_op(AND , rd, rd, arg, cond); } void ands(reg_t rd, reg_t rn, const alu2& arg, AG_COND cond = AL) { alu_op(ANDS, rd, rn, arg, cond); } void ands(reg_t rd, const alu2& arg, AG_COND cond = AL) { alu_op(ANDS, rd, rd, arg, cond); } void eor (reg_t rd, reg_t rn, const alu2& arg, AG_COND cond = AL) { alu_op(EOR , rd, rn, arg, cond); } void eor (reg_t rd, const alu2& arg, AG_COND cond = AL) { alu_op(EOR , rd, rd, arg, cond); } void eors(reg_t rd, reg_t rn, const alu2& arg, AG_COND cond = AL) { alu_op(EORS, rd, rn, arg, cond); } void eors(reg_t rd, const alu2& arg, AG_COND cond = AL) { alu_op(EORS, rd, rd, arg, cond); } void sub (reg_t rd, reg_t rn, const alu2& arg, AG_COND cond = AL) { alu_op(SUB , rd, rn, arg, cond); } void sub (reg_t rd, const alu2& arg, AG_COND cond = AL) { alu_op(SUB , rd, rd, arg, cond); } void subs(reg_t rd, reg_t rn, const alu2& arg, AG_COND cond = AL) { alu_op(SUBS, rd, rn, arg, cond); } void subs(reg_t rd, const alu2& arg, AG_COND cond = AL) { alu_op(SUBS, rd, rd, arg, cond); } void rsb (reg_t rd, reg_t rn, const alu2& arg, AG_COND cond = AL) { alu_op(RSB , rd, rn, arg, cond); } void rsb (reg_t rd, const alu2& arg, AG_COND cond = AL) { alu_op(RSB , rd, rd, arg, cond); } void rsbs(reg_t rd, reg_t rn, const alu2& arg, AG_COND cond = AL) { alu_op(RSBS, rd, rn, arg, cond); } void rsbs(reg_t rd, const alu2& arg, AG_COND cond = AL) { alu_op(RSBS, rd, rd, arg, cond); } void add (reg_t rd, reg_t rn, const alu2& arg, AG_COND cond = AL) { alu_op(ADD , rd, rn, arg, cond); } void add (reg_t rd, const alu2& arg, AG_COND cond = AL) { alu_op(ADD , rd, rd, arg, cond); } void adds(reg_t rd, reg_t rn, const alu2& arg, AG_COND cond = AL) { alu_op(ADDS, rd, rn, arg, cond); } void adds(reg_t rd, const alu2& arg, AG_COND cond = AL) { alu_op(ADDS, rd, rd, arg, cond); } void adc (reg_t rd, reg_t rn, const alu2& arg, AG_COND cond = AL) { alu_op(ADC , rd, rn, arg, cond); } void adc (reg_t rd, const alu2& arg, AG_COND cond = AL) { alu_op(ADC , rd, rd, arg, cond); } void adcs(reg_t rd, reg_t rn, const alu2& arg, AG_COND cond = AL) { alu_op(ADCS, rd, rn, arg, cond); } void adcs(reg_t rd, const alu2& arg, AG_COND cond = AL) { alu_op(ADCS, rd, rd, arg, cond); } void sbc (reg_t rd, reg_t rn, const alu2& arg, AG_COND cond = AL) { alu_op(SBC , rd, rn, arg, cond); } void sbc (reg_t rd, const alu2& arg, AG_COND cond = AL) { alu_op(SBC , rd, rd, arg, cond); } void sbcs(reg_t rd, reg_t rn, const alu2& arg, AG_COND cond = AL) { alu_op(SBCS, rd, rn, arg, cond); } void sbcs(reg_t rd, const alu2& arg, AG_COND cond = AL) { alu_op(SBCS, rd, rd, arg, cond); } void rsc (reg_t rd, reg_t rn, const alu2& arg, AG_COND cond = AL) { alu_op(RSC , rd, rn, arg, cond); } void rsc (reg_t rd, const alu2& arg, AG_COND cond = AL) { alu_op(RSC , rd, rd, arg, cond); } void rscs(reg_t rd, reg_t rn, const alu2& arg, AG_COND cond = AL) { alu_op(RSCS, rd, rn, arg, cond); } void rscs(reg_t rd, const alu2& arg, AG_COND cond = AL) { alu_op(RSCS, rd, rd, arg, cond); } void tst ( reg_t rn, const alu2& arg, AG_COND cond = AL) { alu_op(TST , rn, rn, arg, cond); } // 1 void teq ( reg_t rn, const alu2& arg, AG_COND cond = AL) { alu_op(TEQ , rn, rn, arg, cond); } // 1 void cmp ( reg_t rn, const alu2& arg, AG_COND cond = AL) { alu_op(CMP , rn, rn, arg, cond); } // 1 void cmn ( reg_t rn, const alu2& arg, AG_COND cond = AL) { alu_op(CMN , rn, rn, arg, cond); } // 1 void orr (reg_t rd, reg_t rn, const alu2& arg, AG_COND cond = AL) { alu_op(ORR , rd, rn, arg, cond); } void orr (reg_t rd, const alu2& arg, AG_COND cond = AL) { alu_op(ORR , rd, rd, arg, cond); } void orrs(reg_t rd, reg_t rn, const alu2& arg, AG_COND cond = AL) { alu_op(ORRS, rd, rn, arg, cond); } void orrs(reg_t rd, const alu2& arg, AG_COND cond = AL) { alu_op(ORRS, rd, rd, arg, cond); } void mov (reg_t rd, const alu2& arg, AG_COND cond = AL) { alu_op(MOV , rd, rd, arg, cond); } // 2 void movs(reg_t rd, const alu2& arg, AG_COND cond = AL) { alu_op(MOVS, rd, rd, arg, cond); } // 2 void bic (reg_t rd, reg_t rn, const alu2& arg, AG_COND cond = AL) { alu_op(BIC , rd, rn, arg, cond); } void bic (reg_t rd, const alu2& arg, AG_COND cond = AL) { alu_op(BIC , rd, rd, arg, cond); } void bics(reg_t rd, reg_t rn, const alu2& arg, AG_COND cond = AL) { alu_op(BICS, rd, rn, arg, cond); } void bics(reg_t rd, const alu2& arg, AG_COND cond = AL) { alu_op(BICS, rd, rd, arg, cond); } void mvn (reg_t rd, const alu2& arg, AG_COND cond = AL) { alu_op(MVN , rd, rd, arg, cond); } // 2 void mvns(reg_t rd, const alu2& arg, AG_COND cond = AL) { alu_op(MVNS, rd, rd, arg, cond); } // 2 // Code Gen: Memory void mem_op(AG_MEM_OP op, reg_t rd, reg_t rn, const mem2& arg, AG_MEM_FLAGS flags = MEM_NONE, AG_COND cond = AL); void ldr (reg_t rd, reg_t base, const mem2& arg = mem2::imm(0), AG_MEM_FLAGS flags = MEM_NONE, AG_COND cond = AL) { mem_op(LDR , rd, base, arg, flags, cond); } void str (reg_t rd, reg_t base, const mem2& arg = mem2::imm(0), AG_MEM_FLAGS flags = MEM_NONE, AG_COND cond = AL) { mem_op(STR , rd, base, arg, flags, cond); } void ldrb(reg_t rd, reg_t base, const mem2& arg = mem2::imm(0), AG_MEM_FLAGS flags = MEM_NONE, AG_COND cond = AL) { mem_op(LDRB, rd, base, arg, flags, cond); } void strb(reg_t rd, reg_t base, const mem2& arg = mem2::imm(0), AG_MEM_FLAGS flags = MEM_NONE, AG_COND cond = AL) { mem_op(STRB, rd, base, arg, flags, cond); } // Code Gen: Sign Extend void sxtb(reg_t rd, reg_t rm, AG_COND cond = AL) { insert_instruction( 0x06AF0070 | (rd << 12) | rm, cond ); } void sxth(reg_t rd, reg_t rm, AG_COND cond = AL) { insert_instruction( 0x06BF0070 | (rd << 12) | rm, cond ); } void uxtb(reg_t rd, reg_t rm, AG_COND cond = AL) { insert_instruction( 0x06EF0070 | (rd << 12) | rm, cond ); } void uxth(reg_t rd, reg_t rm, AG_COND cond = AL) { insert_instruction( 0x06FF0070 | (rd << 12) | rm, cond ); } // Code Gen: Other void set_status(reg_t source_reg, AG_COND cond = AL) { insert_instruction( 0x0128F000 | source_reg, cond ); } void get_status(reg_t dest_reg, AG_COND cond = AL) { insert_instruction( 0x010F0000 | (dest_reg << 12), cond ); } void bx(reg_t target_reg, AG_COND cond = AL) { insert_instruction( 0x012FFF10 | target_reg, cond ); } void blx(reg_t target_reg, AG_COND cond = AL) { insert_instruction( 0x012FFF30 | target_reg, cond ); } void push(uint16_t regs, AG_COND cond = AL) { insert_instruction( 0x092D0000 | regs, cond ); } void pop(uint16_t regs, AG_COND cond = AL) { insert_instruction( 0x08BD0000 | regs, cond ); } void b(const char* target, AG_COND cond = AL); // Inserts a movw; movt pair to load the constant, omits movt is constant fits in 16 bits. void load_constant(reg_t target_reg, uint32_t constant, AG_COND cond = AL); void insert_constants(); void jmp(uint32_t offset); void resolve_jmp(uint32_t instruction, uint32_t offset); uint32_t get_next_instruction() { return next_instruction; }; private: const uint32_t instruction_count; uint32_t* instructions; uint32_t next_instruction; uint32_t flush_start; uint32_t literals[128][2]; uint32_t literal_count; static const uint32_t TARGET_COUNT = 16; struct target { const char* name; uint32_t position; }; target labels[TARGET_COUNT]; target branches[TARGET_COUNT]; #if defined(VITA) SceUID block; #endif }; } // namespace arm_gen #endif desmume/src/utils/AsmJit/core/stringbuilder.h000664 001750 001750 00000015613 12755534123 022452 0ustar00sergiosergio000000 000000 // [AsmJit] // Complete JIT Assembler for C++ Language. // // [License] // Zlib - See COPYING file in this package. #include // [Guard] #ifndef _ASMJIT_CORE_STRINGBUILDER_H #define _ASMJIT_CORE_STRINGBUILDER_H // [Dependencies - AsmJit] #include "../core/assert.h" #include "../core/defs.h" namespace AsmJit { //! @addtogroup AsmJit_Core //! @{ // ============================================================================ // [AsmJit::StringBuilder] // ============================================================================ //! @brief String builder. //! //! String builder was designed to be able to build a string using append like //! operation to append numbers, other strings, or signle characters. It can //! allocate it's own buffer or use a buffer created on the stack. //! //! String builder contains method specific to AsmJit functionality, used for //! logging or HTML output. struct StringBuilder { ASMJIT_NO_COPY(StringBuilder) // -------------------------------------------------------------------------- // [Construction / Destruction] // -------------------------------------------------------------------------- ASMJIT_API StringBuilder(); ASMJIT_API ~StringBuilder(); inline StringBuilder(const _DontInitialize&) {} // -------------------------------------------------------------------------- // [Accessors] // -------------------------------------------------------------------------- //! @brief Get string builder capacity. inline size_t getCapacity() const { return _capacity; } //! @brief Get length. inline size_t getLength() const { return _length; } //! @brief Get null-terminated string data. inline char* getData() { return _data; } //! @brief Get null-terminated string data (const). inline const char* getData() const { return _data; } // -------------------------------------------------------------------------- // [Prepare / Reserve] // -------------------------------------------------------------------------- //! @brief Prepare to set/append. ASMJIT_API char* prepare(uint32_t op, size_t len); //! @brief Reserve @a to bytes in string builder. ASMJIT_API bool reserve(size_t to); // -------------------------------------------------------------------------- // [Clear] // -------------------------------------------------------------------------- //! @brief Clear the content in String builder. ASMJIT_API void clear(); // -------------------------------------------------------------------------- // [Methods] // -------------------------------------------------------------------------- ASMJIT_API bool _opString(uint32_t op, const char* str, size_t len = kInvalidSize); ASMJIT_API bool _opVFormat(uint32_t op, const char* fmt, va_list ap); ASMJIT_API bool _opChars(uint32_t op, char c, size_t len); ASMJIT_API bool _opNumber(uint32_t op, uint64_t i, uint32_t base = 0, size_t width = 0, uint32_t flags = 0); ASMJIT_API bool _opHex(uint32_t op, const void* data, size_t length); //! @brief Replace the current content by @a str of @a len. inline bool setString(const char* str, size_t len = kInvalidSize) { return _opString(kStringBuilderOpSet, str, len); } //! @brief Replace the current content by formatted string @a fmt. inline bool setVFormat(const char* fmt, va_list ap) { return _opVFormat(kStringBuilderOpSet, fmt, ap); } //! @brief Replace the current content by formatted string @a fmt. ASMJIT_API bool setFormat(const char* fmt, ...); //! @brief Replace the current content by @a c of @a len. inline bool setChars(char c, size_t len) { return _opChars(kStringBuilderOpSet, c, len); } //! @brief Replace the current content by @a i.. inline bool setNumber(uint64_t i, uint32_t base = 0, size_t width = 0, uint32_t flags = 0) { return _opNumber(kStringBuilderOpSet, i, base, width, flags); } //! @brief Append @a str of @a len. inline bool appendString(const char* str, size_t len = kInvalidSize) { return _opString(kStringBuilderOpAppend, str, len); } //! @brief Append a formatted string @a fmt to the current content. inline bool appendVFormat(const char* fmt, va_list ap) { return _opVFormat(kStringBuilderOpAppend, fmt, ap); } //! @brief Append a formatted string @a fmt to the current content. ASMJIT_API bool appendFormat(const char* fmt, ...); //! @brief Append @a c of @a len. inline bool appendChars(char c, size_t len) { return _opChars(kStringBuilderOpAppend, c, len); } //! @brief Append @a i. inline bool appendNumber(uint64_t i, uint32_t base = 0, size_t width = 0, uint32_t flags = 0) { return _opNumber(kStringBuilderOpAppend, i, base, width, flags); } //! @brief Check for equality with other @a str. ASMJIT_API bool eq(const char* str, size_t len = kInvalidSize) const; //! @brief Check for equality with StringBuilder @a other. inline bool eq(const StringBuilder& other) const { return eq(other._data); } // -------------------------------------------------------------------------- // [Operator Overload] // -------------------------------------------------------------------------- inline bool operator==(const StringBuilder& other) const { return eq(other); } inline bool operator!=(const StringBuilder& other) const { return !eq(other); } inline bool operator==(const char* str) const { return eq(str); } inline bool operator!=(const char* str) const { return !eq(str); } // -------------------------------------------------------------------------- // [Members] // -------------------------------------------------------------------------- //! @brief String data. char* _data; //! @brief Length. size_t _length; //! @brief Capacity. size_t _capacity; //! @brief Whether the string can be freed. size_t _canFree; }; // ============================================================================ // [AsmJit::StringBuilderT] // ============================================================================ template struct StringBuilderT : public StringBuilder { ASMJIT_NO_COPY(StringBuilderT) // -------------------------------------------------------------------------- // [Construction / Destruction] // -------------------------------------------------------------------------- inline StringBuilderT() : StringBuilder(_DontInitialize()) { _data = _embeddedData; _data[0] = 0; _length = 0; _capacity = 0; _canFree = false; } // -------------------------------------------------------------------------- // [Members] // -------------------------------------------------------------------------- //! @brief Embedded data. char _embeddedData[(N + sizeof(uintptr_t)) & ~(sizeof(uintptr_t) - 1)]; }; //! @} } // AsmJit namespace #endif // _ASMJIT_CORE_STRINGBUILDER_H desmume/src/registers.h000664 001750 001750 00000047161 12755534123 016330 0ustar00sergiosergio000000 000000 /* Copyright (C) 2006 Theo Berkau Copyright (C) 2006-2011 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the this software. If not, see . */ #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_DMA_CONTROL_MIN 0x040000B0 #define REG_DMA0SAD 0x040000B0 #define REG_DMA0SADL 0x040000B0 #define REG_DMA0SADH 0x040000B2 #define REG_DMA0DAD 0x040000B4 #define REG_DMA0DADL 0x040000B4 #define REG_DMA0DADH 0x040000B6 #define REG_DMA0CNTL 0x040000B8 #define REG_DMA0CNTH 0x040000BA #define REG_DMA1SAD 0x040000BC #define REG_DMA1SADL 0x040000BC #define REG_DMA1SADH 0x040000BE #define REG_DMA1DAD 0x040000C0 #define REG_DMA1DADL 0x040000C0 #define REG_DMA1DADH 0x040000C2 #define REG_DMA1CNTL 0x040000C4 #define REG_DMA1CNTH 0x040000C6 #define REG_DMA2SAD 0x040000C8 #define REG_DMA2SADL 0x040000C8 #define REG_DMA2SADH 0x040000CA #define REG_DMA2DAD 0x040000CC #define REG_DMA2DADL 0x040000CC #define REG_DMA2DADH 0x040000CE #define REG_DMA2CNTL 0x040000D0 #define REG_DMA2CNTH 0x040000D2 #define REG_DMA3SAD 0x040000D4 #define REG_DMA3SADL 0x040000D4 #define REG_DMA3SADH 0x040000D6 #define REG_DMA3DAD 0x040000D8 #define REG_DMA3DADL 0x040000D8 #define REG_DMA3DADH 0x040000DA #define REG_DMA3CNTL 0x040000DC #define REG_DMA3CNTH 0x040000DE #define _REG_DMA_CONTROL_MAX 0x040000DF #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 0x040001BA #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 REG_DISPA_DISP3DCNT_BIT_RDLINES_UNDERFLOW 0x1000 #define REG_DISPA_DISP3DCNT_BIT_RAM_OVERFLOW 0x2000 #define REG_DISPA_DISP3DCNT_BITS_ACK (REG_DISPA_DISP3DCNT_BIT_RDLINES_UNDERFLOW|REG_DISPA_DISP3DCNT_BIT_RAM_OVERFLOW) #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 //DSI #define REG_DSIMODE 0x04004000 #define IPCFIFOCNT_SENDEMPTY 0x0001 #define IPCFIFOCNT_SENDFULL 0x0002 #define IPCFIFOCNT_SENDIRQEN 0x0004 #define IPCFIFOCNT_SENDCLEAR 0x0008 #define IPCFIFOCNT_RECVEMPTY 0x0100 #define IPCFIFOCNT_RECVFULL 0x0200 #define IPCFIFOCNT_RECVIRQEN 0x0400 #define IPCFIFOCNT_FIFOERROR 0x4000 #define IPCFIFOCNT_FIFOENABLE 0x8000 #define IPCFIFOCNT_WRITEABLE (IPCFIFOCNT_SENDIRQEN | IPCFIFOCNT_RECVIRQEN | IPCFIFOCNT_FIFOENABLE) #define IPCSYNC_IRQ_SEND 0x2000 #define IPCSYNC_IRQ_RECV 0x4000 #define IRQ_BIT_LCD_VBLANK 0 #define IRQ_BIT_LCD_HBLANK 1 #define IRQ_BIT_LCD_VMATCH 2 #define IRQ_BIT_TIMER_0 3 #define IRQ_BIT_TIMER_1 4 #define IRQ_BIT_TIMER_2 5 #define IRQ_BIT_TIMER_3 6 #define IRQ_BIT_ARM7_SIO 7 #define IRQ_BIT_DMA_0 8 #define IRQ_BIT_DMA_2 9 #define IRQ_BIT_DMA_3 10 #define IRQ_BIT_DMA_4 11 #define IRQ_BIT_KEYPAD 12 #define IRQ_BIT_GAMEPAK 13 #define IRQ_BIT_IPCSYNC 16 #define IRQ_BIT_IPCFIFO_SENDEMPTY 17 #define IRQ_BIT_IPCFIFO_RECVNONEMPTY 18 #define IRQ_BIT_GC_TRANSFER_COMPLETE 19 #define IRQ_BIT_GC_IREQ_MC 20 #define IRQ_BIT_ARM9_GXFIFO 21 #define IRQ_BIT_ARM7_FOLD 22 #define IRQ_BIT_ARM7_SPI 23 #define IRQ_BIT_ARM7_WIFI 24 #define IRQ_MASK_LCD_VBLANK (1<<0) #define IRQ_MASK_LCD_HBLANK (1<<1) #define IRQ_MASK_LCD_VMATCH (1<<2) #define IRQ_MASK_TIMER_0 (1<<3) #define IRQ_MASK_TIMER_1 (1<<4) #define IRQ_MASK_TIMER_2 (1<<5) #define IRQ_MASK_TIMER_3 (1<<6) #define IRQ_MASK_ARM7_SIO (1<<7) #define IRQ_MASK_DMA_0 (1<<8) #define IRQ_MASK_DMA_2 (1<<9) #define IRQ_MASK_DMA_3 (1<<10) #define IRQ_MASK_DMA_4 (1<<11) #define IRQ_MASK_KEYPAD (1<<12) #define IRQ_MASK_GAMEPAK (1<<13) #define IRQ_MASK_IPCSYNC (1<<16) #define IRQ_MASK_IPCFIFO_SENDEMPTY (1<<17) #define IRQ_MASK_IPCFIFO_RECVNONEMPTY (1<<18) #define IRQ_MASK_GC_TRANSFER_COMPLETE (1<<19) #define IRQ_MASK_GC_IREQ_MC (1<<20) #define IRQ_MASK_ARM9_GXFIFO (1<<21) #define IRQ_MASK_ARM7_FOLD (1<<22) #define IRQ_MASK_ARM7_SPI (1<<23) #define IRQ_MASK_ARM7_WIFI (1<<24) #define TSC_MEASURE_TEMP1 0 #define TSC_MEASURE_Y 1 #define TSC_MEASURE_BATTERY 2 #define TSC_MEASURE_Z1 3 #define TSC_MEASURE_Z2 4 #define TSC_MEASURE_X 5 #define TSC_MEASURE_AUX 6 #define TSC_MEASURE_TEMP2 7 #define EXMEMCNT_MASK_SLOT2_ARM7 (1<<7) #define EXMEMCNT_MASK_SLOT2_SRAM_TIME (3) #define EXMEMCNT_MASK_SLOT2_ROM_1ST_TIME (3<<2) #define EXMEMCNT_MASK_SLOT2_ROM_2ND_TIME (1<<4) #define EXMEMCNT_MASK_SLOT2_CLOCKRATE (3<<5) #define SPI_DEVICE_POWERMAN 0 #define SPI_DEVICE_FIRMWARE 1 #define SPI_DEVICE_TOUCHSCREEN 2 #define SPI_BAUDRATE_4MHZ 0 #define SPI_BAUDRATE_2MHZ 1 #define SPI_BAUDRATE_1MHZ 2 #define SPI_BAUDRATE_512KHZ 3 #endif desmume/src/utils/libfat/filetime.c000664 001750 001750 00000006353 12755534123 020511 0ustar00sergiosergio000000 000000 /* filetime.c Conversion of file time and date values to various other types Copyright (c) 2006 Michael "Chishm" Chisholm Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. 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. 3. The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 "filetime.h" #include "common.h" #define MAX_HOUR 23 #define MAX_MINUTE 59 #define MAX_SECOND 59 #define MAX_MONTH 11 #define MIN_MONTH 0 #define MAX_DAY 31 #define MIN_DAY 1 uint16_t _FAT_filetime_getTimeFromRTC (void) { #ifdef USE_RTC_TIME struct tm timeParts; time_t epochTime; if (time(&epochTime) == (time_t)-1) { return 0; } localtime_r(&epochTime, &timeParts); // Check that the values are all in range. // If they are not, return 0 (no timestamp) if ((timeParts.tm_hour < 0) || (timeParts.tm_hour > MAX_HOUR)) return 0; if ((timeParts.tm_min < 0) || (timeParts.tm_min > MAX_MINUTE)) return 0; if ((timeParts.tm_sec < 0) || (timeParts.tm_sec > MAX_SECOND)) return 0; return ( ((timeParts.tm_hour & 0x1F) << 11) | ((timeParts.tm_min & 0x3F) << 5) | ((timeParts.tm_sec >> 1) & 0x1F) ); #else return 0; #endif } uint16_t _FAT_filetime_getDateFromRTC (void) { #ifdef USE_RTC_TIME struct tm timeParts; time_t epochTime; if (time(&epochTime) == (time_t)-1) { return 0; } localtime_r(&epochTime, &timeParts); if ((timeParts.tm_mon < MIN_MONTH) || (timeParts.tm_mon > MAX_MONTH)) return 0; if ((timeParts.tm_mday < MIN_DAY) || (timeParts.tm_mday > MAX_DAY)) return 0; return ( (((timeParts.tm_year - 80) & 0x7F) <<9) | // Adjust for MS-FAT base year (1980 vs 1900 for tm_year) (((timeParts.tm_mon + 1) & 0xF) << 5) | (timeParts.tm_mday & 0x1F) ); #else return 0; #endif } time_t _FAT_filetime_to_time_t (uint16_t t, uint16_t d) { struct tm timeParts; timeParts.tm_hour = t >> 11; timeParts.tm_min = (t >> 5) & 0x3F; timeParts.tm_sec = (t & 0x1F) << 1; timeParts.tm_mday = d & 0x1F; timeParts.tm_mon = ((d >> 5) & 0x0F) - 1; timeParts.tm_year = (d >> 9) + 80; timeParts.tm_isdst = 0; return mktime(&timeParts); } desmume/src/libretro-common/include/streams/file_stream.h000664 001750 001750 00000005235 12755534123 025020 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2016 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (file_stream.h). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef __LIBRETRO_SDK_FILE_STREAM_H #define __LIBRETRO_SDK_FILE_STREAM_H #include #include #include #include #include RETRO_BEGIN_DECLS typedef struct RFILE RFILE; enum { RFILE_MODE_READ = 0, RFILE_MODE_READ_TEXT, RFILE_MODE_WRITE, RFILE_MODE_READ_WRITE, /* There is no garantee these requests will be attended. */ RFILE_HINT_UNBUFFERED = 1<<8, RFILE_HINT_MMAP = 1<<9 /* requires RFILE_MODE_READ */ }; RFILE *filestream_open(const char *path, unsigned mode, ssize_t len); ssize_t filestream_seek(RFILE *stream, ssize_t offset, int whence); ssize_t filestream_read(RFILE *stream, void *data, size_t len); ssize_t filestream_write(RFILE *stream, const void *data, size_t len); ssize_t filestream_tell(RFILE *stream); void filestream_rewind(RFILE *stream); int filestream_close(RFILE *stream); int filestream_read_file(const char *path, void **buf, ssize_t *len); char *filestream_gets(RFILE *stream, char *s, size_t len); char *filestream_getline(RFILE *stream); int filestream_getc(RFILE *stream); int filestream_eof(RFILE *stream); bool filestream_write_file(const char *path, const void *data, ssize_t size); int filestream_putc(RFILE *stream, int c); int filestream_get_fd(RFILE *stream); RETRO_END_DECLS #endif desmume/src/PACKED.h000664 001750 001750 00000000307 12755534123 015237 0ustar00sergiosergio000000 000000 #ifndef __GNUC__ #pragma pack(push, 1) #pragma warning(disable : 4103) #endif #ifndef __PACKED #ifdef __GNUC__ #define __PACKED __attribute__((__packed__)) #else #define __PACKED #endif #endif desmume/src/libretro-common/include/hash/000700 001750 001750 00000000000 12756420131 021573 5ustar00sergiosergio000000 000000 desmume/src/libretro-common/include/retro_assert.h000664 001750 001750 00000003211 12755534123 023554 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2016 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (retro_assert.h). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef __RETRO_ASSERT_H #define __RETRO_ASSERT_H #include #ifdef RARCH_INTERNAL #define retro_assert(cond) do { \ if (!(cond)) { printf("Assertion failed at %s:%d.\n", __FILE__, __LINE__); abort(); } \ } while(0) #else #define retro_assert(cond) assert(cond) #endif #endif desmume/src/utils/libfat/bit_ops.h000664 001750 001750 00000004736 12755534123 020362 0ustar00sergiosergio000000 000000 /* bit_ops.h Functions for dealing with conversion of data between types Copyright (c) 2006 Michael "Chishm" Chisholm Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. 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. 3. The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. */ #ifndef _BIT_OPS_H #define _BIT_OPS_H #include #include /*----------------------------------------------------------------- Functions to deal with little endian values stored in uint8_t arrays -----------------------------------------------------------------*/ static INLINE uint16_t u8array_to_u16 (const uint8_t* item, int offset) { return ( item[offset] | (item[offset + 1] << 8)); } static INLINE uint32_t u8array_to_u32 (const uint8_t* item, int offset) { return ( item[offset] | (item[offset + 1] << 8) | (item[offset + 2] << 16) | (item[offset + 3] << 24)); } static INLINE void u16_to_u8array (uint8_t* item, int offset, uint16_t value){ item[offset] = (uint8_t) value; item[offset + 1] = (uint8_t)(value >> 8); } static INLINE void u32_to_u8array (uint8_t* item, int offset, uint32_t value) { item[offset] = (uint8_t) value; item[offset + 1] = (uint8_t)(value >> 8); item[offset + 2] = (uint8_t)(value >> 16); item[offset + 3] = (uint8_t)(value >> 24); } #endif // _BIT_OPS_H desmume/src/libretro-common/glsym/glsym_gl.c000664 001750 001750 00000261545 12755534123 022400 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2015 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this libretro SDK code part (glsym). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include #include #define SYM(x) { "gl" #x, &(gl##x) } const struct rglgen_sym_map rglgen_symbol_map[] = { SYM(DrawRangeElements), SYM(TexImage3D), SYM(TexSubImage3D), SYM(CopyTexSubImage3D), SYM(ActiveTexture), SYM(SampleCoverage), SYM(CompressedTexImage3D), SYM(CompressedTexImage2D), SYM(CompressedTexImage1D), SYM(CompressedTexSubImage3D), SYM(CompressedTexSubImage2D), SYM(CompressedTexSubImage1D), SYM(GetCompressedTexImage), SYM(ClientActiveTexture), SYM(MultiTexCoord1d), SYM(MultiTexCoord1dv), SYM(MultiTexCoord1f), SYM(MultiTexCoord1fv), SYM(MultiTexCoord1i), SYM(MultiTexCoord1iv), SYM(MultiTexCoord1s), SYM(MultiTexCoord1sv), SYM(MultiTexCoord2d), SYM(MultiTexCoord2dv), SYM(MultiTexCoord2f), SYM(MultiTexCoord2fv), SYM(MultiTexCoord2i), SYM(MultiTexCoord2iv), SYM(MultiTexCoord2s), SYM(MultiTexCoord2sv), SYM(MultiTexCoord3d), SYM(MultiTexCoord3dv), SYM(MultiTexCoord3f), SYM(MultiTexCoord3fv), SYM(MultiTexCoord3i), SYM(MultiTexCoord3iv), SYM(MultiTexCoord3s), SYM(MultiTexCoord3sv), SYM(MultiTexCoord4d), SYM(MultiTexCoord4dv), SYM(MultiTexCoord4f), SYM(MultiTexCoord4fv), SYM(MultiTexCoord4i), SYM(MultiTexCoord4iv), SYM(MultiTexCoord4s), SYM(MultiTexCoord4sv), SYM(LoadTransposeMatrixf), SYM(LoadTransposeMatrixd), SYM(MultTransposeMatrixf), SYM(MultTransposeMatrixd), SYM(BlendFuncSeparate), SYM(MultiDrawArrays), SYM(MultiDrawElements), SYM(PointParameterf), SYM(PointParameterfv), SYM(PointParameteri), SYM(PointParameteriv), SYM(FogCoordf), SYM(FogCoordfv), SYM(FogCoordd), SYM(FogCoorddv), SYM(FogCoordPointer), SYM(SecondaryColor3b), SYM(SecondaryColor3bv), SYM(SecondaryColor3d), SYM(SecondaryColor3dv), SYM(SecondaryColor3f), SYM(SecondaryColor3fv), SYM(SecondaryColor3i), SYM(SecondaryColor3iv), SYM(SecondaryColor3s), SYM(SecondaryColor3sv), SYM(SecondaryColor3ub), SYM(SecondaryColor3ubv), SYM(SecondaryColor3ui), SYM(SecondaryColor3uiv), SYM(SecondaryColor3us), SYM(SecondaryColor3usv), SYM(SecondaryColorPointer), SYM(WindowPos2d), SYM(WindowPos2dv), SYM(WindowPos2f), SYM(WindowPos2fv), SYM(WindowPos2i), SYM(WindowPos2iv), SYM(WindowPos2s), SYM(WindowPos2sv), SYM(WindowPos3d), SYM(WindowPos3dv), SYM(WindowPos3f), SYM(WindowPos3fv), SYM(WindowPos3i), SYM(WindowPos3iv), SYM(WindowPos3s), SYM(WindowPos3sv), SYM(BlendColor), SYM(BlendEquation), SYM(GenQueries), SYM(DeleteQueries), SYM(IsQuery), SYM(BeginQuery), SYM(EndQuery), SYM(GetQueryiv), SYM(GetQueryObjectiv), SYM(GetQueryObjectuiv), SYM(BindBuffer), SYM(DeleteBuffers), SYM(GenBuffers), SYM(IsBuffer), SYM(BufferData), SYM(BufferSubData), SYM(GetBufferSubData), SYM(MapBuffer), SYM(UnmapBuffer), SYM(GetBufferParameteriv), SYM(GetBufferPointerv), SYM(BlendEquationSeparate), SYM(DrawBuffers), SYM(StencilOpSeparate), SYM(StencilFuncSeparate), SYM(StencilMaskSeparate), SYM(AttachShader), SYM(BindAttribLocation), SYM(CompileShader), SYM(CreateProgram), SYM(CreateShader), SYM(DeleteProgram), SYM(DeleteShader), SYM(DetachShader), SYM(DisableVertexAttribArray), SYM(EnableVertexAttribArray), SYM(GetActiveAttrib), SYM(GetActiveUniform), SYM(GetAttachedShaders), SYM(GetAttribLocation), SYM(GetProgramiv), SYM(GetProgramInfoLog), SYM(GetShaderiv), SYM(GetShaderInfoLog), SYM(GetShaderSource), SYM(GetUniformLocation), SYM(GetUniformfv), SYM(GetUniformiv), SYM(GetVertexAttribdv), SYM(GetVertexAttribfv), SYM(GetVertexAttribiv), SYM(GetVertexAttribPointerv), SYM(IsProgram), SYM(IsShader), SYM(LinkProgram), SYM(ShaderSource), SYM(UseProgram), SYM(Uniform1f), SYM(Uniform2f), SYM(Uniform3f), SYM(Uniform4f), SYM(Uniform1i), SYM(Uniform2i), SYM(Uniform3i), SYM(Uniform4i), SYM(Uniform1fv), SYM(Uniform2fv), SYM(Uniform3fv), SYM(Uniform4fv), SYM(Uniform1iv), SYM(Uniform2iv), SYM(Uniform3iv), SYM(Uniform4iv), SYM(UniformMatrix2fv), SYM(UniformMatrix3fv), SYM(UniformMatrix4fv), SYM(ValidateProgram), SYM(VertexAttrib1d), SYM(VertexAttrib1dv), SYM(VertexAttrib1f), SYM(VertexAttrib1fv), SYM(VertexAttrib1s), SYM(VertexAttrib1sv), SYM(VertexAttrib2d), SYM(VertexAttrib2dv), SYM(VertexAttrib2f), SYM(VertexAttrib2fv), SYM(VertexAttrib2s), SYM(VertexAttrib2sv), SYM(VertexAttrib3d), SYM(VertexAttrib3dv), SYM(VertexAttrib3f), SYM(VertexAttrib3fv), SYM(VertexAttrib3s), SYM(VertexAttrib3sv), SYM(VertexAttrib4Nbv), SYM(VertexAttrib4Niv), SYM(VertexAttrib4Nsv), SYM(VertexAttrib4Nub), SYM(VertexAttrib4Nubv), SYM(VertexAttrib4Nuiv), SYM(VertexAttrib4Nusv), SYM(VertexAttrib4bv), SYM(VertexAttrib4d), SYM(VertexAttrib4dv), SYM(VertexAttrib4f), SYM(VertexAttrib4fv), SYM(VertexAttrib4iv), SYM(VertexAttrib4s), SYM(VertexAttrib4sv), SYM(VertexAttrib4ubv), SYM(VertexAttrib4uiv), SYM(VertexAttrib4usv), SYM(VertexAttribPointer), SYM(UniformMatrix2x3fv), SYM(UniformMatrix3x2fv), SYM(UniformMatrix2x4fv), SYM(UniformMatrix4x2fv), SYM(UniformMatrix3x4fv), SYM(UniformMatrix4x3fv), SYM(ColorMaski), SYM(GetBooleani_v), SYM(GetIntegeri_v), SYM(Enablei), SYM(Disablei), SYM(IsEnabledi), SYM(BeginTransformFeedback), SYM(EndTransformFeedback), SYM(BindBufferRange), SYM(BindBufferBase), SYM(TransformFeedbackVaryings), SYM(GetTransformFeedbackVarying), SYM(ClampColor), SYM(BeginConditionalRender), SYM(EndConditionalRender), SYM(VertexAttribIPointer), SYM(GetVertexAttribIiv), SYM(GetVertexAttribIuiv), SYM(VertexAttribI1i), SYM(VertexAttribI2i), SYM(VertexAttribI3i), SYM(VertexAttribI4i), SYM(VertexAttribI1ui), SYM(VertexAttribI2ui), SYM(VertexAttribI3ui), SYM(VertexAttribI4ui), SYM(VertexAttribI1iv), SYM(VertexAttribI2iv), SYM(VertexAttribI3iv), SYM(VertexAttribI4iv), SYM(VertexAttribI1uiv), SYM(VertexAttribI2uiv), SYM(VertexAttribI3uiv), SYM(VertexAttribI4uiv), SYM(VertexAttribI4bv), SYM(VertexAttribI4sv), SYM(VertexAttribI4ubv), SYM(VertexAttribI4usv), SYM(GetUniformuiv), SYM(BindFragDataLocation), SYM(GetFragDataLocation), SYM(Uniform1ui), SYM(Uniform2ui), SYM(Uniform3ui), SYM(Uniform4ui), SYM(Uniform1uiv), SYM(Uniform2uiv), SYM(Uniform3uiv), SYM(Uniform4uiv), SYM(TexParameterIiv), SYM(TexParameterIuiv), SYM(GetTexParameterIiv), SYM(GetTexParameterIuiv), SYM(ClearBufferiv), SYM(ClearBufferuiv), SYM(ClearBufferfv), SYM(ClearBufferfi), SYM(GetStringi), SYM(IsRenderbuffer), SYM(BindRenderbuffer), SYM(DeleteRenderbuffers), SYM(GenRenderbuffers), SYM(RenderbufferStorage), SYM(GetRenderbufferParameteriv), SYM(IsFramebuffer), SYM(BindFramebuffer), SYM(DeleteFramebuffers), SYM(GenFramebuffers), SYM(CheckFramebufferStatus), SYM(FramebufferTexture1D), SYM(FramebufferTexture2D), SYM(FramebufferTexture3D), SYM(FramebufferRenderbuffer), SYM(GetFramebufferAttachmentParameteriv), SYM(GenerateMipmap), SYM(BlitFramebuffer), SYM(RenderbufferStorageMultisample), SYM(FramebufferTextureLayer), SYM(MapBufferRange), SYM(FlushMappedBufferRange), SYM(BindVertexArray), SYM(DeleteVertexArrays), SYM(GenVertexArrays), SYM(IsVertexArray), SYM(DrawArraysInstanced), SYM(DrawElementsInstanced), SYM(TexBuffer), SYM(PrimitiveRestartIndex), SYM(CopyBufferSubData), SYM(GetUniformIndices), SYM(GetActiveUniformsiv), SYM(GetActiveUniformName), SYM(GetUniformBlockIndex), SYM(GetActiveUniformBlockiv), SYM(GetActiveUniformBlockName), SYM(UniformBlockBinding), SYM(DrawElementsBaseVertex), SYM(DrawRangeElementsBaseVertex), SYM(DrawElementsInstancedBaseVertex), SYM(MultiDrawElementsBaseVertex), SYM(ProvokingVertex), SYM(FenceSync), SYM(IsSync), SYM(DeleteSync), SYM(ClientWaitSync), SYM(WaitSync), SYM(GetInteger64v), SYM(GetSynciv), SYM(GetInteger64i_v), SYM(GetBufferParameteri64v), SYM(FramebufferTexture), SYM(TexImage2DMultisample), SYM(TexImage3DMultisample), SYM(GetMultisamplefv), SYM(SampleMaski), SYM(BindFragDataLocationIndexed), SYM(GetFragDataIndex), SYM(GenSamplers), SYM(DeleteSamplers), SYM(IsSampler), SYM(BindSampler), SYM(SamplerParameteri), SYM(SamplerParameteriv), SYM(SamplerParameterf), SYM(SamplerParameterfv), SYM(SamplerParameterIiv), SYM(SamplerParameterIuiv), SYM(GetSamplerParameteriv), SYM(GetSamplerParameterIiv), SYM(GetSamplerParameterfv), SYM(GetSamplerParameterIuiv), SYM(QueryCounter), SYM(GetQueryObjecti64v), SYM(GetQueryObjectui64v), SYM(VertexAttribDivisor), SYM(VertexAttribP1ui), SYM(VertexAttribP1uiv), SYM(VertexAttribP2ui), SYM(VertexAttribP2uiv), SYM(VertexAttribP3ui), SYM(VertexAttribP3uiv), SYM(VertexAttribP4ui), SYM(VertexAttribP4uiv), SYM(VertexP2ui), SYM(VertexP2uiv), SYM(VertexP3ui), SYM(VertexP3uiv), SYM(VertexP4ui), SYM(VertexP4uiv), SYM(TexCoordP1ui), SYM(TexCoordP1uiv), SYM(TexCoordP2ui), SYM(TexCoordP2uiv), SYM(TexCoordP3ui), SYM(TexCoordP3uiv), SYM(TexCoordP4ui), SYM(TexCoordP4uiv), SYM(MultiTexCoordP1ui), SYM(MultiTexCoordP1uiv), SYM(MultiTexCoordP2ui), SYM(MultiTexCoordP2uiv), SYM(MultiTexCoordP3ui), SYM(MultiTexCoordP3uiv), SYM(MultiTexCoordP4ui), SYM(MultiTexCoordP4uiv), SYM(NormalP3ui), SYM(NormalP3uiv), SYM(ColorP3ui), SYM(ColorP3uiv), SYM(ColorP4ui), SYM(ColorP4uiv), SYM(SecondaryColorP3ui), SYM(SecondaryColorP3uiv), SYM(MinSampleShading), SYM(BlendEquationi), SYM(BlendEquationSeparatei), SYM(BlendFunci), SYM(BlendFuncSeparatei), SYM(DrawArraysIndirect), SYM(DrawElementsIndirect), SYM(Uniform1d), SYM(Uniform2d), SYM(Uniform3d), SYM(Uniform4d), SYM(Uniform1dv), SYM(Uniform2dv), SYM(Uniform3dv), SYM(Uniform4dv), SYM(UniformMatrix2dv), SYM(UniformMatrix3dv), SYM(UniformMatrix4dv), SYM(UniformMatrix2x3dv), SYM(UniformMatrix2x4dv), SYM(UniformMatrix3x2dv), SYM(UniformMatrix3x4dv), SYM(UniformMatrix4x2dv), SYM(UniformMatrix4x3dv), SYM(GetUniformdv), SYM(GetSubroutineUniformLocation), SYM(GetSubroutineIndex), SYM(GetActiveSubroutineUniformiv), SYM(GetActiveSubroutineUniformName), SYM(GetActiveSubroutineName), SYM(UniformSubroutinesuiv), SYM(GetUniformSubroutineuiv), SYM(GetProgramStageiv), SYM(PatchParameteri), SYM(PatchParameterfv), SYM(BindTransformFeedback), SYM(DeleteTransformFeedbacks), SYM(GenTransformFeedbacks), SYM(IsTransformFeedback), SYM(PauseTransformFeedback), SYM(ResumeTransformFeedback), SYM(DrawTransformFeedback), SYM(DrawTransformFeedbackStream), SYM(BeginQueryIndexed), SYM(EndQueryIndexed), SYM(GetQueryIndexediv), SYM(ReleaseShaderCompiler), SYM(ShaderBinary), SYM(GetShaderPrecisionFormat), SYM(DepthRangef), SYM(ClearDepthf), SYM(GetProgramBinary), SYM(ProgramBinary), SYM(ProgramParameteri), SYM(UseProgramStages), SYM(ActiveShaderProgram), SYM(CreateShaderProgramv), SYM(BindProgramPipeline), SYM(DeleteProgramPipelines), SYM(GenProgramPipelines), SYM(IsProgramPipeline), SYM(GetProgramPipelineiv), SYM(ProgramUniform1i), SYM(ProgramUniform1iv), SYM(ProgramUniform1f), SYM(ProgramUniform1fv), SYM(ProgramUniform1d), SYM(ProgramUniform1dv), SYM(ProgramUniform1ui), SYM(ProgramUniform1uiv), SYM(ProgramUniform2i), SYM(ProgramUniform2iv), SYM(ProgramUniform2f), SYM(ProgramUniform2fv), SYM(ProgramUniform2d), SYM(ProgramUniform2dv), SYM(ProgramUniform2ui), SYM(ProgramUniform2uiv), SYM(ProgramUniform3i), SYM(ProgramUniform3iv), SYM(ProgramUniform3f), SYM(ProgramUniform3fv), SYM(ProgramUniform3d), SYM(ProgramUniform3dv), SYM(ProgramUniform3ui), SYM(ProgramUniform3uiv), SYM(ProgramUniform4i), SYM(ProgramUniform4iv), SYM(ProgramUniform4f), SYM(ProgramUniform4fv), SYM(ProgramUniform4d), SYM(ProgramUniform4dv), SYM(ProgramUniform4ui), SYM(ProgramUniform4uiv), SYM(ProgramUniformMatrix2fv), SYM(ProgramUniformMatrix3fv), SYM(ProgramUniformMatrix4fv), SYM(ProgramUniformMatrix2dv), SYM(ProgramUniformMatrix3dv), SYM(ProgramUniformMatrix4dv), SYM(ProgramUniformMatrix2x3fv), SYM(ProgramUniformMatrix3x2fv), SYM(ProgramUniformMatrix2x4fv), SYM(ProgramUniformMatrix4x2fv), SYM(ProgramUniformMatrix3x4fv), SYM(ProgramUniformMatrix4x3fv), SYM(ProgramUniformMatrix2x3dv), SYM(ProgramUniformMatrix3x2dv), SYM(ProgramUniformMatrix2x4dv), SYM(ProgramUniformMatrix4x2dv), SYM(ProgramUniformMatrix3x4dv), SYM(ProgramUniformMatrix4x3dv), SYM(ValidateProgramPipeline), SYM(GetProgramPipelineInfoLog), SYM(VertexAttribL1d), SYM(VertexAttribL2d), SYM(VertexAttribL3d), SYM(VertexAttribL4d), SYM(VertexAttribL1dv), SYM(VertexAttribL2dv), SYM(VertexAttribL3dv), SYM(VertexAttribL4dv), SYM(VertexAttribLPointer), SYM(GetVertexAttribLdv), SYM(ViewportArrayv), SYM(ViewportIndexedf), SYM(ViewportIndexedfv), SYM(ScissorArrayv), SYM(ScissorIndexed), SYM(ScissorIndexedv), SYM(DepthRangeArrayv), SYM(DepthRangeIndexed), SYM(GetFloati_v), SYM(GetDoublei_v), SYM(DrawArraysInstancedBaseInstance), SYM(DrawElementsInstancedBaseInstance), SYM(DrawElementsInstancedBaseVertexBaseInstance), SYM(GetInternalformativ), SYM(GetActiveAtomicCounterBufferiv), SYM(BindImageTexture), SYM(MemoryBarrier), SYM(TexStorage1D), SYM(TexStorage2D), SYM(TexStorage3D), SYM(DrawTransformFeedbackInstanced), SYM(DrawTransformFeedbackStreamInstanced), SYM(ClearBufferData), SYM(ClearBufferSubData), SYM(DispatchCompute), SYM(DispatchComputeIndirect), SYM(CopyImageSubData), SYM(FramebufferParameteri), SYM(GetFramebufferParameteriv), SYM(GetInternalformati64v), SYM(InvalidateTexSubImage), SYM(InvalidateTexImage), SYM(InvalidateBufferSubData), SYM(InvalidateBufferData), SYM(InvalidateFramebuffer), SYM(InvalidateSubFramebuffer), SYM(MultiDrawArraysIndirect), SYM(MultiDrawElementsIndirect), SYM(GetProgramInterfaceiv), SYM(GetProgramResourceIndex), SYM(GetProgramResourceName), SYM(GetProgramResourceiv), SYM(GetProgramResourceLocation), SYM(GetProgramResourceLocationIndex), SYM(ShaderStorageBlockBinding), SYM(TexBufferRange), SYM(TexStorage2DMultisample), SYM(TexStorage3DMultisample), SYM(TextureView), SYM(BindVertexBuffer), SYM(VertexAttribFormat), SYM(VertexAttribIFormat), SYM(VertexAttribLFormat), SYM(VertexAttribBinding), SYM(VertexBindingDivisor), SYM(DebugMessageControl), SYM(DebugMessageInsert), SYM(DebugMessageCallback), SYM(GetDebugMessageLog), SYM(PushDebugGroup), SYM(PopDebugGroup), SYM(ObjectLabel), SYM(GetObjectLabel), SYM(ObjectPtrLabel), SYM(GetObjectPtrLabel), SYM(BufferStorage), SYM(ClearTexImage), SYM(ClearTexSubImage), SYM(BindBuffersBase), SYM(BindBuffersRange), SYM(BindTextures), SYM(BindSamplers), SYM(BindImageTextures), SYM(BindVertexBuffers), SYM(GetTextureHandleARB), SYM(GetTextureSamplerHandleARB), SYM(MakeTextureHandleResidentARB), SYM(MakeTextureHandleNonResidentARB), SYM(GetImageHandleARB), SYM(MakeImageHandleResidentARB), SYM(MakeImageHandleNonResidentARB), SYM(UniformHandleui64ARB), SYM(UniformHandleui64vARB), SYM(ProgramUniformHandleui64ARB), SYM(ProgramUniformHandleui64vARB), SYM(IsTextureHandleResidentARB), SYM(IsImageHandleResidentARB), SYM(VertexAttribL1ui64ARB), SYM(VertexAttribL1ui64vARB), SYM(GetVertexAttribLui64vARB), SYM(CreateSyncFromCLeventARB), SYM(ClampColorARB), SYM(DispatchComputeGroupSizeARB), SYM(DebugMessageControlARB), SYM(DebugMessageInsertARB), SYM(DebugMessageCallbackARB), SYM(GetDebugMessageLogARB), SYM(DrawBuffersARB), SYM(BlendEquationiARB), SYM(BlendEquationSeparateiARB), SYM(BlendFunciARB), SYM(BlendFuncSeparateiARB), SYM(DrawArraysInstancedARB), SYM(DrawElementsInstancedARB), SYM(ProgramStringARB), SYM(BindProgramARB), SYM(DeleteProgramsARB), SYM(GenProgramsARB), SYM(ProgramEnvParameter4dARB), SYM(ProgramEnvParameter4dvARB), SYM(ProgramEnvParameter4fARB), SYM(ProgramEnvParameter4fvARB), SYM(ProgramLocalParameter4dARB), SYM(ProgramLocalParameter4dvARB), SYM(ProgramLocalParameter4fARB), SYM(ProgramLocalParameter4fvARB), SYM(GetProgramEnvParameterdvARB), SYM(GetProgramEnvParameterfvARB), SYM(GetProgramLocalParameterdvARB), SYM(GetProgramLocalParameterfvARB), SYM(GetProgramivARB), SYM(GetProgramStringARB), SYM(IsProgramARB), SYM(ProgramParameteriARB), SYM(FramebufferTextureARB), SYM(FramebufferTextureLayerARB), SYM(FramebufferTextureFaceARB), SYM(ColorTable), SYM(ColorTableParameterfv), SYM(ColorTableParameteriv), SYM(CopyColorTable), SYM(GetColorTable), SYM(GetColorTableParameterfv), SYM(GetColorTableParameteriv), SYM(ColorSubTable), SYM(CopyColorSubTable), SYM(ConvolutionFilter1D), SYM(ConvolutionFilter2D), SYM(ConvolutionParameterf), SYM(ConvolutionParameterfv), SYM(ConvolutionParameteri), SYM(ConvolutionParameteriv), SYM(CopyConvolutionFilter1D), SYM(CopyConvolutionFilter2D), SYM(GetConvolutionFilter), SYM(GetConvolutionParameterfv), SYM(GetConvolutionParameteriv), SYM(GetSeparableFilter), SYM(SeparableFilter2D), SYM(GetHistogram), SYM(GetHistogramParameterfv), SYM(GetHistogramParameteriv), SYM(GetMinmax), SYM(GetMinmaxParameterfv), SYM(GetMinmaxParameteriv), SYM(Histogram), SYM(Minmax), SYM(ResetHistogram), SYM(ResetMinmax), SYM(MultiDrawArraysIndirectCountARB), SYM(MultiDrawElementsIndirectCountARB), SYM(VertexAttribDivisorARB), SYM(CurrentPaletteMatrixARB), SYM(MatrixIndexubvARB), SYM(MatrixIndexusvARB), SYM(MatrixIndexuivARB), SYM(MatrixIndexPointerARB), SYM(SampleCoverageARB), SYM(ActiveTextureARB), SYM(ClientActiveTextureARB), SYM(MultiTexCoord1dARB), SYM(MultiTexCoord1dvARB), SYM(MultiTexCoord1fARB), SYM(MultiTexCoord1fvARB), SYM(MultiTexCoord1iARB), SYM(MultiTexCoord1ivARB), SYM(MultiTexCoord1sARB), SYM(MultiTexCoord1svARB), SYM(MultiTexCoord2dARB), SYM(MultiTexCoord2dvARB), SYM(MultiTexCoord2fARB), SYM(MultiTexCoord2fvARB), SYM(MultiTexCoord2iARB), SYM(MultiTexCoord2ivARB), SYM(MultiTexCoord2sARB), SYM(MultiTexCoord2svARB), SYM(MultiTexCoord3dARB), SYM(MultiTexCoord3dvARB), SYM(MultiTexCoord3fARB), SYM(MultiTexCoord3fvARB), SYM(MultiTexCoord3iARB), SYM(MultiTexCoord3ivARB), SYM(MultiTexCoord3sARB), SYM(MultiTexCoord3svARB), SYM(MultiTexCoord4dARB), SYM(MultiTexCoord4dvARB), SYM(MultiTexCoord4fARB), SYM(MultiTexCoord4fvARB), SYM(MultiTexCoord4iARB), SYM(MultiTexCoord4ivARB), SYM(MultiTexCoord4sARB), SYM(MultiTexCoord4svARB), SYM(GenQueriesARB), SYM(DeleteQueriesARB), SYM(IsQueryARB), SYM(BeginQueryARB), SYM(EndQueryARB), SYM(GetQueryivARB), SYM(GetQueryObjectivARB), SYM(GetQueryObjectuivARB), SYM(PointParameterfARB), SYM(PointParameterfvARB), SYM(GetGraphicsResetStatusARB), SYM(GetnTexImageARB), SYM(ReadnPixelsARB), SYM(GetnCompressedTexImageARB), SYM(GetnUniformfvARB), SYM(GetnUniformivARB), SYM(GetnUniformuivARB), SYM(GetnUniformdvARB), SYM(GetnMapdvARB), SYM(GetnMapfvARB), SYM(GetnMapivARB), SYM(GetnPixelMapfvARB), SYM(GetnPixelMapuivARB), SYM(GetnPixelMapusvARB), SYM(GetnPolygonStippleARB), SYM(GetnColorTableARB), SYM(GetnConvolutionFilterARB), SYM(GetnSeparableFilterARB), SYM(GetnHistogramARB), SYM(GetnMinmaxARB), SYM(MinSampleShadingARB), SYM(DeleteObjectARB), SYM(GetHandleARB), SYM(DetachObjectARB), SYM(CreateShaderObjectARB), SYM(ShaderSourceARB), SYM(CompileShaderARB), SYM(CreateProgramObjectARB), SYM(AttachObjectARB), SYM(LinkProgramARB), SYM(UseProgramObjectARB), SYM(ValidateProgramARB), SYM(Uniform1fARB), SYM(Uniform2fARB), SYM(Uniform3fARB), SYM(Uniform4fARB), SYM(Uniform1iARB), SYM(Uniform2iARB), SYM(Uniform3iARB), SYM(Uniform4iARB), SYM(Uniform1fvARB), SYM(Uniform2fvARB), SYM(Uniform3fvARB), SYM(Uniform4fvARB), SYM(Uniform1ivARB), SYM(Uniform2ivARB), SYM(Uniform3ivARB), SYM(Uniform4ivARB), SYM(UniformMatrix2fvARB), SYM(UniformMatrix3fvARB), SYM(UniformMatrix4fvARB), SYM(GetObjectParameterfvARB), SYM(GetObjectParameterivARB), SYM(GetInfoLogARB), SYM(GetAttachedObjectsARB), SYM(GetUniformLocationARB), SYM(GetActiveUniformARB), SYM(GetUniformfvARB), SYM(GetUniformivARB), SYM(GetShaderSourceARB), SYM(NamedStringARB), SYM(DeleteNamedStringARB), SYM(CompileShaderIncludeARB), SYM(IsNamedStringARB), SYM(GetNamedStringARB), SYM(GetNamedStringivARB), SYM(TexPageCommitmentARB), SYM(TexBufferARB), SYM(CompressedTexImage3DARB), SYM(CompressedTexImage2DARB), SYM(CompressedTexImage1DARB), SYM(CompressedTexSubImage3DARB), SYM(CompressedTexSubImage2DARB), SYM(CompressedTexSubImage1DARB), SYM(GetCompressedTexImageARB), SYM(LoadTransposeMatrixfARB), SYM(LoadTransposeMatrixdARB), SYM(MultTransposeMatrixfARB), SYM(MultTransposeMatrixdARB), SYM(WeightbvARB), SYM(WeightsvARB), SYM(WeightivARB), SYM(WeightfvARB), SYM(WeightdvARB), SYM(WeightubvARB), SYM(WeightusvARB), SYM(WeightuivARB), SYM(WeightPointerARB), SYM(VertexBlendARB), SYM(BindBufferARB), SYM(DeleteBuffersARB), SYM(GenBuffersARB), SYM(IsBufferARB), SYM(BufferDataARB), SYM(BufferSubDataARB), SYM(GetBufferSubDataARB), SYM(MapBufferARB), SYM(UnmapBufferARB), SYM(GetBufferParameterivARB), SYM(GetBufferPointervARB), SYM(VertexAttrib1dARB), SYM(VertexAttrib1dvARB), SYM(VertexAttrib1fARB), SYM(VertexAttrib1fvARB), SYM(VertexAttrib1sARB), SYM(VertexAttrib1svARB), SYM(VertexAttrib2dARB), SYM(VertexAttrib2dvARB), SYM(VertexAttrib2fARB), SYM(VertexAttrib2fvARB), SYM(VertexAttrib2sARB), SYM(VertexAttrib2svARB), SYM(VertexAttrib3dARB), SYM(VertexAttrib3dvARB), SYM(VertexAttrib3fARB), SYM(VertexAttrib3fvARB), SYM(VertexAttrib3sARB), SYM(VertexAttrib3svARB), SYM(VertexAttrib4NbvARB), SYM(VertexAttrib4NivARB), SYM(VertexAttrib4NsvARB), SYM(VertexAttrib4NubARB), SYM(VertexAttrib4NubvARB), SYM(VertexAttrib4NuivARB), SYM(VertexAttrib4NusvARB), SYM(VertexAttrib4bvARB), SYM(VertexAttrib4dARB), SYM(VertexAttrib4dvARB), SYM(VertexAttrib4fARB), SYM(VertexAttrib4fvARB), SYM(VertexAttrib4ivARB), SYM(VertexAttrib4sARB), SYM(VertexAttrib4svARB), SYM(VertexAttrib4ubvARB), SYM(VertexAttrib4uivARB), SYM(VertexAttrib4usvARB), SYM(VertexAttribPointerARB), SYM(EnableVertexAttribArrayARB), SYM(DisableVertexAttribArrayARB), SYM(GetVertexAttribdvARB), SYM(GetVertexAttribfvARB), SYM(GetVertexAttribivARB), SYM(GetVertexAttribPointervARB), SYM(BindAttribLocationARB), SYM(GetActiveAttribARB), SYM(GetAttribLocationARB), SYM(WindowPos2dARB), SYM(WindowPos2dvARB), SYM(WindowPos2fARB), SYM(WindowPos2fvARB), SYM(WindowPos2iARB), SYM(WindowPos2ivARB), SYM(WindowPos2sARB), SYM(WindowPos2svARB), SYM(WindowPos3dARB), SYM(WindowPos3dvARB), SYM(WindowPos3fARB), SYM(WindowPos3fvARB), SYM(WindowPos3iARB), SYM(WindowPos3ivARB), SYM(WindowPos3sARB), SYM(WindowPos3svARB), SYM(MultiTexCoord1bOES), SYM(MultiTexCoord1bvOES), SYM(MultiTexCoord2bOES), SYM(MultiTexCoord2bvOES), SYM(MultiTexCoord3bOES), SYM(MultiTexCoord3bvOES), SYM(MultiTexCoord4bOES), SYM(MultiTexCoord4bvOES), SYM(TexCoord1bOES), SYM(TexCoord1bvOES), SYM(TexCoord2bOES), SYM(TexCoord2bvOES), SYM(TexCoord3bOES), SYM(TexCoord3bvOES), SYM(TexCoord4bOES), SYM(TexCoord4bvOES), SYM(Vertex2bOES), SYM(Vertex2bvOES), SYM(Vertex3bOES), SYM(Vertex3bvOES), SYM(Vertex4bOES), SYM(Vertex4bvOES), SYM(AlphaFuncxOES), SYM(ClearColorxOES), SYM(ClearDepthxOES), SYM(ClipPlanexOES), SYM(Color4xOES), SYM(DepthRangexOES), SYM(FogxOES), SYM(FogxvOES), SYM(FrustumxOES), SYM(GetClipPlanexOES), SYM(GetFixedvOES), SYM(GetTexEnvxvOES), SYM(GetTexParameterxvOES), SYM(LightModelxOES), SYM(LightModelxvOES), SYM(LightxOES), SYM(LightxvOES), SYM(LineWidthxOES), SYM(LoadMatrixxOES), SYM(MaterialxOES), SYM(MaterialxvOES), SYM(MultMatrixxOES), SYM(MultiTexCoord4xOES), SYM(Normal3xOES), SYM(OrthoxOES), SYM(PointParameterxvOES), SYM(PointSizexOES), SYM(PolygonOffsetxOES), SYM(RotatexOES), SYM(SampleCoverageOES), SYM(ScalexOES), SYM(TexEnvxOES), SYM(TexEnvxvOES), SYM(TexParameterxOES), SYM(TexParameterxvOES), SYM(TranslatexOES), SYM(AccumxOES), SYM(BitmapxOES), SYM(BlendColorxOES), SYM(ClearAccumxOES), SYM(Color3xOES), SYM(Color3xvOES), SYM(Color4xvOES), SYM(ConvolutionParameterxOES), SYM(ConvolutionParameterxvOES), SYM(EvalCoord1xOES), SYM(EvalCoord1xvOES), SYM(EvalCoord2xOES), SYM(EvalCoord2xvOES), SYM(FeedbackBufferxOES), SYM(GetConvolutionParameterxvOES), SYM(GetHistogramParameterxvOES), SYM(GetLightxOES), SYM(GetMapxvOES), SYM(GetMaterialxOES), SYM(GetPixelMapxv), SYM(GetTexGenxvOES), SYM(GetTexLevelParameterxvOES), SYM(IndexxOES), SYM(IndexxvOES), SYM(LoadTransposeMatrixxOES), SYM(Map1xOES), SYM(Map2xOES), SYM(MapGrid1xOES), SYM(MapGrid2xOES), SYM(MultTransposeMatrixxOES), SYM(MultiTexCoord1xOES), SYM(MultiTexCoord1xvOES), SYM(MultiTexCoord2xOES), SYM(MultiTexCoord2xvOES), SYM(MultiTexCoord3xOES), SYM(MultiTexCoord3xvOES), SYM(MultiTexCoord4xvOES), SYM(Normal3xvOES), SYM(PassThroughxOES), SYM(PixelMapx), SYM(PixelStorex), SYM(PixelTransferxOES), SYM(PixelZoomxOES), SYM(PrioritizeTexturesxOES), SYM(RasterPos2xOES), SYM(RasterPos2xvOES), SYM(RasterPos3xOES), SYM(RasterPos3xvOES), SYM(RasterPos4xOES), SYM(RasterPos4xvOES), SYM(RectxOES), SYM(RectxvOES), SYM(TexCoord1xOES), SYM(TexCoord1xvOES), SYM(TexCoord2xOES), SYM(TexCoord2xvOES), SYM(TexCoord3xOES), SYM(TexCoord3xvOES), SYM(TexCoord4xOES), SYM(TexCoord4xvOES), SYM(TexGenxOES), SYM(TexGenxvOES), SYM(Vertex2xOES), SYM(Vertex2xvOES), SYM(Vertex3xOES), SYM(Vertex3xvOES), SYM(Vertex4xOES), SYM(Vertex4xvOES), SYM(QueryMatrixxOES), SYM(ClearDepthfOES), SYM(ClipPlanefOES), SYM(DepthRangefOES), SYM(FrustumfOES), SYM(GetClipPlanefOES), SYM(OrthofOES), SYM(ImageTransformParameteriHP), SYM(ImageTransformParameterfHP), SYM(ImageTransformParameterivHP), SYM(ImageTransformParameterfvHP), SYM(GetImageTransformParameterivHP), SYM(GetImageTransformParameterfvHP), { NULL, NULL }, }; RGLSYMGLDRAWRANGEELEMENTSPROC __rglgen_glDrawRangeElements; RGLSYMGLTEXIMAGE3DPROC __rglgen_glTexImage3D; RGLSYMGLTEXSUBIMAGE3DPROC __rglgen_glTexSubImage3D; RGLSYMGLCOPYTEXSUBIMAGE3DPROC __rglgen_glCopyTexSubImage3D; RGLSYMGLACTIVETEXTUREPROC __rglgen_glActiveTexture; RGLSYMGLSAMPLECOVERAGEPROC __rglgen_glSampleCoverage; RGLSYMGLCOMPRESSEDTEXIMAGE3DPROC __rglgen_glCompressedTexImage3D; RGLSYMGLCOMPRESSEDTEXIMAGE2DPROC __rglgen_glCompressedTexImage2D; RGLSYMGLCOMPRESSEDTEXIMAGE1DPROC __rglgen_glCompressedTexImage1D; RGLSYMGLCOMPRESSEDTEXSUBIMAGE3DPROC __rglgen_glCompressedTexSubImage3D; RGLSYMGLCOMPRESSEDTEXSUBIMAGE2DPROC __rglgen_glCompressedTexSubImage2D; RGLSYMGLCOMPRESSEDTEXSUBIMAGE1DPROC __rglgen_glCompressedTexSubImage1D; RGLSYMGLGETCOMPRESSEDTEXIMAGEPROC __rglgen_glGetCompressedTexImage; RGLSYMGLCLIENTACTIVETEXTUREPROC __rglgen_glClientActiveTexture; RGLSYMGLMULTITEXCOORD1DPROC __rglgen_glMultiTexCoord1d; RGLSYMGLMULTITEXCOORD1DVPROC __rglgen_glMultiTexCoord1dv; RGLSYMGLMULTITEXCOORD1FPROC __rglgen_glMultiTexCoord1f; RGLSYMGLMULTITEXCOORD1FVPROC __rglgen_glMultiTexCoord1fv; RGLSYMGLMULTITEXCOORD1IPROC __rglgen_glMultiTexCoord1i; RGLSYMGLMULTITEXCOORD1IVPROC __rglgen_glMultiTexCoord1iv; RGLSYMGLMULTITEXCOORD1SPROC __rglgen_glMultiTexCoord1s; RGLSYMGLMULTITEXCOORD1SVPROC __rglgen_glMultiTexCoord1sv; RGLSYMGLMULTITEXCOORD2DPROC __rglgen_glMultiTexCoord2d; RGLSYMGLMULTITEXCOORD2DVPROC __rglgen_glMultiTexCoord2dv; RGLSYMGLMULTITEXCOORD2FPROC __rglgen_glMultiTexCoord2f; RGLSYMGLMULTITEXCOORD2FVPROC __rglgen_glMultiTexCoord2fv; RGLSYMGLMULTITEXCOORD2IPROC __rglgen_glMultiTexCoord2i; RGLSYMGLMULTITEXCOORD2IVPROC __rglgen_glMultiTexCoord2iv; RGLSYMGLMULTITEXCOORD2SPROC __rglgen_glMultiTexCoord2s; RGLSYMGLMULTITEXCOORD2SVPROC __rglgen_glMultiTexCoord2sv; RGLSYMGLMULTITEXCOORD3DPROC __rglgen_glMultiTexCoord3d; RGLSYMGLMULTITEXCOORD3DVPROC __rglgen_glMultiTexCoord3dv; RGLSYMGLMULTITEXCOORD3FPROC __rglgen_glMultiTexCoord3f; RGLSYMGLMULTITEXCOORD3FVPROC __rglgen_glMultiTexCoord3fv; RGLSYMGLMULTITEXCOORD3IPROC __rglgen_glMultiTexCoord3i; RGLSYMGLMULTITEXCOORD3IVPROC __rglgen_glMultiTexCoord3iv; RGLSYMGLMULTITEXCOORD3SPROC __rglgen_glMultiTexCoord3s; RGLSYMGLMULTITEXCOORD3SVPROC __rglgen_glMultiTexCoord3sv; RGLSYMGLMULTITEXCOORD4DPROC __rglgen_glMultiTexCoord4d; RGLSYMGLMULTITEXCOORD4DVPROC __rglgen_glMultiTexCoord4dv; RGLSYMGLMULTITEXCOORD4FPROC __rglgen_glMultiTexCoord4f; RGLSYMGLMULTITEXCOORD4FVPROC __rglgen_glMultiTexCoord4fv; RGLSYMGLMULTITEXCOORD4IPROC __rglgen_glMultiTexCoord4i; RGLSYMGLMULTITEXCOORD4IVPROC __rglgen_glMultiTexCoord4iv; RGLSYMGLMULTITEXCOORD4SPROC __rglgen_glMultiTexCoord4s; RGLSYMGLMULTITEXCOORD4SVPROC __rglgen_glMultiTexCoord4sv; RGLSYMGLLOADTRANSPOSEMATRIXFPROC __rglgen_glLoadTransposeMatrixf; RGLSYMGLLOADTRANSPOSEMATRIXDPROC __rglgen_glLoadTransposeMatrixd; RGLSYMGLMULTTRANSPOSEMATRIXFPROC __rglgen_glMultTransposeMatrixf; RGLSYMGLMULTTRANSPOSEMATRIXDPROC __rglgen_glMultTransposeMatrixd; RGLSYMGLBLENDFUNCSEPARATEPROC __rglgen_glBlendFuncSeparate; RGLSYMGLMULTIDRAWARRAYSPROC __rglgen_glMultiDrawArrays; RGLSYMGLMULTIDRAWELEMENTSPROC __rglgen_glMultiDrawElements; RGLSYMGLPOINTPARAMETERFPROC __rglgen_glPointParameterf; RGLSYMGLPOINTPARAMETERFVPROC __rglgen_glPointParameterfv; RGLSYMGLPOINTPARAMETERIPROC __rglgen_glPointParameteri; RGLSYMGLPOINTPARAMETERIVPROC __rglgen_glPointParameteriv; RGLSYMGLFOGCOORDFPROC __rglgen_glFogCoordf; RGLSYMGLFOGCOORDFVPROC __rglgen_glFogCoordfv; RGLSYMGLFOGCOORDDPROC __rglgen_glFogCoordd; RGLSYMGLFOGCOORDDVPROC __rglgen_glFogCoorddv; RGLSYMGLFOGCOORDPOINTERPROC __rglgen_glFogCoordPointer; RGLSYMGLSECONDARYCOLOR3BPROC __rglgen_glSecondaryColor3b; RGLSYMGLSECONDARYCOLOR3BVPROC __rglgen_glSecondaryColor3bv; RGLSYMGLSECONDARYCOLOR3DPROC __rglgen_glSecondaryColor3d; RGLSYMGLSECONDARYCOLOR3DVPROC __rglgen_glSecondaryColor3dv; RGLSYMGLSECONDARYCOLOR3FPROC __rglgen_glSecondaryColor3f; RGLSYMGLSECONDARYCOLOR3FVPROC __rglgen_glSecondaryColor3fv; RGLSYMGLSECONDARYCOLOR3IPROC __rglgen_glSecondaryColor3i; RGLSYMGLSECONDARYCOLOR3IVPROC __rglgen_glSecondaryColor3iv; RGLSYMGLSECONDARYCOLOR3SPROC __rglgen_glSecondaryColor3s; RGLSYMGLSECONDARYCOLOR3SVPROC __rglgen_glSecondaryColor3sv; RGLSYMGLSECONDARYCOLOR3UBPROC __rglgen_glSecondaryColor3ub; RGLSYMGLSECONDARYCOLOR3UBVPROC __rglgen_glSecondaryColor3ubv; RGLSYMGLSECONDARYCOLOR3UIPROC __rglgen_glSecondaryColor3ui; RGLSYMGLSECONDARYCOLOR3UIVPROC __rglgen_glSecondaryColor3uiv; RGLSYMGLSECONDARYCOLOR3USPROC __rglgen_glSecondaryColor3us; RGLSYMGLSECONDARYCOLOR3USVPROC __rglgen_glSecondaryColor3usv; RGLSYMGLSECONDARYCOLORPOINTERPROC __rglgen_glSecondaryColorPointer; RGLSYMGLWINDOWPOS2DPROC __rglgen_glWindowPos2d; RGLSYMGLWINDOWPOS2DVPROC __rglgen_glWindowPos2dv; RGLSYMGLWINDOWPOS2FPROC __rglgen_glWindowPos2f; RGLSYMGLWINDOWPOS2FVPROC __rglgen_glWindowPos2fv; RGLSYMGLWINDOWPOS2IPROC __rglgen_glWindowPos2i; RGLSYMGLWINDOWPOS2IVPROC __rglgen_glWindowPos2iv; RGLSYMGLWINDOWPOS2SPROC __rglgen_glWindowPos2s; RGLSYMGLWINDOWPOS2SVPROC __rglgen_glWindowPos2sv; RGLSYMGLWINDOWPOS3DPROC __rglgen_glWindowPos3d; RGLSYMGLWINDOWPOS3DVPROC __rglgen_glWindowPos3dv; RGLSYMGLWINDOWPOS3FPROC __rglgen_glWindowPos3f; RGLSYMGLWINDOWPOS3FVPROC __rglgen_glWindowPos3fv; RGLSYMGLWINDOWPOS3IPROC __rglgen_glWindowPos3i; RGLSYMGLWINDOWPOS3IVPROC __rglgen_glWindowPos3iv; RGLSYMGLWINDOWPOS3SPROC __rglgen_glWindowPos3s; RGLSYMGLWINDOWPOS3SVPROC __rglgen_glWindowPos3sv; RGLSYMGLBLENDCOLORPROC __rglgen_glBlendColor; RGLSYMGLBLENDEQUATIONPROC __rglgen_glBlendEquation; RGLSYMGLGENQUERIESPROC __rglgen_glGenQueries; RGLSYMGLDELETEQUERIESPROC __rglgen_glDeleteQueries; RGLSYMGLISQUERYPROC __rglgen_glIsQuery; RGLSYMGLBEGINQUERYPROC __rglgen_glBeginQuery; RGLSYMGLENDQUERYPROC __rglgen_glEndQuery; RGLSYMGLGETQUERYIVPROC __rglgen_glGetQueryiv; RGLSYMGLGETQUERYOBJECTIVPROC __rglgen_glGetQueryObjectiv; RGLSYMGLGETQUERYOBJECTUIVPROC __rglgen_glGetQueryObjectuiv; RGLSYMGLBINDBUFFERPROC __rglgen_glBindBuffer; RGLSYMGLDELETEBUFFERSPROC __rglgen_glDeleteBuffers; RGLSYMGLGENBUFFERSPROC __rglgen_glGenBuffers; RGLSYMGLISBUFFERPROC __rglgen_glIsBuffer; RGLSYMGLBUFFERDATAPROC __rglgen_glBufferData; RGLSYMGLBUFFERSUBDATAPROC __rglgen_glBufferSubData; RGLSYMGLGETBUFFERSUBDATAPROC __rglgen_glGetBufferSubData; RGLSYMGLMAPBUFFERPROC __rglgen_glMapBuffer; RGLSYMGLUNMAPBUFFERPROC __rglgen_glUnmapBuffer; RGLSYMGLGETBUFFERPARAMETERIVPROC __rglgen_glGetBufferParameteriv; RGLSYMGLGETBUFFERPOINTERVPROC __rglgen_glGetBufferPointerv; RGLSYMGLBLENDEQUATIONSEPARATEPROC __rglgen_glBlendEquationSeparate; RGLSYMGLDRAWBUFFERSPROC __rglgen_glDrawBuffers; RGLSYMGLSTENCILOPSEPARATEPROC __rglgen_glStencilOpSeparate; RGLSYMGLSTENCILFUNCSEPARATEPROC __rglgen_glStencilFuncSeparate; RGLSYMGLSTENCILMASKSEPARATEPROC __rglgen_glStencilMaskSeparate; RGLSYMGLATTACHSHADERPROC __rglgen_glAttachShader; RGLSYMGLBINDATTRIBLOCATIONPROC __rglgen_glBindAttribLocation; RGLSYMGLCOMPILESHADERPROC __rglgen_glCompileShader; RGLSYMGLCREATEPROGRAMPROC __rglgen_glCreateProgram; RGLSYMGLCREATESHADERPROC __rglgen_glCreateShader; RGLSYMGLDELETEPROGRAMPROC __rglgen_glDeleteProgram; RGLSYMGLDELETESHADERPROC __rglgen_glDeleteShader; RGLSYMGLDETACHSHADERPROC __rglgen_glDetachShader; RGLSYMGLDISABLEVERTEXATTRIBARRAYPROC __rglgen_glDisableVertexAttribArray; RGLSYMGLENABLEVERTEXATTRIBARRAYPROC __rglgen_glEnableVertexAttribArray; RGLSYMGLGETACTIVEATTRIBPROC __rglgen_glGetActiveAttrib; RGLSYMGLGETACTIVEUNIFORMPROC __rglgen_glGetActiveUniform; RGLSYMGLGETATTACHEDSHADERSPROC __rglgen_glGetAttachedShaders; RGLSYMGLGETATTRIBLOCATIONPROC __rglgen_glGetAttribLocation; RGLSYMGLGETPROGRAMIVPROC __rglgen_glGetProgramiv; RGLSYMGLGETPROGRAMINFOLOGPROC __rglgen_glGetProgramInfoLog; RGLSYMGLGETSHADERIVPROC __rglgen_glGetShaderiv; RGLSYMGLGETSHADERINFOLOGPROC __rglgen_glGetShaderInfoLog; RGLSYMGLGETSHADERSOURCEPROC __rglgen_glGetShaderSource; RGLSYMGLGETUNIFORMLOCATIONPROC __rglgen_glGetUniformLocation; RGLSYMGLGETUNIFORMFVPROC __rglgen_glGetUniformfv; RGLSYMGLGETUNIFORMIVPROC __rglgen_glGetUniformiv; RGLSYMGLGETVERTEXATTRIBDVPROC __rglgen_glGetVertexAttribdv; RGLSYMGLGETVERTEXATTRIBFVPROC __rglgen_glGetVertexAttribfv; RGLSYMGLGETVERTEXATTRIBIVPROC __rglgen_glGetVertexAttribiv; RGLSYMGLGETVERTEXATTRIBPOINTERVPROC __rglgen_glGetVertexAttribPointerv; RGLSYMGLISPROGRAMPROC __rglgen_glIsProgram; RGLSYMGLISSHADERPROC __rglgen_glIsShader; RGLSYMGLLINKPROGRAMPROC __rglgen_glLinkProgram; RGLSYMGLSHADERSOURCEPROC __rglgen_glShaderSource; RGLSYMGLUSEPROGRAMPROC __rglgen_glUseProgram; RGLSYMGLUNIFORM1FPROC __rglgen_glUniform1f; RGLSYMGLUNIFORM2FPROC __rglgen_glUniform2f; RGLSYMGLUNIFORM3FPROC __rglgen_glUniform3f; RGLSYMGLUNIFORM4FPROC __rglgen_glUniform4f; RGLSYMGLUNIFORM1IPROC __rglgen_glUniform1i; RGLSYMGLUNIFORM2IPROC __rglgen_glUniform2i; RGLSYMGLUNIFORM3IPROC __rglgen_glUniform3i; RGLSYMGLUNIFORM4IPROC __rglgen_glUniform4i; RGLSYMGLUNIFORM1FVPROC __rglgen_glUniform1fv; RGLSYMGLUNIFORM2FVPROC __rglgen_glUniform2fv; RGLSYMGLUNIFORM3FVPROC __rglgen_glUniform3fv; RGLSYMGLUNIFORM4FVPROC __rglgen_glUniform4fv; RGLSYMGLUNIFORM1IVPROC __rglgen_glUniform1iv; RGLSYMGLUNIFORM2IVPROC __rglgen_glUniform2iv; RGLSYMGLUNIFORM3IVPROC __rglgen_glUniform3iv; RGLSYMGLUNIFORM4IVPROC __rglgen_glUniform4iv; RGLSYMGLUNIFORMMATRIX2FVPROC __rglgen_glUniformMatrix2fv; RGLSYMGLUNIFORMMATRIX3FVPROC __rglgen_glUniformMatrix3fv; RGLSYMGLUNIFORMMATRIX4FVPROC __rglgen_glUniformMatrix4fv; RGLSYMGLVALIDATEPROGRAMPROC __rglgen_glValidateProgram; RGLSYMGLVERTEXATTRIB1DPROC __rglgen_glVertexAttrib1d; RGLSYMGLVERTEXATTRIB1DVPROC __rglgen_glVertexAttrib1dv; RGLSYMGLVERTEXATTRIB1FPROC __rglgen_glVertexAttrib1f; RGLSYMGLVERTEXATTRIB1FVPROC __rglgen_glVertexAttrib1fv; RGLSYMGLVERTEXATTRIB1SPROC __rglgen_glVertexAttrib1s; RGLSYMGLVERTEXATTRIB1SVPROC __rglgen_glVertexAttrib1sv; RGLSYMGLVERTEXATTRIB2DPROC __rglgen_glVertexAttrib2d; RGLSYMGLVERTEXATTRIB2DVPROC __rglgen_glVertexAttrib2dv; RGLSYMGLVERTEXATTRIB2FPROC __rglgen_glVertexAttrib2f; RGLSYMGLVERTEXATTRIB2FVPROC __rglgen_glVertexAttrib2fv; RGLSYMGLVERTEXATTRIB2SPROC __rglgen_glVertexAttrib2s; RGLSYMGLVERTEXATTRIB2SVPROC __rglgen_glVertexAttrib2sv; RGLSYMGLVERTEXATTRIB3DPROC __rglgen_glVertexAttrib3d; RGLSYMGLVERTEXATTRIB3DVPROC __rglgen_glVertexAttrib3dv; RGLSYMGLVERTEXATTRIB3FPROC __rglgen_glVertexAttrib3f; RGLSYMGLVERTEXATTRIB3FVPROC __rglgen_glVertexAttrib3fv; RGLSYMGLVERTEXATTRIB3SPROC __rglgen_glVertexAttrib3s; RGLSYMGLVERTEXATTRIB3SVPROC __rglgen_glVertexAttrib3sv; RGLSYMGLVERTEXATTRIB4NBVPROC __rglgen_glVertexAttrib4Nbv; RGLSYMGLVERTEXATTRIB4NIVPROC __rglgen_glVertexAttrib4Niv; RGLSYMGLVERTEXATTRIB4NSVPROC __rglgen_glVertexAttrib4Nsv; RGLSYMGLVERTEXATTRIB4NUBPROC __rglgen_glVertexAttrib4Nub; RGLSYMGLVERTEXATTRIB4NUBVPROC __rglgen_glVertexAttrib4Nubv; RGLSYMGLVERTEXATTRIB4NUIVPROC __rglgen_glVertexAttrib4Nuiv; RGLSYMGLVERTEXATTRIB4NUSVPROC __rglgen_glVertexAttrib4Nusv; RGLSYMGLVERTEXATTRIB4BVPROC __rglgen_glVertexAttrib4bv; RGLSYMGLVERTEXATTRIB4DPROC __rglgen_glVertexAttrib4d; RGLSYMGLVERTEXATTRIB4DVPROC __rglgen_glVertexAttrib4dv; RGLSYMGLVERTEXATTRIB4FPROC __rglgen_glVertexAttrib4f; RGLSYMGLVERTEXATTRIB4FVPROC __rglgen_glVertexAttrib4fv; RGLSYMGLVERTEXATTRIB4IVPROC __rglgen_glVertexAttrib4iv; RGLSYMGLVERTEXATTRIB4SPROC __rglgen_glVertexAttrib4s; RGLSYMGLVERTEXATTRIB4SVPROC __rglgen_glVertexAttrib4sv; RGLSYMGLVERTEXATTRIB4UBVPROC __rglgen_glVertexAttrib4ubv; RGLSYMGLVERTEXATTRIB4UIVPROC __rglgen_glVertexAttrib4uiv; RGLSYMGLVERTEXATTRIB4USVPROC __rglgen_glVertexAttrib4usv; RGLSYMGLVERTEXATTRIBPOINTERPROC __rglgen_glVertexAttribPointer; RGLSYMGLUNIFORMMATRIX2X3FVPROC __rglgen_glUniformMatrix2x3fv; RGLSYMGLUNIFORMMATRIX3X2FVPROC __rglgen_glUniformMatrix3x2fv; RGLSYMGLUNIFORMMATRIX2X4FVPROC __rglgen_glUniformMatrix2x4fv; RGLSYMGLUNIFORMMATRIX4X2FVPROC __rglgen_glUniformMatrix4x2fv; RGLSYMGLUNIFORMMATRIX3X4FVPROC __rglgen_glUniformMatrix3x4fv; RGLSYMGLUNIFORMMATRIX4X3FVPROC __rglgen_glUniformMatrix4x3fv; RGLSYMGLCOLORMASKIPROC __rglgen_glColorMaski; RGLSYMGLGETBOOLEANI_VPROC __rglgen_glGetBooleani_v; RGLSYMGLGETINTEGERI_VPROC __rglgen_glGetIntegeri_v; RGLSYMGLENABLEIPROC __rglgen_glEnablei; RGLSYMGLDISABLEIPROC __rglgen_glDisablei; RGLSYMGLISENABLEDIPROC __rglgen_glIsEnabledi; RGLSYMGLBEGINTRANSFORMFEEDBACKPROC __rglgen_glBeginTransformFeedback; RGLSYMGLENDTRANSFORMFEEDBACKPROC __rglgen_glEndTransformFeedback; RGLSYMGLBINDBUFFERRANGEPROC __rglgen_glBindBufferRange; RGLSYMGLBINDBUFFERBASEPROC __rglgen_glBindBufferBase; RGLSYMGLTRANSFORMFEEDBACKVARYINGSPROC __rglgen_glTransformFeedbackVaryings; RGLSYMGLGETTRANSFORMFEEDBACKVARYINGPROC __rglgen_glGetTransformFeedbackVarying; RGLSYMGLCLAMPCOLORPROC __rglgen_glClampColor; RGLSYMGLBEGINCONDITIONALRENDERPROC __rglgen_glBeginConditionalRender; RGLSYMGLENDCONDITIONALRENDERPROC __rglgen_glEndConditionalRender; RGLSYMGLVERTEXATTRIBIPOINTERPROC __rglgen_glVertexAttribIPointer; RGLSYMGLGETVERTEXATTRIBIIVPROC __rglgen_glGetVertexAttribIiv; RGLSYMGLGETVERTEXATTRIBIUIVPROC __rglgen_glGetVertexAttribIuiv; RGLSYMGLVERTEXATTRIBI1IPROC __rglgen_glVertexAttribI1i; RGLSYMGLVERTEXATTRIBI2IPROC __rglgen_glVertexAttribI2i; RGLSYMGLVERTEXATTRIBI3IPROC __rglgen_glVertexAttribI3i; RGLSYMGLVERTEXATTRIBI4IPROC __rglgen_glVertexAttribI4i; RGLSYMGLVERTEXATTRIBI1UIPROC __rglgen_glVertexAttribI1ui; RGLSYMGLVERTEXATTRIBI2UIPROC __rglgen_glVertexAttribI2ui; RGLSYMGLVERTEXATTRIBI3UIPROC __rglgen_glVertexAttribI3ui; RGLSYMGLVERTEXATTRIBI4UIPROC __rglgen_glVertexAttribI4ui; RGLSYMGLVERTEXATTRIBI1IVPROC __rglgen_glVertexAttribI1iv; RGLSYMGLVERTEXATTRIBI2IVPROC __rglgen_glVertexAttribI2iv; RGLSYMGLVERTEXATTRIBI3IVPROC __rglgen_glVertexAttribI3iv; RGLSYMGLVERTEXATTRIBI4IVPROC __rglgen_glVertexAttribI4iv; RGLSYMGLVERTEXATTRIBI1UIVPROC __rglgen_glVertexAttribI1uiv; RGLSYMGLVERTEXATTRIBI2UIVPROC __rglgen_glVertexAttribI2uiv; RGLSYMGLVERTEXATTRIBI3UIVPROC __rglgen_glVertexAttribI3uiv; RGLSYMGLVERTEXATTRIBI4UIVPROC __rglgen_glVertexAttribI4uiv; RGLSYMGLVERTEXATTRIBI4BVPROC __rglgen_glVertexAttribI4bv; RGLSYMGLVERTEXATTRIBI4SVPROC __rglgen_glVertexAttribI4sv; RGLSYMGLVERTEXATTRIBI4UBVPROC __rglgen_glVertexAttribI4ubv; RGLSYMGLVERTEXATTRIBI4USVPROC __rglgen_glVertexAttribI4usv; RGLSYMGLGETUNIFORMUIVPROC __rglgen_glGetUniformuiv; RGLSYMGLBINDFRAGDATALOCATIONPROC __rglgen_glBindFragDataLocation; RGLSYMGLGETFRAGDATALOCATIONPROC __rglgen_glGetFragDataLocation; RGLSYMGLUNIFORM1UIPROC __rglgen_glUniform1ui; RGLSYMGLUNIFORM2UIPROC __rglgen_glUniform2ui; RGLSYMGLUNIFORM3UIPROC __rglgen_glUniform3ui; RGLSYMGLUNIFORM4UIPROC __rglgen_glUniform4ui; RGLSYMGLUNIFORM1UIVPROC __rglgen_glUniform1uiv; RGLSYMGLUNIFORM2UIVPROC __rglgen_glUniform2uiv; RGLSYMGLUNIFORM3UIVPROC __rglgen_glUniform3uiv; RGLSYMGLUNIFORM4UIVPROC __rglgen_glUniform4uiv; RGLSYMGLTEXPARAMETERIIVPROC __rglgen_glTexParameterIiv; RGLSYMGLTEXPARAMETERIUIVPROC __rglgen_glTexParameterIuiv; RGLSYMGLGETTEXPARAMETERIIVPROC __rglgen_glGetTexParameterIiv; RGLSYMGLGETTEXPARAMETERIUIVPROC __rglgen_glGetTexParameterIuiv; RGLSYMGLCLEARBUFFERIVPROC __rglgen_glClearBufferiv; RGLSYMGLCLEARBUFFERUIVPROC __rglgen_glClearBufferuiv; RGLSYMGLCLEARBUFFERFVPROC __rglgen_glClearBufferfv; RGLSYMGLCLEARBUFFERFIPROC __rglgen_glClearBufferfi; RGLSYMGLGETSTRINGIPROC __rglgen_glGetStringi; RGLSYMGLISRENDERBUFFERPROC __rglgen_glIsRenderbuffer; RGLSYMGLBINDRENDERBUFFERPROC __rglgen_glBindRenderbuffer; RGLSYMGLDELETERENDERBUFFERSPROC __rglgen_glDeleteRenderbuffers; RGLSYMGLGENRENDERBUFFERSPROC __rglgen_glGenRenderbuffers; RGLSYMGLRENDERBUFFERSTORAGEPROC __rglgen_glRenderbufferStorage; RGLSYMGLGETRENDERBUFFERPARAMETERIVPROC __rglgen_glGetRenderbufferParameteriv; RGLSYMGLISFRAMEBUFFERPROC __rglgen_glIsFramebuffer; RGLSYMGLBINDFRAMEBUFFERPROC __rglgen_glBindFramebuffer; RGLSYMGLDELETEFRAMEBUFFERSPROC __rglgen_glDeleteFramebuffers; RGLSYMGLGENFRAMEBUFFERSPROC __rglgen_glGenFramebuffers; RGLSYMGLCHECKFRAMEBUFFERSTATUSPROC __rglgen_glCheckFramebufferStatus; RGLSYMGLFRAMEBUFFERTEXTURE1DPROC __rglgen_glFramebufferTexture1D; RGLSYMGLFRAMEBUFFERTEXTURE2DPROC __rglgen_glFramebufferTexture2D; RGLSYMGLFRAMEBUFFERTEXTURE3DPROC __rglgen_glFramebufferTexture3D; RGLSYMGLFRAMEBUFFERRENDERBUFFERPROC __rglgen_glFramebufferRenderbuffer; RGLSYMGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC __rglgen_glGetFramebufferAttachmentParameteriv; RGLSYMGLGENERATEMIPMAPPROC __rglgen_glGenerateMipmap; RGLSYMGLBLITFRAMEBUFFERPROC __rglgen_glBlitFramebuffer; RGLSYMGLRENDERBUFFERSTORAGEMULTISAMPLEPROC __rglgen_glRenderbufferStorageMultisample; RGLSYMGLFRAMEBUFFERTEXTURELAYERPROC __rglgen_glFramebufferTextureLayer; RGLSYMGLMAPBUFFERRANGEPROC __rglgen_glMapBufferRange; RGLSYMGLFLUSHMAPPEDBUFFERRANGEPROC __rglgen_glFlushMappedBufferRange; RGLSYMGLBINDVERTEXARRAYPROC __rglgen_glBindVertexArray; RGLSYMGLDELETEVERTEXARRAYSPROC __rglgen_glDeleteVertexArrays; RGLSYMGLGENVERTEXARRAYSPROC __rglgen_glGenVertexArrays; RGLSYMGLISVERTEXARRAYPROC __rglgen_glIsVertexArray; RGLSYMGLDRAWARRAYSINSTANCEDPROC __rglgen_glDrawArraysInstanced; RGLSYMGLDRAWELEMENTSINSTANCEDPROC __rglgen_glDrawElementsInstanced; RGLSYMGLTEXBUFFERPROC __rglgen_glTexBuffer; RGLSYMGLPRIMITIVERESTARTINDEXPROC __rglgen_glPrimitiveRestartIndex; RGLSYMGLCOPYBUFFERSUBDATAPROC __rglgen_glCopyBufferSubData; RGLSYMGLGETUNIFORMINDICESPROC __rglgen_glGetUniformIndices; RGLSYMGLGETACTIVEUNIFORMSIVPROC __rglgen_glGetActiveUniformsiv; RGLSYMGLGETACTIVEUNIFORMNAMEPROC __rglgen_glGetActiveUniformName; RGLSYMGLGETUNIFORMBLOCKINDEXPROC __rglgen_glGetUniformBlockIndex; RGLSYMGLGETACTIVEUNIFORMBLOCKIVPROC __rglgen_glGetActiveUniformBlockiv; RGLSYMGLGETACTIVEUNIFORMBLOCKNAMEPROC __rglgen_glGetActiveUniformBlockName; RGLSYMGLUNIFORMBLOCKBINDINGPROC __rglgen_glUniformBlockBinding; RGLSYMGLDRAWELEMENTSBASEVERTEXPROC __rglgen_glDrawElementsBaseVertex; RGLSYMGLDRAWRANGEELEMENTSBASEVERTEXPROC __rglgen_glDrawRangeElementsBaseVertex; RGLSYMGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC __rglgen_glDrawElementsInstancedBaseVertex; RGLSYMGLMULTIDRAWELEMENTSBASEVERTEXPROC __rglgen_glMultiDrawElementsBaseVertex; RGLSYMGLPROVOKINGVERTEXPROC __rglgen_glProvokingVertex; RGLSYMGLFENCESYNCPROC __rglgen_glFenceSync; RGLSYMGLISSYNCPROC __rglgen_glIsSync; RGLSYMGLDELETESYNCPROC __rglgen_glDeleteSync; RGLSYMGLCLIENTWAITSYNCPROC __rglgen_glClientWaitSync; RGLSYMGLWAITSYNCPROC __rglgen_glWaitSync; RGLSYMGLGETINTEGER64VPROC __rglgen_glGetInteger64v; RGLSYMGLGETSYNCIVPROC __rglgen_glGetSynciv; RGLSYMGLGETINTEGER64I_VPROC __rglgen_glGetInteger64i_v; RGLSYMGLGETBUFFERPARAMETERI64VPROC __rglgen_glGetBufferParameteri64v; RGLSYMGLFRAMEBUFFERTEXTUREPROC __rglgen_glFramebufferTexture; RGLSYMGLTEXIMAGE2DMULTISAMPLEPROC __rglgen_glTexImage2DMultisample; RGLSYMGLTEXIMAGE3DMULTISAMPLEPROC __rglgen_glTexImage3DMultisample; RGLSYMGLGETMULTISAMPLEFVPROC __rglgen_glGetMultisamplefv; RGLSYMGLSAMPLEMASKIPROC __rglgen_glSampleMaski; RGLSYMGLBINDFRAGDATALOCATIONINDEXEDPROC __rglgen_glBindFragDataLocationIndexed; RGLSYMGLGETFRAGDATAINDEXPROC __rglgen_glGetFragDataIndex; RGLSYMGLGENSAMPLERSPROC __rglgen_glGenSamplers; RGLSYMGLDELETESAMPLERSPROC __rglgen_glDeleteSamplers; RGLSYMGLISSAMPLERPROC __rglgen_glIsSampler; RGLSYMGLBINDSAMPLERPROC __rglgen_glBindSampler; RGLSYMGLSAMPLERPARAMETERIPROC __rglgen_glSamplerParameteri; RGLSYMGLSAMPLERPARAMETERIVPROC __rglgen_glSamplerParameteriv; RGLSYMGLSAMPLERPARAMETERFPROC __rglgen_glSamplerParameterf; RGLSYMGLSAMPLERPARAMETERFVPROC __rglgen_glSamplerParameterfv; RGLSYMGLSAMPLERPARAMETERIIVPROC __rglgen_glSamplerParameterIiv; RGLSYMGLSAMPLERPARAMETERIUIVPROC __rglgen_glSamplerParameterIuiv; RGLSYMGLGETSAMPLERPARAMETERIVPROC __rglgen_glGetSamplerParameteriv; RGLSYMGLGETSAMPLERPARAMETERIIVPROC __rglgen_glGetSamplerParameterIiv; RGLSYMGLGETSAMPLERPARAMETERFVPROC __rglgen_glGetSamplerParameterfv; RGLSYMGLGETSAMPLERPARAMETERIUIVPROC __rglgen_glGetSamplerParameterIuiv; RGLSYMGLQUERYCOUNTERPROC __rglgen_glQueryCounter; RGLSYMGLGETQUERYOBJECTI64VPROC __rglgen_glGetQueryObjecti64v; RGLSYMGLGETQUERYOBJECTUI64VPROC __rglgen_glGetQueryObjectui64v; RGLSYMGLVERTEXATTRIBDIVISORPROC __rglgen_glVertexAttribDivisor; RGLSYMGLVERTEXATTRIBP1UIPROC __rglgen_glVertexAttribP1ui; RGLSYMGLVERTEXATTRIBP1UIVPROC __rglgen_glVertexAttribP1uiv; RGLSYMGLVERTEXATTRIBP2UIPROC __rglgen_glVertexAttribP2ui; RGLSYMGLVERTEXATTRIBP2UIVPROC __rglgen_glVertexAttribP2uiv; RGLSYMGLVERTEXATTRIBP3UIPROC __rglgen_glVertexAttribP3ui; RGLSYMGLVERTEXATTRIBP3UIVPROC __rglgen_glVertexAttribP3uiv; RGLSYMGLVERTEXATTRIBP4UIPROC __rglgen_glVertexAttribP4ui; RGLSYMGLVERTEXATTRIBP4UIVPROC __rglgen_glVertexAttribP4uiv; RGLSYMGLVERTEXP2UIPROC __rglgen_glVertexP2ui; RGLSYMGLVERTEXP2UIVPROC __rglgen_glVertexP2uiv; RGLSYMGLVERTEXP3UIPROC __rglgen_glVertexP3ui; RGLSYMGLVERTEXP3UIVPROC __rglgen_glVertexP3uiv; RGLSYMGLVERTEXP4UIPROC __rglgen_glVertexP4ui; RGLSYMGLVERTEXP4UIVPROC __rglgen_glVertexP4uiv; RGLSYMGLTEXCOORDP1UIPROC __rglgen_glTexCoordP1ui; RGLSYMGLTEXCOORDP1UIVPROC __rglgen_glTexCoordP1uiv; RGLSYMGLTEXCOORDP2UIPROC __rglgen_glTexCoordP2ui; RGLSYMGLTEXCOORDP2UIVPROC __rglgen_glTexCoordP2uiv; RGLSYMGLTEXCOORDP3UIPROC __rglgen_glTexCoordP3ui; RGLSYMGLTEXCOORDP3UIVPROC __rglgen_glTexCoordP3uiv; RGLSYMGLTEXCOORDP4UIPROC __rglgen_glTexCoordP4ui; RGLSYMGLTEXCOORDP4UIVPROC __rglgen_glTexCoordP4uiv; RGLSYMGLMULTITEXCOORDP1UIPROC __rglgen_glMultiTexCoordP1ui; RGLSYMGLMULTITEXCOORDP1UIVPROC __rglgen_glMultiTexCoordP1uiv; RGLSYMGLMULTITEXCOORDP2UIPROC __rglgen_glMultiTexCoordP2ui; RGLSYMGLMULTITEXCOORDP2UIVPROC __rglgen_glMultiTexCoordP2uiv; RGLSYMGLMULTITEXCOORDP3UIPROC __rglgen_glMultiTexCoordP3ui; RGLSYMGLMULTITEXCOORDP3UIVPROC __rglgen_glMultiTexCoordP3uiv; RGLSYMGLMULTITEXCOORDP4UIPROC __rglgen_glMultiTexCoordP4ui; RGLSYMGLMULTITEXCOORDP4UIVPROC __rglgen_glMultiTexCoordP4uiv; RGLSYMGLNORMALP3UIPROC __rglgen_glNormalP3ui; RGLSYMGLNORMALP3UIVPROC __rglgen_glNormalP3uiv; RGLSYMGLCOLORP3UIPROC __rglgen_glColorP3ui; RGLSYMGLCOLORP3UIVPROC __rglgen_glColorP3uiv; RGLSYMGLCOLORP4UIPROC __rglgen_glColorP4ui; RGLSYMGLCOLORP4UIVPROC __rglgen_glColorP4uiv; RGLSYMGLSECONDARYCOLORP3UIPROC __rglgen_glSecondaryColorP3ui; RGLSYMGLSECONDARYCOLORP3UIVPROC __rglgen_glSecondaryColorP3uiv; RGLSYMGLMINSAMPLESHADINGPROC __rglgen_glMinSampleShading; RGLSYMGLBLENDEQUATIONIPROC __rglgen_glBlendEquationi; RGLSYMGLBLENDEQUATIONSEPARATEIPROC __rglgen_glBlendEquationSeparatei; RGLSYMGLBLENDFUNCIPROC __rglgen_glBlendFunci; RGLSYMGLBLENDFUNCSEPARATEIPROC __rglgen_glBlendFuncSeparatei; RGLSYMGLDRAWARRAYSINDIRECTPROC __rglgen_glDrawArraysIndirect; RGLSYMGLDRAWELEMENTSINDIRECTPROC __rglgen_glDrawElementsIndirect; RGLSYMGLUNIFORM1DPROC __rglgen_glUniform1d; RGLSYMGLUNIFORM2DPROC __rglgen_glUniform2d; RGLSYMGLUNIFORM3DPROC __rglgen_glUniform3d; RGLSYMGLUNIFORM4DPROC __rglgen_glUniform4d; RGLSYMGLUNIFORM1DVPROC __rglgen_glUniform1dv; RGLSYMGLUNIFORM2DVPROC __rglgen_glUniform2dv; RGLSYMGLUNIFORM3DVPROC __rglgen_glUniform3dv; RGLSYMGLUNIFORM4DVPROC __rglgen_glUniform4dv; RGLSYMGLUNIFORMMATRIX2DVPROC __rglgen_glUniformMatrix2dv; RGLSYMGLUNIFORMMATRIX3DVPROC __rglgen_glUniformMatrix3dv; RGLSYMGLUNIFORMMATRIX4DVPROC __rglgen_glUniformMatrix4dv; RGLSYMGLUNIFORMMATRIX2X3DVPROC __rglgen_glUniformMatrix2x3dv; RGLSYMGLUNIFORMMATRIX2X4DVPROC __rglgen_glUniformMatrix2x4dv; RGLSYMGLUNIFORMMATRIX3X2DVPROC __rglgen_glUniformMatrix3x2dv; RGLSYMGLUNIFORMMATRIX3X4DVPROC __rglgen_glUniformMatrix3x4dv; RGLSYMGLUNIFORMMATRIX4X2DVPROC __rglgen_glUniformMatrix4x2dv; RGLSYMGLUNIFORMMATRIX4X3DVPROC __rglgen_glUniformMatrix4x3dv; RGLSYMGLGETUNIFORMDVPROC __rglgen_glGetUniformdv; RGLSYMGLGETSUBROUTINEUNIFORMLOCATIONPROC __rglgen_glGetSubroutineUniformLocation; RGLSYMGLGETSUBROUTINEINDEXPROC __rglgen_glGetSubroutineIndex; RGLSYMGLGETACTIVESUBROUTINEUNIFORMIVPROC __rglgen_glGetActiveSubroutineUniformiv; RGLSYMGLGETACTIVESUBROUTINEUNIFORMNAMEPROC __rglgen_glGetActiveSubroutineUniformName; RGLSYMGLGETACTIVESUBROUTINENAMEPROC __rglgen_glGetActiveSubroutineName; RGLSYMGLUNIFORMSUBROUTINESUIVPROC __rglgen_glUniformSubroutinesuiv; RGLSYMGLGETUNIFORMSUBROUTINEUIVPROC __rglgen_glGetUniformSubroutineuiv; RGLSYMGLGETPROGRAMSTAGEIVPROC __rglgen_glGetProgramStageiv; RGLSYMGLPATCHPARAMETERIPROC __rglgen_glPatchParameteri; RGLSYMGLPATCHPARAMETERFVPROC __rglgen_glPatchParameterfv; RGLSYMGLBINDTRANSFORMFEEDBACKPROC __rglgen_glBindTransformFeedback; RGLSYMGLDELETETRANSFORMFEEDBACKSPROC __rglgen_glDeleteTransformFeedbacks; RGLSYMGLGENTRANSFORMFEEDBACKSPROC __rglgen_glGenTransformFeedbacks; RGLSYMGLISTRANSFORMFEEDBACKPROC __rglgen_glIsTransformFeedback; RGLSYMGLPAUSETRANSFORMFEEDBACKPROC __rglgen_glPauseTransformFeedback; RGLSYMGLRESUMETRANSFORMFEEDBACKPROC __rglgen_glResumeTransformFeedback; RGLSYMGLDRAWTRANSFORMFEEDBACKPROC __rglgen_glDrawTransformFeedback; RGLSYMGLDRAWTRANSFORMFEEDBACKSTREAMPROC __rglgen_glDrawTransformFeedbackStream; RGLSYMGLBEGINQUERYINDEXEDPROC __rglgen_glBeginQueryIndexed; RGLSYMGLENDQUERYINDEXEDPROC __rglgen_glEndQueryIndexed; RGLSYMGLGETQUERYINDEXEDIVPROC __rglgen_glGetQueryIndexediv; RGLSYMGLRELEASESHADERCOMPILERPROC __rglgen_glReleaseShaderCompiler; RGLSYMGLSHADERBINARYPROC __rglgen_glShaderBinary; RGLSYMGLGETSHADERPRECISIONFORMATPROC __rglgen_glGetShaderPrecisionFormat; RGLSYMGLDEPTHRANGEFPROC __rglgen_glDepthRangef; RGLSYMGLCLEARDEPTHFPROC __rglgen_glClearDepthf; RGLSYMGLGETPROGRAMBINARYPROC __rglgen_glGetProgramBinary; RGLSYMGLPROGRAMBINARYPROC __rglgen_glProgramBinary; RGLSYMGLPROGRAMPARAMETERIPROC __rglgen_glProgramParameteri; RGLSYMGLUSEPROGRAMSTAGESPROC __rglgen_glUseProgramStages; RGLSYMGLACTIVESHADERPROGRAMPROC __rglgen_glActiveShaderProgram; RGLSYMGLCREATESHADERPROGRAMVPROC __rglgen_glCreateShaderProgramv; RGLSYMGLBINDPROGRAMPIPELINEPROC __rglgen_glBindProgramPipeline; RGLSYMGLDELETEPROGRAMPIPELINESPROC __rglgen_glDeleteProgramPipelines; RGLSYMGLGENPROGRAMPIPELINESPROC __rglgen_glGenProgramPipelines; RGLSYMGLISPROGRAMPIPELINEPROC __rglgen_glIsProgramPipeline; RGLSYMGLGETPROGRAMPIPELINEIVPROC __rglgen_glGetProgramPipelineiv; RGLSYMGLPROGRAMUNIFORM1IPROC __rglgen_glProgramUniform1i; RGLSYMGLPROGRAMUNIFORM1IVPROC __rglgen_glProgramUniform1iv; RGLSYMGLPROGRAMUNIFORM1FPROC __rglgen_glProgramUniform1f; RGLSYMGLPROGRAMUNIFORM1FVPROC __rglgen_glProgramUniform1fv; RGLSYMGLPROGRAMUNIFORM1DPROC __rglgen_glProgramUniform1d; RGLSYMGLPROGRAMUNIFORM1DVPROC __rglgen_glProgramUniform1dv; RGLSYMGLPROGRAMUNIFORM1UIPROC __rglgen_glProgramUniform1ui; RGLSYMGLPROGRAMUNIFORM1UIVPROC __rglgen_glProgramUniform1uiv; RGLSYMGLPROGRAMUNIFORM2IPROC __rglgen_glProgramUniform2i; RGLSYMGLPROGRAMUNIFORM2IVPROC __rglgen_glProgramUniform2iv; RGLSYMGLPROGRAMUNIFORM2FPROC __rglgen_glProgramUniform2f; RGLSYMGLPROGRAMUNIFORM2FVPROC __rglgen_glProgramUniform2fv; RGLSYMGLPROGRAMUNIFORM2DPROC __rglgen_glProgramUniform2d; RGLSYMGLPROGRAMUNIFORM2DVPROC __rglgen_glProgramUniform2dv; RGLSYMGLPROGRAMUNIFORM2UIPROC __rglgen_glProgramUniform2ui; RGLSYMGLPROGRAMUNIFORM2UIVPROC __rglgen_glProgramUniform2uiv; RGLSYMGLPROGRAMUNIFORM3IPROC __rglgen_glProgramUniform3i; RGLSYMGLPROGRAMUNIFORM3IVPROC __rglgen_glProgramUniform3iv; RGLSYMGLPROGRAMUNIFORM3FPROC __rglgen_glProgramUniform3f; RGLSYMGLPROGRAMUNIFORM3FVPROC __rglgen_glProgramUniform3fv; RGLSYMGLPROGRAMUNIFORM3DPROC __rglgen_glProgramUniform3d; RGLSYMGLPROGRAMUNIFORM3DVPROC __rglgen_glProgramUniform3dv; RGLSYMGLPROGRAMUNIFORM3UIPROC __rglgen_glProgramUniform3ui; RGLSYMGLPROGRAMUNIFORM3UIVPROC __rglgen_glProgramUniform3uiv; RGLSYMGLPROGRAMUNIFORM4IPROC __rglgen_glProgramUniform4i; RGLSYMGLPROGRAMUNIFORM4IVPROC __rglgen_glProgramUniform4iv; RGLSYMGLPROGRAMUNIFORM4FPROC __rglgen_glProgramUniform4f; RGLSYMGLPROGRAMUNIFORM4FVPROC __rglgen_glProgramUniform4fv; RGLSYMGLPROGRAMUNIFORM4DPROC __rglgen_glProgramUniform4d; RGLSYMGLPROGRAMUNIFORM4DVPROC __rglgen_glProgramUniform4dv; RGLSYMGLPROGRAMUNIFORM4UIPROC __rglgen_glProgramUniform4ui; RGLSYMGLPROGRAMUNIFORM4UIVPROC __rglgen_glProgramUniform4uiv; RGLSYMGLPROGRAMUNIFORMMATRIX2FVPROC __rglgen_glProgramUniformMatrix2fv; RGLSYMGLPROGRAMUNIFORMMATRIX3FVPROC __rglgen_glProgramUniformMatrix3fv; RGLSYMGLPROGRAMUNIFORMMATRIX4FVPROC __rglgen_glProgramUniformMatrix4fv; RGLSYMGLPROGRAMUNIFORMMATRIX2DVPROC __rglgen_glProgramUniformMatrix2dv; RGLSYMGLPROGRAMUNIFORMMATRIX3DVPROC __rglgen_glProgramUniformMatrix3dv; RGLSYMGLPROGRAMUNIFORMMATRIX4DVPROC __rglgen_glProgramUniformMatrix4dv; RGLSYMGLPROGRAMUNIFORMMATRIX2X3FVPROC __rglgen_glProgramUniformMatrix2x3fv; RGLSYMGLPROGRAMUNIFORMMATRIX3X2FVPROC __rglgen_glProgramUniformMatrix3x2fv; RGLSYMGLPROGRAMUNIFORMMATRIX2X4FVPROC __rglgen_glProgramUniformMatrix2x4fv; RGLSYMGLPROGRAMUNIFORMMATRIX4X2FVPROC __rglgen_glProgramUniformMatrix4x2fv; RGLSYMGLPROGRAMUNIFORMMATRIX3X4FVPROC __rglgen_glProgramUniformMatrix3x4fv; RGLSYMGLPROGRAMUNIFORMMATRIX4X3FVPROC __rglgen_glProgramUniformMatrix4x3fv; RGLSYMGLPROGRAMUNIFORMMATRIX2X3DVPROC __rglgen_glProgramUniformMatrix2x3dv; RGLSYMGLPROGRAMUNIFORMMATRIX3X2DVPROC __rglgen_glProgramUniformMatrix3x2dv; RGLSYMGLPROGRAMUNIFORMMATRIX2X4DVPROC __rglgen_glProgramUniformMatrix2x4dv; RGLSYMGLPROGRAMUNIFORMMATRIX4X2DVPROC __rglgen_glProgramUniformMatrix4x2dv; RGLSYMGLPROGRAMUNIFORMMATRIX3X4DVPROC __rglgen_glProgramUniformMatrix3x4dv; RGLSYMGLPROGRAMUNIFORMMATRIX4X3DVPROC __rglgen_glProgramUniformMatrix4x3dv; RGLSYMGLVALIDATEPROGRAMPIPELINEPROC __rglgen_glValidateProgramPipeline; RGLSYMGLGETPROGRAMPIPELINEINFOLOGPROC __rglgen_glGetProgramPipelineInfoLog; RGLSYMGLVERTEXATTRIBL1DPROC __rglgen_glVertexAttribL1d; RGLSYMGLVERTEXATTRIBL2DPROC __rglgen_glVertexAttribL2d; RGLSYMGLVERTEXATTRIBL3DPROC __rglgen_glVertexAttribL3d; RGLSYMGLVERTEXATTRIBL4DPROC __rglgen_glVertexAttribL4d; RGLSYMGLVERTEXATTRIBL1DVPROC __rglgen_glVertexAttribL1dv; RGLSYMGLVERTEXATTRIBL2DVPROC __rglgen_glVertexAttribL2dv; RGLSYMGLVERTEXATTRIBL3DVPROC __rglgen_glVertexAttribL3dv; RGLSYMGLVERTEXATTRIBL4DVPROC __rglgen_glVertexAttribL4dv; RGLSYMGLVERTEXATTRIBLPOINTERPROC __rglgen_glVertexAttribLPointer; RGLSYMGLGETVERTEXATTRIBLDVPROC __rglgen_glGetVertexAttribLdv; RGLSYMGLVIEWPORTARRAYVPROC __rglgen_glViewportArrayv; RGLSYMGLVIEWPORTINDEXEDFPROC __rglgen_glViewportIndexedf; RGLSYMGLVIEWPORTINDEXEDFVPROC __rglgen_glViewportIndexedfv; RGLSYMGLSCISSORARRAYVPROC __rglgen_glScissorArrayv; RGLSYMGLSCISSORINDEXEDPROC __rglgen_glScissorIndexed; RGLSYMGLSCISSORINDEXEDVPROC __rglgen_glScissorIndexedv; RGLSYMGLDEPTHRANGEARRAYVPROC __rglgen_glDepthRangeArrayv; RGLSYMGLDEPTHRANGEINDEXEDPROC __rglgen_glDepthRangeIndexed; RGLSYMGLGETFLOATI_VPROC __rglgen_glGetFloati_v; RGLSYMGLGETDOUBLEI_VPROC __rglgen_glGetDoublei_v; RGLSYMGLDRAWARRAYSINSTANCEDBASEINSTANCEPROC __rglgen_glDrawArraysInstancedBaseInstance; RGLSYMGLDRAWELEMENTSINSTANCEDBASEINSTANCEPROC __rglgen_glDrawElementsInstancedBaseInstance; RGLSYMGLDRAWELEMENTSINSTANCEDBASEVERTEXBASEINSTANCEPROC __rglgen_glDrawElementsInstancedBaseVertexBaseInstance; RGLSYMGLGETINTERNALFORMATIVPROC __rglgen_glGetInternalformativ; RGLSYMGLGETACTIVEATOMICCOUNTERBUFFERIVPROC __rglgen_glGetActiveAtomicCounterBufferiv; RGLSYMGLBINDIMAGETEXTUREPROC __rglgen_glBindImageTexture; RGLSYMGLMEMORYBARRIERPROC __rglgen_glMemoryBarrier; RGLSYMGLTEXSTORAGE1DPROC __rglgen_glTexStorage1D; RGLSYMGLTEXSTORAGE2DPROC __rglgen_glTexStorage2D; RGLSYMGLTEXSTORAGE3DPROC __rglgen_glTexStorage3D; RGLSYMGLDRAWTRANSFORMFEEDBACKINSTANCEDPROC __rglgen_glDrawTransformFeedbackInstanced; RGLSYMGLDRAWTRANSFORMFEEDBACKSTREAMINSTANCEDPROC __rglgen_glDrawTransformFeedbackStreamInstanced; RGLSYMGLCLEARBUFFERDATAPROC __rglgen_glClearBufferData; RGLSYMGLCLEARBUFFERSUBDATAPROC __rglgen_glClearBufferSubData; RGLSYMGLDISPATCHCOMPUTEPROC __rglgen_glDispatchCompute; RGLSYMGLDISPATCHCOMPUTEINDIRECTPROC __rglgen_glDispatchComputeIndirect; RGLSYMGLCOPYIMAGESUBDATAPROC __rglgen_glCopyImageSubData; RGLSYMGLFRAMEBUFFERPARAMETERIPROC __rglgen_glFramebufferParameteri; RGLSYMGLGETFRAMEBUFFERPARAMETERIVPROC __rglgen_glGetFramebufferParameteriv; RGLSYMGLGETINTERNALFORMATI64VPROC __rglgen_glGetInternalformati64v; RGLSYMGLINVALIDATETEXSUBIMAGEPROC __rglgen_glInvalidateTexSubImage; RGLSYMGLINVALIDATETEXIMAGEPROC __rglgen_glInvalidateTexImage; RGLSYMGLINVALIDATEBUFFERSUBDATAPROC __rglgen_glInvalidateBufferSubData; RGLSYMGLINVALIDATEBUFFERDATAPROC __rglgen_glInvalidateBufferData; RGLSYMGLINVALIDATEFRAMEBUFFERPROC __rglgen_glInvalidateFramebuffer; RGLSYMGLINVALIDATESUBFRAMEBUFFERPROC __rglgen_glInvalidateSubFramebuffer; RGLSYMGLMULTIDRAWARRAYSINDIRECTPROC __rglgen_glMultiDrawArraysIndirect; RGLSYMGLMULTIDRAWELEMENTSINDIRECTPROC __rglgen_glMultiDrawElementsIndirect; RGLSYMGLGETPROGRAMINTERFACEIVPROC __rglgen_glGetProgramInterfaceiv; RGLSYMGLGETPROGRAMRESOURCEINDEXPROC __rglgen_glGetProgramResourceIndex; RGLSYMGLGETPROGRAMRESOURCENAMEPROC __rglgen_glGetProgramResourceName; RGLSYMGLGETPROGRAMRESOURCEIVPROC __rglgen_glGetProgramResourceiv; RGLSYMGLGETPROGRAMRESOURCELOCATIONPROC __rglgen_glGetProgramResourceLocation; RGLSYMGLGETPROGRAMRESOURCELOCATIONINDEXPROC __rglgen_glGetProgramResourceLocationIndex; RGLSYMGLSHADERSTORAGEBLOCKBINDINGPROC __rglgen_glShaderStorageBlockBinding; RGLSYMGLTEXBUFFERRANGEPROC __rglgen_glTexBufferRange; RGLSYMGLTEXSTORAGE2DMULTISAMPLEPROC __rglgen_glTexStorage2DMultisample; RGLSYMGLTEXSTORAGE3DMULTISAMPLEPROC __rglgen_glTexStorage3DMultisample; RGLSYMGLTEXTUREVIEWPROC __rglgen_glTextureView; RGLSYMGLBINDVERTEXBUFFERPROC __rglgen_glBindVertexBuffer; RGLSYMGLVERTEXATTRIBFORMATPROC __rglgen_glVertexAttribFormat; RGLSYMGLVERTEXATTRIBIFORMATPROC __rglgen_glVertexAttribIFormat; RGLSYMGLVERTEXATTRIBLFORMATPROC __rglgen_glVertexAttribLFormat; RGLSYMGLVERTEXATTRIBBINDINGPROC __rglgen_glVertexAttribBinding; RGLSYMGLVERTEXBINDINGDIVISORPROC __rglgen_glVertexBindingDivisor; RGLSYMGLDEBUGMESSAGECONTROLPROC __rglgen_glDebugMessageControl; RGLSYMGLDEBUGMESSAGEINSERTPROC __rglgen_glDebugMessageInsert; RGLSYMGLDEBUGMESSAGECALLBACKPROC __rglgen_glDebugMessageCallback; RGLSYMGLGETDEBUGMESSAGELOGPROC __rglgen_glGetDebugMessageLog; RGLSYMGLPUSHDEBUGGROUPPROC __rglgen_glPushDebugGroup; RGLSYMGLPOPDEBUGGROUPPROC __rglgen_glPopDebugGroup; RGLSYMGLOBJECTLABELPROC __rglgen_glObjectLabel; RGLSYMGLGETOBJECTLABELPROC __rglgen_glGetObjectLabel; RGLSYMGLOBJECTPTRLABELPROC __rglgen_glObjectPtrLabel; RGLSYMGLGETOBJECTPTRLABELPROC __rglgen_glGetObjectPtrLabel; RGLSYMGLBUFFERSTORAGEPROC __rglgen_glBufferStorage; RGLSYMGLCLEARTEXIMAGEPROC __rglgen_glClearTexImage; RGLSYMGLCLEARTEXSUBIMAGEPROC __rglgen_glClearTexSubImage; RGLSYMGLBINDBUFFERSBASEPROC __rglgen_glBindBuffersBase; RGLSYMGLBINDBUFFERSRANGEPROC __rglgen_glBindBuffersRange; RGLSYMGLBINDTEXTURESPROC __rglgen_glBindTextures; RGLSYMGLBINDSAMPLERSPROC __rglgen_glBindSamplers; RGLSYMGLBINDIMAGETEXTURESPROC __rglgen_glBindImageTextures; RGLSYMGLBINDVERTEXBUFFERSPROC __rglgen_glBindVertexBuffers; RGLSYMGLGETTEXTUREHANDLEARBPROC __rglgen_glGetTextureHandleARB; RGLSYMGLGETTEXTURESAMPLERHANDLEARBPROC __rglgen_glGetTextureSamplerHandleARB; RGLSYMGLMAKETEXTUREHANDLERESIDENTARBPROC __rglgen_glMakeTextureHandleResidentARB; RGLSYMGLMAKETEXTUREHANDLENONRESIDENTARBPROC __rglgen_glMakeTextureHandleNonResidentARB; RGLSYMGLGETIMAGEHANDLEARBPROC __rglgen_glGetImageHandleARB; RGLSYMGLMAKEIMAGEHANDLERESIDENTARBPROC __rglgen_glMakeImageHandleResidentARB; RGLSYMGLMAKEIMAGEHANDLENONRESIDENTARBPROC __rglgen_glMakeImageHandleNonResidentARB; RGLSYMGLUNIFORMHANDLEUI64ARBPROC __rglgen_glUniformHandleui64ARB; RGLSYMGLUNIFORMHANDLEUI64VARBPROC __rglgen_glUniformHandleui64vARB; RGLSYMGLPROGRAMUNIFORMHANDLEUI64ARBPROC __rglgen_glProgramUniformHandleui64ARB; RGLSYMGLPROGRAMUNIFORMHANDLEUI64VARBPROC __rglgen_glProgramUniformHandleui64vARB; RGLSYMGLISTEXTUREHANDLERESIDENTARBPROC __rglgen_glIsTextureHandleResidentARB; RGLSYMGLISIMAGEHANDLERESIDENTARBPROC __rglgen_glIsImageHandleResidentARB; RGLSYMGLVERTEXATTRIBL1UI64ARBPROC __rglgen_glVertexAttribL1ui64ARB; RGLSYMGLVERTEXATTRIBL1UI64VARBPROC __rglgen_glVertexAttribL1ui64vARB; RGLSYMGLGETVERTEXATTRIBLUI64VARBPROC __rglgen_glGetVertexAttribLui64vARB; RGLSYMGLCREATESYNCFROMCLEVENTARBPROC __rglgen_glCreateSyncFromCLeventARB; RGLSYMGLCLAMPCOLORARBPROC __rglgen_glClampColorARB; RGLSYMGLDISPATCHCOMPUTEGROUPSIZEARBPROC __rglgen_glDispatchComputeGroupSizeARB; RGLSYMGLDEBUGMESSAGECONTROLARBPROC __rglgen_glDebugMessageControlARB; RGLSYMGLDEBUGMESSAGEINSERTARBPROC __rglgen_glDebugMessageInsertARB; RGLSYMGLDEBUGMESSAGECALLBACKARBPROC __rglgen_glDebugMessageCallbackARB; RGLSYMGLGETDEBUGMESSAGELOGARBPROC __rglgen_glGetDebugMessageLogARB; RGLSYMGLDRAWBUFFERSARBPROC __rglgen_glDrawBuffersARB; RGLSYMGLBLENDEQUATIONIARBPROC __rglgen_glBlendEquationiARB; RGLSYMGLBLENDEQUATIONSEPARATEIARBPROC __rglgen_glBlendEquationSeparateiARB; RGLSYMGLBLENDFUNCIARBPROC __rglgen_glBlendFunciARB; RGLSYMGLBLENDFUNCSEPARATEIARBPROC __rglgen_glBlendFuncSeparateiARB; RGLSYMGLDRAWARRAYSINSTANCEDARBPROC __rglgen_glDrawArraysInstancedARB; RGLSYMGLDRAWELEMENTSINSTANCEDARBPROC __rglgen_glDrawElementsInstancedARB; RGLSYMGLPROGRAMSTRINGARBPROC __rglgen_glProgramStringARB; RGLSYMGLBINDPROGRAMARBPROC __rglgen_glBindProgramARB; RGLSYMGLDELETEPROGRAMSARBPROC __rglgen_glDeleteProgramsARB; RGLSYMGLGENPROGRAMSARBPROC __rglgen_glGenProgramsARB; RGLSYMGLPROGRAMENVPARAMETER4DARBPROC __rglgen_glProgramEnvParameter4dARB; RGLSYMGLPROGRAMENVPARAMETER4DVARBPROC __rglgen_glProgramEnvParameter4dvARB; RGLSYMGLPROGRAMENVPARAMETER4FARBPROC __rglgen_glProgramEnvParameter4fARB; RGLSYMGLPROGRAMENVPARAMETER4FVARBPROC __rglgen_glProgramEnvParameter4fvARB; RGLSYMGLPROGRAMLOCALPARAMETER4DARBPROC __rglgen_glProgramLocalParameter4dARB; RGLSYMGLPROGRAMLOCALPARAMETER4DVARBPROC __rglgen_glProgramLocalParameter4dvARB; RGLSYMGLPROGRAMLOCALPARAMETER4FARBPROC __rglgen_glProgramLocalParameter4fARB; RGLSYMGLPROGRAMLOCALPARAMETER4FVARBPROC __rglgen_glProgramLocalParameter4fvARB; RGLSYMGLGETPROGRAMENVPARAMETERDVARBPROC __rglgen_glGetProgramEnvParameterdvARB; RGLSYMGLGETPROGRAMENVPARAMETERFVARBPROC __rglgen_glGetProgramEnvParameterfvARB; RGLSYMGLGETPROGRAMLOCALPARAMETERDVARBPROC __rglgen_glGetProgramLocalParameterdvARB; RGLSYMGLGETPROGRAMLOCALPARAMETERFVARBPROC __rglgen_glGetProgramLocalParameterfvARB; RGLSYMGLGETPROGRAMIVARBPROC __rglgen_glGetProgramivARB; RGLSYMGLGETPROGRAMSTRINGARBPROC __rglgen_glGetProgramStringARB; RGLSYMGLISPROGRAMARBPROC __rglgen_glIsProgramARB; RGLSYMGLPROGRAMPARAMETERIARBPROC __rglgen_glProgramParameteriARB; RGLSYMGLFRAMEBUFFERTEXTUREARBPROC __rglgen_glFramebufferTextureARB; RGLSYMGLFRAMEBUFFERTEXTURELAYERARBPROC __rglgen_glFramebufferTextureLayerARB; RGLSYMGLFRAMEBUFFERTEXTUREFACEARBPROC __rglgen_glFramebufferTextureFaceARB; RGLSYMGLCOLORTABLEPROC __rglgen_glColorTable; RGLSYMGLCOLORTABLEPARAMETERFVPROC __rglgen_glColorTableParameterfv; RGLSYMGLCOLORTABLEPARAMETERIVPROC __rglgen_glColorTableParameteriv; RGLSYMGLCOPYCOLORTABLEPROC __rglgen_glCopyColorTable; RGLSYMGLGETCOLORTABLEPROC __rglgen_glGetColorTable; RGLSYMGLGETCOLORTABLEPARAMETERFVPROC __rglgen_glGetColorTableParameterfv; RGLSYMGLGETCOLORTABLEPARAMETERIVPROC __rglgen_glGetColorTableParameteriv; RGLSYMGLCOLORSUBTABLEPROC __rglgen_glColorSubTable; RGLSYMGLCOPYCOLORSUBTABLEPROC __rglgen_glCopyColorSubTable; RGLSYMGLCONVOLUTIONFILTER1DPROC __rglgen_glConvolutionFilter1D; RGLSYMGLCONVOLUTIONFILTER2DPROC __rglgen_glConvolutionFilter2D; RGLSYMGLCONVOLUTIONPARAMETERFPROC __rglgen_glConvolutionParameterf; RGLSYMGLCONVOLUTIONPARAMETERFVPROC __rglgen_glConvolutionParameterfv; RGLSYMGLCONVOLUTIONPARAMETERIPROC __rglgen_glConvolutionParameteri; RGLSYMGLCONVOLUTIONPARAMETERIVPROC __rglgen_glConvolutionParameteriv; RGLSYMGLCOPYCONVOLUTIONFILTER1DPROC __rglgen_glCopyConvolutionFilter1D; RGLSYMGLCOPYCONVOLUTIONFILTER2DPROC __rglgen_glCopyConvolutionFilter2D; RGLSYMGLGETCONVOLUTIONFILTERPROC __rglgen_glGetConvolutionFilter; RGLSYMGLGETCONVOLUTIONPARAMETERFVPROC __rglgen_glGetConvolutionParameterfv; RGLSYMGLGETCONVOLUTIONPARAMETERIVPROC __rglgen_glGetConvolutionParameteriv; RGLSYMGLGETSEPARABLEFILTERPROC __rglgen_glGetSeparableFilter; RGLSYMGLSEPARABLEFILTER2DPROC __rglgen_glSeparableFilter2D; RGLSYMGLGETHISTOGRAMPROC __rglgen_glGetHistogram; RGLSYMGLGETHISTOGRAMPARAMETERFVPROC __rglgen_glGetHistogramParameterfv; RGLSYMGLGETHISTOGRAMPARAMETERIVPROC __rglgen_glGetHistogramParameteriv; RGLSYMGLGETMINMAXPROC __rglgen_glGetMinmax; RGLSYMGLGETMINMAXPARAMETERFVPROC __rglgen_glGetMinmaxParameterfv; RGLSYMGLGETMINMAXPARAMETERIVPROC __rglgen_glGetMinmaxParameteriv; RGLSYMGLHISTOGRAMPROC __rglgen_glHistogram; RGLSYMGLMINMAXPROC __rglgen_glMinmax; RGLSYMGLRESETHISTOGRAMPROC __rglgen_glResetHistogram; RGLSYMGLRESETMINMAXPROC __rglgen_glResetMinmax; RGLSYMGLMULTIDRAWARRAYSINDIRECTCOUNTARBPROC __rglgen_glMultiDrawArraysIndirectCountARB; RGLSYMGLMULTIDRAWELEMENTSINDIRECTCOUNTARBPROC __rglgen_glMultiDrawElementsIndirectCountARB; RGLSYMGLVERTEXATTRIBDIVISORARBPROC __rglgen_glVertexAttribDivisorARB; RGLSYMGLCURRENTPALETTEMATRIXARBPROC __rglgen_glCurrentPaletteMatrixARB; RGLSYMGLMATRIXINDEXUBVARBPROC __rglgen_glMatrixIndexubvARB; RGLSYMGLMATRIXINDEXUSVARBPROC __rglgen_glMatrixIndexusvARB; RGLSYMGLMATRIXINDEXUIVARBPROC __rglgen_glMatrixIndexuivARB; RGLSYMGLMATRIXINDEXPOINTERARBPROC __rglgen_glMatrixIndexPointerARB; RGLSYMGLSAMPLECOVERAGEARBPROC __rglgen_glSampleCoverageARB; RGLSYMGLACTIVETEXTUREARBPROC __rglgen_glActiveTextureARB; RGLSYMGLCLIENTACTIVETEXTUREARBPROC __rglgen_glClientActiveTextureARB; RGLSYMGLMULTITEXCOORD1DARBPROC __rglgen_glMultiTexCoord1dARB; RGLSYMGLMULTITEXCOORD1DVARBPROC __rglgen_glMultiTexCoord1dvARB; RGLSYMGLMULTITEXCOORD1FARBPROC __rglgen_glMultiTexCoord1fARB; RGLSYMGLMULTITEXCOORD1FVARBPROC __rglgen_glMultiTexCoord1fvARB; RGLSYMGLMULTITEXCOORD1IARBPROC __rglgen_glMultiTexCoord1iARB; RGLSYMGLMULTITEXCOORD1IVARBPROC __rglgen_glMultiTexCoord1ivARB; RGLSYMGLMULTITEXCOORD1SARBPROC __rglgen_glMultiTexCoord1sARB; RGLSYMGLMULTITEXCOORD1SVARBPROC __rglgen_glMultiTexCoord1svARB; RGLSYMGLMULTITEXCOORD2DARBPROC __rglgen_glMultiTexCoord2dARB; RGLSYMGLMULTITEXCOORD2DVARBPROC __rglgen_glMultiTexCoord2dvARB; RGLSYMGLMULTITEXCOORD2FARBPROC __rglgen_glMultiTexCoord2fARB; RGLSYMGLMULTITEXCOORD2FVARBPROC __rglgen_glMultiTexCoord2fvARB; RGLSYMGLMULTITEXCOORD2IARBPROC __rglgen_glMultiTexCoord2iARB; RGLSYMGLMULTITEXCOORD2IVARBPROC __rglgen_glMultiTexCoord2ivARB; RGLSYMGLMULTITEXCOORD2SARBPROC __rglgen_glMultiTexCoord2sARB; RGLSYMGLMULTITEXCOORD2SVARBPROC __rglgen_glMultiTexCoord2svARB; RGLSYMGLMULTITEXCOORD3DARBPROC __rglgen_glMultiTexCoord3dARB; RGLSYMGLMULTITEXCOORD3DVARBPROC __rglgen_glMultiTexCoord3dvARB; RGLSYMGLMULTITEXCOORD3FARBPROC __rglgen_glMultiTexCoord3fARB; RGLSYMGLMULTITEXCOORD3FVARBPROC __rglgen_glMultiTexCoord3fvARB; RGLSYMGLMULTITEXCOORD3IARBPROC __rglgen_glMultiTexCoord3iARB; RGLSYMGLMULTITEXCOORD3IVARBPROC __rglgen_glMultiTexCoord3ivARB; RGLSYMGLMULTITEXCOORD3SARBPROC __rglgen_glMultiTexCoord3sARB; RGLSYMGLMULTITEXCOORD3SVARBPROC __rglgen_glMultiTexCoord3svARB; RGLSYMGLMULTITEXCOORD4DARBPROC __rglgen_glMultiTexCoord4dARB; RGLSYMGLMULTITEXCOORD4DVARBPROC __rglgen_glMultiTexCoord4dvARB; RGLSYMGLMULTITEXCOORD4FARBPROC __rglgen_glMultiTexCoord4fARB; RGLSYMGLMULTITEXCOORD4FVARBPROC __rglgen_glMultiTexCoord4fvARB; RGLSYMGLMULTITEXCOORD4IARBPROC __rglgen_glMultiTexCoord4iARB; RGLSYMGLMULTITEXCOORD4IVARBPROC __rglgen_glMultiTexCoord4ivARB; RGLSYMGLMULTITEXCOORD4SARBPROC __rglgen_glMultiTexCoord4sARB; RGLSYMGLMULTITEXCOORD4SVARBPROC __rglgen_glMultiTexCoord4svARB; RGLSYMGLGENQUERIESARBPROC __rglgen_glGenQueriesARB; RGLSYMGLDELETEQUERIESARBPROC __rglgen_glDeleteQueriesARB; RGLSYMGLISQUERYARBPROC __rglgen_glIsQueryARB; RGLSYMGLBEGINQUERYARBPROC __rglgen_glBeginQueryARB; RGLSYMGLENDQUERYARBPROC __rglgen_glEndQueryARB; RGLSYMGLGETQUERYIVARBPROC __rglgen_glGetQueryivARB; RGLSYMGLGETQUERYOBJECTIVARBPROC __rglgen_glGetQueryObjectivARB; RGLSYMGLGETQUERYOBJECTUIVARBPROC __rglgen_glGetQueryObjectuivARB; RGLSYMGLPOINTPARAMETERFARBPROC __rglgen_glPointParameterfARB; RGLSYMGLPOINTPARAMETERFVARBPROC __rglgen_glPointParameterfvARB; RGLSYMGLGETGRAPHICSRESETSTATUSARBPROC __rglgen_glGetGraphicsResetStatusARB; RGLSYMGLGETNTEXIMAGEARBPROC __rglgen_glGetnTexImageARB; RGLSYMGLREADNPIXELSARBPROC __rglgen_glReadnPixelsARB; RGLSYMGLGETNCOMPRESSEDTEXIMAGEARBPROC __rglgen_glGetnCompressedTexImageARB; RGLSYMGLGETNUNIFORMFVARBPROC __rglgen_glGetnUniformfvARB; RGLSYMGLGETNUNIFORMIVARBPROC __rglgen_glGetnUniformivARB; RGLSYMGLGETNUNIFORMUIVARBPROC __rglgen_glGetnUniformuivARB; RGLSYMGLGETNUNIFORMDVARBPROC __rglgen_glGetnUniformdvARB; RGLSYMGLGETNMAPDVARBPROC __rglgen_glGetnMapdvARB; RGLSYMGLGETNMAPFVARBPROC __rglgen_glGetnMapfvARB; RGLSYMGLGETNMAPIVARBPROC __rglgen_glGetnMapivARB; RGLSYMGLGETNPIXELMAPFVARBPROC __rglgen_glGetnPixelMapfvARB; RGLSYMGLGETNPIXELMAPUIVARBPROC __rglgen_glGetnPixelMapuivARB; RGLSYMGLGETNPIXELMAPUSVARBPROC __rglgen_glGetnPixelMapusvARB; RGLSYMGLGETNPOLYGONSTIPPLEARBPROC __rglgen_glGetnPolygonStippleARB; RGLSYMGLGETNCOLORTABLEARBPROC __rglgen_glGetnColorTableARB; RGLSYMGLGETNCONVOLUTIONFILTERARBPROC __rglgen_glGetnConvolutionFilterARB; RGLSYMGLGETNSEPARABLEFILTERARBPROC __rglgen_glGetnSeparableFilterARB; RGLSYMGLGETNHISTOGRAMARBPROC __rglgen_glGetnHistogramARB; RGLSYMGLGETNMINMAXARBPROC __rglgen_glGetnMinmaxARB; RGLSYMGLMINSAMPLESHADINGARBPROC __rglgen_glMinSampleShadingARB; RGLSYMGLDELETEOBJECTARBPROC __rglgen_glDeleteObjectARB; RGLSYMGLGETHANDLEARBPROC __rglgen_glGetHandleARB; RGLSYMGLDETACHOBJECTARBPROC __rglgen_glDetachObjectARB; RGLSYMGLCREATESHADEROBJECTARBPROC __rglgen_glCreateShaderObjectARB; RGLSYMGLSHADERSOURCEARBPROC __rglgen_glShaderSourceARB; RGLSYMGLCOMPILESHADERARBPROC __rglgen_glCompileShaderARB; RGLSYMGLCREATEPROGRAMOBJECTARBPROC __rglgen_glCreateProgramObjectARB; RGLSYMGLATTACHOBJECTARBPROC __rglgen_glAttachObjectARB; RGLSYMGLLINKPROGRAMARBPROC __rglgen_glLinkProgramARB; RGLSYMGLUSEPROGRAMOBJECTARBPROC __rglgen_glUseProgramObjectARB; RGLSYMGLVALIDATEPROGRAMARBPROC __rglgen_glValidateProgramARB; RGLSYMGLUNIFORM1FARBPROC __rglgen_glUniform1fARB; RGLSYMGLUNIFORM2FARBPROC __rglgen_glUniform2fARB; RGLSYMGLUNIFORM3FARBPROC __rglgen_glUniform3fARB; RGLSYMGLUNIFORM4FARBPROC __rglgen_glUniform4fARB; RGLSYMGLUNIFORM1IARBPROC __rglgen_glUniform1iARB; RGLSYMGLUNIFORM2IARBPROC __rglgen_glUniform2iARB; RGLSYMGLUNIFORM3IARBPROC __rglgen_glUniform3iARB; RGLSYMGLUNIFORM4IARBPROC __rglgen_glUniform4iARB; RGLSYMGLUNIFORM1FVARBPROC __rglgen_glUniform1fvARB; RGLSYMGLUNIFORM2FVARBPROC __rglgen_glUniform2fvARB; RGLSYMGLUNIFORM3FVARBPROC __rglgen_glUniform3fvARB; RGLSYMGLUNIFORM4FVARBPROC __rglgen_glUniform4fvARB; RGLSYMGLUNIFORM1IVARBPROC __rglgen_glUniform1ivARB; RGLSYMGLUNIFORM2IVARBPROC __rglgen_glUniform2ivARB; RGLSYMGLUNIFORM3IVARBPROC __rglgen_glUniform3ivARB; RGLSYMGLUNIFORM4IVARBPROC __rglgen_glUniform4ivARB; RGLSYMGLUNIFORMMATRIX2FVARBPROC __rglgen_glUniformMatrix2fvARB; RGLSYMGLUNIFORMMATRIX3FVARBPROC __rglgen_glUniformMatrix3fvARB; RGLSYMGLUNIFORMMATRIX4FVARBPROC __rglgen_glUniformMatrix4fvARB; RGLSYMGLGETOBJECTPARAMETERFVARBPROC __rglgen_glGetObjectParameterfvARB; RGLSYMGLGETOBJECTPARAMETERIVARBPROC __rglgen_glGetObjectParameterivARB; RGLSYMGLGETINFOLOGARBPROC __rglgen_glGetInfoLogARB; RGLSYMGLGETATTACHEDOBJECTSARBPROC __rglgen_glGetAttachedObjectsARB; RGLSYMGLGETUNIFORMLOCATIONARBPROC __rglgen_glGetUniformLocationARB; RGLSYMGLGETACTIVEUNIFORMARBPROC __rglgen_glGetActiveUniformARB; RGLSYMGLGETUNIFORMFVARBPROC __rglgen_glGetUniformfvARB; RGLSYMGLGETUNIFORMIVARBPROC __rglgen_glGetUniformivARB; RGLSYMGLGETSHADERSOURCEARBPROC __rglgen_glGetShaderSourceARB; RGLSYMGLNAMEDSTRINGARBPROC __rglgen_glNamedStringARB; RGLSYMGLDELETENAMEDSTRINGARBPROC __rglgen_glDeleteNamedStringARB; RGLSYMGLCOMPILESHADERINCLUDEARBPROC __rglgen_glCompileShaderIncludeARB; RGLSYMGLISNAMEDSTRINGARBPROC __rglgen_glIsNamedStringARB; RGLSYMGLGETNAMEDSTRINGARBPROC __rglgen_glGetNamedStringARB; RGLSYMGLGETNAMEDSTRINGIVARBPROC __rglgen_glGetNamedStringivARB; RGLSYMGLTEXPAGECOMMITMENTARBPROC __rglgen_glTexPageCommitmentARB; RGLSYMGLTEXBUFFERARBPROC __rglgen_glTexBufferARB; RGLSYMGLCOMPRESSEDTEXIMAGE3DARBPROC __rglgen_glCompressedTexImage3DARB; RGLSYMGLCOMPRESSEDTEXIMAGE2DARBPROC __rglgen_glCompressedTexImage2DARB; RGLSYMGLCOMPRESSEDTEXIMAGE1DARBPROC __rglgen_glCompressedTexImage1DARB; RGLSYMGLCOMPRESSEDTEXSUBIMAGE3DARBPROC __rglgen_glCompressedTexSubImage3DARB; RGLSYMGLCOMPRESSEDTEXSUBIMAGE2DARBPROC __rglgen_glCompressedTexSubImage2DARB; RGLSYMGLCOMPRESSEDTEXSUBIMAGE1DARBPROC __rglgen_glCompressedTexSubImage1DARB; RGLSYMGLGETCOMPRESSEDTEXIMAGEARBPROC __rglgen_glGetCompressedTexImageARB; RGLSYMGLLOADTRANSPOSEMATRIXFARBPROC __rglgen_glLoadTransposeMatrixfARB; RGLSYMGLLOADTRANSPOSEMATRIXDARBPROC __rglgen_glLoadTransposeMatrixdARB; RGLSYMGLMULTTRANSPOSEMATRIXFARBPROC __rglgen_glMultTransposeMatrixfARB; RGLSYMGLMULTTRANSPOSEMATRIXDARBPROC __rglgen_glMultTransposeMatrixdARB; RGLSYMGLWEIGHTBVARBPROC __rglgen_glWeightbvARB; RGLSYMGLWEIGHTSVARBPROC __rglgen_glWeightsvARB; RGLSYMGLWEIGHTIVARBPROC __rglgen_glWeightivARB; RGLSYMGLWEIGHTFVARBPROC __rglgen_glWeightfvARB; RGLSYMGLWEIGHTDVARBPROC __rglgen_glWeightdvARB; RGLSYMGLWEIGHTUBVARBPROC __rglgen_glWeightubvARB; RGLSYMGLWEIGHTUSVARBPROC __rglgen_glWeightusvARB; RGLSYMGLWEIGHTUIVARBPROC __rglgen_glWeightuivARB; RGLSYMGLWEIGHTPOINTERARBPROC __rglgen_glWeightPointerARB; RGLSYMGLVERTEXBLENDARBPROC __rglgen_glVertexBlendARB; RGLSYMGLBINDBUFFERARBPROC __rglgen_glBindBufferARB; RGLSYMGLDELETEBUFFERSARBPROC __rglgen_glDeleteBuffersARB; RGLSYMGLGENBUFFERSARBPROC __rglgen_glGenBuffersARB; RGLSYMGLISBUFFERARBPROC __rglgen_glIsBufferARB; RGLSYMGLBUFFERDATAARBPROC __rglgen_glBufferDataARB; RGLSYMGLBUFFERSUBDATAARBPROC __rglgen_glBufferSubDataARB; RGLSYMGLGETBUFFERSUBDATAARBPROC __rglgen_glGetBufferSubDataARB; RGLSYMGLMAPBUFFERARBPROC __rglgen_glMapBufferARB; RGLSYMGLUNMAPBUFFERARBPROC __rglgen_glUnmapBufferARB; RGLSYMGLGETBUFFERPARAMETERIVARBPROC __rglgen_glGetBufferParameterivARB; RGLSYMGLGETBUFFERPOINTERVARBPROC __rglgen_glGetBufferPointervARB; RGLSYMGLVERTEXATTRIB1DARBPROC __rglgen_glVertexAttrib1dARB; RGLSYMGLVERTEXATTRIB1DVARBPROC __rglgen_glVertexAttrib1dvARB; RGLSYMGLVERTEXATTRIB1FARBPROC __rglgen_glVertexAttrib1fARB; RGLSYMGLVERTEXATTRIB1FVARBPROC __rglgen_glVertexAttrib1fvARB; RGLSYMGLVERTEXATTRIB1SARBPROC __rglgen_glVertexAttrib1sARB; RGLSYMGLVERTEXATTRIB1SVARBPROC __rglgen_glVertexAttrib1svARB; RGLSYMGLVERTEXATTRIB2DARBPROC __rglgen_glVertexAttrib2dARB; RGLSYMGLVERTEXATTRIB2DVARBPROC __rglgen_glVertexAttrib2dvARB; RGLSYMGLVERTEXATTRIB2FARBPROC __rglgen_glVertexAttrib2fARB; RGLSYMGLVERTEXATTRIB2FVARBPROC __rglgen_glVertexAttrib2fvARB; RGLSYMGLVERTEXATTRIB2SARBPROC __rglgen_glVertexAttrib2sARB; RGLSYMGLVERTEXATTRIB2SVARBPROC __rglgen_glVertexAttrib2svARB; RGLSYMGLVERTEXATTRIB3DARBPROC __rglgen_glVertexAttrib3dARB; RGLSYMGLVERTEXATTRIB3DVARBPROC __rglgen_glVertexAttrib3dvARB; RGLSYMGLVERTEXATTRIB3FARBPROC __rglgen_glVertexAttrib3fARB; RGLSYMGLVERTEXATTRIB3FVARBPROC __rglgen_glVertexAttrib3fvARB; RGLSYMGLVERTEXATTRIB3SARBPROC __rglgen_glVertexAttrib3sARB; RGLSYMGLVERTEXATTRIB3SVARBPROC __rglgen_glVertexAttrib3svARB; RGLSYMGLVERTEXATTRIB4NBVARBPROC __rglgen_glVertexAttrib4NbvARB; RGLSYMGLVERTEXATTRIB4NIVARBPROC __rglgen_glVertexAttrib4NivARB; RGLSYMGLVERTEXATTRIB4NSVARBPROC __rglgen_glVertexAttrib4NsvARB; RGLSYMGLVERTEXATTRIB4NUBARBPROC __rglgen_glVertexAttrib4NubARB; RGLSYMGLVERTEXATTRIB4NUBVARBPROC __rglgen_glVertexAttrib4NubvARB; RGLSYMGLVERTEXATTRIB4NUIVARBPROC __rglgen_glVertexAttrib4NuivARB; RGLSYMGLVERTEXATTRIB4NUSVARBPROC __rglgen_glVertexAttrib4NusvARB; RGLSYMGLVERTEXATTRIB4BVARBPROC __rglgen_glVertexAttrib4bvARB; RGLSYMGLVERTEXATTRIB4DARBPROC __rglgen_glVertexAttrib4dARB; RGLSYMGLVERTEXATTRIB4DVARBPROC __rglgen_glVertexAttrib4dvARB; RGLSYMGLVERTEXATTRIB4FARBPROC __rglgen_glVertexAttrib4fARB; RGLSYMGLVERTEXATTRIB4FVARBPROC __rglgen_glVertexAttrib4fvARB; RGLSYMGLVERTEXATTRIB4IVARBPROC __rglgen_glVertexAttrib4ivARB; RGLSYMGLVERTEXATTRIB4SARBPROC __rglgen_glVertexAttrib4sARB; RGLSYMGLVERTEXATTRIB4SVARBPROC __rglgen_glVertexAttrib4svARB; RGLSYMGLVERTEXATTRIB4UBVARBPROC __rglgen_glVertexAttrib4ubvARB; RGLSYMGLVERTEXATTRIB4UIVARBPROC __rglgen_glVertexAttrib4uivARB; RGLSYMGLVERTEXATTRIB4USVARBPROC __rglgen_glVertexAttrib4usvARB; RGLSYMGLVERTEXATTRIBPOINTERARBPROC __rglgen_glVertexAttribPointerARB; RGLSYMGLENABLEVERTEXATTRIBARRAYARBPROC __rglgen_glEnableVertexAttribArrayARB; RGLSYMGLDISABLEVERTEXATTRIBARRAYARBPROC __rglgen_glDisableVertexAttribArrayARB; RGLSYMGLGETVERTEXATTRIBDVARBPROC __rglgen_glGetVertexAttribdvARB; RGLSYMGLGETVERTEXATTRIBFVARBPROC __rglgen_glGetVertexAttribfvARB; RGLSYMGLGETVERTEXATTRIBIVARBPROC __rglgen_glGetVertexAttribivARB; RGLSYMGLGETVERTEXATTRIBPOINTERVARBPROC __rglgen_glGetVertexAttribPointervARB; RGLSYMGLBINDATTRIBLOCATIONARBPROC __rglgen_glBindAttribLocationARB; RGLSYMGLGETACTIVEATTRIBARBPROC __rglgen_glGetActiveAttribARB; RGLSYMGLGETATTRIBLOCATIONARBPROC __rglgen_glGetAttribLocationARB; RGLSYMGLWINDOWPOS2DARBPROC __rglgen_glWindowPos2dARB; RGLSYMGLWINDOWPOS2DVARBPROC __rglgen_glWindowPos2dvARB; RGLSYMGLWINDOWPOS2FARBPROC __rglgen_glWindowPos2fARB; RGLSYMGLWINDOWPOS2FVARBPROC __rglgen_glWindowPos2fvARB; RGLSYMGLWINDOWPOS2IARBPROC __rglgen_glWindowPos2iARB; RGLSYMGLWINDOWPOS2IVARBPROC __rglgen_glWindowPos2ivARB; RGLSYMGLWINDOWPOS2SARBPROC __rglgen_glWindowPos2sARB; RGLSYMGLWINDOWPOS2SVARBPROC __rglgen_glWindowPos2svARB; RGLSYMGLWINDOWPOS3DARBPROC __rglgen_glWindowPos3dARB; RGLSYMGLWINDOWPOS3DVARBPROC __rglgen_glWindowPos3dvARB; RGLSYMGLWINDOWPOS3FARBPROC __rglgen_glWindowPos3fARB; RGLSYMGLWINDOWPOS3FVARBPROC __rglgen_glWindowPos3fvARB; RGLSYMGLWINDOWPOS3IARBPROC __rglgen_glWindowPos3iARB; RGLSYMGLWINDOWPOS3IVARBPROC __rglgen_glWindowPos3ivARB; RGLSYMGLWINDOWPOS3SARBPROC __rglgen_glWindowPos3sARB; RGLSYMGLWINDOWPOS3SVARBPROC __rglgen_glWindowPos3svARB; RGLSYMGLMULTITEXCOORD1BOESPROC __rglgen_glMultiTexCoord1bOES; RGLSYMGLMULTITEXCOORD1BVOESPROC __rglgen_glMultiTexCoord1bvOES; RGLSYMGLMULTITEXCOORD2BOESPROC __rglgen_glMultiTexCoord2bOES; RGLSYMGLMULTITEXCOORD2BVOESPROC __rglgen_glMultiTexCoord2bvOES; RGLSYMGLMULTITEXCOORD3BOESPROC __rglgen_glMultiTexCoord3bOES; RGLSYMGLMULTITEXCOORD3BVOESPROC __rglgen_glMultiTexCoord3bvOES; RGLSYMGLMULTITEXCOORD4BOESPROC __rglgen_glMultiTexCoord4bOES; RGLSYMGLMULTITEXCOORD4BVOESPROC __rglgen_glMultiTexCoord4bvOES; RGLSYMGLTEXCOORD1BOESPROC __rglgen_glTexCoord1bOES; RGLSYMGLTEXCOORD1BVOESPROC __rglgen_glTexCoord1bvOES; RGLSYMGLTEXCOORD2BOESPROC __rglgen_glTexCoord2bOES; RGLSYMGLTEXCOORD2BVOESPROC __rglgen_glTexCoord2bvOES; RGLSYMGLTEXCOORD3BOESPROC __rglgen_glTexCoord3bOES; RGLSYMGLTEXCOORD3BVOESPROC __rglgen_glTexCoord3bvOES; RGLSYMGLTEXCOORD4BOESPROC __rglgen_glTexCoord4bOES; RGLSYMGLTEXCOORD4BVOESPROC __rglgen_glTexCoord4bvOES; RGLSYMGLVERTEX2BOESPROC __rglgen_glVertex2bOES; RGLSYMGLVERTEX2BVOESPROC __rglgen_glVertex2bvOES; RGLSYMGLVERTEX3BOESPROC __rglgen_glVertex3bOES; RGLSYMGLVERTEX3BVOESPROC __rglgen_glVertex3bvOES; RGLSYMGLVERTEX4BOESPROC __rglgen_glVertex4bOES; RGLSYMGLVERTEX4BVOESPROC __rglgen_glVertex4bvOES; RGLSYMGLALPHAFUNCXOESPROC __rglgen_glAlphaFuncxOES; RGLSYMGLCLEARCOLORXOESPROC __rglgen_glClearColorxOES; RGLSYMGLCLEARDEPTHXOESPROC __rglgen_glClearDepthxOES; RGLSYMGLCLIPPLANEXOESPROC __rglgen_glClipPlanexOES; RGLSYMGLCOLOR4XOESPROC __rglgen_glColor4xOES; RGLSYMGLDEPTHRANGEXOESPROC __rglgen_glDepthRangexOES; RGLSYMGLFOGXOESPROC __rglgen_glFogxOES; RGLSYMGLFOGXVOESPROC __rglgen_glFogxvOES; RGLSYMGLFRUSTUMXOESPROC __rglgen_glFrustumxOES; RGLSYMGLGETCLIPPLANEXOESPROC __rglgen_glGetClipPlanexOES; RGLSYMGLGETFIXEDVOESPROC __rglgen_glGetFixedvOES; RGLSYMGLGETTEXENVXVOESPROC __rglgen_glGetTexEnvxvOES; RGLSYMGLGETTEXPARAMETERXVOESPROC __rglgen_glGetTexParameterxvOES; RGLSYMGLLIGHTMODELXOESPROC __rglgen_glLightModelxOES; RGLSYMGLLIGHTMODELXVOESPROC __rglgen_glLightModelxvOES; RGLSYMGLLIGHTXOESPROC __rglgen_glLightxOES; RGLSYMGLLIGHTXVOESPROC __rglgen_glLightxvOES; RGLSYMGLLINEWIDTHXOESPROC __rglgen_glLineWidthxOES; RGLSYMGLLOADMATRIXXOESPROC __rglgen_glLoadMatrixxOES; RGLSYMGLMATERIALXOESPROC __rglgen_glMaterialxOES; RGLSYMGLMATERIALXVOESPROC __rglgen_glMaterialxvOES; RGLSYMGLMULTMATRIXXOESPROC __rglgen_glMultMatrixxOES; RGLSYMGLMULTITEXCOORD4XOESPROC __rglgen_glMultiTexCoord4xOES; RGLSYMGLNORMAL3XOESPROC __rglgen_glNormal3xOES; RGLSYMGLORTHOXOESPROC __rglgen_glOrthoxOES; RGLSYMGLPOINTPARAMETERXVOESPROC __rglgen_glPointParameterxvOES; RGLSYMGLPOINTSIZEXOESPROC __rglgen_glPointSizexOES; RGLSYMGLPOLYGONOFFSETXOESPROC __rglgen_glPolygonOffsetxOES; RGLSYMGLROTATEXOESPROC __rglgen_glRotatexOES; RGLSYMGLSAMPLECOVERAGEOESPROC __rglgen_glSampleCoverageOES; RGLSYMGLSCALEXOESPROC __rglgen_glScalexOES; RGLSYMGLTEXENVXOESPROC __rglgen_glTexEnvxOES; RGLSYMGLTEXENVXVOESPROC __rglgen_glTexEnvxvOES; RGLSYMGLTEXPARAMETERXOESPROC __rglgen_glTexParameterxOES; RGLSYMGLTEXPARAMETERXVOESPROC __rglgen_glTexParameterxvOES; RGLSYMGLTRANSLATEXOESPROC __rglgen_glTranslatexOES; RGLSYMGLACCUMXOESPROC __rglgen_glAccumxOES; RGLSYMGLBITMAPXOESPROC __rglgen_glBitmapxOES; RGLSYMGLBLENDCOLORXOESPROC __rglgen_glBlendColorxOES; RGLSYMGLCLEARACCUMXOESPROC __rglgen_glClearAccumxOES; RGLSYMGLCOLOR3XOESPROC __rglgen_glColor3xOES; RGLSYMGLCOLOR3XVOESPROC __rglgen_glColor3xvOES; RGLSYMGLCOLOR4XVOESPROC __rglgen_glColor4xvOES; RGLSYMGLCONVOLUTIONPARAMETERXOESPROC __rglgen_glConvolutionParameterxOES; RGLSYMGLCONVOLUTIONPARAMETERXVOESPROC __rglgen_glConvolutionParameterxvOES; RGLSYMGLEVALCOORD1XOESPROC __rglgen_glEvalCoord1xOES; RGLSYMGLEVALCOORD1XVOESPROC __rglgen_glEvalCoord1xvOES; RGLSYMGLEVALCOORD2XOESPROC __rglgen_glEvalCoord2xOES; RGLSYMGLEVALCOORD2XVOESPROC __rglgen_glEvalCoord2xvOES; RGLSYMGLFEEDBACKBUFFERXOESPROC __rglgen_glFeedbackBufferxOES; RGLSYMGLGETCONVOLUTIONPARAMETERXVOESPROC __rglgen_glGetConvolutionParameterxvOES; RGLSYMGLGETHISTOGRAMPARAMETERXVOESPROC __rglgen_glGetHistogramParameterxvOES; RGLSYMGLGETLIGHTXOESPROC __rglgen_glGetLightxOES; RGLSYMGLGETMAPXVOESPROC __rglgen_glGetMapxvOES; RGLSYMGLGETMATERIALXOESPROC __rglgen_glGetMaterialxOES; RGLSYMGLGETPIXELMAPXVPROC __rglgen_glGetPixelMapxv; RGLSYMGLGETTEXGENXVOESPROC __rglgen_glGetTexGenxvOES; RGLSYMGLGETTEXLEVELPARAMETERXVOESPROC __rglgen_glGetTexLevelParameterxvOES; RGLSYMGLINDEXXOESPROC __rglgen_glIndexxOES; RGLSYMGLINDEXXVOESPROC __rglgen_glIndexxvOES; RGLSYMGLLOADTRANSPOSEMATRIXXOESPROC __rglgen_glLoadTransposeMatrixxOES; RGLSYMGLMAP1XOESPROC __rglgen_glMap1xOES; RGLSYMGLMAP2XOESPROC __rglgen_glMap2xOES; RGLSYMGLMAPGRID1XOESPROC __rglgen_glMapGrid1xOES; RGLSYMGLMAPGRID2XOESPROC __rglgen_glMapGrid2xOES; RGLSYMGLMULTTRANSPOSEMATRIXXOESPROC __rglgen_glMultTransposeMatrixxOES; RGLSYMGLMULTITEXCOORD1XOESPROC __rglgen_glMultiTexCoord1xOES; RGLSYMGLMULTITEXCOORD1XVOESPROC __rglgen_glMultiTexCoord1xvOES; RGLSYMGLMULTITEXCOORD2XOESPROC __rglgen_glMultiTexCoord2xOES; RGLSYMGLMULTITEXCOORD2XVOESPROC __rglgen_glMultiTexCoord2xvOES; RGLSYMGLMULTITEXCOORD3XOESPROC __rglgen_glMultiTexCoord3xOES; RGLSYMGLMULTITEXCOORD3XVOESPROC __rglgen_glMultiTexCoord3xvOES; RGLSYMGLMULTITEXCOORD4XVOESPROC __rglgen_glMultiTexCoord4xvOES; RGLSYMGLNORMAL3XVOESPROC __rglgen_glNormal3xvOES; RGLSYMGLPASSTHROUGHXOESPROC __rglgen_glPassThroughxOES; RGLSYMGLPIXELMAPXPROC __rglgen_glPixelMapx; RGLSYMGLPIXELSTOREXPROC __rglgen_glPixelStorex; RGLSYMGLPIXELTRANSFERXOESPROC __rglgen_glPixelTransferxOES; RGLSYMGLPIXELZOOMXOESPROC __rglgen_glPixelZoomxOES; RGLSYMGLPRIORITIZETEXTURESXOESPROC __rglgen_glPrioritizeTexturesxOES; RGLSYMGLRASTERPOS2XOESPROC __rglgen_glRasterPos2xOES; RGLSYMGLRASTERPOS2XVOESPROC __rglgen_glRasterPos2xvOES; RGLSYMGLRASTERPOS3XOESPROC __rglgen_glRasterPos3xOES; RGLSYMGLRASTERPOS3XVOESPROC __rglgen_glRasterPos3xvOES; RGLSYMGLRASTERPOS4XOESPROC __rglgen_glRasterPos4xOES; RGLSYMGLRASTERPOS4XVOESPROC __rglgen_glRasterPos4xvOES; RGLSYMGLRECTXOESPROC __rglgen_glRectxOES; RGLSYMGLRECTXVOESPROC __rglgen_glRectxvOES; RGLSYMGLTEXCOORD1XOESPROC __rglgen_glTexCoord1xOES; RGLSYMGLTEXCOORD1XVOESPROC __rglgen_glTexCoord1xvOES; RGLSYMGLTEXCOORD2XOESPROC __rglgen_glTexCoord2xOES; RGLSYMGLTEXCOORD2XVOESPROC __rglgen_glTexCoord2xvOES; RGLSYMGLTEXCOORD3XOESPROC __rglgen_glTexCoord3xOES; RGLSYMGLTEXCOORD3XVOESPROC __rglgen_glTexCoord3xvOES; RGLSYMGLTEXCOORD4XOESPROC __rglgen_glTexCoord4xOES; RGLSYMGLTEXCOORD4XVOESPROC __rglgen_glTexCoord4xvOES; RGLSYMGLTEXGENXOESPROC __rglgen_glTexGenxOES; RGLSYMGLTEXGENXVOESPROC __rglgen_glTexGenxvOES; RGLSYMGLVERTEX2XOESPROC __rglgen_glVertex2xOES; RGLSYMGLVERTEX2XVOESPROC __rglgen_glVertex2xvOES; RGLSYMGLVERTEX3XOESPROC __rglgen_glVertex3xOES; RGLSYMGLVERTEX3XVOESPROC __rglgen_glVertex3xvOES; RGLSYMGLVERTEX4XOESPROC __rglgen_glVertex4xOES; RGLSYMGLVERTEX4XVOESPROC __rglgen_glVertex4xvOES; RGLSYMGLQUERYMATRIXXOESPROC __rglgen_glQueryMatrixxOES; RGLSYMGLCLEARDEPTHFOESPROC __rglgen_glClearDepthfOES; RGLSYMGLCLIPPLANEFOESPROC __rglgen_glClipPlanefOES; RGLSYMGLDEPTHRANGEFOESPROC __rglgen_glDepthRangefOES; RGLSYMGLFRUSTUMFOESPROC __rglgen_glFrustumfOES; RGLSYMGLGETCLIPPLANEFOESPROC __rglgen_glGetClipPlanefOES; RGLSYMGLORTHOFOESPROC __rglgen_glOrthofOES; RGLSYMGLIMAGETRANSFORMPARAMETERIHPPROC __rglgen_glImageTransformParameteriHP; RGLSYMGLIMAGETRANSFORMPARAMETERFHPPROC __rglgen_glImageTransformParameterfHP; RGLSYMGLIMAGETRANSFORMPARAMETERIVHPPROC __rglgen_glImageTransformParameterivHP; RGLSYMGLIMAGETRANSFORMPARAMETERFVHPPROC __rglgen_glImageTransformParameterfvHP; RGLSYMGLGETIMAGETRANSFORMPARAMETERIVHPPROC __rglgen_glGetImageTransformParameterivHP; RGLSYMGLGETIMAGETRANSFORMPARAMETERFVHPPROC __rglgen_glGetImageTransformParameterfvHP; desmume/src/utils/AsmJit/x86/x86defs.h000664 001750 001750 00000223137 12755534123 020563 0ustar00sergiosergio000000 000000 // [AsmJit] // Complete JIT Assembler for C++ Language. // // [License] // Zlib - See COPYING file in this package. // [Guard] #ifndef _ASMJIT_X86_X86DEFS_H #define _ASMJIT_X86_X86DEFS_H // [Dependencies - AsmJit] #include "../core/assert.h" #include "../core/defs.h" // [Api-Begin] #include "../core/apibegin.h" namespace AsmJit { //! @addtogroup AsmJit_X86 //! @{ // ============================================================================ // [AsmJit::kX86Feature] // ============================================================================ //! @brief X86 CPU features. enum kX86Feature { //! @brief Cpu has RDTSC instruction. kX86FeatureRdtsc = 1U << 0, //! @brief Cpu has RDTSCP instruction. kX86FeatureRdtscP = 1U << 1, //! @brief Cpu has CMOV instruction (conditional move) kX86FeatureCMov = 1U << 2, //! @brief Cpu has CMPXCHG8B instruction kX86FeatureCmpXchg8B = 1U << 3, //! @brief Cpu has CMPXCHG16B instruction (64-bit processors) kX86FeatureCmpXchg16B = 1U << 4, //! @brief Cpu has CLFUSH instruction kX86FeatureClFlush = 1U << 5, //! @brief Cpu has PREFETCH instruction kX86FeaturePrefetch = 1U << 6, //! @brief Cpu supports LAHF and SAHF instrictions. kX86FeatureLahfSahf = 1U << 7, //! @brief Cpu supports FXSAVE and FXRSTOR instructions. kX86FeatureFXSR = 1U << 8, //! @brief Cpu supports FXSAVE and FXRSTOR instruction optimizations (FFXSR). kX86FeatureFFXSR = 1U << 9, //! @brief Cpu has MMX. kX86FeatureMmx = 1U << 10, //! @brief Cpu has extended MMX. kX86FeatureMmxExt = 1U << 11, //! @brief Cpu has 3dNow! kX86Feature3dNow = 1U << 12, //! @brief Cpu has enchanced 3dNow! kX86Feature3dNowExt = 1U << 13, //! @brief Cpu has SSE. kX86FeatureSse = 1U << 14, //! @brief Cpu has SSE2. kX86FeatureSse2 = 1U << 15, //! @brief Cpu has SSE3. kX86FeatureSse3 = 1U << 16, //! @brief Cpu has Supplemental SSE3 (SSSE3). kX86FeatureSsse3 = 1U << 17, //! @brief Cpu has SSE4.A. kX86FeatureSse4A = 1U << 18, //! @brief Cpu has SSE4.1. kX86FeatureSse41 = 1U << 19, //! @brief Cpu has SSE4.2. kX86FeatureSse42 = 1U << 20, //! @brief Cpu has AVX. kX86FeatureAvx = 1U << 22, //! @brief Cpu has Misaligned SSE (MSSE). kX86FeatureMSse = 1U << 23, //! @brief Cpu supports MONITOR and MWAIT instructions. kX86FeatureMonitorMWait = 1U << 24, //! @brief Cpu supports MOVBE instruction. kX86FeatureMovBE = 1U << 25, //! @brief Cpu supports POPCNT instruction. kX86FeaturePopCnt = 1U << 26, //! @brief Cpu supports LZCNT instruction. kX86FeatureLzCnt = 1U << 27, //! @brief Cpu supports PCLMULDQ set of instructions. kX86FeaturePclMulDQ = 1U << 28, //! @brief Cpu supports multithreading. kX86FeatureMultiThreading = 1U << 29, //! @brief Cpu supports execute disable bit (execute protection). kX86FeatureExecuteDisableBit = 1U << 30, //! @brief 64-bit CPU. kX86Feature64Bit = 1U << 31 }; // ============================================================================ // [AsmJit::kX86Bug] // ============================================================================ //! @brief X86 CPU bugs. enum kX86Bug { //! @brief Whether the processor contains bug seen in some //! AMD-Opteron processors. kX86BugAmdLockMB = 1U << 0 }; // ============================================================================ // [AsmJit::kX86Property] // ============================================================================ //! @brief @ref X86Assembler and @ref X86Compiler properties. enum kX86Property { //! @brief Optimize align for current processor. //! //! Default: @c true. kX86PropertyOptimizedAlign = 0, //! @brief Emit hints added to jcc() instructions. //! //! Default: @c true. kX86PropertyJumpHints = 1 }; // ============================================================================ // [AsmJit::kX86Seg] // ============================================================================ //! @brief X86 segment codes. enum kX86Seg { // DO NOT MODIFY INDEX CODES - They are used by _emitSegmentPrefix() and // by logger in the following order: //! @brief ES segment. kX86SegEs = 0, //! @brief CS segment. kX86SegCs = 1, //! @brief SS segment. kX86SegSs = 2, //! @brief DS segment. kX86SegDs = 3, //! @brief FS segment. kX86SegFs = 4, //! @brief GS segment. kX86SegGs = 5, //! @brief Count of segments. kX86SegCount = 6, //! @brief No segment override prefix. kX86SegNone = 0xF }; // ============================================================================ // [AsmJit::kX86RegNum] // ============================================================================ //! @brief X86 registers count. //! //! Count of general purpose registers and XMM registers depends on current //! mode. If application is compiled for 32-bit platform then this number is 8, //! 64-bit platforms have 8 extra general purpose and XMM registers (16 total). enum kX86RegNum { //! @var kX86RegNumBase //! //! Count of general purpose registers and XMM registers depends on current //! bit-mode. If application is compiled for 32-bit platform then this number //! is 8, 64-bit platforms have 8 extra general purpose and XMM registers (16 //! total). #if defined(ASMJIT_X86) kX86RegNumBase = 8, #else kX86RegNumBase = 16, #endif // ASMJIT //! @brief Count of general purpose registers. //! //! 8 in 32-bit mode and 16 in 64-bit mode. kX86RegNumGp = kX86RegNumBase, //! @brief Count of FPU stack registers (always 8). kX86RegNumX87 = 8, //! @brief Count of MM registers (always 8). kX86RegNumMm = 8, //! @brief Count of XMM registers. //! //! 8 in 32-bit mode and 16 in 64-bit mode. kX86RegNumXmm = kX86RegNumBase, //! @brief Count of YMM registers. //! //! 8 in 32-bit mode and 16 in 64-bit mode. kX86RegNumYmm = kX86RegNumBase, //! @brief Count of segment registers, including no segment (AsmJit specific). //! //! @note There are 6 segment registers, but AsmJit uses 0 as no segment, and //! 1...6 as segment registers, this means that there are 7 segment registers //! in AsmJit API, but only 6 can be used through @c Assembler or @c Compiler //! API. kX86RegNumSeg = 7 }; //! @brief X86 register types. enum kX86RegType { // First byte contains register type (mask 0xFF00), Second byte contains // register index code. // -------------------------------------------------------------------------- // [GP Register Types] // -------------------------------------------------------------------------- //! @brief 8-bit general purpose register type (LO). kX86RegTypeGpbLo = 0x0100, //! @brief 8-bit general purpose register type (HI, only AH, BH, CH, DH). kX86RegTypeGpbHi = 0x0200, //! @brief 16-bit general purpose register type. kX86RegTypeGpw = 0x1000, //! @brief 32-bit general purpose register type. kX86RegTypeGpd = 0x2000, //! @brief 64-bit general purpose register type. kX86RegTypeGpq = 0x3000, //! @var kX86RegTypeGpz //! @brief 32-bit or 64-bit general purpose register type. #if defined(ASMJIT_X86) kX86RegTypeGpz = kX86RegTypeGpd, #else kX86RegTypeGpz = kX86RegTypeGpq, #endif //! @brief X87 (FPU) register type. kX86RegTypeX87 = 0x5000, //! @brief 64-bit MM register type. kX86RegTypeMm = 0x6000, //! @brief 128-bit XMM register type. kX86RegTypeXmm = 0x7000, //! @brief 256-bit YMM register type. kX86RegTypeYmm = 0x8000, //! @brief 16-bit segment register type. kX86RegTypeSeg = 0xD000 }; // ============================================================================ // [AsmJit::kX86RegIndex] // ============================================================================ //! @brief X86 register indices. //! //! These codes are real, don't miss with @c REG enum! and don't use these //! values if you are not writing AsmJit code. enum kX86RegIndex { //! @brief ID for AX/EAX/RAX registers. kX86RegIndexEax = 0, //! @brief ID for CX/ECX/RCX registers. kX86RegIndexEcx = 1, //! @brief ID for DX/EDX/RDX registers. kX86RegIndexEdx = 2, //! @brief ID for BX/EBX/RBX registers. kX86RegIndexEbx = 3, //! @brief ID for SP/ESP/RSP registers. kX86RegIndexEsp = 4, //! @brief ID for BP/EBP/RBP registers. kX86RegIndexEbp = 5, //! @brief ID for SI/ESI/RSI registers. kX86RegIndexEsi = 6, //! @brief ID for DI/EDI/RDI registers. kX86RegIndexEdi = 7, //! @brief ID for AX/EAX/RAX registers. kX86RegIndexRax = 0, //! @brief ID for CX/ECX/RCX registers. kX86RegIndexRcx = 1, //! @brief ID for DX/EDX/RDX registers. kX86RegIndexRdx = 2, //! @brief ID for BX/EBX/RBX registers. kX86RegIndexRbx = 3, //! @brief ID for SP/ESP/RSP registers. kX86RegIndexRsp = 4, //! @brief ID for BP/EBP/RBP registers. kX86RegIndexRbp = 5, //! @brief ID for SI/ESI/RSI registers. kX86RegIndexRsi = 6, //! @brief ID for DI/EDI/RDI registers. kX86RegIndexRdi = 7, //! @brief ID for r8 register (additional register introduced by 64-bit architecture). kX86RegIndexR8 = 8, //! @brief ID for R9 register (additional register introduced by 64-bit architecture). kX86RegIndexR9 = 9, //! @brief ID for R10 register (additional register introduced by 64-bit architecture). kX86RegIndexR10 = 10, //! @brief ID for R11 register (additional register introduced by 64-bit architecture). kX86RegIndexR11 = 11, //! @brief ID for R12 register (additional register introduced by 64-bit architecture). kX86RegIndexR12 = 12, //! @brief ID for R13 register (additional register introduced by 64-bit architecture). kX86RegIndexR13 = 13, //! @brief ID for R14 register (additional register introduced by 64-bit architecture). kX86RegIndexR14 = 14, //! @brief ID for R15 register (additional register introduced by 64-bit architecture). kX86RegIndexR15 = 15, //! @brief ID for mm0 register. kX86RegIndexMm0 = 0, //! @brief ID for mm1 register. kX86RegIndexMm1 = 1, //! @brief ID for mm2 register. kX86RegIndexMm2 = 2, //! @brief ID for mm3 register. kX86RegIndexMm3 = 3, //! @brief ID for mm4 register. kX86RegIndexMm4 = 4, //! @brief ID for mm5 register. kX86RegIndexMm5 = 5, //! @brief ID for mm6 register. kX86RegIndexMm6 = 6, //! @brief ID for mm7 register. kX86RegIndexMm7 = 7, //! @brief ID for xmm0 register. kX86RegIndexXmm0 = 0, //! @brief ID for xmm1 register. kX86RegIndexXmm1 = 1, //! @brief ID for xmm2 register. kX86RegIndexXmm2 = 2, //! @brief ID for xmm3 register. kX86RegIndexXmm3 = 3, //! @brief ID for xmm4 register. kX86RegIndexXmm4 = 4, //! @brief ID for xmm5 register. kX86RegIndexXmm5 = 5, //! @brief ID for xmm6 register. kX86RegIndexXmm6 = 6, //! @brief ID for xmm7 register. kX86RegIndexXmm7 = 7, //! @brief ID for xmm8 register (additional register introduced by 64-bit architecture). kX86RegIndexXmm8 = 8, //! @brief ID for xmm9 register (additional register introduced by 64-bit architecture). kX86RegIndexXmm9 = 9, //! @brief ID for xmm10 register (additional register introduced by 64-bit architecture). kX86RegIndexXmm10 = 10, //! @brief ID for xmm11 register (additional register introduced by 64-bit architecture). kX86RegIndexXmm11 = 11, //! @brief ID for xmm12 register (additional register introduced by 64-bit architecture). kX86RegIndexXmm12 = 12, //! @brief ID for xmm13 register (additional register introduced by 64-bit architecture). kX86RegIndexXmm13 = 13, //! @brief ID for xmm14 register (additional register introduced by 64-bit architecture). kX86RegIndexXmm14 = 14, //! @brief ID for xmm15 register (additional register introduced by 64-bit architecture). kX86RegIndexXmm15 = 15, //! @brief ID for ES segment register. kX86RegIndexEs = 0, //! @brief ID for CS segment register. kX86RegIndexCs = 1, //! @brief ID for SS segment register. kX86RegIndexSs = 2, //! @brief ID for DS segment register. kX86RegIndexDs = 3, //! @brief ID for FS segment register. kX86RegIndexFs = 4, //! @brief ID for GS segment register. kX86RegIndexGs = 5 }; // ============================================================================ // [AsmJit::kX86RegCode] // ============================================================================ //! @brief X86 pseudo (not real X86) register codes used for generating opcodes. //! //! From this register code can be generated real x86 register ID, type of //! register and size of register. enum kX86RegCode { // -------------------------------------------------------------------------- // [8-bit Registers] // -------------------------------------------------------------------------- kX86RegAl = kX86RegTypeGpbLo, kX86RegCl, kX86RegDl, kX86RegBl, #if defined(ASMJIT_X64) kX86RegSpl, kX86RegBpl, kX86RegSil, kX86RegDil, #endif // ASMJIT_X64 #if defined(ASMJIT_X64) kX86RegR8b, kX86RegR9b, kX86RegR10b, kX86RegR11b, kX86RegR12b, kX86RegR13b, kX86RegR14b, kX86RegR15b, #endif // ASMJIT_X64 kX86RegAh = kX86RegTypeGpbHi, kX86RegCh, kX86RegDh, kX86RegBh, // -------------------------------------------------------------------------- // [16-bit Registers] // -------------------------------------------------------------------------- kX86RegAx = kX86RegTypeGpw, kX86RegCx, kX86RegDx, kX86RegBx, kX86RegSp, kX86RegBp, kX86RegSi, kX86RegDi, #if defined(ASMJIT_X64) kX86RegR8w, kX86RegR9w, kX86RegR10w, kX86RegR11w, kX86RegR12w, kX86RegR13w, kX86RegR14w, kX86RegR15w, #endif // ASMJIT_X64 // -------------------------------------------------------------------------- // [32-bit Registers] // -------------------------------------------------------------------------- kX86RegEax = kX86RegTypeGpd, kX86RegEcx, kX86RegEdx, kX86RegEbx, kX86RegEsp, kX86RegEbp, kX86RegEsi, kX86RegEdi, #if defined(ASMJIT_X64) kX86RegR8d, kX86RegR9d, kX86RegR10d, kX86RegR11d, kX86RegR12d, kX86RegR13d, kX86RegR14d, kX86RegR15d, #endif // ASMJIT_X64 // -------------------------------------------------------------------------- // [64-bit Registers] // -------------------------------------------------------------------------- #if defined(ASMJIT_X64) kX86RegRax = kX86RegTypeGpq, kX86RegRcx, kX86RegRdx, kX86RegRbx, kX86RegRsp, kX86RegRbp, kX86RegRsi, kX86RegRdi, kX86RegR8, kX86RegR9, kX86RegR10, kX86RegR11, kX86RegR12, kX86RegR13, kX86RegR14, kX86RegR15, #endif // ASMJIT_X64 // -------------------------------------------------------------------------- // [MM Registers] // -------------------------------------------------------------------------- kX86RegMm0 = kX86RegTypeMm, kX86RegMm1, kX86RegMm2, kX86RegMm3, kX86RegMm4, kX86RegMm5, kX86RegMm6, kX86RegMm7, // -------------------------------------------------------------------------- // [XMM Registers] // -------------------------------------------------------------------------- kX86RegXmm0 = kX86RegTypeXmm, kX86RegXmm1, kX86RegXmm2, kX86RegXmm3, kX86RegXmm4, kX86RegXmm5, kX86RegXmm6, kX86RegXmm7, #if defined(ASMJIT_X64) kX86RegXmm8, kX86RegXmm9, kX86RegXmm10, kX86RegXmm11, kX86RegXmm12, kX86RegXmm13, kX86RegXmm14, kX86RegXmm15, #endif // ASMJIT_X64 // -------------------------------------------------------------------------- // [Native registers (depends on 32-bit or 64-bit mode)] // -------------------------------------------------------------------------- kX86RegZax = kX86RegTypeGpz, kX86RegZcx, kX86RegZdx, kX86RegZbx, kX86RegZsp, kX86RegZbp, kX86RegZsi, kX86RegZdi, // -------------------------------------------------------------------------- // [Segment registers] // -------------------------------------------------------------------------- //! @brief ES segment register. kX86RegEs = kX86RegTypeSeg, //! @brief CS segment register. kX86RegCs, //! @brief SS segment register. kX86RegSs, //! @brief DS segment register. kX86RegDs, //! @brief FS segment register. kX86RegFs, //! @brief GS segment register. kX86RegGs }; // ============================================================================ // [AsmJit::kX86Cond] // ============================================================================ //! @brief X86 Condition codes. enum kX86Cond { // Condition codes from processor manuals. kX86CondA = 0x07, kX86CondAE = 0x03, kX86CondB = 0x02, kX86CondBE = 0x06, kX86CondC = 0x02, kX86CondE = 0x04, kX86CondG = 0x0F, kX86CondGE = 0x0D, kX86CondL = 0x0C, kX86CondLE = 0x0E, kX86CondNA = 0x06, kX86CondNAE = 0x02, kX86CondNB = 0x03, kX86CondNBE = 0x07, kX86CondNC = 0x03, kX86CondNE = 0x05, kX86CondNG = 0x0E, kX86CondNGE = 0x0C, kX86CondNL = 0x0D, kX86CondNLE = 0x0F, kX86CondNO = 0x01, kX86CondNP = 0x0B, kX86CondNS = 0x09, kX86CondNZ = 0x05, kX86CondO = 0x00, kX86CondP = 0x0A, kX86CondPE = 0x0A, kX86CondPO = 0x0B, kX86CondS = 0x08, kX86CondZ = 0x04, // Simplified condition codes. kX86CondOverflow = 0x00, kX86CondNotOverflow = 0x01, kX86CondBelow = 0x02, kX86CondAboveEqual = 0x03, kX86CondEqual = 0x04, kX86CondNotEqual = 0x05, kX86CondBelowEqual = 0x06, kX86CondAbove = 0x07, kX86CondSign = 0x08, kX86CondNotSign = 0x09, kX86CondParityEven = 0x0A, kX86CondParityOdd = 0x0B, kX86CondLess = 0x0C, kX86CondGreaterEqual = 0x0D, kX86CondLessEqual = 0x0E, kX86CondGreater = 0x0F, // Aliases. kX86CondZero = 0x04, kX86CondNotZero = 0x05, kX86CondNegative = 0x08, kX86CondPositive = 0x09, // X87 floating point only. kX86CondFpuUnordered = 0x10, kX86CondFpuNotUnordered = 0x11, //! @brief No condition code. kX86CondNone = 0x12 }; // ============================================================================ // [AsmJit::kX86CondPrefix] // ============================================================================ //! @brief X86 condition hint prefix code, see @ref kCondHint. enum kX86CondPrefix { //! @brief Condition is likely to be taken. kX86CondPrefixLikely = 0x3E, //! @brief Condition is unlikely to be taken. kX86CondPrefixUnlikely = 0x2E }; // ============================================================================ // [AsmJit::kX86PrefetchHint] // ============================================================================ //! @brief X86 Prefetch hints. enum kX86PrefetchHint { //! @brief Prefetch using NT hint. kX86PrefetchNta = 0, //! @brief Prefetch to L0 cache. kX86PrefetchT0 = 1, //! @brief Prefetch to L1 cache. kX86PrefetchT1 = 2, //! @brief Prefetch to L2 cache. kX86PrefetchT2 = 3 }; // ============================================================================ // [AsmJit::kX86FPSW] // ============================================================================ //! @brief X86 FPU status-word. enum kX86FPSW { kX86FPSW_Invalid = 0x0001, kX86FPSW_Denormalized = 0x0002, kX86FPSW_DivByZero = 0x0004, kX86FPSW_Overflow = 0x0008, kX86FPSW_Underflow = 0x0010, kX86FPSW_Precision = 0x0020, kX86FPSW_StackFault = 0x0040, kX86FPSW_Interrupt = 0x0080, kX86FPSW_C0 = 0x0100, kX86FPSW_C1 = 0x0200, kX86FPSW_C2 = 0x0400, kX86FPSW_Top = 0x3800, kX86FPSW_C3 = 0x4000, kX86FPSW_Busy = 0x8000 }; // ============================================================================ // [AsmJit::kX86FPCW] // ============================================================================ //! @brief X86 FPU control-word. enum kX86FPCW { // -------------------------------------------------------------------------- // [Exception-Mask] // -------------------------------------------------------------------------- kX86FPCW_EM_Mask = 0x003F, // Bits 0-5. kX86FPCW_EM_Invalid = 0x0001, kX86FPCW_EM_Denormal = 0x0002, kX86FPCW_EM_DivByZero = 0x0004, kX86FPCW_EM_Overflow = 0x0008, kX86FPCW_EM_Underflow = 0x0010, kX86FPCW_EM_Inexact = 0x0020, // -------------------------------------------------------------------------- // [Precision-Control] // -------------------------------------------------------------------------- kX86FPCW_PC_Mask = 0x0300, // Bits 8-9. kX86FPCW_PC_Float = 0x0000, kX86FPCW_PC_Reserved = 0x0100, kX86FPCW_PC_Double = 0x0200, kX86FPCW_PC_Extended = 0x0300, // -------------------------------------------------------------------------- // [Rounding-Control] // -------------------------------------------------------------------------- kX86FPCW_RC_Mask = 0x0C00, // Bits 10-11. kX86FPCW_RC_Nearest = 0x0000, kX86FPCW_RC_Down = 0x0400, kX86FPCW_RC_Up = 0x0800, kX86FPCW_RC_Truncate = 0x0C00, // -------------------------------------------------------------------------- // [Infinity-Control] // -------------------------------------------------------------------------- kX86FPCW_IC_Mask = 0x1000, // Bit 12. kX86FPCW_IC_Projective = 0x0000, kX86FPCW_IC_Affine = 0x1000 }; // ============================================================================ // [AsmJit::kX86EmitOption] // ============================================================================ //! @brief Emit options, mainly for internal purposes. enum kX86EmitOption { //! @brief Force REX prefix to be emitted. //! //! This option should be used carefully, because there are unencodable //! combinations. If you want to access ah, bh, ch or dh registers then you //! can't emit REX prefix and it will cause an illegal instruction error. kX86EmitOptionRex = 0x1, //! @brief Tell @c Assembler or @c Compiler to emit and validate lock prefix. //! //! If this option is used and instruction doesn't support LOCK prefix then //! invalid instruction error is generated. kX86EmitOptionLock = 0x2, //! @brief Emit short/near jump or conditional jump instead of far one to //! some bytes. //! //! @note This option could be dangerous in case that the short jump is not //! possible (displacement can't fit into signed 8-bit integer). AsmJit can //! automatically generate back short jumps, but always generates long forward //! jumps, because the information about the code size between the instruction //! and target is not known. kX86EmitOptionShortJump = 0x4, //! @brief Emit full immediate instead of BYTE in all cases. //! //! @note AsmJit is able to emit both forms of immediate value. In case that //! the instruction supports short form and immediate can fit into a signed //! 8-bit integer short for is preferred, but if for any reason the full form //! is required it can be overridden by using this option. kX86EmitOptionFullImmediate = 0x8 }; // ============================================================================ // [AsmJit::kX86InstCode] // ============================================================================ //! @brief X86 instruction codes. //! //! Note that these instruction codes are AsmJit specific. Each instruction is //! unique ID into AsmJit instruction table. Instruction codes are used together //! with AsmJit::Assembler and you can also use instruction codes to serialize //! instructions by @ref Assembler::_emitInstruction() or //! @ref Compiler::_emitInstruction() enum kX86InstCode { kX86InstAdc = 1, // X86/X64 kX86InstAdd, // X86/X64 kX86InstAddPD, // SSE2 kX86InstAddPS, // SSE kX86InstAddSD, // SSE2 kX86InstAddSS, // SSE kX86InstAddSubPD, // SSE3 kX86InstAddSubPS, // SSE3 kX86InstAmdPrefetch, // 3dNow! kX86InstAmdPrefetchW, // 3dNow! kX86InstAnd, // X86/X64 kX86InstAndnPD, // SSE2 kX86InstAndnPS, // SSE kX86InstAndPD, // SSE2 kX86InstAndPS, // SSE kX86InstBlendPD, // SSE4.1 kX86InstBlendPS, // SSE4.1 kX86InstBlendVPD, // SSE4.1 kX86InstBlendVPS, // SSE4.1 kX86InstBsf, // X86/X64 kX86InstBsr, // X86/X64 kX86InstBSwap, // X86/X64 (i486) kX86InstBt, // X86/X64 kX86InstBtc, // X86/X64 kX86InstBtr, // X86/X64 kX86InstBts, // X86/X64 kX86InstCall, // X86/X64 kX86InstCbw, // X86/X64 kX86InstCdq, // X86/X64 kX86InstCdqe, // X64 only kX86InstClc, // X86/X64 kX86InstCld, // X86/X64 kX86InstClFlush, // SSE2 kX86InstCmc, // X86/X64 kX86InstCMov, // Begin (cmovcc) (i586) kX86InstCMovA=kX86InstCMov,//X86/X64 (cmovcc) (i586) kX86InstCMovAE, // X86/X64 (cmovcc) (i586) kX86InstCMovB, // X86/X64 (cmovcc) (i586) kX86InstCMovBE, // X86/X64 (cmovcc) (i586) kX86InstCMovC, // X86/X64 (cmovcc) (i586) kX86InstCMovE, // X86/X64 (cmovcc) (i586) kX86InstCMovG, // X86/X64 (cmovcc) (i586) kX86InstCMovGE, // X86/X64 (cmovcc) (i586) kX86InstCMovL, // X86/X64 (cmovcc) (i586) kX86InstCMovLE, // X86/X64 (cmovcc) (i586) kX86InstCMovNA, // X86/X64 (cmovcc) (i586) kX86InstCMovNAE, // X86/X64 (cmovcc) (i586) kX86InstCMovNB, // X86/X64 (cmovcc) (i586) kX86InstCMovNBE, // X86/X64 (cmovcc) (i586) kX86InstCMovNC, // X86/X64 (cmovcc) (i586) kX86InstCMovNE, // X86/X64 (cmovcc) (i586) kX86InstCMovNG, // X86/X64 (cmovcc) (i586) kX86InstCMovNGE, // X86/X64 (cmovcc) (i586) kX86InstCMovNL, // X86/X64 (cmovcc) (i586) kX86InstCMovNLE, // X86/X64 (cmovcc) (i586) kX86InstCMovNO, // X86/X64 (cmovcc) (i586) kX86InstCMovNP, // X86/X64 (cmovcc) (i586) kX86InstCMovNS, // X86/X64 (cmovcc) (i586) kX86InstCMovNZ, // X86/X64 (cmovcc) (i586) kX86InstCMovO, // X86/X64 (cmovcc) (i586) kX86InstCMovP, // X86/X64 (cmovcc) (i586) kX86InstCMovPE, // X86/X64 (cmovcc) (i586) kX86InstCMovPO, // X86/X64 (cmovcc) (i586) kX86InstCMovS, // X86/X64 (cmovcc) (i586) kX86InstCMovZ, // X86/X64 (cmovcc) (i586) kX86InstCmp, // X86/X64 kX86InstCmpPD, // SSE2 kX86InstCmpPS, // SSE kX86InstCmpSD, // SSE2 kX86InstCmpSS, // SSE kX86InstCmpXCHG, // X86/X64 (i486) kX86InstCmpXCHG16B, // X64 only kX86InstCmpXCHG8B, // X86/X64 (i586) kX86InstComISD, // SSE2 kX86InstComISS, // SSE kX86InstCpuId, // X86/X64 (i486) kX86InstCqo, // X64 only kX86InstCrc32, // SSE4.2 kX86InstCvtDQ2PD, // SSE2 kX86InstCvtDQ2PS, // SSE2 kX86InstCvtPD2DQ, // SSE2 kX86InstCvtPD2PI, // SSE2 kX86InstCvtPD2PS, // SSE2 kX86InstCvtPI2PD, // SSE2 kX86InstCvtPI2PS, // SSE kX86InstCvtPS2DQ, // SSE2 kX86InstCvtPS2PD, // SSE2 kX86InstCvtPS2PI, // SSE kX86InstCvtSD2SI, // SSE2 kX86InstCvtSD2SS, // SSE2 kX86InstCvtSI2SD, // SSE2 kX86InstCvtSI2SS, // SSE kX86InstCvtSS2SD, // SSE2 kX86InstCvtSS2SI, // SSE kX86InstCvttPD2DQ, // SSE2 kX86InstCvttPD2PI, // SSE2 kX86InstCvttPS2DQ, // SSE2 kX86InstCvttPS2PI, // SSE kX86InstCvttSD2SI, // SSE2 kX86InstCvttSS2SI, // SSE kX86InstCwd, // X86/X64 kX86InstCwde, // X86/X64 kX86InstDaa, // X86 only kX86InstDas, // X86 only kX86InstDec, // X86/X64 kX86InstDiv, // X86/X64 kX86InstDivPD, // SSE2 kX86InstDivPS, // SSE kX86InstDivSD, // SSE2 kX86InstDivSS, // SSE kX86InstDpPD, // SSE4.1 kX86InstDpPS, // SSE4.1 kX86InstEmms, // MMX kX86InstEnter, // X86/X64 kX86InstExtractPS, // SSE4.1 kX86InstF2XM1, // X87 kX86InstFAbs, // X87 kX86InstFAdd, // X87 kX86InstFAddP, // X87 kX86InstFBLd, // X87 kX86InstFBStP, // X87 kX86InstFCHS, // X87 kX86InstFClex, // X87 kX86InstFCMovB, // X87 kX86InstFCMovBE, // X87 kX86InstFCMovE, // X87 kX86InstFCMovNB, // X87 kX86InstFCMovNBE, // X87 kX86InstFCMovNE, // X87 kX86InstFCMovNU, // X87 kX86InstFCMovU, // X87 kX86InstFCom, // X87 kX86InstFComI, // X87 kX86InstFComIP, // X87 kX86InstFComP, // X87 kX86InstFComPP, // X87 kX86InstFCos, // X87 kX86InstFDecStP, // X87 kX86InstFDiv, // X87 kX86InstFDivP, // X87 kX86InstFDivR, // X87 kX86InstFDivRP, // X87 kX86InstFEmms, // 3dNow! kX86InstFFree, // X87 kX86InstFIAdd, // X87 kX86InstFICom, // X87 kX86InstFIComP, // X87 kX86InstFIDiv, // X87 kX86InstFIDivR, // X87 kX86InstFILd, // X87 kX86InstFIMul, // X87 kX86InstFIncStP, // X87 kX86InstFInit, // X87 kX86InstFISt, // X87 kX86InstFIStP, // X87 kX86InstFISttP, // SSE3 kX86InstFISub, // X87 kX86InstFISubR, // X87 kX86InstFLd, // X87 kX86InstFLd1, // X87 kX86InstFLdCw, // X87 kX86InstFLdEnv, // X87 kX86InstFLdL2E, // X87 kX86InstFLdL2T, // X87 kX86InstFLdLg2, // X87 kX86InstFLdLn2, // X87 kX86InstFLdPi, // X87 kX86InstFLdZ, // X87 kX86InstFMul, // X87 kX86InstFMulP, // X87 kX86InstFNClex, // X87 kX86InstFNInit, // X87 kX86InstFNop, // X87 kX86InstFNSave, // X87 kX86InstFNStCw, // X87 kX86InstFNStEnv, // X87 kX86InstFNStSw, // X87 kX86InstFPAtan, // X87 kX86InstFPRem, // X87 kX86InstFPRem1, // X87 kX86InstFPTan, // X87 kX86InstFRndInt, // X87 kX86InstFRstor, // X87 kX86InstFSave, // X87 kX86InstFScale, // X87 kX86InstFSin, // X87 kX86InstFSinCos, // X87 kX86InstFSqrt, // X87 kX86InstFSt, // X87 kX86InstFStCw, // X87 kX86InstFStEnv, // X87 kX86InstFStP, // X87 kX86InstFStSw, // X87 kX86InstFSub, // X87 kX86InstFSubP, // X87 kX86InstFSubR, // X87 kX86InstFSubRP, // X87 kX86InstFTst, // X87 kX86InstFUCom, // X87 kX86InstFUComI, // X87 kX86InstFUComIP, // X87 kX86InstFUComP, // X87 kX86InstFUComPP, // X87 kX86InstFWait, // X87 kX86InstFXam, // X87 kX86InstFXch, // X87 kX86InstFXRstor, // X87 kX86InstFXSave, // X87 kX86InstFXtract, // X87 kX86InstFYL2X, // X87 kX86InstFYL2XP1, // X87 kX86InstHAddPD, // SSE3 kX86InstHAddPS, // SSE3 kX86InstHSubPD, // SSE3 kX86InstHSubPS, // SSE3 kX86InstIDiv, // X86/X64 kX86InstIMul, // X86/X64 kX86InstInc, // X86/X64 kX86InstInt3, // X86/X64 kX86InstJ, // Begin (jcc) kX86InstJA = kX86InstJ, // X86/X64 (jcc) kX86InstJAE, // X86/X64 (jcc) kX86InstJB, // X86/X64 (jcc) kX86InstJBE, // X86/X64 (jcc) kX86InstJC, // X86/X64 (jcc) kX86InstJE, // X86/X64 (jcc) kX86InstJG, // X86/X64 (jcc) kX86InstJGE, // X86/X64 (jcc) kX86InstJL, // X86/X64 (jcc) kX86InstJLE, // X86/X64 (jcc) kX86InstJNA, // X86/X64 (jcc) kX86InstJNAE, // X86/X64 (jcc) kX86InstJNB, // X86/X64 (jcc) kX86InstJNBE, // X86/X64 (jcc) kX86InstJNC, // X86/X64 (jcc) kX86InstJNE, // X86/X64 (jcc) kX86InstJNG, // X86/X64 (jcc) kX86InstJNGE, // X86/X64 (jcc) kX86InstJNL, // X86/X64 (jcc) kX86InstJNLE, // X86/X64 (jcc) kX86InstJNO, // X86/X64 (jcc) kX86InstJNP, // X86/X64 (jcc) kX86InstJNS, // X86/X64 (jcc) kX86InstJNZ, // X86/X64 (jcc) kX86InstJO, // X86/X64 (jcc) kX86InstJP, // X86/X64 (jcc) kX86InstJPE, // X86/X64 (jcc) kX86InstJPO, // X86/X64 (jcc) kX86InstJS, // X86/X64 (jcc) kX86InstJZ, // X86/X64 (jcc) kX86InstJmp, // X86/X64 (jmp) kX86InstLdDQU, // SSE3 kX86InstLdMXCSR, // SSE kX86InstLahf, // X86/X64 (CPUID NEEDED) kX86InstLea, // X86/X64 kX86InstLeave, // X86/X64 kX86InstLFence, // SSE2 kX86InstMaskMovDQU, // SSE2 kX86InstMaskMovQ, // MMX-Ext kX86InstMaxPD, // SSE2 kX86InstMaxPS, // SSE kX86InstMaxSD, // SSE2 kX86InstMaxSS, // SSE kX86InstMFence, // SSE2 kX86InstMinPD, // SSE2 kX86InstMinPS, // SSE kX86InstMinSD, // SSE2 kX86InstMinSS, // SSE kX86InstMonitor, // SSE3 kX86InstMov, // X86/X64 kX86InstMovAPD, // SSE2 kX86InstMovAPS, // SSE kX86InstMovBE, // SSE3 - Intel-Atom kX86InstMovD, // MMX/SSE2 kX86InstMovDDup, // SSE3 kX86InstMovDQ2Q, // SSE2 kX86InstMovDQA, // SSE2 kX86InstMovDQU, // SSE2 kX86InstMovHLPS, // SSE kX86InstMovHPD, // SSE2 kX86InstMovHPS, // SSE kX86InstMovLHPS, // SSE kX86InstMovLPD, // SSE2 kX86InstMovLPS, // SSE kX86InstMovMskPD, // SSE2 kX86InstMovMskPS, // SSE2 kX86InstMovNTDQ, // SSE2 kX86InstMovNTDQA, // SSE4.1 kX86InstMovNTI, // SSE2 kX86InstMovNTPD, // SSE2 kX86InstMovNTPS, // SSE kX86InstMovNTQ, // MMX-Ext kX86InstMovQ, // MMX/SSE/SSE2 kX86InstMovQ2DQ, // SSE2 kX86InstMovSD, // SSE2 kX86InstMovSHDup, // SSE3 kX86InstMovSLDup, // SSE3 kX86InstMovSS, // SSE kX86InstMovSX, // X86/X64 kX86InstMovSXD, // X86/X64 kX86InstMovUPD, // SSE2 kX86InstMovUPS, // SSE kX86InstMovZX, // X86/X64 kX86InstMovPtr, // X86/X64 kX86InstMPSADBW, // SSE4.1 kX86InstMul, // X86/X64 kX86InstMulPD, // SSE2 kX86InstMulPS, // SSE kX86InstMulSD, // SSE2 kX86InstMulSS, // SSE kX86InstMWait, // SSE3 kX86InstNeg, // X86/X64 kX86InstNop, // X86/X64 kX86InstNot, // X86/X64 kX86InstOr, // X86/X64 kX86InstOrPD, // SSE2 kX86InstOrPS, // SSE kX86InstPAbsB, // SSSE3 kX86InstPAbsD, // SSSE3 kX86InstPAbsW, // SSSE3 kX86InstPackSSDW, // MMX/SSE2 kX86InstPackSSWB, // MMX/SSE2 kX86InstPackUSDW, // SSE4.1 kX86InstPackUSWB, // MMX/SSE2 kX86InstPAddB, // MMX/SSE2 kX86InstPAddD, // MMX/SSE2 kX86InstPAddQ, // SSE2 kX86InstPAddSB, // MMX/SSE2 kX86InstPAddSW, // MMX/SSE2 kX86InstPAddUSB, // MMX/SSE2 kX86InstPAddUSW, // MMX/SSE2 kX86InstPAddW, // MMX/SSE2 kX86InstPAlignR, // SSSE3 kX86InstPAnd, // MMX/SSE2 kX86InstPAndN, // MMX/SSE2 kX86InstPause, // SSE2. kX86InstPAvgB, // MMX-Ext kX86InstPAvgW, // MMX-Ext kX86InstPBlendVB, // SSE4.1 kX86InstPBlendW, // SSE4.1 kX86InstPCmpEqB, // MMX/SSE2 kX86InstPCmpEqD, // MMX/SSE2 kX86InstPCmpEqQ, // SSE4.1 kX86InstPCmpEqW, // MMX/SSE2 kX86InstPCmpEStrI, // SSE4.2 kX86InstPCmpEStrM, // SSE4.2 kX86InstPCmpGtB, // MMX/SSE2 kX86InstPCmpGtD, // MMX/SSE2 kX86InstPCmpGtQ, // SSE4.2 kX86InstPCmpGtW, // MMX/SSE2 kX86InstPCmpIStrI, // SSE4.2 kX86InstPCmpIStrM, // SSE4.2 kX86InstPExtrB, // SSE4.1 kX86InstPExtrD, // SSE4.1 kX86InstPExtrQ, // SSE4.1 kX86InstPExtrW, // MMX-Ext/SSE2 kX86InstPF2ID, // 3dNow! kX86InstPF2IW, // Enhanced 3dNow! kX86InstPFAcc, // 3dNow! kX86InstPFAdd, // 3dNow! kX86InstPFCmpEQ, // 3dNow! kX86InstPFCmpGE, // 3dNow! kX86InstPFCmpGT, // 3dNow! kX86InstPFMax, // 3dNow! kX86InstPFMin, // 3dNow! kX86InstPFMul, // 3dNow! kX86InstPFNAcc, // Enhanced 3dNow! kX86InstPFPNAcc, // Enhanced 3dNow! kX86InstPFRcp, // 3dNow! kX86InstPFRcpIt1, // 3dNow! kX86InstPFRcpIt2, // 3dNow! kX86InstPFRSqIt1, // 3dNow! kX86InstPFRSqrt, // 3dNow! kX86InstPFSub, // 3dNow! kX86InstPFSubR, // 3dNow! kX86InstPHAddD, // SSSE3 kX86InstPHAddSW, // SSSE3 kX86InstPHAddW, // SSSE3 kX86InstPHMinPOSUW, // SSE4.1 kX86InstPHSubD, // SSSE3 kX86InstPHSubSW, // SSSE3 kX86InstPHSubW, // SSSE3 kX86InstPI2FD, // 3dNow! kX86InstPI2FW, // Enhanced 3dNow! kX86InstPInsRB, // SSE4.1 kX86InstPInsRD, // SSE4.1 kX86InstPInsRQ, // SSE4.1 kX86InstPInsRW, // MMX-Ext kX86InstPMAddUBSW, // SSSE3 kX86InstPMAddWD, // MMX/SSE2 kX86InstPMaxSB, // SSE4.1 kX86InstPMaxSD, // SSE4.1 kX86InstPMaxSW, // MMX-Ext kX86InstPMaxUB, // MMX-Ext kX86InstPMaxUD, // SSE4.1 kX86InstPMaxUW, // SSE4.1 kX86InstPMinSB, // SSE4.1 kX86InstPMinSD, // SSE4.1 kX86InstPMinSW, // MMX-Ext kX86InstPMinUB, // MMX-Ext kX86InstPMinUD, // SSE4.1 kX86InstPMinUW, // SSE4.1 kX86InstPMovMskB, // MMX-Ext kX86InstPMovSXBD, // SSE4.1 kX86InstPMovSXBQ, // SSE4.1 kX86InstPMovSXBW, // SSE4.1 kX86InstPMovSXDQ, // SSE4.1 kX86InstPMovSXWD, // SSE4.1 kX86InstPMovSXWQ, // SSE4.1 kX86InstPMovZXBD, // SSE4.1 kX86InstPMovZXBQ, // SSE4.1 kX86InstPMovZXBW, // SSE4.1 kX86InstPMovZXDQ, // SSE4.1 kX86InstPMovZXWD, // SSE4.1 kX86InstPMovZXWQ, // SSE4.1 kX86InstPMulDQ, // SSE4.1 kX86InstPMulHRSW, // SSSE3 kX86InstPMulHUW, // MMX-Ext kX86InstPMulHW, // MMX/SSE2 kX86InstPMulLD, // SSE4.1 kX86InstPMulLW, // MMX/SSE2 kX86InstPMulUDQ, // SSE2 kX86InstPop, // X86/X64 kX86InstPopAD, // X86 only kX86InstPopCnt, // SSE4.2 kX86InstPopFD, // X86 only kX86InstPopFQ, // X64 only kX86InstPOr, // MMX/SSE2 kX86InstPrefetch, // MMX-Ext kX86InstPSADBW, // MMX-Ext kX86InstPShufB, // SSSE3 kX86InstPShufD, // SSE2 kX86InstPShufW, // MMX-Ext kX86InstPShufHW, // SSE2 kX86InstPShufLW, // SSE2 kX86InstPSignB, // SSSE3 kX86InstPSignD, // SSSE3 kX86InstPSignW, // SSSE3 kX86InstPSllD, // MMX/SSE2 kX86InstPSllDQ, // SSE2 kX86InstPSllQ, // MMX/SSE2 kX86InstPSllW, // MMX/SSE2 kX86InstPSraD, // MMX/SSE2 kX86InstPSraW, // MMX/SSE2 kX86InstPSrlD, // MMX/SSE2 kX86InstPSrlDQ, // SSE2 kX86InstPSrlQ, // MMX/SSE2 kX86InstPSrlW, // MMX/SSE2 kX86InstPSubB, // MMX/SSE2 kX86InstPSubD, // MMX/SSE2 kX86InstPSubQ, // SSE2 kX86InstPSubSB, // MMX/SSE2 kX86InstPSubSW, // MMX/SSE2 kX86InstPSubUSB, // MMX/SSE2 kX86InstPSubUSW, // MMX/SSE2 kX86InstPSubW, // MMX/SSE2 kX86InstPSwapD, // Enhanced 3dNow! kX86InstPTest, // SSE4.1 kX86InstPunpckHBW, // MMX/SSE2 kX86InstPunpckHDQ, // MMX/SSE2 kX86InstPunpckHQDQ, // SSE2 kX86InstPunpckHWD, // MMX/SSE2 kX86InstPunpckLBW, // MMX/SSE2 kX86InstPunpckLDQ, // MMX/SSE2 kX86InstPunpckLQDQ, // SSE2 kX86InstPunpckLWD, // MMX/SSE2 kX86InstPush, // X86/X64 kX86InstPushAD, // X86 only kX86InstPushFD, // X86 only kX86InstPushFQ, // X64 only kX86InstPXor, // MMX/SSE2 kX86InstRcl, // X86/X64 kX86InstRcpPS, // SSE kX86InstRcpSS, // SSE kX86InstRcr, // X86/X64 kX86InstRdtsc, // X86/X64 kX86InstRdtscP, // X86/X64 kX86InstRepLodSB, // X86/X64 (REP) kX86InstRepLodSD, // X86/X64 (REP) kX86InstRepLodSQ, // X64 only (REP) kX86InstRepLodSW, // X86/X64 (REP) kX86InstRepMovSB, // X86/X64 (REP) kX86InstRepMovSD, // X86/X64 (REP) kX86InstRepMovSQ, // X64 only (REP) kX86InstRepMovSW, // X86/X64 (REP) kX86InstRepStoSB, // X86/X64 (REP) kX86InstRepStoSD, // X86/X64 (REP) kX86InstRepStoSQ, // X64 only (REP) kX86InstRepStoSW, // X86/X64 (REP) kX86InstRepECmpSB, // X86/X64 (REP) kX86InstRepECmpSD, // X86/X64 (REP) kX86InstRepECmpSQ, // X64 only (REP) kX86InstRepECmpSW, // X86/X64 (REP) kX86InstRepEScaSB, // X86/X64 (REP) kX86InstRepEScaSD, // X86/X64 (REP) kX86InstRepEScaSQ, // X64 only (REP) kX86InstRepEScaSW, // X86/X64 (REP) kX86InstRepNECmpSB, // X86/X64 (REP) kX86InstRepNECmpSD, // X86/X64 (REP) kX86InstRepNECmpSQ, // X64 only (REP) kX86InstRepNECmpSW, // X86/X64 (REP) kX86InstRepNEScaSB, // X86/X64 (REP) kX86InstRepNEScaSD, // X86/X64 (REP) kX86InstRepNEScaSQ, // X64 only (REP) kX86InstRepNEScaSW, // X86/X64 (REP) kX86InstRet, // X86/X64 kX86InstRol, // X86/X64 kX86InstRor, // X86/X64 kX86InstRoundPD, // SSE4.1 kX86InstRoundPS, // SSE4.1 kX86InstRoundSD, // SSE4.1 kX86InstRoundSS, // SSE4.1 kX86InstRSqrtPS, // SSE kX86InstRSqrtSS, // SSE kX86InstSahf, // X86/X64 (CPUID NEEDED) kX86InstSal, // X86/X64 kX86InstSar, // X86/X64 kX86InstSbb, // X86/X64 kX86InstSet, // Begin (setcc) kX86InstSetA=kX86InstSet,// X86/X64 (setcc) kX86InstSetAE, // X86/X64 (setcc) kX86InstSetB, // X86/X64 (setcc) kX86InstSetBE, // X86/X64 (setcc) kX86InstSetC, // X86/X64 (setcc) kX86InstSetE, // X86/X64 (setcc) kX86InstSetG, // X86/X64 (setcc) kX86InstSetGE, // X86/X64 (setcc) kX86InstSetL, // X86/X64 (setcc) kX86InstSetLE, // X86/X64 (setcc) kX86InstSetNA, // X86/X64 (setcc) kX86InstSetNAE, // X86/X64 (setcc) kX86InstSetNB, // X86/X64 (setcc) kX86InstSetNBE, // X86/X64 (setcc) kX86InstSetNC, // X86/X64 (setcc) kX86InstSetNE, // X86/X64 (setcc) kX86InstSetNG, // X86/X64 (setcc) kX86InstSetNGE, // X86/X64 (setcc) kX86InstSetNL, // X86/X64 (setcc) kX86InstSetNLE, // X86/X64 (setcc) kX86InstSetNO, // X86/X64 (setcc) kX86InstSetNP, // X86/X64 (setcc) kX86InstSetNS, // X86/X64 (setcc) kX86InstSetNZ, // X86/X64 (setcc) kX86InstSetO, // X86/X64 (setcc) kX86InstSetP, // X86/X64 (setcc) kX86InstSetPE, // X86/X64 (setcc) kX86InstSetPO, // X86/X64 (setcc) kX86InstSetS, // X86/X64 (setcc) kX86InstSetZ, // X86/X64 (setcc) kX86InstSFence, // MMX-Ext/SSE kX86InstShl, // X86/X64 kX86InstShld, // X86/X64 kX86InstShr, // X86/X64 kX86InstShrd, // X86/X64 kX86InstShufPD, // SSE2 kX86InstShufPS, // SSE kX86InstSqrtPD, // SSE2 kX86InstSqrtPS, // SSE kX86InstSqrtSD, // SSE2 kX86InstSqrtSS, // SSE kX86InstStc, // X86/X64 kX86InstStd, // X86/X64 kX86InstStMXCSR, // SSE kX86InstSub, // X86/X64 kX86InstSubPD, // SSE2 kX86InstSubPS, // SSE kX86InstSubSD, // SSE2 kX86InstSubSS, // SSE kX86InstTest, // X86/X64 kX86InstUComISD, // SSE2 kX86InstUComISS, // SSE kX86InstUd2, // X86/X64 kX86InstUnpckHPD, // SSE2 kX86InstUnpckHPS, // SSE kX86InstUnpckLPD, // SSE2 kX86InstUnpckLPS, // SSE kX86InstXadd, // X86/X64 (i486) kX86InstXchg, // X86/X64 (i386) kX86InstXor, // X86/X64 kX86InstXorPD, // SSE2 kX86InstXorPS, // SSE _kX86InstCount, _kX86InstJBegin = kX86InstJ, _kX86InstJEnd = kX86InstJmp }; // ============================================================================ // [AsmJit::kX86InstGroup] // ============================================================================ //! @brief X86 instruction groups. //! //! This should be only used by assembler, because it's @c AsmJit::Assembler //! specific grouping. Each group represents one 'case' in the Assembler's //! main emit method. enum kX86InstGroup { // Group categories. kX86InstGroupNone, kX86InstGroupEmit, kX86InstGroupArith, kX86InstGroupBSwap, kX86InstGroupBTest, kX86InstGroupCall, kX86InstGroupCrc32, kX86InstGroupEnter, kX86InstGroupIMul, kX86InstGroupIncDec, kX86InstGroupJcc, kX86InstGroupJmp, kX86InstGroupLea, kX86InstGroupMem, kX86InstGroupMov, kX86InstGroupMovPtr, kX86InstGroupMovSxMovZx, kX86InstGroupMovSxD, kX86InstGroupPush, kX86InstGroupPop, kX86InstGroupRegRm, kX86InstGroupRm, kX86InstGroupRmByte, kX86InstGroupRmReg, kX86InstGroupRep, kX86InstGroupRet, kX86InstGroupRot, kX86InstGroupShldShrd, kX86InstGroupTest, kX86InstGroupXchg, // Group for x87 FP instructions in format mem or st(i), st(i) (fadd, fsub, fdiv, ...) kX86InstGroupX87StM, // Group for x87 FP instructions in format st(i), st(i) kX86InstGroupX87StI, // Group for fld/fst/fstp instruction, internally uses @ref kX86InstGroupX87StM group. kX86InstGroupX87FldFst, // Group for x87 FP instructions that uses Word, DWord, QWord or TWord memory pointer. kX86InstGroupX87Mem, // Group for x87 FSTSW/FNSTSW instructions kX86InstGroupX87Status, // Group for movbe instruction kX86InstGroupMovBE, // Group for MMX/SSE instructions in format (X)MM|Reg|Mem <- (X)MM|Reg|Mem, // 0x66 prefix must be set manually in opcodes. // - Primary opcode is used for instructions in (X)MM <- (X)MM/Mem format, // - Secondary opcode is used for instructions in (X)MM/Mem <- (X)MM format. kX86InstGroupMmuMov, kX86InstGroupMmuMovD, kX86InstGroupMmuMovQ, // Group for pextrd, pextrq and pextrw instructions (it's special instruction // not similar to others) kX86InstGroupMmuExtract, // Group for prefetch instruction kX86InstGroupMmuPrefetch, // Group for MMX/SSE instructions in format (X)MM|Reg <- (X)MM|Reg|Mem|Imm, // 0x66 prefix is added for MMX instructions that used by SSE2 registers. // - Primary opcode is used for instructions in (X)MM|Reg <- (X)MM|Reg|Mem format, // - Secondary opcode is iused for instructions in (X)MM|Reg <- Imm format. kX86InstGroupMmuRmI, kX86InstGroupMmuRmImm8, // Group for 3dNow instructions kX86InstGroupMmuRm3dNow }; // ============================================================================ // [AsmJit::kX86InstFlags] // ============================================================================ //! @brief X86 instruction type flags. enum kX86InstFlags { //! @brief No flags. kX86InstFlagNone = 0x00, //! @brief Instruction is jump, conditional jump, call or ret. kX86InstFlagJump = 0x01, //! @brief Instruction will overwrite first operand - o[0]. kX86InstFlagMov = 0x02, //! @brief Instruction is X87 FPU. kX86InstFlagFpu = 0x04, //! @brief Instruction can be prepended using LOCK prefix //! (usable for multithreaded applications). kX86InstFlagLockable = 0x08, //! @brief Instruction is special, this is for @c Compiler. kX86InstFlagSpecial = 0x10, //! @brief Instruction always performs memory access. //! //! This flag is always combined with @c kX86InstFlagSpecial and signalizes //! that there is an implicit address which is accessed (usually EDI/RDI or //! ESI/EDI). kX86InstFlagSpecialMem = 0x20 }; // ============================================================================ // [AsmJit::kX86InstOp] // ============================================================================ //! @brief X86 instruction operand flags. enum kX86InstOp { // X86, MM, XMM kX86InstOpGb = 0x0001, kX86InstOpGw = 0x0002, kX86InstOpGd = 0x0004, kX86InstOpGq = 0x0008, kX86InstOpMm = 0x0010, kX86InstOpXmm = 0x0020, kX86InstOpMem = 0x0040, kX86InstOpImm = 0x0080, kX86InstOpGbMem = kX86InstOpGb | kX86InstOpMem, kX86InstOpGwMem = kX86InstOpGw | kX86InstOpMem, kX86InstOpGdMem = kX86InstOpGd | kX86InstOpMem, kX86InstOpGqMem = kX86InstOpGq | kX86InstOpMem, kX86InstOpGqdwb = kX86InstOpGq | kX86InstOpGd | kX86InstOpGw | kX86InstOpGb, kX86InstOpGqdw = kX86InstOpGq | kX86InstOpGd | kX86InstOpGw, kX86InstOpGqd = kX86InstOpGq | kX86InstOpGd, kX86InstOpGwb = kX86InstOpGw | kX86InstOpGb, kX86InstOpGqdwbMem = kX86InstOpGqdwb | kX86InstOpMem, kX86InstOpGqdwMem = kX86InstOpGqdw | kX86InstOpMem, kX86InstOpGqdMem = kX86InstOpGqd | kX86InstOpMem, kX86InstOpGwbMem = kX86InstOpGwb | kX86InstOpMem, // MMX/XMM. kX86InstOpMmMem = kX86InstOpMm | kX86InstOpMem, kX86InstOpXmmMem = kX86InstOpXmm | kX86InstOpMem, kX86InstOpMmXmm = kX86InstOpMm | kX86InstOpXmm, kX86InstOpMmXmmMem = kX86InstOpMmXmm | kX86InstOpMem, // X87. kX86InstOpStM2 = kX86InstOpMem | 0x0100, kX86InstOpStM4 = kX86InstOpMem | 0x0200, kX86InstOpStM8 = kX86InstOpMem | 0x0400, kX86InstOpStM10 = kX86InstOpMem | 0x0800, kX86InstOpStM2_4 = kX86InstOpStM2 | kX86InstOpStM4, kX86InstOpStM2_4_8 = kX86InstOpStM2_4 | kX86InstOpStM8, kX86InstOpStM4_8 = kX86InstOpStM4 | kX86InstOpStM8, kX86InstOpStM4_8_10 = kX86InstOpStM4_8 | kX86InstOpStM10, // Don't emit REX prefix. kX86InstOpNoRex = 0x2000 }; // ============================================================================ // [AsmJit::x86InstName] // ============================================================================ //! @internal //! //! @brief X86 instruction names. ASMJIT_VAR const char x86InstName[]; // ============================================================================ // [AsmJit::X86InstInfo] // ============================================================================ //! @brief X86 instruction information. struct X86InstInfo { // -------------------------------------------------------------------------- // [Accessors] // -------------------------------------------------------------------------- //! @brief Get instruction code, see @ref kX86InstCode. inline uint32_t getCode() const { return _code; } //! @brief Get instruction name string (null terminated string). inline const char* getName() const { return x86InstName + static_cast(_nameIndex); } //! @brief Get instruction name index (index to @ref x86InstName array). inline uint32_t getNameIndex() const { return _nameIndex; } //! @brief Get instruction group, see @ref kX86InstGroup. inline uint32_t getGroup() const { return _group; } //! @brief Get instruction flags, see @ref kX86InstFlags. inline uint32_t getFlags() const { return _group; } //! @brief Get whether the instruction is conditional or standard jump. inline bool isJump() const { return (_flags & kX86InstFlagJump) != 0; } //! @brief Get whether the instruction is MOV type. inline bool isMov() const { return (_flags & kX86InstFlagMov) != 0; } //! @brief Get whether the instruction is X87 FPU type. inline bool isFpu() const { return (_flags & kX86InstFlagFpu) != 0; } //! @brief Get whether the instruction can be prefixed by LOCK prefix. inline bool isLockable() const { return (_flags & kX86InstFlagLockable) != 0; } //! @brief Get whether the instruction is special type (this is used by //! @c Compiler to manage additional variables or functionality). inline bool isSpecial() const { return (_flags & kX86InstFlagSpecial) != 0; } //! @brief Get whether the instruction is special type and it performs //! memory access. inline bool isSpecialMem() const { return (_flags & kX86InstFlagSpecialMem) != 0; } // -------------------------------------------------------------------------- // [Members] // -------------------------------------------------------------------------- //! @brief Instruction code. uint16_t _code; //! @brief Instruction name index in x86InstName[] array. uint16_t _nameIndex; //! @brief Instruction group, used also by @c Compiler. uint8_t _group; //! @brief Instruction type flags. uint8_t _flags; //! @brief First and second operand flags (some groups depends on these settings, used also by @c Compiler). uint16_t _opFlags[2]; //! @brief If instruction has only memory operand, this is register opcode. uint16_t _opCodeR; //! @brief Primary and secondary opcodes. uint32_t _opCode[2]; }; // ============================================================================ // [AsmJit::x86InstInfo] // ============================================================================ ASMJIT_VAR const X86InstInfo x86InstInfo[]; // ============================================================================ // [AsmJit::kX86FuncConv] // ============================================================================ //! @brief X86 function calling conventions. //! //! Calling convention is scheme how function arguments are passed into //! function and how functions returns values. In assembler programming //! it's needed to always comply with function calling conventions, because //! even small inconsistency can cause undefined behavior or crash. //! //! List of calling conventions for 32-bit x86 mode: //! - @c kX86FuncConvCDecl - Calling convention for C runtime. //! - @c kX86FuncConvStdCall - Calling convention for WinAPI functions. //! - @c kX86FuncConvMsThisCall - Calling convention for C++ members under //! Windows (produced by MSVC and all MSVC compatible compilers). //! - @c kX86FuncConvMsFastCall - Fastest calling convention that can be used //! by MSVC compiler. //! - @c kX86FuncConv_BORNANDFASTCALL - Borland fastcall convention. //! - @c kX86FuncConvGccFastCall - GCC fastcall convention (2 register arguments). //! - @c kX86FuncConvGccRegParm1 - GCC regparm(1) convention. //! - @c kX86FuncConvGccRegParm2 - GCC regparm(2) convention. //! - @c kX86FuncConvGccRegParm3 - GCC regparm(3) convention. //! //! List of calling conventions for 64-bit x86 mode (x64): //! - @c kX86FuncConvX64W - Windows 64-bit calling convention (WIN64 ABI). //! - @c kX86FuncConvX64U - Unix 64-bit calling convention (AMD64 ABI). //! //! There is also @c kX86FuncConvDefault that is defined to fit best to your //! compiler. //! //! These types are used together with @c AsmJit::Compiler::newFunc() //! method. enum kX86FuncConv { // -------------------------------------------------------------------------- // [X64] // -------------------------------------------------------------------------- //! @brief X64 calling convention for Windows platform (WIN64 ABI). //! //! For first four arguments are used these registers: //! - 1. 32/64-bit integer or floating point argument - rcx/xmm0 //! - 2. 32/64-bit integer or floating point argument - rdx/xmm1 //! - 3. 32/64-bit integer or floating point argument - r8/xmm2 //! - 4. 32/64-bit integer or floating point argument - r9/xmm3 //! //! Note first four arguments here means arguments at positions from 1 to 4 //! (included). For example if second argument is not passed by register then //! rdx/xmm1 register is unused. //! //! All other arguments are pushed on the stack in right-to-left direction. //! Stack is aligned by 16 bytes. There is 32-byte shadow space on the stack //! that can be used to save up to four 64-bit registers (probably designed to //! be used to save first four arguments passed in registers). //! //! Arguments direction: //! - Right to Left (except for first 4 parameters that's in registers) //! //! Stack is cleaned by: //! - Caller. //! //! Return value: //! - Integer types - RAX register. //! - Floating points - XMM0 register. //! //! Stack is always aligned by 16 bytes. //! //! More information about this calling convention can be found on MSDN: //! http://msdn.microsoft.com/en-us/library/9b372w95.aspx . kX86FuncConvX64W = 1, //! @brief X64 calling convention for Unix platforms (AMD64 ABI). //! //! First six 32 or 64-bit integer arguments are passed in rdi, rsi, rdx, //! rcx, r8, r9 registers. First eight floating point or XMM arguments //! are passed in xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7 registers. //! This means that in registers can be transferred up to 14 arguments total. //! //! There is also RED ZONE below the stack pointer that can be used for //! temporary storage. The red zone is the space from [rsp-128] to [rsp-8]. //! //! Arguments direction: //! - Right to Left (Except for arguments passed in registers). //! //! Stack is cleaned by: //! - Caller. //! //! Return value: //! - Integer types - RAX register. //! - Floating points - XMM0 register. //! //! Stack is always aligned by 16 bytes. kX86FuncConvX64U = 2, // -------------------------------------------------------------------------- // [X86] // -------------------------------------------------------------------------- //! @brief Cdecl calling convention (used by C runtime). //! //! Compatible across MSVC and GCC. //! //! Arguments direction: //! - Right to Left //! //! Stack is cleaned by: //! - Caller. kX86FuncConvCDecl = 3, //! @brief Stdcall calling convention (used by WinAPI). //! //! Compatible across MSVC and GCC. //! //! Arguments direction: //! - Right to Left //! //! Stack is cleaned by: //! - Callee. //! //! Return value: //! - Integer types - EAX:EDX registers. //! - Floating points - st(0) register. kX86FuncConvStdCall = 4, //! @brief MSVC specific calling convention used by MSVC/Intel compilers //! for struct/class methods. //! //! This is MSVC (and Intel) only calling convention used in Windows //! world for C++ class methods. Implicit 'this' pointer is stored in //! ECX register instead of storing it on the stack. //! //! Arguments direction: //! - Right to Left (except this pointer in ECX) //! //! Stack is cleaned by: //! - Callee. //! //! Return value: //! - Integer types - EAX:EDX registers. //! - Floating points - st(0) register. //! //! C++ class methods that have variable count of arguments uses different //! calling convention called cdecl. //! //! @note This calling convention is always used by MSVC for class methods, //! it's implicit and there is no way how to override it. kX86FuncConvMsThisCall = 5, //! @brief MSVC specific fastcall. //! //! Two first parameters (evaluated from left-to-right) are in ECX:EDX //! registers, all others on the stack in right-to-left order. //! //! Arguments direction: //! - Right to Left (except to first two integer arguments in ECX:EDX) //! //! Stack is cleaned by: //! - Callee. //! //! Return value: //! - Integer types - EAX:EDX registers. //! - Floating points - st(0) register. //! //! @note This calling convention differs to GCC one in stack cleaning //! mechanism. kX86FuncConvMsFastCall = 6, //! @brief Borland specific fastcall with 2 parameters in registers. //! //! Two first parameters (evaluated from left-to-right) are in ECX:EDX //! registers, all others on the stack in left-to-right order. //! //! Arguments direction: //! - Left to Right (except to first two integer arguments in ECX:EDX) //! //! Stack is cleaned by: //! - Callee. //! //! Return value: //! - Integer types - EAX:EDX registers. //! - Floating points - st(0) register. //! //! @note Arguments on the stack are in left-to-right order that differs //! to other fastcall conventions used in different compilers. kX86FuncConvBorlandFastCall = 7, //! @brief GCC specific fastcall convention. //! //! Two first parameters (evaluated from left-to-right) are in ECX:EDX //! registers, all others on the stack in right-to-left order. //! //! Arguments direction: //! - Right to Left (except to first two integer arguments in ECX:EDX) //! //! Stack is cleaned by: //! - Callee. //! //! Return value: //! - Integer types - EAX:EDX registers. //! - Floating points - st(0) register. //! //! @note This calling convention should be compatible to //! @c kX86FuncConvMsFastCall. kX86FuncConvGccFastCall = 8, //! @brief GCC specific regparm(1) convention. //! //! The first parameter (evaluated from left-to-right) is in EAX register, //! all others on the stack in right-to-left order. //! //! Arguments direction: //! - Right to Left (except to first one integer argument in EAX) //! //! Stack is cleaned by: //! - Caller. //! //! Return value: //! - Integer types - EAX:EDX registers. //! - Floating points - st(0) register. kX86FuncConvGccRegParm1 = 9, //! @brief GCC specific regparm(2) convention. //! //! Two first parameters (evaluated from left-to-right) are in EAX:EDX //! registers, all others on the stack in right-to-left order. //! //! Arguments direction: //! - Right to Left (except to first two integer arguments in EAX:EDX) //! //! Stack is cleaned by: //! - Caller. //! //! Return value: //! - Integer types - EAX:EDX registers. //! - Floating points - st(0) register. kX86FuncConvGccRegParm2 = 10, //! @brief GCC specific fastcall with 3 parameters in registers. //! //! Three first parameters (evaluated from left-to-right) are in //! EAX:EDX:ECX registers, all others on the stack in right-to-left order. //! //! Arguments direction: //! - Right to Left (except to first three integer arguments in EAX:EDX:ECX) //! //! Stack is cleaned by: //! - Caller. //! //! Return value: //! - Integer types - EAX:EDX registers. //! - Floating points - st(0) register. kX86FuncConvGccRegParm3 = 11, // -------------------------------------------------------------------------- // [Detect] // -------------------------------------------------------------------------- //! @def kX86FuncConvDefault //! @brief Default calling convention for current platform / operating system. //! @def kX86FuncConvCompatFastCall //! @brief Compatibility for __fastcall calling convention. //! //! @note This enumeration is always set to a value which is compatible to //! current compilers __fastcall calling convention. In 64-bit mode the value //! is compatible to @ref kX86FuncConvX64W or @ref kX86FuncConvX64U. //! @def kX86FuncConvCompatStdCall //! @brief Compatibility for __stdcall calling convention. //! //! @note This enumeration is always set to a value which is compatible to //! current compilers __stdcall calling convention. In 64-bit mode the value //! is compatible to @ref kX86FuncConvX64W or @ref kX86FuncConvX64U. //! @def kX86FuncConvCompatCDecl //! @brief Default C calling convention based on current compiler's settings. #if defined(ASMJIT_X86) kX86FuncConvDefault = kX86FuncConvCDecl, # if defined(_MSC_VER) kX86FuncConvCompatFastCall = kX86FuncConvMsFastCall, # elif defined(__GNUC__) kX86FuncConvCompatFastCall = kX86FuncConvGccFastCall, # elif defined(__BORLANDC__) kX86FuncConvCompatFastCall = kX86FuncConvBorlandFastCall, # else # error "AsmJit::kX86FuncConvCompatFastCall not supported." # endif kX86FuncConvCompatStdCall = kX86FuncConvStdCall, kX86FuncConvCompatCDecl = kX86FuncConvCDecl #else # if defined(ASMJIT_WINDOWS) kX86FuncConvDefault = kX86FuncConvX64W, # else kX86FuncConvDefault = kX86FuncConvX64U, # endif kX86FuncConvCompatFastCall = kX86FuncConvDefault, kX86FuncConvCompatStdCall = kX86FuncConvDefault, kX86FuncConvCompatCDecl = kX86FuncConvDefault #endif // ASMJIT_X86 }; // ============================================================================ // [AsmJit::kX86FuncHint] // ============================================================================ //! @brief X86 function hints. enum kX86FuncHint { //! @brief Use push/pop sequences instead of mov sequences in function prolog //! and epilog. kX86FuncHintPushPop = 8, //! @brief Add emms instruction to the function epilog. kX86FuncHintEmms = 9, //! @brief Add sfence instruction to the function epilog. kX86FuncHintSFence = 10, //! @brief Add lfence instruction to the function epilog. kX86FuncHintLFence = 11, //! @brief Assume that stack is aligned to 16-bytes. kX86FuncHintAssume16ByteAlignment = 12, //! @brief Perform 16-byte stack alignmend by function. kX86FuncHintPerform16ByteAlignment = 13 }; // ============================================================================ // [AsmJit::kX86FuncFlags] // ============================================================================ //! @brief X86 function flags. enum kX86FuncFlags { //! @brief Whether to emit prolog / epilog sequence using push & pop //! instructions (the default). kX86FuncFlagPushPop = (1U << 8), //! @brief Whether to emit EMMS instruction in epilog (auto-detected). kX86FuncFlagEmitEmms = (1U << 9), //! @brief Whether to emit SFence instruction in epilog (auto-detected). //! //! @note @ref kX86FuncFlagEmitSFence and @ref kX86FuncFlagEmitLFence //! combination will result in emitting mfence. kX86FuncFlagEmitSFence = (1U << 10), //! @brief Whether to emit LFence instruction in epilog (auto-detected). //! //! @note @ref kX86FuncFlagEmitSFence and @ref kX86FuncFlagEmitLFence //! combination will result in emitting mfence. kX86FuncFlagEmitLFence = (1U << 11), //! @brief Whether the function stack is aligned by 16-bytes by OS. //! //! This is always true for 64-bit mode and for linux. kX86FuncFlagAssume16ByteAlignment = (1U << 12), //! @brief Whether the function stack (for variables) is aligned manually //! by function to 16-bytes. //! //! This makes sense only if @ref kX86FuncFlagAssume16ByteAlignment is //! false and MOVDQA instruction or other SSE/SSE2 instructions are used to //! work with variables stored on the stack. //! //! Value is determined automatically by these factors, expectations are: //! //! 1. There is 16-byte wide variable which address was used (alloc, spill, //! op). //! 2. Function can't be naked. kX86FuncFlagPerform16ByteAlignment = (1U << 13), //! @brief Whether the ESP register is adjusted by the stack size needed //! to save registers and function variables. //! //! Esp is adjusted by 'sub' instruction in prolog and by add function in //! epilog (only if function is not naked). kX86FuncFlagIsEspAdjusted = (1U << 14) }; // ============================================================================ // [AsmJit::kX86CompilerInst] // ============================================================================ //! @brief Instruction flags used by @ref X86CompilerInst item. enum kX86CompilerInstFlag { //! @brief Whether the instruction is special. kX86CompilerInstFlagIsSpecial = (1U << 0), //! @brief Whether the instruction is FPU. kX86CompilerInstFlagIsFpu = (1U << 1), //! @brief Whether the one of the operands is GPB.Lo register. kX86CompilerInstFlagIsGpbLoUsed = (1U << 2), //! @brief Whether the one of the operands is GPB.Hi register. kX86CompilerInstFlagIsGpbHiUsed = (1U << 3), //! @brief Whether the jmp/jcc is likely to be taken. kX86CompilerInstFlagIsTaken = (1U << 7) }; // ============================================================================ // [AsmJit::kX86VarClass] // ============================================================================ //! @brief X86 variable class. enum kX86VarClass { //! @brief No class (used internally). kX86VarClassNone = 0, //! @brief General purpose register. kX86VarClassGp = 1, //! @brief X87 floating point. kX86VarClassX87 = 2, //! @brief MMX register. kX86VarClassMm = 3, //! @brief XMM register. kX86VarClassXmm = 4, //! @brief Count of X86 variable classes. kX86VarClassCount = 5 }; // ============================================================================ // [AsmJit::kX86VarFlags] // ============================================================================ //! @brief X86 variable class. enum kX86VarFlags { //! @brief Variable contains single-precision floating-point(s). kX86VarFlagSP = 0x10, //! @brief Variable contains double-precision floating-point(s). kX86VarFlagDP = 0x20, //! @brief Variable is packed (for example float4x, double2x, ...). kX86VarFlagPacked = 0x40 }; // ============================================================================ // [AsmJit::kX86VarType] // ============================================================================ //! @brief X86 variable type. enum kX86VarType { // -------------------------------------------------------------------------- // [Platform Dependent] // -------------------------------------------------------------------------- //! @brief Variable is 32-bit general purpose register. kX86VarTypeGpd = 0, //! @brief Variable is 64-bit general purpose register. kX86VarTypeGpq = 1, //! @var kX86VarTypeGpz //! @brief Variable is system wide general purpose register (32-bit or 64-bit). #if defined(ASMJIT_X86) kX86VarTypeGpz = kX86VarTypeGpd, #else kX86VarTypeGpz = kX86VarTypeGpq, #endif //! @brief Variable is X87 (FPU). kX86VarTypeX87 = 2, //! @brief Variable is X87 (FPU) SP-FP number (float). kX86VarTypeX87SS = 3, //! @brief Variable is X87 (FPU) DP-FP number (double). kX86VarTypeX87SD = 4, //! @brief Variable is MM register / memory location. kX86VarTypeMm = 5, //! @brief Variable is XMM register / memory location. kX86VarTypeXmm = 6, //! @brief Variable is SSE scalar SP-FP number. kX86VarTypeXmmSS = 7, //! @brief Variable is SSE packed SP-FP number (4 floats). kX86VarTypeXmmPS = 8, //! @brief Variable is SSE2 scalar DP-FP number. kX86VarTypeXmmSD = 9, //! @brief Variable is SSE2 packed DP-FP number (2 doubles). kX86VarTypeXmmPD = 10, //! @brief Count of variable types. kX86VarTypeCount = 11, // -------------------------------------------------------------------------- // [Platform Independent] // -------------------------------------------------------------------------- //! @brief Variable is 32-bit integer. kX86VarTypeInt32 = kX86VarTypeGpd, //! @brief Variable is 64-bit integer. kX86VarTypeInt64 = kX86VarTypeGpq, //! @brief Variable is system dependent integer / pointer. kX86VarTypeIntPtr = kX86VarTypeGpz, #if defined(ASMJIT_X86) kX86VarTypeFloat = kX86VarTypeX87SS, kX86VarTypeDouble = kX86VarTypeX87SD #else kX86VarTypeFloat = kX86VarTypeXmmSS, kX86VarTypeDouble = kX86VarTypeXmmSD #endif }; // ============================================================================ // [AsmJit::X86VarInfo] // ============================================================================ //! @brief X86 variable information. struct X86VarInfo { // -------------------------------------------------------------------------- // [Accessors] // -------------------------------------------------------------------------- //! @brief Get register code base, see @ref kX86RegCode. inline uint32_t getCode() const { return _code; } //! @brief Get register size in bytes. inline uint32_t getSize() const { return _size; } //! @brief Get variable class, see @ref kX86VarClass. inline uint32_t getClass() const { return _class; } //! @brief Get variable flags, see @ref kX86VarFlags. inline uint32_t getFlags() const { return _flags; } //! @brief Get variable type name. inline const char* getName() const { return _name; } // -------------------------------------------------------------------------- // [Members] // -------------------------------------------------------------------------- //! @brief Register code base, see @ref kX86RegCode. uint32_t _code; //! @brief Register size in bytes. uint16_t _size; //! @brief Variable class, see @ref kX86VarClass. uint8_t _class; //! @brief Variable flags, see @ref kX86VarFlags. uint8_t _flags; //! @brief Variable type name. char _name[8]; }; // ============================================================================ // [AsmJit::x86VarInfo] // ============================================================================ ASMJIT_VAR const X86VarInfo x86VarInfo[]; //! @} } // AsmJit namespace // [Api-End] #include "../core/apiend.h" // [Guard] #endif // _ASMJIT_X86_X86DEFS_H desmume/src/libretro-common/encodings/encoding_utf.c000664 001750 001750 00000012256 12755534123 024036 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2016 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (encodings_utf.c). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include #include #include #include #include #include static INLINE unsigned leading_ones(uint8_t c) { unsigned ones = 0; while (c & 0x80) { ones++; c <<= 1; } return ones; } /* Simple implementation. Assumes the sequence is * properly synchronized and terminated. */ size_t utf8_conv_utf32(uint32_t *out, size_t out_chars, const char *in, size_t in_size) { unsigned i; size_t ret = 0; while (in_size && out_chars) { unsigned extra, shift; uint32_t c; uint8_t first = *in++; unsigned ones = leading_ones(first); if (ones > 6 || ones == 1) /* Invalid or desync. */ break; extra = ones ? ones - 1 : ones; if (1 + extra > in_size) /* Overflow. */ break; shift = (extra - 1) * 6; c = (first & ((1 << (7 - ones)) - 1)) << (6 * extra); for (i = 0; i < extra; i++, in++, shift -= 6) c |= (*in & 0x3f) << shift; *out++ = c; in_size -= 1 + extra; out_chars--; ret++; } return ret; } bool utf16_conv_utf8(uint8_t *out, size_t *out_chars, const uint16_t *in, size_t in_size) { static uint8_t kUtf8Limits[5] = { 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; size_t out_pos = 0; size_t in_pos = 0; for (;;) { unsigned numAdds; uint32_t value; if (in_pos == in_size) { *out_chars = out_pos; return true; } value = in[in_pos++]; if (value < 0x80) { if (out) out[out_pos] = (char)value; out_pos++; continue; } if (value >= 0xD800 && value < 0xE000) { uint32_t c2; if (value >= 0xDC00 || in_pos == in_size) break; c2 = in[in_pos++]; if (c2 < 0xDC00 || c2 >= 0xE000) break; value = (((value - 0xD800) << 10) | (c2 - 0xDC00)) + 0x10000; } for (numAdds = 1; numAdds < 5; numAdds++) if (value < (((uint32_t)1) << (numAdds * 5 + 6))) break; if (out) out[out_pos] = (char)(kUtf8Limits[numAdds - 1] + (value >> (6 * numAdds))); out_pos++; do { numAdds--; if (out) out[out_pos] = (char)(0x80 + ((value >> (6 * numAdds)) & 0x3F)); out_pos++; }while (numAdds != 0); } *out_chars = out_pos; return false; } /* Acts mostly like strlcpy. * * Copies the given number of UTF-8 characters, * but at most d_len bytes. * * Always NULL terminates. * Does not copy half a character. * * Returns number of bytes. 's' is assumed valid UTF-8. * Use only if 'chars' is considerably less than 'd_len'. */ size_t utf8cpy(char *d, size_t d_len, const char *s, size_t chars) { #ifdef HAVE_UTF8 char *d_org = d; char *d_end = d+d_len; const uint8_t *sb = (const uint8_t*)s; const uint8_t *sb_org = sb; while (*sb && chars-- > 0) { sb++; while ((*sb&0xC0) == 0x80) sb++; } if (sb - sb_org > d_len-1 /* NUL */) { sb = sb_org + d_len-1; while ((*sb&0xC0) == 0x80) sb--; } memcpy(d, sb_org, sb-sb_org); d[sb-sb_org] = '\0'; return sb-sb_org; #else return strlcpy(d, s, chars + 1); #endif } const char *utf8skip(const char *str, size_t chars) { #ifdef HAVE_UTF8 const uint8_t *strb = (const uint8_t*)str; if (!chars) return str; do { strb++; while ((*strb&0xC0)==0x80) strb++; chars--; } while(chars); return (const char*)strb; #else return str + chars; #endif } size_t utf8len(const char *string) { #ifdef HAVE_UTF8 size_t ret = 0; while (*string) { if ((*string & 0xC0) != 0x80) ret++; string++; } return ret; #else return strlen(string); #endif } desmume/src/version.h000664 001750 001750 00000002344 12755534123 016000 0ustar00sergiosergio000000 000000 /* Copyright (C) 2009-2013 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the this software. If not, see . */ #ifndef _DESMUME_VERSION_H #define _DESMUME_VERSION_H #include #ifdef __cplusplus extern "C" { #endif extern const uint8_t DESMUME_VERSION_MAJOR; extern const uint8_t DESMUME_VERSION_MINOR; extern const uint8_t DESMUME_VERSION_BUILD; uint32_t EMU_DESMUME_VERSION_NUMERIC(); uint32_t EMU_DESMUME_SUBVERSION_NUMERIC(); const char* EMU_DESMUME_VERSION_STRING(); const char* EMU_DESMUME_SUBVERSION_STRING(); const char* EMU_DESMUME_NAME_AND_VERSION(); const char* EMU_DESMUME_COMPILER_DETAIL(); #ifdef __cplusplus } #endif #endif desmume/src/utils/fsnitro.cpp000664 001750 001750 00000032504 12755534123 017473 0ustar00sergiosergio000000 000000 /* Copyright (C) 2013 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the this software. If not, see . */ #include "types.h" #include #include #ifdef WIN32 #include #ifdef _XBOX #include #else #include #endif #define __mkdir(x) mkdir(x) #else #include #include #include #include #define __mkdir(x) mkdir(x, 0777) #endif #include "fsnitro.h" using namespace std; #ifdef HOST_WINDOWS #define FS_DIRECTORY_DELIMITER_CHAR "\\" #else #define FS_DIRECTORY_DELIMITER_CHAR "/" #endif FS_NITRO::FS_NITRO(u8 *cart_rom) { inited = false; numDirs = numFiles = numOverlay7 = numOverlay9 = currentID =0; fat = NULL; fnt = NULL; ovr9 = NULL; ovr7 = NULL; if (!cart_rom) return; rom = cart_rom; FNameTblOff = *(u32*)(rom + 0x40); FNameTblSize = *(u32*)(rom + 0x44); FATOff = *(u32*)(rom + 0x48); FATSize = *(u32*)(rom + 0x4C); ARM9OverlayOff = *(u32*)(rom + 0x50); ARM9OverlaySize = *(u32*)(rom + 0x54); ARM7OverlayOff = *(u32*)(rom + 0x58); ARM7OverlaySize = *(u32*)(rom + 0x5C); ARM9exeSize = *(u32*)(rom + 0x2C); ARM9exeStart = *(u32*)(rom + 0x20); ARM9exeEnd = (ARM9exeStart + ARM9exeSize); ARM7exeSize = *(u32*)(rom + 0x3C); ARM7exeStart = *(u32*)(rom + 0x30); ARM7exeEnd = (ARM7exeStart + ARM7exeSize); //printf("ARM9exe %08Xh - %08Xh, size %08Xh\n", ARM9exeStart, ARM9exeEnd, ARM9exeSize); //printf("ARM7exe %08Xh - %08Xh, size %08Xh\n", ARM7exeStart, ARM7exeEnd, ARM7exeSize); if (FNameTblOff < 0x8000) return; if (FNameTblOff == 0) return; if (FATOff < 0x8000) return; if (FATSize == 0) return; numDirs = *(u16*)(rom + FNameTblOff + 6); numFiles = FATSize / 8; if (numFiles == 0 || numDirs == 0) { numFiles = numDirs = 0; return; } FATEnd = (FATOff + FATSize); numOverlay9 = ARM9OverlaySize / sizeof(OVR_NITRO); numOverlay7 = ARM7OverlaySize / sizeof(OVR_NITRO); printf("Nitro File System:\n"); printf("\t* FNT at 0x%08X, size 0x%08X\n", FNameTblOff, FNameTblSize); printf("\t* FAT at 0x%08X, size 0x%08X\n", FATOff, FATSize); printf("\t* ARM9 at Overlay 0x%08X, size 0x%08X\n", ARM9OverlayOff, ARM9OverlaySize); printf("\t* ARM7 at Overlay 0x%08X, size 0x%08X\n", ARM7OverlayOff, ARM7OverlaySize); printf("\t* ARM9 exe at %08X, size %08Xh\n", ARM9exeStart, ARM9exeSize); printf("\t* ARM7 exe at %08X, size %08Xh\n", ARM7exeStart, ARM7exeSize); printf("\t* Directories: %u\n", numDirs); printf("\t* Files %u\n", numFiles); printf("\t* ARM9 Overlays %u\n", numOverlay9); printf("\t* ARM7 Overlays %u\n", numOverlay7); fat = new FAT_NITRO[numFiles]; fnt = new FNT_NITRO[numDirs]; if (numOverlay7) ovr7 = new OVR_NITRO[numOverlay7]; if (numOverlay9) ovr9 = new OVR_NITRO[numOverlay9]; if (!loadFileTables()) { destroy(); printf("FSNITRO: Error loading file system tables\n"); return; } inited = true; } FS_NITRO::~FS_NITRO() { destroy(); } void FS_NITRO::destroy() { if (fat) { delete [] fat; fat = NULL; } if (fnt) { delete [] fnt; fnt = NULL; } if (ovr9) { delete [] ovr9; ovr9 = NULL; } if (ovr7) { delete [] ovr7; ovr7 = NULL; } numDirs = numFiles = numOverlay7 = numOverlay9 = currentID = 0; inited = false; } FNT_TYPES FS_NITRO::getFNTType(u8 type) { if (type == 0x00) return FS_END_SUBTABLE; if (type == 0x80) return FS_RESERVED; if (type < 0x80) return FS_FILE_ENTRY; return FS_SUBDIR_ENTRY; } bool FS_NITRO::loadFileTables() { if (!fnt) return false; if (!fat) return false; if (numOverlay7 && !ovr7) return false; if (numOverlay9 && !ovr9) return false; delete[] fat; delete[] fnt; fat = new FAT_NITRO[numFiles]; fnt = new FNT_NITRO[numDirs]; // ========= FAT (File Allocation Table) u32 *_FAT = (u32*)(rom + FATOff); for (u32 i = 0; i < numFiles; i++) { const u32 ofs = (i * 2); fat[i].start = *(_FAT + ofs); fat[i].end = *(_FAT + ofs + 1); fat[i].size = fat[i].end - fat[i].start; fat[i].sizeFile = fat[i].size; fat[i].isOverlay = false; } // ========= Overlays ARM9 if (numOverlay9) { memcpy(ovr9, (rom + ARM9OverlayOff), ARM9OverlaySize); for (u32 i = 0 ; i < numOverlay9; i++) { char buf[129] = {0}; memset(&buf[0], 0, sizeof(buf)); fat[ovr9[i].fileID].isOverlay = true; sprintf(buf, "overlay_%04u.bin", ovr9[i].id); fat[ovr9[i].fileID].filename = buf; } } // ========= Overlays ARM7 if (numOverlay7) { memcpy(ovr7, (rom + ARM7OverlayOff), ARM7OverlaySize); for (u32 i = 0 ; i < numOverlay7; i++) { char buf[129] = {0}; memset(&buf[0], 0, sizeof(buf)); fat[ovr7[i].fileID].isOverlay = true; sprintf(buf, "overlay_%04u.bin", ovr7[i].id); fat[ovr7[i].fileID].filename = buf; } } // ========= FNT (File Names Table) u8 *_FNT = (u8*)(rom + FNameTblOff); for (u32 i = 0; i < numDirs; i++) { memcpy(&fnt[i], _FNT, 8); //printf("FNT %04Xh: sub:%08Xh, 1st ID:%04xh, parentID:%04Xh\n", i, fnt[i].offset, fnt[i].firstID, fnt[i].parentID); _FNT += 8; } // ========= Read file structure u8 *sub = (u8*)(rom + FNameTblOff + fnt[0].offset); u8 *_end = (u8*)(rom + FNameTblOff + FNameTblSize - 1); u16 fileCount = fnt[0].firstID; u16 fntID = 0xF000; uintptr_t *store = new uintptr_t[numDirs]; if (!store) return false; memset(store, 0, sizeof(uintptr_t) * numDirs); fnt[0].filename = FS_DIRECTORY_DELIMITER_CHAR; fnt[0].parentID = 0xF000; //printf("FNT F000: Sub:%08Xh, 1st ID:%04xh, parentID:%04Xh <%s>\n", fnt[0].offset, fnt[0].firstID, fnt[0].parentID, fnt[0].filename); while (true) { u8 len = (sub[0] & 0x7F); FNT_TYPES type = getFNTType(sub[0]); if (type == FS_END_SUBTABLE) { //printf("********** End Subdir (%04Xh, parent %04X)\n", fntID, fnt[fntID & 0x0FFF].parentID); sub = (u8*)store[fntID & 0x0FFF]; fntID = fnt[fntID & 0x0FFF].parentID; continue; } if (type == FS_SUBDIR_ENTRY) { //printf("********** Subdir Entry\n"); char buf[129] = {0}; memcpy(buf, (sub + 1), len); buf[len] = 0; sub += (len + 1); fntID = (*(u16*)sub); sub += 2; u32 id = (fntID & 0x0FFF); store[id] = (uintptr_t)sub; sub = (u8*)(rom + FNameTblOff + fnt[id].offset); fnt[id].filename = buf; //printf("FNT %04X: Sub:%08Xh, 1st ID:%04xh, parentID:%04Xh <%s>\n", fntID, fnt[id].offset, fnt[id].firstID, fnt[id].parentID, buf); continue; } if (type == FS_FILE_ENTRY) { //printf("********** File Entry\n"); char buf[129] = {0}; memcpy(buf, (sub + 1), len); buf[len] = 0; fat[fileCount].filename = buf; fat[fileCount].parentID = fntID; //printf("ID:%04Xh, len %03d, type %d, parentID %04X, filename: %s\n", fileCount, len, (u32)type, fntID, fat[fileCount].filename); sub += (len + 1); fileCount++; if (fileCount >= numFiles) break; continue; } if (type == FS_RESERVED) { printf("********** FS_RESERVED\n"); break; } } delete [] store; store = NULL; return true; } // ======================= tools bool FS_NITRO::rebuildFAT(u32 addr, u32 size, string pathData) { if (!inited) return false; if (size == 0) return false; if (addr < FATOff) return false; if (addr > FATEnd) return false; const u32 startID = (addr - FATOff) / 8; const u32 endID = startID + (size / 8); //printf("Start rebuild FAT (start ID:%04Xh)\n", startID); u8 *romFAT = (u8*)(rom + addr); for (u32 i = startID; i < endID; i++) { if (i >= numFiles) break; string path = pathData + getFullPathByFileID(i); //printf("%04Xh - %s (%d)\n", i, path.c_str(), fat[i].size); fat[i].file = false; FILE *fp = fopen(path.c_str(), "rb"); if (!fp) continue; fseek(fp, 0, SEEK_END); u32 size = ftell(fp); fclose(fp); fat[i].file = true; if (fat[i].size != size) { //printf("Different size: %s (ROM: %d, file %d)\n", path.c_str(), fat[i].size, size); fat[i].sizeFile = size; } else fat[i].sizeFile = fat[i].size; } return true; } bool FS_NITRO::rebuildFAT(string pathData) { return rebuildFAT(FATOff, FATSize, pathData); } u32 FS_NITRO::getFATRecord(u32 addr) { if (!inited) return 0xFFFFFFFF; if (addr < FATOff) return 0xFFFFFFFF; if (addr > FATEnd) return 0xFFFFFFFF; u32 id = (addr - FATOff) / 8; u32 offs = (addr - FATOff) % 8; if (offs == 0) { return fat[id].start; } else { if (fat[id].file) return (fat[id].start + fat[id].sizeFile); else return fat[id].end; } return 0xFFFFFFFF; } bool FS_NITRO::getFileIdByAddr(u32 addr, u16 &id) { id = 0xFFFF; if (!inited) return false; u32 pos = currentID; while (true) { if ((addr >= fat[pos].start) && (addr < fat[pos].end)) { id = pos; currentID = pos; return true; } pos++; if (pos >= numFiles) pos = 0; if (pos == currentID) break; } return false; } bool FS_NITRO::getFileIdByAddr(u32 addr, u16 &id, u32 &offset) { id = 0xFFFF; offset = 0; if (!inited) return false; u32 pos = currentID; while (true) { if ((addr >= fat[pos].start) && (addr < fat[pos].end)) { id = pos; offset = addr - fat[pos].start; currentID = pos; return true; } pos++; if (pos >= numFiles) pos = 0; if (pos == currentID) break; } return false; } string FS_NITRO::getDirNameByID(u16 id) { if (!inited) return ""; if ((id & 0xF000) != 0xF000) return "|file|"; if ((id & 0x0FFF) > numDirs) return ""; return fnt[id & 0x0FFF].filename; } u16 FS_NITRO::getDirParrentByID(u16 id) { if (!inited) return 0xFFFF; if ((id & 0xF000) != 0xF000) return 0xFFFF; if ((id & 0x0FFF) > numDirs) return 0xFFFF; return fnt[id & 0x0FFF].parentID; } string FS_NITRO::getFileNameByID(u16 id) { if (!inited) return ""; if ((id & 0xF000) == 0xF000) return ""; if (id > numFiles) return ""; return fat[id].filename; } u16 FS_NITRO::getFileParentById(u16 id) { if (!inited) return 0xFFFF; if ((id & 0xF000) == 0xF000) return 0xFFFF; if (id > numFiles) return 0xFFFF; return fat[id].parentID; } string FS_NITRO::getFullPathByFileID(u16 id, bool addRoot) { if (!inited) return ""; if (id > numFiles) return ""; string res = ""; if (!fat[id].isOverlay) { u32 parentID = (fat[id].parentID & 0x0FFF); while (parentID) { res = fnt[parentID].filename + string(FS_DIRECTORY_DELIMITER_CHAR) + res; parentID = (fnt[parentID].parentID & 0x0FFF); } if (addRoot) res = string(FS_DIRECTORY_DELIMITER_CHAR) + string("data") + string(FS_DIRECTORY_DELIMITER_CHAR) + res; } else { if (addRoot) res = string(FS_DIRECTORY_DELIMITER_CHAR) + string("overlay") + string(FS_DIRECTORY_DELIMITER_CHAR); } res += fat[id].filename; return res; } u32 FS_NITRO::getFileSizeById(u16 id) { if (!inited) return 0; if (id > numFiles) return 0; return (fat[id].size); } u32 FS_NITRO::getStartAddrById(u16 id) { if (!inited) return 0; if (id > numFiles) return 0; return (fat[id].start); } u32 FS_NITRO::getEndAddrById(u16 id) { if (!inited) return 0; if (id > numFiles) return 0; return (fat[id].end); } bool FS_NITRO::extract(u16 id, string to) { printf("Extract to %s\n", to.c_str()); FILE *fp = fopen(to.c_str(), "wb"); if (fp) { fwrite((rom + fat[id].start), 1, fat[id].size, fp); fclose(fp); return true; } return false; } bool FS_NITRO::extractFile(u16 id, string to) { if (!inited) return false; if (id > numFiles) return false; char curr_dir[PATH_MAX_LENGTH] = {0}; getcwd(curr_dir, sizeof(curr_dir)); chdir(to.c_str()); extract(id, fat[id].filename); chdir(curr_dir); return true; } bool FS_NITRO::extractAll(string to, void (*callback)(u32 current, u32 num)) { if (!inited) return false; string dataDir = to + "data" + FS_DIRECTORY_DELIMITER_CHAR; string overlayDir = to + "overlay" + FS_DIRECTORY_DELIMITER_CHAR; __mkdir(dataDir.c_str()); __mkdir(overlayDir.c_str()); char curr_dir[PATH_MAX_LENGTH] = {0}; getcwd(curr_dir, sizeof(curr_dir)); chdir(dataDir.c_str()); for (u32 i = 0; i < numDirs; i++) { string tmp = fnt[i].filename; u16 parent = (fnt[i].parentID) & 0x0FFF; while (parent) { tmp = fnt[parent].filename + string(FS_DIRECTORY_DELIMITER_CHAR) + tmp; parent = (fnt[parent].parentID) & 0x0FFF; } __mkdir(tmp.c_str()); } chdir(dataDir.c_str()); for (u32 i = 0; i < numFiles; i++) { if (fat[i].isOverlay) continue; string fname = getFullPathByFileID(i, false); extract(i, fname); if (callback) callback(i, numFiles); } chdir(overlayDir.c_str()); for (u32 i = 0; i < numFiles; i++) { if (!fat[i].isOverlay) continue; extract(i, fat[i].filename); } chdir(curr_dir); return true; } desmume/src/utils/AsmJit/core/compileritem.cpp000664 001750 001750 00000017711 12755534123 022622 0ustar00sergiosergio000000 000000 // [AsmJit] // Complete JIT Assembler for C++ Language. // // [License] // Zlib - See COPYING file in this package. #define ASMJIT_EXPORTS // [Dependencies - AsmJit] #include "../core/assembler.h" #include "../core/compiler.h" #include "../core/compilercontext.h" #include "../core/compilerfunc.h" #include "../core/compileritem.h" #include "../core/intutil.h" #include "../core/logger.h" // [Dependencies - C] #include // [Api-Begin] #include "../core/apibegin.h" namespace AsmJit { // ============================================================================ // [AsmJit::CompilerItem - Construction / Destruction] // ============================================================================ CompilerItem::CompilerItem(Compiler* compiler, uint32_t type) : _compiler(compiler), _prev(NULL), _next(NULL), _comment(NULL), _type(static_cast(type)), _isTranslated(false), _isUnreachable(false), _reserved(0), _offset(kInvalidValue) { } CompilerItem::~CompilerItem() { } // ============================================================================ // [AsmJit::CompilerItem - Interface] // ============================================================================ void CompilerItem::prepare(CompilerContext& cc) { _offset = cc._currentOffset; } CompilerItem* CompilerItem::translate(CompilerContext& cc) { return translated(); } void CompilerItem::emit(Assembler& a) {} void CompilerItem::post(Assembler& a) {} // ============================================================================ // [AsmJit::CompilerItem - Misc] // ============================================================================ int CompilerItem::getMaxSize() const { // Default maximum size is -1 which means that it's not known. return -1; } bool CompilerItem::_tryUnuseVar(CompilerVar* v) { return false; } // ============================================================================ // [AsmJit::CompilerItem - Comment] // ============================================================================ void CompilerItem::setComment(const char* str) { _comment = _compiler->getZoneMemory().sdup(str); } void CompilerItem::formatComment(const char* fmt, ...) { // The capacity should be large enough. char buf[128]; va_list ap; va_start(ap, fmt); vsnprintf(buf, ASMJIT_ARRAY_SIZE(buf), fmt, ap); va_end(ap); // I don't know if vsnprintf can produce non-null terminated string, in case // it can, we terminate it here. buf[ASMJIT_ARRAY_SIZE(buf) - 1] = '\0'; setComment(buf); } // ============================================================================ // [AsmJit::CompilerMark - Construction / Destruction] // ============================================================================ CompilerMark::CompilerMark(Compiler* compiler) : CompilerItem(compiler, kCompilerItemMark) { } CompilerMark::~CompilerMark() { } // ============================================================================ // [AsmJit::CompilerMark - Misc] // ============================================================================ int CompilerMark::getMaxSize() const { return 0; } // ============================================================================ // [AsmJit::CompilerComment - Construction / Destruction] // ============================================================================ CompilerComment::CompilerComment(Compiler* compiler, const char* str) : CompilerItem(compiler, kCompilerItemComment) { if (str != NULL) setComment(str); } CompilerComment::~CompilerComment() { } // ============================================================================ // [AsmJit::CompilerComment - Interface] // ============================================================================ void CompilerComment::emit(Assembler& a) { Logger* logger = a.getLogger(); if (logger == NULL || !logger->isUsed()) return; logger->logString(logger->getInstructionPrefix()); logger->logString(getComment()); } // ============================================================================ // [AsmJit::CompilerComment - Misc] // ============================================================================ int CompilerComment::getMaxSize() const { return 0; } // ============================================================================ // [AsmJit::CompilerEmbed - Construction / Destruction] // ============================================================================ CompilerEmbed::CompilerEmbed(Compiler* compiler, const void* data, size_t length) : CompilerItem(compiler, kCompilerItemEmbed) { _length = length; memcpy(_data, data, length); } CompilerEmbed::~CompilerEmbed() { } // ============================================================================ // [AsmJit::CompilerEmbed - Interface] // ============================================================================ void CompilerEmbed::emit(Assembler& a) { a.embed(_data, _length); } // ============================================================================ // [AsmJit::CompilerEmbed - Misc] // ============================================================================ int CompilerEmbed::getMaxSize() const { return (int)_length;; } // ============================================================================ // [AsmJit::CompilerAlign - Construction / Destruction] // ============================================================================ CompilerAlign::CompilerAlign(Compiler* compiler, uint32_t size) : CompilerItem(compiler, kCompilerItemAlign), _size(size) { } CompilerAlign::~CompilerAlign() { } // ============================================================================ // [AsmJit::CompilerAlign - Misc] // ============================================================================ int CompilerAlign::getMaxSize() const { if (_size == 0) return 0; else return static_cast(_size - 1); } // ============================================================================ // [AsmJit::CompilerHint - Construction / Destruction] // ============================================================================ CompilerHint::CompilerHint(Compiler* compiler, CompilerVar* var, uint32_t hintId, uint32_t hintValue) : CompilerItem(compiler, kCompilerItemHint), _var(var), _hintId(hintId), _hintValue(hintValue) { ASMJIT_ASSERT(var != NULL); } CompilerHint::~CompilerHint() { } // ============================================================================ // [AsmJit::CompilerTarget - Construction / Destruction] // ============================================================================ CompilerTarget::CompilerTarget(Compiler* compiler, const Label& label) : CompilerItem(compiler, kCompilerItemTarget), _label(label), _from(NULL), _state(NULL), _jumpsCount(0) { } CompilerTarget::~CompilerTarget() { } // ============================================================================ // [AsmJit::CompilerTarget - Misc] // ============================================================================ int CompilerTarget::getMaxSize() const { return 0; } // ============================================================================ // [AsmJit::CompilerInst - Construction / Destruction] // ============================================================================ CompilerInst::CompilerInst(Compiler* compiler, uint32_t code, Operand* opData, uint32_t opCount) : CompilerItem(compiler, kCompilerItemInst), _code(code), _emitOptions(static_cast(compiler->_emitOptions)), _instFlags(0), _operandsCount(static_cast(opCount)), _variablesCount(0), _operands(opData) { // Each created instruction takes emit options and clears it. compiler->_emitOptions = 0; } CompilerInst::~CompilerInst() { } // ============================================================================ // [AsmJit::CompilerInst - GetJumpTarget] // ============================================================================ CompilerTarget* CompilerInst::getJumpTarget() const { return NULL; } } // AsmJit namespace // [Api-Begin] #include "../core/apibegin.h" desmume/src/version.c000664 001750 001750 00000011526 12755534123 015775 0ustar00sergiosergio000000 000000 /* Copyright (C) 2009-2013 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the this software. If not, see . */ #include #include "version.h" // Helper macros to convert numerics to strings #if defined(_MSC_VER) //re: http://72.14.203.104/search?q=cache:HG-okth5NGkJ:mail.python.org/pipermail/python-checkins/2002-November/030704.html+_msc_ver+compiler+version+string&hl=en&gl=us&ct=clnk&cd=5 #define _Py_STRINGIZE(X) _Py_STRINGIZE1((X)) #define _Py_STRINGIZE1(X) _Py_STRINGIZE2 ## X #define _Py_STRINGIZE2(X) #X #define TOSTRING(X) _Py_STRINGIZE(X) // Alias _Py_STRINGIZE so that we have a common macro name #else #define STRINGIFY(x) #x #define TOSTRING(x) STRINGIFY(x) #endif //todo - everyone will want to support this eventually, i suppose #if defined(HOST_WINDOWS) || defined(DESMUME_COCOA) || defined(DESMUME_QT) #include "svnrev.h" #else #ifndef SVN_REV #define SVN_REV 0 #define SVN_REV_STR "0" #endif #endif #define DESMUME_NAME "DeSmuME" #if defined(__x86_64__) || defined(__LP64) || defined(__IA64__) || defined(_M_X64) || defined(_WIN64) #define DESMUME_PLATFORM_STRING " x64" #elif defined(__i386__) || defined(_M_IX86) || defined(_WIN32) #define DESMUME_PLATFORM_STRING " x86" #elif defined(__arm__) #define DESMUME_PLATFORM_STRING " ARM" #elif defined(__thumb__) #define DESMUME_PLATFORM_STRING " ARM-Thumb" #elif defined(__ppc64__) #define DESMUME_PLATFORM_STRING " PPC64" #elif defined(__ppc__) || defined(_M_PPC) #define DESMUME_PLATFORM_STRING " PPC" #else #define DESMUME_PLATFORM_STRING "" #endif #ifndef ENABLE_SSE2 #ifndef ENABLE_SSE #define DESMUME_CPUEXT_STRING " NOSSE" #else #define DESMUME_CPUEXT_STRING " NOSSE2" #endif #else #define DESMUME_CPUEXT_STRING "" #endif #ifdef DEVELOPER #define DESMUME_FEATURE_STRING " dev+" #else #define DESMUME_FEATURE_STRING "" #endif #ifdef DEBUG #define DESMUME_SUBVERSION_STRING " debug" #elif defined(PUBLIC_RELEASE) #define DESMUME_SUBVERSION_STRING "" #else #define DESMUME_SUBVERSION_STRING " svn" SVN_REV_STR #endif #ifdef __INTEL_COMPILER #define DESMUME_COMPILER " (Intel)" #define DESMUME_COMPILER_DETAIL " (Intel v" TOSTRING(__INTEL_COMPILER) ")" #elif defined(_MSC_VER) #define DESMUME_COMPILER " (MSVC)" #define DESMUME_COMPILER_DETAIL " (MSVC v" TOSTRING(_MSC_VER) ")" #elif defined(__clang__) #define DESMUME_COMPILER " (LLVM-Clang)" #define DESMUME_COMPILER_DETAIL " (LLVM-Clang v" TOSTRING(__clang_major__) "." TOSTRING(__clang_minor__) "." TOSTRING(__clang_patchlevel__) ")" #elif defined(__llvm__) #define DESMUME_COMPILER " (LLVM)" #define DESMUME_COMPILER_DETAIL " (LLVM)" #elif defined(__GNUC__) // Always make GCC the last check, since other compilers, such as Clang, may define __GNUC__ internally. #define DESMUME_COMPILER " (GCC)" #if defined(__GNUC_PATCHLEVEL__) #define DESMUME_COMPILER_DETAIL " (GCC v" TOSTRING(__GNUC__) "." TOSTRING(__GNUC_MINOR__) "." TOSTRING(__GNUC_PATCHLEVEL__) ")" #else #define DESMUME_COMPILER_DETAIL " (GCC v" TOSTRING(__GNUC__) "." TOSTRING(__GNUC_MINOR__) ")" #endif #else #define DESMUME_COMPILER "" #define DESMUME_COMPILER_DETAIL "" #endif #if defined(HAVE_JIT) && !defined(PUBLIC_RELEASE) #define DESMUME_JIT "-JIT" #else #define DESMUME_JIT "" #endif #ifdef PUBLIC_RELEASE const uint32_t DESMUME_SUBVERSION_NUMERIC = 0xFFFFFFFF; #else const uint32_t DESMUME_SUBVERSION_NUMERIC = SVN_REV; #endif const uint8_t DESMUME_VERSION_MAJOR = 0; const uint8_t DESMUME_VERSION_MINOR = 9; const uint8_t DESMUME_VERSION_BUILD = 11; #define DESMUME_VERSION_NUMERIC 91100 #define DESMUME_VERSION_STRING " " "0.9.11" DESMUME_SUBVERSION_STRING DESMUME_FEATURE_STRING DESMUME_PLATFORM_STRING DESMUME_JIT DESMUME_CPUEXT_STRING #define DESMUME_NAME_AND_VERSION DESMUME_NAME DESMUME_VERSION_STRING uint32_t EMU_DESMUME_VERSION_NUMERIC() { return DESMUME_VERSION_NUMERIC; } uint32_t EMU_DESMUME_SUBVERSION_NUMERIC() { return DESMUME_SUBVERSION_NUMERIC; } const char* EMU_DESMUME_VERSION_STRING() { return DESMUME_VERSION_STRING; } const char* EMU_DESMUME_SUBVERSION_STRING() { return DESMUME_SUBVERSION_STRING; } const char* EMU_DESMUME_NAME_AND_VERSION() { return DESMUME_NAME_AND_VERSION; } const char* EMU_DESMUME_COMPILER_DETAIL() { return DESMUME_COMPILER_DETAIL; } desmume/src/libretro-common/memmap/memalign.c000664 001750 001750 00000004375 12755534123 022471 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2015 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (memalign.c). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include #include #include void *memalign_alloc(size_t boundary, size_t size) { void **place = NULL; uintptr_t addr = 0; void *ptr = (void*)malloc(boundary + size + sizeof(uintptr_t)); if (!ptr) return NULL; addr = ((uintptr_t)ptr + sizeof(uintptr_t) + boundary) & ~(boundary - 1); place = (void**)addr; place[-1] = ptr; return (void*)addr; } void memalign_free(void *ptr) { void **p = NULL; if (!ptr) return; p = (void**)ptr; free(p[-1]); } void *memalign_alloc_aligned(size_t size) { #if defined(__x86_64__) || defined(__LP64) || defined(__IA64__) || defined(_M_X64) || defined(_WIN64) return memalign_alloc(64, size); #elif defined(__i386__) || defined(__i486__) || defined(__i686__) || defined(GEKKO) return memalign_alloc(32, size); #else return memalign_alloc(32, size); #endif } desmume/src/addons/slot1comp_rom.cpp000664 001750 001750 00000007471 12755534123 020722 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2015 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the this software. If not, see . */ #include "slot1comp_rom.h" #include "../NDSSystem.h" #include "../emufile.h" void Slot1Comp_Rom::start(eSlot1Operation operation, u32 addr) { this->operation = operation; this->address = addr; } u32 Slot1Comp_Rom::read() { switch(operation) { case eSlot1Operation_00_ReadHeader_Unencrypted: { u32 ret = gameInfo.readROM(address); address = (address + 4) & 0xFFF; return ret; } break; case eSlot1Operation_2x_SecureAreaLoad: { //see B7 for details //zero 15-sep-2014 - this is meaningless. newer mask is actually reasonable //address &= gameInfo.mask; //sanity check u32 secureAreaAddress = (address - 0x4000); secureAreaAddress &= 0x3FFF; //memory safe sanity test u32 ret = LE_TO_LOCAL_32(*(u32*)(gameInfo.secureArea + secureAreaAddress)); address = (address&~0xFFF) + ((address+4)&0xFFF); return ret; } case eSlot1Operation_B7_Read: { //TODO - check about non-4-byte aligned addresses //it seems that etrian odyssey 3 doesnt work unless we mask this to cart size. //but, a thought: does the internal rom address counter register wrap around? we may be making a mistake by keeping the extra precision //but there is no test case yet address &= gameInfo.mask; //feature of retail carts: //B7 "Can be used only for addresses 8000h and up, smaller addresses will be silently redirected to address `8000h+(addr AND 1FFh)`" if(address < 0x8000) address = (0x8000 + (address & 0x1FF)); //1. as a sanity measure for funny-sized roms (homebrew and perhaps truncated retail roms) we need to protect ourselves by returning 0xFF for things still out of range. //2. this isnt right, unless someone documents otherwise: //if (address > gameInfo.header.endROMoffset) // ... the cart hardware doesnt know anything about the rom header. if it has a totally bogus endROMoffset, the cart will probably work just fine. and, the +4 is missing anyway: //3. this is better: it just allows us to read 0xFF anywhere we dont have rom data. forget what the header says if(address+4 > gameInfo.romsize) { #ifdef DEBUG DEBUG_Notify.ReadBeyondEndOfCart(address,gameInfo.romsize); #endif return 0xFFFFFFFF; } //actually read from the ROM provider u32 ret = gameInfo.readROM(address); //"However, the datastream wraps to the begin of the current 4K block when address+length crosses a 4K boundary (1000h bytes)" address = (address&~0xFFF) + ((address+4)&0xFFF); return ret; } break; default: return 0; } //switch(operation) } //Slot1Comp_Rom::read() u32 Slot1Comp_Rom::getAddress() { return address & gameInfo.mask; } //Slot1Comp_Rom::getAddress() u32 Slot1Comp_Rom::incAddress() { address &= gameInfo.mask; address = (address&~0xFFF) + ((address+4)&0xFFF); return address; } void Slot1Comp_Rom::savestate(EMUFILE* os) { s32 version = 0; os->write32le(version); os->write32le((s32)operation); os->write32le(address); } void Slot1Comp_Rom::loadstate(EMUFILE* is) { s32 version = is->read32le(); operation = (eSlot1Operation)is->read32le(); address = is->read32le(); } desmume/src/utils/AsmJit/core.h000664 001750 001750 00000001522 12755534123 017567 0ustar00sergiosergio000000 000000 // [AsmJit] // Complete JIT Assembler for C++ Language. // // [License] // Zlib - See COPYING file in this package. // [Guard] #ifndef _ASMJIT_CORE_H #define _ASMJIT_CORE_H // [Dependencies - AsmJit] #include "core/build.h" #include "core/assembler.h" #include "core/assert.h" #include "core/buffer.h" #include "core/compiler.h" #include "core/compilercontext.h" #include "core/compilerfunc.h" #include "core/compileritem.h" #include "core/cpuinfo.h" #include "core/defs.h" #include "core/func.h" #include "core/intutil.h" #include "core/lock.h" #include "core/logger.h" #include "core/memorymanager.h" #include "core/memorymarker.h" #include "core/operand.h" #include "core/podvector.h" #include "core/stringbuilder.h" #include "core/stringutil.h" #include "core/virtualmemory.h" #include "core/zonememory.h" // [Guard] #endif // _ASMJIT_CORE_H desmume/src/wifi.h000664 001750 001750 00000037213 12755534123 015254 0ustar00sergiosergio000000 000000 /* Copyright (C) 2007 Tim Seidel Copyright (C) 2008-2015 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the this software. If not, see . */ #ifndef WIFI_H #define WIFI_H #include #include #include "types.h" #ifdef EXPERIMENTAL_WIFI_COMM #ifdef HOST_WINDOWS #define WIN32_LEAN_AND_MEAN #endif #include #define HAVE_REMOTE #define WPCAP #define PACKET_SIZE 65535 #define _INC_STDIO #endif #define REG_WIFI_ID 0x000 #define REG_WIFI_MODE 0x004 #define REG_WIFI_WEP 0x006 #define REG_WIFI_TXSTATCNT 0x008 #define REG_WIFI_0A 0x00A #define REG_WIFI_IF 0x010 #define REG_WIFI_IE 0x012 #define REG_WIFI_MAC0 0x018 #define REG_WIFI_MAC1 0x01A #define REG_WIFI_MAC2 0x01C #define REG_WIFI_BSS0 0x020 #define REG_WIFI_BSS1 0x022 #define REG_WIFI_BSS2 0x024 #define REG_WIFI_AID_LOW 0x028 #define REG_WIFI_AID_HIGH 0x02A #define REG_WIFI_RETRYLIMIT 0x02C // 02E - internal #define REG_WIFI_RXCNT 0x030 #define REG_WIFI_WEPCNT 0x032 // 034 - internal #define REG_WIFI_POWER_US 0x036 #define REG_WIFI_POWER_TX 0x038 #define REG_WIFI_POWERSTATE 0x03C #define REG_WIFI_POWERFORCE 0x040 #define REG_WIFI_RANDOM 0x044 #define REG_WIFI_POWER_UNK 0x048 #define REG_WIFI_RXRANGEBEGIN 0x050 #define REG_WIFI_RXRANGEEND 0x052 #define REG_WIFI_RXHWWRITECSR 0x054 #define REG_WIFI_WRITECSRLATCH 0x056 #define REG_WIFI_CIRCBUFRADR 0x058 #define REG_WIFI_RXREADCSR 0x05A #define REG_WIFI_RXBUF_COUNT 0x05C #define REG_WIFI_CIRCBUFREAD 0x060 #define REG_WIFI_CIRCBUFRD_END 0x062 #define REG_WIFI_CIRCBUFRD_SKIP 0x064 #define REG_WIFI_CIRCBUFWADR 0x068 #define REG_WIFI_TXBUFCOUNT 0x06C #define REG_WIFI_CIRCBUFWRITE 0x070 #define REG_WIFI_CIRCBUFWR_END 0x074 #define REG_WIFI_CIRCBUFWR_SKIP 0x076 // 078 - internal #define REG_WIFI_TXBUF_BEACON 0x080 #define REG_WIFI_LISTENCOUNT 0x088 #define REG_WIFI_BEACONPERIOD 0x08C #define REG_WIFI_LISTENINT 0x08E #define REG_WIFI_TXBUF_CMD 0x090 #define REG_WIFI_TXBUF_REPLY1 0x094 #define REG_WIFI_TXBUF_REPLY2 0x098 // 09C - internal #define REG_WIFI_TXBUF_LOC1 0x0A0 #define REG_WIFI_TXBUF_LOC2 0x0A4 #define REG_WIFI_TXBUF_LOC3 0x0A8 #define REG_WIFI_TXREQ_RESET 0x0AC #define REG_WIFI_TXREQ_SET 0x0AE #define REG_WIFI_TXREQ_READ 0x0B0 #define REG_WIFI_TXRESET 0x0B4 #define REG_WIFI_TXBUSY 0x0B6 #define REG_WIFI_TXSTAT 0x0B8 // 0BA - internal #define REG_WIFI_PREAMBLE 0x0BC // 0C0 - ? // 0C4 - ? // 0C8 - internal #define REG_WIFI_RXFILTER 0x0D0 // 0D4 - config // 0D8 - config // 0DA - config #define REG_WIFI_RXFILTER2 0x0E0 #define REG_WIFI_USCOUNTERCNT 0x0E8 #define REG_WIFI_USCOMPARECNT 0x0EA // 0EC - config #define REG_WIFI_EXTRACOUNTCNT 0x0EE #define REG_WIFI_USCOMPARE0 0x0F0 #define REG_WIFI_USCOMPARE1 0x0F2 #define REG_WIFI_USCOMPARE2 0x0F4 #define REG_WIFI_USCOMPARE3 0x0F6 #define REG_WIFI_USCOUNTER0 0x0F8 #define REG_WIFI_USCOUNTER1 0x0FA #define REG_WIFI_USCOUNTER2 0x0FC #define REG_WIFI_USCOUNTER3 0x0FE // 100 - internal // 102 - internal // 104 - internal // 106 - internal #define REG_WIFI_CONTENTFREE 0x10C #define REG_WIFI_PREBEACONCOUNT 0x110 #define REG_WIFI_EXTRACOUNT 0x118 #define REG_WIFI_BEACONCOUNT1 0x11C // 120 to 132 - config/internal ports #define REG_WIFI_BEACONCOUNT2 0x134 // 140 to 154 - config ports #define REG_WIFI_BBCNT 0x158 #define REG_WIFI_BBWRITE 0x15A #define REG_WIFI_BBREAD 0x15C #define REG_WIFI_BBBUSY 0x15E #define REG_WIFI_BBMODE 0x160 #define REG_WIFI_BBPOWER 0x168 // 16A to 178 - internal #define REG_WIFI_RFDATA2 0x17C #define REG_WIFI_RFDATA1 0x17E #define REG_WIFI_RFBUSY 0x180 #define REG_WIFI_RFCNT 0x184 // 190 - internal // 194 - ? // 198 - internal #define REG_WIFI_RFPINS 0x19C // 1A0 - internal // 1A2 - internal #define REG_WIFI_MAYBE_RATE 0x1A4 #define REG_WIFI_RXSTAT_INC_IF 0x1A8 #define REG_WIFI_RXSTAT_INC_IE 0x1AA #define REG_WIFI_RXSTAT_OVF_IF 0x1AC #define REG_WIFI_RXSTAT_OVF_IE 0x1AE #define REG_WIFI_TXERR_COUNT 0x1C0 #define REG_WIFI_RX_COUNT 0x1C4 // 1D0 to 1DE - related to multiplayer. argh. #define REG_WIFI_RFSTATUS 0x214 #define REG_WIFI_IF_SET 0x21C #define REG_WIFI_TXSEQNO 0x210 #define REG_WIFI_RXTXADDR 0x268 #define REG_WIFI_POWERACK 0x2D0 #define WIFI_IOREG(reg) wifiMac.IOPorts[(reg) >> 1] /* WIFI misc constants */ #define WIFI_CHIPID 0x1440 /* emulates "old" wifi chip, new is 0xC340 */ /* Referenced as RF_ in dswifi: rffilter_t */ /* based on the documentation for the RF2958 chip of RF Micro Devices */ /* using the register names as in docs ( http://www.rfmd.com/pdfs/2958.pdf )*/ /* even tho every register only has 18 bits we are using u32 */ typedef struct rffilter_t { union CFG1 { struct { /* 0*/ unsigned IF_VGA_REG_EN:1; /* 1*/ unsigned IF_VCO_REG_EN:1; /* 2*/ unsigned RF_VCO_REG_EN:1; /* 3*/ unsigned HYBERNATE:1; /* 4*/ unsigned :10; /*14*/ unsigned REF_SEL:2; /*16*/ unsigned :2; } bits; u32 val; } CFG1; union IFPLL1 { struct { /* 0*/ unsigned DAC:4; /* 4*/ unsigned :5; /* 9*/ unsigned P1:1; /*10*/ unsigned LD_EN1:1; /*11*/ unsigned AUTOCAL_EN1:1; /*12*/ unsigned PDP1:1; /*13*/ unsigned CPL1:1; /*14*/ unsigned LPF1:1; /*15*/ unsigned VTC_EN1:1; /*16*/ unsigned KV_EN1:1; /*17*/ unsigned PLL_EN1:1; } bits; u32 val; } IFPLL1; union IFPLL2 { struct { /* 0*/ unsigned IF_N:16; /*16*/ unsigned :2; } bits; u32 val; } IFPLL2; union IFPLL3 { struct { /* 0*/ unsigned KV_DEF1:4; /* 4*/ unsigned CT_DEF1:4; /* 8*/ unsigned DN1:9; /*17*/ unsigned :1; } bits; u32 val; } IFPLL3; union RFPLL1 { struct { /* 0*/ unsigned DAC:4; /* 4*/ unsigned :5; /* 9*/ unsigned P:1; /*10*/ unsigned LD_EN:1; /*11*/ unsigned AUTOCAL_EN:1; /*12*/ unsigned PDP:1; /*13*/ unsigned CPL:1; /*14*/ unsigned LPF:1; /*15*/ unsigned VTC_EN:1; /*16*/ unsigned KV_EN:1; /*17*/ unsigned PLL_EN:1; } bits; u32 val; } RFPLL1; union RFPLL2 { struct { /* 0*/ unsigned NUM2:6; /* 6*/ unsigned N2:12; } bits; u32 val; } RFPLL2; union RFPLL3 { struct { /* 0*/ unsigned NUM2:18; } bits; u32 val; } RFPLL3; union RFPLL4 { struct { /* 0*/ unsigned KV_DEF:4; /* 4*/ unsigned CT_DEF:4; /* 8*/ unsigned DN:9; /*17*/ unsigned :1; } bits; u32 val; } RFPLL4; union CAL1 { struct { /* 0*/ unsigned LD_WINDOW:3; /* 3*/ unsigned M_CT_VALUE:5; /* 8*/ unsigned TLOCK:5; /*13*/ unsigned TVCO:5; } bits; u32 val; } CAL1; union TXRX1 { struct { /* 0*/ unsigned TXBYPASS:1; /* 1*/ unsigned INTBIASEN:1; /* 2*/ unsigned TXENMODE:1; /* 3*/ unsigned TXDIFFMODE:1; /* 4*/ unsigned TXLPFBW:3; /* 7*/ unsigned RXLPFBW:3; /*10*/ unsigned TXVGC:5; /*15*/ unsigned PCONTROL:2; /*17*/ unsigned RXDCFBBYPS:1; } bits; u32 val; } TXRX1; union PCNT1 { struct { /* 0*/ unsigned TX_DELAY:3; /* 3*/ unsigned PC_OFFSET:6; /* 9*/ unsigned P_DESIRED:6; /*15*/ unsigned MID_BIAS:3; } bits; u32 val; } PCNT1; union PCNT2 { struct { /* 0*/ unsigned MIN_POWER:6; /* 6*/ unsigned MID_POWER:6; /*12*/ unsigned MAX_POWER:6; } bits; u32 val; } PCNT2; union VCOT1 { struct { /* 0*/ unsigned :16; /*16*/ unsigned AUX1:1; /*17*/ unsigned AUX:1; } bits; u32 val; } VCOT1; } rffilter_t; /* baseband chip refered as BB_, dataformat is unknown yet */ /* it has at least 105 bytes of functional data */ typedef struct { u8 data[105]; } bb_t; /* communication interface between RF,BB and the mac */ typedef union { struct { /* 0*/ unsigned wordsize:5; /* 5*/ unsigned :2; /* 7*/ unsigned readOperation:1; /* 8*/ unsigned :8; } bits; u16 val; } rfIOCnt_t; typedef union { struct { /* 0*/ unsigned busy:1; /* 1*/ unsigned :15; } bits; u16 val; } rfIOStat_t; typedef union { struct { /* 0*/ unsigned content:18; /*18*/ unsigned address:5; /*23*/ unsigned :9; } bits; struct { /* 0*/ unsigned low:16; /*16*/ unsigned high:16; } val16; u16 array16[2]; u32 val; } rfIOData_t; typedef union { struct { /* 0*/ unsigned address:7; /* 7*/ unsigned :5; /*12*/ unsigned mode:2; /*14*/ unsigned enable:1; /*15*/ unsigned :1; } bits; u16 val; } bbIOCnt_t; #define WIFI_IRQ_RXEND 0 #define WIFI_IRQ_TXEND 1 #define WIFI_IRQ_RXINC 2 #define WIFI_IRQ_TXERROR 3 #define WIFI_IRQ_RXOVF 4 #define WIFI_IRQ_TXERROVF 5 #define WIFI_IRQ_RXSTART 6 #define WIFI_IRQ_TXSTART 7 #define WIFI_IRQ_TXCOUNTEXP 8 #define WIFI_IRQ_RXCOUNTEXP 9 #define WIFI_IRQ_RFWAKEUP 11 #define WIFI_IRQ_UNK 12 #define WIFI_IRQ_TIMEPOSTBEACON 13 #define WIFI_IRQ_TIMEBEACON 14 #define WIFI_IRQ_TIMEPREBEACON 15 struct Wifi_TXSlot { u16 RegVal; u16 CurAddr; int RemPreamble; // preamble time in µs int RemHWords; u32 TimeMask; // 3 = 2mbps, 7 = 1mbps bool NotStarted; }; #define WIFI_TXSLOT_LOC1 0 #define WIFI_TXSLOT_MPCMD 1 #define WIFI_TXSLOT_LOC2 2 #define WIFI_TXSLOT_LOC3 3 #define WIFI_TXSLOT_BEACON 4 #define WIFI_TXSLOT_MPREPLY 5 #define WIFI_TXSLOT_NUM 6 struct Wifi_RXPacket { u8* Data; int CurOffset; int RemHWords; bool NotStarted; }; typedef std::queue Wifi_RXPacketQueue; enum EAPStatus { APStatus_Disconnected = 0, APStatus_Authenticated, APStatus_Associated }; /* wifimac_t: the buildin mac (arm7 addressrange: 0x04800000-0x04FFFFFF )*/ /* http://www.akkit.org/info/dswifi.htm#WifiIOMap */ typedef struct { /* power */ BOOL powerOn; BOOL powerOnPending; /* status */ u16 rfStatus; u16 rfPins; /* wifi interrupt handling */ u16 IE; u16 IF; /* modes */ u16 macMode; u16 wepMode; BOOL WEP_enable; /* sending */ u16 TXStatCnt; u16 TXPower; u16 TXCnt; u16 TXStat; u16 TXSeqNo; Wifi_TXSlot TXSlots[WIFI_TXSLOT_NUM]; int TXCurSlot; u16 TXBusy; /* receiving */ u16 RXCnt; u16 RXCheckCounter; u8 RXNum; Wifi_RXPacketQueue RXPacketQueue; u16 RXStatIncIF, RXStatIncIE; u16 RXStatOvfIF, RXStatOvfIE; u8 RXStat[16]; u16 RXTXAddr; /* addressing/handshaking */ union { //TODO - is this endian safe? don't think so u16 words[3]; u8 bytes[6]; } mac; union { u16 words[3]; u8 bytes[6]; } bss; u16 aid; u16 pid; /* player ID or aid_low */ u16 retryLimit; /* timing */ u64 GlobalUsecTimer; BOOL crystalEnabled; u64 usec; BOOL usecEnable; u64 ucmp; BOOL ucmpEnable; u32 eCount; BOOL eCountEnable; u16 BeaconInterval; u16 BeaconCount1; u16 BeaconCount2; u16 ListenInterval; u16 ListenCount; /* subchips */ rffilter_t RF; bb_t BB; /* subchip communications */ rfIOCnt_t rfIOCnt; rfIOStat_t rfIOStatus; rfIOData_t rfIOData; bbIOCnt_t bbIOCnt; /* buffers */ u16 RAM[0x1000]; u16 RXRangeBegin; u16 RXRangeEnd; u16 RXWriteCursor; u16 RXReadCursor; u16 RXUnits; u16 RXBufCount; u16 CircBufReadAddress; u16 CircBufWriteAddress; u16 CircBufRdEnd; u16 CircBufRdSkip; u16 CircBufWrEnd; u16 CircBufWrSkip; /* I/O ports */ u16 IOPorts[0x800]; /* others */ u16 randomSeed; } wifimac_t; typedef struct { EAPStatus status; u16 seqNum; } SoftAP_t; // desmume host communication #ifdef EXPERIMENTAL_WIFI_COMM typedef struct pcap pcap_t; extern pcap_t *wifi_bridge; #endif extern wifimac_t wifiMac; extern SoftAP_t SoftAP; bool WIFI_Init(); void WIFI_DeInit(); void WIFI_Reset(); /* subchip communication IO functions */ void WIFI_setRF_CNT(u16 val); void WIFI_setRF_DATA(u16 val, u8 part); u16 WIFI_getRF_DATA(u8 part); u16 WIFI_getRF_STATUS(); void WIFI_setBB_CNT(u16 val); u8 WIFI_getBB_DATA(); void WIFI_setBB_DATA(u8 val); /* wifimac io */ void WIFI_write16(u32 address, u16 val); u16 WIFI_read16(u32 address); /* wifimac timing */ void WIFI_usTrigger(); /* DS WFC profile data documented here : */ /* http://dsdev.bigredpimp.com/2006/07/31/aoss-wfc-profile-data/ */ /* Note : we use bytes to avoid endianness issues */ typedef struct _FW_WFCProfile { char SSID[32]; char SSID_WEP64[32]; char WEPKEY_PART1[16]; char WEPKEY_PART2[16]; char WEPKEY_PART3[16]; char WEPKEY_PART4[16]; u8 IP_ADDRESS[4]; u8 GATEWAY[4]; u8 PRIM_DNS[4]; u8 SEC_DNS[4]; u8 SUBNET_MASK; u8 WEP64_KEY_AOSS[20]; u8 UNK1; u8 WEP_MODE; u8 STATUS; u8 UNK2[7]; u8 UNK3; u8 UNK4[14]; u8 CRC16[2]; } FW_WFCProfile; class WifiHandler { public: #ifdef EXPERIMENTAL_WIFI_COMM virtual bool WIFI_SocketsAvailable() { return true; } virtual bool WIFI_PCapAvailable() { return false; } virtual void WIFI_GetUniqueMAC(u8* mac) {} virtual bool WIFI_WFCWarning() { return false; } virtual int PCAP_findalldevs(pcap_if_t** alldevs, char* errbuf) { return -1; } virtual void PCAP_freealldevs(pcap_if_t* alldevs) {} virtual pcap_t* PCAP_open(const char* source, int snaplen, int flags, int readtimeout, char* errbuf) { return NULL; } virtual void PCAP_close(pcap_t* dev) {} virtual int PCAP_setnonblock(pcap_t* dev, int nonblock, char* errbuf) { return -1; } virtual int PCAP_sendpacket(pcap_t* dev, const u_char* data, int len) { return -1; } virtual int PCAP_dispatch(pcap_t* dev, int num, pcap_handler callback, u_char* userdata) { return -1; } #endif }; #ifndef HOST_WINDOWS class UnixWifiHandler : public WifiHandler { #ifdef EXPERIMENTAL_WIFI_COMM virtual bool WIFI_SocketsAvailable() { return true; } virtual bool WIFI_PCapAvailable() { return true; } virtual bool WIFI_WFCWarning() { return false; } virtual int PCAP_findalldevs(pcap_if_t** alldevs, char* errbuf) { return pcap_findalldevs(alldevs, errbuf); } virtual void PCAP_freealldevs(pcap_if_t* alldevs) { pcap_freealldevs(alldevs); } virtual pcap_t* PCAP_open(const char* source, int snaplen, int flags, int readtimeout, char* errbuf) { return pcap_open_live(source, snaplen, flags, readtimeout, errbuf); } virtual void PCAP_close(pcap_t* dev) { pcap_close(dev); } virtual int PCAP_setnonblock(pcap_t* dev, int nonblock, char* errbuf) { return pcap_setnonblock(dev, nonblock, errbuf); } virtual int PCAP_sendpacket(pcap_t* dev, const u_char* data, int len) { return pcap_sendpacket(dev, data, len); } virtual int PCAP_dispatch(pcap_t* dev, int num, pcap_handler callback, u_char* userdata) { return pcap_dispatch(dev, num, callback, userdata); } #endif }; #endif /* wifi data to be stored in firmware, when no firmware image was loaded */ extern u8 FW_Mac[6]; extern const u8 FW_WIFIInit[32]; extern const u8 FW_BBInit[105]; extern const u8 FW_RFInit[36]; extern const u8 FW_RFChannel[6*14]; extern const u8 FW_BBChannel[14]; extern FW_WFCProfile FW_WFCProfile1; extern FW_WFCProfile FW_WFCProfile2; extern FW_WFCProfile FW_WFCProfile3; extern WifiHandler *CurrentWifiHandler; #endif desmume/src/firmware.h000664 001750 001750 00000007555 12755534123 016140 0ustar00sergiosergio000000 000000 /* Copyright (C) 2009-2015 DeSmuME Team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the this software. If not, see . */ #ifndef _FIRMWARE_H_ #define _FIRMWARE_H_ #include #include #include "types.h" #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 */ // the count of bytes (user settings) copied from the firmware into memory (for easy access) during the firmware boot process #define NDS_FW_USER_SETTINGS_MEM_BYTE_COUNT 0x70 //extension of the firmware user settings file #define FW_CONFIG_FILE_EXT "dfc" struct NDS_fw_config_data; class CFIRMWARE { private: u8 *tmp_data9; u8 *tmp_data7; u32 size9, size7; u32 userDataAddr; u16 getBootCodeCRC16(); u32 decrypt(const u8 *in, u8* &out); u32 decompress(const u8 *in, u8* &out); bool successLoad; public: CFIRMWARE(): size9(0), size7(0), ARM9bootAddr(0), ARM7bootAddr(0), patched(0), userDataAddr(0x3FE00), successLoad(false) {}; bool load(); bool unpack(); bool loadSettings(); bool saveSettings(); static std::string GetExternalFilePath(); u32 getID() { return header.fw_identifier; } bool loaded() { return successLoad; } void *getTouchCalibrate(); struct HEADER { u16 part3_rom_gui9_addr; // 000h u16 part4_rom_wifi7_addr; // 002h u16 part34_gui_wifi_crc16; // 004h u16 part12_boot_crc16; // 006h u32 fw_identifier; // 008h u16 part1_rom_boot9_addr; // 00Ch u16 part1_ram_boot9_addr; // 00Eh u16 part2_rom_boot7_addr; // 010h u16 part2_ram_boot7_addr; // 012h u16 shift_amounts; // 014h u16 part5_data_gfx_addr; // 016h u8 fw_timestamp[5]; // 018h u8 console_type; // 01Dh u16 unused1; // 01Eh u16 user_settings_offset; // 020h u16 unknown1; // 022h u16 unknown2; // 024h u16 part5_crc16; // 026h u16 unused2; // 028h - FFh filled } header; u32 ARM9bootAddr; u32 ARM7bootAddr; bool patched; }; int copy_firmware_user_data( u8 *dest_buffer, const u8 *fw_data); int NDS_CreateDummyFirmware(NDS_fw_config_data *user_settings); void NDS_FillDefaultFirmwareConfigData(NDS_fw_config_data *fw_config); void NDS_PatchFirmwareMAC(); struct fw_memory_chip { 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; // needs only for firmware bool isFirmware; char userfile[PATH_MAX_LENGTH]; }; void fw_reset_com(fw_memory_chip *mc); u8 fw_transfer(fw_memory_chip *mc, u8 data); void mc_init(fw_memory_chip *mc, int type); /* reset and init values for memory struct */ u8 *mc_alloc(fw_memory_chip *mc, u32 size); /* alloc mc memory */ void mc_realloc(fw_memory_chip *mc, int type, u32 size); /* realloc mc memory */ void mc_load_file(fw_memory_chip *mc, const char* filename); /* load save file and setup fp */ void mc_free(fw_memory_chip *mc); /* delete mc memory */ #endif desmume/src/libretro-common/include/lists/file_list.h000664 001750 001750 00000007522 12755534123 024161 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2016 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (file_list.h). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef __LIBRETRO_SDK_FILE_LIST_H__ #define __LIBRETRO_SDK_FILE_LIST_H__ #include RETRO_BEGIN_DECLS #include #include #include struct item_file { char *path; char *label; char *alt; unsigned type; size_t directory_ptr; size_t entry_idx; void *userdata; void *actiondata; }; typedef struct file_list { struct item_file *list; size_t capacity; size_t size; } file_list_t; void *file_list_get_userdata_at_offset(const file_list_t *list, size_t index); void *file_list_get_actiondata_at_offset(const file_list_t *list, size_t index); void file_list_free(file_list_t *list); bool file_list_append(file_list_t *userdata, const char *path, const char *label, unsigned type, size_t current_directory_ptr, size_t entry_index); bool file_list_prepend(file_list_t *list, const char *path, const char *label, unsigned type, size_t directory_ptr, size_t entry_idx); void file_list_pop(file_list_t *list, size_t *directory_ptr); void file_list_clear(file_list_t *list); void file_list_copy(const file_list_t *src, file_list_t *dst); void file_list_get_last(const file_list_t *list, const char **path, const char **label, unsigned *type, size_t *entry_idx); void *file_list_get_last_actiondata(const file_list_t *list); size_t file_list_get_size(const file_list_t *list); size_t file_list_get_directory_ptr(const file_list_t *list); void file_list_get_at_offset(const file_list_t *list, size_t index, const char **path, const char **label, unsigned *type, size_t *entry_idx); void file_list_free_userdata(const file_list_t *list, size_t index); void file_list_free_actiondata(const file_list_t *list, size_t idx); void file_list_set_label_at_offset(file_list_t *list, size_t index, const char *label); void file_list_get_label_at_offset(const file_list_t *list, size_t index, const char **label); void file_list_set_alt_at_offset(file_list_t *list, size_t index, const char *alt); void file_list_set_userdata(const file_list_t *list, size_t idx, void *ptr); void file_list_set_actiondata(const file_list_t *list, size_t idx, void *ptr); void file_list_get_alt_at_offset(const file_list_t *list, size_t index, const char **alt); void file_list_sort_on_alt(file_list_t *list); void file_list_sort_on_type(file_list_t *list); bool file_list_search(const file_list_t *list, const char *needle, size_t *index); RETRO_END_DECLS #endif desmume/src/SPU.h000664 001750 001750 00000012562 12755534123 014765 0ustar00sergiosergio000000 000000 /* Copyright 2006 Theo Berkau Copyright (C) 2006-2015 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the this software. If not, see . */ #ifndef SPU_H #define SPU_H #include #include #include #include #include "types.h" #include "matrix.h" class EMUFILE; #define SNDCORE_DEFAULT -1 #define SNDCORE_DUMMY 0 #define CHANSTAT_STOPPED 0 #define CHANSTAT_PLAY 1 //who made these static? theyre used in multiple places. FORCEINLINE u32 sputrunc(float f) { return u32floor(f); } FORCEINLINE u32 sputrunc(double d) { return u32floor(d); } FORCEINLINE s32 spumuldiv7(s32 val, u8 multiplier) { assert(multiplier <= 127); return (multiplier == 127) ? val : ((val * multiplier) >> 7); } extern int SPU_currentCoreNum; struct channel_struct { channel_struct() : num(0), vol(0), volumeDiv(0), hold(0), pan(0), waveduty(0), repeat(0), format(0), keyon(0), status(0), addr(0), timer(0), loopstart(0), length(0), totlength(0), double_totlength_shifted(0.0), sampcnt(0.0), sampinc(0.0), lastsampcnt(0), pcm16b(0), pcm16b_last(0), loop_pcm16b(0), index(0), loop_index(0), x(0), psgnoise_last(0) {} u32 num; u8 vol; u8 volumeDiv; u8 hold; u8 pan; u8 waveduty; u8 repeat; u8 format; u8 keyon; u8 status; u32 addr; u16 timer; u16 loopstart; u32 length; u32 totlength; double double_totlength_shifted; double sampcnt; double sampinc; // ADPCM specific u32 lastsampcnt; s16 pcm16b, pcm16b_last; s16 loop_pcm16b; int index; int loop_index; u16 x; s16 psgnoise_last; }; class SPUFifo { public: SPUFifo(); void enqueue(s16 val); s16 dequeue(); s16 buffer[16]; s32 head,tail,size; void save(EMUFILE* fp); bool load(EMUFILE* fp); void reset(); }; class SPU_struct { public: SPU_struct(int buffersize); u32 bufpos; u32 buflength; s32 *sndbuf; s32 lastdata; //the last sample that a channel generated s16 *outbuf; u32 outbufptr; u32 bufsize; channel_struct channels[16]; //registers struct REGS { REGS() : mastervol(0) , ctl_left(0) , ctl_right(0) , ctl_ch1bypass(0) , ctl_ch3bypass(0) , masteren(0) , soundbias(0) {} u8 mastervol; u8 ctl_left, ctl_right; u8 ctl_ch1bypass, ctl_ch3bypass; u8 masteren; u16 soundbias; enum LeftOutputMode { LOM_LEFT_MIXER=0, LOM_CH1=1, LOM_CH3=2, LOM_CH1_PLUS_CH3=3 }; enum RightOutputMode { ROM_RIGHT_MIXER=0, ROM_CH1=1, ROM_CH3=2, ROM_CH1_PLUS_CH3=3 }; struct CAP { CAP() : add(0), source(0), oneshot(0), bits8(0), active(0), dad(0), len(0) {} u8 add, source, oneshot, bits8, active; u32 dad; u16 len; struct Runtime { Runtime() : running(0), curdad(0), maxdad(0) {} u8 running; u32 curdad; u32 maxdad; double sampcnt; SPUFifo fifo; } runtime; } cap[2]; } regs; void reset(); ~SPU_struct(); void KeyOff(int channel); void KeyOn(int channel); void KeyProbe(int channel); void ProbeCapture(int which); void WriteByte(u32 addr, u8 val); void WriteWord(u32 addr, u16 val); void WriteLong(u32 addr, u32 val); u8 ReadByte(u32 addr); u16 ReadWord(u32 addr); u32 ReadLong(u32 addr); bool isSPU(u32 addr) { return ((addr >= 0x04000400) && (addr < 0x04000520)); } //kills all channels but leaves SPU otherwise running normally void ShutUp(); }; extern SPU_struct *SPU_core; extern int spu_core_samples; int SPU_ChangeSoundCore(int coreid, int buffersize); void SPU_ReInit(bool fakeBoot = false); int SPU_Init(int coreid, int buffersize); void SPU_Pause(int pause); void SPU_SetVolume(int volume); void SPU_SetSynchMode(int method); void SPU_ClearOutputBuffer(void); void SPU_Reset(void); void SPU_DeInit(void); void SPU_KeyOn(int channel); static FORCEINLINE void SPU_WriteByte(u32 addr, u8 val) { addr &= 0xFFF; SPU_core->WriteByte(addr,val); } static FORCEINLINE void SPU_WriteWord(u32 addr, u16 val) { addr &= 0xFFF; SPU_core->WriteWord(addr,val); } static FORCEINLINE void SPU_WriteLong(u32 addr, u32 val) { addr &= 0xFFF; SPU_core->WriteLong(addr,val); } static FORCEINLINE u8 SPU_ReadByte(u32 addr) { return SPU_core->ReadByte(addr & 0x0FFF); } static FORCEINLINE u16 SPU_ReadWord(u32 addr) { return SPU_core->ReadWord(addr & 0x0FFF); } static FORCEINLINE u32 SPU_ReadLong(u32 addr) { return SPU_core->ReadLong(addr & 0x0FFF); } void SPU_Emulate_core(void); void SPU_Emulate_user(bool mix = true); void spu_savestate(EMUFILE* os); bool spu_loadstate(EMUFILE* is, int size); // we should make this configurable eventually // but at least defining it somewhere is probably a step in the right direction #define DESMUME_SAMPLE_RATE 44100 //#define DESMUME_SAMPLE_RATE 48000 #endif desmume/src/libretro/libretro.cpp000664 001750 001750 00000105715 12755534123 020320 0ustar00sergiosergio000000 000000 #include #include #include "cheatSystem.h" #include "MMU.h" #include "NDSSystem.h" #include "debug.h" #include "render3D.h" #include "rasterize.h" #include "saves.h" #include "firmware.h" #include "GPU.h" #include "SPU.h" #include "emufile.h" #include "common.h" #define LAYOUTS_MAX 7 retro_log_printf_t log_cb = NULL; static retro_video_refresh_t video_cb = NULL; static retro_input_poll_t poll_cb = NULL; static retro_input_state_t input_cb = NULL; retro_audio_sample_batch_t audio_batch_cb = NULL; retro_environment_t environ_cb = NULL; volatile int execute = 0; static int delay_timer = 0; static bool quick_switch_enable = false; static bool mouse_enable = false; static int pointer_device = 0; static int analog_stick_deadzone; static int analog_stick_acceleration = 2048; static int analog_stick_acceleration_modifier = 0; static int microphone_force_enable = 0; static int nds_screen_gap = 0; static uint16_t *screen_buf; extern GPUSubsystem *GPU; int currFrameCounter; unsigned GPU_LR_FRAMEBUFFER_NATIVE_WIDTH = 256; unsigned GPU_LR_FRAMEBUFFER_NATIVE_HEIGHT = 192; unsigned scale = 1; #define NDS_MAX_SCREEN_GAP 100 int current_layout = LAYOUT_TOP_BOTTOM; struct LayoutData { uint16_t *dst; uint16_t *dst2; uint32_t touch_x; uint32_t touch_y; uint32_t width; uint32_t height; uint32_t pitch; bool draw_screen1; bool draw_screen2; }; static bool touchEnabled; static unsigned host_get_language(void) { static const u8 langconv[]={ // libretro to NDS NDS_FW_LANG_ENG, NDS_FW_LANG_JAP, NDS_FW_LANG_FRE, NDS_FW_LANG_SPA, NDS_FW_LANG_GER, NDS_FW_LANG_ITA }; unsigned lang = RETRO_LANGUAGE_ENGLISH; environ_cb(RETRO_ENVIRONMENT_GET_LANGUAGE, &lang); if (lang >= 6) lang = RETRO_LANGUAGE_ENGLISH; return langconv[lang]; } static inline int32_t Saturate(int32_t min, int32_t max, int32_t aValue) { return std::max(min, std::min(max, aValue)); } static int32_t TouchX; static int32_t TouchY; static const uint32_t FramesWithPointerBase = 60 * 10; static int32_t FramesWithPointer; static void DrawPointerLine(uint16_t* aOut, uint32_t aPitchInPix) { for(int i = 0; i < (5 * scale) ; i ++) aOut[aPitchInPix * i] = 0xFFFF; } static void DrawPointer(uint16_t* aOut, uint32_t aPitchInPix) { if(FramesWithPointer-- < 0) return; TouchX = Saturate(0, (GPU_LR_FRAMEBUFFER_NATIVE_WIDTH-1), TouchX); TouchY = Saturate(0, (GPU_LR_FRAMEBUFFER_NATIVE_HEIGHT-1), TouchY); if(TouchX > (5 * scale)) DrawPointerLine(&aOut[TouchY * aPitchInPix + TouchX - (5 * scale) ], 1); if(TouchX < (GPU_LR_FRAMEBUFFER_NATIVE_WIDTH - (5 * scale) )) DrawPointerLine(&aOut[TouchY * aPitchInPix + TouchX + 1], 1); if(TouchY > (5 * scale)) DrawPointerLine(&aOut[(TouchY - (5 * scale) ) * aPitchInPix + TouchX], aPitchInPix); if(TouchY < (GPU_LR_FRAMEBUFFER_NATIVE_HEIGHT-(5 * scale) )) DrawPointerLine(&aOut[(TouchY + 1) * aPitchInPix + TouchX], aPitchInPix); } static retro_pixel_format colorMode; static uint32_t frameSkip; static uint32_t frameIndex; #define CONVERT_COLOR(color) (((color & 0x001f) << 11) | ((color & 0x03e0) << 1) | ((color & 0x0200) >> 4) | ((color & 0x7c00) >> 10)) static void SwapScreen(uint16_t *dst, const uint16_t *src, uint32_t pitch) { unsigned i, j; uint32_t skip = pitch - GPU_LR_FRAMEBUFFER_NATIVE_WIDTH; for(i = 0; i < GPU_LR_FRAMEBUFFER_NATIVE_HEIGHT; i ++) { for(j = 0; j < GPU_LR_FRAMEBUFFER_NATIVE_WIDTH; j ++) { uint16_t col = *src++; *dst++ = CONVERT_COLOR(col); } dst += skip; } } namespace { uint32_t firmwareLanguage; } void retro_get_system_info(struct retro_system_info *info) { info->library_name = "DeSmuME"; info->library_version = "SVN"; info->valid_extensions = "nds|bin"; info->need_fullpath = true; info->block_extract = false; } static void get_layout_params(unsigned id, uint16_t *src, LayoutData *layout) { if (!layout) return; switch (id) { case LAYOUT_TOP_BOTTOM: if (src) { layout->dst = src; layout->dst2 = (uint16_t*)(src + GPU_LR_FRAMEBUFFER_NATIVE_WIDTH * (GPU_LR_FRAMEBUFFER_NATIVE_HEIGHT + nds_screen_gap)); } layout->width = GPU_LR_FRAMEBUFFER_NATIVE_WIDTH; layout->height = GPU_LR_FRAMEBUFFER_NATIVE_HEIGHT * 2 + nds_screen_gap; layout->pitch = GPU_LR_FRAMEBUFFER_NATIVE_WIDTH; layout->touch_x= 0; layout->touch_y= GPU_LR_FRAMEBUFFER_NATIVE_HEIGHT; layout->draw_screen1 = true; layout->draw_screen2 = true; break; case LAYOUT_BOTTOM_TOP: if (src) { layout->dst = (uint16_t*)(src + GPU_LR_FRAMEBUFFER_NATIVE_WIDTH * (GPU_LR_FRAMEBUFFER_NATIVE_HEIGHT + nds_screen_gap)); layout->dst2 = src; } layout->width = GPU_LR_FRAMEBUFFER_NATIVE_WIDTH; layout->height = GPU_LR_FRAMEBUFFER_NATIVE_HEIGHT * 2 + nds_screen_gap; layout->pitch = GPU_LR_FRAMEBUFFER_NATIVE_WIDTH; layout->touch_x= 0; layout->touch_y= GPU_LR_FRAMEBUFFER_NATIVE_WIDTH; layout->draw_screen1 = true; layout->draw_screen2 = true; break; case LAYOUT_LEFT_RIGHT: if (src) { layout->dst = src; layout->dst2 = (uint16_t*)(src + GPU_LR_FRAMEBUFFER_NATIVE_WIDTH + nds_screen_gap); } layout->width = GPU_LR_FRAMEBUFFER_NATIVE_WIDTH * 2 + nds_screen_gap; layout->height = GPU_LR_FRAMEBUFFER_NATIVE_HEIGHT; layout->pitch = GPU_LR_FRAMEBUFFER_NATIVE_WIDTH * 2 + nds_screen_gap; layout->touch_x= GPU_LR_FRAMEBUFFER_NATIVE_WIDTH; layout->touch_y= 0; layout->draw_screen1 = true; layout->draw_screen2 = true; break; case LAYOUT_RIGHT_LEFT: if (src) { layout->dst = (uint16_t*)(src + GPU_LR_FRAMEBUFFER_NATIVE_WIDTH + nds_screen_gap); layout->dst2 = src; } layout->width = GPU_LR_FRAMEBUFFER_NATIVE_WIDTH * 2 + nds_screen_gap; layout->height = GPU_LR_FRAMEBUFFER_NATIVE_HEIGHT; layout->pitch = GPU_LR_FRAMEBUFFER_NATIVE_WIDTH * 2 + nds_screen_gap; layout->touch_x= 0; layout->touch_y= 0; layout->draw_screen1 = true; layout->draw_screen2 = true; break; case LAYOUT_TOP_ONLY: if (src) { layout->dst = src; layout->dst2 = (uint16_t*)(src + GPU_LR_FRAMEBUFFER_NATIVE_WIDTH * GPU_LR_FRAMEBUFFER_NATIVE_HEIGHT); } layout->width = GPU_LR_FRAMEBUFFER_NATIVE_WIDTH; layout->height = GPU_LR_FRAMEBUFFER_NATIVE_HEIGHT; layout->pitch = GPU_LR_FRAMEBUFFER_NATIVE_WIDTH; layout->touch_x= 0; layout->touch_y= GPU_LR_FRAMEBUFFER_NATIVE_HEIGHT; layout->draw_screen1 = true; break; case LAYOUT_BOTTOM_ONLY: if (src) { layout->dst = (uint16_t*)(src + GPU_LR_FRAMEBUFFER_NATIVE_WIDTH * GPU_LR_FRAMEBUFFER_NATIVE_HEIGHT); layout->dst2 = src; } layout->width = GPU_LR_FRAMEBUFFER_NATIVE_WIDTH; layout->height = GPU_LR_FRAMEBUFFER_NATIVE_HEIGHT; layout->pitch = GPU_LR_FRAMEBUFFER_NATIVE_WIDTH; layout->touch_x= 0; layout->touch_y= GPU_LR_FRAMEBUFFER_NATIVE_HEIGHT; layout->draw_screen2 = true; break; } } void retro_get_system_av_info(struct retro_system_av_info *info) { struct LayoutData layout; get_layout_params(current_layout, NULL, &layout); info->geometry.base_width = layout.width; info->geometry.base_height = layout.height; info->geometry.max_width = layout.width * 2; info->geometry.max_height = layout.height; info->geometry.aspect_ratio = 0.0; info->timing.fps = 60.0; info->timing.sample_rate = 44100.0; } static void MicrophoneToggle(void) { if (NDS_getFinalUserInput().mic.micButtonPressed) NDS_setMic(false); else NDS_setMic(true); } static void check_variables(bool first_boot) { struct retro_variable var = {0}; if (first_boot) { var.key = "desmume_internal_resolution"; if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) { char *pch; char str[100]; snprintf(str, sizeof(str), "%s", var.value); pch = strtok(str, "x"); if (pch) GPU_LR_FRAMEBUFFER_NATIVE_WIDTH = strtoul(pch, NULL, 0); pch = strtok(NULL, "x"); if (pch) GPU_LR_FRAMEBUFFER_NATIVE_HEIGHT = strtoul(pch, NULL, 0); switch (GPU_LR_FRAMEBUFFER_NATIVE_WIDTH) { case 256: scale = 1; break; case 512: scale = 2; break; case 768: scale = 3; break; case 1024: scale = 4; break; case 1280: scale = 5; break; case 1536: scale = 6; break; case 1792: scale = 7; break; case 2048: scale = 8; break; case 2304: scale = 9; break; case 2560: scale = 10; break; } } } var.key = "desmume_num_cores"; if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) CommonSettings.num_cores = var.value ? strtol(var.value, 0, 10) : 1; else CommonSettings.num_cores = 1; var.key = "desmume_cpu_mode"; var.value = 0; if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) { if (!strcmp(var.value, "jit")) CommonSettings.use_jit = true; else if (!strcmp(var.value, "interpreter")) CommonSettings.use_jit = false; } else { #ifdef HAVE_JIT CommonSettings.use_jit = true; #else CommonSettings.use_jit = false; #endif } #ifdef HAVE_JIT var.key = "desmume_jit_block_size"; if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) CommonSettings.jit_max_block_size = var.value ? strtol(var.value, 0, 10) : 100; else CommonSettings.jit_max_block_size = 100; #endif var.key = "desmume_screens_layout"; if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) { static int old_layout_id = -1; unsigned new_layout_id = 0; quick_switch_enable = false; if (!strcmp(var.value, "top/bottom")) new_layout_id = LAYOUT_TOP_BOTTOM; else if (!strcmp(var.value, "bottom/top")) new_layout_id = LAYOUT_BOTTOM_TOP; else if (!strcmp(var.value, "left/right")) new_layout_id = LAYOUT_LEFT_RIGHT; else if (!strcmp(var.value, "right/left")) new_layout_id = LAYOUT_RIGHT_LEFT; else if (!strcmp(var.value, "top only")) new_layout_id = LAYOUT_TOP_ONLY; else if (!strcmp(var.value, "bottom only")) new_layout_id = LAYOUT_BOTTOM_ONLY; else if (!strcmp(var.value, "quick switch")) { new_layout_id = LAYOUT_TOP_ONLY; quick_switch_enable = true; } if (old_layout_id != new_layout_id) { old_layout_id = new_layout_id; current_layout = new_layout_id; } } else quick_switch_enable = false; var.key = "desmume_pointer_mouse"; if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) { if (!strcmp(var.value, "enable")) mouse_enable = true; else if (!strcmp(var.value, "disable")) mouse_enable = false; } else mouse_enable = false; var.key = "desmume_pointer_device"; if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) { if (!strcmp(var.value, "l-stick")) pointer_device = 1; else if(!strcmp(var.value, "r-stick")) pointer_device = 2; else pointer_device=0; } else pointer_device=0; var.key = "desmume_pointer_device_deadzone"; if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) analog_stick_deadzone = (int)(atoi(var.value)); var.key = "desmume_pointer_type"; if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) { touchEnabled = var.value && (!strcmp(var.value, "touch")); } var.key = "desmume_frameskip"; if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) frameSkip = var.value ? strtol(var.value, 0, 10) : 0; else frameSkip = 0; var.key = "desmume_firmware_language"; if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) { static const struct { const char* name; int id; } languages[] = { { "Auto", -1 }, { "Japanese", 0 }, { "English", 1 }, { "French", 2 }, { "German", 3 }, { "Italian", 4 }, { "Spanish", 5 } }; for (int i = 0; i < 7; i ++) { if (!strcmp(languages[i].name, var.value)) { firmwareLanguage = languages[i].id; if (firmwareLanguage == -1) firmwareLanguage = host_get_language(); break; } } } else firmwareLanguage = 1; var.key = "desmume_gfx_edgemark"; if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) { if (!strcmp(var.value, "enable")) CommonSettings.GFX3D_EdgeMark = true; else if (!strcmp(var.value, "disable")) CommonSettings.GFX3D_EdgeMark = false; } else CommonSettings.GFX3D_EdgeMark = true; var.key = "desmume_gfx_linehack"; if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) { if (!strcmp(var.value, "enable")) CommonSettings.GFX3D_LineHack = true; else if (!strcmp(var.value, "disable")) CommonSettings.GFX3D_LineHack = false; } else CommonSettings.GFX3D_LineHack = true; var.key = "desmume_gfx_txthack"; if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) { if (!strcmp(var.value, "enable")) CommonSettings.GFX3D_TXTHack = true; else if (!strcmp(var.value, "disable")) CommonSettings.GFX3D_TXTHack = false; } else CommonSettings.GFX3D_TXTHack = false; var.key = "desmume_mic_force_enable"; if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) { if (!strcmp(var.value, "yes")) microphone_force_enable = 1; else if(!strcmp(var.value, "no")) microphone_force_enable = 0; } else NDS_setMic(false); var.key = "desmume_mic_mode"; if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) { if (!strcmp(var.value, "internal")) CommonSettings.micMode = TCommonSettings::InternalNoise; else if(!strcmp(var.value, "sample")) CommonSettings.micMode = TCommonSettings::Sample; else if(!strcmp(var.value, "random")) CommonSettings.micMode = TCommonSettings::Random; else if(!strcmp(var.value, "physical")) CommonSettings.micMode = TCommonSettings::Physical; } else CommonSettings.micMode = TCommonSettings::InternalNoise; var.key = "desmume_pointer_device_acceleration_mod"; if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) analog_stick_acceleration_modifier = atoi(var.value); else analog_stick_acceleration_modifier = 0; var.key = "desmume_pointer_stylus_pressure"; if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) CommonSettings.StylusPressure = atoi(var.value); else CommonSettings.StylusPressure = 50; var.key = "desmume_pointer_stylus_jitter"; if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) { if (!strcmp(var.value, "enable")) CommonSettings.StylusJitter = true; else if (!strcmp(var.value, "disable")) CommonSettings.StylusJitter = false; } else CommonSettings.StylusJitter = false; var.key = "desmume_load_to_memory"; if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) { if (!strcmp(var.value, "enable")) CommonSettings.loadToMemory = true; else if (!strcmp(var.value, "disable")) CommonSettings.loadToMemory = false; } else CommonSettings.loadToMemory = false; var.key = "desmume_advanced_timing"; if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) { if (!strcmp(var.value, "enable")) CommonSettings.advanced_timing = true; else if (!strcmp(var.value, "disable")) CommonSettings.advanced_timing = false; } else CommonSettings.advanced_timing = true; var.key = "desmume_screens_gap"; if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) { if ((atoi(var.value)) != nds_screen_gap) { nds_screen_gap = atoi(var.value); if (nds_screen_gap > 100) nds_screen_gap = 100; } } } #ifndef GPU3D_NULL #define GPU3D_NULL 0 #endif #ifdef HAVE_OPENGL #define GPU3D_OPENGL_3_2 1 #define GPU3D_SWRAST 2 #define GPU3D_OPENGL_OLD 3 #else #define GPU3D_SWRAST 1 #endif GPU3DInterface* core3DList[] = { &gpu3DNull, #ifdef HAVE_OPENGL &gpu3Dgl_3_2, #endif &gpu3DRasterize, #ifdef HAVE_OPENGL &gpu3DglOld, #endif NULL }; void retro_set_video_refresh(retro_video_refresh_t cb) { video_cb = cb; } void retro_set_audio_sample(retro_audio_sample_t cb) { } void retro_set_audio_sample_batch(retro_audio_sample_batch_t cb) { audio_batch_cb = cb; } void retro_set_input_poll(retro_input_poll_t cb) { poll_cb = cb; } void retro_set_input_state(retro_input_state_t cb) { input_cb = cb; } void retro_set_environment(retro_environment_t cb) { environ_cb = cb; static const retro_variable values[] = { { "desmume_internal_resolution", "Internal resolution (restart); 256x192|512x384|768x576|1024x768|1280x960|1536x1152|1792x1344|2048x1536|2304x1728|2560x1920" }, { "desmume_num_cores", "CPU cores; 1|2|3|4" }, #ifdef HAVE_JIT #if defined(IOS) || defined(ANDROID) { "desmume_cpu_mode", "CPU mode; interpreter|jit" }, #else { "desmume_cpu_mode", "CPU mode; jit|interpreter" }, #endif { "desmume_jit_block_size", "JIT block size; 12|11|10|9|8|7|6|5|4|3|2|1|0|100|99|98|97|96|95|94|93|92|91|90|89|88|87|86|85|84|83|82|81|80|79|78|77|76|75|74|73|72|71|70|69|68|67|66|65|64|63|62|61|60|59|58|57|56|55|54|53|52|51|50|49|48|47|46|45|44|43|42|41|40|39|38|37|36|35|34|33|32|31|30|29|28|27|26|25|24|23|22|21|20|19|18|17|16|15|14|13" }, #else { "desmume_cpu_mode", "CPU mode; interpreter" }, #endif { "desmume_screens_layout", "Screen layout; top/bottom|bottom/top|left/right|right/left|top only|bottom only|quick switch" }, { "desmume_pointer_mouse", "Enable mouse/pointer; enable|disable" }, { "desmume_pointer_type", "Pointer type; mouse|touch" }, { "desmume_pointer_device", "Pointer emulation; none|l-stick|r-stick" }, { "desmume_pointer_device_deadzone", "Emulated pointer deadzone percent; 15|20|25|30|0|5|10" }, { "desmume_pointer_device_acceleration_mod", "Emulated pointer acceleration modifier percent; 0|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31|32|33|34|35|36|37|38|39|40|41|42|43|44|45|46|47|48|49|50|51|52|53|54|55|56|57|58|59|60|61|62|63|64|65|66|67|68|69|70|71|72|73|74|75|76|77|78|79|80|81|82|83|84|85|86|87|88|89|90|91|92|93|94|95|96|97|98|99|100" }, { "desmume_pointer_stylus_pressure", "Emulated stylus pressure modifier percent; 50|51|52|53|54|55|56|57|58|59|60|61|62|63|64|65|66|67|68|69|70|71|72|73|74|75|76|77|78|79|80|81|82|83|84|85|86|87|88|89|90|91|92|93|94|95|96|97|98|99|100|0|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31|32|33|34|35|36|37|38|39|40|41|42|43|44|45|46|47|48|49|" }, { "desmume_pointer_stylus_jitter", "Enable emulated stylus jitter; disable|enable"}, { "desmume_load_to_memory", "Load Game into Memory (restart); disable|enable" }, { "desmume_advanced_timing", "Enable Advanced Bus-Level Timing; enable|disable" }, { "desmume_firmware_language", "Firmware language; Auto|English|Japanese|French|German|Italian|Spanish" }, { "desmume_frameskip", "Frameskip; 0|1|2|3|4|5|6|7|8|9" }, { "desmume_screens_gap", "Screen Gap; 0|5|64|90|0|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31|32|33|34|35|36|37|38|39|40|41|42|43|44|45|46|47|48|49|50|51|52|53|54|55|56|57|58|59|60|61|62|63|64|65|66|67|68|69|70|71|72|73|74|75|76|77|78|79|80|81|82|83|84|85|86|87|88|89|90|91|92|93|94|95|96|97|98|99|100" }, { "desmume_gfx_edgemark", "Enable Edgemark; enable|disable" }, { "desmume_gfx_linehack", "Enable Line Hack; enable|disable" }, { "desmume_gfx_txthack", "Enable TXT Hack; disable|enable"}, { "desmume_mic_force_enable", "Force Microphone Enable; no|yes" }, { "desmume_mic_mode", "Microphone Simulation Settings; internal|sample|random|physical" }, { 0, 0 } }; environ_cb(RETRO_ENVIRONMENT_SET_VARIABLES, (void*)values); } //====================== Message box #define MSG_ARG \ char msg_buf[1024] = {0}; \ { \ va_list args; \ va_start (args, fmt); \ vsprintf (msg_buf, fmt, args); \ va_end (args); \ } void msgWndInfo(const char *fmt, ...) { MSG_ARG; if (log_cb) log_cb(RETRO_LOG_INFO, "%s.\n", msg_buf); } bool msgWndConfirm(const char *fmt, ...) { MSG_ARG; if (log_cb) log_cb(RETRO_LOG_INFO, "%s.\n", msg_buf); return true; } void msgWndError(const char *fmt, ...) { MSG_ARG; if (log_cb) log_cb(RETRO_LOG_ERROR, "%s.\n", msg_buf); } void msgWndWarn(const char *fmt, ...) { MSG_ARG; if (log_cb) log_cb(RETRO_LOG_WARN, "%s.\n", msg_buf); } msgBoxInterface msgBoxWnd = { msgWndInfo, msgWndConfirm, msgWndError, msgWndWarn, }; //====================== Dialogs end static void check_system_specs(void) { unsigned level = 15; environ_cb(RETRO_ENVIRONMENT_SET_PERFORMANCE_LEVEL, &level); } static void Change3DCoreWithFallback(int newCore) { if( (newCore < 0) #ifdef HAVE_OPENGL || (newCore > GPU3D_OPENGL_OLD) #endif ) newCore = GPU3D_SWRAST; printf("Attempting change to 3d core to: %s\n",core3DList[newCore]->name); #ifdef HAVE_OPENGL if(newCore == GPU3D_OPENGL_OLD) goto TRY_OGL_OLD; #endif if(newCore == GPU3D_SWRAST) goto TRY_SWRAST; if(newCore == GPU3D_NULL) { NDS_3D_ChangeCore(GPU3D_NULL); cur3DCore = GPU3D_NULL; goto DONE; } #ifdef HAVE_OPENGL if(!NDS_3D_ChangeCore(GPU3D_OPENGL_3_2)) { printf("falling back to 3d core: %s\n",core3DList[GPU3D_OPENGL_OLD]->name); cur3DCore = GPU3D_OPENGL_3_2; goto TRY_OGL_OLD; } #endif goto DONE; #ifdef HAVE_OPENGL TRY_OGL_OLD: if(!NDS_3D_ChangeCore(GPU3D_OPENGL_OLD)) { printf("falling back to 3d core: %s\n",core3DList[GPU3D_SWRAST]->name); cur3DCore = GPU3D_OPENGL_OLD; goto TRY_SWRAST; } goto DONE; #endif TRY_SWRAST: cur3DCore = GPU3D_SWRAST; NDS_3D_ChangeCore(GPU3D_SWRAST); DONE: (void)0; } void retro_init (void) { struct retro_log_callback log; if (environ_cb(RETRO_ENVIRONMENT_GET_LOG_INTERFACE, &log)) log_cb = log.log; else log_cb = NULL; colorMode = RETRO_PIXEL_FORMAT_RGB565; if(!environ_cb(RETRO_ENVIRONMENT_SET_PIXEL_FORMAT, &colorMode)) return; check_variables(true); // Init DeSmuME struct NDS_fw_config_data fw_config; NDS_FillDefaultFirmwareConfigData(&fw_config); fw_config.language = firmwareLanguage; //addonsChangePak(NDS_ADDON_NONE); NDS_Init(); SPU_ChangeSoundCore(0, 735 * 2); NDS_CreateDummyFirmware(&fw_config); Change3DCoreWithFallback(GPU3D_SWRAST); backup_setManualBackupType(MC_TYPE_AUTODETECT); msgbox = &msgBoxWnd; check_system_specs(); } void retro_deinit(void) { NDS_DeInit(); #ifdef PERF_TEST rarch_perf_log(); #endif } void retro_reset (void) { NDS_Reset(); } void retro_run (void) { struct LayoutData layout; bool updated = false; bool have_touch = false; if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE, &updated) && updated) { check_variables(false); struct retro_system_av_info new_av_info; retro_get_system_av_info(&new_av_info); environ_cb(RETRO_ENVIRONMENT_SET_GEOMETRY, &new_av_info); } poll_cb(); get_layout_params(current_layout, screen_buf, &layout); if(pointer_device != 0) { int16_t analogX = 0; int16_t analogY = 0; float final_acceleration = analog_stick_acceleration * (1.0 + (float)analog_stick_acceleration_modifier / 100.0); if(pointer_device == 1) { analogX = input_cb(0, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_X) / final_acceleration; analogY = input_cb(0, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_Y) / final_acceleration; } else if(pointer_device == 2) { analogX = input_cb(0, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_RIGHT, RETRO_DEVICE_ID_ANALOG_X) / final_acceleration; analogY = input_cb(0, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_RIGHT, RETRO_DEVICE_ID_ANALOG_Y) / final_acceleration; } else { analogX = 0; analogY = 0; } // Convert cartesian coordinate analog stick to polar coordinates double radius = sqrt(analogX * analogX + analogY * analogY); double angle = atan2(analogY, analogX); double max = (float)0x8000/analog_stick_acceleration; //log_cb(RETRO_LOG_DEBUG, "%d %d.\n", analogX,analogY); //log_cb(RETRO_LOG_DEBUG, "%d %d.\n", radius,analog_stick_deadzone); if (radius > (float)analog_stick_deadzone*max/100) { // Re-scale analog stick range to negate deadzone (makes slow movements possible) radius = (radius - (float)analog_stick_deadzone*max/100)*((float)max/(max - (float)analog_stick_deadzone*max/100)); // Convert back to cartesian coordinates analogX = (int32_t)round(radius * cos(angle)); analogY = (int32_t)round(radius * sin(angle)); } else { analogX = 0; analogY = 0; } //log_cb(RETRO_LOG_DEBUG, "%d %d.\n", GPU_LR_FRAMEBUFFER_NATIVE_WIDTH,GPU_LR_FRAMEBUFFER_NATIVE_HEIGHT); //log_cb(RETRO_LOG_DEBUG, "%d %d.\n", analogX,analogY); have_touch = have_touch || input_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R2); TouchX = Saturate(0, (GPU_LR_FRAMEBUFFER_NATIVE_WIDTH-1), TouchX + analogX); TouchY = Saturate(0, (GPU_LR_FRAMEBUFFER_NATIVE_HEIGHT-1), TouchY + analogY); FramesWithPointer = (analogX || analogY) ? FramesWithPointerBase : FramesWithPointer; } if(mouse_enable) { // TOUCH: Mouse if(!touchEnabled) { const int16_t mouseX = input_cb(1, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_X); const int16_t mouseY = input_cb(1, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_Y); have_touch = have_touch || input_cb(1, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_LEFT); TouchX = Saturate(0, (GPU_LR_FRAMEBUFFER_NATIVE_WIDTH-1), TouchX + mouseX); TouchY = Saturate(0, (GPU_LR_FRAMEBUFFER_NATIVE_HEIGHT-1), TouchY + mouseY); FramesWithPointer = (mouseX || mouseY) ? FramesWithPointerBase : FramesWithPointer; } // TOUCH: Pointer else if(input_cb(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_PRESSED)) { const float X_FACTOR = ((float)layout.width / 65536.0f); const float Y_FACTOR = ((float)layout.height / 65536.0f); float x = (input_cb(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_X) + 32768.0f) * X_FACTOR; float y = (input_cb(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_Y) + 32768.0f) * Y_FACTOR; if ((x >= layout.touch_x) && (x < layout.touch_x + GPU_LR_FRAMEBUFFER_NATIVE_WIDTH) && (y >= layout.touch_y) && (y < layout.touch_y + GPU_LR_FRAMEBUFFER_NATIVE_HEIGHT)) { have_touch = true; TouchX = x - layout.touch_x; TouchY = y - layout.touch_y; } } } if(have_touch) NDS_setTouchPos(TouchX, TouchY, scale); else NDS_releaseTouch(); // BUTTONS //NDS_beginProcessingInput(); NDS_setPad( input_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT), input_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT), input_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_DOWN), input_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP), input_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_SELECT), input_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START), input_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B), input_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_A), input_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_Y), input_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_X), input_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L), input_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R), 0, // debug input_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L2) //Lid ); if (!microphone_force_enable) { if(input_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L3)) NDS_setMic(true); else if(!input_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L3)) NDS_setMic(false); } else NDS_setMic(true); if(input_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R3) && quick_switch_enable && delay_timer == 0) { switch (current_layout) { case LAYOUT_TOP_ONLY: current_layout = LAYOUT_BOTTOM_ONLY; break; case LAYOUT_BOTTOM_ONLY: current_layout = LAYOUT_TOP_ONLY; break; } delay_timer++; } if(delay_timer != 0) { delay_timer++; if(delay_timer == 30) delay_timer = 0; } NDS_endProcessingInput(); // RUN frameIndex ++; bool skipped = frameIndex <= frameSkip; if (skipped) NDS_SkipNextFrame(); NDS_exec(); SPU_Emulate_user(); if (!skipped) { u16 *screen = GPU->GetCustomFramebuffer(); if (layout.draw_screen1) SwapScreen (layout.dst, screen, layout.pitch); if (layout.draw_screen2) { screen = GPU->GetCustomFramebuffer() + GPU_LR_FRAMEBUFFER_NATIVE_WIDTH * GPU_LR_FRAMEBUFFER_NATIVE_HEIGHT; SwapScreen (layout.dst2, screen, layout.pitch); DrawPointer(layout.dst2, layout.pitch); } } video_cb(skipped ? 0 : screen_buf, layout.width, layout.height, layout.pitch * 2); frameIndex = skipped ? frameIndex : 0; } size_t retro_serialize_size (void) { // HACK: Usually around 10 MB but can vary frame to frame! return 1024 * 1024 * 12; } bool retro_serialize(void *data, size_t size) { EMUFILE_MEMORY state; savestate_save(&state); if(state.size() <= size) { memcpy(data, state.buf(), state.size()); return true; } return false; } bool retro_unserialize(const void * data, size_t size) { EMUFILE_MEMORY state(const_cast(data), size); return savestate_load(&state); } bool retro_load_game(const struct retro_game_info *game) { if (colorMode != RETRO_PIXEL_FORMAT_RGB565) return false; struct retro_input_descriptor desc[] = { { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT, "Left" }, { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP, "Up" }, { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_DOWN, "Down" }, { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT, "Right" }, { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_X, "X" }, { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_Y, "Y" }, { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B, "B" }, { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_A, "A" }, { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L, "L" }, { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L2, "Lid Close/Open" }, { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L3, "Toggle Microphone" }, { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R, "R" }, { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R3, "Quick Screen Switch" }, { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_SELECT, "Select" }, { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START, "Reset" }, { 0 }, }; environ_cb(RETRO_ENVIRONMENT_SET_INPUT_DESCRIPTORS, desc); execute = NDS_LoadROM(game->path); if (execute == -1) return false; screen_buf = (uint16_t*)malloc(GPU_LR_FRAMEBUFFER_NATIVE_WIDTH * (GPU_LR_FRAMEBUFFER_NATIVE_HEIGHT + NDS_MAX_SCREEN_GAP) * 2 * sizeof(uint16_t)); return true; } bool retro_load_game_special(unsigned game_type, const struct retro_game_info *info, size_t num_info) { #if 0 if(game_type == RETRO_GAME_TYPE_SUPER_GAME_BOY && num_info == 2) { strncpy(GBAgameName, info[1].path, sizeof(GBAgameName)); addonsChangePak(NDS_ADDON_GBAGAME); return retro_load_game(&info[0]); } #endif return false; } void retro_unload_game (void) { NDS_FreeROM(); if (screen_buf) free(screen_buf); screen_buf = NULL; execute = 0; } // Stubs void retro_set_controller_port_device(unsigned in_port, unsigned device) { } void *retro_get_memory_data(unsigned type) { return 0; } size_t retro_get_memory_size(unsigned type) { return 0; } unsigned retro_api_version(void) { return RETRO_API_VERSION; } extern CHEATS *cheats; void retro_cheat_reset(void) { if (cheats) cheats->clear(); } void retro_cheat_set(unsigned index, bool enabled, const char *code) { char ds_code[1024]; char desc[1024]; strcpy(ds_code, code); strcpy(desc, "N/A"); if (!cheats) return; if (cheats->add_AR(ds_code, desc, 1) != TRUE) { /* Couldn't add Action Replay code */ } } unsigned retro_get_region (void) { return RETRO_REGION_NTSC; } #if defined(PSP) int ftruncate(int fd, off_t length) { int ret; SceOff oldpos; if (!__PSP_IS_FD_VALID(fd)) { errno = EBADF; return -1; } switch(__psp_descriptormap[fd]->type) { case __PSP_DESCRIPTOR_TYPE_FILE: if (__psp_descriptormap[fd]->filename != NULL) { if (!(__psp_descriptormap[fd]->flags & (O_WRONLY | O_RDWR))) break; return truncate(__psp_descriptormap[fd]->filename, length); /* ANSI sez ftruncate doesn't move the file pointer */ } break; case __PSP_DESCRIPTOR_TYPE_TTY: case __PSP_DESCRIPTOR_TYPE_PIPE: case __PSP_DESCRIPTOR_TYPE_SOCKET: default: break; } errno = EINVAL; return -1; } #endif desmume/src/SPU.cpp000664 001750 001750 00000124654 12755534123 015326 0ustar00sergiosergio000000 000000 /* Copyright (C) 2006 yopyop Copyright (C) 2006 Theo Berkau Copyright (C) 2008-2015 DeSmuME team Ideas borrowed from Stephane Dallongeville's SCSP core This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the this software. If not, see . */ #define _USE_MATH_DEFINES #include #ifndef M_PI #define M_PI 3.1415926535897932386 #endif #include #include #include #include #include #include "debug.h" #include "driver.h" #include "MMU.h" #include "SPU.h" #include "mem.h" #include "readwrite.h" #include "armcpu.h" #include "NDSSystem.h" #include "matrix.h" #include "utils/bits.h" extern retro_audio_sample_batch_t audio_batch_cb; static inline s16 read16(u32 addr) { return (s16)_MMU_read16(addr); } static inline u8 read08(u32 addr) { return _MMU_read08(addr); } static inline s8 read_s8(u32 addr) { return (s8)_MMU_read08(addr); } #define K_ADPCM_LOOPING_RECOVERY_INDEX 99999 #define COSINE_INTERPOLATION_RESOLUTION 8192 //#ifdef FASTBUILD #undef FORCEINLINE #define FORCEINLINE //#endif SPU_struct *SPU_core = 0; int SPU_currentCoreNum = SNDCORE_DUMMY; static int volume = 100; static size_t buffersize = 0; //const int shift = (FORMAT == 0 ? 2 : 1); static const int format_shift[] = { 2, 1, 3, 0 }; static const u8 volume_shift[] = { 0, 1, 2, 4 }; static const s8 indextbl[8] = { -1, -1, -1, -1, 2, 4, 6, 8 }; static const u16 adpcmtbl[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 wavedutytbl[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 s32 precalcdifftbl[89][16]; static u8 precalcindextbl[89][8]; static const double ARM7_CLOCK = 33513982; static const double samples_per_hline = (DESMUME_SAMPLE_RATE / 59.8261f) / 263.0f; static double samples = 0; static FORCEINLINE int MinMax(int val, int min, int max) { if (val < min) return min; else if (val > max) return max; return val; } //--------------external spu interface--------------- int SPU_ChangeSoundCore(int coreid, int buffersize) { int i; ::buffersize = buffersize; return 0; } void SPU_ReInit(bool fakeBoot) { SPU_Init(0, buffersize); // Firmware set BIAS to 0x200 if (fakeBoot) SPU_WriteWord(0x04000504, 0x0200); } int SPU_Init(int coreid, int buffersize) { int i, j; SPU_core = new SPU_struct((int)ceil(samples_per_hline)); SPU_Reset(); //create adpcm decode accelerator lookups for(i = 0; i < 16; i++) { for(j = 0; j < 89; j++) { precalcdifftbl[j][i] = (((i & 0x7) * 2 + 1) * adpcmtbl[j] / 8); if(i & 0x8) precalcdifftbl[j][i] = -precalcdifftbl[j][i]; } } for(i = 0; i < 8; i++) { for(j = 0; j < 89; j++) { precalcindextbl[j][i] = MinMax((j + indextbl[i]), 0, 88); } } SPU_SetSynchMode(CommonSettings.SPU_sync_method); return SPU_ChangeSoundCore(coreid, buffersize); } void SPU_Pause(int pause) { } void SPU_CloneUser() { } void SPU_SetSynchMode(int method) { } void SPU_ClearOutputBuffer() { } void SPU_SetVolume(int volume) { } void SPU_Reset(void) { int i; SPU_core->reset(); //zero - 09-apr-2010: this concerns me, regarding savestate synch. //After 0.9.6, lets experiment with removing it and just properly zapping the spu instead // Reset Registers for (i = 0x400; i < 0x51D; i++) T1WriteByte(MMU.ARM7_REG, i, 0); samples = 0; } //------------------------------------------ void SPU_struct::reset() { memset(sndbuf,0,bufsize*2*4); memset(outbuf,0,768*2*sizeof(s16)); memset((void *)channels, 0, sizeof(channel_struct) * 16); reconstruct(®s); for(int i = 0; i < 16; i++) { channels[i].num = i; } } SPU_struct::SPU_struct(int buffersize) : bufpos(0) , buflength(0) , sndbuf(0) , outbuf(0) , outbufptr(0) , bufsize(buffersize) { sndbuf = new s32[buffersize*2]; outbuf = new s16[768*2]; reset(); } SPU_struct::~SPU_struct() { if(sndbuf) delete[] sndbuf; if(outbuf) delete[] outbuf; } void SPU_DeInit(void) { delete SPU_core; SPU_core=0; } ////////////////////////////////////////////////////////////////////////////// void SPU_struct::ShutUp() { for(int i=0;i<16;i++) channels[i].status = CHANSTAT_STOPPED; } static FORCEINLINE void adjust_channel_timer(channel_struct *chan) { chan->sampinc = (((double)ARM7_CLOCK) / (DESMUME_SAMPLE_RATE * 2)) / (double)(0x10000 - chan->timer); } void SPU_struct::KeyProbe(int chan_num) { channel_struct &thischan = channels[chan_num]; if(thischan.status == CHANSTAT_STOPPED) { if(thischan.keyon && regs.masteren) KeyOn(chan_num); } else if(thischan.status == CHANSTAT_PLAY) { if(!thischan.keyon || !regs.masteren) KeyOff(chan_num); } } void SPU_struct::KeyOff(int channel) { //printf("keyoff%d\n",channel); channel_struct &thischan = channels[channel]; thischan.status = CHANSTAT_STOPPED; } void SPU_struct::KeyOn(int channel) { channel_struct &thischan = channels[channel]; thischan.status = CHANSTAT_PLAY; thischan.totlength = thischan.length + thischan.loopstart; adjust_channel_timer(&thischan); //printf("keyon %d totlength:%d\n",channel,thischan.totlength); //LOG("Channel %d key on: vol = %d, volumeDiv = %d, hold = %d, pan = %d, waveduty = %d, repeat = %d, format = %d, source address = %07X," // "timer = %04X, loop start = %04X, length = %06X, MMU.ARM7_REG[0x501] = %02X\n", channel, chan->vol, chan->volumeDiv, chan->hold, // chan->pan, chan->waveduty, chan->repeat, chan->format, chan->addr, chan->timer, chan->loopstart, chan->length, T1ReadByte(MMU.ARM7_REG, 0x501)); switch(thischan.format) { case 0: // 8-bit // thischan.loopstart = thischan.loopstart << 2; // thischan.length = (thischan.length << 2) + thischan.loopstart; thischan.sampcnt = -3; break; case 1: // 16-bit // thischan.loopstart = thischan.loopstart << 1; // thischan.length = (thischan.length << 1) + thischan.loopstart; thischan.sampcnt = -3; break; case 2: // ADPCM { thischan.pcm16b = (s16)read16(thischan.addr); thischan.pcm16b_last = thischan.pcm16b; thischan.index = read08(thischan.addr + 2) & 0x7F;; thischan.lastsampcnt = 7; thischan.sampcnt = -3; thischan.loop_index = K_ADPCM_LOOPING_RECOVERY_INDEX; // thischan.loopstart = thischan.loopstart << 3; // thischan.length = (thischan.length << 3) + thischan.loopstart; break; } case 3: // PSG { thischan.sampcnt = -1; thischan.x = 0x7FFF; break; } default: break; } thischan.double_totlength_shifted = (double)(thischan.totlength << format_shift[thischan.format]); if(thischan.format != 3) { if(thischan.double_totlength_shifted == 0) { printf("INFO: Stopping channel %d due to zero length\n",channel); thischan.status = CHANSTAT_STOPPED; } } } ////////////////////////////////////////////////////////////////////////////// u8 SPU_struct::ReadByte(u32 addr) { u8 * channel_timer; u8 * channel_loopstart; u8 * sound_bias = (u8 *)regs.soundbias; u8 * cap0_dad = (u8 *)regs.cap[0].dad; u8 * cap1_dad = (u8 *)regs.cap[1].dad; u8 * cap0_len = (u8 *)regs.cap[0].len; u8 * cap1_len = (u8 *)regs.cap[1].len; //individual channel regs if ((addr & 0x0F00) == 0x0400) { u32 chan_num = (addr >> 4) & 0xF; channel_struct &thischan = channels[chan_num]; channel_timer = (u8 *)thischan.timer; channel_loopstart = (u8 *)thischan.loopstart; switch (addr & 0xF) { case 0x0: return thischan.vol; case 0x1: return (thischan.volumeDiv | (thischan.hold << 7)); case 0x2: return thischan.pan; case 0x3: return ( thischan.waveduty | (thischan.repeat << 3) | (thischan.format << 5) | ((thischan.status == CHANSTAT_PLAY)?0x80:0) ); case 0x8: return channel_timer[0]; case 0x9: return channel_timer[1]; case 0xA: return channel_loopstart[0]; case 0xB: return channel_loopstart[1]; } return 0; } switch(addr) { //SOUNDCNT case 0x500: return regs.mastervol; case 0x501: return (regs.ctl_left | (regs.ctl_right << 2) | (regs.ctl_ch1bypass << 4) | (regs.ctl_ch3bypass << 5) | (regs.masteren << 7) ); //SOUNDBIAS case 0x504: return sound_bias[0]; case 0x505: return sound_bias[1]; //SNDCAP0CNT/SNDCAP1CNT case 0x508: case 0x509: { u32 which = (addr - 0x508); return regs.cap[which].add | (regs.cap[which].source << 1) | (regs.cap[which].oneshot << 2) | (regs.cap[which].bits8 << 3) | (regs.cap[which].runtime.running << 7); } //SNDCAP0DAD case 0x510: return cap0_dad[0]; case 0x511: return cap0_dad[1]; case 0x512: return cap0_dad[2]; case 0x513: return cap0_dad[3]; //SNDCAP0LEN case 0x514: return cap0_len[0]; case 0x515: return cap0_len[1]; //SNDCAP1DAD case 0x518: return cap1_dad[0]; case 0x519: return cap1_dad[1]; case 0x51A: return cap1_dad[2]; case 0x51B: return cap1_dad[3]; //SNDCAP1LEN case 0x51C: return cap1_len[0]; case 0x51D: return cap1_len[1]; } //switch on address return 0; } u16 SPU_struct::ReadWord(u32 addr) { u16 * cap0_dad = (u16 *)regs.cap[0].dad; u16 * cap1_dad = (u16 *)regs.cap[1].dad; //individual channel regs if ((addr & 0x0F00) == 0x0400) { u32 chan_num = (addr >> 4) & 0xF; channel_struct &thischan=channels[chan_num]; switch (addr & 0xF) { case 0x0: return (thischan.vol | (thischan.volumeDiv << 8) | (thischan.hold << 15) ); case 0x2: return (thischan.pan | (thischan.waveduty << 8) | (thischan.repeat << 11) | (thischan.format << 13) | ((thischan.status == CHANSTAT_PLAY)?(1 << 15):0) ); case 0x8: return thischan.timer; case 0xA: return thischan.loopstart; } //switch on individual channel regs return 0; } switch(addr) { //SOUNDCNT case 0x500: return (regs.mastervol | (regs.ctl_left << 8) | (regs.ctl_right << 10) | (regs.ctl_ch1bypass << 12) | (regs.ctl_ch3bypass << 13) | (regs.masteren << 15) ); //SOUNDBIAS case 0x504: return regs.soundbias; //SNDCAP0CNT/SNDCAP1CNT case 0x508: { u8 val0 = regs.cap[0].add | (regs.cap[0].source << 1) | (regs.cap[0].oneshot << 2) | (regs.cap[0].bits8 << 3) | (regs.cap[0].runtime.running << 7); u8 val1 = regs.cap[1].add | (regs.cap[1].source << 1) | (regs.cap[1].oneshot << 2) | (regs.cap[1].bits8 << 3) | (regs.cap[1].runtime.running << 7); return (u16)(val0 | (val1 << 8)); } //SNDCAP0DAD case 0x510: return cap0_dad[0]; case 0x512: return cap0_dad[1]; //SNDCAP0LEN case 0x514: return regs.cap[0].len; //SNDCAP1DAD case 0x518: return cap1_dad[0]; case 0x51A: return cap1_dad[1]; //SNDCAP1LEN case 0x51C: return regs.cap[1].len; } //switch on address return 0; } u32 SPU_struct::ReadLong(u32 addr) { //individual channel regs if ((addr & 0x0F00) == 0x0400) { u32 chan_num = (addr >> 4) & 0xF; channel_struct &thischan=channels[chan_num]; switch (addr & 0xF) { case 0x0: return (thischan.vol | (thischan.volumeDiv << 8) | (thischan.hold << 15) | (thischan.pan << 16) | (thischan.waveduty << 24) | (thischan.repeat << 27) | (thischan.format << 29) | ((thischan.status == CHANSTAT_PLAY)?(1 << 31):0) ); case 0x8: return (thischan.timer | (thischan.loopstart << 16)); } //switch on individual channel regs return 0; } switch(addr) { //SOUNDCNT case 0x500: return (regs.mastervol | (regs.ctl_left << 8) | (regs.ctl_right << 10) | (regs.ctl_ch1bypass << 12) | (regs.ctl_ch3bypass << 13) | (regs.masteren << 15) ); //SOUNDBIAS case 0x504: return (u32)regs.soundbias; //SNDCAP0CNT/SNDCAP1CNT case 0x508: { u8 val0 = regs.cap[0].add | (regs.cap[0].source << 1) | (regs.cap[0].oneshot << 2) | (regs.cap[0].bits8 << 3) | (regs.cap[0].runtime.running << 7); u8 val1 = regs.cap[1].add | (regs.cap[1].source << 1) | (regs.cap[1].oneshot << 2) | (regs.cap[1].bits8 << 3) | (regs.cap[1].runtime.running << 7); return (u32)(val0 | (val1 << 8)); } //SNDCAP0DAD case 0x510: return regs.cap[0].dad; //SNDCAP0LEN case 0x514: return (u32)regs.cap[0].len; //SNDCAP1DAD case 0x518: return regs.cap[1].dad; //SNDCAP1LEN case 0x51C: return (u32)regs.cap[1].len; } //switch on address return 0; } SPUFifo::SPUFifo() { reset(); } void SPUFifo::reset() { head = tail = size = 0; } void SPUFifo::enqueue(s16 val) { if(size==16) return; buffer[tail] = val; tail++; tail &= 15; size++; } s16 SPUFifo::dequeue() { if(size==0) return 0; head++; head &= 15; s16 ret = buffer[head]; size--; return ret; } void SPUFifo::save(EMUFILE* fp) { u32 version = 1; write32le(version,fp); write32le(head,fp); write32le(tail,fp); write32le(size,fp); for(int i=0;i<16;i++) write16le(buffer[i],fp); } bool SPUFifo::load(EMUFILE* fp) { u32 version; if(read32le(&version,fp) != 1) return false; read32le(&head,fp); read32le(&tail,fp); read32le(&size,fp); for(int i=0;i<16;i++) read16le(&buffer[i],fp); return true; } void SPU_struct::ProbeCapture(int which) { //VERY UNTESTED -- HOW MUCH OF THIS RESETS, AND WHEN? if(!regs.cap[which].active) { regs.cap[which].runtime.running = 0; return; } REGS::CAP &cap = regs.cap[which]; cap.runtime.running = 1; cap.runtime.curdad = cap.dad; u32 len = cap.len; if(len==0) len=1; cap.runtime.maxdad = cap.dad + len*4; cap.runtime.sampcnt = 0; cap.runtime.fifo.reset(); } void SPU_struct::WriteByte(u32 addr, u8 val) { u8 * channel_address; u8 * channel_timer; u8 * channel_loopstart; u8 * channel_length; u8 * sound_bias = (u8 *)regs.soundbias; u8 * cap0_dad = (u8 *)regs.cap[0].dad; u8 * cap1_dad = (u8 *)regs.cap[1].dad; u8 * cap0_len = (u8 *)regs.cap[0].len; u8 * cap1_len = (u8 *)regs.cap[1].len; //individual channel regs if ((addr & 0x0F00) == 0x0400) { u8 chan_num = (addr >> 4) & 0xF; channel_struct &thischan = channels[chan_num]; channel_address = (u8 *)thischan.addr; channel_timer = (u8 *)thischan.timer; channel_loopstart = (u8 *)thischan.loopstart; channel_length = (u8 *)thischan.length; //printf("SPU write08 channel%d, reg %04X, val %02X\n", chan_num, addr, val); switch (addr & 0x000F) { case 0x0: thischan.vol = (val & 0x7F); break; case 0x1: thischan.volumeDiv = (val & 0x03); thischan.hold = (val >> 7) & 0x01; break; case 0x2: thischan.pan = (val & 0x7F); break; case 0x3: thischan.waveduty = (val & 0x07); thischan.repeat = (val >> 3) & 0x03; thischan.format = (val >> 5) & 0x03; thischan.keyon = (val >> 7) & 0x01; KeyProbe(chan_num); break; case 0x4: channel_address[0] = (val & 0xFC); break; case 0x5: channel_address[1] = val; break; case 0x6: channel_address[2] = val; break; case 0x7: channel_address[3] = (val & 0x07); break; //only 27 bits of this register are used case 0x8: channel_timer[0] = val; adjust_channel_timer(&thischan); break; case 0x9: channel_timer[1] = val; adjust_channel_timer(&thischan); break; case 0xA: channel_loopstart[0] = val; break; case 0xB: channel_loopstart[1] = val; break; case 0xC: channel_length[0] = val; break; case 0xD: channel_length[1] = val; break; case 0xE: channel_length[2] = (val & 0x3F); break; //only 22 bits of this register are used case 0xF: channel_length[3] = 0; break; } //switch on individual channel regs return; } switch(addr) { //SOUNDCNT case 0x500: regs.mastervol = (val & 0x7F); break; case 0x501: regs.ctl_left = (val >> 0) & 3; regs.ctl_right = (val >> 2) & 3; regs.ctl_ch1bypass = (val >> 4) & 1; regs.ctl_ch3bypass = (val >> 5) & 1; regs.masteren = (val >> 7) & 1; for(u8 i=0; i<16; i++) KeyProbe(i); break; //SOUNDBIAS case 0x504: sound_bias[0] = val; break; case 0x505: sound_bias[1] = (val & 0x03); break; //SNDCAP0CNT/SNDCAP1CNT case 0x508: case 0x509: { u32 which = (addr - 0x508); regs.cap[which].add = BIT0(val); regs.cap[which].source = BIT1(val); regs.cap[which].oneshot = BIT2(val); regs.cap[which].bits8 = BIT3(val); regs.cap[which].active = BIT7(val); ProbeCapture(which); break; } //SNDCAP0DAD case 0x510: cap0_dad[0] = (val & 0xFC); break; case 0x511: cap0_dad[1] = val; break; case 0x512: cap0_dad[2] = val; break; case 0x513: cap0_dad[3] = (val & 0x07); break; //SNDCAP0LEN case 0x514: cap0_len[0] = val; break; case 0x515: cap0_len[1] = val; break; //SNDCAP1DAD case 0x518: cap1_dad[0] = (val & 0xFC); break; case 0x519: cap1_dad[1] = val; break; case 0x51A: cap1_dad[2] = val; break; case 0x51B: cap1_dad[3] = (val & 0x07); break; //SNDCAP1LEN case 0x51C: cap1_len[0] = val; break; case 0x51D: cap1_len[1] = val; break; } //switch on address } void SPU_struct::WriteWord(u32 addr, u16 val) { u16 * channel_address; u16 * channel_length; u16 * cap0_dad = (u16 *)regs.cap[0].dad; u16 * cap1_dad = (u16 *)regs.cap[1].dad; //individual channel regs if ((addr & 0x0F00) == 0x0400) { u32 chan_num = (addr >> 4) & 0xF; channel_struct &thischan = channels[chan_num]; channel_address = (u16 *)thischan.addr; channel_length = (u16 *)thischan.length; //printf("SPU write16 channel%d, reg %04X, val %04X\n", chan_num, addr, val); switch (addr & 0xF) { case 0x0: thischan.vol = (val & 0x7F); thischan.volumeDiv = (val >> 8) & 0x3; thischan.hold = (val >> 15) & 0x1; break; case 0x2: thischan.pan = (val & 0x7F); thischan.waveduty = (val >> 8) & 0x7; thischan.repeat = (val >> 11) & 0x3; thischan.format = (val >> 13) & 0x3; thischan.keyon = (val >> 15) & 0x1; KeyProbe(chan_num); break; case 0x4: channel_address[0] = (val & 0xFFFC); break; case 0x6: channel_address[1] = (val & 0x07FF); break; case 0x8: thischan.timer = val; adjust_channel_timer(&thischan); break; case 0xA: thischan.loopstart = val; break; case 0xC: channel_length[0] = val; break; case 0xE: channel_length[1] = (val & 0x003F); break; //only 22 bits of this register are used } //switch on individual channel regs return; } switch (addr) { //SOUNDCNT case 0x500: regs.mastervol = (val & 0x7F); regs.ctl_left = (val >> 8) & 0x03; regs.ctl_right = (val >> 10) & 0x03; regs.ctl_ch1bypass = (val >> 12) & 0x01; regs.ctl_ch3bypass = (val >> 13) & 0x01; regs.masteren = (val >> 15) & 0x01; for(u8 i=0; i<16; i++) KeyProbe(i); break; //SOUNDBIAS case 0x504: regs.soundbias = (val & 0x3FF); break; //SNDCAP0CNT/SNDCAP1CNT case 0x508: { regs.cap[0].add = BIT0(val); regs.cap[0].source = BIT1(val); regs.cap[0].oneshot = BIT2(val); regs.cap[0].bits8 = BIT3(val); regs.cap[0].active = BIT7(val); ProbeCapture(0); regs.cap[1].add = BIT8(val); regs.cap[1].source = BIT9(val); regs.cap[1].oneshot = BIT10(val); regs.cap[1].bits8 = BIT11(val); regs.cap[1].active = BIT15(val); ProbeCapture(1); break; } //SNDCAP0DAD case 0x510: cap0_dad[0] = (val & 0xFFFC); break; case 0x512: cap0_dad[1] = (val & 0x7FFF); break; //SNDCAP0LEN case 0x514: regs.cap[0].len = val; break; //SNDCAP1DAD case 0x518: cap1_dad[0] = (val & 0xFFFC); break; case 0x51A: cap1_dad[1] = (val & 0x7FFF); break; //SNDCAP1LEN case 0x51C: regs.cap[1].len = val; break; } //switch on address } void SPU_struct::WriteLong(u32 addr, u32 val) { //individual channel regs if ((addr & 0x0F00) == 0x0400) { u32 chan_num = (addr >> 4) & 0xF; channel_struct &thischan=channels[chan_num]; //printf("SPU write32 channel%d, reg %04X, val %08X\n", chan_num, addr, val); switch (addr & 0xF) { case 0x0: thischan.vol = val & 0x7F; thischan.volumeDiv = (val >> 8) & 0x3; thischan.hold = (val >> 15) & 0x1; thischan.pan = (val >> 16) & 0x7F; thischan.waveduty = (val >> 24) & 0x7; thischan.repeat = (val >> 27) & 0x3; thischan.format = (val >> 29) & 0x3; thischan.keyon = (val >> 31) & 0x1; KeyProbe(chan_num); break; case 0x4: thischan.addr = (val & 0x07FFFFFC); break; case 0x8: thischan.timer = (val & 0xFFFF); thischan.loopstart = ((val >> 16) & 0xFFFF); adjust_channel_timer(&thischan); break; case 0xC: thischan.length = (val & 0x003FFFFF); break; //only 22 bits of this register are used } //switch on individual channel regs return; } switch(addr) { //SOUNDCNT case 0x500: regs.mastervol = (val & 0x7F); regs.ctl_left = ((val >> 8) & 3); regs.ctl_right = ((val>>10) & 3); regs.ctl_ch1bypass = ((val >> 12) & 1); regs.ctl_ch3bypass = ((val >> 13) & 1); regs.masteren = ((val >> 15) & 1); for(u8 i=0; i<16; i++) KeyProbe(i); break; //SOUNDBIAS case 0x504: regs.soundbias = (val & 0x3FF); //SNDCAP0CNT/SNDCAP1CNT case 0x508: regs.cap[0].add = BIT0(val); regs.cap[0].source = BIT1(val); regs.cap[0].oneshot = BIT2(val); regs.cap[0].bits8 = BIT3(val); regs.cap[0].active = BIT7(val); ProbeCapture(0); regs.cap[1].add = BIT8(val); regs.cap[1].source = BIT9(val); regs.cap[1].oneshot = BIT10(val); regs.cap[1].bits8 = BIT11(val); regs.cap[1].active = BIT15(val); ProbeCapture(1); break; //SNDCAP0DAD case 0x510: regs.cap[0].dad = (val & 0x07FFFFFC); break; //SNDCAP0LEN case 0x514: regs.cap[0].len = (val & 0xFFFF); break; //SNDCAP1DAD case 0x518: regs.cap[1].dad = (val & 0x07FFFFFC); break; //SNDCAP1LEN case 0x51C: regs.cap[1].len = (val & 0xFFFF); break; } //switch on address } static FORCEINLINE void FetchADPCMData(channel_struct * const chan, s32 * const data) { const u32 endExclusive = sputrunc(chan->sampcnt+1); for (u32 i = chan->lastsampcnt+1; i < endExclusive; i++) { const u32 shift = (i&1)<<2; const u32 data4bit = ((u32)read08(chan->addr + (i>>1))) >> shift; const s32 diff = precalcdifftbl[chan->index][data4bit & 0xF]; chan->index = precalcindextbl[chan->index][data4bit & 0x7]; chan->pcm16b_last = chan->pcm16b; chan->pcm16b = MinMax(chan->pcm16b+diff, -0x8000, 0x7FFF); if(i == (chan->loopstart<<3)) { if(chan->loop_index != K_ADPCM_LOOPING_RECOVERY_INDEX) printf("over-snagging\n"); chan->loop_pcm16b = chan->pcm16b; chan->loop_index = chan->index; } } chan->lastsampcnt = sputrunc(chan->sampcnt); *data = (s32)chan->pcm16b; } static FORCEINLINE void FetchPSGData(channel_struct *chan, s32 *data) { if(chan->lastsampcnt == sputrunc(chan->sampcnt)) { *data = (s32)chan->psgnoise_last; return; } u32 max = sputrunc(chan->sampcnt); for(u32 i = chan->lastsampcnt; i < max; i++) { if(chan->x & 0x1) { chan->x = (chan->x >> 1) ^ 0x6000; chan->psgnoise_last = -0x7FFF; } else { chan->x >>= 1; chan->psgnoise_last = 0x7FFF; } } chan->lastsampcnt = sputrunc(chan->sampcnt); *data = (s32)chan->psgnoise_last; } ////////////////////////////////////////////////////////////////////////////// static FORCEINLINE int TestForLoop(SPU_struct *SPU, channel_struct *chan, int shift) { if (chan->sampcnt > chan->double_totlength_shifted) { // Do we loop? Or are we done? if (chan->repeat == 1) { while (chan->sampcnt > chan->double_totlength_shifted) chan->sampcnt -= chan->double_totlength_shifted - (double)(chan->loopstart << shift); return 0; } SPU->KeyOff(chan->num); SPU->bufpos = SPU->buflength; return 1; } return -1; } //WORK template FORCEINLINE static void ____SPU_ChanUpdate(SPU_struct* const SPU, channel_struct* const chan) { for (; SPU->bufpos < SPU->buflength; SPU->bufpos++) { int ret; int shift = (FORMAT == 0 ? 2 : 1); if(CHANNELS != -1) { s32 data; if (chan->sampcnt < 0) data = 0; else { switch(FORMAT) { case 0: /* Fetch 8-bit data */ data = (s32)read_s8(chan->addr + sputrunc(chan->sampcnt))<< 8; break; case 1: /* Fetch 16-bit data */ data = read16(chan->addr + sputrunc(chan->sampcnt)*2); break; case 2: /* Fetch ADPCM data */ /* No sense decoding, just return the last sample */ if (chan->lastsampcnt == sputrunc(chan->sampcnt)) data = (s32)chan->pcm16b; else FetchADPCMData(chan, &data); break; case 3: /* Fetch PSG data */ if(chan->num < 8) data = 0; else if(chan->num < 14) data = (s32)wavedutytbl[chan->waveduty][(sputrunc(chan->sampcnt)) & 0x7]; else FetchPSGData(chan, &data); break; } } data = spumuldiv7(data, chan->vol) >> volume_shift[chan->volumeDiv]; switch(CHANNELS) { case 0: /* MixL */ SPU->sndbuf[SPU->bufpos<<1] += data; break; case 1: /* MixLR */ SPU->sndbuf[SPU->bufpos<<1] += spumuldiv7(data, 127 - chan->pan); SPU->sndbuf[(SPU->bufpos<<1)+1] += spumuldiv7(data, chan->pan); break; case 2: /* MixR */ SPU->sndbuf[(SPU->bufpos<<1)+1] += data; break; } SPU->lastdata = data; } // Minimum length (the sum of PNT+LEN) is 4 words (16 bytes), // smaller values (0..3 words) are causing hang-ups // (busy bit remains set infinite, but no sound output occurs). // fix: 7th Dragon (JP) - http://sourceforge.net/p/desmume/bugs/1357/ if (FORMAT == 2 && chan->totlength < 4) continue; chan->sampcnt += chan->sampinc; switch(FORMAT) { case 2: shift = 3; /* fall-through */ case 0: case 1: ret = TestForLoop(SPU, chan, shift); if (FORMAT == 2 && ret != -1) { switch (ret) { case 0: if(chan->loop_index == K_ADPCM_LOOPING_RECOVERY_INDEX) { chan->pcm16b = (s16)read16(chan->addr); chan->index = read08(chan->addr+2) & 0x7F; chan->lastsampcnt = 7; } else { chan->pcm16b = chan->loop_pcm16b; chan->index = chan->loop_index; chan->lastsampcnt = (chan->loopstart << 3); } break; case 1: chan->status = CHANSTAT_STOPPED; break; } } break; } } } template FORCEINLINE static void ___SPU_ChanUpdate(const bool actuallyMix, SPU_struct* const SPU, channel_struct* const chan) { if(!actuallyMix) ____SPU_ChanUpdate(SPU,chan); else if (chan->pan == 0) ____SPU_ChanUpdate(SPU,chan); else if (chan->pan == 127) ____SPU_ChanUpdate(SPU,chan); else ____SPU_ChanUpdate(SPU,chan); } //ENTERNEW static void SPU_MixAudio_Advanced(SPU_struct *SPU, int length) { //the advanced spu function correctly handles all sound control mixing options, as well as capture //this code is not entirely optimal, as it relies on sort of manhandling the core mixing functions //in order to get the results it needs. //THIS IS MAX HACKS!!!! //AND NEEDS TO BE REWRITTEN ALONG WITH THE DEEPEST PARTS OF THE SPU //ONCE WE KNOW THAT IT WORKS //BIAS gets ignored since our spu is still not bit perfect, //and it doesnt matter for purposes of capture s32 samp0[2]; //believe it or not, we are going to do this one sample at a time. //like i said, it is slower. for(int samp=0;sampsndbuf[0] = 0; SPU->sndbuf[1] = 0; SPU->buflength = 1; s32 capmix[2] = {0,0}; s32 mix[2] = {0,0}; s32 chanout[16]; s32 submix[32]; //generate each channel, and helpfully mix it at the same time for(int i=0;i<16;i++) { channel_struct *chan = &SPU->channels[i]; if (chan->status == CHANSTAT_PLAY) { SPU->bufpos = 0; bool bypass = false; if(i==1 && SPU->regs.ctl_ch1bypass) bypass=true; if(i==3 && SPU->regs.ctl_ch3bypass) bypass=true; //output to mixer unless we are bypassed. //dont output to mixer if the user muted us bool outputToMix = true; if(bypass) outputToMix = false; bool outputToCap = outputToMix; //channels 1 and 3 should probably always generate their audio //internally at least, just in case they get used by the spu output bool domix = outputToCap || outputToMix || i==1 || i==3; //clear the output buffer since this is where _SPU_ChanUpdate wants to accumulate things SPU->sndbuf[0] = SPU->sndbuf[1] = 0; //get channel's next output sample. switch(chan->format) { case 0: ___SPU_ChanUpdate<0>(domix, SPU, chan); break; case 1: ___SPU_ChanUpdate<1>(domix, SPU, chan); break; case 2: ___SPU_ChanUpdate<2>(domix, SPU, chan); break; case 3: ___SPU_ChanUpdate<3>(domix, SPU, chan); break; } chanout[i] = SPU->lastdata >> volume_shift[chan->volumeDiv]; //save the panned results submix[i*2] = SPU->sndbuf[0]; submix[i*2+1] = SPU->sndbuf[1]; //send sample to our capture mix if(outputToCap) { capmix[0] += submix[i*2]; capmix[1] += submix[i*2+1]; } //send sample to our main mixer if(outputToMix) { mix[0] += submix[i*2]; mix[1] += submix[i*2+1]; } } else { chanout[i] = 0; submix[i*2] = 0; submix[i*2+1] = 0; } } //foreach channel s32 mixout[2] = {mix[0],mix[1]}; s32 capmixout[2] = {capmix[0],capmix[1]}; s32 sndout[2]; s32 capout[2]; //create SPU output switch(SPU->regs.ctl_left) { case SPU_struct::REGS::LOM_LEFT_MIXER: sndout[0] = mixout[0]; break; case SPU_struct::REGS::LOM_CH1: sndout[0] = submix[1*2+0]; break; case SPU_struct::REGS::LOM_CH3: sndout[0] = submix[3*2+0]; break; case SPU_struct::REGS::LOM_CH1_PLUS_CH3: sndout[0] = submix[1*2+0] + submix[3*2+0]; break; } switch(SPU->regs.ctl_right) { case SPU_struct::REGS::ROM_RIGHT_MIXER: sndout[1] = mixout[1]; break; case SPU_struct::REGS::ROM_CH1: sndout[1] = submix[1*2+1]; break; case SPU_struct::REGS::ROM_CH3: sndout[1] = submix[3*2+1]; break; case SPU_struct::REGS::ROM_CH1_PLUS_CH3: sndout[1] = submix[1*2+1] + submix[3*2+1]; break; } //generate capture output ("capture bugs" from gbatek are not emulated) if(SPU->regs.cap[0].source==0) capout[0] = capmixout[0]; //cap0 = L-mix else if(SPU->regs.cap[0].add) capout[0] = chanout[0] + chanout[1]; //cap0 = ch0+ch1 else capout[0] = chanout[0]; //cap0 = ch0 if(SPU->regs.cap[1].source==0) capout[1] = capmixout[1]; //cap1 = R-mix else if(SPU->regs.cap[1].add) capout[1] = chanout[2] + chanout[3]; //cap1 = ch2+ch3 else capout[1] = chanout[2]; //cap1 = ch2 capout[0] = MinMax(capout[0],-0x8000,0x7FFF); capout[1] = MinMax(capout[1],-0x8000,0x7FFF); //write the output sample where it is supposed to go if(samp==0) { samp0[0] = sndout[0]; samp0[1] = sndout[1]; } else { SPU->sndbuf[samp*2+0] = sndout[0]; SPU->sndbuf[samp*2+1] = sndout[1]; } for(int capchan=0;capchan<2;capchan++) { if(SPU->regs.cap[capchan].runtime.running) { SPU_struct::REGS::CAP& cap = SPU->regs.cap[capchan]; u32 last = sputrunc(cap.runtime.sampcnt); cap.runtime.sampcnt += SPU->channels[1+2*capchan].sampinc; u32 curr = sputrunc(cap.runtime.sampcnt); for(u32 j=last;j>8; _MMU_write08<1,MMU_AT_DMA>(cap.runtime.curdad,sample8); cap.runtime.curdad++; multiplier = 4; } else { s16 sample16 = sample; _MMU_write16<1,MMU_AT_DMA>(cap.runtime.curdad,sample16); cap.runtime.curdad+=2; multiplier = 2; } if(cap.runtime.curdad>=cap.runtime.maxdad) { cap.runtime.curdad = cap.dad; cap.runtime.sampcnt -= cap.len*multiplier; } } //sampinc loop } //if capchan running } //capchan loop } //main sample loop SPU->sndbuf[0] = samp0[0]; SPU->sndbuf[1] = samp0[1]; } //ENTER static void SPU_MixAudio(SPU_struct *SPU, int length) { u8 vol; bool advanced; memset(SPU->sndbuf, 0, length*4*2); //we used to use master enable here, and do nothing if audio is disabled. //now, master enable is emulated better.. //but for a speed optimization we will still do it if(!SPU->regs.masteren) return; vol = SPU->regs.mastervol; advanced = CommonSettings.spu_advanced ; //branch here so that slow computers don't have to take the advanced (slower) codepath. //it remains to be seen exactly how much slower it is //if it isnt much slower then we should refactor everything to be simpler, once it is working if(advanced && SPU == SPU_core) SPU_MixAudio_Advanced(SPU, length); else { //non-advanced mode for(int i=0;i<16;i++) { channel_struct *chan = &SPU->channels[i]; if (chan->status != CHANSTAT_PLAY) continue; SPU->bufpos = 0; SPU->buflength = length; // Mix audio switch(chan->format) { case 0: ___SPU_ChanUpdate<0>(true, SPU, chan); break; case 1: ___SPU_ChanUpdate<1>(true, SPU, chan); break; case 2: ___SPU_ChanUpdate<2>(true, SPU, chan); break; case 3: ___SPU_ChanUpdate<3>(true, SPU, chan); break; } } } // convert from 32-bit->16-bit for (int i = 0; i < length*2; i++) { // Apply Master Volume SPU->sndbuf[i] = SPU->sndbuf[i] * vol / 127; s16 outsample = MinMax(SPU->sndbuf[i],-0x8000,0x7FFF); SPU->outbuf[SPU->outbufptr++] = outsample; } } ////////////////////////////////////////////////////////////////////////////// //emulates one hline of the cpu core. //this will produce a variable number of samples, calculated to keep a 44100hz output //in sync with the emulator framerate int spu_core_samples = 0; void SPU_Emulate_core() { samples += samples_per_hline; spu_core_samples = (int)(samples); samples -= spu_core_samples; SPU_MixAudio(SPU_core, spu_core_samples); } void SPU_Emulate_user(bool mix) { // FIXME: sometimes outbufptr > 735*2, figure out what to do with the extra samples audio_batch_cb(SPU_core->outbuf, 735); memset(SPU_core->outbuf, 0, 735 * 2 * sizeof(s16)); SPU_core->outbufptr = 0; } void spu_savestate(EMUFILE* os) { //version write32le(6,os); SPU_struct *spu = SPU_core; for(int j=0;j<16;j++) { channel_struct &chan = spu->channels[j]; write32le(chan.num,os); write8le(chan.vol,os); write8le(chan.volumeDiv,os); write8le(chan.hold,os); write8le(chan.pan,os); write8le(chan.waveduty,os); write8le(chan.repeat,os); write8le(chan.format,os); write8le(chan.status,os); write32le(chan.addr,os); write16le(chan.timer,os); write16le(chan.loopstart,os); write32le(chan.length,os); write64le(double_to_u64(chan.sampcnt),os); write64le(double_to_u64(chan.sampinc),os); write32le(chan.lastsampcnt,os); write16le(chan.pcm16b,os); write16le(chan.pcm16b_last,os); write32le(chan.index,os); write16le(chan.x,os); write16le(chan.psgnoise_last,os); write8le(chan.keyon,os); } write64le(double_to_u64(samples),os); write8le(spu->regs.mastervol,os); write8le(spu->regs.ctl_left,os); write8le(spu->regs.ctl_right,os); write8le(spu->regs.ctl_ch1bypass,os); write8le(spu->regs.ctl_ch3bypass,os); write8le(spu->regs.masteren,os); write16le(spu->regs.soundbias,os); for(int i=0;i<2;i++) { write8le(spu->regs.cap[i].add,os); write8le(spu->regs.cap[i].source,os); write8le(spu->regs.cap[i].oneshot,os); write8le(spu->regs.cap[i].bits8,os); write8le(spu->regs.cap[i].active,os); write32le(spu->regs.cap[i].dad,os); write16le(spu->regs.cap[i].len,os); write8le(spu->regs.cap[i].runtime.running,os); write32le(spu->regs.cap[i].runtime.curdad,os); write32le(spu->regs.cap[i].runtime.maxdad,os); write_double_le(spu->regs.cap[i].runtime.sampcnt,os); } for(int i=0;i<2;i++) spu->regs.cap[i].runtime.fifo.save(os); } bool spu_loadstate(EMUFILE* is, int size) { u64 temp64; //read version u32 version; if(read32le(&version,is) != 1) return false; SPU_struct *spu = SPU_core; reconstruct(&SPU_core->regs); for(int j=0;j<16;j++) { channel_struct &chan = spu->channels[j]; read32le(&chan.num,is); read8le(&chan.vol,is); read8le(&chan.volumeDiv,is); if (chan.volumeDiv == 4) chan.volumeDiv = 3; read8le(&chan.hold,is); read8le(&chan.pan,is); read8le(&chan.waveduty,is); read8le(&chan.repeat,is); read8le(&chan.format,is); read8le(&chan.status,is); read32le(&chan.addr,is); read16le(&chan.timer,is); read16le(&chan.loopstart,is); read32le(&chan.length,is); chan.totlength = chan.length + chan.loopstart; chan.double_totlength_shifted = (double)(chan.totlength << format_shift[chan.format]); //printf("%f\n",chan.double_totlength_shifted); if(version >= 2) { read64le(&temp64,is); chan.sampcnt = u64_to_double(temp64); read64le(&temp64,is); chan.sampinc = u64_to_double(temp64); } else { read32le((u32*)&chan.sampcnt,is); read32le((u32*)&chan.sampinc,is); } read32le(&chan.lastsampcnt,is); read16le(&chan.pcm16b,is); read16le(&chan.pcm16b_last,is); read32le(&chan.index,is); read16le(&chan.x,is); read16le(&chan.psgnoise_last,is); if(version>=4) read8le(&chan.keyon,is); //hopefully trigger a recovery of the adpcm looping system chan.loop_index = K_ADPCM_LOOPING_RECOVERY_INDEX; } if(version>=2) { read64le(&temp64,is); samples = u64_to_double(temp64); } if(version>=4) { read8le(&spu->regs.mastervol,is); read8le(&spu->regs.ctl_left,is); read8le(&spu->regs.ctl_right,is); read8le(&spu->regs.ctl_ch1bypass,is); read8le(&spu->regs.ctl_ch3bypass,is); read8le(&spu->regs.masteren,is); read16le(&spu->regs.soundbias,is); } if(version>=5) { for(int i=0;i<2;i++) { read8le(&spu->regs.cap[i].add,is); read8le(&spu->regs.cap[i].source,is); read8le(&spu->regs.cap[i].oneshot,is); read8le(&spu->regs.cap[i].bits8,is); read8le(&spu->regs.cap[i].active,is); read32le(&spu->regs.cap[i].dad,is); read16le(&spu->regs.cap[i].len,is); read8le(&spu->regs.cap[i].runtime.running,is); read32le(&spu->regs.cap[i].runtime.curdad,is); read32le(&spu->regs.cap[i].runtime.maxdad,is); read_double_le(&spu->regs.cap[i].runtime.sampcnt,is); } } if(version>=6) for(int i=0;i<2;i++) spu->regs.cap[i].runtime.fifo.load(is); else for(int i=0;i<2;i++) spu->regs.cap[i].runtime.fifo.reset(); //older versions didnt store a mastervol; //we must reload this or else games will start silent if(version<4) { spu->regs.mastervol = T1ReadByte(MMU.ARM7_REG, 0x500) & 0x7F; spu->regs.masteren = BIT15(T1ReadWord(MMU.ARM7_REG, 0x500)); } //copy the core spu (the more accurate) to the user spu SPU_CloneUser(); return true; } desmume/src/libretro-common/utils/crc32.c000664 001750 001750 00000001444 12755534123 021472 0ustar00sergiosergio000000 000000 /* gcc -O3 -o crc32 crc32.c -lz */ #include #include #include #include int main(int argc, const char* argv[]) { if (argc != 2 ) { fprintf( stderr, "Usage: crc32 \n" ); return 1; } FILE *file = fopen(argv[1], "rb"); if (file) { uLong crc = crc32(0L, Z_NULL, 0 ); for (;;) { Bytef buffer[16384]; int numread = fread((void*)buffer, 1, sizeof(buffer), file); if (numread > 0) crc = crc32( crc, buffer, numread ); else break; } fclose(file); printf("%08x\n", crc); return 0; } fprintf(stderr, "Error opening input file: %s\n", strerror(errno)); return 1; } desmume/src/libretro-common/rthreads/rsemaphore.c000664 001750 001750 00000006116 12755534123 023400 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2016 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (rsemaphore.c). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifdef __unix__ #define _POSIX_C_SOURCE 199309 #endif #include #include #include struct ssem { int value; int wakeups; slock_t *mutex; scond_t *cond; }; ssem_t *ssem_new(int value) { ssem_t *semaphore = (ssem_t*)calloc(1, sizeof(*semaphore)); if (!semaphore) goto error; semaphore->value = value; semaphore->wakeups = 0; semaphore->mutex = slock_new(); if (!semaphore->mutex) goto error; semaphore->cond = scond_new(); if (!semaphore->cond) goto error; return semaphore; error: if (semaphore) { if (semaphore->mutex) slock_free(semaphore->mutex); semaphore->mutex = NULL; free((void*)semaphore); } return NULL; } void ssem_free(ssem_t *semaphore) { if (!semaphore) return; scond_free(semaphore->cond); slock_free(semaphore->mutex); free((void*)semaphore); } int ssem_get(ssem_t *semaphore) { int val = 0; if (!semaphore) return 0; slock_lock(semaphore->mutex); val = semaphore->value; slock_unlock(semaphore->mutex); return val; } void ssem_wait(ssem_t *semaphore) { if (!semaphore) return; slock_lock(semaphore->mutex); semaphore->value--; if (semaphore->value < 0) { do { scond_wait(semaphore->cond, semaphore->mutex); }while (semaphore->wakeups < 1); semaphore->wakeups--; } slock_unlock(semaphore->mutex); } void ssem_signal(ssem_t *semaphore) { if (!semaphore) return; slock_lock(semaphore->mutex); semaphore->value++; if (semaphore->value <= 0) { semaphore->wakeups++; scond_signal(semaphore->cond); } slock_unlock(semaphore->mutex); } desmume/src/libretro-common/include/formats/jsonsax.h000664 001750 001750 00000005023 12755534123 024203 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2016 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (jsonsax.h). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef __LIBRETRO_SDK_FORMAT_JSONSAX_H__ #define __LIBRETRO_SDK_FORMAT_JSONSAX_H__ #include enum { JSONSAX_OK = 0, JSONSAX_INTERRUPTED, JSONSAX_MISSING_KEY, JSONSAX_UNTERMINATED_KEY, JSONSAX_MISSING_VALUE, JSONSAX_UNTERMINATED_OBJECT, JSONSAX_UNTERMINATED_ARRAY, JSONSAX_UNTERMINATED_STRING, JSONSAX_INVALID_VALUE }; #ifdef JSONSAX_ERRORS extern const char* jsonsax_errors[]; #endif typedef struct { int ( *start_document )( void* userdata ); int ( *end_document )( void* userdata ); int ( *start_object )( void* userdata ); int ( *end_object )( void* userdata ); int ( *start_array )( void* userdata ); int ( *end_array )( void* userdata ); int ( *key )( void* userdata, const char* name, size_t length ); int ( *index )( void* userdata, unsigned int index ); int ( *string )( void* userdata, const char* string, size_t length ); int ( *number )( void* userdata, const char* number, size_t length ); int ( *boolean )( void* userdata, int istrue ); int ( *null )( void* userdata ); } jsonsax_handlers_t; int jsonsax_parse( const char* json, const jsonsax_handlers_t* handlers, void* userdata ); #endif /* __LIBRETRO_SDK_FORMAT_JSONSAX_H__ */ desmume/src/readwrite.cpp000664 001750 001750 00000005157 12755534123 016641 0ustar00sergiosergio000000 000000 /* Copyright (C) 2006-2015 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the this software. If not, see . */ #include "readwrite.h" #include "emufile.h" //well. just for the sake of consistency int write8le(u8 b, EMUFILE*os) { os->fwrite((char*)&b,1); return 1; } //well. just for the sake of consistency int read8le(u8 *Bufo, EMUFILE*is) { if(is->_fread((char*)Bufo,1) != 1) return 0; return 1; } ///writes a little endian 16bit value to the specified file int write16le(u16 b, EMUFILE *fp) { u8 s[2]; s[0]=(u8)b; s[1]=(u8)(b>>8); fp->fwrite(s,2); return 2; } ///writes a little endian 32bit value to the specified file int write32le(u32 b, EMUFILE *fp) { u8 s[4]; s[0]=(u8)b; s[1]=(u8)(b>>8); s[2]=(u8)(b>>16); s[3]=(u8)(b>>24); fp->fwrite(s,4); return 4; } void writebool(bool b, EMUFILE* os) { write32le(b?1:0,os); } int write64le(u64 b, EMUFILE* os) { u8 s[8]; s[0]=(u8)b; s[1]=(u8)(b>>8); s[2]=(u8)(b>>16); s[3]=(u8)(b>>24); s[4]=(u8)(b>>32); s[5]=(u8)(b>>40); s[6]=(u8)(b>>48); s[7]=(u8)(b>>56); os->fwrite((char*)&s,8); return 8; } int read32le(u32 *Bufo, EMUFILE *fp) { u32 buf = 0; if(fp->_fread(&buf,4)<4) return 0; *Bufo = LE_TO_LOCAL_32(buf); return 1; } int read16le(u16 *Bufo, EMUFILE *is) { u16 buf; if(is->_fread((char*)&buf,2) != 2) return 0; *Bufo = LE_TO_LOCAL_16(buf); return 1; } int read64le(u64 *Bufo, EMUFILE *is) { u64 buf; if(is->_fread((char*)&buf,8) != 8) return 0; *Bufo = LE_TO_LOCAL_64(buf); return 1; } static int read32le(u32 *Bufo, std::istream *is) { u32 buf; if(is->read((char*)&buf,4).gcount() != 4) return 0; *Bufo = LE_TO_LOCAL_32(buf); return 1; } int readbool(bool *b, EMUFILE* is) { u32 temp; int ret = read32le(&temp,is); *b = temp!=0; return ret; } int readbuffer(std::vector &vec, EMUFILE* is) { u32 size; if(read32le(&size,is) != 1) return 0; vec.resize(size); if(size>0) is->fread((char*)&vec[0],size); return 1; } int writebuffer(std::vector& vec, EMUFILE* os) { u32 size = vec.size(); write32le(size,os); if(size>0) os->fwrite((char*)&vec[0],size); return 1; } desmume/src/libretro-common/file/retro_stat.c000664 001750 001750 00000012354 12755534123 022525 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2016 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (retro_stat.c). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include #include #include #include #if defined(_WIN32) #ifdef _MSC_VER #define setmode _setmode #endif #ifdef _XBOX #include #define INVALID_FILE_ATTRIBUTES -1 #else #include #include #include #include #endif #elif defined(VITA) #define SCE_ERROR_ERRNO_EEXIST 0x80010011 #include #include #include #else #include #include #include #endif #if defined(PSP) #include #endif #ifdef __HAIKU__ #include #endif #if defined(__CELLOS_LV2__) #include #endif #if defined(VITA) #define FIO_S_ISDIR SCE_S_ISDIR #endif #if (defined(__CELLOS_LV2__) && !defined(__PSL1GHT__)) || defined(__QNX__) || defined(PSP) #include /* stat() is defined here */ #endif #include #include enum stat_mode { IS_DIRECTORY = 0, IS_CHARACTER_SPECIAL, IS_VALID }; static bool path_stat(const char *path, enum stat_mode mode, int32_t *size) { #if defined(VITA) || defined(PSP) SceIoStat buf; char *tmp = strdup(path); size_t len = strlen(tmp); if (tmp[len-1] == '/') tmp[len-1]='\0'; if (sceIoGetstat(tmp, &buf) < 0) { free(tmp); return false; } free(tmp); #elif defined(__CELLOS_LV2__) CellFsStat buf; if (cellFsStat(path, &buf) < 0) return false; #elif defined(_WIN32) WIN32_FILE_ATTRIBUTE_DATA file_info; GET_FILEEX_INFO_LEVELS fInfoLevelId = GetFileExInfoStandard; DWORD ret = GetFileAttributesEx(path, fInfoLevelId, &file_info); if (ret == 0) return false; #else struct stat buf; if (stat(path, &buf) < 0) return false; #endif #if defined(_WIN32) if (size) *size = file_info.nFileSizeLow; #else if (size) *size = buf.st_size; #endif switch (mode) { case IS_DIRECTORY: #if defined(VITA) || defined(PSP) return FIO_S_ISDIR(buf.st_mode); #elif defined(__CELLOS_LV2__) return ((buf.st_mode & S_IFMT) == S_IFDIR); #elif defined(_WIN32) return (file_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY); #else return S_ISDIR(buf.st_mode); #endif case IS_CHARACTER_SPECIAL: #if defined(VITA) || defined(PSP) || defined(__CELLOS_LV2__) || defined(_WIN32) return false; #else return S_ISCHR(buf.st_mode); #endif case IS_VALID: return true; } return false; } /** * path_is_directory: * @path : path * * Checks if path is a directory. * * Returns: true (1) if path is a directory, otherwise false (0). */ bool path_is_directory(const char *path) { return path_stat(path, IS_DIRECTORY, NULL); } bool path_is_character_special(const char *path) { return path_stat(path, IS_CHARACTER_SPECIAL, NULL); } bool path_is_valid(const char *path) { return path_stat(path, IS_VALID, NULL); } int32_t path_get_size(const char *path) { int32_t filesize = 0; if (path_stat(path, IS_VALID, &filesize)) return filesize; return -1; } /** * path_mkdir_norecurse: * @dir : directory * * Create directory on filesystem. * * Returns: true (1) if directory could be created, otherwise false (0). **/ bool mkdir_norecurse(const char *dir) { int ret; #if defined(_WIN32) ret = _mkdir(dir); #elif defined(IOS) ret = mkdir(dir, 0755); #elif defined(VITA) || defined(PSP) ret = sceIoMkdir(dir, 0777); #else ret = mkdir(dir, 0750); #endif /* Don't treat this as an error. */ #if defined(VITA) if ((ret == SCE_ERROR_ERRNO_EEXIST) && path_is_directory(dir)) ret = 0; #elif defined(PSP) || defined(_3DS) if ((ret == -1) && path_is_directory(dir)) ret = 0; #else if (ret < 0 && errno == EEXIST && path_is_directory(dir)) ret = 0; #endif if (ret < 0) printf("mkdir(%s) error: %s.\n", dir, strerror(errno)); return ret == 0; } desmume/src/libretro-common/rthreads/gx_pthread.h000664 001750 001750 00000011456 12755534123 023370 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2016 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (gx_pthread.h). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef _GX_PTHREAD_WRAP_GX_ #define _GX_PTHREAD_WRAP_GX_ #include #include #include #include #ifndef OSThread #define OSThread lwp_t #endif #ifndef OSCond #define OSCond lwpq_t #endif #ifndef OSThreadQueue #define OSThreadQueue lwpq_t #endif #ifndef OSInitMutex #define OSInitMutex(mutex) LWP_MutexInit(mutex, 0) #endif #ifndef OSLockMutex #define OSLockMutex(mutex) LWP_MutexLock(mutex) #endif #ifndef OSUnlockMutex #define OSUnlockMutex(mutex) LWP_MutexUnlock(mutex) #endif #ifndef OSTryLockMutex #define OSTryLockMutex(mutex) LWP_MutexTryLock(mutex) #endif #ifndef OSInitCond #define OSInitCond(cond) LWP_CondInit(cond) #endif #ifndef OSWaitCond #define OSWaitCond(cond, mutex) LWP_CondWait(cond, mutex) #endif #ifndef OSInitThreadQueue #define OSInitThreadQueue(queue) LWP_InitQueue(queue) #endif #ifndef OSSleepThread #define OSSleepThread(queue) LWP_ThreadSleep(queue) #endif #ifndef OSJoinThread #define OSJoinThread(thread, val) LWP_JoinThread(thread, val) #endif #ifndef OSCreateThread #define OSCreateThread(thread, func, intarg, ptrarg, stackbase, stacksize, priority, attrs) LWP_CreateThread(thread, func, ptrarg, stackbase, stacksize, priority) #endif #define STACKSIZE (8 * 1024) typedef OSThread pthread_t; typedef mutex_t pthread_mutex_t; typedef void* pthread_mutexattr_t; typedef int pthread_attr_t; typedef OSCond pthread_cond_t; typedef OSCond pthread_condattr_t; static INLINE int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void*), void *arg) { *thread = 0; return OSCreateThread(thread, start_routine, 0 /* unused */, arg, 0, STACKSIZE, 64, 0 /* unused */); } static INLINE pthread_t pthread_self(void) { /* zero 20-mar-2016: untested */ return LWP_GetSelf(); } static INLINE int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr) { return OSInitMutex(mutex); } static INLINE int pthread_mutex_destroy(pthread_mutex_t *mutex) { return LWP_MutexDestroy(*mutex); } static INLINE int pthread_mutex_lock(pthread_mutex_t *mutex) { return OSLockMutex(*mutex); } static INLINE int pthread_mutex_unlock(pthread_mutex_t *mutex) { return OSUnlockMutex(*mutex); } static INLINE void pthread_exit(void *retval) { /* FIXME: No LWP equivalent for this? */ (void)retval; } static INLINE int pthread_detach(pthread_t thread) { /* FIXME: pthread_detach equivalent missing? */ (void)thread; return 0; } static INLINE int pthread_join(pthread_t thread, void **retval) { return OSJoinThread(thread, retval); } static INLINE int pthread_mutex_trylock(pthread_mutex_t *mutex) { return OSTryLockMutex(*mutex); } static INLINE int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex) { return OSWaitCond(*cond, *mutex); } static INLINE int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime) { return LWP_CondTimedWait(*cond, *mutex, abstime); } static INLINE int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr) { return OSInitCond(cond); } static INLINE int pthread_cond_signal(pthread_cond_t *cond) { return LWP_CondSignal(*cond); } static INLINE int pthread_cond_broadcast(pthread_cond_t *cond) { return LWP_CondBroadcast(*cond); } static INLINE int pthread_cond_destroy(pthread_cond_t *cond) { return LWP_CondDestroy(*cond); } extern int pthread_equal(pthread_t t1, pthread_t t2); #endif desmume/src/utils/decrypt/decrypt.h000664 001750 001750 00000002505 12755534123 020576 0ustar00sergiosergio000000 000000 /* decrypt.h - this file is part of DeSmuME * * Copyright (C) 2006 Rafael Vuijk * * This file is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This file is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ #ifndef _DECRYPT_H_ #define _DECRYPT_H_ #include "../../types.h" extern const unsigned char arm7_key[]; //decrypts the secure area of a rom (or does nothing if it is already decrypted) bool DecryptSecureArea(u8 *romheader, u8 *secure); //encrypts the secure area of a rom (or does nothing if it is already encrypted) bool EncryptSecureArea(u8 *romheader, u8 *secure); //since we have rom-type detection heuristics here, this module is responsible for checking whether a rom is valid bool CheckValidRom(u8 *header, u8 *secure); #endif desmume/src/utils/AsmJit/x86/x86compileritem.cpp000664 001750 001750 00000151270 12755534123 022664 0ustar00sergiosergio000000 000000 // [AsmJit] // Complete JIT Assembler for C++ Language. // // [License] // Zlib - See COPYING file in this package. #define ASMJIT_EXPORTS // [Dependencies - AsmJit] #include "../core/intutil.h" #include "../core/stringutil.h" #include "../x86/x86compiler.h" #include "../x86/x86compilercontext.h" #include "../x86/x86compilerfunc.h" #include "../x86/x86compileritem.h" #include "../x86/x86util.h" // [Api-Begin] #include "../core/apibegin.h" namespace AsmJit { // ============================================================================ // [AsmJit::X86CompilerAlign - Construction / Destruction] // ============================================================================ X86CompilerAlign::X86CompilerAlign(X86Compiler* x86Compiler, uint32_t size) : CompilerAlign(x86Compiler, size) { } X86CompilerAlign::~X86CompilerAlign() { } // ============================================================================ // [AsmJit::X86CompilerAlign - Interface] // ============================================================================ void X86CompilerAlign::emit(Assembler& a) { X86Assembler& x86Asm = static_cast(a); x86Asm.align(_size); } // ============================================================================ // [AsmJit::X86CompilerTarget - Construction / Destruction] // ============================================================================ X86CompilerTarget::X86CompilerTarget(X86Compiler* c, const Label& label) : CompilerTarget(c, label) { } X86CompilerTarget::~X86CompilerTarget() { } // ============================================================================ // [AsmJit::X86CompilerTarget - Interface] // ============================================================================ static X86CompilerTarget* X86CompilerTarget_removeUnreachableItems(X86CompilerTarget* target) { CompilerItem* prev = target->getPrev(); CompilerItem* item = target->getNext(); ASMJIT_ASSERT(prev != NULL); ASMJIT_ASSERT(item != NULL); for (;;) { CompilerItem* next = item->getNext(); ASMJIT_ASSERT(next != NULL); if (item->getType() == kCompilerItemTarget) break; item->_prev = NULL; item->_next = NULL; item->_isUnreachable = true; item = next; } target->_prev = NULL; target->_next = NULL; target->_isTranslated = true; prev->_next = item; item->_prev = prev; return static_cast(item); } void X86CompilerTarget::prepare(CompilerContext& cc) { X86CompilerContext& x86Context = static_cast(cc); _offset = x86Context._currentOffset++; } CompilerItem* X86CompilerTarget::translate(CompilerContext& cc) { X86CompilerContext& x86Context = static_cast(cc); // If this X86CompilerTarget was already translated, it's needed to change // the current state and return NULL to tell CompilerContext to process next // untranslated item. if (_isTranslated) { x86Context._restoreState(getState()); return NULL; } if (x86Context._isUnreachable) { // If the context has "isUnreachable" flag set and there is no state then // it means that this code will be never called. This is a problem, because // we are unable to assign a state to current location so we can't allocate // registers for variables used inside. So instead of doing anything wrong // we remove the unreachable code. if (_state == NULL) return X86CompilerTarget_removeUnreachableItems(this); // Assign state to the compiler context. x86Context._isUnreachable = 0; x86Context._assignState(getState()); } else { _state = x86Context._saveState(); } return translated(); } void X86CompilerTarget::emit(Assembler& a) { X86Assembler& x86Asm = static_cast(a); x86Asm.bind(_label); } // ============================================================================ // [AsmJit::X86CompilerHint - Construction / Destruction] // ============================================================================ X86CompilerHint::X86CompilerHint(X86Compiler* compiler, X86CompilerVar* var, uint32_t hintId, uint32_t hintValue) : CompilerHint(compiler, var, hintId, hintValue) { } X86CompilerHint::~X86CompilerHint() { } // ============================================================================ // [AsmJit::X86CompilerHint - Interface] // ============================================================================ void X86CompilerHint::prepare(CompilerContext& cc) { X86CompilerContext& x86Context = static_cast(cc); X86CompilerVar* var = getVar(); _offset = x86Context._currentOffset; // First item (begin of variable scope). if (var->firstItem == NULL) var->firstItem = this; // Last item (end of variable scope). CompilerItem* oldLast = var->lastItem; var->lastItem = this; switch (_hintId) { case kVarHintAlloc: case kVarHintSpill: case kVarHintSave: if (!x86Context._isActive(var)) x86Context._addActive(var); break; case kVarHintSaveAndUnuse: if (!x86Context._isActive(var)) x86Context._addActive(var); break; case kVarHintUnuse: if (oldLast) oldLast->_tryUnuseVar(var); break; } } CompilerItem* X86CompilerHint::translate(CompilerContext& cc) { X86CompilerContext& x86Context = static_cast(cc); X86CompilerVar* var = getVar(); switch (_hintId) { case kVarHintAlloc: x86Context.allocVar(var, _hintValue, kVarAllocRead); break; case kVarHintSpill: if (var->state == kVarStateReg) x86Context.spillVar(var); break; case kVarHintSave: case kVarHintSaveAndUnuse: if (var->state == kVarStateReg && var->changed) { x86Context.emitSaveVar(var, var->regIndex); var->changed = false; } if (_hintId == kVarHintSaveAndUnuse) goto _Unuse; break; case kVarHintUnuse: _Unuse: x86Context.unuseVar(var, kVarStateUnused); goto _End; } x86Context._unuseVarOnEndOfScope(this, var); _End: return translated(); } // ============================================================================ // [AsmJit::X86CompilerHint - Misc] // ============================================================================ int X86CompilerHint::getMaxSize() const { // Compiler hint is NOP, but it can generate other items which can do // something - in such more items are added into the stream so we don't need // to worry about this. return 0; } // ============================================================================ // [AsmJit::X86CompilerInst - Construction / Destruction] // ============================================================================ X86CompilerInst::X86CompilerInst(X86Compiler* x86Compiler, uint32_t code, Operand* opData, uint32_t opCount) : CompilerInst(x86Compiler, code, opData, opCount) { uint32_t i; _memOp = NULL; _vars = NULL; _variablesCount = 0; for (i = 0; i < opCount; i++) { if (_operands[i].isMem()) { _memOp = reinterpret_cast(&_operands[i]); break; } } const X86InstInfo* info = &x86InstInfo[_code]; if (info->isSpecial()) setInstFlag(kX86CompilerInstFlagIsSpecial); if (info->isFpu()) setInstFlag(kX86CompilerInstFlagIsFpu); if (isSpecial()) { // ${SPECIAL_INSTRUCTION_HANDLING_BEGIN} switch (_code) { case kX86InstCpuId: // Special... break; case kX86InstCbw: case kX86InstCdq: case kX86InstCdqe: case kX86InstCwd: case kX86InstCwde: case kX86InstCqo: // Special... break; case kX86InstCmpXCHG: case kX86InstCmpXCHG8B: #if defined(ASMJIT_X64) case kX86InstCmpXCHG16B: #endif // ASMJIT_X64 // Special... break; #if defined(ASMJIT_X86) case kX86InstDaa: case kX86InstDas: // Special... break; #endif // ASMJIT_X86 case kX86InstIMul: switch (_operandsCount) { case 2: // IMUL dst, src is not special instruction. clearInstFlag(kX86CompilerInstFlagIsSpecial); break; case 3: // Only IMUL dst_hi, dst_lo, reg/mem is special, all others don't. if (!(_operands[0].isVar() && _operands[1].isVar() && _operands[2].isVarMem())) clearInstFlag(kX86CompilerInstFlagIsSpecial); break; } break; case kX86InstMul: case kX86InstIDiv: case kX86InstDiv: // Special... break; case kX86InstMovPtr: // Special... break; case kX86InstLahf: case kX86InstSahf: // Special... break; case kX86InstMaskMovQ: case kX86InstMaskMovDQU: // Special... break; case kX86InstEnter: case kX86InstLeave: // Special... break; case kX86InstRet: // Special... break; case kX86InstMonitor: case kX86InstMWait: // Special... break; case kX86InstPop: case kX86InstPopAD: case kX86InstPopFD: case kX86InstPopFQ: // Special... break; case kX86InstPush: case kX86InstPushAD: case kX86InstPushFD: case kX86InstPushFQ: // Special... break; case kX86InstRcl: case kX86InstRcr: case kX86InstRol: case kX86InstRor: case kX86InstSal: case kX86InstSar: case kX86InstShl: case kX86InstShr: // Rot instruction is special only if last operand is variable (register). if (!_operands[1].isVar()) clearInstFlag(kX86CompilerInstFlagIsSpecial); break; case kX86InstShld: case kX86InstShrd: // Shld/Shrd instruction is special only if last operand is variable (register). if (!_operands[2].isVar()) clearInstFlag(kX86CompilerInstFlagIsSpecial); break; case kX86InstRdtsc: case kX86InstRdtscP: // Special... break; case kX86InstRepLodSB: case kX86InstRepLodSD: case kX86InstRepLodSQ: case kX86InstRepLodSW: case kX86InstRepMovSB: case kX86InstRepMovSD: case kX86InstRepMovSQ: case kX86InstRepMovSW: case kX86InstRepStoSB: case kX86InstRepStoSD: case kX86InstRepStoSQ: case kX86InstRepStoSW: case kX86InstRepECmpSB: case kX86InstRepECmpSD: case kX86InstRepECmpSQ: case kX86InstRepECmpSW: case kX86InstRepEScaSB: case kX86InstRepEScaSD: case kX86InstRepEScaSQ: case kX86InstRepEScaSW: case kX86InstRepNECmpSB: case kX86InstRepNECmpSD: case kX86InstRepNECmpSQ: case kX86InstRepNECmpSW: case kX86InstRepNEScaSB: case kX86InstRepNEScaSD: case kX86InstRepNEScaSQ: case kX86InstRepNEScaSW: // Special... break; default: ASMJIT_ASSERT(0); } // ${SPECIAL_INSTRUCTION_HANDLING_END} } } X86CompilerInst::~X86CompilerInst() { } // ============================================================================ // [AsmJit::X86CompilerInst - Interface] // ============================================================================ void X86CompilerInst::prepare(CompilerContext& cc) { X86CompilerContext& x86Context = static_cast(cc); X86Compiler* x86Compiler = getCompiler(); #define __GET_VARIABLE(__vardata__) \ { \ X86CompilerVar* _candidate = __vardata__; \ \ for (var = cur; ;) \ { \ if (var == _vars) \ { \ var = cur++; \ var->vdata = _candidate; \ var->vflags = 0; \ var->regMask = 0xFFFFFFFF; \ break; \ } \ \ var--; \ \ if (var->vdata == _candidate) \ { \ break; \ } \ } \ \ ASMJIT_ASSERT(var != NULL); \ } _offset = x86Context._currentOffset; const X86InstInfo* id = &x86InstInfo[_code]; uint32_t i, len = _operandsCount; uint32_t variablesCount = 0; for (i = 0; i < len; i++) { Operand& o = _operands[i]; if (o.isVar()) { ASMJIT_ASSERT(o.getId() != kInvalidValue); X86CompilerVar* vdata = x86Compiler->_getVar(o.getId()); ASMJIT_ASSERT(vdata != NULL); if (reinterpret_cast(&o)->isGpVar()) { if (reinterpret_cast(&o)->isGpbLo()) { setInstFlag(kX86CompilerInstFlagIsGpbLoUsed); vdata->regGpbLoCount++; }; if (reinterpret_cast(&o)->isGpbHi()) { setInstFlag(kX86CompilerInstFlagIsGpbHiUsed); vdata->regGpbHiCount++; }; } if (vdata->workOffset != _offset) { if (!x86Context._isActive(vdata)) x86Context._addActive(vdata); vdata->workOffset = _offset; variablesCount++; } } else if (o.isMem()) { if ((o.getId() & kOperandIdTypeMask) == kOperandIdTypeVar) { X86CompilerVar* vdata = x86Compiler->_getVar(o.getId()); ASMJIT_ASSERT(vdata != NULL); x86Context._markMemoryUsed(vdata); if (vdata->workOffset != _offset) { if (!x86Context._isActive(vdata)) x86Context._addActive(vdata); vdata->workOffset = _offset; variablesCount++; } } else if ((o._mem.base & kOperandIdTypeMask) == kOperandIdTypeVar) { X86CompilerVar* vdata = x86Compiler->_getVar(o._mem.base); ASMJIT_ASSERT(vdata != NULL); if (vdata->workOffset != _offset) { if (!x86Context._isActive(vdata)) x86Context._addActive(vdata); vdata->workOffset = _offset; variablesCount++; } } if ((o._mem.index & kOperandIdTypeMask) == kOperandIdTypeVar) { X86CompilerVar* vdata = x86Compiler->_getVar(o._mem.index); ASMJIT_ASSERT(vdata != NULL); if (vdata->workOffset != _offset) { if (!x86Context._isActive(vdata)) x86Context._addActive(vdata); vdata->workOffset = _offset; variablesCount++; } } } } if (!variablesCount) { x86Context._currentOffset++; return; } _vars = reinterpret_cast(x86Compiler->getZoneMemory().alloc(sizeof(VarAllocRecord) * variablesCount)); if (_vars == NULL) { x86Compiler->setError(kErrorNoHeapMemory); x86Context._currentOffset++; return; } _variablesCount = variablesCount; VarAllocRecord* cur = _vars; VarAllocRecord* var = NULL; bool _isGpbUsed = hasInstFlag(kX86CompilerInstFlagIsGpbLoUsed) | hasInstFlag(kX86CompilerInstFlagIsGpbHiUsed) ; uint32_t gpRestrictMask = IntUtil::maskUpToIndex(kX86RegNumGp); #if defined(ASMJIT_X64) if (hasInstFlag(kX86CompilerInstFlagIsGpbHiUsed)) { gpRestrictMask &= IntUtil::maskFromIndex(kX86RegIndexEax) | IntUtil::maskFromIndex(kX86RegIndexEbx) | IntUtil::maskFromIndex(kX86RegIndexEcx) | IntUtil::maskFromIndex(kX86RegIndexEdx) | IntUtil::maskFromIndex(kX86RegIndexEbp) | IntUtil::maskFromIndex(kX86RegIndexEsi) | IntUtil::maskFromIndex(kX86RegIndexEdi) ; } #endif // ASMJIT_X64 for (i = 0; i < len; i++) { Operand& o = _operands[i]; if (o.isVar()) { X86CompilerVar* vdata = x86Compiler->_getVar(o.getId()); ASMJIT_ASSERT(vdata != NULL); __GET_VARIABLE(vdata) var->vflags |= kVarAllocRegister; if (_isGpbUsed) { #if defined(ASMJIT_X86) if (reinterpret_cast(&o)->isGpb()) { var->regMask &= IntUtil::maskFromIndex(kX86RegIndexEax) | IntUtil::maskFromIndex(kX86RegIndexEbx) | IntUtil::maskFromIndex(kX86RegIndexEcx) | IntUtil::maskFromIndex(kX86RegIndexEdx) ; } #else // Restrict all BYTE registers to RAX/RBX/RCX/RDX if HI BYTE register // is used (REX prefix makes HI BYTE addressing unencodable). if (hasInstFlag(kX86CompilerInstFlagIsGpbHiUsed)) { if (reinterpret_cast(&o)->isGpb()) { var->regMask &= IntUtil::maskFromIndex(kX86RegIndexEax) | IntUtil::maskFromIndex(kX86RegIndexEbx) | IntUtil::maskFromIndex(kX86RegIndexEcx) | IntUtil::maskFromIndex(kX86RegIndexEdx) ; } } #endif // ASMJIT_X86/X64 } if (isSpecial()) { // ${SPECIAL_INSTRUCTION_HANDLING_BEGIN} switch (_code) { case kX86InstCpuId: switch (i) { case 0: vdata->regRwCount++; var->vflags |= kVarAllocReadWrite | kVarAllocSpecial; var->regMask = IntUtil::maskFromIndex(kX86RegIndexEax); gpRestrictMask &= ~var->regMask; break; case 1: vdata->regWriteCount++; var->vflags |= kVarAllocWrite | kVarAllocSpecial; var->regMask = IntUtil::maskFromIndex(kX86RegIndexEbx); gpRestrictMask &= ~var->regMask; break; case 2: vdata->regWriteCount++; var->vflags |= kVarAllocWrite | kVarAllocSpecial; var->regMask = IntUtil::maskFromIndex(kX86RegIndexEcx); gpRestrictMask &= ~var->regMask; break; case 3: vdata->regWriteCount++; var->vflags |= kVarAllocWrite | kVarAllocSpecial; var->regMask = IntUtil::maskFromIndex(kX86RegIndexEdx); gpRestrictMask &= ~var->regMask; break; default: ASMJIT_ASSERT(0); } break; case kX86InstCbw: case kX86InstCdqe: case kX86InstCwde: switch (i) { case 0: vdata->regRwCount++; var->vflags |= kVarAllocReadWrite | kVarAllocSpecial; var->regMask = IntUtil::maskFromIndex(kX86RegIndexEax); gpRestrictMask &= ~var->regMask; break; default: ASMJIT_ASSERT(0); } break; case kX86InstCdq: case kX86InstCwd: case kX86InstCqo: switch (i) { case 0: vdata->regWriteCount++; var->vflags |= kVarAllocWrite | kVarAllocSpecial; var->regMask = IntUtil::maskFromIndex(kX86RegIndexEdx); gpRestrictMask &= ~var->regMask; break; case 1: vdata->regReadCount++; var->vflags |= kVarAllocRead | kVarAllocSpecial; var->regMask = IntUtil::maskFromIndex(kX86RegIndexEax); gpRestrictMask &= ~var->regMask; break; default: ASMJIT_ASSERT(0); } break; case kX86InstCmpXCHG: switch (i) { case 0: vdata->regRwCount++; var->vflags |= kVarAllocReadWrite | kVarAllocSpecial; var->regMask = IntUtil::maskFromIndex(kX86RegIndexEax); gpRestrictMask &= ~var->regMask; break; case 1: vdata->regRwCount++; var->vflags |= kVarAllocReadWrite; break; case 2: vdata->regReadCount++; var->vflags |= kVarAllocRead; break; default: ASMJIT_ASSERT(0); } break; case kX86InstCmpXCHG8B: #if defined(ASMJIT_X64) case kX86InstCmpXCHG16B: #endif // ASMJIT_X64 switch (i) { case 0: vdata->regRwCount++; var->vflags |= kVarAllocReadWrite | kVarAllocSpecial; var->regMask = IntUtil::maskFromIndex(kX86RegIndexEdx); gpRestrictMask &= ~var->regMask; break; case 1: vdata->regRwCount++; var->vflags |= kVarAllocReadWrite | kVarAllocSpecial; var->regMask = IntUtil::maskFromIndex(kX86RegIndexEax); gpRestrictMask &= ~var->regMask; break; case 2: vdata->regReadCount++; var->vflags |= kVarAllocRead | kVarAllocSpecial; var->regMask = IntUtil::maskFromIndex(kX86RegIndexEcx); gpRestrictMask &= ~var->regMask; break; case 3: vdata->regReadCount++; var->vflags |= kVarAllocRead | kVarAllocSpecial; var->regMask = IntUtil::maskFromIndex(kX86RegIndexEbx); gpRestrictMask &= ~var->regMask; break; default: ASMJIT_ASSERT(0); } break; #if defined(ASMJIT_X86) case kX86InstDaa: case kX86InstDas: ASMJIT_ASSERT(i == 0); vdata->regRwCount++; var->vflags |= kVarAllocReadWrite | kVarAllocSpecial; var->regMask = IntUtil::maskFromIndex(kX86RegIndexEax); gpRestrictMask &= ~var->regMask; break; #endif // ASMJIT_X86 case kX86InstIMul: case kX86InstMul: case kX86InstIDiv: case kX86InstDiv: switch (i) { case 0: vdata->regWriteCount++; var->vflags |= kVarAllocWrite | kVarAllocSpecial; var->regMask = IntUtil::maskFromIndex(kX86RegIndexEdx); gpRestrictMask &= ~var->regMask; break; case 1: vdata->regRwCount++; var->vflags |= kVarAllocReadWrite | kVarAllocSpecial; var->regMask = IntUtil::maskFromIndex(kX86RegIndexEax); gpRestrictMask &= ~var->regMask; break; case 2: vdata->regReadCount++; var->vflags |= kVarAllocRead; break; default: ASMJIT_ASSERT(0); } break; case kX86InstMovPtr: switch (i) { case 0: vdata->regWriteCount++; var->vflags |= kVarAllocWrite | kVarAllocSpecial; var->regMask = IntUtil::maskFromIndex(kX86RegIndexEax); gpRestrictMask &= ~var->regMask; break; case 1: vdata->regReadCount++; var->vflags |= kVarAllocRead | kVarAllocSpecial; var->regMask = IntUtil::maskFromIndex(kX86RegIndexEax); gpRestrictMask &= ~var->regMask; break; default: ASMJIT_ASSERT(0); } break; case kX86InstLahf: ASMJIT_ASSERT(i == 0); vdata->regWriteCount++; var->vflags |= kVarAllocWrite | kVarAllocSpecial; var->regMask = IntUtil::maskFromIndex(kX86RegIndexEax); gpRestrictMask &= ~var->regMask; break; case kX86InstSahf: ASMJIT_ASSERT(i == 0); vdata->regReadCount++; var->vflags |= kVarAllocRead | kVarAllocSpecial; var->regMask = IntUtil::maskFromIndex(kX86RegIndexEax); gpRestrictMask &= ~var->regMask; break; case kX86InstMaskMovQ: case kX86InstMaskMovDQU: switch (i) { case 0: vdata->regReadCount++; var->vflags |= kVarAllocRead | kVarAllocSpecial; var->regMask = IntUtil::maskFromIndex(kX86RegIndexEdi); gpRestrictMask &= ~var->regMask; break; case 1: case 2: vdata->regReadCount++; var->vflags |= kVarAllocRead; break; } break; case kX86InstEnter: case kX86InstLeave: // TODO: SPECIAL INSTRUCTION. break; case kX86InstRet: // TODO: SPECIAL INSTRUCTION. break; case kX86InstMonitor: case kX86InstMWait: // TODO: MONITOR/MWAIT (COMPILER). break; case kX86InstPop: // TODO: SPECIAL INSTRUCTION. break; case kX86InstPopAD: case kX86InstPopFD: case kX86InstPopFQ: // TODO: SPECIAL INSTRUCTION. break; case kX86InstPush: // TODO: SPECIAL INSTRUCTION. break; case kX86InstPushAD: case kX86InstPushFD: case kX86InstPushFQ: // TODO: SPECIAL INSTRUCTION. break; case kX86InstRcl: case kX86InstRcr: case kX86InstRol: case kX86InstRor: case kX86InstSal: case kX86InstSar: case kX86InstShl: case kX86InstShr: switch (i) { case 0: vdata->regRwCount++; var->vflags |= kVarAllocReadWrite; break; case 1: vdata->regReadCount++; var->vflags |= kVarAllocRead | kVarAllocSpecial; var->regMask = IntUtil::maskFromIndex(kX86RegIndexEcx); gpRestrictMask &= ~var->regMask; break; default: ASMJIT_ASSERT(0); } break; case kX86InstShld: case kX86InstShrd: switch (i) { case 0: vdata->regRwCount++; var->vflags |= kVarAllocReadWrite; break; case 1: vdata->regReadCount++; var->vflags |= kVarAllocRead; break; case 2: vdata->regReadCount++; var->vflags |= kVarAllocRead | kVarAllocSpecial; var->regMask = IntUtil::maskFromIndex(kX86RegIndexEcx); gpRestrictMask &= ~var->regMask; break; default: ASMJIT_ASSERT(0); } break; case kX86InstRdtsc: case kX86InstRdtscP: switch (i) { case 0: vdata->regWriteCount++; var->vflags |= kVarAllocWrite | kVarAllocSpecial; var->regMask = IntUtil::maskFromIndex(kX86RegIndexEdx); gpRestrictMask &= ~var->regMask; break; case 1: vdata->regWriteCount++; var->vflags |= kVarAllocWrite | kVarAllocSpecial; var->regMask = IntUtil::maskFromIndex(kX86RegIndexEax); gpRestrictMask &= ~var->regMask; break; case 2: ASMJIT_ASSERT(_code == kX86InstRdtscP); vdata->regWriteCount++; var->vflags |= kVarAllocWrite | kVarAllocSpecial; var->regMask = IntUtil::maskFromIndex(kX86RegIndexEcx); gpRestrictMask &= ~var->regMask; break; default: ASMJIT_ASSERT(0); } break; case kX86InstRepLodSB: case kX86InstRepLodSD: case kX86InstRepLodSQ: case kX86InstRepLodSW: switch (i) { case 0: vdata->regWriteCount++; var->vflags |= kVarAllocWrite | kVarAllocSpecial; var->regMask = IntUtil::maskFromIndex(kX86RegIndexEax); gpRestrictMask &= ~var->regMask; break; case 1: vdata->regReadCount++; var->vflags |= kVarAllocRead | kVarAllocSpecial; var->regMask = IntUtil::maskFromIndex(kX86RegIndexEsi); gpRestrictMask &= ~var->regMask; break; case 2: vdata->regRwCount++; var->vflags |= kVarAllocReadWrite | kVarAllocSpecial; var->regMask = IntUtil::maskFromIndex(kX86RegIndexEcx); gpRestrictMask &= ~var->regMask; break; default: ASMJIT_ASSERT(0); } break; case kX86InstRepMovSB: case kX86InstRepMovSD: case kX86InstRepMovSQ: case kX86InstRepMovSW: case kX86InstRepECmpSB: case kX86InstRepECmpSD: case kX86InstRepECmpSQ: case kX86InstRepECmpSW: case kX86InstRepNECmpSB: case kX86InstRepNECmpSD: case kX86InstRepNECmpSQ: case kX86InstRepNECmpSW: switch (i) { case 0: vdata->regReadCount++; var->vflags |= kVarAllocRead | kVarAllocSpecial; var->regMask = IntUtil::maskFromIndex(kX86RegIndexEdi); gpRestrictMask &= ~var->regMask; break; case 1: vdata->regReadCount++; var->vflags |= kVarAllocRead | kVarAllocSpecial; var->regMask = IntUtil::maskFromIndex(kX86RegIndexEsi); gpRestrictMask &= ~var->regMask; break; case 2: vdata->regRwCount++; var->vflags |= kVarAllocReadWrite | kVarAllocSpecial; var->regMask = IntUtil::maskFromIndex(kX86RegIndexEcx); gpRestrictMask &= ~var->regMask; break; default: ASMJIT_ASSERT(0); } break; case kX86InstRepStoSB: case kX86InstRepStoSD: case kX86InstRepStoSQ: case kX86InstRepStoSW: switch (i) { case 0: vdata->regReadCount++; var->vflags |= kVarAllocRead | kVarAllocSpecial; var->regMask = IntUtil::maskFromIndex(kX86RegIndexEdi); gpRestrictMask &= ~var->regMask; break; case 1: vdata->regReadCount++; var->vflags |= kVarAllocRead | kVarAllocSpecial; var->regMask = IntUtil::maskFromIndex(kX86RegIndexEax); gpRestrictMask &= ~var->regMask; break; case 2: vdata->regRwCount++; var->vflags |= kVarAllocReadWrite | kVarAllocSpecial; var->regMask = IntUtil::maskFromIndex(kX86RegIndexEcx); gpRestrictMask &= ~var->regMask; break; default: ASMJIT_ASSERT(0); } break; case kX86InstRepEScaSB: case kX86InstRepEScaSD: case kX86InstRepEScaSQ: case kX86InstRepEScaSW: case kX86InstRepNEScaSB: case kX86InstRepNEScaSD: case kX86InstRepNEScaSQ: case kX86InstRepNEScaSW: switch (i) { case 0: vdata->regReadCount++; var->vflags |= kVarAllocRead | kVarAllocSpecial; var->regMask = IntUtil::maskFromIndex(kX86RegIndexEdi); gpRestrictMask &= ~var->regMask; break; case 1: vdata->regReadCount++; var->vflags |= kVarAllocRead | kVarAllocSpecial; var->regMask = IntUtil::maskFromIndex(kX86RegIndexEax); gpRestrictMask &= ~var->regMask; break; case 2: vdata->regRwCount++; var->vflags |= kVarAllocReadWrite | kVarAllocSpecial; var->regMask = IntUtil::maskFromIndex(kX86RegIndexEcx); gpRestrictMask &= ~var->regMask; break; default: ASMJIT_ASSERT(0); } break; default: ASMJIT_ASSERT(0); } // ${SPECIAL_INSTRUCTION_HANDLING_END} } else { if (i == 0) { // CMP/TEST instruction. if (id->getCode() == kX86InstCmp || id->getCode() == kX86InstTest) { // Read-only case. vdata->regReadCount++; var->vflags |= kVarAllocRead; } // CVTTSD2SI/CVTTSS2SI instructions. else if (id->getCode() == kX86InstCvttSD2SI || id->getCode() == kX86InstCvttSS2SI) { // In 32-bit mode the whole destination is replaced. In 64-bit mode // we need to check whether the destination operand size is 64-bits. #if defined(ASMJIT_X64) if (_operands[0].isRegType(kX86RegTypeGpq)) { #endif // ASMJIT_X64 // Write-only case. vdata->regWriteCount++; var->vflags |= kVarAllocWrite; #if defined(ASMJIT_X64) } else { // Read/Write. vdata->regRwCount++; var->vflags |= kVarAllocReadWrite; } #endif // ASMJIT_X64 } // MOV/MOVSS/MOVSD instructions. // // If instruction is MOV (source replaces the destination) or // MOVSS/MOVSD and source operand is memory location then register // allocator should know that previous destination value is lost // (write only operation). else if ((id->isMov()) || ((id->getCode() == kX86InstMovSS || id->getCode() == kX86InstMovSD) /* && _operands[1].isMem() */) || (id->getCode() == kX86InstIMul && _operandsCount == 3 && !isSpecial())) { // Write-only case. vdata->regWriteCount++; var->vflags |= kVarAllocWrite; } else if (id->getCode() == kX86InstLea) { // Write. vdata->regWriteCount++; var->vflags |= kVarAllocWrite; } else { // Read/Write. vdata->regRwCount++; var->vflags |= kVarAllocReadWrite; } } else { // Second, third, ... operands are read-only. vdata->regReadCount++; var->vflags |= kVarAllocRead; } if (!_memOp && i < 2 && (id->_opFlags[i] & kX86InstOpMem) != 0) { var->vflags |= kVarAllocMem; } } // If variable must be in specific register we could add some hint to allocator. if (var->vflags & kVarAllocSpecial) { vdata->prefRegisterMask |= var->regMask; x86Context._newRegisterHomeIndex(vdata, IntUtil::findFirstBit(var->regMask)); } } else if (o.isMem()) { if ((o.getId() & kOperandIdTypeMask) == kOperandIdTypeVar) { X86CompilerVar* vdata = x86Compiler->_getVar(o.getId()); ASMJIT_ASSERT(vdata != NULL); __GET_VARIABLE(vdata) if (i == 0) { // If variable is MOV instruction type (source replaces the destination) // or variable is MOVSS/MOVSD instruction then register allocator should // know that previous destination value is lost (write only operation). if (id->isMov() || ((id->getCode() == kX86InstMovSS || id->getCode() == kX86InstMovSD))) { // Write only case. vdata->memWriteCount++; } else { vdata->memRwCount++; } } else { vdata->memReadCount++; } } else if ((o._mem.base & kOperandIdTypeMask) == kOperandIdTypeVar) { X86CompilerVar* vdata = x86Compiler->_getVar(reinterpret_cast(o).getBase()); ASMJIT_ASSERT(vdata != NULL); __GET_VARIABLE(vdata) vdata->regReadCount++; var->vflags |= kVarAllocRegister | kVarAllocRead; var->regMask &= gpRestrictMask; } if ((o._mem.index & kOperandIdTypeMask) == kOperandIdTypeVar) { X86CompilerVar* vdata = x86Compiler->_getVar(reinterpret_cast(o).getIndex()); ASMJIT_ASSERT(vdata != NULL); __GET_VARIABLE(vdata) vdata->regReadCount++; var->vflags |= kVarAllocRegister | kVarAllocRead; var->regMask &= gpRestrictMask; } } } // Traverse all variables and update firstItem / lastItem. This // function is called from iterator that scans items using forward // direction so we can use this knowledge to optimize the process. // // Similar to X86CompilerFuncCall::prepare(). for (i = 0; i < _variablesCount; i++) { X86CompilerVar* v = _vars[i].vdata; // Update GP register allocator restrictions. if (X86Util::isVarTypeInt(v->getType())) { if (_vars[i].regMask == 0xFFFFFFFF) _vars[i].regMask &= gpRestrictMask; } // Update first/last item (begin of variable scope). if (v->firstItem == NULL) v->firstItem = this; v->lastItem = this; } // There are some instructions that can be used to clear or to set all bits // in a register: // // - andn reg, reg ; Set all bits in reg to 0. // - xor/pxor reg, reg ; Set all bits in reg to 0. // - sub/psub reg, reg ; Set all bits in reg to 0. // - pcmpgt reg, reg ; Set all bits in reg to 0. // - pcmpeq reg, reg ; Set all bits in reg to 1. // // There are also combinations which do nothing: // // - and reg, reg ; Nop. // - or reg, reg ; Nop. // - xchg reg, reg ; Nop. if (_variablesCount == 1 && _operandsCount > 1 && _operands[0].isVar() && _operands[1].isVar() && !_memOp) { switch (_code) { // ---------------------------------------------------------------------- // [Zeros/Ones] // ---------------------------------------------------------------------- // ANDN Instructions. case kX86InstPAndN: // XOR Instructions. case kX86InstXor: case kX86InstXorPD: case kX86InstXorPS: case kX86InstPXor: // SUB Instructions. case kX86InstSub: case kX86InstPSubB: case kX86InstPSubW: case kX86InstPSubD: case kX86InstPSubQ: case kX86InstPSubSB: case kX86InstPSubSW: case kX86InstPSubUSB: case kX86InstPSubUSW: // PCMPEQ Instructions. case kX86InstPCmpEqB: case kX86InstPCmpEqW: case kX86InstPCmpEqD: case kX86InstPCmpEqQ: // PCMPGT Instructions. case kX86InstPCmpGtB: case kX86InstPCmpGtW: case kX86InstPCmpGtD: case kX86InstPCmpGtQ: // Clear the read flag. This prevents variable alloc/spill. _vars[0].vflags = kVarAllocWrite; _vars[0].vdata->regReadCount--; break; // ---------------------------------------------------------------------- // [Nop] // ---------------------------------------------------------------------- // AND Instructions. case kX86InstAnd: case kX86InstAndPD: case kX86InstAndPS: case kX86InstPAnd: // OR Instructions. case kX86InstOr: case kX86InstOrPD: case kX86InstOrPS: case kX86InstPOr: // XCHG Instruction. case kX86InstXchg: // Clear the write flag. _vars[0].vflags = kVarAllocRead; _vars[0].vdata->regWriteCount--; break; } } x86Context._currentOffset++; #undef __GET_VARIABLE } CompilerItem* X86CompilerInst::translate(CompilerContext& cc) { X86CompilerContext& x86Context = static_cast(cc); X86Compiler* x86Compiler = getCompiler(); uint32_t i; uint32_t variablesCount = _variablesCount; if (variablesCount > 0) { // These variables are used by the instruction and we set current offset // to their work offsets -> getSpillCandidate never return the variable // used this instruction. for (i = 0; i < variablesCount; i++) { _vars[i].vdata->workOffset = x86Context._currentOffset; } // Alloc variables used by the instruction (special first). for (i = 0; i < variablesCount; i++) { VarAllocRecord& r = _vars[i]; // Alloc variables with specific register first. if ((r.vflags & kVarAllocSpecial) != 0) x86Context.allocVar(r.vdata, r.regMask, r.vflags); } for (i = 0; i < variablesCount; i++) { VarAllocRecord& r = _vars[i]; // Alloc variables without specific register last. if ((r.vflags & kVarAllocSpecial) == 0) x86Context.allocVar(r.vdata, r.regMask, r.vflags); } x86Context.translateOperands(_operands, _operandsCount); } if (_memOp && (_memOp->getId() & kOperandIdTypeMask) == kOperandIdTypeVar) { X86CompilerVar* cv = x86Compiler->_getVar(_memOp->getId()); ASMJIT_ASSERT(cv != NULL); switch (cv->state) { case kVarStateUnused: cv->state = kVarStateMem; break; case kVarStateReg: cv->changed = false; x86Context.unuseVar(cv, kVarStateMem); break; } } for (i = 0; i < variablesCount; i++) { x86Context._unuseVarOnEndOfScope(this, &_vars[i]); } return translated(); } void X86CompilerInst::emit(Assembler& a) { X86Assembler& x86Asm = static_cast(a); x86Asm._inlineComment = _comment; x86Asm._emitOptions = _emitOptions; if (isSpecial()) { // ${SPECIAL_INSTRUCTION_HANDLING_BEGIN} switch (_code) { case kX86InstCpuId: x86Asm._emitInstruction(_code); return; case kX86InstCbw: case kX86InstCdq: case kX86InstCdqe: case kX86InstCwd: case kX86InstCwde: case kX86InstCqo: x86Asm._emitInstruction(_code); return; case kX86InstCmpXCHG: x86Asm._emitInstruction(_code, &_operands[1], &_operands[2]); return; case kX86InstCmpXCHG8B: #if defined(ASMJIT_X64) case kX86InstCmpXCHG16B: #endif // ASMJIT_X64 x86Asm._emitInstruction(_code, &_operands[4]); return; #if defined(ASMJIT_X86) case kX86InstDaa: case kX86InstDas: x86Asm._emitInstruction(_code); return; #endif // ASMJIT_X86 case kX86InstIMul: case kX86InstMul: case kX86InstIDiv: case kX86InstDiv: // INST dst_lo (implicit), dst_hi (implicit), src (explicit) ASMJIT_ASSERT(_operandsCount == 3); x86Asm._emitInstruction(_code, &_operands[2]); return; case kX86InstMovPtr: break; case kX86InstLahf: case kX86InstSahf: x86Asm._emitInstruction(_code); return; case kX86InstMaskMovQ: case kX86InstMaskMovDQU: x86Asm._emitInstruction(_code, &_operands[1], &_operands[2]); return; case kX86InstEnter: case kX86InstLeave: // TODO: SPECIAL INSTRUCTION. break; case kX86InstRet: // TODO: SPECIAL INSTRUCTION. break; case kX86InstMonitor: case kX86InstMWait: // TODO: MONITOR/MWAIT (COMPILER). break; case kX86InstPop: case kX86InstPopAD: case kX86InstPopFD: case kX86InstPopFQ: // TODO: SPECIAL INSTRUCTION. break; case kX86InstPush: case kX86InstPushAD: case kX86InstPushFD: case kX86InstPushFQ: // TODO: SPECIAL INSTRUCTION. break; case kX86InstRcl: case kX86InstRcr: case kX86InstRol: case kX86InstRor: case kX86InstSal: case kX86InstSar: case kX86InstShl: case kX86InstShr: x86Asm._emitInstruction(_code, &_operands[0], &cl); return; case kX86InstShld: case kX86InstShrd: x86Asm._emitInstruction(_code, &_operands[0], &_operands[1], &cl); return; case kX86InstRdtsc: case kX86InstRdtscP: x86Asm._emitInstruction(_code); return; case kX86InstRepLodSB: case kX86InstRepLodSD: case kX86InstRepLodSQ: case kX86InstRepLodSW: case kX86InstRepMovSB: case kX86InstRepMovSD: case kX86InstRepMovSQ: case kX86InstRepMovSW: case kX86InstRepStoSB: case kX86InstRepStoSD: case kX86InstRepStoSQ: case kX86InstRepStoSW: case kX86InstRepECmpSB: case kX86InstRepECmpSD: case kX86InstRepECmpSQ: case kX86InstRepECmpSW: case kX86InstRepEScaSB: case kX86InstRepEScaSD: case kX86InstRepEScaSQ: case kX86InstRepEScaSW: case kX86InstRepNECmpSB: case kX86InstRepNECmpSD: case kX86InstRepNECmpSQ: case kX86InstRepNECmpSW: case kX86InstRepNEScaSB: case kX86InstRepNEScaSD: case kX86InstRepNEScaSQ: case kX86InstRepNEScaSW: x86Asm._emitInstruction(_code); return; default: ASMJIT_ASSERT(0); } // ${SPECIAL_INSTRUCTION_HANDLING_END} } switch (_operandsCount) { case 0: x86Asm._emitInstruction(_code); break; case 1: x86Asm._emitInstruction(_code, &_operands[0]); break; case 2: x86Asm._emitInstruction(_code, &_operands[0], &_operands[1]); break; case 3: x86Asm._emitInstruction(_code, &_operands[0], &_operands[1], &_operands[2]); break; default: ASMJIT_ASSERT(0); break; } } // ============================================================================ // [AsmJit::X86CompilerInst - Misc] // ============================================================================ int X86CompilerInst::getMaxSize() const { // TODO: Instruction max size. return 15; } bool X86CompilerInst::_tryUnuseVar(CompilerVar* _v) { X86CompilerVar* cv = static_cast(_v); for (uint32_t i = 0; i < _variablesCount; i++) { if (_vars[i].vdata == cv) { _vars[i].vflags |= kVarAllocUnuseAfterUse; return true; } } return false; } // ============================================================================ // [AsmJit::X86CompilerJmpInst - Construction / Destruction] // ============================================================================ X86CompilerJmpInst::X86CompilerJmpInst(X86Compiler* x86Compiler, uint32_t code, Operand* opData, uint32_t opCount) : X86CompilerInst(x86Compiler, code, opData, opCount) { _jumpTarget = x86Compiler->_getTarget(_operands[0].getId()); _jumpTarget->_jumpsCount++; _jumpNext = static_cast(_jumpTarget->_from); _jumpTarget->_from = this; // The 'jmp' is always taken, conditional jump can contain hint, we detect it. if (getCode() == kX86InstJmp) setInstFlag(kX86CompilerInstFlagIsTaken); else if (opCount > 1 && opData[1].isImm() && reinterpret_cast(&opData[1])->getValue() == kCondHintLikely) setInstFlag(kX86CompilerInstFlagIsTaken); } X86CompilerJmpInst::~X86CompilerJmpInst() { } // ============================================================================ // [AsmJit::X86CompilerJmpInst - Interface] // ============================================================================ void X86CompilerJmpInst::prepare(CompilerContext& cc) { X86CompilerContext& x86Context = static_cast(cc); _offset = x86Context._currentOffset; // Update _isTaken to true if this is conditional backward jump. This behavior // can be overridden by using kCondHintUnlikely when using the instruction. if (getCode() != kX86InstJmp && _operandsCount == 1 && _jumpTarget->getOffset() < getOffset()) { setInstFlag(kX86CompilerInstFlagIsTaken); } // Now patch all variables where jump location is in the active range. if (_jumpTarget->getOffset() != kInvalidValue && x86Context._active) { X86CompilerVar* first = static_cast(x86Context._active); X86CompilerVar* var = first; uint32_t jumpOffset = _jumpTarget->getOffset(); do { if (var->firstItem) { ASMJIT_ASSERT(var->lastItem != NULL); uint32_t start = var->firstItem->getOffset(); uint32_t end = var->lastItem->getOffset(); if (jumpOffset >= start && jumpOffset <= end) var->lastItem = this; } var = var->nextActive; } while (var != first); } x86Context._currentOffset++; } CompilerItem* X86CompilerJmpInst::translate(CompilerContext& cc) { X86CompilerContext& x86Context = static_cast(cc); X86Compiler* x86Compiler = getCompiler(); // Translate using X86CompilerInst. CompilerItem* ret = X86CompilerInst::translate(cc); // We jump with item if its kX86InstJUMP (not based on condiiton) and it // points into yet unknown location. if (_code == kX86InstJmp && !_jumpTarget->isTranslated()) { x86Context.addBackwardCode(this); ret = _jumpTarget; } else { _state = x86Context._saveState(); if (_jumpTarget->isTranslated()) { doJump(cc); } else { // State is not known, so we need to call doJump() later. Compiler will // do it for us. x86Context.addForwardJump(this); _jumpTarget->_state = _state; } // Mark next code as unreachable, cleared by a next label (CompilerTarget). if (_code == kX86InstJmp) x86Context._isUnreachable = 1; } // Need to traverse over all active variables and unuse them if their scope ends // here. if (x86Context._active) { X86CompilerVar* first = static_cast(x86Context._active); X86CompilerVar* var = first; do { x86Context._unuseVarOnEndOfScope(this, var); var = var->nextActive; } while (var != first); } return ret; } void X86CompilerJmpInst::emit(Assembler& a) { static const uint MAXIMUM_SHORT_JMP_SIZE = 127; // Try to minimize size of jump using SHORT jump (8-bit displacement) by // traversing into the target and calculating the maximum code size. We // end when code size reaches MAXIMUM_SHORT_JMP_SIZE. if (!(_emitOptions & kX86EmitOptionShortJump) && getJumpTarget()->getOffset() > getOffset()) { // Calculate the code size. uint codeSize = 0; CompilerItem* cur = this->getNext(); CompilerItem* target = getJumpTarget(); while (cur) { if (cur == target) { // Target found, we can tell assembler to generate short form of jump. _emitOptions |= kX86EmitOptionShortJump; goto _End; } int s = cur->getMaxSize(); if (s == -1) break; codeSize += (uint)s; if (codeSize > MAXIMUM_SHORT_JMP_SIZE) break; cur = cur->getNext(); } } _End: X86CompilerInst::emit(a); } // ============================================================================ // [AsmJit::X86CompilerJmpInst - DoJump] // ============================================================================ void X86CompilerJmpInst::doJump(CompilerContext& cc) { X86CompilerContext& x86Context = static_cast(cc); X86Compiler* x86Compiler = getCompiler(); // The state have to be already known. The doJump() method is called by // translate() or by Compiler in case that it's forward jump. ASMJIT_ASSERT(_jumpTarget->getState()); if (getCode() == kX86InstJmp || (isTaken() && _jumpTarget->getOffset() < getOffset())) { // Instruction type is JMP or conditional jump that should be taken (likely). // We can set state here instead of jumping out, setting state and jumping // to _jumpTarget. // // NOTE: We can't use this technique if instruction is forward conditional // jump. The reason is that when generating code we can't change state here, // because the next instruction depends on it. x86Context._restoreState(_jumpTarget->getState(), _jumpTarget->getOffset()); } else { // Instruction type is JMP or conditional jump that should be not normally // taken. If we need add code that will switch between different states we // add it after the end of function body (after epilog, using 'ExtraBlock'). CompilerItem* ext = x86Context.getExtraBlock(); CompilerItem* old = x86Compiler->setCurrentItem(ext); x86Context._restoreState(_jumpTarget->getState(), _jumpTarget->getOffset()); if (x86Compiler->getCurrentItem() != ext) { // Add the jump to the target. x86Compiler->jmp(_jumpTarget->_label); ext = x86Compiler->getCurrentItem(); // The x86Context._restoreState() method emitted some instructions so we need to // patch the jump. Label L = x86Compiler->newLabel(); x86Compiler->setCurrentItem(x86Context.getExtraBlock()); x86Compiler->bind(L); // Finally, patch the jump target. ASMJIT_ASSERT(_operandsCount > 0); _operands[0] = L; // Operand part (Label). _jumpTarget = x86Compiler->_getTarget(L.getId()); // Compiler part (CompilerTarget). } x86Context.setExtraBlock(ext); x86Compiler->setCurrentItem(old); // Assign state back. x86Context._assignState(static_cast(_state)); } } // ============================================================================ // [AsmJit::X86CompilerJmpInst - GetJumpTarget] // ============================================================================ CompilerTarget* X86CompilerJmpInst::getJumpTarget() const { return _jumpTarget; } } // AsmJit namespace // [Api-End] #include "../core/apiend.h" desmume/src/libretro-common/include/queues/fifo_queue.h000664 001750 001750 00000003664 12755534123 024512 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2016 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (fifo_queue.h). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef __LIBRETRO_SDK_FIFO_BUFFER_H #define __LIBRETRO_SDK_FIFO_BUFFER_H #include #include #include RETRO_BEGIN_DECLS typedef struct fifo_buffer fifo_buffer_t; fifo_buffer_t *fifo_new(size_t size); void fifo_clear(fifo_buffer_t *buffer); void fifo_write(fifo_buffer_t *buffer, const void *in_buf, size_t size); void fifo_read(fifo_buffer_t *buffer, void *in_buf, size_t size); void fifo_free(fifo_buffer_t *buffer); size_t fifo_read_avail(fifo_buffer_t *buffer); size_t fifo_write_avail(fifo_buffer_t *buffer); RETRO_END_DECLS #endif desmume/src/utils/AsmJit/core/intutil.h000664 001750 001750 00000016210 12755534123 021257 0ustar00sergiosergio000000 000000 // [AsmJit] // Complete JIT Assembler for C++ Language. // // [License] // Zlib - See COPYING file in this package. // [Guard] #ifndef _ASMJIT_CORE_INTUTIL_H #define _ASMJIT_CORE_INTUTIL_H // [Dependencies - AsmJit] #include "../core/assert.h" // [Api-Begin] #include "../core/apibegin.h" namespace AsmJit { //! @addtogroup AsmJit_Core //! @{ // ============================================================================ // [AsmJit::I32FPUnion] // ============================================================================ //! @internal //! //! @brief used to cast from float to 32-bit integer and vica versa. union I32FPUnion { //! @brief 32-bit signed integer value. int32_t i; //! @brief 32-bit SP-FP value. float f; }; // ============================================================================ // [AsmJit::I64FPUnion] // ============================================================================ //! @internal //! //! @brief used to cast from double to 64-bit integer and vica versa. union I64FPUnion { //! @brief 64-bit signed integer value. int64_t i; //! @brief 64-bit DP-FP value. double f; }; // ============================================================================ // [AsmJit::IntUtil] // ============================================================================ namespace IntUtil { // -------------------------------------------------------------------------- // [Min/Max] // -------------------------------------------------------------------------- // NOTE: Because some environments declare min() and max() as macros, we // decided to use different name so we never collide. template static inline T _min(const T& a, const T& b) { return a < b ? a : b; } template static inline T _max(const T& a, const T& b) { return a > b ? a : b; } // -------------------------------------------------------------------------- // [Limits] // -------------------------------------------------------------------------- template static inline T maxValue() { return ~T(0); } // -------------------------------------------------------------------------- // [IsInt / IsUInt] // -------------------------------------------------------------------------- //! @brief Returns @c true if a given integer @a x is signed 8-bit integer static inline bool isInt8(intptr_t x) { return x >= -128 && x <= 127; } //! @brief Returns @c true if a given integer @a x is unsigned 8-bit integer static inline bool isUInt8(intptr_t x) { return x >= 0 && x <= 255; } //! @brief Returns @c true if a given integer @a x is signed 16-bit integer static inline bool isInt16(intptr_t x) { return x >= -32768 && x <= 32767; } //! @brief Returns @c true if a given integer @a x is unsigned 16-bit integer static inline bool isUInt16(intptr_t x) { return x >= 0 && x <= 65535; } //! @brief Returns @c true if a given integer @a x is signed 16-bit integer static inline bool isInt32(intptr_t x) { #if defined(ASMJIT_X86) return true; #else return x >= ASMJIT_INT64_C(-2147483648) && x <= ASMJIT_INT64_C(2147483647); #endif } //! @brief Returns @c true if a given integer @a x is unsigned 16-bit integer static inline bool isUInt32(intptr_t x) { #if defined(ASMJIT_X86) return x >= 0; #else return x >= 0 && x <= ASMJIT_INT64_C(4294967295); #endif } // -------------------------------------------------------------------------- // [Masking] // -------------------------------------------------------------------------- static inline uint32_t maskFromIndex(uint32_t x) { ASMJIT_ASSERT(x < 32); return (1U << x); } static inline uint32_t maskUpToIndex(uint32_t x) { if (x >= 32) return 0xFFFFFFFF; else return (1U << x) - 1; } // -------------------------------------------------------------------------- // [Bits] // -------------------------------------------------------------------------- // From http://graphics.stanford.edu/~seander/bithacks.html . static inline uint32_t bitCount(uint32_t x) { x = x - ((x >> 1) & 0x55555555U); x = (x & 0x33333333U) + ((x >> 2) & 0x33333333U); return (((x + (x >> 4)) & 0x0F0F0F0FU) * 0x01010101U) >> 24; } static inline uint32_t findFirstBit(uint32_t mask) { for (uint32_t i = 0; i < sizeof(uint32_t) * 8; i++, mask >>= 1) { if (mask & 0x1) return i; } // kInvalidValue. return 0xFFFFFFFF; } // -------------------------------------------------------------------------- // [Alignment] // -------------------------------------------------------------------------- template static inline bool isAligned(T base, T alignment) { return (base % alignment) == 0; } //! @brief Align @a base to @a alignment. template static inline T align(T base, T alignment) { return (base + (alignment - 1)) & ~(alignment - 1); } //! @brief Get delta required to align @a base to @a alignment. template static inline T delta(T base, T alignment) { return align(base, alignment) - base; } // -------------------------------------------------------------------------- // [Round] // -------------------------------------------------------------------------- template static inline T roundUp(T base, T alignment) { T over = base % alignment; return base + (over > 0 ? alignment - over : 0); } template static inline T roundUpToPowerOf2(T base) { // Implementation is from "Hacker's Delight" by Henry S. Warren, Jr., // figure 3-3, page 48, where the function is called clp2. base -= 1; // I'm trying to make this portable and MSVC strikes me the warning C4293: // "Shift count negative or too big, undefined behavior" // Fixing... #if defined(_MSC_VER) # pragma warning(push) # pragma warning(disable: 4293) #endif // _MSC_VER base = base | (base >> 1); base = base | (base >> 2); base = base | (base >> 4); if (sizeof(T) >= 2) base = base | (base >> 8); if (sizeof(T) >= 4) base = base | (base >> 16); if (sizeof(T) >= 8) base = base | (base >> 16 >> 16); #if defined(_MSC_VER) # pragma warning(pop) #endif // _MSC_VER return base + 1; } // -------------------------------------------------------------------------- // [Cast] // -------------------------------------------------------------------------- //! @brief Binary cast from 32-bit integer to SP-FP value (@c float). static inline float int32AsFloat(int32_t i) { I32FPUnion u; u.i = i; return u.f; } //! @brief Binary cast SP-FP value (@c float) to 32-bit integer. static inline int32_t floatAsInt32(float f) { I32FPUnion u; u.f = f; return u.i; } //! @brief Binary cast from 64-bit integer to DP-FP value (@c double). static inline double int64AsDouble(int64_t i) { I64FPUnion u; u.i = i; return u.f; } //! @brief Binary cast from DP-FP value (@c double) to 64-bit integer. static inline int64_t doubleAsInt64(double f) { I64FPUnion u; u.f = f; return u.i; } }; //! @} } // AsmJit namespace // [Api-End] #include "../core/apiend.h" // [Guard] #endif // _ASMJIT_CORE_INTUTIL_H desmume/src/libretro-common/include/net/net_compat.h000664 001750 001750 00000012747 12755534123 023775 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2016 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (net_compat.h). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef LIBRETRO_SDK_NETPLAY_COMPAT_H__ #define LIBRETRO_SDK_NETPLAY_COMPAT_H__ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #if defined(_WIN32) && !defined(_XBOX) #ifndef _WIN32_WINNT #define _WIN32_WINNT 0x0501 #endif #define WIN32_LEAN_AND_MEAN #include #include #include #ifndef MSG_NOSIGNAL #define MSG_NOSIGNAL 0 #endif #elif defined(_XBOX) #define NOD3D #include #include #elif defined(GEKKO) #include #elif defined(VITA) #include #include #define sockaddr_in SceNetSockaddrIn #define sockaddr SceNetSockaddr #define sendto sceNetSendto #define recvfrom sceNetRecvfrom #define socket(a,b,c) sceNetSocket("unknown",a,b,c) #define bind sceNetBind #define accept sceNetAccept #define setsockopt sceNetSetsockopt #define connect sceNetConnect #define listen sceNetListen #define send sceNetSend #define recv sceNetRecv #define MSG_DONTWAIT SCE_NET_MSG_DONTWAIT #define AF_INET SCE_NET_AF_INET #define AF_UNSPEC 0 #define INADDR_ANY SCE_NET_INADDR_ANY #define INADDR_NONE 0xffffffff #define SOCK_STREAM SCE_NET_SOCK_STREAM #define SOCK_DGRAM SCE_NET_SOCK_DGRAM #define SOL_SOCKET SCE_NET_SOL_SOCKET #define SO_REUSEADDR SCE_NET_SO_REUSEADDR #define SO_SNDBUF SCE_NET_SO_SNDBUF #define SO_SNDTIMEO SCE_NET_SO_SNDTIMEO #define SO_NBIO SCE_NET_SO_NBIO #define htonl sceNetHtonl #define ntohl sceNetNtohl #define htons sceNetHtons #define socklen_t unsigned int struct hostent { char *h_name; char **h_aliases; int h_addrtype; int h_length; char **h_addr_list; char *h_addr; }; #else #include #include #include #include #ifndef __PSL1GHT__ #include #endif #include #include #include #if defined(__CELLOS_LV2__) && !defined(__PSL1GHT__) #include #include #include #include #ifndef EWOULDBLOCK #define EWOULDBLOCK SYS_NET_EWOULDBLOCK #endif #else #include #endif #endif #include #ifdef GEKKO #define sendto(s, msg, len, flags, addr, tolen) net_sendto(s, msg, len, 0, addr, 8) #define socket(domain, type, protocol) net_socket(domain, type, protocol) #endif static INLINE bool isagain(int bytes) { #if defined(_WIN32) if (bytes != SOCKET_ERROR) return false; if (WSAGetLastError() != WSAEWOULDBLOCK) return false; return true; #elif defined(VITA) return (bytes<0 && (bytes == SCE_NET_ERROR_EAGAIN || bytes == SCE_NET_ERROR_EWOULDBLOCK)); #else return (bytes < 0 && (errno == EAGAIN || errno == EWOULDBLOCK)); #endif } #ifdef _XBOX #define socklen_t int #ifndef h_addr #define h_addr h_addr_list[0] /* for backward compatibility */ #endif #ifndef SO_KEEPALIVE #define SO_KEEPALIVE 0 /* verify if correct */ #endif #endif #ifndef MSG_NOSIGNAL #define MSG_NOSIGNAL 0 #endif #ifndef _WIN32 #include #include #endif /* Compatibility layer for legacy or incomplete BSD socket implementations. * Only for IPv4. Mostly useful for the consoles which do not support * anything reasonably modern on the socket API side of things. */ #ifdef HAVE_SOCKET_LEGACY #define sockaddr_storage sockaddr_in #define addrinfo addrinfo_retro__ struct addrinfo { int ai_flags; int ai_family; int ai_socktype; int ai_protocol; size_t ai_addrlen; struct sockaddr *ai_addr; char *ai_canonname; struct addrinfo *ai_next; }; #ifndef AI_PASSIVE #define AI_PASSIVE 1 #endif /* gai_strerror() not used, so we skip that. */ #endif uint16_t inet_htons(uint16_t hostshort); int inet_ptrton(int af, const char *src, void *dst); int getaddrinfo_retro(const char *node, const char *service, struct addrinfo *hints, struct addrinfo **res); void freeaddrinfo_retro(struct addrinfo *res); /** * network_init: * * Platform specific socket library initialization. * * Returns: true (1) if successful, otherwise false (0). **/ bool network_init(void); /** * network_deinit: * * Deinitialize platform specific socket libraries. **/ void network_deinit(void); #endif desmume/src/mic.cpp000664 001750 001750 00000013216 12755534123 015416 0ustar00sergiosergio000000 000000 /* mic.cpp - this file is part of DeSmuME * * Copyright (C) 2009-2015 DeSmuME Team * * This file is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This file is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ #if !defined(WIN32) || defined(__LIBRETRO__) || defined(DESMUME_QT) #include #include "mic.h" #include "NDSSystem.h" #include "readwrite.h" #include "emufile.h" #define MIC_NULL_SAMPLE_VALUE 0x40 #define MIC_MAX_BUFFER_SAMPLES 320 #define MIC_BUFFER_SIZE (sizeof(u8) * MIC_MAX_BUFFER_SAMPLES) #define NUM_INTERNAL_NOISE_SAMPLES 32 static u8 *micSampleBuffer = NULL; // Pointer to the internal sample buffer. static u8 *micReadPosition = NULL; // Pointer to the read position of the internal sample buffer. static u8 *micWritePosition = NULL; // Pointer to the write position of the internal sample buffer. static unsigned int micBufferFillCount; // The number of readable samples in the internal sample buffer. static void Mic_BufferClear(void) { if (micSampleBuffer == NULL) { return; } memset(micSampleBuffer, MIC_NULL_SAMPLE_VALUE, MIC_BUFFER_SIZE); micReadPosition = micSampleBuffer; micWritePosition = micSampleBuffer; micBufferFillCount = 0; } BOOL Mic_Init(void) { BOOL result = FALSE; u8 *newBuffer = (u8 *)malloc(MIC_BUFFER_SIZE); if (newBuffer == NULL) { return result; } micSampleBuffer = newBuffer; Mic_BufferClear(); result = TRUE; return result; } void Mic_DeInit(void) { free(micSampleBuffer); micSampleBuffer = NULL; } void Mic_Reset(void) { *micReadPosition = MIC_NULL_SAMPLE_VALUE; micWritePosition = micReadPosition; micBufferFillCount = 0; } static bool Mic_GetActivate(void) { return NDS_getFinalUserInput().mic.micButtonPressed; } static bool Mic_IsBufferFull(void) { return (micBufferFillCount >= MIC_MAX_BUFFER_SAMPLES); } static bool Mic_IsBufferEmpty(void) { return (micBufferFillCount == 0); } static u8 Mic_DefaultBufferRead(void) { u8 theSample = MIC_NULL_SAMPLE_VALUE; if (micSampleBuffer == NULL) { return theSample; } theSample = *micReadPosition; if (Mic_IsBufferEmpty()) { return theSample; } micReadPosition++; micBufferFillCount--; // Move the pointer back to start if we reach the end of the memory block. if (micReadPosition >= (micSampleBuffer + MIC_BUFFER_SIZE)) { micReadPosition = micSampleBuffer; } return theSample; } static void Mic_DefaultBufferWrite(u8 theSample) { if (micSampleBuffer == NULL || Mic_IsBufferFull()) { return; } *micWritePosition = theSample; micWritePosition++; micBufferFillCount++; // Move the pointer back to start if we reach the end of the memory block. if (micWritePosition >= (micSampleBuffer + MIC_BUFFER_SIZE)) { micWritePosition = micSampleBuffer; } } static u8 Mic_GenerateInternalNoiseSample(void) { const u8 noiseSample[NUM_INTERNAL_NOISE_SAMPLES] = { 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF5, 0xFF, 0xFF, 0xFF, 0xFF, 0x8E, 0xFF, 0xF4, 0xE1, 0xBF, 0x9A, 0x71, 0x58, 0x5B, 0x5F, 0x62, 0xC2, 0x25, 0x05, 0x01, 0x01, 0x01, 0x01 }; static unsigned int i = 0; if (++i >= NUM_INTERNAL_NOISE_SAMPLES) { i = 0; } return noiseSample[i]; } static u8 Mic_GenerateWhiteNoiseSample(void) { return (u8)(rand() & 0xFF); } static u8 Mic_GenerateNullSample(void) { return MIC_NULL_SAMPLE_VALUE; } void Mic_DoNoise(BOOL noise) { u8 (*generator) (void) = NULL; if (micSampleBuffer == NULL) { return; } if (!noise) { generator = &Mic_GenerateNullSample; } else if (CommonSettings.micMode == TCommonSettings::InternalNoise) { generator = &Mic_GenerateInternalNoiseSample; } else if (CommonSettings.micMode == TCommonSettings::Random) { generator = &Mic_GenerateWhiteNoiseSample; } if (generator == NULL) { return; } while (micBufferFillCount < MIC_MAX_BUFFER_SAMPLES) { Mic_DefaultBufferWrite(generator()); } } u8 Mic_ReadSample(void) { // All mic modes other than Physical must have the mic hotkey pressed in order // to work. #if defined(FAKE_MIC) if (CommonSettings.micMode != TCommonSettings::Physical && Mic_GetActivate()) Mic_DoNoise(true); #elif !defined(FAKE_MIC) if (CommonSettings.micMode == TCommonSettings::Physical) { // TODO return MIC_NULL_SAMPLE_VALUE; } else { if (Mic_GetActivate()) { if (CommonSettings.micMode == TCommonSettings::InternalNoise) { while (micBufferFillCount < MIC_MAX_BUFFER_SAMPLES) Mic_DefaultBufferWrite(Mic_GenerateInternalNoiseSample()); } else if (CommonSettings.micMode == TCommonSettings::Random) { while (micBufferFillCount < MIC_MAX_BUFFER_SAMPLES) Mic_DefaultBufferWrite(Mic_GenerateWhiteNoiseSample()); } else if (CommonSettings.micMode == TCommonSettings::Sample) { // TODO return MIC_NULL_SAMPLE_VALUE; } } else { return MIC_NULL_SAMPLE_VALUE; } } #endif return Mic_DefaultBufferRead(); } void mic_savestate(EMUFILE* os) { write32le(-1,os); } bool mic_loadstate(EMUFILE* is, int size) { is->fseek(size, SEEK_CUR); return TRUE; } #endif desmume/src/libretro-common/net/net_socket.c000664 001750 001750 00000017011 12755534123 022337 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2016 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (net_socket.c). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include #include #include int socket_init(void **address, uint16_t port, const char *server, enum socket_type type) { char port_buf[16] = {0}; struct addrinfo hints = {0}; struct addrinfo **addrinfo = (struct addrinfo**)address; struct addrinfo *addr = NULL; if (!network_init()) goto error; switch (type) { case SOCKET_TYPE_DATAGRAM: hints.ai_socktype = SOCK_DGRAM; break; case SOCKET_TYPE_STREAM: hints.ai_socktype = SOCK_STREAM; break; case SOCKET_TYPE_SEQPACKET: /* TODO/FIXME - implement? */ break; } if (!server) hints.ai_flags = AI_PASSIVE; snprintf(port_buf, sizeof(port_buf), "%hu", (unsigned short)port); if (getaddrinfo_retro(server, port_buf, &hints, addrinfo) < 0) goto error; addr = (struct addrinfo*)*addrinfo; if (!addr) goto error; return socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol); error: return -1; } ssize_t socket_receive_all_nonblocking(int fd, bool *error, void *data_, size_t size) { const uint8_t *data = (const uint8_t*)data_; ssize_t ret = recv(fd, (char*)data, size, 0); if (ret > 0) return ret; if (ret == 0) return -1; if (isagain(ret)) return 0; *error = true; return -1; } int socket_receive_all_blocking(int fd, void *data_, size_t size) { const uint8_t *data = (const uint8_t*)data_; while (size) { ssize_t ret = recv(fd, (char*)data, size, 0); if (ret <= 0) return false; data += ret; size -= ret; } return true; } bool socket_nonblock(int fd) { #if defined(__CELLOS_LV2__) || defined(VITA) int i = 1; setsockopt(fd, SOL_SOCKET, SO_NBIO, &i, sizeof(int)); return true; #elif defined(_WIN32) u_long mode = 1; return ioctlsocket(fd, FIONBIO, &mode) == 0; #else return fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK) == 0; #endif } int socket_close(int fd) { #if defined(_WIN32) && !defined(_XBOX360) /* WinSock has headers from the stone age. */ return closesocket(fd); #elif defined(__CELLOS_LV2__) return socketclose(fd); #elif defined(VITA) return sceNetSocketClose(fd); #else return close(fd); #endif } int socket_select(int nfds, fd_set *readfs, fd_set *writefds, fd_set *errorfds, struct timeval *timeout) { #if defined(__CELLOS_LV2__) return socketselect(nfds, readfs, writefds, errorfds, timeout); #elif defined(VITA) SceNetEpollEvent ev = {0}; ev.events = SCE_NET_EPOLLIN | SCE_NET_EPOLLHUP; ev.data.fd = nfds; if((sceNetEpollControl(retro_epoll_fd, SCE_NET_EPOLL_CTL_ADD, nfds, &ev))) { int ret = sceNetEpollWait(retro_epoll_fd, &ev, 1, 0); sceNetEpollControl(retro_epoll_fd, SCE_NET_EPOLL_CTL_DEL, nfds, NULL); return ret; } return 0; #else return select(nfds, readfs, writefds, errorfds, timeout); #endif } int socket_send_all_blocking(int fd, const void *data_, size_t size, bool no_signal) { const uint8_t *data = (const uint8_t*)data_; while (size) { ssize_t ret = send(fd, (const char*)data, size, no_signal ? MSG_NOSIGNAL : 0); if (ret <= 0) { if (!isagain(ret)) continue; return false; } data += ret; size -= ret; } return true; } bool socket_bind(int fd, void *data) { int yes = 1; struct addrinfo *res = (struct addrinfo*)data; setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const char*)&yes, sizeof(int)); if (bind(fd, res->ai_addr, res->ai_addrlen) < 0) return false; return true; } int socket_connect(int fd, void *data, bool timeout_enable) { struct addrinfo *addr = (struct addrinfo*)data; #ifndef _WIN32 #ifndef VITA if (timeout_enable) { struct timeval timeout; timeout.tv_sec = 4; timeout.tv_usec = 0; setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, (char*)&timeout, sizeof timeout); } #endif #endif return connect(fd, addr->ai_addr, addr->ai_addrlen); } static int domain_get(enum socket_domain type) { switch (type) { case SOCKET_DOMAIN_INET: #ifdef VITA return SCE_NET_AF_INET; #else return AF_INET; #endif default: break; } return 0; } int socket_create( const char *name, enum socket_domain domain_type, enum socket_type socket_type, enum socket_protocol protocol_type) { int type = 0; int protocol = 0; int domain = domain_get(domain_type); #ifdef VITA switch (socket_type) { case SOCKET_TYPE_DATAGRAM: type = SCE_NET_SOCK_DGRAM; break; case SOCKET_TYPE_STREAM: type = SCE_NET_SOCK_STREAM; break; case SOCKET_TYPE_SEQPACKET: /* TODO/FIXME - implement */ break; } switch (protocol_type) { case SOCKET_PROTOCOL_NONE: protocol = 0; break; case SOCKET_PROTOCOL_TCP: protocol = SCE_NET_IPPROTO_TCP; break; case SOCKET_PROTOCOL_UDP: protocol = SCE_NET_IPPROTO_UDP; break; } return sceNetSocket(name, domain, type, protocol); #else switch (socket_type) { case SOCKET_TYPE_DATAGRAM: type = SOCK_DGRAM; break; case SOCKET_TYPE_STREAM: type = SOCK_STREAM; break; case SOCKET_TYPE_SEQPACKET: /* TODO/FIXME - implement */ break; } switch (protocol_type) { case SOCKET_PROTOCOL_NONE: protocol = 0; break; case SOCKET_PROTOCOL_TCP: protocol = IPPROTO_TCP; break; case SOCKET_PROTOCOL_UDP: protocol = IPPROTO_UDP; break; } return socket(domain, type, protocol); #endif } void socket_set_target(void *data, socket_target_t *in_addr) { struct sockaddr_in *out_target = (struct sockaddr_in*)data; out_target->sin_port = inet_htons(in_addr->port); out_target->sin_family = domain_get(in_addr->domain); #ifdef VITA out_target->sin_addr = inet_aton(in_addr->server); #else #ifdef GEKKO out_target->sin_len = 8; #endif inet_ptrton(AF_INET, in_addr->server, &out_target->sin_addr); #endif } desmume/src/libretro-common/utils/md5.c000664 001750 001750 00000024510 12755534123 021242 0ustar00sergiosergio000000 000000 /* * This is an OpenSSL-compatible implementation of the RSA Data Security, Inc. * MD5 Message-Digest Algorithm (RFC 1321). * * Homepage: * http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5 * * Author: * Alexander Peslyak, better known as Solar Designer * * This software was written by Alexander Peslyak in 2001. No copyright is * claimed, and the software is hereby placed in the public domain. * In case this attempt to disclaim copyright and place the software in the * public domain is deemed null and void, then the software is * Copyright (c) 2001 Alexander Peslyak and it is hereby released to the * general public under the following terms: * * Redistribution and use in source and binary forms, with or without * modification, are permitted. * * There's ABSOLUTELY NO WARRANTY, express or implied. * * (This is a heavily cut-down "BSD license".) * * This differs from Colin Plumb's older public domain implementation in that * no exactly 32-bit integer data type is required (any 32-bit or wider * unsigned integer data type will do), there's no compile-time endianness * configuration, and the function prototypes match OpenSSL's. No code from * Colin Plumb's implementation has been reused; this comment merely compares * the properties of the two independent implementations. * * The primary goals of this implementation are portability and ease of use. * It is meant to be fast, but not as fast as possible. Some known * optimizations are not included to reduce source code size and avoid * compile-time configuration. */ #include #include "rhash.h" /* * The basic MD5 functions. * * F and G are optimized compared to their RFC 1321 definitions for * architectures that lack an AND-NOT instruction, just like in Colin Plumb's * implementation. */ #define MD5_F(x, y, z) ((z) ^ ((x) & ((y) ^ (z)))) #define MD5_G(x, y, z) ((y) ^ ((z) & ((x) ^ (y)))) #define MD5_H(x, y, z) (((x) ^ (y)) ^ (z)) #define MD5_H2(x, y, z) ((x) ^ ((y) ^ (z))) #define MD5_I(x, y, z) ((y) ^ ((x) | ~(z))) /* * The MD5 transformation for all four rounds. */ #define MD5_STEP(f, a, b, c, d, x, t, s) \ (a) += f((b), (c), (d)) + (x) + (t); \ (a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s)))); \ (a) += (b); /* * MD5_SET reads 4 input bytes in little-endian byte order and stores them * in a properly aligned word in host byte order. * * The check for little-endian architectures that tolerate unaligned * memory accesses is just an optimization. Nothing will break if it * doesn't work. */ #if defined(__i386__) || defined(__x86_64__) || defined(__vax__) #define MD5_SET(n) \ (*(MD5_u32plus *)&ptr[(n) * 4]) #define MD5_GET(n) \ MD5_SET(n) #else #define MD5_SET(n) \ (ctx->block[(n)] = \ (MD5_u32plus)ptr[(n) * 4] | \ ((MD5_u32plus)ptr[(n) * 4 + 1] << 8) | \ ((MD5_u32plus)ptr[(n) * 4 + 2] << 16) | \ ((MD5_u32plus)ptr[(n) * 4 + 3] << 24)) #define MD5_GET(n) \ (ctx->block[(n)]) #endif /* * This processes one or more 64-byte data blocks, but does NOT update * the bit counters. There are no alignment requirements. */ static const void *MD5_body(MD5_CTX *ctx, const void *data, unsigned long size) { const unsigned char *ptr; MD5_u32plus a, b, c, d; MD5_u32plus saved_a, saved_b, saved_c, saved_d; ptr = (const unsigned char *)data; a = ctx->a; b = ctx->b; c = ctx->c; d = ctx->d; do { saved_a = a; saved_b = b; saved_c = c; saved_d = d; /* Round 1 */ MD5_STEP(MD5_F, a, b, c, d, MD5_SET(0), 0xd76aa478, 7) MD5_STEP(MD5_F, d, a, b, c, MD5_SET(1), 0xe8c7b756, 12) MD5_STEP(MD5_F, c, d, a, b, MD5_SET(2), 0x242070db, 17) MD5_STEP(MD5_F, b, c, d, a, MD5_SET(3), 0xc1bdceee, 22) MD5_STEP(MD5_F, a, b, c, d, MD5_SET(4), 0xf57c0faf, 7) MD5_STEP(MD5_F, d, a, b, c, MD5_SET(5), 0x4787c62a, 12) MD5_STEP(MD5_F, c, d, a, b, MD5_SET(6), 0xa8304613, 17) MD5_STEP(MD5_F, b, c, d, a, MD5_SET(7), 0xfd469501, 22) MD5_STEP(MD5_F, a, b, c, d, MD5_SET(8), 0x698098d8, 7) MD5_STEP(MD5_F, d, a, b, c, MD5_SET(9), 0x8b44f7af, 12) MD5_STEP(MD5_F, c, d, a, b, MD5_SET(10), 0xffff5bb1, 17) MD5_STEP(MD5_F, b, c, d, a, MD5_SET(11), 0x895cd7be, 22) MD5_STEP(MD5_F, a, b, c, d, MD5_SET(12), 0x6b901122, 7) MD5_STEP(MD5_F, d, a, b, c, MD5_SET(13), 0xfd987193, 12) MD5_STEP(MD5_F, c, d, a, b, MD5_SET(14), 0xa679438e, 17) MD5_STEP(MD5_F, b, c, d, a, MD5_SET(15), 0x49b40821, 22) /* Round 2 */ MD5_STEP(MD5_G, a, b, c, d, MD5_GET(1), 0xf61e2562, 5) MD5_STEP(MD5_G, d, a, b, c, MD5_GET(6), 0xc040b340, 9) MD5_STEP(MD5_G, c, d, a, b, MD5_GET(11), 0x265e5a51, 14) MD5_STEP(MD5_G, b, c, d, a, MD5_GET(0), 0xe9b6c7aa, 20) MD5_STEP(MD5_G, a, b, c, d, MD5_GET(5), 0xd62f105d, 5) MD5_STEP(MD5_G, d, a, b, c, MD5_GET(10), 0x02441453, 9) MD5_STEP(MD5_G, c, d, a, b, MD5_GET(15), 0xd8a1e681, 14) MD5_STEP(MD5_G, b, c, d, a, MD5_GET(4), 0xe7d3fbc8, 20) MD5_STEP(MD5_G, a, b, c, d, MD5_GET(9), 0x21e1cde6, 5) MD5_STEP(MD5_G, d, a, b, c, MD5_GET(14), 0xc33707d6, 9) MD5_STEP(MD5_G, c, d, a, b, MD5_GET(3), 0xf4d50d87, 14) MD5_STEP(MD5_G, b, c, d, a, MD5_GET(8), 0x455a14ed, 20) MD5_STEP(MD5_G, a, b, c, d, MD5_GET(13), 0xa9e3e905, 5) MD5_STEP(MD5_G, d, a, b, c, MD5_GET(2), 0xfcefa3f8, 9) MD5_STEP(MD5_G, c, d, a, b, MD5_GET(7), 0x676f02d9, 14) MD5_STEP(MD5_G, b, c, d, a, MD5_GET(12), 0x8d2a4c8a, 20) /* Round 3 */ MD5_STEP(MD5_H, a, b, c, d, MD5_GET(5), 0xfffa3942, 4) MD5_STEP(MD5_H2, d, a, b, c, MD5_GET(8), 0x8771f681, 11) MD5_STEP(MD5_H, c, d, a, b, MD5_GET(11), 0x6d9d6122, 16) MD5_STEP(MD5_H2, b, c, d, a, MD5_GET(14), 0xfde5380c, 23) MD5_STEP(MD5_H, a, b, c, d, MD5_GET(1), 0xa4beea44, 4) MD5_STEP(MD5_H2, d, a, b, c, MD5_GET(4), 0x4bdecfa9, 11) MD5_STEP(MD5_H, c, d, a, b, MD5_GET(7), 0xf6bb4b60, 16) MD5_STEP(MD5_H2, b, c, d, a, MD5_GET(10), 0xbebfbc70, 23) MD5_STEP(MD5_H, a, b, c, d, MD5_GET(13), 0x289b7ec6, 4) MD5_STEP(MD5_H2, d, a, b, c, MD5_GET(0), 0xeaa127fa, 11) MD5_STEP(MD5_H, c, d, a, b, MD5_GET(3), 0xd4ef3085, 16) MD5_STEP(MD5_H2, b, c, d, a, MD5_GET(6), 0x04881d05, 23) MD5_STEP(MD5_H, a, b, c, d, MD5_GET(9), 0xd9d4d039, 4) MD5_STEP(MD5_H2, d, a, b, c, MD5_GET(12), 0xe6db99e5, 11) MD5_STEP(MD5_H, c, d, a, b, MD5_GET(15), 0x1fa27cf8, 16) MD5_STEP(MD5_H2, b, c, d, a, MD5_GET(2), 0xc4ac5665, 23) /* Round 4 */ MD5_STEP(MD5_I, a, b, c, d, MD5_GET(0), 0xf4292244, 6) MD5_STEP(MD5_I, d, a, b, c, MD5_GET(7), 0x432aff97, 10) MD5_STEP(MD5_I, c, d, a, b, MD5_GET(14), 0xab9423a7, 15) MD5_STEP(MD5_I, b, c, d, a, MD5_GET(5), 0xfc93a039, 21) MD5_STEP(MD5_I, a, b, c, d, MD5_GET(12), 0x655b59c3, 6) MD5_STEP(MD5_I, d, a, b, c, MD5_GET(3), 0x8f0ccc92, 10) MD5_STEP(MD5_I, c, d, a, b, MD5_GET(10), 0xffeff47d, 15) MD5_STEP(MD5_I, b, c, d, a, MD5_GET(1), 0x85845dd1, 21) MD5_STEP(MD5_I, a, b, c, d, MD5_GET(8), 0x6fa87e4f, 6) MD5_STEP(MD5_I, d, a, b, c, MD5_GET(15), 0xfe2ce6e0, 10) MD5_STEP(MD5_I, c, d, a, b, MD5_GET(6), 0xa3014314, 15) MD5_STEP(MD5_I, b, c, d, a, MD5_GET(13), 0x4e0811a1, 21) MD5_STEP(MD5_I, a, b, c, d, MD5_GET(4), 0xf7537e82, 6) MD5_STEP(MD5_I, d, a, b, c, MD5_GET(11), 0xbd3af235, 10) MD5_STEP(MD5_I, c, d, a, b, MD5_GET(2), 0x2ad7d2bb, 15) MD5_STEP(MD5_I, b, c, d, a, MD5_GET(9), 0xeb86d391, 21) a += saved_a; b += saved_b; c += saved_c; d += saved_d; ptr += 64; } while (size -= 64); ctx->a = a; ctx->b = b; ctx->c = c; ctx->d = d; return ptr; } void MD5_Init(MD5_CTX *ctx) { ctx->a = 0x67452301; ctx->b = 0xefcdab89; ctx->c = 0x98badcfe; ctx->d = 0x10325476; ctx->lo = 0; ctx->hi = 0; } void MD5_Update(MD5_CTX *ctx, const void *data, unsigned long size) { MD5_u32plus saved_lo; unsigned long used, available; saved_lo = ctx->lo; if ((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo) ctx->hi++; ctx->hi += size >> 29; used = saved_lo & 0x3f; if (used) { available = 64 - used; if (size < available) { memcpy(&ctx->buffer[used], data, size); return; } memcpy(&ctx->buffer[used], data, available); data = (const unsigned char *)data + available; size -= available; MD5_body(ctx, ctx->buffer, 64); } if (size >= 64) { data = MD5_body(ctx, data, size & ~(unsigned long)0x3f); size &= 0x3f; } memcpy(ctx->buffer, data, size); } void MD5_Final(unsigned char *result, MD5_CTX *ctx) { unsigned long used, available; used = ctx->lo & 0x3f; ctx->buffer[used++] = 0x80; available = 64 - used; if (available < 8) { memset(&ctx->buffer[used], 0, available); MD5_body(ctx, ctx->buffer, 64); used = 0; available = 64; } memset(&ctx->buffer[used], 0, available - 8); ctx->lo <<= 3; ctx->buffer[56] = ctx->lo; ctx->buffer[57] = ctx->lo >> 8; ctx->buffer[58] = ctx->lo >> 16; ctx->buffer[59] = ctx->lo >> 24; ctx->buffer[60] = ctx->hi; ctx->buffer[61] = ctx->hi >> 8; ctx->buffer[62] = ctx->hi >> 16; ctx->buffer[63] = ctx->hi >> 24; MD5_body(ctx, ctx->buffer, 64); result[0] = ctx->a; result[1] = ctx->a >> 8; result[2] = ctx->a >> 16; result[3] = ctx->a >> 24; result[4] = ctx->b; result[5] = ctx->b >> 8; result[6] = ctx->b >> 16; result[7] = ctx->b >> 24; result[8] = ctx->c; result[9] = ctx->c >> 8; result[10] = ctx->c >> 16; result[11] = ctx->c >> 24; result[12] = ctx->d; result[13] = ctx->d >> 8; result[14] = ctx->d >> 16; result[15] = ctx->d >> 24; memset(ctx, 0, sizeof(*ctx)); } #ifdef MD5_BUILD_UTILITY #include int main (int argc, char *argv[]) { /* For each command line argument in turn: ** filename -- prints message digest and name of file */ int i; MD5_CTX ctx; FILE* file; size_t numread; char buffer[16384]; unsigned char result[16]; for (i = 1; i < argc; i++) { MD5_Init(&ctx); file = fopen(argv[i], "rb"); if (file) { do { numread = fread((void*)buffer, 1, sizeof(buffer), file); if (numread) { MD5_Update(&ctx,(void*)buffer, numread); } } while (numread); fclose(file); MD5_Final(result, &ctx); printf("%02x%02x%02x%02x%02x%02x%02x%02x" "%02x%02x%02x%02x%02x%02x%02x%02x %s\n", result[ 0 ], result[ 1 ], result[ 2 ], result[ 3 ], result[ 4 ], result[ 5 ], result[ 6 ], result[ 7 ], result[ 8 ], result[ 9 ], result[ 10 ], result[ 11 ], result[ 12 ], result[ 13 ], result[ 14 ], result[ 15 ], argv[i]); } } return 0; } #endif desmume/src/utils/AsmJit/core/func.h000664 001750 001750 00000036402 12755534123 020527 0ustar00sergiosergio000000 000000 // [AsmJit] // Complete JIT Assembler for C++ Language. // // [License] // Zlib - See COPYING file in this package. // [Guard] #ifndef _ASMJIT_CORE_FUNC_H #define _ASMJIT_CORE_FUNC_H // [Dependencies - AsmJit] #include "../core/assert.h" #include "../core/defs.h" // [Api-Begin] #include "../core/apibegin.h" namespace AsmJit { // ============================================================================ // [Forward Declaration] // ============================================================================ template struct TypeId; // ============================================================================ // [AsmJit::TypeId] // ============================================================================ #if defined(ASMJIT_HAS_PARTIAL_TEMPLATE_SPECIALIZATION) #define ASMJIT_DECLARE_TYPE_CORE(_PtrId_) \ template \ struct TypeId \ { \ enum \ { \ Id = static_cast(::AsmJit::kVarTypeInvalid) \ }; \ }; \ \ template \ struct TypeId { enum { Id = _PtrId_ }; } #else // Code without partial template specialization is a bit complex. We need to // determine whether the size of the return value of this function is equal // to sizeof(char) or sizeof(void*). Any sizeof() can be used to distinguish // between these two, but these are commonly used in other libraries as well. template char TypeId_NoPtiHelper(T*(*)()); // And specialization. void* TypeId_NoPtiHelper(...); #define ASMJIT_DECLARE_TYPE_CORE(_PtrId_) \ template \ struct TypeId \ { \ enum \ { \ Id = (sizeof( ::AsmJit::TypeId_NoPtiHelper((T(*)())0) ) == sizeof(char) \ ? static_cast(_PtrId_) \ : static_cast(::AsmJit::kVarTypeInvalid)) \ }; \ } #endif // ASMJIT_HAS_PARTIAL_TEMPLATE_SPECIALIZATION //! @brief Declare C/C++ type-id mapped to @c AsmJit::kX86VarType. #define ASMJIT_DECLARE_TYPE_ID(_T_, _Id_) \ template<> \ struct TypeId<_T_> { enum { Id = _Id_ }; } // ============================================================================ // [AsmJit::FuncArg] // ============================================================================ //! @brief Function argument translated from @ref FuncPrototype. struct FuncArg { // -------------------------------------------------------------------------- // [Accessors] // -------------------------------------------------------------------------- inline uint32_t getVarType() const { return _varType; } inline uint32_t getRegIndex() const { return _regIndex; } inline bool hasRegIndex() const { return _regIndex != kRegIndexInvalid; } inline int32_t getStackOffset() const { return static_cast(_stackOffset); } inline bool hasStackOffset() const { return _stackOffset != kFuncStackInvalid; } //! @brief Get whether the argument is assigned, for private use only. inline bool isAssigned() const { return (_regIndex != kRegIndexInvalid) | (_stackOffset != kFuncStackInvalid); } // -------------------------------------------------------------------------- // [Reset] // -------------------------------------------------------------------------- //! @brief Reset the function argument to "unassigned state". inline void reset() { _packed = 0xFFFFFFFF; } // -------------------------------------------------------------------------- // [Members] // -------------------------------------------------------------------------- union { struct { //! @brief Variable type, see @c kVarType. uint8_t _varType; //! @brief Register index is argument is passed through register. uint8_t _regIndex; //! @brief Stack offset if argument is passed through stack. int16_t _stackOffset; }; //! @brief All members packed into single 32-bit integer. uint32_t _packed; }; }; // ============================================================================ // [AsmJit::FuncPrototype] // ============================================================================ //! @brief Function prototype. //! //! Function prototype contains information about function return type, count //! of arguments and their types. Function definition is low level structure //! which doesn't contain platform or calling convention specific information. struct FuncPrototype { // -------------------------------------------------------------------------- // [Accessors] // -------------------------------------------------------------------------- //! @brief Get function return value. inline uint32_t getReturnType() const { return _returnType; } //! @brief Get count of function arguments. inline uint32_t getArgumentsCount() const { return _argumentsCount; } //! @brief Get argument at index @a id. inline uint32_t getArgument(uint32_t id) const { ASMJIT_ASSERT(id < _argumentsCount); return _arguments[id]; } //! @brief Get function arguments' IDs. inline const uint32_t* getArguments() const { return _arguments; } //! @brief Set function definition - return type and arguments. inline void _setPrototype(uint32_t returnType, const uint32_t* arguments, uint32_t argumentsCount) { _returnType = returnType; _arguments = arguments; _argumentsCount = argumentsCount; } // -------------------------------------------------------------------------- // [Members] // -------------------------------------------------------------------------- uint32_t _returnType; uint32_t _argumentsCount; const uint32_t* _arguments; }; // ============================================================================ // [AsmJit::FuncDecl] // ============================================================================ //! @brief Function declaration. struct FuncDecl { // -------------------------------------------------------------------------- // [Accessors] // -------------------------------------------------------------------------- //! @brief Get function return value or @ref kInvalidValue if it's void. inline uint32_t getReturnType() const { return _returnType; } //! @brief Get count of function arguments. inline uint32_t getArgumentsCount() const { return _argumentsCount; } //! @brief Get function arguments array. inline FuncArg* getArguments() { return _arguments; } //! @brief Get function arguments array (const). inline const FuncArg* getArguments() const { return _arguments; } //! @brief Get function argument at index @a index. inline FuncArg& getArgument(size_t index) { ASMJIT_ASSERT(index < static_cast(_argumentsCount)); return _arguments[index]; } //! @brief Get function argument at index @a index. inline const FuncArg& getArgument(size_t index) const { ASMJIT_ASSERT(index < static_cast(_argumentsCount)); return _arguments[index]; } // -------------------------------------------------------------------------- // [Members] // -------------------------------------------------------------------------- //! @brief Function return type. uint8_t _returnType; //! @brief Count of arguments (in @c _argumentsList). uint8_t _argumentsCount; //! @brief Reserved for future use (alignment). uint8_t _reserved0[2]; //! @brief Function arguments array. FuncArg _arguments[kFuncArgsMax]; }; // ============================================================================ // [AsmJit::FuncBuilderX] // ============================================================================ //! @brief Custom function builder for up to 32 function arguments. struct FuncBuilderX : public FuncPrototype { // -------------------------------------------------------------------------- // [Construction / Destruction] // -------------------------------------------------------------------------- inline FuncBuilderX() { _setPrototype(kVarTypeInvalid, _argumentsData, 0); } // -------------------------------------------------------------------------- // [Accessors] // -------------------------------------------------------------------------- template inline void setReturnTypeT() { setReturnTypeRaw(TypeId::Id); } template inline void setArgumentT(uint32_t id) { setArgumentRaw(id, TypeId::Id); } template inline void addArgumentT() { addArgumentRaw(TypeId::Id); } inline void setReturnTypeRaw(uint32_t returnType) { _returnType = returnType; } inline void setArgumentRaw(uint32_t id, uint32_t type) { ASMJIT_ASSERT(id < _argumentsCount); _argumentsData[id] = type; } inline void addArgumentRaw(uint32_t type) { ASMJIT_ASSERT(_argumentsCount < kFuncArgsMax); _argumentsData[_argumentsCount++] = type; } // -------------------------------------------------------------------------- // [Members] // -------------------------------------------------------------------------- uint32_t _argumentsData[kFuncArgsMax]; }; //! @brief Class used to build function without arguments. template struct FuncBuilder0 : public FuncPrototype { inline FuncBuilder0() { _setPrototype(TypeId::Id, NULL, 0); } }; //! @brief Class used to build function with 1 argument. template struct FuncBuilder1 : public FuncPrototype { inline FuncBuilder1() { static const uint32_t arguments[] = { TypeId::Id }; _setPrototype(TypeId::Id, arguments, ASMJIT_ARRAY_SIZE(arguments)); } }; //! @brief Class used to build function with 2 arguments. template struct FuncBuilder2 : public FuncPrototype { inline FuncBuilder2() { static const uint32_t arguments[] = { TypeId::Id, TypeId::Id }; _setPrototype(TypeId::Id, arguments, ASMJIT_ARRAY_SIZE(arguments)); } }; //! @brief Class used to build function with 3 arguments. template struct FuncBuilder3 : public FuncPrototype { inline FuncBuilder3() { static const uint32_t arguments[] = { TypeId::Id, TypeId::Id, TypeId::Id }; _setPrototype(TypeId::Id, arguments, ASMJIT_ARRAY_SIZE(arguments)); } }; //! @brief Class used to build function with 4 arguments. template struct FuncBuilder4 : public FuncPrototype { inline FuncBuilder4() { static const uint32_t arguments[] = { TypeId::Id, TypeId::Id, TypeId::Id, TypeId::Id }; _setPrototype(TypeId::Id, arguments, ASMJIT_ARRAY_SIZE(arguments)); } }; //! @brief Class used to build function with 5 arguments. template struct FuncBuilder5 : public FuncPrototype { inline FuncBuilder5() { static const uint32_t arguments[] = { TypeId::Id, TypeId::Id, TypeId::Id, TypeId::Id, TypeId::Id }; _setPrototype(TypeId::Id, arguments, ASMJIT_ARRAY_SIZE(arguments)); } }; //! @brief Class used to build function with 6 arguments. template struct FuncBuilder6 : public FuncPrototype { inline FuncBuilder6() { static const uint32_t arguments[] = { TypeId::Id, TypeId::Id, TypeId::Id, TypeId::Id, TypeId::Id, TypeId::Id }; _setPrototype(TypeId::Id, arguments, ASMJIT_ARRAY_SIZE(arguments)); } }; //! @brief Class used to build function with 7 arguments. template struct FuncBuilder7 : public FuncPrototype { inline FuncBuilder7() { static const uint32_t arguments[] = { TypeId::Id, TypeId::Id, TypeId::Id, TypeId::Id, TypeId::Id, TypeId::Id, TypeId::Id }; _setPrototype(TypeId::Id, arguments, ASMJIT_ARRAY_SIZE(arguments)); } }; //! @brief Class used to build function with 8 arguments. template struct FuncBuilder8 : public FuncPrototype { inline FuncBuilder8() { static const uint32_t arguments[] = { TypeId::Id, TypeId::Id, TypeId::Id, TypeId::Id, TypeId::Id, TypeId::Id, TypeId::Id, TypeId::Id }; _setPrototype(TypeId::Id, arguments, ASMJIT_ARRAY_SIZE(arguments)); } }; //! @brief Class used to build function with 9 arguments. template struct FuncBuilder9 : public FuncPrototype { inline FuncBuilder9() { static const uint32_t arguments[] = { TypeId::Id, TypeId::Id, TypeId::Id, TypeId::Id, TypeId::Id, TypeId::Id, TypeId::Id, TypeId::Id, TypeId::Id }; _setPrototype(TypeId::Id, arguments, ASMJIT_ARRAY_SIZE(arguments)); } }; //! @brief Class used to build function with 10 arguments. template struct FuncBuilder10 : public FuncPrototype { inline FuncBuilder10() { static const uint32_t arguments[] = { TypeId::Id, TypeId::Id, TypeId::Id, TypeId::Id, TypeId::Id, TypeId::Id, TypeId::Id, TypeId::Id, TypeId::Id, TypeId::Id }; _setPrototype(TypeId::Id, arguments, ASMJIT_ARRAY_SIZE(arguments)); } }; } // AsmJit namespace // [Api-End] #include "../core/apiend.h" // [Guard] #endif // _ASMJIT_CORE_FUNC_H desmume/src/libretro/jni/000700 001750 001750 00000000000 12756420131 016517 5ustar00sergiosergio000000 000000 desmume/src/addons/slot2_gbagame.cpp000664 001750 001750 00000021144 12755534123 020623 0ustar00sergiosergio000000 000000 /* Copyright (C) 2009 CrazyMax Copyright (C) 2009-2016 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the this software. If not, see . */ #include "../slot2.h" #include #include "../debug.h" #include "../NDSSystem.h" #include "../path.h" #include "../emufile.h" #define EEPROM 0x52504545 #define SRAM_ 0x4D415253 #define FLASH 0x53414C46 #define FLASH1M_ 0x5F4D3148 #define SIIRTC_V 0x52494953 static const char *saveTypes[] = { "EEPROM", "SRAM", "FLASH", "FLASH1M", "SIIRTC_V", }; class Slot2_GbaCart : public ISlot2Interface { private: EMUFILE* fROM; EMUFILE* fSRAM; u32 romSize; u32 sramSize; u32 saveType; struct { u32 size; u8 state; u8 cmd; u8 idDevice; u8 idManufacturer; u8 bank; } gbaFlash; u32 readRom(const u32 pos, const u8 size) { if (!fROM) return 0xFFFFFFFF; fROM->fseek(pos, SEEK_SET); u32 data = 0xFFFFFFFF; u32 readed = fROM->fread(&data, size); return data; } u32 readSRAM(const u32 pos, const u8 size) { if (!fSRAM) return 0xFFFFFFFF; fSRAM->fseek(pos, SEEK_SET); u32 data = 0xFFFFFFFF; u32 readed = fSRAM->fread(&data, size); return data; } void writeSRAM(const u32 pos, const u8 *data, u32 size) { if (!fSRAM) return; fSRAM->fseek(pos, SEEK_SET); u32 writed = size; fSRAM->fwrite(data, size); fSRAM->fflush(); } u32 scanSaveTypeGBA() { if (!fROM) return 0xFF; fROM->fseek(0, SEEK_SET); int size = fROM->size(); int lastpct=1; int len = fROM->size(); for(;;) { u32 tmp; u32 readed = fROM->fread(&tmp, 4); int pos = fROM->ftell(); int currPct = pos*100/(size-1); for(int i=lastpct;i= len) break; switch (tmp) { case EEPROM: return 1; case SRAM_: return 2; case FLASH: { u32 tmp = fROM->read32le(); return ((tmp == FLASH1M_)?3:5); } case SIIRTC_V: return 4; } } return 0xFF; } void gbaWriteFlash(u32 adr, u8 val) { if (!fSRAM) return; switch (gbaFlash.state) { case 0: if (adr == 0x0A005555) { if (val == 0xF0) { //INFO("GBAgame: Flash: reset\n"); gbaFlash.state = 0; gbaFlash.cmd = 0; return; } if (val == 0xAA) { gbaFlash.state = 1; return; } } if (adr == 0x0A000000) { if (gbaFlash.cmd == 0xB0) { gbaFlash.bank = val; gbaFlash.cmd = 0; //INFO("GBAgame: Flash: change bank %i\n", val); return; } } break; case 1: if ( (adr == 0x0A002AAA) && (val == 0x55) ) { gbaFlash.state = 2; return; } gbaFlash.state = 0; break; case 2: if (adr == 0x0A005555) { //INFO("GBAgame: Flash: send command flash 0x%02X\n", val); switch (val) { case 0x80: // Erase gbaFlash.state = 0x80; break; case 0x90: // Chip Identification gbaFlash.state = 0x90; break; case 0xA0: // Write gbaFlash.state = 0; break; default: gbaFlash.state = 0; break; } gbaFlash.cmd = val; return; } gbaFlash.state = 0; break; // erase case 0x80: if ( (adr == 0x0A005555) && (val == 0xAA) ) { gbaFlash.state = 0x81; return; } gbaFlash.state = 0; break; case 0x81: if ( (adr == 0x0A002AAA) && (val == 0x55) ) { gbaFlash.state = 0x82; return; } gbaFlash.state = 0; break; case 0x82: if (val == 0x30) { u32 ofs = (adr & 0x0000F000) + (0x10000 * gbaFlash.bank); //INFO("GBAgame: Flash: erase from 0x%08X to 0x%08X\n", ofs + 0x0A000000, ofs + 0x0A001000); u8 *tmp = new u8[0x1000]; memset(tmp, 0xFF, 0x1000); writeSRAM(ofs, tmp, 0x1000); delete [] tmp; } gbaFlash.state = 0; gbaFlash.cmd = 0; return; // Chip Identification case 0x90: if ( (adr == 0x0A005555) && (val == 0xAA) ) { gbaFlash.state = 0x91; return; } gbaFlash.state = 0; break; case 0x91: if ( (adr == 0x0A002AAA) && (val == 0x55) ) { gbaFlash.state = 0x92; return; } gbaFlash.state = 0; break; case 0x92: gbaFlash.state = 0; gbaFlash.cmd = 0; return; } if (gbaFlash.cmd == 0xA0) // write { writeSRAM((adr & 0x1FFFF) + (0x10000 * gbaFlash.bank), &val, 1); gbaFlash.state = 0; gbaFlash.cmd = 0; return; } #ifdef DEBUG INFO("GBAgame: Flash: write unknown atn 0x%08X = 0x%02X\n", adr, val); #endif } u8 gbaReadFlash(u32 adr) { if (!fSRAM) return 0xFF; if (gbaFlash.cmd == 0) return readSRAM((adr & 0x1FFFF) + (0x10000 * gbaFlash.bank), 1); //INFO("GBAgame: flash read at 0x%08X\n", adr); switch (gbaFlash.cmd) { case 0x90: // Chip Identification if (adr == 0x0A000000) return gbaFlash.idManufacturer; if (adr == 0x0A000001) return gbaFlash.idDevice; break; case 0xF0: // gbaFlash.state = 0; gbaFlash.cmd = 0; break; case 0xB0: // Bank switching break; default: #ifdef DEBUG INFO("GBAgame: Flash: read - unknown command at 0x%08X = 0x%02X\n", adr, gbaFlash.cmd); #endif break; } return 0xFF; } void Close() { delete fROM; fROM = NULL; delete fSRAM; fSRAM = NULL; romSize = 0; sramSize = 0; } public: Slot2_GbaCart() : fROM(NULL) , fSRAM(NULL) { Close(); } virtual Slot2Info const* info() { static Slot2InfoSimple info("GBA Cartridge", "GBA cartridge in slot", 0x03); return &info; } virtual void connect() { Close(); romSize = 0; sramSize = 0; if (gameInfo.romsize == 0) { return; } if (GBACartridge_RomPath.empty()) { return; } if (!strcasecmp(GBACartridge_RomPath.c_str(), "self")) { GBACartridge_RomPath = path.path; GBACartridge_SRAMPath = Path::GetFileNameWithoutExt(GBACartridge_RomPath) + "." + GBA_SRAM_FILE_EXT; } printf("GBASlot opening ROM: %s\n", GBACartridge_RomPath.c_str()); EMUFILE_FILE *inf = new EMUFILE_FILE(GBACartridge_RomPath, "rb"); fROM = inf; if (fROM->fail()) { printf(" - Failed\n"); Close(); return; } inf->EnablePositionCache(); romSize = fROM->size(); printf(" - Success (%u bytes)\n", romSize); // Load the GBA cartridge SRAM. inf = new EMUFILE_FILE(GBACartridge_SRAMPath, "rb+"); fSRAM = inf; if(fSRAM->fail()) { delete fSRAM; fSRAM = NULL; printf("GBASlot did not load associated SRAM.\n"); } else { inf->EnablePositionCache(); sramSize = fSRAM->size(); printf("Scanning GBA rom to ID save type\n"); saveType = scanSaveTypeGBA(); printf("\nGBASlot found SRAM (%s - %u bytes) at:\n%s\n", (saveType == 0xFF)?"Unknown":saveTypes[saveType], sramSize, GBACartridge_SRAMPath.c_str()); gbaFlash.size = sramSize; if (gbaFlash.size <= (64 * 1024)) { gbaFlash.idDevice = 0x1B; gbaFlash.idManufacturer = 0x32; } else { gbaFlash.idDevice = 0x09; gbaFlash.idManufacturer = 0xC2; } gbaFlash.state = 0; } } virtual void disconnect() { Close(); } virtual void writeByte(u8 PROCNUM, u32 addr, u8 val) { if ((addr >= 0x0A000000) && (addr < 0x0A010000)) { switch (saveType) { case 3: // Flash case 5: gbaWriteFlash(addr, val); break; default: break; } } } virtual u8 readByte(u8 PROCNUM, u32 addr) { if (addr < 0x0A000000) return (u8)readRom(addr - 0x08000000, 1); if (addr < 0x0A010000) { if ((saveType == 3) || (saveType == 5)) return gbaReadFlash(addr); return (u8)readSRAM(addr - 0x0A000000, 1); } return 0xFF; } virtual u16 readWord(u8 PROCNUM, u32 addr) { if (addr < 0x0A000000) return (u16)readRom(addr - 0x08000000, 2); if (addr < 0x0A010000) return (u16)readSRAM(addr - 0x0A000000, 2); return 0xFFFF; } virtual u32 readLong(u8 PROCNUM, u32 addr) { if (addr < 0x0A000000) return (u32)readRom(addr - 0x08000000, 4); if (addr < 0x0A010000) return (u32)readSRAM(addr - 0x0A000000, 4); return 0xFFFFFFFF; } }; ISlot2Interface* construct_Slot2_GbaCart() { return new Slot2_GbaCart(); } desmume/src/libretro-common/file/nbio/test/nbio_test.c000664 001750 001750 00000002415 12755534123 024230 0ustar00sergiosergio000000 000000 #include #include #include static void nbio_write_test(void) { size_t size; bool looped = false; void* ptr = NULL; struct nbio_t* write = nbio_open("test.bin", NBIO_WRITE); nbio_resize(write, 1024*1024); ptr = nbio_get_ptr(write, &size); if (size != 1024*1024) puts("ERROR: wrong size (1)"); memset(ptr, 0x42, 1024*1024); nbio_begin_write(write); while (!nbio_iterate(write)) looped=true; if (!looped) puts("Write finished immediately?"); nbio_free(write); } static void nbio_read_test(void) { size_t size; bool looped = false; struct nbio_t* read = nbio_open("test.bin", NBIO_READ); void* ptr = nbio_get_ptr(read, &size); if (size != 1024*1024) puts("ERROR: wrong size (2)"); if (ptr) puts("Read pointer is available before iterating?"); nbio_begin_read(read); while (!nbio_iterate(read)) looped=true; if (!looped) puts("Read finished immediately?"); ptr = nbio_get_ptr(read, &size); if (size != 1024*1024) puts("ERROR: wrong size (3)"); if (*(char*)ptr != 0x42 || memcmp(ptr, (char*)ptr+1, 1024*1024-1)) puts("ERROR: wrong data"); nbio_free(read); } int main(void) { nbio_write_test(); nbio_read_test(); } desmume/src/mc.cpp000664 001750 001750 00000110712 12755534123 015244 0ustar00sergiosergio000000 000000 /* Copyright (C) 2006 thoduv Copyright (C) 2006-2007 Theo Berkau Copyright (C) 2008-2015 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the this software. If not, see . */ #include "mc.h" #include #include #include "common.h" #include "armcpu.h" #include "debug.h" #include "MMU.h" #include "readwrite.h" #include "NDSSystem.h" #include "path.h" #include "emufile.h" #include "utils/advanscene.h" //#define _DONT_SAVE_BACKUP //#define _MCLOG // TODO: motion device was broken //#define _ENABLE_MOTION #define BM_CMD_NOP 0x00 #define BM_CMD_AUTODETECT 0xFF #define BM_CMD_WRITESTATUS 0x01 #define BM_CMD_WRITELOW 0x02 #define BM_CMD_READLOW 0x03 #define BM_CMD_WRITEDISABLE 0x04 #define BM_CMD_READSTATUS 0x05 #define BM_CMD_WRITEENABLE 0x06 #define BM_CMD_WRITEHIGH 0x0A #define BM_CMD_READHIGH 0x0B // Pokemons IrDA #define BM_CMD_IRDA 0x08 //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*/ #ifdef _MCLOG #define MCLOG(...) printf(__VA_ARGS__) #else #define MCLOG(...) #endif static const char* DESMUME_BACKUP_FOOTER_TXT = "|<--Snip above here to create a raw sav by excluding this DeSmuME savedata footer:"; static const char* kDesmumeSaveCookie = "|-DESMUME SAVE-|"; static const u32 saveSizes[] = {512, // 4k 8*1024, // 64k 32*1024, // 512k 64*1024, // 1Mbit 256*1024, // 2Mbit 512*1024, // 4Mbit 1024*1024, // 8Mbit 2048*1024, // 16Mbit 4096*1024, // 32Mbit 8192*1024, // 64Mbit 16384*1024, // 128Mbit 32768*1024, // 256Mbit 65536*1024, // 512Mbit 0xFFFFFFFF}; static const u32 saveSizes_count = ARRAY_SIZE(saveSizes); //the lookup table from user save types to save parameters const SAVE_TYPE save_types[] = { {"Autodetect", MC_TYPE_AUTODETECT, 1, 0}, {"EEPROM 4kbit", MC_TYPE_EEPROM1, MC_SIZE_4KBITS , 1}, {"EEPROM 64kbit", MC_TYPE_EEPROM2, MC_SIZE_64KBITS , 2}, {"EEPROM 512kbit", MC_TYPE_EEPROM2, MC_SIZE_512KBITS , 2}, {"FRAM 256kbit", MC_TYPE_FRAM, MC_SIZE_256KBITS , 2}, {"FLASH 2Mbit", MC_TYPE_FLASH, MC_SIZE_2MBITS , 3}, {"FLASH 4Mbit", MC_TYPE_FLASH, MC_SIZE_4MBITS , 3}, {"FLASH 8Mbit", MC_TYPE_FLASH, MC_SIZE_8MBITS , 3}, {"FLASH 16Mbit", MC_TYPE_FLASH, MC_SIZE_16MBITS , 3}, {"FLASH 32Mbit", MC_TYPE_FLASH, MC_SIZE_32MBITS , 3}, {"FLASH 64Mbit", MC_TYPE_FLASH, MC_SIZE_64MBITS , 3}, {"FLASH 128Mbit", MC_TYPE_FLASH, MC_SIZE_128MBITS , 3}, {"FLASH 256Mbit", MC_TYPE_FLASH, MC_SIZE_256MBITS , 3}, {"FLASH 512Mbit", MC_TYPE_FLASH, MC_SIZE_512MBITS , 3} }; //forces the currently selected backup type to be current //(can possibly be used to repair poorly chosen save types discovered late in gameplay i.e. pokemon gamers) void backup_forceManualBackupType() { MMU_new.backupDevice.forceManualBackupType(); } void backup_setManualBackupType(int type) { CommonSettings.manualBackupType = type; } bool BackupDevice::save_state(EMUFILE* os) { size_t elements_read; u32 version = 5; u32 savePos = fpMC->ftell(); std::vector data(fsize); fpMC->fseek(0, SEEK_SET); if (data.size() != 0) elements_read = fread(&data[0], 1, fsize, fpMC->get_fp()); if (elements_read != fsize) printf( "Expected %u bytes from saved state but read %lu.\n", fsize, (long unsigned int)elements_read ); //v0 write32le(version,os); write32le(write_enable,os); write32le(com,os); write32le(addr_size,os); write32le(addr_counter,os); write32le((u32)state,os); writebuffer(data,os); writebuffer(data_autodetect,os); //v1 write32le(addr,os); //v2 write8le(motionInitState,os); write8le(motionFlag,os); //v3 writebool(reset_command_state,os); //v4 write8le(write_protect,os); //v5 write32le(savePos,os); fpMC->fseek(savePos, SEEK_SET); data.clear(); return true; } bool BackupDevice::load_state(EMUFILE* is) { u32 version; u32 temp; std::vector data; if(read32le(&version,is)!=1) return false; if(version>=0) { readbool(&write_enable,is); read32le(&com,is); read32le(&addr_size,is); read32le(&addr_counter,is); read32le(&temp,is); state = (STATE)temp; readbuffer(data,is); readbuffer(data_autodetect,is); } if(version>=1) read32le(&addr,is); if(version>=2) { read8le(&motionInitState,is); read8le(&motionFlag,is); } if(version>=3) { readbool(&reset_command_state,is); } if(version>=4) { read8le(&write_protect,is); } fsize = data.size(); #ifndef _DONT_SAVE_BACKUP fpMC->fseek(0, SEEK_SET); if(data.size()!=0) fwrite((char*)&data[0], 1, fsize, fpMC->get_fp()); ensure(data.size(), fpMC); #endif if(version>=5) { read32le(&temp,is); fpMC->fseek(temp, SEEK_SET); } else fpMC->fseek(addr, SEEK_SET); return true; } BackupDevice::BackupDevice() { size_t elements_read, elements_written; fpMC = NULL; fsize = 0; addr_size = 0; //default for most games; will be altered where appropriate //usually 0xFF, but occasionally others. If these exceptions could be related to a particular backup memory type, that would be helpful. //at first we assumed it would be 0x00, but baby pals proved that it should be 0xFF: // the game reads its initial sound volumes from uninitialized data, and if it is 0, the game will be silent // if it is 0xFF then the game starts with its sound and music at max, as presumably it is supposed to. // so in r3303 we finally changed it (no$ appears definitely to initialize to 0xFF) uninitializedValue = 0xFF; if (gameInfo.romsize == 0) return; char buf[PATH_MAX_LENGTH] = {0}; memset(buf, 0, sizeof(buf)); path.getpathnoext(path.BATTERY, buf); filename = std::string(buf) + ".dsv"; MCLOG("MC: %s\n", filename.c_str()); bool fexists = (access(filename.c_str(), 0) == 0)?true:false; if (fexists && CommonSettings.backupSave) { std::string tmp_fsav = std::string(buf) + ".dsv.bak"; EMUFILE_FILE *in = new EMUFILE_FILE(filename, "rb"); if (!in->fail()) { u32 sz = in->size(); if (sz > 0) { EMUFILE_FILE *out = new EMUFILE_FILE(tmp_fsav, "wb"); if (!out->fail()) { u8 *data = new u8[sz]; elements_read = fread(data, 1, sz, in->get_fp()); elements_written = fwrite(data, 1, sz, out->get_fp()); if (elements_read != sz || elements_written != sz) printf("Possibly incomplete data read/write.\n"); delete [] data; } delete out; } } delete in; } if (!fexists) { printf("DeSmuME .dsv save file not found. Trying to load an old raw .sav file.\n"); std::string tmp_fsav = std::string(buf) + ".sav"; EMUFILE_FILE *fpTmp = new EMUFILE_FILE(tmp_fsav, "rb"); if (!fpTmp->fail()) { u32 sz = fpTmp->size(); if (sz > 0) { EMUFILE_FILE *fpOut = new EMUFILE_FILE(filename, "wb"); if (!fpOut->fail()) { u8 *buf = new u8[sz + 1]; if ((buf) && (fread(buf, 1, sz, fpTmp->get_fp()) == sz)) { if (no_gba_unpack(buf, sz)) printf("Converted from no$gba save.\n"); else sz = trim(buf, sz); if (fwrite(buf, 1, sz, fpOut->get_fp()) == sz) { u8 res = searchFileSaveType(sz); if (res != 0xFF) { info.type = (res + 1); addr_size = info.addr_size = save_types[info.type].addr_size; info.size = fsize = sz; ensure(sz, fpOut); fsize = 0; } else info.type = 0; fexists = true; } } delete [] buf; } delete fpOut; } } delete fpTmp; } fpMC = new EMUFILE_FILE(filename, fexists?"rb+":"wb+"); if (!fpMC->fail()) { fsize = fpMC->size(); if (fsize < saveSizes[0]) fpMC->truncate(0); if (readFooter() == 0) fsize -= (strlen(kDesmumeSaveCookie) + strlen(DESMUME_BACKUP_FOOTER_TXT) + 24); else { memset(&info, 0, sizeof(info)); fsize = 0; } fpMC->fseek(0, SEEK_SET); u32 left = 0; if (CommonSettings.autodetectBackupMethod == 1) { if (advsc.isLoaded()) { info.type = advsc.getSaveType(); if (info.type != 0xFF && info.type != 0xFE) { info.type++; u32 adv_size = save_types[info.type].size; if (info.size > adv_size) { info.size = adv_size; fpMC->truncate(adv_size); ensure(adv_size, fpMC); } else if (info.size < adv_size) { left = adv_size - info.size; info.size = adv_size; ensure(adv_size); } fsize = adv_size; } } } addr_size = info.addr_size; info.padSize = fsize; //none of the other fields are used right now if (CommonSettings.autodetectBackupMethod != 1 && info.type == 0) { info.type = searchFileSaveType(info.size); if (info.type == 0xFF) info.type = 0; } u32 ss = (info.padSize * 8) / 1024; bool _Mbit = false; if (ss >= 1024) { ss /= 1024; _Mbit = true; } if (ss > 0) printf("Backup size: %u %cbit\n", ss, _Mbit?'M':'K'); } state = (fsize > 0)?RUNNING:DETECTING; reset(); } BackupDevice::~BackupDevice() { delete fpMC; fpMC = NULL; } int BackupDevice::readFooter() { //scan for desmume save footer const s32 cookieLen = (s32)strlen(kDesmumeSaveCookie); char *sigbuf = new char[cookieLen]; fpMC->fseek(-cookieLen, SEEK_END); fpMC->fread(sigbuf, cookieLen); int cmp = memcmp(sigbuf,kDesmumeSaveCookie,cookieLen); delete[] sigbuf; if (cmp) return -1; //desmume format fpMC->fseek(-cookieLen, SEEK_END); fpMC->fseek(-4, SEEK_CUR); u32 version = 0xFFFFFFFF; fpMC->read32le(&version); if (version != 0) return -2; fpMC->fseek(-24, SEEK_CUR); fpMC->read32le(&info.size); fpMC->read32le(&info.padSize); fpMC->read32le(&info.type); fpMC->read32le(&info.addr_size); fpMC->read32le(&info.mem_size); MCLOG("DeSmuME backup footer:\n"); MCLOG("\t* size:\t\t%u\n", info.size); MCLOG("\t* padSize:\t%u\n", info.padSize); MCLOG("\t* type (%u):\t%s\n", info.type, save_types[info.type].descr); MCLOG("\t* addr_size:\t%u\n", info.addr_size); MCLOG("\t* mem_size:\t%u\n", info.mem_size); return 0; } u8 BackupDevice::read() { u8 val = 0xFF; fpMC->read8le(&val); return val; } u8 BackupDevice::readByte(u32 addr, const u8 init) { u8 val = init; fpMC->fseek(addr, SEEK_SET); fpMC->read8le(&val); return val; } u16 BackupDevice::readWord(u32 addr, const u16 init) { u16 val = init; fpMC->fseek(addr, SEEK_SET); fpMC->read16le(&val); return val; } u32 BackupDevice::readLong(u32 addr, const u32 init) { u32 val = init; fpMC->fseek(addr, SEEK_SET); fpMC->read32le(&val); return val; } u8 BackupDevice::readByte(const u8 init) { u8 val = init; fpMC->read8le(&val); return val; } u16 BackupDevice::readWord(const u16 init) { u16 val = init; fpMC->read16le(&val); return val; } u32 BackupDevice::readLong(const u32 init) { u32 val = init; fpMC->read32le(&val); return val; } bool BackupDevice::write(u8 val) { #ifdef _DONT_SAVE_BACKUP return true; #endif return fwrite(&val, 1, 1, fpMC->get_fp())?true:false; } void BackupDevice::writeByte(u32 addr, u8 val) { fpMC->fseek(addr, SEEK_SET); fpMC->write8le(val); } void BackupDevice::writeWord(u32 addr, u16 val) { fpMC->fseek(addr, SEEK_SET); fpMC->write16le(val); } void BackupDevice::writeLong(u32 addr, u32 val) { fpMC->fseek(addr, SEEK_SET); fpMC->write32le(val); } void BackupDevice::writeByte(u8 val) { fpMC->write8le(val); } void BackupDevice::writeWord(u16 val) { fpMC->write16le(val); } void BackupDevice::writeLong(u32 val) { fpMC->write32le(val); } void BackupDevice::seek(u32 pos) { fpMC->fseek(pos, SEEK_SET); } void BackupDevice::flushBackup() { fpMC->fflush(); } bool BackupDevice::saveBuffer(u8 *data, u32 size, bool _rewind, bool _truncate) { if (_rewind) { fpMC->fseek(0, SEEK_SET); if (_truncate) fpMC->truncate(0); } fsize = size; fwrite(data, 1, size, fpMC->get_fp()); ensure(size, fpMC); return true; } void BackupDevice::reset_hardware() { com = 0; reset_command_state = false; write_enable = FALSE; write_protect = 0; addr = addr_counter = 0; motionInitState = MOTION_INIT_STATE_IDLE; motionFlag = MOTION_FLAG_NONE; } void BackupDevice::reset() { reset_hardware(); data_autodetect.resize(0); //if the user has requested a manual choice for backup type, and we havent imported a raw save file, then apply it now if(state == DETECTING && CommonSettings.manualBackupType != MC_TYPE_AUTODETECT) { state = RUNNING; int savetype = save_types[CommonSettings.manualBackupType].media_type; int savesize = save_types[CommonSettings.manualBackupType].size; ensure((u32)savesize); //expand properly if necessary addr_size = addr_size_for_old_save_type(savetype); } } void BackupDevice::close_rom() { fpMC->fflush(); delete fpMC; fpMC = NULL; } //todo - this function is horrible. it's only needed due to our big disorganization between save types and sizes. //the concept of a backup memory type "enum" (not actually an enum) was added after the original .dsv format //the original .dsv format contains a 'type' which is kind of useless (flash vs eeprom) and then a memory size //the memory size also happens to exactly identify a memory type. this function performs that mapping. //we should fix this in a new revision of .dsv u8 BackupDevice::searchFileSaveType(u32 size) { for (u8 i = 1; i < MAX_SAVE_TYPES; i++) { if (size == save_types[i].size) return (i - 1); } return 0xFF; } void BackupDevice::detect() { if (!reset_command_state) return; if(state == DETECTING && data_autodetect.size()>0) { //we can now safely detect the save address size u32 autodetect_size = data_autodetect.size(); printf("Autodetecting with autodetect_size=%d\n",autodetect_size); //detect based on rules switch(autodetect_size) { case 0: case 1: addr_size = 1; //choose 1 just to keep the busted savefile from growing too big msgbox->error("Catastrophic error while autodetecting save type.\nIt will need to be specified manually\n"); break; case 2: //the modern typical case for small eeproms addr_size = 1; break; case 3: //another modern typical case.. //but unfortunately we select this case on accident sometimes when what it meant to do was present the archaic 1+2 case //(the archaic 1+2 case is: specifying one address byte, and then reading the first two bytes, instead of the first one byte, as most other games would do.) //so, we're gonna hack in checks for the games that are doing this addr_size = 2; // TODO: will study a deep, why this happens (wrong detect size) if(!memcmp(gameInfo.header.gameCode,"AL3", 3)) addr_size = 1; //spongebob atlantis squarepantis. if(!memcmp(gameInfo.header.gameCode,"AH5", 3)) addr_size = 1; //over the hedge if(!memcmp(gameInfo.header.gameCode,"AVH", 3)) addr_size = 1; //over the hedge - Hammy Goes Nuts! if(!memcmp(gameInfo.header.gameCode,"AQ3", 3)) addr_size = 1; //spider-man 3 break; case 4: //a modern typical case addr_size = 3; if(!memcmp(gameInfo.header.gameCode,"ASM", 3)) addr_size = 2; //super mario 64 ds break; default: //the archaic case: write the address and then some modulo-4 number of bytes //why modulo 4? who knows. //SM64 (KOR) makes it here with autodetect_size=11 and nothing interesting in the buffer addr_size = autodetect_size & 3; if(!memcmp(gameInfo.header.gameCode,"BDE", 3)) addr_size = 2; // Dementium II break; } state = RUNNING; data_autodetect.resize(0); } } void BackupDevice::checkReset() { if (reset_command_state) { //printf("MC : reset command\n"); if(com == BM_CMD_WRITELOW || com == BM_CMD_WRITEHIGH) fpMC->fflush(); com = 0; reset_command_state = false; } } u8 BackupDevice::data_command(u8 val, u8 PROCNUM) { //printf("MC%c : cmd %02X, val %02X\n", PROCNUM?'7':'9', com, val); #ifdef _ENABLE_MOTION //motion: some guessing here... hope it doesn't break anything if(com == BM_CMD_READLOW && motionInitState == MOTION_INIT_STATE_RECEIVED_4_B && val == 0) { motionInitState = MOTION_INIT_STATE_IDLE; motionFlag |= MOTION_FLAG_ENABLED; //return 0x04; //return 0x04 to enable motion!!!!! return 0; //but we return 0 to disable it! since we don't emulate it anyway } //if the game firmly believes we have motion support, then ignore all motion commands, since theyre not emulated. if(motionFlag & MOTION_FLAG_SENSORMODE) { return 0; } #endif switch (com) { case BM_CMD_WRITESTATUS: //printf("MC%c: write status %02X\n", PROCNUM?'7':'9', val); write_protect = (val & 0xFC); break; case BM_CMD_WRITELOW: case BM_CMD_READLOW: //handle data or address if(state == DETECTING) { if(com == BM_CMD_WRITELOW) printf("MC%c: Unexpected backup device initialization sequence using writes!\n", PROCNUM?'7':'9'); //just buffer the data until we're no longer detecting data_autodetect.push_back(val); detect(); val = 0xFF; } else { if(addr_counterfseek(addr, SEEK_SET); } else { //why does tomb raider underworld access 0x180 and go clear through to 0x280? //should this wrap around at 0 or at 0x100? //TODO - dont other backup memory types have similar wraparound issues? if(addr_size == 1) { addr &= 0x1FF; //since we changed the address unexpectedly (non-sequentially), be sure to seek the FP fpMC->fseek(addr, SEEK_SET); } //if we're writing a byte at address 0, we need to ensure that we have at least 1 byte in the file (IOW, ensure to size addr+1 == 0+1) ensure(addr+1); if(com == BM_CMD_READLOW) { val = read(); //MCLOG("BACKUP: Read at 0x%08X, value 0x%02X\n", addr, val); } else if(write_enable) { write(val); //MCLOG("BACKUP: Write to %08X, value %02Xh\n", addr, val); } addr++; } } break; case BM_CMD_READSTATUS: //handle request to read status //LOG("Backup Memory Read Status: %02X\n", write_enable << 1); val = (write_enable << 1) | write_protect; break; case BM_CMD_IRDA: printf("MC%c: Unverified Backup Memory command: %02X FROM %08X\n", PROCNUM?'7':'9', com, PROCNUM?NDS_ARM7.instruct_adr:NDS_ARM9.instruct_adr); val = 0xAA; break; default: if (com != 0) { printf("MC%c: Unhandled Backup Memory command %02X, value %02X (PC:%08X)\n", PROCNUM?'7':'9', com, val, PROCNUM?NDS_ARM7.instruct_adr:NDS_ARM9.instruct_adr); break; } com = val; val = 0xFF; //there is no current command. receive one switch (com) { case BM_CMD_NOP: break; case BM_CMD_WRITESTATUS: break; #ifdef _ENABLE_MOTION case 0xFE: if(motionInitState == MOTION_INIT_STATE_IDLE) { motionInitState = MOTION_INIT_STATE_FE; return 0; } break; case 0xFD: if(motionInitState == MOTION_INIT_STATE_FE) { motionInitState = MOTION_INIT_STATE_FD; return 0; } break; case 0xFB: if(motionInitState == MOTION_INIT_STATE_FD) { motionInitState = MOTION_INIT_STATE_FB; return 0; } break; case 0xF8: //enable sensor mode if(motionInitState == MOTION_INIT_STATE_FD) { motionInitState = MOTION_INIT_STATE_IDLE; motionFlag |= MOTION_FLAG_SENSORMODE; return 0; } break; case 0xF9: //disable sensor mode if(motionInitState == MOTION_INIT_STATE_FD) { motionInitState = MOTION_INIT_STATE_IDLE; motionFlag &= ~MOTION_FLAG_SENSORMODE; return 0; } break; #endif case BM_CMD_IRDA: printf("MC%c: Unverified Backup Memory command: %02X FROM %08X\n", PROCNUM?'7':'9', com, PROCNUM?NDS_ARM7.instruct_adr:NDS_ARM9.instruct_adr); val = 0xAA; break; case BM_CMD_WRITEDISABLE: //printf("MC%c: write disable\n", PROCNUM?'7':'9'); #ifdef _ENABLE_MOTION switch (motionInitState) { case MOTION_INIT_STATE_IDLE: motionInitState = MOTION_INIT_STATE_RECEIVED_4; break; case MOTION_INIT_STATE_RECEIVED_4: motionInitState = MOTION_INIT_STATE_RECEIVED_4_B; break; } #endif write_enable = FALSE; break; case BM_CMD_READSTATUS: break; case BM_CMD_WRITEENABLE: //printf("MC%c: write enable\n", PROCNUM?'7':'9'); write_enable = TRUE; break; case BM_CMD_WRITELOW: case BM_CMD_READLOW: //printf("XLO: %08X\n",addr); addr_counter = 0; addr = 0; break; case BM_CMD_WRITEHIGH: case BM_CMD_READHIGH: //printf("XHI: %08X\n",addr); if(com == BM_CMD_WRITEHIGH) com = BM_CMD_WRITELOW; if(com == BM_CMD_READHIGH) com = BM_CMD_READLOW; addr_counter = 0; addr = 0; if(addr_size==1) { //"write command that's only available on ST M95040-W that I know of" //this makes sense, since this device would only have a 256 bytes address space with writelow //and writehigh would allow access to the upper 256 bytes //but it was detected in pokemon diamond also during the main save process addr = 0x1; } break; default: printf("MC%c: Unhandled Backup Memory command: %02X FROM %08X\n", PROCNUM?'7':'9', com, PROCNUM?NDS_ARM7.instruct_adr:NDS_ARM9.instruct_adr); break; } //switch(val) break; } //switch (com) #ifdef _ENABLE_MOTION //motion control state machine broke, return to ground motionInitState = MOTION_INIT_STATE_IDLE; #endif checkReset(); return val; } //guarantees that the data buffer has room enough for the specified number of bytes void BackupDevice::ensure(u32 addr, EMUFILE_FILE *fpOut) { ensure(addr, uninitializedValue, fpOut); } void BackupDevice::ensure(u32 addr, u8 val, EMUFILE_FILE *fpOut) { if (!fpOut && (addr < fsize)) return; EMUFILE_FILE *fp = fpOut?fpOut:fpMC; #ifndef _DONT_SAVE_BACKUP fp->fseek(fsize, SEEK_SET); #endif u32 padSize = pad_up_size(addr); u32 size = padSize - fsize; info.padSize = info.size = fsize = padSize; int type = searchFileSaveType(fsize); if (type != 0xFF) info.type = (type + 1); #ifndef _DONT_SAVE_BACKUP if (size > 0) { u8 *tmp = new u8[size]; memset(tmp, val, size); fwrite(tmp, 1, size, fp->get_fp()); delete [] tmp; } //this is just for humans to read fp->fprintf(DESMUME_BACKUP_FOOTER_TXT); //and now the actual footer fp->write32le(addr); //the size of data that has actually been written fp->write32le(padSize); //the size we padded it to fp->write32le(info.type); //save memory type fp->write32le(addr_size); fp->write32le(info.size); //save memory size fp->write32le((u32)0); //version number fp->fprintf("%s", kDesmumeSaveCookie); //this is what we'll use to recognize the desmume format save fp->fflush(); //this is a HORRIBLE IDEA. //leave the FP positioned to write the final byte //this is a HACK to make the basic read/write byte operation work when it calls ensure(). //IDEALLY, no assumptions about the file pointer can be made. //but someone (actually, not really) so very carefully profiled the save IO code and discovered that not fseeking for every byte read/write was a great optimization. //so, now all this code is depending/assuming on the FP being kept in a precise position, and I dont think its smart to change the main user of this assumption to paper over this bug by making it fseek before read/write, while leaving other unknown assuming clients intact fpMC->fseek(addr-1, SEEK_SET); #endif } u32 BackupDevice::addr_size_for_old_save_size(int bupmem_size) { switch(bupmem_size) { case MC_SIZE_4KBITS: return 1; case MC_SIZE_64KBITS: case MC_SIZE_256KBITS: case MC_SIZE_512KBITS: return 2; case MC_SIZE_1MBITS: case MC_SIZE_2MBITS: case MC_SIZE_4MBITS: case MC_SIZE_8MBITS: case MC_SIZE_16MBITS: case MC_SIZE_64MBITS: return 3; default: return 0xFFFFFFFF; } } u32 BackupDevice::addr_size_for_old_save_type(int bupmem_type) { switch(bupmem_type) { case MC_TYPE_EEPROM1: return 1; case MC_TYPE_EEPROM2: case MC_TYPE_FRAM: return 2; case MC_TYPE_FLASH: return 3; default: return 0xFFFFFFFF; } } // TODO: this is required yet? void BackupDevice::load_old_state(u32 addr_size, u8* data, u32 datasize) { //state = RUNNING; //this->addr_size = addr_size; //resize(datasize); //memcpy(&this->data[0],data,datasize); //dump back out as a dsv, just to keep things sane //flush(); } //======================================================================= Tools //======================================================================= //======================================================================= u32 BackupDevice::importDataSize(const char *filename) { u32 res = 0; if (strlen(filename) < 4) return 0; if ((memcmp(filename + strlen(filename) - 4, ".duc", 4) == 0) || (memcmp(filename + strlen(filename) - 4, ".dss", 4) == 0)) { res = get_save_duc_size(filename); if (res == 0xFFFFFFFF) return 0; return res; } res = get_save_nogba_size(filename); if (res != 0xFFFFFFFF) return res; res = get_save_raw_size(filename); if (res != 0xFFFFFFFF) return res; return 0; } bool BackupDevice::importData(const char *filename, u32 force_size) { bool res = false; if (strlen(filename) < 4) return res; if ((memcmp(filename + strlen(filename) - 4, ".duc", 4) == 0) || (memcmp(filename + strlen(filename) - 4, ".dss", 4) == 0)) res = import_duc(filename, force_size); else if (import_no_gba(filename, force_size)) res = true; else res = import_raw(filename, force_size); if (res) NDS_Reset(); return res; } bool BackupDevice::exportData(const char *filename) { if (strlen(filename) < 4) return false; if (memcmp(filename + strlen(filename) - 5, ".sav*", 5) == 0) { char tmp[PATH_MAX_LENGTH]; memset(tmp, 0, PATH_MAX_LENGTH); strcpy(tmp, filename); tmp[strlen(tmp)-1] = 0; return export_no_gba(tmp); } if (memcmp(filename + strlen(filename) - 4, ".sav", 4) == 0) return export_raw(filename); return false; } //======================================================================= no$GBA //======================================================================= //======================================================================= const char no_GBA_HEADER_ID[] = "NocashGbaBackupMediaSavDataFile"; const char no_GBA_HEADER_SRAM_ID[] = "SRAM"; u32 BackupDevice::get_save_nogba_size(const char* fname) { FILE *fsrc = fopen(fname, "rb"); if (fsrc) { char src[0x50] = {0}; u32 fsize = 0; fseek(fsrc, 0, SEEK_END); fsize = ftell(fsrc); fseek(fsrc, 0, SEEK_SET); if (fsize < 0x50) { fclose(fsrc); return 0xFFFFFFFF; } memset(&src[0], 0, sizeof(src)); if (fread(src, 1, sizeof(src), fsrc) != sizeof(src)) { fclose(fsrc); return 0xFFFFFFFF; } for (u8 i = 0; i < 0x1F; i++) if (src[i] != no_GBA_HEADER_ID[i]) { fclose(fsrc); return 0xFFFFFFFF; } if (src[0x1F] != 0x1A) { fclose(fsrc); return 0xFFFFFFFF; } for (int i = 0; i < 0x4; i++) if (src[i+0x40] != no_GBA_HEADER_SRAM_ID[i]) { fclose(fsrc); return 0xFFFFFFFF; } u32 compressMethod = *((u32*)(src+0x44)); if (compressMethod == 0) { fclose(fsrc); return *((u32*)(src+0x48)); } else if (compressMethod == 1) { fclose(fsrc); return *((u32*)(src+0x4C)); } fclose(fsrc); } return 0xFFFFFFFF; } u32 BackupDevice::get_save_nogba_size(u8 *data) { for (u8 i = 0; i < 0x1F; i++) if (data[i] != no_GBA_HEADER_ID[i]) return 0xFFFFFFFF; if (data[0x1F] != 0x1A) return 0xFFFFFFFF; for (int i = 0; i < 0x4; i++) if (data[i+0x40] != no_GBA_HEADER_SRAM_ID[i]) return 0xFFFFFFFF; u32 compressMethod = *((u32*)(data+0x44)); if (compressMethod == 0) return *((u32*)(data+0x48)); if (compressMethod == 1) return *((u32*)(data+0x4C)); return 0xFFFFFFFF; } static int no_gba_unpackSAV(void *in_buf, u32 fsize, void *out_buf, u32 &size) { u8 *src = (u8 *)in_buf; u8 *dst = (u8 *)out_buf; u32 src_pos = 0; u32 dst_pos = 0; u8 cc = 0; u32 size_unpacked = 0; u32 size_packed = 0; u32 compressMethod = 0; if (fsize < 0x50) return (1); for (int i = 0; i < 0x1F; i++) { if (src[i] != no_GBA_HEADER_ID[i]) return (2); } if (src[0x1F] != 0x1A) return (2); for (int i = 0; i < 0x4; i++) { if (src[i+0x40] != no_GBA_HEADER_SRAM_ID[i]) return (3); } compressMethod = *((u32*)(src+0x44)); if (compressMethod == 0) // unpacked { size_unpacked = *((u32*)(src+0x48)); src_pos = 0x4C; for (u32 i = 0; i < size_unpacked; i++) { dst[dst_pos++] = src[src_pos++]; } size = dst_pos; return (0); } if (compressMethod == 1) // packed (method 1) { size_packed = *((u32*)(src+0x48)); size_unpacked = *((u32*)(src+0x4C)); src_pos = 0x50; while (true) { cc = src[src_pos++]; if (cc == 0) { size = dst_pos; return (0); } if (cc == 0x80) { u16 tsize = *((u16*)(src+src_pos+1)); for (int t = 0; t < tsize; t++) dst[dst_pos++] = src[src_pos]; src_pos += 3; continue; } if (cc > 0x80) // repeat { cc -= 0x80; for (int t = 0; t < cc; t++) dst[dst_pos++] = src[src_pos]; src_pos++; continue; } // copy for (int t = 0; t < cc; t++) dst[dst_pos++] = src[src_pos++]; } size = dst_pos; return (0); } return (200); } u32 BackupDevice::trim(void *buf, u32 size) { u32 rows = size / 16; u32 pos = (size - 16); u8 *src = (u8*)buf; for (unsigned int i = 0; i < rows; i++, pos -= 16) { if (src[pos] == 0xFF) { for (int t = 0; t < 16; t++) { if (src[pos+t] != 0xFF) return (pos+16); } } else { return (pos+16); } } return (size); } u32 BackupDevice::fillLeft(u32 size) { for (u32 i = 1; i < ARRAY_SIZE(save_types); i++) { if (size <= (u32)save_types[i].size) return (size + (save_types[i].size - size)); } return size; } bool BackupDevice::import_no_gba(const char *fname, u32 force_size) { FILE *fsrc = fopen(fname, "rb"); u8 *in_buf = NULL; u8 *out_buf = NULL; if (fsrc) { u32 fsize = 0; fseek(fsrc, 0, SEEK_END); fsize = ftell(fsrc); fseek(fsrc, 0, SEEK_SET); //printf("Open %s file (size %i bytes)\n", fname, fsize); in_buf = new u8 [fsize]; if (fread(in_buf, 1, fsize, fsrc) == fsize) { out_buf = new u8 [8 * 1024 * 1024 / 8]; u32 size = 0; memset(out_buf, 0xFF, 8 * 1024 * 1024 / 8); if (no_gba_unpackSAV(in_buf, fsize, out_buf, size) == 0) { if (force_size > 0) size = force_size; //printf("New size %i byte(s)\n", size); size = trim(out_buf, size); //printf("--- new size after trim %i byte(s)\n", size); size = fillLeft(size); //printf("--- new size after fill %i byte(s)\n", size); raw_applyUserSettings(size, (force_size > 0)); saveBuffer(out_buf, size, true, true); if (in_buf) delete [] in_buf; if (out_buf) delete [] out_buf; fclose(fsrc); return true; } if (out_buf) delete [] out_buf; } if (in_buf) delete [] in_buf; fclose(fsrc); } return false; } bool BackupDevice::no_gba_unpack(u8 *&buf, u32 &size) { if (!buf) return false; u32 out_size = get_save_nogba_size(buf); if (out_size == 0xFFFFFFFF) return false; u8 *out_buf = new u8 [out_size]; if (out_buf) { if (no_gba_unpackSAV(buf, size, out_buf, out_size) == 0) { out_size = trim(out_buf, out_size); out_size = fillLeft(out_size); delete [] buf; buf = out_buf; size = out_size; return true; } } delete[] out_buf; return false; } bool BackupDevice::export_no_gba(const char* fname) { size_t elements_read; std::vector data(fsize); u32 pos = fpMC->ftell(); fpMC->fseek(0, SEEK_SET); elements_read = fread(&data[0], 1, fsize, fpMC->get_fp()); if (elements_read != fsize) printf( "Expected %u bytes from saved state but read %lu.\n", fsize, (long unsigned int)elements_read ); fpMC->fseek(pos, SEEK_SET); FILE* outf = fopen(fname,"wb"); if(!outf) return false; u32 size = data.size(); u32 padSize = pad_up_size(size); if(data.size()>0) fwrite(&data[0],1,size,outf); for(u32 i=size;i data(fsize); u32 pos = fpMC->ftell(); fpMC->fseek(0, SEEK_SET); elements_read = fread(&data[0], 1, fsize, fpMC->get_fp()); if (elements_read != fsize) printf( "Expected %u bytes from saved state but read %lu.\n", fsize, (long unsigned int)elements_read ); fpMC->fseek(pos, SEEK_SET); FILE* outf = fopen(filename,"wb"); if(!outf) return false; u32 size = data.size(); u32 padSize = pad_up_size(size); if(data.size()>0) fwrite(&data[0],1,size,outf); for(u32 i=size;i saveSizes[ctr])) ctr++; u32 padSize = saveSizes[ctr]; if(padSize == 0xFFFFFFFF) { printf("PANIC! Couldn't pad up save size. Refusing to pad.\n"); padSize = startSize; } return padSize; } void BackupDevice::raw_applyUserSettings(u32& size, bool manual) { //respect the user's choice of backup memory type if(CommonSettings.manualBackupType == MC_TYPE_AUTODETECT && !manual) { addr_size = addr_size_for_old_save_size(size); ensure(size); } else { u32 type = CommonSettings.manualBackupType; if (manual) { u32 res = searchFileSaveType(size); if (res != 0xFF) type = (res + 1); // +1 - skip autodetect } int savetype = save_types[type].media_type; int savesize = save_types[type].size; addr_size = addr_size_for_old_save_type(savetype); if((u32)savesize 0) { if (size > force_size) size = force_size; else if (size < force_size) { left = force_size - size; size = force_size; } } fseek(inf, 0, SEEK_SET); raw_applyUserSettings(size, (force_size > 0)); u8 *data = new u8[size]; u32 sz = (size-left); bool res = (fread(data, 1, sz, inf) == sz); fclose(inf); if (res) saveBuffer(data, sz, true, true); delete [] data; return true; } u32 BackupDevice::get_save_duc_size(const char* fname) { FILE* inf = fopen(fname,"rb"); if (!inf) return 0xFFFFFFFF; fseek(inf, 0, SEEK_END); u32 size = (u32)ftell(inf); fclose(inf); if (size < 500) return 0xFFFFFFFF; return (size - 500); } bool BackupDevice::import_duc(const char* filename, u32 force_size) { size_t elements_read; u32 size; char id[16]; FILE* file = fopen(filename, "rb"); if(!file) return false; fseek(file, 0, SEEK_END); size = (u32)ftell(file) - 500; fseek(file, 0, SEEK_SET); // Make sure we really have the right file elements_read = fread((void *)id, sizeof(char), 16, file); if (elements_read != 16) printf("DUC file should be 16 bytes, not %lu bytes.\n", (long unsigned int)elements_read); if (memcmp(id, "ARDS000000000001", 16) != 0) { printf("Not recognized as a valid DUC file\n"); fclose(file); return false; } // Skip the rest of the header since we don't need it fseek(file, 500, SEEK_SET); u32 left = 0; if (force_size > 0) { if (size > force_size) size = force_size; else if (size < force_size) { left = force_size - size; size = force_size; } } raw_applyUserSettings(size, (force_size > 0)); u8 *data = new u8[size]; u32 sz = (size-left); bool res = (fread(data, 1, sz, file) == sz); fclose(file); if (res) saveBuffer(data, sz, true, true); delete [] data; return res; } void BackupDevice::forceManualBackupType() { addr_size = addr_size_for_old_save_size(save_types[CommonSettings.manualBackupType].size); state = RUNNING; } desmume/src/libretro-common/include/math/fxp.h000664 001750 001750 00000003723 12755534123 022576 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2016 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (fxp.h). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef __LIBRETRO_SDK_MATH_FXP_H__ #define __LIBRETRO_SDK_MATH_FXP_H__ #include #ifdef _MSC_VER #include #endif #include static INLINE int64_t fx32_mul(const int32_t a, const int32_t b) { #ifdef _MSC_VER return __emul(a, b); #else return ((int64_t)a) * ((int64_t)b); #endif } static INLINE int32_t fx32_shiftdown(const int64_t a) { #ifdef _MSC_VER return (int32_t)__ll_rshift(a, 12); #else return (int32_t)(a >> 12); #endif } static INLINE int64_t fx32_shiftup(const int32_t a) { #ifdef _MSC_VER return __ll_lshift(a, 12); #else return ((int64_t)a) << 12; #endif } #endif desmume/src/libretro-common/include/conversion/000700 001750 001750 00000000000 12756420131 023035 5ustar00sergiosergio000000 000000 desmume/src/libretro-common/include/file/000700 001750 001750 00000000000 12756420131 021567 5ustar00sergiosergio000000 000000 desmume/src/utils/AsmJit/core/zonememory.cpp000664 001750 001750 00000004246 12755534123 022334 0ustar00sergiosergio000000 000000 // [AsmJit] // Complete JIT Assembler for C++ Language. // // [License] // Zlib - See COPYING file in this package. #define ASMJIT_EXPORTS // [Dependencies - AsmJit] #include "../core/defs.h" #include "../core/intutil.h" #include "../core/zonememory.h" // [Api-Begin] #include "../core/apibegin.h" namespace AsmJit { // ============================================================================ // [AsmJit::ZoneMemory] // ============================================================================ ZoneMemory::ZoneMemory(size_t chunkSize) { _chunks = NULL; _total = 0; _chunkSize = chunkSize; } ZoneMemory::~ZoneMemory() { reset(); } void* ZoneMemory::alloc(size_t size) { ZoneChunk* cur = _chunks; // Align to 4 or 8 bytes. size = IntUtil::align(size, sizeof(size_t)); if (cur == NULL || cur->getRemainingBytes() < size) { size_t chSize = _chunkSize; if (chSize < size) chSize = size; cur = (ZoneChunk*)ASMJIT_MALLOC(sizeof(ZoneChunk) - sizeof(void*) + chSize); if (cur == NULL) return NULL; cur->prev = _chunks; cur->pos = 0; cur->size = chSize; _chunks = cur; } uint8_t* p = cur->data + cur->pos; cur->pos += size; _total += size; ASMJIT_ASSERT(cur->pos <= cur->size); return (void*)p; } char* ZoneMemory::sdup(const char* str) { if (str == NULL) return NULL; size_t len = strlen(str); if (len == 0) return NULL; // Include NULL terminator and limit string length. if (++len > 256) len = 256; char* m = reinterpret_cast(alloc(IntUtil::align(len, 16))); if (m == NULL) return NULL; memcpy(m, str, len); m[len - 1] = '\0'; return m; } void ZoneMemory::clear() { ZoneChunk* cur = _chunks; if (cur == NULL) return; cur = cur->prev; while (cur != NULL) { ZoneChunk* prev = cur->prev; ASMJIT_FREE(cur); cur = prev; } _chunks->pos = 0; _chunks->prev = NULL; _total = 0; } void ZoneMemory::reset() { ZoneChunk* cur = _chunks; _chunks = NULL; _total = 0; while (cur != NULL) { ZoneChunk* prev = cur->prev; ASMJIT_FREE(cur); cur = prev; } } } // AsmJit namespace // [Api-End] #include "../core/apiend.h" desmume/src/libretro-common/include/gfx/scaler/000700 001750 001750 00000000000 12756420131 022705 5ustar00sergiosergio000000 000000 desmume/src/utils/AsmJit/core/memorymanager.cpp000664 001750 001750 00000073302 12755534123 022772 0ustar00sergiosergio000000 000000 // [AsmJit] // Complete JIT Assembler for C++ Language. // // [License] // Zlib - See COPYING file in this package. #define ASMJIT_EXPORTS // [Dependencies - AsmJit] #include "../core/assert.h" #include "../core/lock.h" #include "../core/memorymanager.h" #include "../core/virtualmemory.h" // [Api-Begin] #include "../core/apibegin.h" // This file contains implementation of virtual memory management for AsmJit // library. The initial concept is to keep this implementation simple but // efficient. There are several goals I decided to write implementation myself. // // Goals: // - We need usually to allocate blocks of 64 bytes long and more. // - Alignment of allocated blocks is large - 32 bytes or 64 bytes. // - Keep memory manager information outside allocated virtual memory pages // (these pages allows execution of code). // - Keep implementation small. // // I think that implementation is not small and probably not too much readable, // so there is small know how. // // - Implementation is based on bit arrays and binary trees. Bit arrays // contains information about allocated and unused blocks of memory. Each // block size describes MemNode::density member. Count of blocks are // stored in MemNode::blocks member. For example if density is 64 and // count of blocks is 20, memory node contains 64*20 bytes of memory and // smallest possible allocation (and also alignment) is 64 bytes. So density // describes also memory alignment. Binary trees are used to enable fast // lookup into all addresses allocated by memory manager instance. This is // used mainly in MemoryManagerPrivate::free(). // // Bit array looks like this (empty = unused, X = used) - Size of block 64 // ------------------------------------------------------------------------- // | |X|X| | | | | |X|X|X|X|X|X| | | | | | | | | | | | |X| | | | |X|X|X| | | // ------------------------------------------------------------------------- // Bits array shows that there are 12 allocated blocks of 64 bytes, so total // allocated size is 768 bytes. Maximum count of continuous blocks is 12 // (see largest gap). namespace AsmJit { // ============================================================================ // [Bits Manipulation] // ============================================================================ #define BITS_PER_ENTITY (sizeof(size_t) * 8) static void _SetBit(size_t* buf, size_t index) { size_t i = index / BITS_PER_ENTITY; // size_t[] size_t j = index % BITS_PER_ENTITY; // size_t[][] bit index buf += i; *buf |= (size_t)1 << j; } static void _ClearBit(size_t* buf, size_t index) { size_t i = index / BITS_PER_ENTITY; // size_t[] size_t j = index % BITS_PER_ENTITY; // size_t[][] bit index buf += i; *buf &= ~((size_t)1 << j); } static void _SetBits(size_t* buf, size_t index, size_t len) { if (len == 0) return; size_t i = index / BITS_PER_ENTITY; // size_t[] size_t j = index % BITS_PER_ENTITY; // size_t[][] bit index // How many bytes process in the first group. size_t c = BITS_PER_ENTITY - j; if (c > len) c = len; // Offset. buf += i; *buf++ |= ((~(size_t)0) >> (BITS_PER_ENTITY - c)) << j; len -= c; while (len >= BITS_PER_ENTITY) { *buf++ = ~(size_t)0; len -= BITS_PER_ENTITY; } if (len) { *buf |= ((~(size_t)0) >> (BITS_PER_ENTITY - len)); } } static void _ClearBits(size_t* buf, size_t index, size_t len) { if (len == 0) return; size_t i = index / BITS_PER_ENTITY; // size_t[] size_t j = index % BITS_PER_ENTITY; // size_t[][] bit index // How many bytes process in the first group. size_t c = BITS_PER_ENTITY - j; if (c > len) c = len; // Offset. buf += i; *buf++ &= ~(((~(size_t)0) >> (BITS_PER_ENTITY - c)) << j); len -= c; while (len >= BITS_PER_ENTITY) { *buf++ = 0; len -= BITS_PER_ENTITY; } if (len) { *buf &= (~(size_t)0) << len; } } // ============================================================================ // [AsmJit::MemNode] // ============================================================================ #define M_DIV(x, y) ((x) / (y)) #define M_MOD(x, y) ((x) % (y)) template struct RbNode { // -------------------------------------------------------------------------- // [Node red-black tree tree, key is mem pointer]. // -------------------------------------------------------------------------- // Implementation is based on article by Julienne Walker (Public Domain), // including C code and original comments. Thanks for the excellent article. // Left[0] and right[1] nodes. T* node[2]; // Whether the node is RED. uint32_t red; // -------------------------------------------------------------------------- // [Chunk Memory] // -------------------------------------------------------------------------- // Virtual memory address. uint8_t* mem; }; // Get whether the node is red (NULL or node with red flag). template inline bool isRed(RbNode* node) { return node != NULL && node->red; } struct MemNode : public RbNode { // -------------------------------------------------------------------------- // [Node double-linked list] // -------------------------------------------------------------------------- MemNode* prev; // Prev node in list. MemNode* next; // Next node in list. // -------------------------------------------------------------------------- // [Chunk Data] // -------------------------------------------------------------------------- size_t size; // How many bytes contain this node. size_t blocks; // How many blocks are here. size_t density; // Minimum count of allocated bytes in this node (also alignment). size_t used; // How many bytes are used in this node. size_t largestBlock; // Contains largest block that can be allocated. size_t* baUsed; // Contains bits about used blocks. // (0 = unused, 1 = used). size_t* baCont; // Contains bits about continuous blocks. // (0 = stop, 1 = continue). // -------------------------------------------------------------------------- // [Methods] // -------------------------------------------------------------------------- // Get available space. inline size_t getAvailable() const { return size - used; } inline void fillData(MemNode* other) { mem = other->mem; size = other->size; blocks = other->blocks; density = other->density; used = other->used; largestBlock = other->largestBlock; baUsed = other->baUsed; baCont = other->baCont; } }; // ============================================================================ // [AsmJit::M_Permanent] // ============================================================================ //! @brief Permanent node. struct PermanentNode { uint8_t* mem; // Base pointer (virtual memory address). size_t size; // Count of bytes allocated. size_t used; // Count of bytes used. PermanentNode* prev; // Pointer to prev chunk or NULL. // Get available space. inline size_t getAvailable() const { return size - used; } }; // ============================================================================ // [AsmJit::MemoryManagerPrivate] // ============================================================================ struct MemoryManagerPrivate { // -------------------------------------------------------------------------- // [Construction / Destruction] // -------------------------------------------------------------------------- #if !defined(ASMJIT_WINDOWS) MemoryManagerPrivate(); #else MemoryManagerPrivate(HANDLE hProcess); #endif // ASMJIT_WINDOWS ~MemoryManagerPrivate(); // -------------------------------------------------------------------------- // [Allocation] // -------------------------------------------------------------------------- MemNode* createNode(size_t size, size_t density); void* allocPermanent(size_t vsize); void* allocFreeable(size_t vsize); bool free(void* address); bool shrink(void* address, size_t used); void freeAll(bool keepVirtualMemory); // Helpers to avoid ifdefs in the code. inline uint8_t* allocVirtualMemory(size_t size, size_t* vsize) { #if !defined(ASMJIT_WINDOWS) return (uint8_t*)VirtualMemory::alloc(size, vsize, true); #else return (uint8_t*)VirtualMemory::allocProcessMemory(_hProcess, size, vsize, true); #endif } inline void freeVirtualMemory(void* vmem, size_t vsize) { #if !defined(ASMJIT_WINDOWS) VirtualMemory::free(vmem, vsize); #else VirtualMemory::freeProcessMemory(_hProcess, vmem, vsize); #endif } // -------------------------------------------------------------------------- // [NodeList RB-Tree] // -------------------------------------------------------------------------- bool checkTree(); void insertNode(MemNode* node); MemNode* removeNode(MemNode* node); MemNode* findPtr(uint8_t* mem); // -------------------------------------------------------------------------- // [Members] // -------------------------------------------------------------------------- #if defined(ASMJIT_WINDOWS) HANDLE _hProcess; // Process where to allocate memory. #endif // ASMJIT_WINDOWS Lock _lock; // Lock for thread safety. size_t _newChunkSize; // Default node size. size_t _newChunkDensity; // Default node density. size_t _allocated; // How many bytes are allocated. size_t _used; // How many bytes are used. // Memory nodes list. MemNode* _first; MemNode* _last; MemNode* _optimal; // Memory nodes tree. MemNode* _root; // Permanent memory. PermanentNode* _permanent; // Whether to keep virtual memory after destroy. bool _keepVirtualMemory; }; // ============================================================================ // [AsmJit::MemoryManagerPrivate - Construction / Destruction] // ============================================================================ #if !defined(ASMJIT_WINDOWS) MemoryManagerPrivate::MemoryManagerPrivate() : #else MemoryManagerPrivate::MemoryManagerPrivate(HANDLE hProcess) : _hProcess(hProcess), #endif _newChunkSize(65536), _newChunkDensity(64), _allocated(0), _used(0), _root(NULL), _first(NULL), _last(NULL), _optimal(NULL), _permanent(NULL), _keepVirtualMemory(false) { } MemoryManagerPrivate::~MemoryManagerPrivate() { // Freeable memory cleanup - Also frees the virtual memory if configured to. freeAll(_keepVirtualMemory); // Permanent memory cleanup - Never frees the virtual memory. PermanentNode* node = _permanent; while (node) { PermanentNode* prev = node->prev; ASMJIT_FREE(node); node = prev; } } // ============================================================================ // [AsmJit::MemoryManagerPrivate - Allocation] // ============================================================================ // Allocates virtual memory node and MemNode structure. // // Returns MemNode* on success, otherwise NULL. MemNode* MemoryManagerPrivate::createNode(size_t size, size_t density) { size_t vsize; uint8_t* vmem = allocVirtualMemory(size, &vsize); // Out of memory. if (vmem == NULL) return NULL; size_t blocks = (vsize / density); size_t bsize = (((blocks + 7) >> 3) + sizeof(size_t) - 1) & ~(size_t)(sizeof(size_t) - 1); MemNode* node = reinterpret_cast(ASMJIT_MALLOC(sizeof(MemNode))); uint8_t* data = reinterpret_cast(ASMJIT_MALLOC(bsize * 2)); // Out of memory. if (node == NULL || data == NULL) { freeVirtualMemory(vmem, vsize); if (node) ASMJIT_FREE(node); if (data) ASMJIT_FREE(data); return NULL; } // Initialize RbNode data. node->node[0] = NULL; node->node[1] = NULL; node->red = 1; node->mem = vmem; // Initialize MemNode data. node->prev = NULL; node->next = NULL; node->size = vsize; node->blocks = blocks; node->density = density; node->used = 0; node->largestBlock = vsize; memset(data, 0, bsize * 2); node->baUsed = reinterpret_cast(data); node->baCont = reinterpret_cast(data + bsize); return node; } void* MemoryManagerPrivate::allocPermanent(size_t vsize) { static const size_t permanentAlignment = 32; static const size_t permanentNodeSize = 32768; size_t over = vsize % permanentAlignment; if (over) over = permanentAlignment - over; size_t alignedSize = vsize + over; AutoLock locked(_lock); PermanentNode* node = _permanent; // Try to find space in allocated chunks. while (node && alignedSize > node->getAvailable()) node = node->prev; // Or allocate new node. if (node == NULL) { size_t nodeSize = permanentNodeSize; if (vsize > nodeSize) nodeSize = vsize; node = (PermanentNode*)ASMJIT_MALLOC(sizeof(PermanentNode)); // Out of memory. if (node == NULL) return NULL; node->mem = allocVirtualMemory(nodeSize, &node->size); // Out of memory. if (node->mem == NULL) { ASMJIT_FREE(node); return NULL; } node->used = 0; node->prev = _permanent; _permanent = node; } // Finally, copy function code to our space we reserved for. uint8_t* result = node->mem + node->used; // Update Statistics. node->used += alignedSize; _used += alignedSize; // Code can be null to only reserve space for code. return (void*)result; } void* MemoryManagerPrivate::allocFreeable(size_t vsize) { size_t i; // Current index. size_t need; // How many we need to be freed. size_t minVSize; // Align to 32 bytes (our default alignment). vsize = (vsize + 31) & ~(size_t)31; if (vsize == 0) return NULL; AutoLock locked(_lock); MemNode* node = _optimal; minVSize = _newChunkSize; // Try to find memory block in existing nodes. while (node) { // Skip this node? if ((node->getAvailable() < vsize) || (node->largestBlock < vsize && node->largestBlock != 0)) { MemNode* next = node->next; if (node->getAvailable() < minVSize && node == _optimal && next) _optimal = next; node = next; continue; } size_t* up = node->baUsed; // Current ubits address. size_t ubits; // Current ubits[0] value. size_t bit; // Current bit mask. size_t blocks = node->blocks; // Count of blocks in node. size_t cont = 0; // How many bits are currently freed in find loop. size_t maxCont = 0; // Largest continuous block (bits count). size_t j; need = M_DIV((vsize + node->density - 1), node->density); i = 0; // Try to find node that is large enough. while (i < blocks) { ubits = *up++; // Fast skip used blocks. if (ubits == ~(size_t)0) { if (cont > maxCont) maxCont = cont; cont = 0; i += BITS_PER_ENTITY; continue; } size_t max = BITS_PER_ENTITY; if (i + max > blocks) max = blocks - i; for (j = 0, bit = 1; j < max; bit <<= 1) { j++; if ((ubits & bit) == 0) { if (++cont == need) { i += j; i -= cont; goto _Found; } continue; } if (cont > maxCont) maxCont = cont; cont = 0; } i += BITS_PER_ENTITY; } // Because we traversed entire node, we can set largest node size that // will be used to cache next traversing.. node->largestBlock = maxCont * node->density; node = node->next; } // If we are here, we failed to find existing memory block and we must // allocate new. { size_t chunkSize = _newChunkSize; if (chunkSize < vsize) chunkSize = vsize; node = createNode(chunkSize, _newChunkDensity); if (node == NULL) return NULL; // Update binary tree. insertNode(node); ASMJIT_ASSERT(checkTree()); // Alloc first node at start. i = 0; need = (vsize + node->density - 1) / node->density; // Update statistics. _allocated += node->size; } _Found: // Update bits. _SetBits(node->baUsed, i, need); _SetBits(node->baCont, i, need - 1); // Update statistics. { size_t u = need * node->density; node->used += u; node->largestBlock = 0; _used += u; } // And return pointer to allocated memory. uint8_t* result = node->mem + i * node->density; ASMJIT_ASSERT(result >= node->mem && result <= node->mem + node->size - vsize); return result; } bool MemoryManagerPrivate::free(void* address) { if (address == NULL) return true; AutoLock locked(_lock); MemNode* node = findPtr((uint8_t*)address); if (node == NULL) return false; size_t offset = (size_t)((uint8_t*)address - (uint8_t*)node->mem); size_t bitpos = M_DIV(offset, node->density); size_t i = (bitpos / BITS_PER_ENTITY); size_t* up = node->baUsed + i; // Current ubits address. size_t* cp = node->baCont + i; // Current cbits address. size_t ubits = *up; // Current ubits[0] value. size_t cbits = *cp; // Current cbits[0] value. size_t bit = (size_t)1 << (bitpos % BITS_PER_ENTITY); size_t cont = 0; bool stop; for (;;) { stop = (cbits & bit) == 0; ubits &= ~bit; cbits &= ~bit; bit <<= 1; cont++; if (stop || bit == 0) { *up = ubits; *cp = cbits; if (stop) break; ubits = *++up; cbits = *++cp; bit = 1; } } // If the freed block is fully allocated node then it's needed to // update 'optimal' pointer in memory manager. if (node->used == node->size) { MemNode* cur = _optimal; do { cur = cur->prev; if (cur == node) { _optimal = node; break; } } while (cur); } // Statistics. cont *= node->density; if (node->largestBlock < cont) node->largestBlock = cont; node->used -= cont; _used -= cont; // If page is empty, we can free it. if (node->used == 0) { // Free memory associated with node (this memory is not accessed // anymore so it's safe). freeVirtualMemory(node->mem, node->size); ASMJIT_FREE(node->baUsed); node->baUsed = NULL; node->baCont = NULL; // Statistics. _allocated -= node->size; // Remove node. This function can return different node than // passed into, but data is copied into previous node if needed. ASMJIT_FREE(removeNode(node)); ASMJIT_ASSERT(checkTree()); } return true; } bool MemoryManagerPrivate::shrink(void* address, size_t used) { if (address == NULL) return false; if (used == 0) return free(address); AutoLock locked(_lock); MemNode* node = findPtr((uint8_t*)address); if (node == NULL) return false; size_t offset = (size_t)((uint8_t*)address - (uint8_t*)node->mem); size_t bitpos = M_DIV(offset, node->density); size_t i = (bitpos / BITS_PER_ENTITY); size_t* up = node->baUsed + i; // Current ubits address. size_t* cp = node->baCont + i; // Current cbits address. size_t ubits = *up; // Current ubits[0] value. size_t cbits = *cp; // Current cbits[0] value. size_t bit = (size_t)1 << (bitpos % BITS_PER_ENTITY); size_t cont = 0; size_t usedBlocks = (used + node->density - 1) / node->density; bool stop; // Find the first block we can mark as free. for (;;) { stop = (cbits & bit) == 0; if (stop) return true; if (++cont == usedBlocks) break; bit <<= 1; if (bit == 0) { ubits = *++up; cbits = *++cp; bit = 1; } } // Free the tail blocks. cont = ~(size_t)0; goto _EnterFreeLoop; for (;;) { stop = (cbits & bit) == 0; ubits &= ~bit; _EnterFreeLoop: cbits &= ~bit; bit <<= 1; cont++; if (stop || bit == 0) { *up = ubits; *cp = cbits; if (stop) break; ubits = *++up; cbits = *++cp; bit = 1; } } // Statistics. cont *= node->density; if (node->largestBlock < cont) node->largestBlock = cont; node->used -= cont; _used -= cont; return true; } void MemoryManagerPrivate::freeAll(bool keepVirtualMemory) { MemNode* node = _first; while (node) { MemNode* next = node->next; if (!keepVirtualMemory) freeVirtualMemory(node->mem, node->size); ASMJIT_FREE(node->baUsed); ASMJIT_FREE(node); node = next; } _allocated = 0; _used = 0; _root = NULL; _first = NULL; _last = NULL; _optimal = NULL; } // ============================================================================ // [AsmJit::MemoryManagerPrivate - NodeList RB-Tree] // ============================================================================ static int rbAssert(MemNode* root) { if (root == NULL) return 1; MemNode* ln = root->node[0]; MemNode* rn = root->node[1]; // Red violation. ASMJIT_ASSERT( !(isRed(root) && (isRed(ln) || isRed(rn))) ); int lh = rbAssert(ln); int rh = rbAssert(rn); // Invalid btree. ASMJIT_ASSERT(ln == NULL || ln->mem < root->mem); ASMJIT_ASSERT(rn == NULL || rn->mem > root->mem); // Black violation. ASMJIT_ASSERT( !(lh != 0 && rh != 0 && lh != rh) ); // Only count black links. if (lh != 0 && rh != 0) return isRed(root) ? lh : lh + 1; else return 0; } static inline MemNode* rbRotateSingle(MemNode* root, int dir) { MemNode* save = root->node[!dir]; root->node[!dir] = save->node[dir]; save->node[dir] = root; root->red = 1; save->red = 0; return save; } static inline MemNode* rbRotateDouble(MemNode* root, int dir) { root->node[!dir] = rbRotateSingle(root->node[!dir], !dir); return rbRotateSingle(root, dir); } bool MemoryManagerPrivate::checkTree() { return rbAssert(_root) > 0; } void MemoryManagerPrivate::insertNode(MemNode* node) { if (_root == NULL) { // Empty tree case. _root = node; } else { // False tree root. RbNode head = {0}; // Grandparent & parent. MemNode* g = NULL; MemNode* t = reinterpret_cast(&head); // Iterator & parent. MemNode* p = NULL; MemNode* q = t->node[1] = _root; int dir = 0, last; // Search down the tree. for (;;) { if (q == NULL) { // Insert new node at the bottom. q = node; p->node[dir] = node; } else if (isRed(q->node[0]) && isRed(q->node[1])) { // Color flip. q->red = 1; q->node[0]->red = 0; q->node[1]->red = 0; } // Fix red violation. if (isRed(q) && isRed(p)) { int dir2 = t->node[1] == g; t->node[dir2] = (q == p->node[last]) ? rbRotateSingle(g, !last) : rbRotateDouble(g, !last); } // Stop if found. if (q == node) break; last = dir; dir = q->mem < node->mem; // Update helpers. if (g != NULL) t = g; g = p; p = q; q = q->node[dir]; } // Update root. _root = head.node[1]; } // Make root black. _root->red = 0; // Link with others. node->prev = _last; if (_first == NULL) { _first = node; _last = node; _optimal = node; } else { node->prev = _last; _last->next = node; _last = node; } } MemNode* MemoryManagerPrivate::removeNode(MemNode* node) { // False tree root. RbNode head = {0}; // Helpers. MemNode* q = reinterpret_cast(&head); MemNode* p = NULL; MemNode* g = NULL; // Found item. MemNode* f = NULL; int dir = 1; // Set up. q->node[1] = _root; // Search and push a red down. while (q->node[dir] != NULL) { int last = dir; // Update helpers. g = p; p = q; q = q->node[dir]; dir = q->mem < node->mem; // Save found node. if (q == node) f = q; // Push the red node down. if (!isRed(q) && !isRed(q->node[dir])) { if (isRed(q->node[!dir])) { p = p->node[last] = rbRotateSingle(q, dir); } else if (!isRed(q->node[!dir])) { MemNode* s = p->node[!last]; if (s != NULL) { if (!isRed(s->node[!last]) && !isRed(s->node[last])) { // Color flip. p->red = 0; s->red = 1; q->red = 1; } else { int dir2 = g->node[1] == p; if (isRed(s->node[last])) g->node[dir2] = rbRotateDouble(p, last); else if (isRed(s->node[!last])) g->node[dir2] = rbRotateSingle(p, last); // Ensure correct coloring. q->red = g->node[dir2]->red = 1; g->node[dir2]->node[0]->red = 0; g->node[dir2]->node[1]->red = 0; } } } } } // Replace and remove. ASMJIT_ASSERT(f != NULL); ASMJIT_ASSERT(f != reinterpret_cast(&head)); ASMJIT_ASSERT(q != reinterpret_cast(&head)); if (f != q) f->fillData(q); p->node[p->node[1] == q] = q->node[q->node[0] == NULL]; // Update root and make it black. if ((_root = head.node[1]) != NULL) _root->red = 0; // Unlink. MemNode* next = q->next; MemNode* prev = q->prev; if (prev) { prev->next = next; } else { _first = next; } if (next) { next->prev = prev; } else { _last = prev; } if (_optimal == q) { _optimal = prev ? prev : next; } return q; } MemNode* MemoryManagerPrivate::findPtr(uint8_t* mem) { MemNode* cur = _root; while (cur) { uint8_t* curMem = cur->mem; if (mem < curMem) { // Go left. cur = cur->node[0]; continue; } else { uint8_t* curEnd = curMem + cur->size; if (mem >= curEnd) { // Go right. cur = cur->node[1]; continue; } else { // Match. break; } } } return cur; } // ============================================================================ // [AsmJit::MemoryManager] // ============================================================================ MemoryManager::MemoryManager() { } MemoryManager::~MemoryManager() { } MemoryManager* MemoryManager::getGlobal() { static VirtualMemoryManager memmgr; return &memmgr; } // ============================================================================ // [AsmJit::VirtualMemoryManager] // ============================================================================ #if !defined(ASMJIT_WINDOWS) VirtualMemoryManager::VirtualMemoryManager() { MemoryManagerPrivate* d = new(std::nothrow) MemoryManagerPrivate(); _d = (void*)d; } #else VirtualMemoryManager::VirtualMemoryManager() { MemoryManagerPrivate* d = new(std::nothrow) MemoryManagerPrivate(GetCurrentProcess()); _d = (void*)d; } VirtualMemoryManager::VirtualMemoryManager(HANDLE hProcess) { MemoryManagerPrivate* d = new(std::nothrow) MemoryManagerPrivate(hProcess); _d = (void*)d; } #endif // ASMJIT_WINDOWS VirtualMemoryManager::~VirtualMemoryManager() { MemoryManagerPrivate* d = reinterpret_cast(_d); delete d; } void* VirtualMemoryManager::alloc(size_t size, uint32_t type) { MemoryManagerPrivate* d = reinterpret_cast(_d); if (type == kMemAllocPermanent) return d->allocPermanent(size); else return d->allocFreeable(size); } bool VirtualMemoryManager::free(void* address) { MemoryManagerPrivate* d = reinterpret_cast(_d); return d->free(address); } bool VirtualMemoryManager::shrink(void* address, size_t used) { MemoryManagerPrivate* d = reinterpret_cast(_d); return d->shrink(address, used); } void VirtualMemoryManager::freeAll() { MemoryManagerPrivate* d = reinterpret_cast(_d); // Calling MemoryManager::freeAll() will never keep allocated memory. return d->freeAll(false); } size_t VirtualMemoryManager::getUsedBytes() { MemoryManagerPrivate* d = reinterpret_cast(_d); return d->_used; } size_t VirtualMemoryManager::getAllocatedBytes() { MemoryManagerPrivate* d = reinterpret_cast(_d); return d->_allocated; } bool VirtualMemoryManager::getKeepVirtualMemory() const { MemoryManagerPrivate* d = reinterpret_cast(_d); return d->_keepVirtualMemory; } void VirtualMemoryManager::setKeepVirtualMemory(bool keepVirtualMemory) { MemoryManagerPrivate* d = reinterpret_cast(_d); d->_keepVirtualMemory = keepVirtualMemory; } // ============================================================================ // [AsmJit::VirtualMemoryManager - Debug] // ============================================================================ #if defined(ASMJIT_MEMORY_MANAGER_DUMP) struct GraphVizContext { GraphVizContext(); ~GraphVizContext(); bool openFile(const char* fileName); void closeFile(); void dumpNode(MemNode* node); void connect(MemNode* node, MemNode* other, const char* dst); FILE* file; }; GraphVizContext::GraphVizContext() : file(NULL) { } GraphVizContext::~GraphVizContext() { closeFile(); } bool GraphVizContext::openFile(const char* fileName) { file = fopen(fileName, "w"); return file != NULL; } void GraphVizContext::closeFile() { if (file) { fclose(file); file = NULL; } } void GraphVizContext::dumpNode(MemNode* node) { fprintf(file, " NODE_%p [shape=record, style=filled, color=%s, label=\"|Mem: %p, Used: %d/%d|\"];\n", node, node->red ? "red" : "gray", node->mem, node->used, node->size); if (node->node[0]) connect(node, node->node[0], "L"); if (node->node[1]) connect(node, node->node[1], "R"); } void GraphVizContext::connect(MemNode* node, MemNode* other, const char* dst) { dumpNode(other); fprintf(file, " NODE_%p:%s -> NODE_%p:C", node, dst, other); if (other->red) fprintf(file, " [style=bold, color=red]"); fprintf(file, ";\n"); } void VirtualMemoryManager::dump(const char* fileName) { MemoryManagerPrivate* d = reinterpret_cast(_d); GraphVizContext ctx; if (!ctx.openFile(fileName)) return; fprintf(ctx.file, "digraph {\n"); if (d->_root) ctx.dumpNode(d->_root); fprintf(ctx.file, "}\n"); } #endif // ASMJIT_MEMORY_MANAGER_DUMP } // AsmJit namespace // [Api-End] #include "../core/apiend.h" desmume/src/utils/AsmJit/core/compilerfunc.h000664 001750 001750 00000027017 12755534123 022264 0ustar00sergiosergio000000 000000 // [AsmJit] // Complete JIT Assembler for C++ Language. // // [License] // Zlib - See COPYING file in this package. // [Guard] #ifndef _ASMJIT_CORE_COMPILERFUNC_H #define _ASMJIT_CORE_COMPILERFUNC_H // [Dependencies - AsmJit] #include "../core/compiler.h" #include "../core/compileritem.h" // [Api-Begin] #include "../core/apibegin.h" namespace AsmJit { // ============================================================================ // [AsmJit::CompilerFuncDecl] // ============================================================================ //! @brief Compiler function declaration item. //! //! Functions are base blocks for generating assembler output. Each generated //! assembler stream needs standard entry and leave sequences thats compatible //! with the operating system conventions (ABI). //! //! Function class can be used to generate function prolog) and epilog sequences //! that are compatible with the demanded calling convention and to allocate and //! manage variables that can be allocated/spilled during compilation time. //! //! @note To create a function use @c Compiler::newFunc() method, do not //! create any form of compiler function items using new operator. //! //! @sa @ref CompilerState, @ref CompilerVar. struct CompilerFuncDecl : public CompilerItem { // -------------------------------------------------------------------------- // [Construction / Destruction] // -------------------------------------------------------------------------- //! @brief Create a new @c CompilerFuncDecl instance. //! //! @note Always use @c AsmJit::Compiler::newFunc() to create @c Function //! instance. ASMJIT_API CompilerFuncDecl(Compiler* compiler); //! @brief Destroy the @c CompilerFuncDecl instance. ASMJIT_API virtual ~CompilerFuncDecl(); // -------------------------------------------------------------------------- // [Accessors] // -------------------------------------------------------------------------- //! @brief Get function entry label. //! //! Entry label can be used to call this function from another code that's //! being generated. inline const Label& getEntryLabel() const { return _entryLabel; } //! @brief Get function exit label. //! //! Use exit label to jump to function epilog. inline const Label& getExitLabel() const { return _exitLabel; } //! @brief Get function entry target. inline CompilerTarget* getEntryTarget() const { return _entryTarget; } //! @brief Get function exit target. inline CompilerTarget* getExitTarget() const { return _exitTarget; } //! @brief Get function end item. inline CompilerFuncEnd* getEnd() const { return _end; } //! @brief Get function declaration. inline FuncDecl* getDecl() const { return _decl; } //! @brief Get function arguments as variables. inline CompilerVar** getVars() const { return _vars; } //! @brief Get function argument at @a index. inline CompilerVar* getVar(uint32_t index) const { ASMJIT_ASSERT(index < _decl->getArgumentsCount()); return _vars[index]; } //! @brief Get function hints. inline uint32_t getFuncHints() const { return _funcHints; } //! @brief Get function flags. inline uint32_t getFuncFlags() const { return _funcFlags; } //! @brief Get whether the _funcFlags has @a flag inline bool hasFuncFlag(uint32_t flag) const { return (_funcFlags & flag) != 0; } //! @brief Set function @a flag. inline void setFuncFlag(uint32_t flag) { _funcFlags |= flag; } //! @brief Clear function @a flag. inline void clearFuncFlag(uint32_t flag) { _funcFlags &= ~flag; } //! @brief Get whether the function is also a caller. inline bool isCaller() const { return hasFuncFlag(kFuncFlagIsCaller); } //! @brief Get whether the function is finished. inline bool isFinished() const { return hasFuncFlag(kFuncFlagIsFinished); } //! @brief Get whether the function is naked. inline bool isNaked() const { return hasFuncFlag(kFuncFlagIsNaked); } //! @brief Get stack size needed to call other functions. inline int32_t getFuncCallStackSize() const { return _funcCallStackSize; } // -------------------------------------------------------------------------- // [Hints] // -------------------------------------------------------------------------- //! @brief Set function hint. ASMJIT_API virtual void setHint(uint32_t hint, uint32_t value); //! @brief Get function hint. ASMJIT_API virtual uint32_t getHint(uint32_t hint) const; // -------------------------------------------------------------------------- // [Prototype] // -------------------------------------------------------------------------- virtual void setPrototype( uint32_t convention, uint32_t returnType, const uint32_t* arguments, uint32_t argumentsCount) = 0; // -------------------------------------------------------------------------- // [Members] // -------------------------------------------------------------------------- //! @brief Function entry label. Label _entryLabel; //! @brief Function exit label. Label _exitLabel; //! @brief Function entry target. CompilerTarget* _entryTarget; //! @brief Function exit target. CompilerTarget* _exitTarget; //! @brief Function end item. CompilerFuncEnd* _end; //! @brief Function declaration. FuncDecl* _decl; //! @brief Function arguments as compiler variables. CompilerVar** _vars; //! @brief Function hints; uint32_t _funcHints; //! @brief Function flags. uint32_t _funcFlags; //! @brief Stack size needed to call other functions. int32_t _funcCallStackSize; }; // ============================================================================ // [AsmJit::CompilerFuncEnd] // ============================================================================ //! @brief Compiler function end item. //! //! This item does nothing; it's only used by @ref Compiler to mark specific //! location in the code. The @c CompilerFuncEnd is similar to @c CompilerMark, //! except that it overrides @c translate() to return @c NULL. struct CompilerFuncEnd : public CompilerItem { ASMJIT_NO_COPY(CompilerFuncEnd) // -------------------------------------------------------------------------- // [Construction / Destruction] // -------------------------------------------------------------------------- //! @brief Create a new @ref CompilerMark instance. ASMJIT_API CompilerFuncEnd(Compiler* compiler, CompilerFuncDecl* func); //! @brief Destroy the @ref CompilerMark instance. ASMJIT_API virtual ~CompilerFuncEnd(); // -------------------------------------------------------------------------- // [Accessors] // -------------------------------------------------------------------------- //! @brief Get related function. inline CompilerFuncDecl* getFunc() const { return _func; } // -------------------------------------------------------------------------- // [Interface] // -------------------------------------------------------------------------- ASMJIT_API virtual CompilerItem* translate(CompilerContext& cc); // -------------------------------------------------------------------------- // [Members] // -------------------------------------------------------------------------- //! @brief Related function. CompilerFuncDecl* _func; }; // ============================================================================ // [AsmJit::CompilerFuncRet] // ============================================================================ //! @brief Compiler return from function item. struct CompilerFuncRet : public CompilerItem { ASMJIT_NO_COPY(CompilerFuncRet) // -------------------------------------------------------------------------- // [Construction / Destruction] // -------------------------------------------------------------------------- //! @brief Create a new @ref CompilerFuncRet instance. ASMJIT_API CompilerFuncRet(Compiler* compiler, CompilerFuncDecl* func, const Operand* first, const Operand* second); //! @brief Destroy the @ref CompilerFuncRet instance. ASMJIT_API virtual ~CompilerFuncRet(); // -------------------------------------------------------------------------- // [Accessors] // -------------------------------------------------------------------------- //! @Brief Get the related function. inline CompilerFuncDecl* getFunc() const { return _func; } //! @brief Get the first return operand. inline Operand& getFirst() { return _ret[0]; } //! @overload inline const Operand& getFirst() const { return _ret[0]; } //! @brief Get the second return operand. inline Operand& getSecond() { return _ret[1]; } //! @overload inline const Operand& getSecond() const { return _ret[1]; } // -------------------------------------------------------------------------- // [Misc] // -------------------------------------------------------------------------- //! @brief Get whether jump to epilog has to be emitted. ASMJIT_API bool mustEmitJump() const; // -------------------------------------------------------------------------- // [Members] // -------------------------------------------------------------------------- //! @brief Related function. CompilerFuncDecl* _func; //! @brief Return operand(s). Operand _ret[2]; }; // ============================================================================ // [AsmJit::CompilerFuncCall] // ============================================================================ //! @brief Compiler function call item. struct CompilerFuncCall : public CompilerItem { ASMJIT_NO_COPY(CompilerFuncCall) // -------------------------------------------------------------------------- // [Construction / Destruction] // -------------------------------------------------------------------------- //! @brief Create a new @ref CompilerFuncCall instance. ASMJIT_API CompilerFuncCall(Compiler* compiler, CompilerFuncDecl* caller, const Operand* target); //! @brief Destroy the @ref CompilerFuncCall instance. ASMJIT_API virtual ~CompilerFuncCall(); // -------------------------------------------------------------------------- // [Accessors] // -------------------------------------------------------------------------- //! @brief Get caller. inline CompilerFuncDecl* getCaller() const { return _caller; } //! @brief Get function declaration. inline FuncDecl* getDecl() const { return _decl; } //! @brief Get target operand. inline Operand& getTarget() { return _target; } //! @overload inline const Operand& getTarget() const { return _target; } // -------------------------------------------------------------------------- // [Prototype] // -------------------------------------------------------------------------- virtual void setPrototype(uint32_t convention, uint32_t returnType, const uint32_t* arguments, uint32_t argumentsCount) = 0; //! @brief Set function prototype. inline void setPrototype(uint32_t convention, const FuncPrototype& func) { setPrototype(convention, func.getReturnType(), func.getArguments(), func.getArgumentsCount()); } // -------------------------------------------------------------------------- // [Members] // -------------------------------------------------------------------------- //! @brief Caller (the function which does the call). CompilerFuncDecl* _caller; //! @brief Function declaration. FuncDecl* _decl; //! @brief Operand (address of function, register, label, ...). Operand _target; //! @brief Return operands. Operand _ret[2]; //! @brief Arguments operands. Operand* _args; }; } // AsmJit namespace // [Api-End] #include "../core/apiend.h" // [Guard] #endif // _ASMJIT_CORE_COMPILERFUNC_H desmume/src/utils/arm_arm/reg_manager.h000664 001750 001750 00000011200 12755534123 021327 0ustar00sergiosergio000000 000000 #ifndef ARM_JIT_REG_MANAGER_H #define ARM_JIT_REG_MANAGER_H #include #include "arm_gen.h" #include "armcpu.h" extern const arm_gen::reg_t RCPU; class register_manager { public: register_manager(arm_gen::code_pool* apool) : pool(apool) { reset(); } void reset() { memset(mapping, 0xFF, sizeof(mapping)); memset(usage_tag, 0, sizeof(usage_tag)); memset(dirty, 0, sizeof(dirty)); memset(weak, 0, sizeof(weak)); next_usage_tag = 1; } bool is_usable(arm_gen::reg_t reg) const { static const uint32_t USE_MAP = 0xDE0; return (USE_MAP & (1 << reg)) ? true : false; } private: int32_t find(uint32_t emu_reg_id) { for (int i = 0; i != 16; i ++) { if (is_usable(i) && mapping[i] == emu_reg_id) { usage_tag[i] = next_usage_tag ++; assert(is_usable(i)); return i; } } return -1; } int32_t get_loaded(uint32_t emu_reg_id, bool no_read) { int32_t current = find(emu_reg_id); if (current >= 0) { if (weak[current] && !no_read) { read_emu(current, emu_reg_id); weak[current] = false; } } return current; } arm_gen::reg_t get_oldest() { uint32_t result = 0; uint32_t lowtag = 0xFFFFFFFF; for (int i = 0; i != 16; i ++) { if (is_usable(i) && usage_tag[i] < lowtag) { lowtag = usage_tag[i]; result = i; } } assert(is_usable(result)); return result; } public: void get(uint32_t reg_count, int32_t* emu_reg_ids) { assert(reg_count < 5); bool found[5] = { false, false, false, false, false }; // Find existing registers for (uint32_t i = 0; i < reg_count; i ++) { if (emu_reg_ids[i] < 0) { found[i] = true; } else { int32_t current = get_loaded(emu_reg_ids[i] & 0xF, emu_reg_ids[i] & 0x10); if (current >= 0) { emu_reg_ids[i] = current; found[i] = true; } } } // Load new registers for (uint32_t i = 0; i != reg_count; i ++) { if (!found[i]) { // Search register list again, in case the same register is used twice int32_t current = get_loaded(emu_reg_ids[i] & 0xF, emu_reg_ids[i] & 0x10); if (current >= 0) { emu_reg_ids[i] = current; found[i] = true; } else { // Read the new register arm_gen::reg_t result = get_oldest(); flush(result); if (!(emu_reg_ids[i] & 0x10)) { read_emu(result, emu_reg_ids[i] & 0xF); } mapping[result] = emu_reg_ids[i] & 0xF; usage_tag[result] = next_usage_tag ++; weak[result] = (emu_reg_ids[i] & 0x10) ? true : false; emu_reg_ids[i] = result; found[i] = true; } } } } void mark_dirty(uint32_t native_reg) { assert(is_usable(native_reg)); dirty[native_reg] = true; weak[native_reg] = false; } void flush(uint32_t native_reg) { assert(is_usable(native_reg)); if (dirty[native_reg] && !weak[native_reg]) { write_emu(native_reg, mapping[native_reg]); dirty[native_reg] = false; } } void flush_all() { for (int i = 0; i != 16; i ++) { if (is_usable(i)) { flush(i); } } } private: void read_emu(arm_gen::reg_t native, arm_gen::reg_t emu) { pool->ldr(native, RCPU, arm_gen::mem2::imm(offsetof(armcpu_t, R) + 4 * emu)); } void write_emu(arm_gen::reg_t native, arm_gen::reg_t emu) { pool->str(native, RCPU, arm_gen::mem2::imm(offsetof(armcpu_t, R) + 4 * emu)); } private: arm_gen::code_pool* pool; uint32_t mapping[16]; // Mapping[native] = emu uint32_t usage_tag[16]; bool dirty[16]; bool weak[16]; uint32_t next_usage_tag; }; #endif desmume/src/libretro-common/rthreads/psp_pthread.h000664 001750 001750 00000016611 12755534123 023552 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2016 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (psp_pthread.h). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /* FIXME: unfinished on PSP, mutexes and condition variables basically a stub. */ #ifndef _PSP_PTHREAD_WRAP__ #define _PSP_PTHREAD_WRAP__ #ifdef VITA #include #else #include #include #include #endif #include #include #define STACKSIZE (8 * 1024) typedef SceUID pthread_t; typedef SceUID pthread_mutex_t; typedef void* pthread_mutexattr_t; typedef int pthread_attr_t; typedef struct { SceUID mutex; SceUID sema; int waiting; } pthread_cond_t; typedef SceUID pthread_condattr_t; /* Use pointer values to create unique names for threads/mutexes */ char name_buffer[256]; typedef void* (*sthreadEntry)(void *argp); typedef struct { void* arg; sthreadEntry start_routine; } sthread_args_struct; static int psp_thread_wrap(SceSize args, void *argp) { sthread_args_struct* sthread_args = (sthread_args_struct*)argp; return (int)sthread_args->start_routine(sthread_args->arg); } static INLINE int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void*), void *arg) { sprintf(name_buffer, "0x%08X", (uint32_t) thread); #ifdef VITA *thread = sceKernelCreateThread(name_buffer, psp_thread_wrap, 0x10000100, 0x10000, 0, 0, NULL); #else *thread = sceKernelCreateThread(name_buffer, psp_thread_wrap, 0x20, STACKSIZE, 0, NULL); #endif sthread_args_struct sthread_args; sthread_args.arg = arg; sthread_args.start_routine = start_routine; return sceKernelStartThread(*thread, sizeof(sthread_args), &sthread_args); } static INLINE int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr) { sprintf(name_buffer, "0x%08X", (uint32_t) mutex); #ifdef VITA *mutex = sceKernelCreateMutex(name_buffer, 0, 0, 0); if(*mutex<0) return *mutex; return 0; #else return *mutex = sceKernelCreateSema(name_buffer, 0, 1, 1, NULL); #endif } static INLINE int pthread_mutex_destroy(pthread_mutex_t *mutex) { #ifdef VITA return sceKernelDeleteMutex(*mutex); #else return sceKernelDeleteSema(*mutex); #endif } static INLINE int pthread_mutex_lock(pthread_mutex_t *mutex) { #ifdef VITA int ret = sceKernelLockMutex(*mutex, 1, 0); //sceClibPrintf("pthread_mutex_lock: %x\n",ret); return ret; #else /* FIXME: stub */ return 1; #endif } static INLINE int pthread_mutex_unlock(pthread_mutex_t *mutex) { #ifdef VITA int ret = sceKernelUnlockMutex(*mutex, 1); //sceClibPrintf("pthread_mutex_unlock: %x\n",ret); return ret; #else /* FIXME: stub */ return 1; #endif } static INLINE int pthread_join(pthread_t thread, void **retval) { #ifdef VITA int res = sceKernelWaitThreadEnd(thread, 0, 0); if (res < 0) { return res; } return sceKernelDeleteThread(thread); #else SceUInt timeout = (SceUInt)-1; sceKernelWaitThreadEnd(thread, &timeout); exit_status = sceKernelGetThreadExitStatus(thread); sceKernelDeleteThread(thread); return exit_status; #endif } static INLINE int pthread_mutex_trylock(pthread_mutex_t *mutex) { #ifdef VITA return sceKernelTryLockMutex(*mutex, 1 /* not sure about this last param */); #else /* FIXME: stub */ return 1; #endif } static INLINE int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex) { #ifdef VITA int ret = pthread_mutex_lock(&cond->mutex); if (ret < 0) { return ret; } ++cond->waiting; pthread_mutex_unlock(mutex); pthread_mutex_unlock(&cond->mutex); ret = sceKernelWaitSema(cond->sema, 1, 0); if (ret < 0) { sceClibPrintf("Premature wakeup: %08X", ret); } pthread_mutex_lock(mutex); return ret; #else /* FIXME: stub */ sceKernelDelayThread(10000); return 1; #endif } static INLINE int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime) { #ifdef VITA int ret = pthread_mutex_lock(&cond->mutex); if (ret < 0) { return ret; } ++cond->waiting; pthread_mutex_unlock(mutex); pthread_mutex_unlock(&cond->mutex); SceUInt timeout = 0; timeout = abstime->tv_sec; timeout += abstime->tv_nsec / 1.0e6; ret = sceKernelWaitSema(cond->sema, 1, &timeout); if (ret < 0) { sceClibPrintf("Premature wakeup: %08X", ret); } pthread_mutex_lock(mutex); return ret; #else /* FIXME: stub */ return 1; #endif } static INLINE int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr) { #ifdef VITA pthread_mutex_init(&cond->mutex,NULL); sceClibPrintf("pthread_cond_init: mutex %x\n",cond->mutex); if(cond->mutex<0){ return cond->mutex; } sprintf(name_buffer, "0x%08X", (uint32_t) cond); //cond->sema = sceKernelCreateCond(name_buffer, 0, cond->mutex, 0); cond->sema = sceKernelCreateSema(name_buffer, 0, 0, 1, 0); sceClibPrintf("pthread_cond_init: sema %x\n",cond->sema); if(cond->sema<0){ pthread_mutex_destroy(&cond->mutex); return cond->sema; } cond->waiting = 0; return 0; #else /* FIXME: stub */ return 1; #endif } static INLINE int pthread_cond_signal(pthread_cond_t *cond) { #ifdef VITA pthread_mutex_lock(&cond->mutex); if (cond->waiting) { --cond->waiting; int ret = sceKernelSignalSema(cond->sema, 1); sceClibPrintf("pthread_cond_signal: %x\n",ret); } pthread_mutex_unlock(&cond->mutex); return 0; #else /* FIXME: stub */ return 1; #endif } static INLINE int pthread_cond_broadcast(pthread_cond_t *cond) { /* FIXME: stub */ return 1; } static INLINE int pthread_cond_destroy(pthread_cond_t *cond) { #ifdef VITA int ret = sceKernelDeleteSema(cond->sema); if(ret < 0) return ret; return sceKernelDeleteMutex(cond->mutex); #else /* FIXME: stub */ return 1; #endif } static INLINE int pthread_detach(pthread_t thread) { return 0; } static INLINE void pthread_exit(void *retval) { #ifdef VITA sceKernelExitDeleteThread(sceKernelGetThreadId()); #endif } static INLINE pthread_t pthread_self(void) { /* zero 20-mar-2016: untested */ return sceKernelGetThreadId(); } static INLINE int pthread_equal(pthread_t t1, pthread_t t2) { return t1 == t2; } #endif //_PSP_PTHREAD_WRAP__ desmume/src/utils/libfat/lock.h000664 001750 001750 00000004061 12755534123 017642 0ustar00sergiosergio000000 000000 /* lock.h Copyright (c) 2008 Sven Peter Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. 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. 3. The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. */ #ifndef _LOCK_H #define _LOCK_H #include "common.h" #ifdef USE_LWP_LOCK static inline void _FAT_lock_init(mutex_t *mutex) { LWP_MutexInit(mutex, false); } static inline void _FAT_lock_deinit(mutex_t *mutex) { LWP_MutexDestroy(*mutex); } static inline void _FAT_lock(mutex_t *mutex) { LWP_MutexLock(*mutex); } static inline void _FAT_unlock(mutex_t *mutex) { LWP_MutexUnlock(*mutex); } #else // We still need a blank lock type #ifndef mutex_t typedef int mutex_t; #endif void _FAT_lock_init(mutex_t *mutex); void _FAT_lock_deinit(mutex_t *mutex); void _FAT_lock(mutex_t *mutex); void _FAT_unlock(mutex_t *mutex); #endif // USE_LWP_LOCK #endif // _LOCK_H desmume/src/libretro-common/include/rthreads/000700 001750 001750 00000000000 12756420131 022464 5ustar00sergiosergio000000 000000 desmume/src/libretro-common/include/compat/ifaddrs.h000664 001750 001750 00000003461 12755534123 023746 0ustar00sergiosergio000000 000000 /* * Copyright (c) 1995, 1999 * Berkeley Software Design, Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, Inc. ``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 Berkeley Software Design, Inc. 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. * * BSDI ifaddrs.h,v 2.5 2000/02/23 14:51:59 dab Exp */ #ifndef _IFADDRS_H_ #define _IFADDRS_H_ struct ifaddrs { struct ifaddrs *ifa_next; char *ifa_name; unsigned int ifa_flags; struct sockaddr *ifa_addr; struct sockaddr *ifa_netmask; struct sockaddr *ifa_dstaddr; void *ifa_data; }; /* * This may have been defined in . Note that if is * to be included it must be included before this header file. */ #ifndef ifa_broadaddr #define ifa_broadaddr ifa_dstaddr /* broadcast address interface */ #endif #include extern int getifaddrs(struct ifaddrs **ifap); extern void freeifaddrs(struct ifaddrs *ifa); #endif desmume/src/libretro-common/rthreads/async_job.c000664 001750 001750 00000007000 12755534123 023173 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2016 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (async_job.c). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include #include #include #include typedef struct async_job_node async_job_node_t; struct async_job_node { async_task_t task; void *payload; async_job_node_t *next; }; struct async_job { async_job_node_t *first; async_job_node_t *last; volatile int finish; slock_t *lock; ssem_t *sem; sthread_t* thread; }; static void async_job_processor(void *userdata) { async_job_node_t *node = NULL; async_job_t *ajob = (async_job_t*)userdata; for (;;) { ssem_wait(ajob->sem); if (ajob->finish) return; slock_lock(ajob->lock); node = ajob->first; ajob->first = node->next; slock_unlock(ajob->lock); node->task(node->payload); free((void*)node); } } async_job_t *async_job_new(void) { async_job_t *ajob = (async_job_t*)calloc(1, sizeof(*ajob)); if (!ajob) return NULL; ajob->lock = slock_new(); if (!ajob->lock) goto error; ajob->sem = ssem_new(0); if (!ajob->sem) goto error; ajob->thread = sthread_create(async_job_processor, (void*)ajob); if (!ajob->thread) goto error; return ajob; error: if (ajob->lock) slock_free(ajob->lock); ajob->lock = NULL; if (ajob->sem) ssem_free(ajob->sem); if (ajob) free((void*)ajob); return NULL; } void async_job_free(async_job_t *ajob) { if (!ajob) return; ajob->finish = 1; ssem_signal(ajob->sem); sthread_join(ajob->thread); slock_free(ajob->lock); ssem_free(ajob->sem); free((void*)ajob); } int async_job_add(async_job_t *ajob, async_task_t task, void *payload) { async_job_node_t *node; if (!ajob) return -1; node = (async_job_node_t*)calloc(1, sizeof(*node)); if (!node) return -1; node->task = task; node->payload = payload; slock_lock(ajob->lock); if (ajob->first) { ajob->last->next = node; ajob->last = node; } else ajob->first = ajob->last = node; slock_unlock(ajob->lock); ssem_signal(ajob->sem); return 0; } desmume/src/utils/libfat/lock.c000664 001750 001750 00000000541 12755534123 017634 0ustar00sergiosergio000000 000000 #include "common.h" #ifndef USE_LWP_LOCK #ifndef mutex_t typedef int mutex_t; #endif void _ATTR_WEAK_ _FAT_lock_init(mutex_t *mutex) { return; } void _ATTR_WEAK_ _FAT_lock_deinit(mutex_t *mutex) { return; } void _ATTR_WEAK_ _FAT_lock(mutex_t *mutex) { return; } void _ATTR_WEAK_ _FAT_unlock(mutex_t *mutex) { return; } #endif // USE_LWP_LOCK desmume/src/libretro-common/libco/amd64.c000664 001750 001750 00000020223 12755534123 021415 0ustar00sergiosergio000000 000000 /* libco.amd64 (2009-10-12) author: byuu license: public domain */ #define LIBCO_C #include #include #include #if defined(__GNUC__) && !defined(_WIN32) && !defined(__cplusplus) #define CO_USE_INLINE_ASM #endif #ifdef __cplusplus extern "C" { #endif static thread_local long long co_active_buffer[64]; static thread_local cothread_t co_active_handle = 0; #ifndef CO_USE_INLINE_ASM static void (*co_swap)(cothread_t, cothread_t) = 0; #endif #ifdef _WIN32 /* ABI: Win64 */ static unsigned char co_swap_function[] = { 0x48, 0x89, 0x22, /* mov [rdx],rsp */ 0x48, 0x8b, 0x21, /* mov rsp,[rcx] */ 0x58, /* pop rax */ 0x48, 0x89, 0x6a, 0x08, /* mov [rdx+0x8],rbp */ 0x48, 0x89, 0x72, 0x10, /* mov [rdx+0x10],rsi */ 0x48, 0x89, 0x7a, 0x18, /* mov [rdx+0x18],rdi */ 0x48, 0x89, 0x5a, 0x20, /* mov [rdx+0x20],rbx */ 0x4c, 0x89, 0x62, 0x28, /* mov [rdx+0x28],r12 */ 0x4c, 0x89, 0x6a, 0x30, /* mov [rdx+0x30],r13 */ 0x4c, 0x89, 0x72, 0x38, /* mov [rdx+0x38],r14 */ 0x4c, 0x89, 0x7a, 0x40, /* mov [rdx+0x40],r15 */ 0x48, 0x81, 0xc2, 0x80, 0x00, 0x00, 0x00, /* add rdx,0x80 */ 0x48, 0x83, 0xe2, 0xf0, /* and rdx,-0x10 */ 0x0f, 0x29, 0x32, /* movaps [rdx],xmm6 */ 0x0f, 0x29, 0x7a, 0x10, /* movaps [rdx+0x10],xmm7 */ 0x44, 0x0f, 0x29, 0x42, 0x20, /* movaps [rdx+0x20],xmm8 */ 0x44, 0x0f, 0x29, 0x4a, 0x30, /* movaps [rdx+0x30],xmm9 */ 0x44, 0x0f, 0x29, 0x52, 0x40, /* movaps [rdx+0x40],xmm10 */ 0x44, 0x0f, 0x29, 0x5a, 0x50, /* movaps [rdx+0x50],xmm11 */ 0x44, 0x0f, 0x29, 0x62, 0x60, /* movaps [rdx+0x60],xmm12 */ 0x44, 0x0f, 0x29, 0x6a, 0x70, /* movaps [rdx+0x70],xmm13 */ 0x44, 0x0f, 0x29, 0xb2, 0x80, 0x00, 0x00, 0x00, /* movaps [rdx+0x80],xmm14 */ 0x44, 0x0f, 0x29, 0xba, 0x90, 0x00, 0x00, 0x00, /* movaps [rdx+0x90],xmm15 */ 0x48, 0x8b, 0x69, 0x08, /* mov rbp,[rcx+0x8] */ 0x48, 0x8b, 0x71, 0x10, /* mov rsi,[rcx+0x10] */ 0x48, 0x8b, 0x79, 0x18, /* mov rdi,[rcx+0x18] */ 0x48, 0x8b, 0x59, 0x20, /* mov rbx,[rcx+0x20] */ 0x4c, 0x8b, 0x61, 0x28, /* mov r12,[rcx+0x28] */ 0x4c, 0x8b, 0x69, 0x30, /* mov r13,[rcx+0x30] */ 0x4c, 0x8b, 0x71, 0x38, /* mov r14,[rcx+0x38] */ 0x4c, 0x8b, 0x79, 0x40, /* mov r15,[rcx+0x40] */ 0x48, 0x81, 0xc1, 0x80, 0x00, 0x00, 0x00, /* add rcx,0x80 */ 0x48, 0x83, 0xe1, 0xf0, /* and rcx,-0x10 */ 0x0f, 0x29, 0x31, /* movaps [rcx],xmm6 */ 0x0f, 0x29, 0x79, 0x10, /* movaps [rcx+0x10],xmm7 */ 0x44, 0x0f, 0x29, 0x41, 0x20, /* movaps [rcx+0x20],xmm8 */ 0x44, 0x0f, 0x29, 0x49, 0x30, /* movaps [rcx+0x30],xmm9 */ 0x44, 0x0f, 0x29, 0x51, 0x40, /* movaps [rcx+0x40],xmm10 */ 0x44, 0x0f, 0x29, 0x59, 0x50, /* movaps [rcx+0x50],xmm11 */ 0x44, 0x0f, 0x29, 0x61, 0x60, /* movaps [rcx+0x60],xmm12 */ 0x44, 0x0f, 0x29, 0x69, 0x70, /* movaps [rcx+0x70],xmm13 */ 0x44, 0x0f, 0x29, 0xb1, 0x80, 0x00, 0x00, 0x00, /* movaps [rcx+0x80],xmm14 */ 0x44, 0x0f, 0x29, 0xb9, 0x90, 0x00, 0x00, 0x00, /* movaps [rcx+0x90],xmm15 */ 0xff, 0xe0, /* jmp rax */ }; #include void co_init(void) { DWORD old_privileges; VirtualProtect(co_swap_function, sizeof(co_swap_function), PAGE_EXECUTE_READWRITE, &old_privileges); } #else /* ABI: SystemV */ #ifndef CO_USE_INLINE_ASM static unsigned char co_swap_function[] = { 0x48, 0x89, 0x26, /* mov [rsi],rsp */ 0x48, 0x8b, 0x27, /* mov rsp,[rdi] */ 0x58, /* pop rax */ 0x48, 0x89, 0x6e, 0x08, /* mov [rsi+0x08],rbp */ 0x48, 0x89, 0x5e, 0x10, /* mov [rsi+0x10],rbx */ 0x4c, 0x89, 0x66, 0x18, /* mov [rsi+0x18],r12 */ 0x4c, 0x89, 0x6e, 0x20, /* mov [rsi+0x20],r13 */ 0x4c, 0x89, 0x76, 0x28, /* mov [rsi+0x28],r14 */ 0x4c, 0x89, 0x7e, 0x30, /* mov [rsi+0x30],r15 */ 0x48, 0x8b, 0x6f, 0x08, /* mov rbp,[rdi+0x08] */ 0x48, 0x8b, 0x5f, 0x10, /* mov rbx,[rdi+0x10] */ 0x4c, 0x8b, 0x67, 0x18, /* mov r12,[rdi+0x18] */ 0x4c, 0x8b, 0x6f, 0x20, /* mov r13,[rdi+0x20] */ 0x4c, 0x8b, 0x77, 0x28, /* mov r14,[rdi+0x28] */ 0x4c, 0x8b, 0x7f, 0x30, /* mov r15,[rdi+0x30] */ 0xff, 0xe0, /* jmp rax */ }; #include #include void co_init(void) { unsigned long long addr = (unsigned long long)co_swap_function; unsigned long long base = addr - (addr % sysconf(_SC_PAGESIZE)); unsigned long long size = (addr - base) + sizeof(co_swap_function); mprotect((void*)base, size, PROT_READ | PROT_WRITE | PROT_EXEC); } #else void co_init(void) {} #endif #endif static void crash(void) { assert(0); /* called only if cothread_t entrypoint returns */ } cothread_t co_active(void) { if (!co_active_handle) co_active_handle = &co_active_buffer; return co_active_handle; } cothread_t co_create(unsigned int size, void (*entrypoint)(void)) { cothread_t handle; #ifndef CO_USE_INLINE_ASM if(!co_swap) { co_init(); co_swap = (void (*)(cothread_t, cothread_t))co_swap_function; } #endif if (!co_active_handle) co_active_handle = &co_active_buffer; size += 512; /* allocate additional space for storage */ size &= ~15; /* align stack to 16-byte boundary */ if((handle = (cothread_t)malloc(size))) { long long *p = (long long*)((char*)handle + size); /* seek to top of stack */ *--p = (long long)crash; /* crash if entrypoint returns */ *--p = (long long)entrypoint; /* start of function */ *(long long*)handle = (long long)p; /* stack pointer */ } return handle; } void co_delete(cothread_t handle) { free(handle); } #ifndef CO_USE_INLINE_ASM void co_switch(cothread_t handle) { register cothread_t co_previous_handle = co_active_handle; co_swap(co_active_handle = handle, co_previous_handle); } #else #ifdef __APPLE__ #define ASM_PREFIX "_" #else #define ASM_PREFIX "" #endif __asm__( ".intel_syntax noprefix \n" ".globl " ASM_PREFIX "co_switch \n" ASM_PREFIX "co_switch: \n" "mov rsi, [rip+" ASM_PREFIX "co_active_handle]\n" "mov [rsi],rsp \n" "mov [rsi+0x08],rbp \n" "mov [rsi+0x10],rbx \n" "mov [rsi+0x18],r12 \n" "mov [rsi+0x20],r13 \n" "mov [rsi+0x28],r14 \n" "mov [rsi+0x30],r15 \n" "mov [rip+" ASM_PREFIX "co_active_handle], rdi\n" "mov rsp,[rdi] \n" "mov rbp,[rdi+0x08] \n" "mov rbx,[rdi+0x10] \n" "mov r12,[rdi+0x18] \n" "mov r13,[rdi+0x20] \n" "mov r14,[rdi+0x28] \n" "mov r15,[rdi+0x30] \n" "ret \n" ".att_syntax \n" ); #endif #ifdef __cplusplus } #endif desmume/src/libretro-common/include/retro_miscellaneous.h000664 001750 001750 00000012627 12755534123 025131 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2016 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (retro_miscellaneous.h). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef __RARCH_MISCELLANEOUS_H #define __RARCH_MISCELLANEOUS_H #include #include #if defined(__CELLOS_LV2__) && !defined(__PSL1GHT__) #include #elif defined(XENON) #include