From 3eb9de46148714fc364da2d4fcb1ffff5ecf37c5 Mon Sep 17 00:00:00 2001 From: mtabachenko Date: Tue, 6 Apr 2010 15:44:03 +0000 Subject: [PATCH] core: - fix CP15 register 1 (control register); - fix CP15 register 2 (TCM size); - remove CP15 from ARM7; - fix some CPU bugs in THUMB mode (added comments from official reference); - added loops for HLE BIOS exceptions; --- desmume/src/Disassembler.cpp | 2 +- desmume/src/NDSSystem.cpp | 197 ++++++++++++---- desmume/src/armcpu.cpp | 53 ++++- desmume/src/armcpu.h | 27 +++ desmume/src/cp15.cpp | 47 ++-- desmume/src/saves.cpp | 18 +- desmume/src/thumb_instructions.cpp | 345 +++++++++++++++++------------ desmume/src/thumb_tabdef.inc | 64 +++--- 8 files changed, 506 insertions(+), 247 deletions(-) diff --git a/desmume/src/Disassembler.cpp b/desmume/src/Disassembler.cpp index 039636c50..2befc6cfc 100644 --- a/desmume/src/Disassembler.cpp +++ b/desmume/src/Disassembler.cpp @@ -3756,7 +3756,7 @@ static char * OP_BL_10(u32 adr, u32 i, char * txt) } -static char * OP_BL_THUMB(u32 adr, u32 i, char * txt) +static char * OP_BL_11(u32 adr, u32 i, char * txt) { sprintf(txt, "BL #%X", (int)(part + ((i&0x7FF)<<1))&0xFFFFFFFC); return txt; diff --git a/desmume/src/NDSSystem.cpp b/desmume/src/NDSSystem.cpp index 117298f3e..1ceeaffcb 100644 --- a/desmume/src/NDSSystem.cpp +++ b/desmume/src/NDSSystem.cpp @@ -43,6 +43,16 @@ #include "path.h" +//#define LOG_ARM9 +//#define LOG_ARM7 +bool dolog = true; +//#define LOG_TO_FILE +//#define LOG_TO_FILE_REGS + +//=============================================================== +FILE *fp_dis7 = NULL; +FILE *fp_dis9 = NULL; + PathInfo path; TCommonSettings CommonSettings; @@ -147,6 +157,21 @@ void NDS_DeInit(void) { if (cheatSearch) delete cheatSearch; +#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 } BOOL NDS_SetROM(u8 * rom, u32 mask) @@ -355,8 +380,8 @@ static void loadrom(std::string fname) { int NDS_LoadROM(const char *filename, const char *logicalFilename) { - int type = ROM_NDS; - char buf[MAX_PATH]; + int type = ROM_NDS; + char buf[MAX_PATH]; if (filename == NULL) return -1; @@ -391,7 +416,7 @@ int NDS_LoadROM(const char *filename, const char *logicalFilename) if (gameInfo.romsize < 352) { return -1; } - + //decrypt if necessary.. @@ -1677,10 +1702,6 @@ bool nds_loadstate(EMUFILE* is, int size) return temp; } -//#define LOG_ARM9 -//#define LOG_ARM7 -//bool dolog = false; - FORCEINLINE void arm9log() { #ifdef LOG_ARM9 @@ -1692,18 +1713,34 @@ FORCEINLINE void arm9log() 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;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", + 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 } FORCEINLINE void arm7log() { - #ifdef LOG_ARM7 +#ifdef LOG_ARM7 if(dolog) { char dasmbuf[4096]; @@ -1711,14 +1748,29 @@ FORCEINLINE void arm7log() 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;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", + 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 +#endif } //these have not been tuned very well yet. @@ -2000,6 +2052,11 @@ void NDS_Reset() MMU_Reset(); + NDS_ARM7.BIOS_loaded = false; + NDS_ARM9.BIOS_loaded = false; + memset(MMU.ARM7_BIOS, 0, sizeof(MMU.ARM7_BIOS)); + memset(MMU.ARM9_BIOS, 0, sizeof(MMU.ARM9_BIOS)); + //ARM7 BIOS IRQ HANDLER if(CommonSettings.UseExtBIOS == true) inf = fopen(CommonSettings.ARM7BIOS,"rb"); @@ -2008,33 +2065,39 @@ void NDS_Reset() if(inf) { - fread(MMU.ARM7_BIOS,1,16384,inf); + if (fread(MMU.ARM7_BIOS,1,16384,inf) == 16384) NDS_ARM7.BIOS_loaded = true; fclose(inf); - if(CommonSettings.SWIFromBIOS == true) NDS_ARM7.swi_tab = 0; + if((CommonSettings.SWIFromBIOS) && (NDS_ARM7.BIOS_loaded)) NDS_ARM7.swi_tab = 0; else NDS_ARM7.swi_tab = ARM7_swi_tab; if (CommonSettings.PatchSWI3) _MMU_write16(0x00002F08, 0x4770); - INFO("ARM7 BIOS is loaded.\n"); + INFO("ARM7 BIOS is %s.\n", NDS_ARM7.BIOS_loaded?"loaded":"failed"); } else { NDS_ARM7.swi_tab = ARM7_swi_tab; - for (int t = 0; t < 16384; t++) - MMU.ARM7_BIOS[t] = 0xFF; - - T1WriteLong(MMU.ARM7_BIOS,0x00, 0xE25EF002); - T1WriteLong(MMU.ARM7_BIOS,0x04, 0xEAFFFFFE); - T1WriteLong(MMU.ARM7_BIOS,0x18, 0xEA000000); - T1WriteLong(MMU.ARM7_BIOS,0x20, 0xE92D500F); - T1WriteLong(MMU.ARM7_BIOS,0x24, 0xE3A00301); - T1WriteLong(MMU.ARM7_BIOS,0x28, 0xE28FE000); - T1WriteLong(MMU.ARM7_BIOS,0x2C, 0xE510F004); - T1WriteLong(MMU.ARM7_BIOS,0x30, 0xE8BD500F); - T1WriteLong(MMU.ARM7_BIOS,0x34, 0xE25EF004); +#if 0 + // TODO + T1WriteLong(MMU.ARM7_BIOS, 0x0000, 0xEAFFFFFE); // loop for Reset !!! + T1WriteLong(MMU.ARM7_BIOS, 0x0004, 0xEAFFFFFE); // loop for Undef instr expection + T1WriteLong(MMU.ARM7_BIOS, 0x0008, 0xEA00009C); // SWI + T1WriteLong(MMU.ARM7_BIOS, 0x000C, 0xEAFFFFFE); // loop for Prefetch Abort + T1WriteLong(MMU.ARM7_BIOS, 0x0010, 0xEAFFFFFE); // loop for Data Abort + T1WriteLong(MMU.ARM7_BIOS, 0x0014, 0x00000000); // Reserved + T1WriteLong(MMU.ARM7_BIOS, 0x001C, 0x00000000); // Fast IRQ +#endif + T1WriteLong(MMU.ARM7_BIOS, 0x0000, 0xE25EF002); + T1WriteLong(MMU.ARM7_BIOS, 0x0018, 0xEA000000); + T1WriteLong(MMU.ARM7_BIOS, 0x0020, 0xE92D500F); + T1WriteLong(MMU.ARM7_BIOS, 0x0024, 0xE3A00301); + T1WriteLong(MMU.ARM7_BIOS, 0x0028, 0xE28FE000); + T1WriteLong(MMU.ARM7_BIOS, 0x002C, 0xE510F004); + T1WriteLong(MMU.ARM7_BIOS, 0x0030, 0xE8BD500F); + T1WriteLong(MMU.ARM7_BIOS, 0x0034, 0xE25EF004); } //ARM9 BIOS IRQ HANDLER @@ -2042,44 +2105,63 @@ void NDS_Reset() inf = fopen(CommonSettings.ARM9BIOS,"rb"); else inf = NULL; - //memcpy(MMU.ARM9_BIOS + 0x20, gba_header_data_0x04, 156); if(inf) { - fread(MMU.ARM9_BIOS,1,4096,inf); + if (fread(MMU.ARM9_BIOS,1,4096,inf) == 4096) NDS_ARM9.BIOS_loaded = true; fclose(inf); - if(CommonSettings.SWIFromBIOS == true) NDS_ARM9.swi_tab = 0; + if((CommonSettings.SWIFromBIOS) && (NDS_ARM9.BIOS_loaded)) NDS_ARM9.swi_tab = 0; else NDS_ARM9.swi_tab = ARM9_swi_tab; if (CommonSettings.PatchSWI3) _MMU_write16(0xFFFF07CC, 0x4770); - INFO("ARM9 BIOS is loaded.\n"); + INFO("ARM9 BIOS is %s.\n", NDS_ARM9.BIOS_loaded?"loaded":"failed"); } else { NDS_ARM9.swi_tab = ARM9_swi_tab; - for (int t = 0; t < 4096; t++) - MMU.ARM9_BIOS[t] = 0xFF; - - _MMU_write32(0xFFFF0018, 0xEA000095); - - for (int t = 0; t < 156; t++) // load logo + T1WriteLong(MMU.ARM9_BIOS, 0x0000, 0xEAFFFFFE); // loop for Reset !!! + T1WriteLong(MMU.ARM9_BIOS, 0x0004, 0xEAFFFFFE); // loop for Undef instr expection + T1WriteLong(MMU.ARM9_BIOS, 0x0008, 0xEA00009C); // SWI + T1WriteLong(MMU.ARM9_BIOS, 0x000C, 0xEAFFFFFE); // loop for Prefetch Abort + T1WriteLong(MMU.ARM9_BIOS, 0x0010, 0xEAFFFFFE); // loop for Data Abort + T1WriteLong(MMU.ARM9_BIOS, 0x0014, 0x00000000); // Reserved + T1WriteLong(MMU.ARM9_BIOS, 0x0018, 0xEA000095); // Normal IRQ + T1WriteLong(MMU.ARM9_BIOS, 0x001C, 0x00000000); // Fast IRQ + for (int t = 0; t < 156; t++) // logo MMU.ARM9_BIOS[t + 0x20] = logo_data[t]; - - _MMU_write32(0xFFFF0274, 0xE92D500F); - _MMU_write32(0xFFFF0278, 0xEE190F11); - _MMU_write32(0xFFFF027C, 0xE1A00620); - _MMU_write32(0xFFFF0280, 0xE1A00600); - _MMU_write32(0xFFFF0284, 0xE2800C40); - _MMU_write32(0xFFFF0288, 0xE28FE000); - _MMU_write32(0xFFFF028C, 0xE510F004); - _MMU_write32(0xFFFF0290, 0xE8BD500F); - _MMU_write32(0xFFFF0294, 0xE25EF004); + T1WriteLong(MMU.ARM9_BIOS, 0x0274, 0xE92D500F); + T1WriteLong(MMU.ARM9_BIOS, 0x0278, 0xEE190F11); + T1WriteLong(MMU.ARM9_BIOS, 0x027C, 0xE1A00620); + T1WriteLong(MMU.ARM9_BIOS, 0x0280, 0xE1A00600); + T1WriteLong(MMU.ARM9_BIOS, 0x0284, 0xE2800C40); + T1WriteLong(MMU.ARM9_BIOS, 0x0288, 0xE28FE000); + T1WriteLong(MMU.ARM9_BIOS, 0x028C, 0xE510F004); + T1WriteLong(MMU.ARM9_BIOS, 0x0290, 0xE8BD500F); + T1WriteLong(MMU.ARM9_BIOS, 0x0294, 0xE25EF004); } +#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 + if (firmware) { delete firmware; @@ -2087,7 +2169,7 @@ void NDS_Reset() } firmware = new CFIRMWARE(); fw_success = firmware->load(); - if ((CommonSettings.UseExtBIOS == true) && (CommonSettings.BootFromFirmware == true) && (fw_success == TRUE)) + if (NDS_ARM7.BIOS_loaded && NDS_ARM9.BIOS_loaded && CommonSettings.BootFromFirmware && fw_success) { // Copy secure area to memory if needed if ((header->ARM9src >= 0x4000) && (header->ARM9src < 0x8000)) @@ -2220,8 +2302,8 @@ void NDS_Reset() std::string rompath = "fat:/" + path.RomName; const u32 kCommandline = 0x027E0000; //const u32 kCommandline = 0x027FFF84; - - // + + // _MMU_write32(0x02FFFE70, 0x5f617267); _MMU_write32(0x02FFFE74, kCommandline); //(commandline starts here) _MMU_write32(0x02FFFE78, rompath.size()+1); @@ -2654,6 +2736,25 @@ void NDS_suspendProcessingInput(bool suspend) 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 } //these templates needed to be instantiated manually diff --git a/desmume/src/armcpu.cpp b/desmume/src/armcpu.cpp index 07ebb15c2..7dbe29367 100644 --- a/desmume/src/armcpu.cpp +++ b/desmume/src/armcpu.cpp @@ -230,11 +230,10 @@ void armcpu_init(armcpu_t *armcpu, u32 adr) armcpu->irq_flag = 0; #endif - if(armcpu->coproc[15]) free(armcpu->coproc[15]); - for(i = 0; i < 15; ++i) { armcpu->R[i] = 0; + if(armcpu->coproc[i]) free(armcpu->coproc[i]); armcpu->coproc[i] = NULL; } @@ -258,7 +257,9 @@ void armcpu_init(armcpu_t *armcpu, u32 adr) armcpu->next_instruction = adr; - armcpu->coproc[15] = (armcp_t*)armcp15_new(armcpu); + // only ARM9 have co-processor + if (armcpu->proc_ID==0) + armcpu->coproc[15] = (armcp_t*)armcp15_new(armcpu); #ifndef GDB_STUB armcpu_prefetch(armcpu); @@ -380,10 +381,10 @@ FORCEINLINE static u32 armcpu_prefetch() #ifdef GDB_STUB u32 temp_instruction; #endif + u32 curInstruction = armcpu->next_instruction; if(armcpu->CPSR.bits.T == 0) { - u32 curInstruction = armcpu->next_instruction; #ifdef GDB_STUB temp_instruction = armcpu->mem_if->prefetch32( armcpu->mem_if->data, @@ -396,7 +397,8 @@ FORCEINLINE static u32 armcpu_prefetch() armcpu->R[15] = armcpu->next_instruction + 4; } #else - armcpu->instruction = _MMU_read32(curInstruction&0xFFFFFFFC); + curInstruction &= 0x0FFFFFFC; + armcpu->instruction = _MMU_read32(curInstruction); armcpu->instruct_adr = curInstruction; armcpu->next_instruction = curInstruction + 4; armcpu->R[15] = curInstruction + 8; @@ -405,7 +407,6 @@ FORCEINLINE static u32 armcpu_prefetch() return MMU_codeFetchCycles(curInstruction); } - u32 curInstruction = armcpu->next_instruction; #ifdef GDB_STUB temp_instruction = armcpu->mem_if->prefetch16( armcpu->mem_if->data, @@ -418,7 +419,8 @@ FORCEINLINE static u32 armcpu_prefetch() armcpu->R[15] = armcpu->next_instruction + 2; } #else - armcpu->instruction = _MMU_read16(curInstruction&0xFFFFFFFE); + curInstruction &= 0x0FFFFFFE; + armcpu->instruction = _MMU_read16(curInstruction); armcpu->instruct_adr = curInstruction; armcpu->next_instruction = curInstruction + 2; armcpu->R[15] = curInstruction + 4; @@ -524,6 +526,43 @@ u32 armcpu_exec() //this assert is annoying. but sometimes it is handy. //assert(ARMPROC.instruct_adr!=0x00000000); +#ifdef DEVELOPER + 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 #ifdef GDB_STUB if (ARMPROC.stalled) { diff --git a/desmume/src/armcpu.h b/desmume/src/armcpu.h index 3faa5cfe2..e5914ed46 100644 --- a/desmume/src/armcpu.h +++ b/desmume/src/armcpu.h @@ -45,6 +45,31 @@ inline T SIGNED_OVERFLOW(T a,T b,T c) { return BIT31(((a)&(b)&(~c)) | ((~a)&(~(b template inline T SIGNED_UNDERFLOW(T a,T b,T c) { return BIT31(((a)&(~(b))&(~c)) | ((~a)&(b)&(c))); } +// ============================= CPRS flags funcs +static bool CarryFrom(s32 left, s32 right) +{ + u32 res = (0xFFFFFFFF - (u32)left); + + return ((u32)right > res); +} + +static bool BorrowFrom(s32 left, s32 right) +{ + return ((u32)right > (u32)left); +} + +static 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)); +} + +static 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 @@ -175,6 +200,8 @@ struct armcpu_t BOOL waitIRQ; BOOL wirq; + BOOL BIOS_loaded; + u32 (* *swi_tab)(); // flag indicating if the processor is stalled (for debugging) diff --git a/desmume/src/cp15.cpp b/desmume/src/cp15.cpp index e9e29ebbe..d793d2f91 100644 --- a/desmume/src/cp15.cpp +++ b/desmume/src/cp15.cpp @@ -31,11 +31,12 @@ armcp15_t *armcp15_new(armcpu_t * c) armcp15_t *armcp15 = (armcp15_t*)malloc(sizeof(armcp15_t)); if(!armcp15) return NULL; + armcp15->cpu = c; armcp15->IDCode = 0x41049460; armcp15->cacheType = 0x0F0D2112; - armcp15->TCMSize = 0x00140140; - armcp15->ctrl = 0x00000000; + armcp15->TCMSize = 0x00140180; + armcp15->ctrl = 0x00012078; armcp15->DCConfig = 0x0; armcp15->ICConfig = 0x0; armcp15->writeBuffCtrl = 0x0; @@ -57,6 +58,10 @@ armcp15_t *armcp15_new(armcpu_t * c) armcp15->DTCMRegion = 0x0080000A; armcp15->processID = 0; + MMU.ARM9_RW_MODE = BIT7(armcp15->ctrl); + armcp15->cpu->intVector = 0xFFFF0000 * (BIT13(armcp15->ctrl)); + armcp15->cpu->LDTBit = !BIT15(armcp15->ctrl); //TBit + /* preset calculated regionmasks */ for (i=0;i<8;i++) { armcp15->regionWriteMask_USR[i] = 0 ; @@ -291,6 +296,7 @@ BOOL armcp15_moveCP2ARM(armcp15_t *armcp15, u32 * R, u8 CRn, u8 CRm, u8 opcode1, if((opcode1==0) && (opcode2==0) && (CRm==0)) { *R = armcp15->ctrl; + //LOG("CP15: CPtoARM ctrl %08X\n", armcp15->ctrl); return TRUE; } return FALSE; @@ -315,6 +321,7 @@ BOOL armcp15_moveCP2ARM(armcp15_t *armcp15, u32 * R, u8 CRn, u8 CRm, u8 opcode1, if((opcode1==0) && (opcode2==0) && (CRm==0)) { *R = armcp15->writeBuffCtrl; + //LOG("CP15: CPtoARM writeBuffer ctrl %08X\n", armcp15->writeBuffCtrl); return TRUE; } return FALSE; @@ -406,33 +413,38 @@ BOOL armcp15_moveCP2ARM(armcp15_t *armcp15, u32 * R, u8 CRn, u8 CRm, u8 opcode1, } } - static u32 CP15wait4IRQ(armcpu_t *cpu) { +#if 1 u32 instructAddr = cpu->instruct_adr; - /* on the first call, wirq is not set */ + // on the first call, wirq is not set if(cpu->wirq) { - /* check wether an irq was issued */ + // check wether an irq was issued if(!cpu->waitIRQ) { cpu->waitIRQ = 0; cpu->wirq = 0; - return 1; /* return execution */ + return 1; // return execution } - /* otherwise, repeat this instruction */ + // otherwise, repeat this instruction cpu->R[15] = instructAddr; cpu->next_instruction = instructAddr; return 1; } - /* first run, set us into waiting state */ + + // first run, set us into waiting state cpu->waitIRQ = 1; cpu->wirq = 1; - /* and set next instruction to repeat this */ + // and set next instruction to repeat this cpu->R[15] = instructAddr; cpu->next_instruction = instructAddr; - /* CHECKME: IME shouldn't be modified (?) */ - MMU.reg_IME[0] = 1; +#else + //printf("CP15: IME %X, IE %08X, IF %08X res %08X\n", MMU.reg_IME[0], MMU.reg_IE[0], MMU.reg_IF[0], MMU.reg_IE[0] & MMU.reg_IF[0]); + //if ((MMU.reg_IE[0] & MMU.reg_IF[0]) == 0) return 1; + cpu->waitIRQ = 1; +#endif + // only SWI set IME to 1 return 1; } @@ -445,7 +457,9 @@ BOOL armcp15_moveARM2CP(armcp15_t *armcp15, u32 val, u8 CRn, u8 CRm, u8 opcode1, case 1 : if((opcode1==0) && (opcode2==0) && (CRm==0)) { - armcp15->ctrl = val; + + //On the NDS bit0,2,7,12..19 are R/W, Bit3..6 are always set, all other bits are always zero. + armcp15->ctrl = (val & 0x000FF085) | 0x00000078; MMU.ARM9_RW_MODE = BIT7(val); //zero 31-jan-2010: change from 0x0FFF0000 to 0xFFFF0000 per gbatek armcp15->cpu->intVector = 0xFFFF0000 * (BIT13(val)); @@ -458,6 +472,8 @@ BOOL armcp15_moveARM2CP(armcp15_t *armcp15, u32 val, u8 CRn, u8 CRm, u8 opcode1, { log::ajouter("outch !!!!!!!"); }*/ + + //LOG("CP15: ARMtoCP ctrl %08X (val %08X)\n", armcp15->ctrl, val); return TRUE; } return FALSE; @@ -481,6 +497,7 @@ BOOL armcp15_moveARM2CP(armcp15_t *armcp15, u32 val, u8 CRn, u8 CRm, u8 opcode1, if((opcode1==0) && (opcode2==0) && (CRm==0)) { armcp15->writeBuffCtrl = val; + //LOG("CP15: ARMtoCP writeBuffer ctrl %08X\n", armcp15->writeBuffCtrl); return TRUE; } return FALSE; @@ -572,8 +589,10 @@ BOOL armcp15_moveARM2CP(armcp15_t *armcp15, u32 val, u8 CRn, u8 CRm, u8 opcode1, switch(opcode2) { case 0 : - armcp15->DTCMRegion = val; - MMU.DTCMRegion = val & 0x0FFFFFFC0; + MMU.DTCMRegion = armcp15->DTCMRegion = val & 0x0FFFF000; + //MMU.DTCMRegion = val; + //MMU.DTCMRegion = val & 0x0FFFFFFC0; + //LOG("CP15: set DTCM %08X (size %i)\n", MMU.DTCMRegion, 512<<(val & 0x00000FFF)); /*sprintf(logbuf, "%08X", val); log::ajouter(logbuf);*/ return TRUE; diff --git a/desmume/src/saves.cpp b/desmume/src/saves.cpp index 80a43b364..948df4432 100644 --- a/desmume/src/saves.cpp +++ b/desmume/src/saves.cpp @@ -497,10 +497,11 @@ static void cp15_saveone(armcp15_t *cp15, EMUFILE* os) static void cp15_savestate(EMUFILE* os) { //version - write32le(0,os); + write32le(1,os); cp15_saveone((armcp15_t *)NDS_ARM9.coproc[15],os); - cp15_saveone((armcp15_t *)NDS_ARM7.coproc[15],os); + //ARM7 not have coprocessor + //cp15_saveone((armcp15_t *)NDS_ARM7.coproc[15],os); } static bool cp15_loadone(armcp15_t *cp15, EMUFILE* is) @@ -553,10 +554,19 @@ static bool cp15_loadstate(EMUFILE* is, int size) //read version u32 version; if(read32le(&version,is) != 1) return false; - if(version != 0) return false; + if(version > 1) return false; if(!cp15_loadone((armcp15_t *)NDS_ARM9.coproc[15],is)) return false; - if(!cp15_loadone((armcp15_t *)NDS_ARM7.coproc[15],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((armcp15_t *)tmp_buf,is)) return false; + delete [] tmp_buf; + tmp_buf = NULL; + } return true; } diff --git a/desmume/src/thumb_instructions.cpp b/desmume/src/thumb_instructions.cpp index 2721d52dc..fb086b512 100644 --- a/desmume/src/thumb_instructions.cpp +++ b/desmume/src/thumb_instructions.cpp @@ -44,6 +44,7 @@ TEMPLATE static u32 FASTCALL OP_UND_THUMB(const u32 i) { + INFO("THUMB%c: Undefined instruction: 0x%08X PC=0x%08X. Stopped!!!\n", cpu->proc_ID?'7':'9', cpu->instruction, cpu->instruct_adr); emu_halt(); return 1; } @@ -74,7 +75,7 @@ TEMPLATE static u32 FASTCALL OP_LSL(const u32 i) TEMPLATE static u32 FASTCALL OP_LSL_REG(const u32 i) { - u32 v = cpu->R[REG_NUM(i, 3)]&0xFF; + u32 v = cpu->R[REG_NUM(i, 3)] & 0xFF; if(v == 0) { @@ -129,7 +130,7 @@ TEMPLATE static u32 FASTCALL OP_LSR(const u32 i) TEMPLATE static u32 FASTCALL OP_LSR_REG(const u32 i) { - u32 v = cpu->R[REG_NUM(i, 3)]&0xFF; + u32 v = cpu->R[REG_NUM(i, 3)] & 0xFF; if(v == 0) { @@ -174,7 +175,7 @@ TEMPLATE static u32 FASTCALL OP_ASR(const u32 i) { u32 v = (i>>6) & 0x1F; cpu->CPSR.bits.C = BIT_N(cpu->R[REG_NUM(i, 3)], v-1); - cpu->R[REG_NUM(i, 0)] = (((s32)cpu->R[REG_NUM(i, 3)]) >> v); + cpu->R[REG_NUM(i, 0)] = (u32)(((s32)cpu->R[REG_NUM(i, 3)]) >> v); cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]); cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0; @@ -183,7 +184,7 @@ TEMPLATE static u32 FASTCALL OP_ASR(const u32 i) TEMPLATE static u32 FASTCALL OP_ASR_REG(const u32 i) { - u32 v = cpu->R[REG_NUM(i, 3)]&0xFF; + u32 v = cpu->R[REG_NUM(i, 3)] & 0xFF; if(v == 0) { @@ -212,47 +213,63 @@ TEMPLATE static u32 FASTCALL OP_ASR_REG(const u32 i) // ADD //----------------------------------------------------------------------------- -TEMPLATE static u32 FASTCALL OP_ADD_REG(const u32 i) -{ - u32 a = cpu->R[REG_NUM(i, 3)]; - u32 b = cpu->R[REG_NUM(i, 6)]; - cpu->R[REG_NUM(i, 0)] = a + b; - cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]); - cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0; - cpu->CPSR.bits.C = UNSIGNED_OVERFLOW(a, b, cpu->R[REG_NUM(i, 0)]); - cpu->CPSR.bits.V = SIGNED_OVERFLOW(a, b, cpu->R[REG_NUM(i, 0)]); - - return 1; -} - TEMPLATE static u32 FASTCALL OP_ADD_IMM3(const u32 i) { - u32 a = cpu->R[REG_NUM(i, 3)]; + u32 imm3 = (i >> 6) & 0x07; + u32 Rn = cpu->R[REG_NUM(i, 3)]; - cpu->R[REG_NUM(i, 0)] = a + REG_NUM(i, 6); + if (imm3 == 0) // mov 2 + { + cpu->R[REG_NUM(i, 0)] = Rn; + + cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]); + cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0; + cpu->CPSR.bits.C = 0; + cpu->CPSR.bits.V = 0; + return 1; + } + + cpu->R[REG_NUM(i, 0)] = Rn + imm3; cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]); cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0; - cpu->CPSR.bits.C = UNSIGNED_OVERFLOW(a, REG_NUM(i, 6), cpu->R[REG_NUM(i, 0)]); - cpu->CPSR.bits.V = SIGNED_OVERFLOW(a, REG_NUM(i, 6), cpu->R[REG_NUM(i, 0)]); + cpu->CPSR.bits.C = CarryFrom(Rn, imm3); + cpu->CPSR.bits.V = OverflowFromADD(cpu->R[REG_NUM(i, 0)], Rn, imm3); return 1; } TEMPLATE static u32 FASTCALL OP_ADD_IMM8(const u32 i) { - u32 tmp = cpu->R[REG_NUM(i, 8)] + (i & 0xFF); - cpu->CPSR.bits.N = BIT31(tmp); - cpu->CPSR.bits.Z = tmp == 0; - cpu->CPSR.bits.C = UNSIGNED_OVERFLOW(cpu->R[REG_NUM(i, 8)], (i & 0xFF), tmp); - cpu->CPSR.bits.V = SIGNED_OVERFLOW(cpu->R[REG_NUM(i, 8)], (i & 0xFF), tmp); - cpu->R[REG_NUM(i, 8)] = tmp; + u32 imm8 = (i & 0xFF); + u32 Rd = cpu->R[REG_NUM(i, 8)]; + + cpu->R[REG_NUM(i, 8)] = Rd + imm8; + cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 8)]); + cpu->CPSR.bits.Z = (cpu->R[REG_NUM(i, 8)] == 0); + cpu->CPSR.bits.C = CarryFrom(Rd, imm8); + cpu->CPSR.bits.V = OverflowFromADD(cpu->R[REG_NUM(i, 8)], Rd, imm8); + + return 1; +} + +TEMPLATE static u32 FASTCALL OP_ADD_REG(const u32 i) +{ + u32 Rn = cpu->R[REG_NUM(i, 3)]; + u32 Rm = cpu->R[REG_NUM(i, 6)]; + + cpu->R[REG_NUM(i, 0)] = Rn + Rm; + cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]); + cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0; + cpu->CPSR.bits.C = CarryFrom(Rn, Rm); + cpu->CPSR.bits.V = OverflowFromADD(cpu->R[REG_NUM(i, 0)], Rn, Rm); return 1; } TEMPLATE static u32 FASTCALL OP_ADD_SPE(const u32 i) { - u32 Rd = (i&7) | ((i>>4)&8); + u32 Rd = REG_NUM(i, 0) | ((i>>4)&8); + cpu->R[Rd] += cpu->R[REG_POS(i, 3)]; if(Rd==15) @@ -264,7 +281,6 @@ TEMPLATE static u32 FASTCALL OP_ADD_SPE(const u32 i) return 1; } - TEMPLATE static u32 FASTCALL OP_ADD_2PC(const u32 i) { cpu->R[REG_NUM(i, 8)] = (cpu->R[15]&0xFFFFFFFC) + ((i&0xFF)<<2); @@ -283,39 +299,44 @@ TEMPLATE static u32 FASTCALL OP_ADD_2SP(const u32 i) // SUB //----------------------------------------------------------------------------- -TEMPLATE static u32 FASTCALL OP_SUB_REG(const u32 i) -{ - u32 a = cpu->R[REG_NUM(i, 3)]; - u32 b = cpu->R[REG_NUM(i, 6)]; - cpu->R[REG_NUM(i, 0)] = a - b; - cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]); - cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0; - cpu->CPSR.bits.C = !UNSIGNED_UNDERFLOW(a, b, cpu->R[REG_NUM(i, 0)]); - cpu->CPSR.bits.V = SIGNED_UNDERFLOW(a, b, cpu->R[REG_NUM(i, 0)]); - - return 1; -} - TEMPLATE static u32 FASTCALL OP_SUB_IMM3(const u32 i) { - u32 a = cpu->R[REG_NUM(i, 3)]; - cpu->R[REG_NUM(i, 0)] = a - REG_NUM(i, 6); + u32 imm3 = (i>>6) & 0x07; + u32 Rn = cpu->R[REG_NUM(i, 3)]; + + cpu->R[REG_NUM(i, 0)] = Rn - imm3; cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]); cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0; - cpu->CPSR.bits.C = !UNSIGNED_UNDERFLOW(a, REG_NUM(i, 6), cpu->R[REG_NUM(i, 0)]); - cpu->CPSR.bits.V = SIGNED_UNDERFLOW(a, REG_NUM(i, 6), cpu->R[REG_NUM(i, 0)]); + cpu->CPSR.bits.C = !BorrowFrom(Rn, imm3); + cpu->CPSR.bits.V = OverflowFromSUB(REG_NUM(i, 0), Rn, imm3); return 1; } TEMPLATE static u32 FASTCALL OP_SUB_IMM8(const u32 i) { - u32 tmp = cpu->R[REG_NUM(i, 8)] - (i & 0xFF); - cpu->CPSR.bits.N = BIT31(tmp); - cpu->CPSR.bits.Z = tmp == 0; - cpu->CPSR.bits.C = !UNSIGNED_UNDERFLOW(cpu->R[REG_NUM(i, 8)], (i & 0xFF), tmp); - cpu->CPSR.bits.V = SIGNED_UNDERFLOW(cpu->R[REG_NUM(i, 8)], (i & 0xFF), tmp); - cpu->R[REG_NUM(i, 8)] = tmp; + u32 imm8 = (i & 0xFF); + u32 Rd = cpu->R[REG_NUM(i, 8)]; + + cpu->R[REG_NUM(i, 8)] = Rd - imm8; + cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 8)]); + cpu->CPSR.bits.Z = (cpu->R[REG_NUM(i, 8)] == 0); + cpu->CPSR.bits.C = !BorrowFrom(Rd, imm8); + cpu->CPSR.bits.V = OverflowFromSUB(cpu->R[REG_NUM(i, 8)], Rd, imm8); + + return 1; +} + +TEMPLATE static u32 FASTCALL OP_SUB_REG(const u32 i) +{ + u32 Rn = cpu->R[REG_NUM(i, 3)]; + u32 Rm = cpu->R[REG_NUM(i, 6)]; + + cpu->R[REG_NUM(i, 0)] = Rn - Rm; + cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]); + cpu->CPSR.bits.Z = (cpu->R[REG_NUM(i, 0)] == 0); + cpu->CPSR.bits.C = !BorrowFrom(Rn, Rm); + cpu->CPSR.bits.V = OverflowFromSUB(cpu->R[REG_NUM(i, 0)], Rn, Rm); return 1; } @@ -326,7 +347,7 @@ TEMPLATE static u32 FASTCALL OP_SUB_IMM8(const u32 i) TEMPLATE static u32 FASTCALL OP_MOV_IMM8(const u32 i) { - cpu->R[REG_NUM(i, 8)] = i & 0xFF; + cpu->R[REG_NUM(i, 8)] = (i & 0xFF); cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 8)]); cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 8)] == 0; @@ -335,7 +356,8 @@ TEMPLATE static u32 FASTCALL OP_MOV_IMM8(const u32 i) TEMPLATE static u32 FASTCALL OP_MOV_SPE(const u32 i) { - u32 Rd = (i&7) | ((i>>4)&8); + u32 Rd = REG_NUM(i, 0) | ((i>>4)&8); + cpu->R[Rd] = cpu->R[REG_POS(i, 3)]; if(Rd==15) @@ -350,40 +372,40 @@ TEMPLATE static u32 FASTCALL OP_MOV_SPE(const u32 i) //----------------------------------------------------------------------------- // CMP //----------------------------------------------------------------------------- - -TEMPLATE static u32 FASTCALL OP_CMP(const u32 i) -{ - u32 tmp = cpu->R[REG_NUM(i, 0)] -cpu->R[REG_NUM(i, 3)]; - - cpu->CPSR.bits.N = BIT31(tmp); - cpu->CPSR.bits.Z = tmp == 0; - cpu->CPSR.bits.C = !UNSIGNED_UNDERFLOW(cpu->R[REG_NUM(i, 0)], cpu->R[REG_NUM(i, 3)], tmp); - cpu->CPSR.bits.V = SIGNED_UNDERFLOW(cpu->R[REG_NUM(i, 0)], cpu->R[REG_NUM(i, 3)], tmp); - - return 1; -} - TEMPLATE static u32 FASTCALL OP_CMP_IMM8(const u32 i) { u32 tmp = cpu->R[REG_NUM(i, 8)] - (i & 0xFF); cpu->CPSR.bits.N = BIT31(tmp); cpu->CPSR.bits.Z = tmp == 0; - cpu->CPSR.bits.C = !UNSIGNED_UNDERFLOW(cpu->R[REG_NUM(i, 8)], (i & 0xFF), tmp); - cpu->CPSR.bits.V = SIGNED_UNDERFLOW(cpu->R[REG_NUM(i, 8)], (i & 0xFF), tmp); + cpu->CPSR.bits.C = !BorrowFrom(cpu->R[REG_NUM(i, 8)], (i & 0xFF)); + cpu->CPSR.bits.V = OverflowFromSUB(tmp, cpu->R[REG_NUM(i, 8)], (i & 0xFF)); return 1; } +TEMPLATE static u32 FASTCALL OP_CMP(const u32 i) +{ + u32 tmp = cpu->R[REG_NUM(i, 0)] - cpu->R[REG_NUM(i, 3)]; + + cpu->CPSR.bits.N = BIT31(tmp); + cpu->CPSR.bits.Z = tmp == 0; + cpu->CPSR.bits.C = !BorrowFrom(cpu->R[REG_NUM(i, 0)], cpu->R[REG_NUM(i, 3)]); + cpu->CPSR.bits.V = OverflowFromSUB(tmp, cpu->R[REG_NUM(i, 0)], cpu->R[REG_NUM(i, 3)]); + + return 1; +} + TEMPLATE static u32 FASTCALL OP_CMP_SPE(const u32 i) { u32 Rn = (i&7) | ((i>>4)&8); - u32 tmp = cpu->R[Rn] -cpu->R[REG_POS(i, 3)]; + + u32 tmp = cpu->R[Rn] - cpu->R[REG_POS(i, 3)]; cpu->CPSR.bits.N = BIT31(tmp); cpu->CPSR.bits.Z = tmp == 0; - cpu->CPSR.bits.C = !UNSIGNED_UNDERFLOW(cpu->R[Rn], cpu->R[REG_POS(i, 3)], tmp); - cpu->CPSR.bits.V = SIGNED_UNDERFLOW(cpu->R[Rn], cpu->R[REG_POS(i, 3)], tmp); + cpu->CPSR.bits.C = !BorrowFrom(cpu->R[Rn], cpu->R[REG_NUM(i, 3)]); + cpu->CPSR.bits.V = OverflowFromSUB(tmp, cpu->R[Rn], cpu->R[REG_NUM(i, 3)]); return 1; } @@ -397,7 +419,6 @@ TEMPLATE static u32 FASTCALL OP_AND(const u32 i) cpu->R[REG_NUM(i, 0)] &= cpu->R[REG_NUM(i, 3)]; cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]); cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0; - return 1; } @@ -420,6 +441,22 @@ TEMPLATE static u32 FASTCALL OP_EOR(const u32 i) TEMPLATE static u32 FASTCALL OP_ADC_REG(const u32 i) { +#if 0 + printf("THUMB%c: ADC\n", PROCNUM?'7':'9'); + u32 Rd = cpu->R[REG_NUM(i, 0)]; + u32 Rm = cpu->R[REG_NUM(i, 3)]; + + cpu->R[REG_NUM(i, 0)] = Rd + Rm + cpu->CPSR.bits.C; + + cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]); + cpu->CPSR.bits.Z = (cpu->R[REG_NUM(i, 0)] == 0); + + // TODO!!!! + cpu->CPSR.bits.C = CarryFrom(Rd, Rm + cpu->CPSR.bits.C); + cpu->CPSR.bits.V = OverflowFromADD(cpu->R[REG_NUM(i, 0)], Rd, Rm + cpu->CPSR.bits.C); + //cpu->CPSR.bits.C = UNSIGNED_OVERFLOW(b, (u32) cpu->CPSR.bits.C, tmp) | UNSIGNED_OVERFLOW(tmp, a, res); + //cpu->CPSR.bits.V = SIGNED_OVERFLOW(b, (u32) cpu->CPSR.bits.C, tmp) | SIGNED_OVERFLOW(tmp, a, res); +#else u32 a = cpu->R[REG_NUM(i, 0)]; u32 b = cpu->R[REG_NUM(i, 3)]; u32 tmp = b + cpu->CPSR.bits.C; @@ -430,19 +467,9 @@ TEMPLATE static u32 FASTCALL OP_ADC_REG(const u32 i) cpu->CPSR.bits.N = BIT31(res); cpu->CPSR.bits.Z = res == 0; -#if 0 - //the below UNSIGNED_OVERFLOW calculation is the clever way of doing it - //but just to keep from making a mistake, lets assert that it matches the precise definition of unsigned overflow - static long passcount = 0; - assert(++passcount); - assert( - ((((u64)a+(u64)b+cpu->CPSR.bits.C)>>32)&1) - == (UNSIGNED_OVERFLOW(b, (u32) cpu->CPSR.bits.C, tmp) | UNSIGNED_OVERFLOW(tmp, a, res)) - ); -#endif - cpu->CPSR.bits.C = UNSIGNED_OVERFLOW(b, (u32) cpu->CPSR.bits.C, tmp) | UNSIGNED_OVERFLOW(tmp, a, res); cpu->CPSR.bits.V = SIGNED_OVERFLOW(b, (u32) cpu->CPSR.bits.C, tmp) | SIGNED_OVERFLOW(tmp, a, res); +#endif return 1; } @@ -453,6 +480,17 @@ TEMPLATE static u32 FASTCALL OP_ADC_REG(const u32 i) TEMPLATE static u32 FASTCALL OP_SBC_REG(const u32 i) { +#if 0 + u32 Rd = cpu->R[REG_NUM(i, 0)]; + u32 Rm = cpu->R[REG_NUM(i, 3)]; + + cpu->R[REG_NUM(i, 0)] = Rd - Rm - !cpu->CPSR.bits.C; + + cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]); + cpu->CPSR.bits.Z = (cpu->R[REG_NUM(i, 0)] == 0); + + // TODO +#else u32 a = cpu->R[REG_NUM(i, 0)]; u32 b = cpu->R[REG_NUM(i, 3)]; u32 tmp = a - (!cpu->CPSR.bits.C); @@ -462,22 +500,12 @@ TEMPLATE static u32 FASTCALL OP_SBC_REG(const u32 i) cpu->CPSR.bits.N = BIT31(res); cpu->CPSR.bits.Z = res == 0; -#if 0 - //the below UNSIGNED_UNDERFLOW calculation is the clever way of doing it - //but just to keep from making a mistake, lets assert that it matches the precise definition of unsigned overflow - static long passcount = 0; - assert(++passcount); - assert( - ((((u64)a-(u64)b-(!cpu->CPSR.bits.C))>>32)&1) - == UNSIGNED_UNDERFLOW(a, b, res) - ); -#endif - //zero 31-dec-2008 - apply normatt's fixed logic from the arm SBC instruction //although it seemed a bit odd to me and to whomever wrote this for SBC not to work similar to ADC.. //but thats how it is. cpu->CPSR.bits.C = !UNSIGNED_UNDERFLOW(a, b, res); cpu->CPSR.bits.V = SIGNED_UNDERFLOW(a, b, res); +#endif return 1; } @@ -488,7 +516,7 @@ TEMPLATE static u32 FASTCALL OP_SBC_REG(const u32 i) TEMPLATE static u32 FASTCALL OP_ROR_REG(const u32 i) { - u32 v = cpu->R[REG_NUM(i, 3)]&0xFF; + u32 v = cpu->R[REG_NUM(i, 3)] & 0xFF; if(v == 0) { @@ -496,6 +524,7 @@ TEMPLATE static u32 FASTCALL OP_ROR_REG(const u32 i) cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0; return 2; } + v &= 0x1F; if(v == 0) { @@ -520,7 +549,7 @@ TEMPLATE static u32 FASTCALL OP_TST(const u32 i) { u32 tmp = cpu->R[REG_NUM(i, 0)] & cpu->R[REG_NUM(i, 3)]; cpu->CPSR.bits.N = BIT31(tmp); - cpu->CPSR.bits.Z = tmp == 0; + cpu->CPSR.bits.Z = (tmp == 0); return 1; } @@ -531,13 +560,14 @@ TEMPLATE static u32 FASTCALL OP_TST(const u32 i) TEMPLATE static u32 FASTCALL OP_NEG(const u32 i) { - u32 a = cpu->R[REG_NUM(i, 3)]; - cpu->R[REG_NUM(i, 0)] = -((signed int)a); + u32 Rm = cpu->R[REG_NUM(i, 3)]; + + cpu->R[REG_NUM(i, 0)] = (u32)((s32)0 - (s32)Rm); cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]); - cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0; - cpu->CPSR.bits.C = !UNSIGNED_UNDERFLOW((u32)0, a, cpu->R[REG_NUM(i, 0)]); - cpu->CPSR.bits.V = SIGNED_UNDERFLOW((u32)0, a, cpu->R[REG_NUM(i, 0)]); + cpu->CPSR.bits.Z = (cpu->R[REG_NUM(i, 0)] == 0); + cpu->CPSR.bits.C = !BorrowFrom(0, Rm); + cpu->CPSR.bits.V = OverflowFromSUB(cpu->R[REG_NUM(i, 0)], 0, Rm); return 1; } @@ -567,8 +597,9 @@ TEMPLATE static u32 FASTCALL OP_CMN(const u32 i) TEMPLATE static u32 FASTCALL OP_ORR(const u32 i) { cpu->R[REG_NUM(i, 0)] |= cpu->R[REG_NUM(i, 3)]; + cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]); - cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0; + cpu->CPSR.bits.Z = (cpu->R[REG_NUM(i, 0)] == 0); return 1; } @@ -580,8 +611,9 @@ TEMPLATE static u32 FASTCALL OP_ORR(const u32 i) TEMPLATE static u32 FASTCALL OP_BIC(const u32 i) { cpu->R[REG_NUM(i, 0)] &= (~cpu->R[REG_NUM(i, 3)]); + cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]); - cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0; + cpu->CPSR.bits.Z = (cpu->R[REG_NUM(i, 0)] == 0); return 1; } @@ -593,6 +625,7 @@ TEMPLATE static u32 FASTCALL OP_BIC(const u32 i) TEMPLATE static u32 FASTCALL OP_MVN(const u32 i) { cpu->R[REG_NUM(i, 0)] = (~cpu->R[REG_NUM(i, 3)]); + cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]); cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0; @@ -618,9 +651,19 @@ TEMPLATE static u32 FASTCALL OP_MVN(const u32 i) TEMPLATE static u32 FASTCALL OP_MUL_REG(const u32 i) { u32 v = cpu->R[REG_NUM(i, 3)]; + + // FIXME: + //------ Rd = (Rm * Rd)[31:0] + //------ u64 res = ((u64)cpu->R[REG_NUM(i, 0)] * (u64)v)); + //------ cpu->R[REG_NUM(i, 0)] = (u32)(res & 0xFFFFFFFF); + //------ + cpu->R[REG_NUM(i, 0)] *= v; cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]); cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0; + //The MUL instruction is defined to leave the C flag unchanged in ARMv5 and above. + //In earlier versions of the architecture, the value of the C flag was UNPREDICTABLE + //after a MUL instruction. if (PROCNUM == 1) // ARM4T 1S + mI, m = 3 return 4; @@ -643,7 +686,7 @@ TEMPLATE static u32 FASTCALL OP_STRB_IMM_OFF(const u32 i) TEMPLATE static u32 FASTCALL OP_LDRB_IMM_OFF(const u32 i) { u32 adr = cpu->R[REG_NUM(i, 3)] + ((i>>6)&0x1F); - cpu->R[REG_NUM(i, 0)] = READ8(cpu->mem_if->data, adr); + cpu->R[REG_NUM(i, 0)] = (u32)READ8(cpu->mem_if->data, adr); return MMU_aluMemAccessCycles(3, adr); } @@ -652,7 +695,7 @@ TEMPLATE static u32 FASTCALL OP_LDRB_IMM_OFF(const u32 i) TEMPLATE static u32 FASTCALL OP_STRB_REG_OFF(const u32 i) { u32 adr = cpu->R[REG_NUM(i, 3)] + cpu->R[REG_NUM(i, 6)]; - WRITE8(cpu->mem_if->data, adr, ((u8)cpu->R[REG_NUM(i, 0)])); + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_NUM(i, 0)]); return MMU_aluMemAccessCycles(2, adr); } @@ -672,7 +715,7 @@ TEMPLATE static u32 FASTCALL OP_LDRB_REG_OFF(const u32 i) TEMPLATE static u32 FASTCALL OP_LDRSB_REG_OFF(const u32 i) { u32 adr = cpu->R[REG_NUM(i, 3)] + cpu->R[REG_NUM(i, 6)]; - cpu->R[REG_NUM(i, 0)] = (s32)((s8)READ8(cpu->mem_if->data, adr)); + cpu->R[REG_NUM(i, 0)] = (u32)((s8)READ8(cpu->mem_if->data, adr)); return MMU_aluMemAccessCycles(3, adr); } @@ -692,7 +735,7 @@ TEMPLATE static u32 FASTCALL OP_STRH_IMM_OFF(const u32 i) TEMPLATE static u32 FASTCALL OP_LDRH_IMM_OFF(const u32 i) { u32 adr = cpu->R[REG_NUM(i, 3)] + ((i>>5)&0x3E); - cpu->R[REG_NUM(i, 0)] = READ16(cpu->mem_if->data, adr); + cpu->R[REG_NUM(i, 0)] = (u32)READ16(cpu->mem_if->data, adr); return MMU_aluMemAccessCycles(3, adr); } @@ -721,7 +764,7 @@ TEMPLATE static u32 FASTCALL OP_LDRH_REG_OFF(const u32 i) TEMPLATE static u32 FASTCALL OP_LDRSH_REG_OFF(const u32 i) { u32 adr = cpu->R[REG_NUM(i, 3)] + cpu->R[REG_NUM(i, 6)]; - cpu->R[REG_NUM(i, 0)] = (s32)((s16)READ16(cpu->mem_if->data, adr)); + cpu->R[REG_NUM(i, 0)] = (u32)((s16)READ16(cpu->mem_if->data, adr)); return MMU_aluMemAccessCycles(3, adr); } @@ -741,11 +784,8 @@ TEMPLATE static u32 FASTCALL OP_STR_IMM_OFF(const u32 i) TEMPLATE static u32 FASTCALL OP_LDR_IMM_OFF(const u32 i) { u32 adr = cpu->R[REG_NUM(i, 3)] + ((i>>4)&0x7C); - u32 tempValue = READ32(cpu->mem_if->data, adr); - adr = (adr&3)*8; - tempValue = (tempValue>>adr) | (tempValue<<(32-adr)); - cpu->R[REG_NUM(i, 0)] = tempValue; - + cpu->R[REG_NUM(i, 0)] = READ32(cpu->mem_if->data, adr); + return MMU_aluMemAccessCycles(3, adr); } @@ -761,11 +801,7 @@ TEMPLATE static u32 FASTCALL OP_STR_REG_OFF(const u32 i) TEMPLATE static u32 FASTCALL OP_LDR_REG_OFF(const u32 i) { u32 adr = (cpu->R[REG_NUM(i, 3)] + cpu->R[REG_NUM(i, 6)]); - u32 tempValue = READ32(cpu->mem_if->data, adr); - - adr = (adr&3)*8; - tempValue = (tempValue>>adr) | (tempValue<<(32-adr)); - cpu->R[REG_NUM(i, 0)] = tempValue; + cpu->R[REG_NUM(i, 0)] = READ32(cpu->mem_if->data, adr); return MMU_aluMemAccessCycles(3, adr); } @@ -782,16 +818,16 @@ TEMPLATE static u32 FASTCALL OP_STR_SPREL(const u32 i) TEMPLATE static u32 FASTCALL OP_LDR_SPREL(const u32 i) { u32 adr = cpu->R[13] + ((i&0xFF)<<2); - cpu->R[REG_NUM(i, 8)] = READ32(cpu->mem_if->data, adr); + cpu->R[REG_NUM(i, 8)] = READ32(cpu->mem_if->data, adr); return MMU_aluMemAccessCycles(3, adr); } TEMPLATE static u32 FASTCALL OP_LDR_PCREL(const u32 i) { - u32 adr = (cpu->R[15]&0xFFFFFFFC) + ((cpu->instruction&0xFF)<<2); + u32 adr = (cpu->R[15]&0xFFFFFFFC) + ((i&0xFF)<<2); - cpu->R[REG_NUM(cpu->instruction, 8)] = READ32(cpu->mem_if->data, adr); + cpu->R[REG_NUM(i, 8)] = READ32(cpu->mem_if->data, adr); return MMU_aluMemAccessCycles(3, adr); } @@ -802,14 +838,14 @@ TEMPLATE static u32 FASTCALL OP_LDR_PCREL(const u32 i) TEMPLATE static u32 FASTCALL OP_ADJUST_P_SP(const u32 i) { - cpu->R[13] += ((cpu->instruction&0x7F)<<2); + cpu->R[13] += ((i&0x7F)<<2); return 1; } TEMPLATE static u32 FASTCALL OP_ADJUST_M_SP(const u32 i) { - cpu->R[13] -= ((cpu->instruction&0x7F)<<2); + cpu->R[13] -= ((i&0x7F)<<2); return 1; } @@ -823,7 +859,7 @@ TEMPLATE static u32 FASTCALL OP_PUSH(const u32 i) u32 adr = cpu->R[13] - 4; u32 c = 0, j; - for(j = 0; j<8; ++j) + for(j = 0; j<8; j++) if(BIT_N(i, 7-j)) { WRITE32(cpu->mem_if->data, adr, cpu->R[7-j]); @@ -844,7 +880,7 @@ TEMPLATE static u32 FASTCALL OP_PUSH_LR(const u32 i) c += MMU_memAccessCycles(adr); adr -= 4; - for(j = 0; j<8; ++j) + for(j = 0; j<8; j++) if(BIT_N(i, 7-j)) { WRITE32(cpu->mem_if->data, adr, cpu->R[7-j]); @@ -861,7 +897,7 @@ TEMPLATE static u32 FASTCALL OP_POP(const u32 i) u32 adr = cpu->R[13]; u32 c = 0, j; - for(j = 0; j<8; ++j) + for(j = 0; j<8; j++) if(BIT_N(i, j)) { cpu->R[j] = READ32(cpu->mem_if->data, adr); @@ -877,9 +913,9 @@ TEMPLATE static u32 FASTCALL OP_POP_PC(const u32 i) { u32 adr = cpu->R[13]; u32 c = 0, j; - u32 v; + u32 v = 0; - for(j = 0; j<8; ++j) + for(j = 0; j<8; j++) if(BIT_N(i, j)) { cpu->R[j] = READ32(cpu->mem_if->data, adr); @@ -909,10 +945,14 @@ TEMPLATE static u32 FASTCALL OP_STMIA_THUMB(const u32 i) u32 c = 0, j; u32 erList = 1; //Empty Register List + // ------ ARM_REF: + // ------ If is specified in : + // ------ * If is the lowest-numbered register specified in , the original value of is stored. + // ------ * Otherwise, the stored value of is UNPREDICTABLE. if (BIT_N(i, REG_NUM(i, 8))) printf("STMIA with Rb in Rlist\n"); - for(j = 0; j<8; ++j) + for(j = 0; j<8; j++) { if(BIT_N(i, j)) { @@ -940,7 +980,7 @@ TEMPLATE static u32 FASTCALL OP_LDMIA_THUMB(const u32 i) //if (BIT_N(i, regIndex)) // printf("LDMIA with Rb in Rlist at %08X\n",cpu->instruct_adr); - for(j = 0; j<8; ++j) + for(j = 0; j<8; j++) { if(BIT_N(i, j)) { @@ -954,8 +994,10 @@ TEMPLATE static u32 FASTCALL OP_LDMIA_THUMB(const u32 i) if (erList) printf("LDMIA with Empty Rlist\n"); - // Only over-write if not on the read list - if(!BIT_N(i, regIndex)) + // 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 (!BIT_N(i, regIndex)) cpu->R[regIndex] = adr; return MMU_aluMemCycles(3, c); @@ -967,6 +1009,8 @@ TEMPLATE static u32 FASTCALL OP_LDMIA_THUMB(const u32 i) TEMPLATE static u32 FASTCALL OP_BKPT_THUMB(const u32 i) { + // TODO + printf("THUMB%c: Unimplemented opcode BKPT\n", PROCNUM?'7':'9'); return 1; } @@ -976,7 +1020,7 @@ TEMPLATE static u32 FASTCALL OP_BKPT_THUMB(const u32 i) TEMPLATE static u32 FASTCALL OP_SWI_THUMB(const u32 i) { - u32 swinum = cpu->instruction & 0xFF; + u32 swinum = i & 0xFF; //ideas-style debug prints (execute this SWI with the null terminated string address in R0) if(swinum==0xFC) { @@ -1026,7 +1070,7 @@ TEMPLATE static u32 FASTCALL OP_B_COND(const u32 i) if(!TEST_COND((i>>8)&0xF, 0, cpu->CPSR)) return 1; - cpu->R[15] += ((s32)((s8)(i&0xFF)))<<1; + cpu->R[15] += (u32)((s8)(i&0xFF))<<1; cpu->next_instruction = cpu->R[15]; return 3; } @@ -1064,7 +1108,7 @@ TEMPLATE static u32 FASTCALL OP_BL_10(const u32 i) return 1; } -TEMPLATE static u32 FASTCALL OP_BL_THUMB(const u32 i) +TEMPLATE static u32 FASTCALL OP_BL_11(const u32 i) { cpu->R[15] = (cpu->R[14] + ((i&0x7FF)<<1)); cpu->R[14] = cpu->next_instruction | 1; @@ -1076,7 +1120,9 @@ TEMPLATE static u32 FASTCALL OP_BX_THUMB(const u32 i) { // When using PC as operand with BX opcode, switch to ARM state and jump to (instruct_adr+4) // Reference: http://nocash.emubase.de/gbatek.htm#thumb5hiregisteroperationsbranchexchange - if (REG_POS(cpu->instruction, 3) == 15) + +#if 0 + if (REG_POS(i, 3) == 15) { cpu->CPSR.bits.T = 0; cpu->R[15] &= 0xFFFFFFFC; @@ -1084,23 +1130,40 @@ TEMPLATE static u32 FASTCALL OP_BX_THUMB(const u32 i) } else { - u32 Rm = cpu->R[REG_POS(cpu->instruction, 3)]; + u32 Rm = cpu->R[REG_POS(i, 3)]; cpu->CPSR.bits.T = BIT0(Rm); cpu->R[15] = (Rm & 0xFFFFFFFE); cpu->next_instruction = cpu->R[15]; } - +#else + u32 Rm = cpu->R[REG_POS(i, 3)]; + //----- ARM_REF: + //----- Register 15 can be specified for . If this is done, R15 is read as normal for Thumb code, + //----- that is, it is the address of the BX instruction itself plus 4. If the BX instruction is at a + //----- word-aligned address, this results in a branch to the next word, executing in ARM state. + //----- However, if the BX instruction is not at a word-aligned address, this means that the results of + //----- the instruction are UNPREDICTABLE (because the value read for R15 has bits[1:0]==0b10). + if (Rm == 15) + { + printf("THUMB%c: BX using PC as operand\n", PROCNUM?'7':'9'); + //emu_halt(); + } + cpu->CPSR.bits.T = BIT0(Rm); + cpu->R[15] = (Rm & (0xFFFFFFFC|(1<CPSR.bits.T))); + cpu->next_instruction = cpu->R[15]; +#endif return 3; } TEMPLATE static u32 FASTCALL OP_BLX_THUMB(const u32 i) { - u32 Rm = cpu->R[REG_POS(cpu->instruction, 3)]; + u32 Rm = cpu->R[REG_POS(i, 3)]; cpu->CPSR.bits.T = BIT0(Rm); cpu->R[14] = cpu->next_instruction | 1; - cpu->R[15] = (Rm & 0xFFFFFFFE); + //cpu->R[15] = (Rm & (0xFFFFFFFC|(1<CPSR.bits.T))); + cpu->R[15] = (Rm & (0xFFFFFFFC|(1<CPSR.bits.T))); cpu->next_instruction = cpu->R[15]; return 4; diff --git a/desmume/src/thumb_tabdef.inc b/desmume/src/thumb_tabdef.inc index bf1e20d19..d491ee423 100644 --- a/desmume/src/thumb_tabdef.inc +++ b/desmume/src/thumb_tabdef.inc @@ -1072,36 +1072,36 @@ TABDECL( OP_BL_10), //11 1101 1101 TABDECL( OP_BL_10), //11 1101 1110 TABDECL( OP_BL_10), //11 1101 1111 -TABDECL( OP_BL_THUMB), //11 1110 0000 -TABDECL( OP_BL_THUMB), //11 1110 0001 -TABDECL( OP_BL_THUMB), //11 1110 0010 -TABDECL( OP_BL_THUMB), //11 1110 0011 -TABDECL( OP_BL_THUMB), //11 1110 0100 -TABDECL( OP_BL_THUMB), //11 1110 0101 -TABDECL( OP_BL_THUMB), //11 1110 0110 -TABDECL( OP_BL_THUMB), //11 1110 0111 -TABDECL( OP_BL_THUMB), //11 1110 1000 -TABDECL( OP_BL_THUMB), //11 1110 1001 -TABDECL( OP_BL_THUMB), //11 1110 1010 -TABDECL( OP_BL_THUMB), //11 1110 1011 -TABDECL( OP_BL_THUMB), //11 1110 1100 -TABDECL( OP_BL_THUMB), //11 1110 1101 -TABDECL( OP_BL_THUMB), //11 1110 1110 -TABDECL( OP_BL_THUMB), //11 1110 1111 +TABDECL( OP_BL_11), //11 1110 0000 +TABDECL( OP_BL_11), //11 1110 0001 +TABDECL( OP_BL_11), //11 1110 0010 +TABDECL( OP_BL_11), //11 1110 0011 +TABDECL( OP_BL_11), //11 1110 0100 +TABDECL( OP_BL_11), //11 1110 0101 +TABDECL( OP_BL_11), //11 1110 0110 +TABDECL( OP_BL_11), //11 1110 0111 +TABDECL( OP_BL_11), //11 1110 1000 +TABDECL( OP_BL_11), //11 1110 1001 +TABDECL( OP_BL_11), //11 1110 1010 +TABDECL( OP_BL_11), //11 1110 1011 +TABDECL( OP_BL_11), //11 1110 1100 +TABDECL( OP_BL_11), //11 1110 1101 +TABDECL( OP_BL_11), //11 1110 1110 +TABDECL( OP_BL_11), //11 1110 1111 -TABDECL( OP_BL_THUMB), //11 1111 0000 -TABDECL( OP_BL_THUMB), //11 1111 0001 -TABDECL( OP_BL_THUMB), //11 1111 0010 -TABDECL( OP_BL_THUMB), //11 1111 0011 -TABDECL( OP_BL_THUMB), //11 1111 0100 -TABDECL( OP_BL_THUMB), //11 1111 0101 -TABDECL( OP_BL_THUMB), //11 1111 0110 -TABDECL( OP_BL_THUMB), //11 1111 0111 -TABDECL( OP_BL_THUMB), //11 1111 1000 -TABDECL( OP_BL_THUMB), //11 1111 1001 -TABDECL( OP_BL_THUMB), //11 1111 1010 -TABDECL( OP_BL_THUMB), //11 1111 1011 -TABDECL( OP_BL_THUMB), //11 1111 1100 -TABDECL( OP_BL_THUMB), //11 1111 1101 -TABDECL( OP_BL_THUMB), //11 1111 1110 -TABDECL( OP_BL_THUMB), //11 1111 1111 +TABDECL( OP_BL_11), //11 1111 0000 +TABDECL( OP_BL_11), //11 1111 0001 +TABDECL( OP_BL_11), //11 1111 0010 +TABDECL( OP_BL_11), //11 1111 0011 +TABDECL( OP_BL_11), //11 1111 0100 +TABDECL( OP_BL_11), //11 1111 0101 +TABDECL( OP_BL_11), //11 1111 0110 +TABDECL( OP_BL_11), //11 1111 0111 +TABDECL( OP_BL_11), //11 1111 1000 +TABDECL( OP_BL_11), //11 1111 1001 +TABDECL( OP_BL_11), //11 1111 1010 +TABDECL( OP_BL_11), //11 1111 1011 +TABDECL( OP_BL_11), //11 1111 1100 +TABDECL( OP_BL_11), //11 1111 1101 +TABDECL( OP_BL_11), //11 1111 1110 +TABDECL( OP_BL_11), //11 1111 1111