From 53b38c363fb820f97c4f44b8601540970f9017cf Mon Sep 17 00:00:00 2001 From: Jaklyy <102590697+Jaklyy@users.noreply.github.com> Date: Thu, 10 Oct 2024 03:32:53 -0400 Subject: [PATCH 1/4] ok no it didn't lie to me --- src/ARMInterpreter.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/ARMInterpreter.cpp b/src/ARMInterpreter.cpp index 72d1e189..1f95c1f8 100644 --- a/src/ARMInterpreter.cpp +++ b/src/ARMInterpreter.cpp @@ -136,7 +136,8 @@ void A_MSR_IMM(ARM* cpu) } } - cpu->AddCycles_C(); + if ((cpu->Num != 1) && (cpu->CurInstr & (0x7<<16))) cpu->AddCycles_CI(2); + else cpu->AddCycles_C(); } void A_MSR_REG(ARM* cpu) @@ -196,7 +197,8 @@ void A_MSR_REG(ARM* cpu) } } - cpu->AddCycles_C(); + if ((cpu->Num != 1) && (cpu->CurInstr & (0x7<<16))) cpu->AddCycles_CI(2); + else cpu->AddCycles_C(); } void A_MRS(ARM* cpu) From 3870216fd06f634c2b0864feea5c4353ca94fd0b Mon Sep 17 00:00:00 2001 From: Jaklyy <102590697+Jaklyy@users.noreply.github.com> Date: Thu, 10 Oct 2024 03:53:51 -0400 Subject: [PATCH 2/4] correction: --- src/ARMInterpreter.cpp | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/src/ARMInterpreter.cpp b/src/ARMInterpreter.cpp index 1f95c1f8..2b14de73 100644 --- a/src/ARMInterpreter.cpp +++ b/src/ARMInterpreter.cpp @@ -98,7 +98,8 @@ void A_MSR_IMM(ARM* cpu) case 0x1A: case 0x1B: psr = &cpu->R_UND[2]; break; default: - cpu->AddCycles_C(); + if (cpu->Num != 1) cpu->AddCycles_C(); // arm 7 + else cpu->AddCycles_CI(2); // arm 9 return; } } @@ -135,8 +136,16 @@ void A_MSR_IMM(ARM* cpu) cpu->CPSR &= ~0x20; // keep it from crashing the emulator at least } } - - if ((cpu->Num != 1) && (cpu->CurInstr & (0x7<<16))) cpu->AddCycles_CI(2); + + if (cpu->Num != 1) + { + if (cpu->CurInstr & (1<<22)) + { + cpu->AddCycles_CI(2); // spsr_fsxc + } + else if (cpu->CurInstr & (0x7<<16)) cpu->AddCycles_CI(2); // cpsr_sxc + else cpu->AddCycles_C(); + } else cpu->AddCycles_C(); } @@ -159,7 +168,8 @@ void A_MSR_REG(ARM* cpu) case 0x1A: case 0x1B: psr = &cpu->R_UND[2]; break; default: - cpu->AddCycles_C(); + if (cpu->Num != 1) cpu->AddCycles_C(); // arm 7 + else cpu->AddCycles_CI(2); // arm 9 return; } } @@ -196,8 +206,16 @@ void A_MSR_REG(ARM* cpu) cpu->CPSR &= ~0x20; // keep it from crashing the emulator at least } } - - if ((cpu->Num != 1) && (cpu->CurInstr & (0x7<<16))) cpu->AddCycles_CI(2); + + if (cpu->Num != 1) + { + if (cpu->CurInstr & (1<<22)) + { + cpu->AddCycles_CI(2); // spsr_fsxc + } + else if (cpu->CurInstr & (0x7<<16)) cpu->AddCycles_CI(2); // cpsr_sxc + else cpu->AddCycles_C(); + } else cpu->AddCycles_C(); } From 93dce82b078a1df48fb2d74a6091300f5e807b37 Mon Sep 17 00:00:00 2001 From: Jaklyy <102590697+Jaklyy@users.noreply.github.com> Date: Thu, 10 Oct 2024 10:48:17 -0400 Subject: [PATCH 3/4] implement cmp with "rd == 15" on arm9 cmp and friends with bits 12-15 set to 1 borrow characteristics from their legacy 26 bit p variants thumb version does nothing of note --- src/ARMInterpreter.cpp | 4 +- src/ARMInterpreter_ALU.cpp | 82 ++++++++++++++++++++++++-------------- 2 files changed, 54 insertions(+), 32 deletions(-) diff --git a/src/ARMInterpreter.cpp b/src/ARMInterpreter.cpp index 2b14de73..a04b6140 100644 --- a/src/ARMInterpreter.cpp +++ b/src/ARMInterpreter.cpp @@ -141,7 +141,7 @@ void A_MSR_IMM(ARM* cpu) { if (cpu->CurInstr & (1<<22)) { - cpu->AddCycles_CI(2); // spsr_fsxc + cpu->AddCycles_CI(2); // spsr } else if (cpu->CurInstr & (0x7<<16)) cpu->AddCycles_CI(2); // cpsr_sxc else cpu->AddCycles_C(); @@ -211,7 +211,7 @@ void A_MSR_REG(ARM* cpu) { if (cpu->CurInstr & (1<<22)) { - cpu->AddCycles_CI(2); // spsr_fsxc + cpu->AddCycles_CI(2); // spsr } else if (cpu->CurInstr & (0x7<<16)) cpu->AddCycles_CI(2); // cpsr_sxc else cpu->AddCycles_C(); diff --git a/src/ARMInterpreter_ALU.cpp b/src/ARMInterpreter_ALU.cpp index 9305fc42..83fc1944 100644 --- a/src/ARMInterpreter_ALU.cpp +++ b/src/ARMInterpreter_ALU.cpp @@ -581,12 +581,12 @@ A_IMPLEMENT_ALU_OP(RSC,) #define A_TST(c) \ u32 a = cpu->R[(cpu->CurInstr>>16) & 0xF]; \ u32 res = a & b; \ - cpu->SetNZ(res & 0x80000000, \ - !res); \ - if (((cpu->CurInstr>>12) & 0xF) == 15) [[unlikely]] /* yes this instruction has a secret rd for some reason */ \ + if (((cpu->CurInstr>>12) & 0xF) == 15) [[unlikely]] /* this seems to trigger alu rd==15 behavior for arm7 and legacy instruction behavior for arm9 */ \ { \ if (cpu->Num == 1) \ { \ + cpu->SetNZ(res & 0x80000000, \ + !res); \ u32 oldpsr = cpu->CPSR; \ cpu->RestoreCPSR(); /* ARM7TDMI restores cpsr and does ___not___ flush the pipeline. */ \ if (cpu->CPSR & 0x20) \ @@ -595,7 +595,12 @@ A_IMPLEMENT_ALU_OP(RSC,) cpu->CPSR &= ~0x20; /* keep it from crashing the emulator at least */ \ } \ } \ - else Platform::Log(Platform::LogLevel::Warn, "UNIMPLEMENTED: TST w/ rd == 15 on ARM9\n"); \ + else cpu->JumpTo(res & ~1, true); /* TSTP dna, doesn't update flags */ \ + } \ + else \ + { \ + cpu->SetNZ(res & 0x80000000, \ + !res); \ } \ if (c) cpu->AddCycles_CI(c); else cpu->AddCycles_C(); @@ -605,12 +610,12 @@ A_IMPLEMENT_ALU_TEST(TST,_S) #define A_TEQ(c) \ u32 a = cpu->R[(cpu->CurInstr>>16) & 0xF]; \ u32 res = a ^ b; \ - cpu->SetNZ(res & 0x80000000, \ - !res); \ - if (((cpu->CurInstr>>12) & 0xF) == 15) [[unlikely]] /* yes this instruction has a secret rd for some reason */ \ + if (((cpu->CurInstr>>12) & 0xF) == 15) [[unlikely]] /* this seems to trigger alu rd==15 behavior for arm7 and legacy instruction behavior for arm9 */ \ { \ if (cpu->Num == 1) \ { \ + cpu->SetNZ(res & 0x80000000, \ + !res); \ u32 oldpsr = cpu->CPSR; \ cpu->RestoreCPSR(); /* ARM7TDMI restores cpsr and does ___not___ flush the pipeline. */ \ if (cpu->CPSR & 0x20) \ @@ -619,7 +624,12 @@ A_IMPLEMENT_ALU_TEST(TST,_S) cpu->CPSR &= ~0x20; /* keep it from crashing the emulator at least */ \ } \ } \ - else Platform::Log(Platform::LogLevel::Warn, "UNIMPLEMENTED: TEQ w/ rd == 15 on ARM9\n"); \ + else cpu->JumpTo(res & ~1, true); /* TEQP dna, doesn't update flags */ \ + } \ + else \ + { \ + cpu->SetNZ(res & 0x80000000, \ + !res); \ } \ if (c) cpu->AddCycles_CI(c); else cpu->AddCycles_C(); @@ -629,14 +639,14 @@ A_IMPLEMENT_ALU_TEST(TEQ,_S) #define A_CMP(c) \ u32 a = cpu->R[(cpu->CurInstr>>16) & 0xF]; \ u32 res = a - b; \ - cpu->SetNZCV(res & 0x80000000, \ - !res, \ - CarrySub(a, b), \ - OverflowSub(a, b)); \ - if (((cpu->CurInstr>>12) & 0xF) == 15) [[unlikely]] /* yes this instruction has a secret rd for some reason */ \ + if (((cpu->CurInstr>>12) & 0xF) == 15) [[unlikely]] /* this seems to trigger alu rd==15 behavior for arm7 and legacy instruction behavior for arm9 */ \ { \ if (cpu->Num == 1) \ { \ + cpu->SetNZCV(res & 0x80000000, \ + !res, \ + CarrySub(a, b), \ + OverflowSub(a, b)); \ u32 oldpsr = cpu->CPSR; \ cpu->RestoreCPSR(); /* ARM7TDMI restores cpsr and does ___not___ flush the pipeline. */ \ if (cpu->CPSR & 0x20) \ @@ -645,7 +655,14 @@ A_IMPLEMENT_ALU_TEST(TEQ,_S) cpu->CPSR &= ~0x20; /* keep it from crashing the emulator at least */ \ } \ } \ - else Platform::Log(Platform::LogLevel::Warn, "UNIMPLEMENTED: CMP w/ rd == 15 on ARM9\n"); \ + else cpu->JumpTo(res & ~1, true); /* CMPP dna, doesn't update flags */ \ + } \ + else \ + { \ + cpu->SetNZCV(res & 0x80000000, \ + !res, \ + CarrySub(a, b), \ + OverflowSub(a, b)); \ } \ if (c) cpu->AddCycles_CI(c); else cpu->AddCycles_C(); @@ -655,14 +672,14 @@ A_IMPLEMENT_ALU_TEST(CMP,) #define A_CMN(c) \ u32 a = cpu->R[(cpu->CurInstr>>16) & 0xF]; \ u32 res = a + b; \ - cpu->SetNZCV(res & 0x80000000, \ - !res, \ - CarryAdd(a, b), \ - OverflowAdd(a, b)); \ - if (((cpu->CurInstr>>12) & 0xF) == 15) [[unlikely]] /* yes this instruction has a secret rd for some reason */ \ + if (((cpu->CurInstr>>12) & 0xF) == 15) [[unlikely]] /* this seems to trigger alu rd==15 behavior for arm7 and legacy instruction behavior for arm9 */ \ { \ if (cpu->Num == 1) \ { \ + cpu->SetNZCV(res & 0x80000000, \ + !res, \ + CarryAdd(a, b), \ + OverflowAdd(a, b)); \ u32 oldpsr = cpu->CPSR; \ cpu->RestoreCPSR(); /* ARM7TDMI restores cpsr and does ___not___ flush the pipeline. */ \ if (cpu->CPSR & 0x20) \ @@ -671,7 +688,14 @@ A_IMPLEMENT_ALU_TEST(CMP,) cpu->CPSR &= ~0x20; /* keep it from crashing the emulator at least */ \ } \ } \ - else Platform::Log(Platform::LogLevel::Warn, "UNIMPLEMENTED: CMN w/ rd == 15 on ARM9\n"); \ + else cpu->JumpTo(res & ~1, true); /* CMNP dna, doesn't update flags */ \ + } \ + else \ + { \ + cpu->SetNZCV(res & 0x80000000, \ + !res, \ + CarryAdd(a, b), \ + OverflowAdd(a, b)); \ } \ if (c) cpu->AddCycles_CI(c); else cpu->AddCycles_C(); @@ -1625,20 +1649,18 @@ void T_CMP_HIREG(ARM* cpu) !res, CarrySub(a, b), OverflowSub(a, b)); - if (rd == 15) [[unlikely]] + + if ((cpu->Num == 1) && (rd == 15)) { - if (cpu->Num == 1) + u32 oldpsr = cpu->CPSR; + cpu->RestoreCPSR(); // ARM7TDMI restores cpsr and does ___not___ flush the pipeline. + if (!(cpu->CPSR & 0x20)) { - u32 oldpsr = cpu->CPSR; - cpu->RestoreCPSR(); // ARM7TDMI restores cpsr and does ___not___ flush the pipeline. - if (!(cpu->CPSR & 0x20)) - { - Platform::Log(Platform::LogLevel::Warn, "UNIMPLEMENTED: MSR REG T bit change on ARM7\n"); - cpu->CPSR |= 0x20; // keep it from crashing the emulator at least - } + Platform::Log(Platform::LogLevel::Warn, "UNIMPLEMENTED: MSR REG T bit change on ARM7\n"); + cpu->CPSR |= 0x20; // keep it from crashing the emulator at least } - else Platform::Log(Platform::LogLevel::Warn, "UNIMPLEMENTED: CMP HIREG w/ rd == 15 on ARM9\n"); } + cpu->AddCycles_C(); } From 787d0c9afcd963380eb364b72ac71e7012d85689 Mon Sep 17 00:00:00 2001 From: Jaklyy <102590697+Jaklyy@users.noreply.github.com> Date: Thu, 10 Oct 2024 11:09:07 -0400 Subject: [PATCH 4/4] mrc r15 updates flags also my prior implementation made mrc w/ r15 raise an exception by accident oops! --- src/ARMInterpreter.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/ARMInterpreter.cpp b/src/ARMInterpreter.cpp index a04b6140..82dc6876 100644 --- a/src/ARMInterpreter.cpp +++ b/src/ARMInterpreter.cpp @@ -297,11 +297,17 @@ void A_MRC(ARM* cpu) u32 cpinfo = (cpu->CurInstr >> 5) & 0x7; u32 rd = (cpu->CurInstr>>12) & 0xF; - if (cpu->Num==0 && cp==15 && rd!=15) + if (cpu->Num==0 && cp==15) { - cpu->R[rd] = ((ARMv5*)cpu)->CP15Read((cn<<8)|(cm<<4)|cpinfo); + if (rd != 15) cpu->R[rd] = ((ARMv5*)cpu)->CP15Read((cn<<8)|(cm<<4)|cpinfo); + else + { + // r15 updates the top 4 bits of the cpsr, done to "allow for conditional branching based on coprocessor status" + u32 flags = ((ARMv5*)cpu)->CP15Read((cn<<8)|(cm<<4)|cpinfo) & 0xF0000000; + cpu->CPSR = (cpu->CPSR & ~0xF0000000) | flags; + } } - else if (cpu->Num==1 && cp==14 && rd!=15) + else if (cpu->Num==1 && cp==14) { Log(LogLevel::Debug, "MRC p14,%d,%d,%d on ARM7\n", cn, cm, cpinfo); }