diff options
Diffstat (limited to 'src/ARMJIT_x64/ARMJIT_Compiler.cpp')
| -rw-r--r-- | src/ARMJIT_x64/ARMJIT_Compiler.cpp | 185 | 
1 files changed, 61 insertions, 124 deletions
| diff --git a/src/ARMJIT_x64/ARMJIT_Compiler.cpp b/src/ARMJIT_x64/ARMJIT_Compiler.cpp index 4fe0c70..6799a90 100644 --- a/src/ARMJIT_x64/ARMJIT_Compiler.cpp +++ b/src/ARMJIT_x64/ARMJIT_Compiler.cpp @@ -50,50 +50,6 @@ Compiler::Compiler()      ResetStart = GetWritableCodePtr();  } -void* Compiler::Gen_ChangeCPSRRoutine() -{ -    void* res = (void*)GetWritableCodePtr(); - -    MOV(32, R(RSCRATCH), R(RCPSR)); -    AND(32, R(RSCRATCH), Imm8(0x1F)); -    CMP(32, R(RSCRATCH), Imm8(0x11)); -    FixupBranch fiq = J_CC(CC_E); -    CMP(32, R(RSCRATCH), Imm8(0x12)); -    FixupBranch irq = J_CC(CC_E); -    CMP(32, R(RSCRATCH), Imm8(0x13)); -    FixupBranch svc = J_CC(CC_E); -    CMP(32, R(RSCRATCH), Imm8(0x17)); -    FixupBranch abt = J_CC(CC_E); -    CMP(32, R(RSCRATCH), Imm8(0x1B)); -    FixupBranch und = J_CC(CC_E); - -    SetJumpTarget(fiq); - -    SetJumpTarget(irq); - -    SetJumpTarget(svc); - -    SetJumpTarget(abt); - -    SetJumpTarget(und); - -    return res; -} - -DataRegion Compiler::ClassifyAddress(u32 addr) -{ -    if (Num == 0 && addr >= ((ARMv5*)CurCPU)->DTCMBase && addr < ((ARMv5*)CurCPU)->DTCMBase) -        return dataRegionDTCM; -    switch (addr & 0xFF000000) -    { -        case 0x02000000: return dataRegionMainRAM; -        case 0x03000000: return Num == 1 && (addr & 0xF00000) == 0x800000 ? dataRegionWRAM7 : dataRegionSWRAM; -        case 0x04000000: return dataRegionIO; -        case 0x06000000: return dataRegionVRAM; -    } -    return dataRegionGeneric; -} -  void Compiler::LoadCPSR()  {      assert(!CPSRDirty); @@ -123,6 +79,29 @@ void Compiler::SaveReg(int reg, X64Reg nativeReg)      MOV(32, MDisp(RCPU, offsetof(ARM, R[reg])), R(nativeReg));  } +// invalidates RSCRATCH and RSCRATCH3 +Gen::FixupBranch Compiler::CheckCondition(u32 cond) +{ +    if (cond >= 0x8) +    { +        static_assert(RSCRATCH3 == ECX); +        MOV(32, R(RSCRATCH3), R(RCPSR)); +        SHR(32, R(RSCRATCH3), Imm8(28)); +        MOV(32, R(RSCRATCH), Imm32(1)); +        SHL(32, R(RSCRATCH), R(RSCRATCH3)); +        TEST(32, R(RSCRATCH), Imm32(ARM::ConditionTable[cond])); + +        return J_CC(CC_Z); +    } +    else +    { +        // could have used a LUT, but then where would be the fun? +        TEST(32, R(RCPSR), Imm32(1 << (28 + ((~(cond >> 1) & 1) << 1 | (cond >> 2 & 1) ^ (cond >> 1 & 1))))); + +        return J_CC(cond & 1 ? CC_NZ : CC_Z); +    } +} +  CompiledBlock Compiler::CompileBlock(ARM* cpu, FetchedInstr instrs[], int instrsCount)  {      if (IsAlmostFull()) @@ -140,6 +119,8 @@ CompiledBlock Compiler::CompileBlock(ARM* cpu, FetchedInstr instrs[], int instrs      CodeRegion = cpu->CodeRegion;      CurCPU = cpu; +    bool mergedThumbBL = false; +      ABI_PushRegistersAndAdjustStack({ABI_ALL_CALLEE_SAVED & ABI_ALL_GPRS}, 8, 16);      MOV(64, R(RCPU), ImmPtr(cpu)); @@ -167,17 +148,10 @@ CompiledBlock Compiler::CompileBlock(ARM* cpu, FetchedInstr instrs[], int instrs                  MOV(32, MDisp(RCPU, offsetof(ARM, NextInstr[1])), Imm32(CurInstr.NextInstr[1]));              } -            if (comp == NULL || CurInstr.Info.Branches()) +            if (comp == NULL)                  SaveCPSR();          } - -        // run interpreter -        cpu->CodeCycles = CurInstr.CodeCycles; -        cpu->R[15] = R15; -        cpu->CurInstr = CurInstr.Instr; -        cpu->NextInstr[0] = CurInstr.NextInstr[0]; -        cpu->NextInstr[1] = CurInstr.NextInstr[1]; - +                  if (comp != NULL)              RegCache.Prepare(i);          else @@ -185,58 +159,44 @@ CompiledBlock Compiler::CompileBlock(ARM* cpu, FetchedInstr instrs[], int instrs          if (Thumb)          { -            u32 icode = (CurInstr.Instr >> 6) & 0x3FF; -            if (comp == NULL) +            if (i < instrsCount - 1 && CurInstr.Info.Kind == ARMInstrInfo::tk_BL_LONG_1 +                && instrs[i + 1].Info.Kind == ARMInstrInfo::tk_BL_LONG_2) +                mergedThumbBL = true; +            else              { -                MOV(64, R(ABI_PARAM1), R(RCPU)); +                u32 icode = (CurInstr.Instr >> 6) & 0x3FF; +                if (comp == NULL) +                { +                    MOV(64, R(ABI_PARAM1), R(RCPU)); -                ABI_CallFunction(ARMInterpreter::THUMBInstrTable[icode]); +                    ABI_CallFunction(ARMInterpreter::THUMBInstrTable[icode]); +                } +                else if (mergedThumbBL) +                    T_Comp_BL_Merged(instrs[i - 1]); +                else +                    (this->*comp)();              } -            else -                (this->*comp)(); - -            ARMInterpreter::THUMBInstrTable[icode](cpu);          }          else          {              u32 cond = CurInstr.Cond();              if (CurInstr.Info.Kind == ARMInstrInfo::ak_BLX_IMM)              { -                MOV(64, R(ABI_PARAM1), R(RCPU)); -                ABI_CallFunction(ARMInterpreter::A_BLX_IMM); - -                ARMInterpreter::A_BLX_IMM(cpu); +                if (comp) +                    (this->*comp)(); +                else +                { +                    MOV(64, R(ABI_PARAM1), R(RCPU)); +                    ABI_CallFunction(ARMInterpreter::A_BLX_IMM); +                }              }              else if (cond == 0xF) -            {                  Comp_AddCycles_C(); -                cpu->AddCycles_C(); -            }              else              {                  FixupBranch skipExecute;                  if (cond < 0xE) -                { -                    if (cond >= 0x8) -                    { -                        static_assert(RSCRATCH3 == ECX); -                        MOV(32, R(RSCRATCH3), R(RCPSR)); -                        SHR(32, R(RSCRATCH3), Imm8(28)); -                        MOV(32, R(RSCRATCH), Imm32(1)); -                        SHL(32, R(RSCRATCH), R(RSCRATCH3)); -                        TEST(32, R(RSCRATCH), Imm32(ARM::ConditionTable[cond])); - -                        skipExecute = J_CC(CC_Z); -                    } -                    else -                    { -                        // could have used a LUT, but then where would be the fun? -                        TEST(32, R(RCPSR), Imm32(1 << (28 + ((~(cond >> 1) & 1) << 1 | (cond >> 2 & 1) ^ (cond >> 1 & 1))))); - -                        skipExecute = J_CC(cond & 1 ? CC_NZ : CC_Z); -                    } - -                } +                    skipExecute = CheckCondition(cond);                  u32 icode = ((CurInstr.Instr >> 4) & 0xF) | ((CurInstr.Instr >> 16) & 0xFF0);                  if (comp == NULL) @@ -258,19 +218,9 @@ CompiledBlock Compiler::CompileBlock(ARM* cpu, FetchedInstr instrs[], int instrs                      SetJumpTarget(skipFailed);                  } - -                if (cpu->CheckCondition(cond)) -                    ARMInterpreter::ARMInstrTable[icode](cpu); -                else -                    cpu->AddCycles_C();              }          } -        /* -            we don't need to collect the interpreted cycles, -            since cpu->Cycles is taken into account by the dispatcher. -        */ -          if (comp == NULL && i != instrsCount - 1)              LoadCPSR();      } @@ -367,7 +317,7 @@ CompileFunc Compiler::GetCompFunc(int kind)          // LDM/STM          NULL, NULL,          // Branch -        NULL, NULL, NULL, NULL, NULL, +        A_Comp_BranchImm, A_Comp_BranchImm, A_Comp_BranchImm, A_Comp_BranchXchangeReg, A_Comp_BranchXchangeReg,          // system stuff          NULL, NULL, NULL, NULL, NULL, NULL, NULL,      }; @@ -389,7 +339,7 @@ CompileFunc Compiler::GetCompFunc(int kind)          // pc/sp relative          T_Comp_RelAddr, T_Comp_RelAddr, T_Comp_AddSP,          // LDR pcrel -        NULL, +        T_Comp_LoadPCRel,          // LDR/STR reg offset          T_Comp_MemReg, T_Comp_MemReg, T_Comp_MemReg, T_Comp_MemReg,          // LDR/STR sign extended, half @@ -399,25 +349,27 @@ CompileFunc Compiler::GetCompFunc(int kind)          // LDR/STR half imm offset          T_Comp_MemImmHalf, T_Comp_MemImmHalf,          // LDR/STR sp rel -        NULL, NULL, +        T_Comp_MemSPRel, T_Comp_MemSPRel,          // PUSH/POP -        NULL, NULL,  +        T_Comp_PUSH_POP, T_Comp_PUSH_POP,           // LDMIA, STMIA -        NULL, NULL,  -        NULL, NULL, -        NULL, NULL, NULL, NULL, NULL, NULL +        T_Comp_LDMIA_STMIA, T_Comp_LDMIA_STMIA,  +        // Branch +        T_Comp_BCOND, T_Comp_BranchXchangeReg, T_Comp_BranchXchangeReg, T_Comp_B, T_Comp_BL_LONG_1, T_Comp_BL_LONG_2,  +        // Unk, SVC +        NULL, NULL      };      return Thumb ? T_Comp[kind] : A_Comp[kind];  } -void Compiler::Comp_AddCycles_C() +void Compiler::Comp_AddCycles_C(bool forceNonConstant)  {      s32 cycles = Num ?          NDS::ARM7MemTimings[CurInstr.CodeCycles][Thumb ? 1 : 3]          : ((R15 & 0x2) ? 0 : CurInstr.CodeCycles); -    if (CurInstr.Cond() < 0xE) +    if ((!Thumb && CurInstr.Cond() < 0xE) || forceNonConstant)          ADD(32, MDisp(RCPU, offsetof(ARM, Cycles)), Imm8(cycles));      else          ConstantCycles += cycles; @@ -429,25 +381,10 @@ void Compiler::Comp_AddCycles_CI(u32 i)          NDS::ARM7MemTimings[CurInstr.CodeCycles][Thumb ? 0 : 2]          : ((R15 & 0x2) ? 0 : CurInstr.CodeCycles)) + i; -    if (CurInstr.Cond() < 0xE) +    if (!Thumb && CurInstr.Cond() < 0xE)          ADD(32, MDisp(RCPU, offsetof(ARM, Cycles)), Imm8(cycles));      else          ConstantCycles += cycles;  } -void Compiler::Comp_JumpTo(Gen::X64Reg addr, bool restoreCPSR) -{ -    // potentieller Bug: falls ein Register das noch gecacht ist, beim Modeswitch gespeichert -    // wird der alte Wert gespeichert -    SaveCPSR(); - -    MOV(64, R(ABI_PARAM1), R(RCPU)); -    MOV(32, R(ABI_PARAM2), R(addr)); -    MOV(32, R(ABI_PARAM3), Imm32(restoreCPSR)); -    if (Num == 0) -        CALL((void*)&ARMv5::JumpTo); -    else -        CALL((void*)&ARMv4::JumpTo); -} -  }
\ No newline at end of file |