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;
This commit is contained in:
parent
47bb26f093
commit
3eb9de4614
|
@ -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;
|
||||
|
|
|
@ -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<ARMCPU_ARM7>(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<ARMCPU_ARM9>(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<ARMCPU_ARM9>(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<ARMCPU_ARM9>(0xFFFF0274, 0xE92D500F);
|
||||
_MMU_write32<ARMCPU_ARM9>(0xFFFF0278, 0xEE190F11);
|
||||
_MMU_write32<ARMCPU_ARM9>(0xFFFF027C, 0xE1A00620);
|
||||
_MMU_write32<ARMCPU_ARM9>(0xFFFF0280, 0xE1A00600);
|
||||
_MMU_write32<ARMCPU_ARM9>(0xFFFF0284, 0xE2800C40);
|
||||
_MMU_write32<ARMCPU_ARM9>(0xFFFF0288, 0xE28FE000);
|
||||
_MMU_write32<ARMCPU_ARM9>(0xFFFF028C, 0xE510F004);
|
||||
_MMU_write32<ARMCPU_ARM9>(0xFFFF0290, 0xE8BD500F);
|
||||
_MMU_write32<ARMCPU_ARM9>(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<ARMCPU_ARM9>(0x02FFFE70, 0x5f617267);
|
||||
_MMU_write32<ARMCPU_ARM9>(0x02FFFE74, kCommandline); //(commandline starts here)
|
||||
_MMU_write32<ARMCPU_ARM9>(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
|
||||
|
|
|
@ -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<PROCNUM,MMU_AT_CODE>(curInstruction&0xFFFFFFFC);
|
||||
curInstruction &= 0x0FFFFFFC;
|
||||
armcpu->instruction = _MMU_read32<PROCNUM, MMU_AT_CODE>(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<PROCNUM,32>(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<PROCNUM, MMU_AT_CODE>(curInstruction&0xFFFFFFFE);
|
||||
curInstruction &= 0x0FFFFFFE;
|
||||
armcpu->instruction = _MMU_read16<PROCNUM, MMU_AT_CODE>(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) {
|
||||
|
|
|
@ -45,6 +45,31 @@ inline T SIGNED_OVERFLOW(T a,T b,T c) { return BIT31(((a)&(b)&(~c)) | ((~a)&(~(b
|
|||
template<typename T>
|
||||
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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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<PROCNUM,8,MMU_AD_READ>(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<PROCNUM,8,MMU_AD_WRITE>(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<PROCNUM,8,MMU_AD_READ>(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<PROCNUM,16,MMU_AD_READ>(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<PROCNUM,16,MMU_AD_READ>(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<PROCNUM,32,MMU_AD_READ>(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<PROCNUM,32,MMU_AD_READ>(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<PROCNUM,32,MMU_AD_READ>(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<PROCNUM,32,MMU_AD_READ>(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<PROCNUM,32,MMU_AD_WRITE>(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 <Rn> is specified in <registers>:
|
||||
// ------ * If <Rn> is the lowest-numbered register specified in <registers>, the original value of <Rn> is stored.
|
||||
// ------ * Otherwise, the stored value of <Rn> 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 <Rn> is specified in <registers>, the final value of <Rn> is the loaded value
|
||||
// (not the written-back value).
|
||||
if (!BIT_N(i, regIndex))
|
||||
cpu->R[regIndex] = adr;
|
||||
|
||||
return MMU_aluMemCycles<PROCNUM>(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 <Rm>. 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<<cpu->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<<cpu->CPSR.bits.T)));
|
||||
cpu->R[15] = (Rm & (0xFFFFFFFC|(1<<cpu->CPSR.bits.T)));
|
||||
cpu->next_instruction = cpu->R[15];
|
||||
|
||||
return 4;
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue