mirror of
				https://git.zaroz.cloud/nintendo-back-up/yuzu/yuzu.git
				synced 2025-05-12 00:45:25 +00:00 
			
		
		
		
	arm: Remove SkyEye/Dyncom code that is ARMv6-only.
This commit is contained in:
		
							parent
							
								
									f0eab802e8
								
							
						
					
					
						commit
						b172f0d770
					
				@ -70,7 +70,6 @@ void RegistersWidget::OnDebugModeEntered() {
 | 
			
		||||
            1, QString("0x%1").arg(Core::CPU().GetVFPReg(i), 8, 16, QLatin1Char('0')));
 | 
			
		||||
 | 
			
		||||
    UpdateCPSRValues();
 | 
			
		||||
    UpdateVFPSystemRegisterValues();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RegistersWidget::OnDebugModeLeft() {}
 | 
			
		||||
@ -191,48 +190,5 @@ void RegistersWidget::CreateVFPSystemRegisterChildren() {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RegistersWidget::UpdateVFPSystemRegisterValues() {
 | 
			
		||||
    const u32 fpscr_val = Core::CPU().GetVFPSystemReg(VFP_FPSCR);
 | 
			
		||||
    const u32 fpexc_val = Core::CPU().GetVFPSystemReg(VFP_FPEXC);
 | 
			
		||||
    const u32 fpinst_val = Core::CPU().GetVFPSystemReg(VFP_FPINST);
 | 
			
		||||
    const u32 fpinst2_val = Core::CPU().GetVFPSystemReg(VFP_FPINST2);
 | 
			
		||||
 | 
			
		||||
    QTreeWidgetItem* const fpscr = vfp_system_registers->child(0);
 | 
			
		||||
    fpscr->setText(1, QString("0x%1").arg(fpscr_val, 8, 16, QLatin1Char('0')));
 | 
			
		||||
    fpscr->child(0)->setText(1, QString::number(fpscr_val & 1));
 | 
			
		||||
    fpscr->child(1)->setText(1, QString::number((fpscr_val >> 1) & 1));
 | 
			
		||||
    fpscr->child(2)->setText(1, QString::number((fpscr_val >> 2) & 1));
 | 
			
		||||
    fpscr->child(3)->setText(1, QString::number((fpscr_val >> 3) & 1));
 | 
			
		||||
    fpscr->child(4)->setText(1, QString::number((fpscr_val >> 4) & 1));
 | 
			
		||||
    fpscr->child(5)->setText(1, QString::number((fpscr_val >> 7) & 1));
 | 
			
		||||
    fpscr->child(6)->setText(1, QString::number((fpscr_val >> 8) & 1));
 | 
			
		||||
    fpscr->child(7)->setText(1, QString::number((fpscr_val >> 9) & 1));
 | 
			
		||||
    fpscr->child(8)->setText(1, QString::number((fpscr_val >> 10) & 1));
 | 
			
		||||
    fpscr->child(9)->setText(1, QString::number((fpscr_val >> 11) & 1));
 | 
			
		||||
    fpscr->child(10)->setText(1, QString::number((fpscr_val >> 12) & 1));
 | 
			
		||||
    fpscr->child(11)->setText(1, QString::number((fpscr_val >> 15) & 1));
 | 
			
		||||
    fpscr->child(12)->setText(1, QString("b%1").arg((fpscr_val >> 16) & 7, 3, 2, QLatin1Char('0')));
 | 
			
		||||
    fpscr->child(13)->setText(1, QString("b%1").arg((fpscr_val >> 20) & 3, 2, 2, QLatin1Char('0')));
 | 
			
		||||
    fpscr->child(14)->setText(1, QString("b%1").arg((fpscr_val >> 22) & 3, 2, 2, QLatin1Char('0')));
 | 
			
		||||
    fpscr->child(15)->setText(1, QString::number((fpscr_val >> 24) & 1));
 | 
			
		||||
    fpscr->child(16)->setText(1, QString::number((fpscr_val >> 25) & 1));
 | 
			
		||||
    fpscr->child(17)->setText(1, QString::number((fpscr_val >> 28) & 1));
 | 
			
		||||
    fpscr->child(18)->setText(1, QString::number((fpscr_val >> 29) & 1));
 | 
			
		||||
    fpscr->child(19)->setText(1, QString::number((fpscr_val >> 30) & 1));
 | 
			
		||||
    fpscr->child(20)->setText(1, QString::number((fpscr_val >> 31) & 1));
 | 
			
		||||
 | 
			
		||||
    QTreeWidgetItem* const fpexc = vfp_system_registers->child(1);
 | 
			
		||||
    fpexc->setText(1, QString("0x%1").arg(fpexc_val, 8, 16, QLatin1Char('0')));
 | 
			
		||||
    fpexc->child(0)->setText(1, QString::number(fpexc_val & 1));
 | 
			
		||||
    fpexc->child(1)->setText(1, QString::number((fpexc_val >> 2) & 1));
 | 
			
		||||
    fpexc->child(2)->setText(1, QString::number((fpexc_val >> 3) & 1));
 | 
			
		||||
    fpexc->child(3)->setText(1, QString::number((fpexc_val >> 7) & 1));
 | 
			
		||||
    fpexc->child(4)->setText(1, QString("b%1").arg((fpexc_val >> 8) & 7, 3, 2, QLatin1Char('0')));
 | 
			
		||||
    fpexc->child(5)->setText(1, QString::number((fpexc_val >> 28) & 1));
 | 
			
		||||
    fpexc->child(6)->setText(1, QString::number((fpexc_val >> 30) & 1));
 | 
			
		||||
    fpexc->child(7)->setText(1, QString::number((fpexc_val >> 31) & 1));
 | 
			
		||||
 | 
			
		||||
    vfp_system_registers->child(2)->setText(
 | 
			
		||||
        1, QString("0x%1").arg(fpinst_val, 8, 16, QLatin1Char('0')));
 | 
			
		||||
    vfp_system_registers->child(3)->setText(
 | 
			
		||||
        1, QString("0x%1").arg(fpinst2_val, 8, 16, QLatin1Char('0')));
 | 
			
		||||
    UNIMPLEMENTED();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,19 +1,7 @@
 | 
			
		||||
set(SRCS
 | 
			
		||||
            arm/dynarmic/arm_dynarmic.cpp
 | 
			
		||||
            arm/dynarmic/arm_dynarmic_cp15.cpp
 | 
			
		||||
            arm/dyncom/arm_dyncom.cpp
 | 
			
		||||
            arm/dyncom/arm_dyncom_dec.cpp
 | 
			
		||||
            arm/dyncom/arm_dyncom_interpreter.cpp
 | 
			
		||||
            arm/dyncom/arm_dyncom_thumb.cpp
 | 
			
		||||
            arm/dyncom/arm_dyncom_trans.cpp
 | 
			
		||||
            arm/unicorn/arm_unicorn.cpp
 | 
			
		||||
            arm/unicorn/unicorn_dynload.c
 | 
			
		||||
            arm/skyeye_common/armstate.cpp
 | 
			
		||||
            arm/skyeye_common/armsupp.cpp
 | 
			
		||||
            arm/skyeye_common/vfp/vfp.cpp
 | 
			
		||||
            arm/skyeye_common/vfp/vfpdouble.cpp
 | 
			
		||||
            arm/skyeye_common/vfp/vfpinstr.cpp
 | 
			
		||||
            arm/skyeye_common/vfp/vfpsingle.cpp
 | 
			
		||||
            core.cpp
 | 
			
		||||
            core_timing.cpp
 | 
			
		||||
            file_sys/archive_backend.cpp
 | 
			
		||||
@ -86,21 +74,8 @@ set(HEADERS
 | 
			
		||||
            3ds.h
 | 
			
		||||
            arm/arm_interface.h
 | 
			
		||||
            arm/dynarmic/arm_dynarmic.h
 | 
			
		||||
            arm/dynarmic/arm_dynarmic_cp15.h
 | 
			
		||||
            arm/dyncom/arm_dyncom.h
 | 
			
		||||
            arm/dyncom/arm_dyncom_dec.h
 | 
			
		||||
            arm/dyncom/arm_dyncom_interpreter.h
 | 
			
		||||
            arm/dyncom/arm_dyncom_run.h
 | 
			
		||||
            arm/dyncom/arm_dyncom_thumb.h
 | 
			
		||||
            arm/dyncom/arm_dyncom_trans.h
 | 
			
		||||
            arm/unicorn/arm_unicorn.h
 | 
			
		||||
            arm/unicorn/unicorn_dynload.h
 | 
			
		||||
            arm/skyeye_common/arm_regformat.h
 | 
			
		||||
            arm/skyeye_common/armstate.h
 | 
			
		||||
            arm/skyeye_common/armsupp.h
 | 
			
		||||
            arm/skyeye_common/vfp/asm_vfp.h
 | 
			
		||||
            arm/skyeye_common/vfp/vfp.h
 | 
			
		||||
            arm/skyeye_common/vfp/vfp_helper.h
 | 
			
		||||
            core.h
 | 
			
		||||
            core_timing.h
 | 
			
		||||
            file_sys/archive_backend.h
 | 
			
		||||
 | 
			
		||||
@ -6,8 +6,6 @@
 | 
			
		||||
 | 
			
		||||
#include "common/common_types.h"
 | 
			
		||||
#include "core/hle/kernel/vm_manager.h"
 | 
			
		||||
#include "core/arm/skyeye_common/arm_regformat.h"
 | 
			
		||||
#include "core/arm/skyeye_common/vfp/asm_vfp.h"
 | 
			
		||||
 | 
			
		||||
/// Generic ARM11 CPU interface
 | 
			
		||||
class ARM_Interface : NonCopyable {
 | 
			
		||||
@ -95,20 +93,6 @@ public:
 | 
			
		||||
     */
 | 
			
		||||
    virtual void SetVFPReg(int index, u32 value) = 0;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets the current value within a given VFP system register
 | 
			
		||||
     * @param reg The VFP system register
 | 
			
		||||
     * @return The value within the VFP system register
 | 
			
		||||
     */
 | 
			
		||||
    virtual u32 GetVFPSystemReg(VFPSystemRegister reg) const = 0;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Sets the VFP system register to the given value
 | 
			
		||||
     * @param reg   The VFP system register
 | 
			
		||||
     * @param value Value to set the VFP system register to
 | 
			
		||||
     */
 | 
			
		||||
    virtual void SetVFPSystemReg(VFPSystemRegister reg, u32 value) = 0;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Get the current CPSR register
 | 
			
		||||
     * @return Returns the value of the CPSR register
 | 
			
		||||
@ -121,20 +105,6 @@ public:
 | 
			
		||||
     */
 | 
			
		||||
    virtual void SetCPSR(u32 cpsr) = 0;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets the value stored in a CP15 register.
 | 
			
		||||
     * @param reg The CP15 register to retrieve the value from.
 | 
			
		||||
     * @return the value stored in the given CP15 register.
 | 
			
		||||
     */
 | 
			
		||||
    virtual u32 GetCP15Register(CP15Register reg) = 0;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Stores the given value into the indicated CP15 register.
 | 
			
		||||
     * @param reg   The CP15 register to store the value into.
 | 
			
		||||
     * @param value The value to store into the CP15 register.
 | 
			
		||||
     */
 | 
			
		||||
    virtual void SetCP15Register(CP15Register reg, u32 value) = 0;
 | 
			
		||||
 | 
			
		||||
    virtual VAddr GetTlsAddress() const = 0;
 | 
			
		||||
 | 
			
		||||
    virtual void SetTlsAddress(VAddr address) = 0;
 | 
			
		||||
 | 
			
		||||
@ -7,11 +7,9 @@
 | 
			
		||||
#include "common/assert.h"
 | 
			
		||||
#include "common/microprofile.h"
 | 
			
		||||
#include "core/arm/dynarmic/arm_dynarmic.h"
 | 
			
		||||
#include "core/arm/dynarmic/arm_dynarmic_cp15.h"
 | 
			
		||||
#include "core/arm/dyncom/arm_dyncom_interpreter.h"
 | 
			
		||||
#include "core/core.h"
 | 
			
		||||
#include "core/core_timing.h"
 | 
			
		||||
#include "core/hle/svc.h"
 | 
			
		||||
#include "core/hle/kernel/svc.h"
 | 
			
		||||
#include "core/memory.h"
 | 
			
		||||
 | 
			
		||||
static void InterpreterFallback(u64 pc, Dynarmic::Jit* jit, void* user_arg) {
 | 
			
		||||
@ -55,11 +53,11 @@ void MemoryWrite64(const u64 addr, const u64 data) {
 | 
			
		||||
    Memory::Write64(static_cast<VAddr>(addr), data);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static Dynarmic::UserCallbacks GetUserCallbacks(ARM_Dynarmic* this_) {
 | 
			
		||||
static Dynarmic::UserCallbacks GetUserCallbacks(ARM_Interface* interpreter_fallback) {
 | 
			
		||||
    Dynarmic::UserCallbacks user_callbacks{};
 | 
			
		||||
    user_callbacks.InterpreterFallback = &InterpreterFallback;
 | 
			
		||||
    user_callbacks.user_arg = static_cast<void*>(this_);
 | 
			
		||||
    user_callbacks.CallSVC = &SVC::CallSVC;
 | 
			
		||||
    user_callbacks.user_arg = static_cast<void*>(interpreter_fallback);
 | 
			
		||||
    user_callbacks.CallSVC = &Kernel::CallSVC;
 | 
			
		||||
    user_callbacks.memory.IsReadOnlyMemory = &IsReadOnlyMemory;
 | 
			
		||||
    user_callbacks.memory.ReadCode = &MemoryRead32;
 | 
			
		||||
    user_callbacks.memory.Read8 = &MemoryRead8;
 | 
			
		||||
@ -74,7 +72,7 @@ static Dynarmic::UserCallbacks GetUserCallbacks(ARM_Dynarmic* this_) {
 | 
			
		||||
    return user_callbacks;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ARM_Dynarmic::ARM_Dynarmic(PrivilegeMode initial_mode) {
 | 
			
		||||
ARM_Dynarmic::ARM_Dynarmic() {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ARM_Dynarmic::MapBackingMemory(VAddr address, size_t size, u8* memory, Kernel::VMAPermission perms) {
 | 
			
		||||
@ -111,13 +109,6 @@ u32 ARM_Dynarmic::GetVFPReg(int index) const {
 | 
			
		||||
void ARM_Dynarmic::SetVFPReg(int index, u32 value) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
u32 ARM_Dynarmic::GetVFPSystemReg(VFPSystemRegister reg) const {
 | 
			
		||||
    return {};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ARM_Dynarmic::SetVFPSystemReg(VFPSystemRegister reg, u32 value) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
u32 ARM_Dynarmic::GetCPSR() const {
 | 
			
		||||
    return jit->Cpsr();
 | 
			
		||||
}
 | 
			
		||||
@ -126,13 +117,6 @@ void ARM_Dynarmic::SetCPSR(u32 cpsr) {
 | 
			
		||||
    jit->Cpsr() = cpsr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
u32 ARM_Dynarmic::GetCP15Register(CP15Register reg) {
 | 
			
		||||
    return {};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ARM_Dynarmic::SetCP15Register(CP15Register reg, u32 value) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
VAddr ARM_Dynarmic::GetTlsAddress() const {
 | 
			
		||||
    return jit->TlsAddr();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -9,7 +9,6 @@
 | 
			
		||||
#include <dynarmic/dynarmic.h>
 | 
			
		||||
#include "common/common_types.h"
 | 
			
		||||
#include "core/arm/arm_interface.h"
 | 
			
		||||
#include "core/arm/skyeye_common/armstate.h"
 | 
			
		||||
 | 
			
		||||
namespace Memory {
 | 
			
		||||
struct PageTable;
 | 
			
		||||
@ -17,7 +16,7 @@ struct PageTable;
 | 
			
		||||
 | 
			
		||||
class ARM_Dynarmic final : public ARM_Interface {
 | 
			
		||||
public:
 | 
			
		||||
    ARM_Dynarmic(PrivilegeMode initial_mode);
 | 
			
		||||
    ARM_Dynarmic();
 | 
			
		||||
 | 
			
		||||
    void MapBackingMemory(VAddr address, size_t size, u8* memory, Kernel::VMAPermission perms) override;
 | 
			
		||||
 | 
			
		||||
@ -29,12 +28,8 @@ public:
 | 
			
		||||
    void SetExtReg(int index, u128& value) override;
 | 
			
		||||
    u32 GetVFPReg(int index) const override;
 | 
			
		||||
    void SetVFPReg(int index, u32 value) override;
 | 
			
		||||
    u32 GetVFPSystemReg(VFPSystemRegister reg) const override;
 | 
			
		||||
    void SetVFPSystemReg(VFPSystemRegister reg, u32 value) override;
 | 
			
		||||
    u32 GetCPSR() const override;
 | 
			
		||||
    void SetCPSR(u32 cpsr) override;
 | 
			
		||||
    u32 GetCP15Register(CP15Register reg) override;
 | 
			
		||||
    void SetCP15Register(CP15Register reg, u32 value) override;
 | 
			
		||||
    VAddr GetTlsAddress() const override;
 | 
			
		||||
    void SetTlsAddress(VAddr address) override;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,88 +0,0 @@
 | 
			
		||||
// Copyright 2017 Citra Emulator Project
 | 
			
		||||
// Licensed under GPLv2 or any later version
 | 
			
		||||
// Refer to the license.txt file included.
 | 
			
		||||
 | 
			
		||||
#include "core/arm/dynarmic/arm_dynarmic_cp15.h"
 | 
			
		||||
#include "core/arm/skyeye_common/arm_regformat.h"
 | 
			
		||||
#include "core/arm/skyeye_common/armstate.h"
 | 
			
		||||
 | 
			
		||||
using Callback = Dynarmic::Coprocessor::Callback;
 | 
			
		||||
using CallbackOrAccessOneWord = Dynarmic::Coprocessor::CallbackOrAccessOneWord;
 | 
			
		||||
using CallbackOrAccessTwoWords = Dynarmic::Coprocessor::CallbackOrAccessTwoWords;
 | 
			
		||||
 | 
			
		||||
DynarmicCP15::DynarmicCP15(const std::shared_ptr<ARMul_State>& state) : interpreter_state(state) {}
 | 
			
		||||
 | 
			
		||||
DynarmicCP15::~DynarmicCP15() = default;
 | 
			
		||||
 | 
			
		||||
boost::optional<Callback> DynarmicCP15::CompileInternalOperation(bool two, unsigned opc1,
 | 
			
		||||
                                                                 CoprocReg CRd, CoprocReg CRn,
 | 
			
		||||
                                                                 CoprocReg CRm, unsigned opc2) {
 | 
			
		||||
    return boost::none;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
CallbackOrAccessOneWord DynarmicCP15::CompileSendOneWord(bool two, unsigned opc1, CoprocReg CRn,
 | 
			
		||||
                                                         CoprocReg CRm, unsigned opc2) {
 | 
			
		||||
    // TODO(merry): Privileged CP15 registers
 | 
			
		||||
 | 
			
		||||
    if (!two && CRn == CoprocReg::C7 && opc1 == 0 && CRm == CoprocReg::C5 && opc2 == 4) {
 | 
			
		||||
        // This is a dummy write, we ignore the value written here.
 | 
			
		||||
        return &interpreter_state->CP15[CP15_FLUSH_PREFETCH_BUFFER];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (!two && CRn == CoprocReg::C7 && opc1 == 0 && CRm == CoprocReg::C10) {
 | 
			
		||||
        switch (opc2) {
 | 
			
		||||
        case 4:
 | 
			
		||||
            // This is a dummy write, we ignore the value written here.
 | 
			
		||||
            return &interpreter_state->CP15[CP15_DATA_SYNC_BARRIER];
 | 
			
		||||
        case 5:
 | 
			
		||||
            // This is a dummy write, we ignore the value written here.
 | 
			
		||||
            return &interpreter_state->CP15[CP15_DATA_MEMORY_BARRIER];
 | 
			
		||||
        default:
 | 
			
		||||
            return boost::blank{};
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (!two && CRn == CoprocReg::C13 && opc1 == 0 && CRm == CoprocReg::C0 && opc2 == 2) {
 | 
			
		||||
        return &interpreter_state->CP15[CP15_THREAD_UPRW];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return boost::blank{};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
CallbackOrAccessTwoWords DynarmicCP15::CompileSendTwoWords(bool two, unsigned opc, CoprocReg CRm) {
 | 
			
		||||
    return boost::blank{};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
CallbackOrAccessOneWord DynarmicCP15::CompileGetOneWord(bool two, unsigned opc1, CoprocReg CRn,
 | 
			
		||||
                                                        CoprocReg CRm, unsigned opc2) {
 | 
			
		||||
    // TODO(merry): Privileged CP15 registers
 | 
			
		||||
 | 
			
		||||
    if (!two && CRn == CoprocReg::C13 && opc1 == 0 && CRm == CoprocReg::C0) {
 | 
			
		||||
        switch (opc2) {
 | 
			
		||||
        case 2:
 | 
			
		||||
            return &interpreter_state->CP15[CP15_THREAD_UPRW];
 | 
			
		||||
        case 3:
 | 
			
		||||
            return &interpreter_state->CP15[CP15_THREAD_URO];
 | 
			
		||||
        default:
 | 
			
		||||
            return boost::blank{};
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return boost::blank{};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
CallbackOrAccessTwoWords DynarmicCP15::CompileGetTwoWords(bool two, unsigned opc, CoprocReg CRm) {
 | 
			
		||||
    return boost::blank{};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
boost::optional<Callback> DynarmicCP15::CompileLoadWords(bool two, bool long_transfer,
 | 
			
		||||
                                                         CoprocReg CRd,
 | 
			
		||||
                                                         boost::optional<u8> option) {
 | 
			
		||||
    return boost::none;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
boost::optional<Callback> DynarmicCP15::CompileStoreWords(bool two, bool long_transfer,
 | 
			
		||||
                                                          CoprocReg CRd,
 | 
			
		||||
                                                          boost::optional<u8> option) {
 | 
			
		||||
    return boost::none;
 | 
			
		||||
}
 | 
			
		||||
@ -1,32 +0,0 @@
 | 
			
		||||
// Copyright 2017 Citra Emulator Project
 | 
			
		||||
// Licensed under GPLv2 or any later version
 | 
			
		||||
// Refer to the license.txt file included.
 | 
			
		||||
 | 
			
		||||
#include <memory>
 | 
			
		||||
#include <dynarmic/coprocessor.h>
 | 
			
		||||
#include "common/common_types.h"
 | 
			
		||||
 | 
			
		||||
struct ARMul_State;
 | 
			
		||||
 | 
			
		||||
class DynarmicCP15 final : public Dynarmic::Coprocessor {
 | 
			
		||||
public:
 | 
			
		||||
    explicit DynarmicCP15(const std::shared_ptr<ARMul_State>&);
 | 
			
		||||
    ~DynarmicCP15() override;
 | 
			
		||||
 | 
			
		||||
    boost::optional<Callback> CompileInternalOperation(bool two, unsigned opc1, CoprocReg CRd,
 | 
			
		||||
                                                       CoprocReg CRn, CoprocReg CRm,
 | 
			
		||||
                                                       unsigned opc2) override;
 | 
			
		||||
    CallbackOrAccessOneWord CompileSendOneWord(bool two, unsigned opc1, CoprocReg CRn,
 | 
			
		||||
                                               CoprocReg CRm, unsigned opc2) override;
 | 
			
		||||
    CallbackOrAccessTwoWords CompileSendTwoWords(bool two, unsigned opc, CoprocReg CRm) override;
 | 
			
		||||
    CallbackOrAccessOneWord CompileGetOneWord(bool two, unsigned opc1, CoprocReg CRn, CoprocReg CRm,
 | 
			
		||||
                                              unsigned opc2) override;
 | 
			
		||||
    CallbackOrAccessTwoWords CompileGetTwoWords(bool two, unsigned opc, CoprocReg CRm) override;
 | 
			
		||||
    boost::optional<Callback> CompileLoadWords(bool two, bool long_transfer, CoprocReg CRd,
 | 
			
		||||
                                               boost::optional<u8> option) override;
 | 
			
		||||
    boost::optional<Callback> CompileStoreWords(bool two, bool long_transfer, CoprocReg CRd,
 | 
			
		||||
                                                boost::optional<u8> option) override;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    std::shared_ptr<ARMul_State> interpreter_state;
 | 
			
		||||
};
 | 
			
		||||
@ -1,132 +0,0 @@
 | 
			
		||||
// Copyright 2014 Citra Emulator Project
 | 
			
		||||
// Licensed under GPLv2 or any later version
 | 
			
		||||
// Refer to the license.txt file included.
 | 
			
		||||
 | 
			
		||||
#include <cstring>
 | 
			
		||||
#include <memory>
 | 
			
		||||
#include "core/arm/dyncom/arm_dyncom.h"
 | 
			
		||||
#include "core/arm/dyncom/arm_dyncom_interpreter.h"
 | 
			
		||||
#include "core/arm/dyncom/arm_dyncom_run.h"
 | 
			
		||||
#include "core/arm/dyncom/arm_dyncom_trans.h"
 | 
			
		||||
#include "core/arm/skyeye_common/armstate.h"
 | 
			
		||||
#include "core/arm/skyeye_common/armsupp.h"
 | 
			
		||||
#include "core/arm/skyeye_common/vfp/vfp.h"
 | 
			
		||||
#include "core/core.h"
 | 
			
		||||
#include "core/core_timing.h"
 | 
			
		||||
 | 
			
		||||
ARM_DynCom::ARM_DynCom(PrivilegeMode initial_mode) {
 | 
			
		||||
    state = std::make_unique<ARMul_State>(initial_mode);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ARM_DynCom::~ARM_DynCom() {}
 | 
			
		||||
 | 
			
		||||
void ARM_DynCom::ClearInstructionCache() {
 | 
			
		||||
    state->instruction_cache.clear();
 | 
			
		||||
    trans_cache_buf_top = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ARM_DynCom::SetPC(u64 pc) {
 | 
			
		||||
    state->Reg[15] = pc;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ARM_DynCom::PageTableChanged() {
 | 
			
		||||
    ClearInstructionCache();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
u64 ARM_DynCom::GetPC() const {
 | 
			
		||||
    return state->Reg[15];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
u64 ARM_DynCom::GetReg(int index) const {
 | 
			
		||||
    return state->Reg[index];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ARM_DynCom::SetReg(int index, u64 value) {
 | 
			
		||||
    state->Reg[index] = value;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const u128& ARM_DynCom::GetExtReg(int index) const {
 | 
			
		||||
    return {};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ARM_DynCom::SetExtReg(int index, u128& value) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
u32 ARM_DynCom::GetVFPReg(int index) const {
 | 
			
		||||
    return state->ExtReg[index];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ARM_DynCom::SetVFPReg(int index, u32 value) {
 | 
			
		||||
    state->ExtReg[index] = value;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
u32 ARM_DynCom::GetVFPSystemReg(VFPSystemRegister reg) const {
 | 
			
		||||
    return state->VFP[reg];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ARM_DynCom::SetVFPSystemReg(VFPSystemRegister reg, u32 value) {
 | 
			
		||||
    state->VFP[reg] = value;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
u32 ARM_DynCom::GetCPSR() const {
 | 
			
		||||
    return state->Cpsr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ARM_DynCom::SetCPSR(u32 cpsr) {
 | 
			
		||||
    state->Cpsr = cpsr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
u32 ARM_DynCom::GetCP15Register(CP15Register reg) {
 | 
			
		||||
    return state->CP15[reg];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ARM_DynCom::SetCP15Register(CP15Register reg, u32 value) {
 | 
			
		||||
    state->CP15[reg] = value;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
VAddr ARM_DynCom::GetTlsAddress() const {
 | 
			
		||||
    return {};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ARM_DynCom::SetTlsAddress(VAddr /*address*/) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ARM_DynCom::ExecuteInstructions(int num_instructions) {
 | 
			
		||||
    state->NumInstrsToExecute = num_instructions;
 | 
			
		||||
 | 
			
		||||
    // Dyncom only breaks on instruction dispatch. This only happens on every instruction when
 | 
			
		||||
    // executing one instruction at a time. Otherwise, if a block is being executed, more
 | 
			
		||||
    // instructions may actually be executed than specified.
 | 
			
		||||
    unsigned ticks_executed = InterpreterMainLoop(state.get());
 | 
			
		||||
    CoreTiming::AddTicks(ticks_executed);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ARM_DynCom::SaveContext(ThreadContext& ctx) {
 | 
			
		||||
    memcpy(ctx.cpu_registers, state->Reg.data(), sizeof(ctx.cpu_registers));
 | 
			
		||||
    memcpy(ctx.fpu_registers, state->ExtReg.data(), sizeof(ctx.fpu_registers));
 | 
			
		||||
 | 
			
		||||
    ctx.sp = state->Reg[13];
 | 
			
		||||
    ctx.lr = state->Reg[14];
 | 
			
		||||
    ctx.pc = state->Reg[15];
 | 
			
		||||
    ctx.cpsr = state->Cpsr;
 | 
			
		||||
 | 
			
		||||
    ctx.fpscr = state->VFP[VFP_FPSCR];
 | 
			
		||||
    ctx.fpexc = state->VFP[VFP_FPEXC];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ARM_DynCom::LoadContext(const ThreadContext& ctx) {
 | 
			
		||||
    memcpy(state->Reg.data(), ctx.cpu_registers, sizeof(ctx.cpu_registers));
 | 
			
		||||
    memcpy(state->ExtReg.data(), ctx.fpu_registers, sizeof(ctx.fpu_registers));
 | 
			
		||||
 | 
			
		||||
    state->Reg[13] = ctx.sp;
 | 
			
		||||
    state->Reg[14] = ctx.lr;
 | 
			
		||||
    state->Reg[15] = ctx.pc;
 | 
			
		||||
    state->Cpsr = ctx.cpsr;
 | 
			
		||||
 | 
			
		||||
    state->VFP[VFP_FPSCR] = ctx.fpscr;
 | 
			
		||||
    state->VFP[VFP_FPEXC] = ctx.fpexc;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ARM_DynCom::PrepareReschedule() {
 | 
			
		||||
    state->NumInstrsToExecute = 0;
 | 
			
		||||
}
 | 
			
		||||
@ -1,46 +0,0 @@
 | 
			
		||||
// Copyright 2014 Citra Emulator Project
 | 
			
		||||
// Licensed under GPLv2 or any later version
 | 
			
		||||
// Refer to the license.txt file included.
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <memory>
 | 
			
		||||
#include "common/common_types.h"
 | 
			
		||||
#include "core/arm/arm_interface.h"
 | 
			
		||||
#include "core/arm/skyeye_common/arm_regformat.h"
 | 
			
		||||
#include "core/arm/skyeye_common/armstate.h"
 | 
			
		||||
 | 
			
		||||
class ARM_DynCom final : public ARM_Interface {
 | 
			
		||||
public:
 | 
			
		||||
    ARM_DynCom(PrivilegeMode initial_mode);
 | 
			
		||||
    ~ARM_DynCom();
 | 
			
		||||
 | 
			
		||||
    void ClearInstructionCache() override;
 | 
			
		||||
    void PageTableChanged() override;
 | 
			
		||||
 | 
			
		||||
    void SetPC(u64 pc) override;
 | 
			
		||||
    u64 GetPC() const override;
 | 
			
		||||
    u64 GetReg(int index) const override;
 | 
			
		||||
    void SetReg(int index, u64 value) override;
 | 
			
		||||
    const u128& GetExtReg(int index) const override;
 | 
			
		||||
    void SetExtReg(int index, u128& value) override;
 | 
			
		||||
    u32 GetVFPReg(int index) const override;
 | 
			
		||||
    void SetVFPReg(int index, u32 value) override;
 | 
			
		||||
    u32 GetVFPSystemReg(VFPSystemRegister reg) const override;
 | 
			
		||||
    void SetVFPSystemReg(VFPSystemRegister reg, u32 value) override;
 | 
			
		||||
    u32 GetCPSR() const override;
 | 
			
		||||
    void SetCPSR(u32 cpsr) override;
 | 
			
		||||
    u32 GetCP15Register(CP15Register reg) override;
 | 
			
		||||
    void SetCP15Register(CP15Register reg, u32 value) override;
 | 
			
		||||
    VAddr GetTlsAddress() const override;
 | 
			
		||||
    void SetTlsAddress(VAddr address) override;
 | 
			
		||||
 | 
			
		||||
    void SaveContext(ThreadContext& ctx) override;
 | 
			
		||||
    void LoadContext(const ThreadContext& ctx) override;
 | 
			
		||||
 | 
			
		||||
    void PrepareReschedule() override;
 | 
			
		||||
    void ExecuteInstructions(int num_instructions) override;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    std::unique_ptr<ARMul_State> state;
 | 
			
		||||
};
 | 
			
		||||
@ -1,478 +0,0 @@
 | 
			
		||||
// Copyright 2012 Michael Kang, 2014 Citra Emulator Project
 | 
			
		||||
// Licensed under GPLv2 or any later version
 | 
			
		||||
// Refer to the license.txt file included.
 | 
			
		||||
 | 
			
		||||
#include "core/arm/dyncom/arm_dyncom_dec.h"
 | 
			
		||||
#include "core/arm/skyeye_common/armsupp.h"
 | 
			
		||||
 | 
			
		||||
// clang-format off
 | 
			
		||||
const InstructionSetEncodingItem arm_instruction[] = {
 | 
			
		||||
    { "vmla", 5, ARMVFP2,      { 23, 27, 0x1C, 20, 21, 0x0, 9, 11, 0x5, 6, 6, 0, 4, 4, 0 }},
 | 
			
		||||
    { "vmls", 5, ARMVFP2,      { 23, 27, 0x1C, 20, 21, 0x0, 9, 11, 0x5, 6, 6, 1, 4, 4, 0 }},
 | 
			
		||||
    { "vnmla", 5, ARMVFP2,     { 23, 27, 0x1C, 20, 21, 0x1, 9, 11, 0x5, 6, 6, 1, 4, 4, 0 }},
 | 
			
		||||
    { "vnmls", 5, ARMVFP2,     { 23, 27, 0x1C, 20, 21, 0x1, 9, 11, 0x5, 6, 6, 0, 4, 4, 0 }},
 | 
			
		||||
    { "vnmul", 5, ARMVFP2,     { 23, 27, 0x1C, 20, 21, 0x2, 9, 11, 0x5, 6, 6, 1, 4, 4, 0 }},
 | 
			
		||||
    { "vmul", 5, ARMVFP2,      { 23, 27, 0x1C, 20, 21, 0x2, 9, 11, 0x5, 6, 6, 0, 4, 4, 0 }},
 | 
			
		||||
    { "vadd", 5, ARMVFP2,      { 23, 27, 0x1C, 20, 21, 0x3, 9, 11, 0x5, 6, 6, 0, 4, 4, 0 }},
 | 
			
		||||
    { "vsub", 5, ARMVFP2,      { 23, 27, 0x1C, 20, 21, 0x3, 9, 11, 0x5, 6, 6, 1, 4, 4, 0 }},
 | 
			
		||||
    { "vdiv", 5, ARMVFP2,      { 23, 27, 0x1D, 20, 21, 0x0, 9, 11, 0x5, 6, 6, 0, 4, 4, 0 }},
 | 
			
		||||
    { "vmov(i)", 4, ARMVFP3,   { 23, 27, 0x1D, 20, 21, 0x3, 9, 11, 0x5, 4, 7, 0 }},
 | 
			
		||||
    { "vmov(r)", 5, ARMVFP3,   { 23, 27, 0x1D, 16, 21, 0x30, 9, 11, 0x5, 6, 7, 1, 4, 4, 0 }},
 | 
			
		||||
    { "vabs", 5, ARMVFP2,      { 23, 27, 0x1D, 16, 21, 0x30, 9, 11, 0x5, 6, 7, 3, 4, 4, 0 }},
 | 
			
		||||
    { "vneg", 5, ARMVFP2,      { 23, 27, 0x1D, 17, 21, 0x18, 9, 11, 0x5, 6, 7, 1, 4, 4, 0 }},
 | 
			
		||||
    { "vsqrt", 5, ARMVFP2,     { 23, 27, 0x1D, 16, 21, 0x31, 9, 11, 0x5, 6, 7, 3, 4, 4, 0 }},
 | 
			
		||||
    { "vcmp", 5, ARMVFP2,      { 23, 27, 0x1D, 16, 21, 0x34, 9, 11, 0x5, 6, 6, 1, 4, 4, 0 }},
 | 
			
		||||
    { "vcmp2", 5, ARMVFP2,     { 23, 27, 0x1D, 16, 21, 0x35, 9, 11, 0x5, 0, 6, 0x40 }},
 | 
			
		||||
    { "vcvt(bds)", 5, ARMVFP2, { 23, 27, 0x1D, 16, 21, 0x37, 9, 11, 0x5, 6, 7, 3, 4, 4, 0 }},
 | 
			
		||||
    { "vcvt(bff)", 6, ARMVFP3, { 23, 27, 0x1D, 19, 21, 0x7, 17, 17, 0x1, 9, 11, 5, 6, 6, 1 }},
 | 
			
		||||
    { "vcvt(bfi)", 5, ARMVFP2, { 23, 27, 0x1D, 19, 21, 0x7, 9, 11, 0x5, 6, 6, 1, 4, 4, 0 }},
 | 
			
		||||
    { "vmovbrs", 3, ARMVFP2,   { 21, 27, 0x70, 8, 11, 0xA, 0, 6, 0x10 }},
 | 
			
		||||
    { "vmsr", 2, ARMVFP2,      { 20, 27, 0xEE, 0, 11, 0xA10 }},
 | 
			
		||||
    { "vmovbrc", 4, ARMVFP2,   { 23, 27, 0x1C, 20, 20, 0x0, 8, 11, 0xB, 0, 4, 0x10 }},
 | 
			
		||||
    { "vmrs", 2, ARMVFP2,      { 20, 27, 0xEF, 0, 11, 0xA10 }},
 | 
			
		||||
    { "vmovbcr", 4, ARMVFP2,   { 24, 27, 0xE, 20, 20, 1, 8, 11, 0xB, 0, 4, 0x10 }},
 | 
			
		||||
    { "vmovbrrss", 3, ARMVFP2, { 21, 27, 0x62, 8, 11, 0xA, 4, 4, 1 }},
 | 
			
		||||
    { "vmovbrrd", 3, ARMVFP2,  { 21, 27, 0x62, 6, 11, 0x2C, 4, 4, 1 }},
 | 
			
		||||
    { "vstr", 3, ARMVFP2,      { 24, 27, 0xD, 20, 21, 0, 9, 11, 5 }},
 | 
			
		||||
    { "vpush", 3, ARMVFP2,     { 23, 27, 0x1A, 16, 21, 0x2D, 9, 11, 5 }},
 | 
			
		||||
    { "vstm", 3, ARMVFP2,      { 25, 27, 0x6, 20, 20, 0, 9, 11, 5 }},
 | 
			
		||||
    { "vpop", 3, ARMVFP2,      { 23, 27, 0x19, 16, 21, 0x3D, 9, 11, 5 }},
 | 
			
		||||
    { "vldr", 3, ARMVFP2,      { 24, 27, 0xD, 20, 21, 1, 9, 11, 5 }},
 | 
			
		||||
    { "vldm", 3, ARMVFP2,      { 25, 27, 0x6, 20, 20, 1, 9, 11, 5 }},
 | 
			
		||||
 | 
			
		||||
    { "srs", 4, 6,         { 25, 31, 0x0000007c, 22, 22, 0x00000001, 16, 20, 0x0000000d, 8, 11, 0x00000005 }},
 | 
			
		||||
    { "rfe", 4, 6,         { 25, 31, 0x0000007c, 22, 22, 0x00000000, 20, 20, 0x00000001, 8, 11, 0x0000000a }},
 | 
			
		||||
    { "bkpt", 2, 3,        { 20, 27, 0x00000012, 4, 7, 0x00000007 }},
 | 
			
		||||
    { "blx", 1, 3,         { 25, 31, 0x0000007d }},
 | 
			
		||||
    { "cps", 3, 6,         { 20, 31, 0x00000f10, 16, 16, 0x00000000, 5, 5, 0x00000000 }},
 | 
			
		||||
    { "pld", 4, 4,         { 26, 31, 0x0000003d, 24, 24, 0x00000001, 20, 22, 0x00000005, 12, 15, 0x0000000f }},
 | 
			
		||||
    { "setend", 2, 6,      { 16, 31, 0x0000f101, 4, 7, 0x00000000 }},
 | 
			
		||||
    { "clrex", 1, 6,       { 0, 31, 0xf57ff01f }},
 | 
			
		||||
    { "rev16", 2, 6,       { 16, 27, 0x000006bf, 4, 11, 0x000000fb }},
 | 
			
		||||
    { "usad8", 3, 6,       { 20, 27, 0x00000078, 12, 15, 0x0000000f, 4, 7, 0x00000001 }},
 | 
			
		||||
    { "sxtb", 2, 6,        { 16, 27, 0x000006af, 4, 7, 0x00000007 }},
 | 
			
		||||
    { "uxtb", 2, 6,        { 16, 27, 0x000006ef, 4, 7, 0x00000007 }},
 | 
			
		||||
    { "sxth", 2, 6,        { 16, 27, 0x000006bf, 4, 7, 0x00000007 }},
 | 
			
		||||
    { "sxtb16", 2, 6,      { 16, 27, 0x0000068f, 4, 7, 0x00000007 }},
 | 
			
		||||
    { "uxth", 2, 6,        { 16, 27, 0x000006ff, 4, 7, 0x00000007 }},
 | 
			
		||||
    { "uxtb16", 2, 6,      { 16, 27, 0x000006cf, 4, 7, 0x00000007 }},
 | 
			
		||||
    { "cpy", 2, 6,         { 20, 27, 0x0000001a, 4, 11, 0x00000000 }},
 | 
			
		||||
    { "uxtab", 2, 6,       { 20, 27, 0x0000006e, 4, 9, 0x00000007 }},
 | 
			
		||||
    { "ssub8", 2, 6,       { 20, 27, 0x00000061, 4, 7, 0x0000000f }},
 | 
			
		||||
    { "shsub8", 2, 6,      { 20, 27, 0x00000063, 4, 7, 0x0000000f }},
 | 
			
		||||
    { "ssubaddx", 2, 6,    { 20, 27, 0x00000061, 4, 7, 0x00000005 }},
 | 
			
		||||
    { "strex", 2, 6,       { 20, 27, 0x00000018, 4, 7, 0x00000009 }},
 | 
			
		||||
    { "strexb", 2, 7,      { 20, 27, 0x0000001c, 4, 7, 0x00000009 }},
 | 
			
		||||
    { "swp", 2, 0,         { 20, 27, 0x00000010, 4, 7, 0x00000009 }},
 | 
			
		||||
    { "swpb", 2, 0,        { 20, 27, 0x00000014, 4, 7, 0x00000009 }},
 | 
			
		||||
    { "ssub16", 2, 6,      { 20, 27, 0x00000061, 4, 7, 0x00000007 }},
 | 
			
		||||
    { "ssat16", 2, 6,      { 20, 27, 0x0000006a, 4, 7, 0x00000003 }},
 | 
			
		||||
    { "shsubaddx", 2, 6,   { 20, 27, 0x00000063, 4, 7, 0x00000005 }},
 | 
			
		||||
    { "qsubaddx", 2, 6,    { 20, 27, 0x00000062, 4, 7, 0x00000005 }},
 | 
			
		||||
    { "shaddsubx", 2, 6,   { 20, 27, 0x00000063, 4, 7, 0x00000003 }},
 | 
			
		||||
    { "shadd8", 2, 6,      { 20, 27, 0x00000063, 4, 7, 0x00000009 }},
 | 
			
		||||
    { "shadd16", 2, 6,     { 20, 27, 0x00000063, 4, 7, 0x00000001 }},
 | 
			
		||||
    { "sel", 2, 6,         { 20, 27, 0x00000068, 4, 7, 0x0000000b }},
 | 
			
		||||
    { "saddsubx", 2, 6,    { 20, 27, 0x00000061, 4, 7, 0x00000003 }},
 | 
			
		||||
    { "sadd8", 2, 6,       { 20, 27, 0x00000061, 4, 7, 0x00000009 }},
 | 
			
		||||
    { "sadd16", 2, 6,      { 20, 27, 0x00000061, 4, 7, 0x00000001 }},
 | 
			
		||||
    { "shsub16", 2, 6,     { 20, 27, 0x00000063, 4, 7, 0x00000007 }},
 | 
			
		||||
    { "umaal", 2, 6,       { 20, 27, 0x00000004, 4, 7, 0x00000009 }},
 | 
			
		||||
    { "uxtab16", 2, 6,     { 20, 27, 0x0000006c, 4, 7, 0x00000007 }},
 | 
			
		||||
    { "usubaddx", 2, 6,    { 20, 27, 0x00000065, 4, 7, 0x00000005 }},
 | 
			
		||||
    { "usub8", 2, 6,       { 20, 27, 0x00000065, 4, 7, 0x0000000f }},
 | 
			
		||||
    { "usub16", 2, 6,      { 20, 27, 0x00000065, 4, 7, 0x00000007 }},
 | 
			
		||||
    { "usat16", 2, 6,      { 20, 27, 0x0000006e, 4, 7, 0x00000003 }},
 | 
			
		||||
    { "usada8", 2, 6,      { 20, 27, 0x00000078, 4, 7, 0x00000001 }},
 | 
			
		||||
    { "uqsubaddx", 2, 6,   { 20, 27, 0x00000066, 4, 7, 0x00000005 }},
 | 
			
		||||
    { "uqsub8", 2, 6,      { 20, 27, 0x00000066, 4, 7, 0x0000000f }},
 | 
			
		||||
    { "uqsub16", 2, 6,     { 20, 27, 0x00000066, 4, 7, 0x00000007 }},
 | 
			
		||||
    { "uqaddsubx", 2, 6,   { 20, 27, 0x00000066, 4, 7, 0x00000003 }},
 | 
			
		||||
    { "uqadd8", 2, 6,      { 20, 27, 0x00000066, 4, 7, 0x00000009 }},
 | 
			
		||||
    { "uqadd16", 2, 6,     { 20, 27, 0x00000066, 4, 7, 0x00000001 }},
 | 
			
		||||
    { "sxtab", 2, 6,       { 20, 27, 0x0000006a, 4, 7, 0x00000007 }},
 | 
			
		||||
    { "uhsubaddx", 2, 6,   { 20, 27, 0x00000067, 4, 7, 0x00000005 }},
 | 
			
		||||
    { "uhsub8", 2, 6,      { 20, 27, 0x00000067, 4, 7, 0x0000000f }},
 | 
			
		||||
    { "uhsub16", 2, 6,     { 20, 27, 0x00000067, 4, 7, 0x00000007 }},
 | 
			
		||||
    { "uhaddsubx", 2, 6,   { 20, 27, 0x00000067, 4, 7, 0x00000003 }},
 | 
			
		||||
    { "uhadd8", 2, 6,      { 20, 27, 0x00000067, 4, 7, 0x00000009 }},
 | 
			
		||||
    { "uhadd16", 2, 6,     { 20, 27, 0x00000067, 4, 7, 0x00000001 }},
 | 
			
		||||
    { "uaddsubx", 2, 6,    { 20, 27, 0x00000065, 4, 7, 0x00000003 }},
 | 
			
		||||
    { "uadd8", 2, 6,       { 20, 27, 0x00000065, 4, 7, 0x00000009 }},
 | 
			
		||||
    { "uadd16", 2, 6,      { 20, 27, 0x00000065, 4, 7, 0x00000001 }},
 | 
			
		||||
    { "sxtah", 2, 6,       { 20, 27, 0x0000006b, 4, 7, 0x00000007 }},
 | 
			
		||||
    { "sxtab16", 2, 6,     { 20, 27, 0x00000068, 4, 7, 0x00000007 }},
 | 
			
		||||
    { "qadd8", 2, 6,       { 20, 27, 0x00000062, 4, 7, 0x00000009 }},
 | 
			
		||||
    { "bxj", 2, 5,         { 20, 27, 0x00000012, 4, 7, 0x00000002 }},
 | 
			
		||||
    { "clz", 2, 3,         { 20, 27, 0x00000016, 4, 7, 0x00000001 }},
 | 
			
		||||
    { "uxtah", 2, 6,       { 20, 27, 0x0000006f, 4, 7, 0x00000007 }},
 | 
			
		||||
    { "bx", 2, 2,          { 20, 27, 0x00000012, 4, 7, 0x00000001 }},
 | 
			
		||||
    { "rev", 2, 6,         { 20, 27, 0x0000006b, 4, 7, 0x00000003 }},
 | 
			
		||||
    { "blx", 2, 3,         { 20, 27, 0x00000012, 4, 7, 0x00000003 }},
 | 
			
		||||
    { "revsh", 2, 6,       { 20, 27, 0x0000006f, 4, 7, 0x0000000b }},
 | 
			
		||||
    { "qadd", 2, 4,        { 20, 27, 0x00000010, 4, 7, 0x00000005 }},
 | 
			
		||||
    { "qadd16", 2, 6,      { 20, 27, 0x00000062, 4, 7, 0x00000001 }},
 | 
			
		||||
    { "qaddsubx", 2, 6,    { 20, 27, 0x00000062, 4, 7, 0x00000003 }},
 | 
			
		||||
    { "ldrex", 2, 0,       { 20, 27, 0x00000019, 4, 7, 0x00000009 }},
 | 
			
		||||
    { "qdadd", 2, 4,       { 20, 27, 0x00000014, 4, 7, 0x00000005 }},
 | 
			
		||||
    { "qdsub", 2, 4,       { 20, 27, 0x00000016, 4, 7, 0x00000005 }},
 | 
			
		||||
    { "qsub", 2, 4,        { 20, 27, 0x00000012, 4, 7, 0x00000005 }},
 | 
			
		||||
    { "ldrexb", 2, 7,      { 20, 27, 0x0000001d, 4, 7, 0x00000009 }},
 | 
			
		||||
    { "qsub8", 2, 6,       { 20, 27, 0x00000062, 4, 7, 0x0000000f }},
 | 
			
		||||
    { "qsub16", 2, 6,      { 20, 27, 0x00000062, 4, 7, 0x00000007 }},
 | 
			
		||||
    { "smuad", 4, 6,       { 20, 27, 0x00000070, 12, 15, 0x0000000f, 6, 7, 0x00000000, 4, 4, 0x00000001 }},
 | 
			
		||||
    { "smmul", 4, 6,       { 20, 27, 0x00000075, 12, 15, 0x0000000f, 6, 7, 0x00000000, 4, 4, 0x00000001 }},
 | 
			
		||||
    { "smusd", 4, 6,       { 20, 27, 0x00000070, 12, 15, 0x0000000f, 6, 7, 0x00000001, 4, 4, 0x00000001 }},
 | 
			
		||||
    { "smlsd", 3, 6,       { 20, 27, 0x00000070, 6, 7, 0x00000001, 4, 4, 0x00000001 }},
 | 
			
		||||
    { "smlsld", 3, 6,      { 20, 27, 0x00000074, 6, 7, 0x00000001, 4, 4, 0x00000001 }},
 | 
			
		||||
    { "smmla", 3, 6,       { 20, 27, 0x00000075, 6, 7, 0x00000000, 4, 4, 0x00000001 }},
 | 
			
		||||
    { "smmls", 3, 6,       { 20, 27, 0x00000075, 6, 7, 0x00000003, 4, 4, 0x00000001 }},
 | 
			
		||||
    { "smlald", 3, 6,      { 20, 27, 0x00000074, 6, 7, 0x00000000, 4, 4, 0x00000001 }},
 | 
			
		||||
    { "smlad", 3, 6,       { 20, 27, 0x00000070, 6, 7, 0x00000000, 4, 4, 0x00000001 }},
 | 
			
		||||
    { "smlaw", 3, 4,       { 20, 27, 0x00000012, 7, 7, 0x00000001, 4, 5, 0x00000000 }},
 | 
			
		||||
    { "smulw", 3, 4,       { 20, 27, 0x00000012, 7, 7, 0x00000001, 4, 5, 0x00000002 }},
 | 
			
		||||
    { "pkhtb", 2, 6,       { 20, 27, 0x00000068, 4, 6, 0x00000005 }},
 | 
			
		||||
    { "pkhbt", 2, 6,       { 20, 27, 0x00000068, 4, 6, 0x00000001 }},
 | 
			
		||||
    { "smul", 3, 4,        { 20, 27, 0x00000016, 7, 7, 0x00000001, 4, 4, 0x00000000 }},
 | 
			
		||||
    { "smlalxy", 3, 4,     { 20, 27, 0x00000014, 7, 7, 0x00000001, 4, 4, 0x00000000 }},
 | 
			
		||||
    { "smla", 3, 4,        { 20, 27, 0x00000010, 7, 7, 0x00000001, 4, 4, 0x00000000 }},
 | 
			
		||||
    { "mcrr", 1, 6,        { 20, 27, 0x000000c4 }},
 | 
			
		||||
    { "mrrc", 1, 6,        { 20, 27, 0x000000c5 }},
 | 
			
		||||
    { "cmp", 2, 0,         { 26, 27, 0x00000000, 20, 24, 0x00000015 }},
 | 
			
		||||
    { "tst", 2, 0,         { 26, 27, 0x00000000, 20, 24, 0x00000011 }},
 | 
			
		||||
    { "teq", 2, 0,         { 26, 27, 0x00000000, 20, 24, 0x00000013 }},
 | 
			
		||||
    { "cmn", 2, 0,         { 26, 27, 0x00000000, 20, 24, 0x00000017 }},
 | 
			
		||||
    { "smull", 2, 0,       { 21, 27, 0x00000006, 4, 7, 0x00000009 }},
 | 
			
		||||
    { "umull", 2, 0,       { 21, 27, 0x00000004, 4, 7, 0x00000009 }},
 | 
			
		||||
    { "umlal", 2, 0,       { 21, 27, 0x00000005, 4, 7, 0x00000009 }},
 | 
			
		||||
    { "smlal", 2, 0,       { 21, 27, 0x00000007, 4, 7, 0x00000009 }},
 | 
			
		||||
    { "mul", 2, 0,         { 21, 27, 0x00000000, 4, 7, 0x00000009 }},
 | 
			
		||||
    { "mla", 2, 0,         { 21, 27, 0x00000001, 4, 7, 0x00000009 }},
 | 
			
		||||
    { "ssat", 2, 6,        { 21, 27, 0x00000035, 4, 5, 0x00000001 }},
 | 
			
		||||
    { "usat", 2, 6,        { 21, 27, 0x00000037, 4, 5, 0x00000001 }},
 | 
			
		||||
    { "mrs", 4, 0,         { 23, 27, 0x00000002, 20, 21, 0x00000000, 16, 19, 0x0000000f, 0, 11, 0x00000000 }},
 | 
			
		||||
    { "msr", 3, 0,         { 23, 27, 0x00000002, 20, 21, 0x00000002, 4, 7, 0x00000000 }},
 | 
			
		||||
    { "and", 2, 0,         { 26, 27, 0x00000000, 21, 24, 0x00000000 }},
 | 
			
		||||
    { "bic", 2, 0,         { 26, 27, 0x00000000, 21, 24, 0x0000000e }},
 | 
			
		||||
    { "ldm", 3, 0,         { 25, 27, 0x00000004, 20, 22, 0x00000005, 15, 15, 0x00000000 }},
 | 
			
		||||
    { "eor", 2, 0,         { 26, 27, 0x00000000, 21, 24, 0x00000001 }},
 | 
			
		||||
    { "add", 2, 0,         { 26, 27, 0x00000000, 21, 24, 0x00000004 }},
 | 
			
		||||
    { "rsb", 2, 0,         { 26, 27, 0x00000000, 21, 24, 0x00000003 }},
 | 
			
		||||
    { "rsc", 2, 0,         { 26, 27, 0x00000000, 21, 24, 0x00000007 }},
 | 
			
		||||
    { "sbc", 2, 0,         { 26, 27, 0x00000000, 21, 24, 0x00000006 }},
 | 
			
		||||
    { "adc", 2, 0,         { 26, 27, 0x00000000, 21, 24, 0x00000005 }},
 | 
			
		||||
    { "sub", 2, 0,         { 26, 27, 0x00000000, 21, 24, 0x00000002 }},
 | 
			
		||||
    { "orr", 2, 0,         { 26, 27, 0x00000000, 21, 24, 0x0000000c }},
 | 
			
		||||
    { "mvn", 2, 0,         { 26, 27, 0x00000000, 21, 24, 0x0000000f }},
 | 
			
		||||
    { "mov", 2, 0,         { 26, 27, 0x00000000, 21, 24, 0x0000000d }},
 | 
			
		||||
    { "stm", 2, 0,         { 25, 27, 0x00000004, 20, 22, 0x00000004 }},
 | 
			
		||||
    { "ldm", 4, 0,         { 25, 27, 0x00000004, 22, 22, 0x00000001, 20, 20, 0x00000001, 15, 15, 0x00000001 }},
 | 
			
		||||
    { "ldrsh", 3, 2,       { 25, 27, 0x00000000, 20, 20, 0x00000001, 4, 7, 0x0000000f }},
 | 
			
		||||
    { "stm", 3, 0,         { 25, 27, 0x00000004, 22, 22, 0x00000000, 20, 20, 0x00000000 }},
 | 
			
		||||
    { "ldm", 3, 0,         { 25, 27, 0x00000004, 22, 22, 0x00000000, 20, 20, 0x00000001 }},
 | 
			
		||||
    { "ldrsb", 3, 2,       { 25, 27, 0x00000000, 20, 20, 0x00000001, 4, 7, 0x0000000d }},
 | 
			
		||||
    { "strd", 3, 4,        { 25, 27, 0x00000000, 20, 20, 0x00000000, 4, 7, 0x0000000f }},
 | 
			
		||||
    { "ldrh", 3, 0,        { 25, 27, 0x00000000, 20, 20, 0x00000001, 4, 7, 0x0000000b }},
 | 
			
		||||
    { "strh", 3, 0,        { 25, 27, 0x00000000, 20, 20, 0x00000000, 4, 7, 0x0000000b }},
 | 
			
		||||
    { "ldrd", 3, 4,        { 25, 27, 0x00000000, 20, 20, 0x00000000, 4, 7, 0x0000000d }},
 | 
			
		||||
    { "strt", 3, 0,        { 26, 27, 0x00000001, 24, 24, 0x00000000, 20, 22, 0x00000002 }},
 | 
			
		||||
    { "strbt", 3, 0,       { 26, 27, 0x00000001, 24, 24, 0x00000000, 20, 22, 0x00000006 }},
 | 
			
		||||
    { "ldrbt", 3, 0,       { 26, 27, 0x00000001, 24, 24, 0x00000000, 20, 22, 0x00000007 }},
 | 
			
		||||
    { "ldrt", 3, 0,        { 26, 27, 0x00000001, 24, 24, 0x00000000, 20, 22, 0x00000003 }},
 | 
			
		||||
    { "mrc", 3, 6,         { 24, 27, 0x0000000e, 20, 20, 0x00000001, 4, 4, 0x00000001 }},
 | 
			
		||||
    { "mcr", 3, 0,         { 24, 27, 0x0000000e, 20, 20, 0x00000000, 4, 4, 0x00000001 }},
 | 
			
		||||
    { "msr", 3, 0,         { 23, 27, 0x00000006, 20, 21, 0x00000002, 22, 22, 0x00000001 }},
 | 
			
		||||
    { "msr", 4, 0,         { 23, 27, 0x00000006, 20, 21, 0x00000002, 22, 22, 0x00000000, 16, 19, 0x00000004 }},
 | 
			
		||||
    { "msr", 5, 0,         { 23, 27, 0x00000006, 20, 21, 0x00000002, 22, 22, 0x00000000, 19, 19, 0x00000001, 16, 17, 0x00000000 }},
 | 
			
		||||
    { "msr", 4, 0,         { 23, 27, 0x00000006, 20, 21, 0x00000002, 22, 22, 0x00000000, 16, 17, 0x00000001 }},
 | 
			
		||||
    { "msr", 4, 0,         { 23, 27, 0x00000006, 20, 21, 0x00000002, 22, 22, 0x00000000, 17, 17, 0x00000001 }},
 | 
			
		||||
    { "ldrb", 3, 0,        { 26, 27, 0x00000001, 22, 22, 0x00000001, 20, 20, 0x00000001 }},
 | 
			
		||||
    { "strb", 3, 0,        { 26, 27, 0x00000001, 22, 22, 0x00000001, 20, 20, 0x00000000 }},
 | 
			
		||||
    { "ldr", 4, 0,         { 28, 31, 0x0000000e, 26, 27, 0x00000001, 22, 22, 0x00000000, 20, 20, 0x00000001 }},
 | 
			
		||||
    { "ldrcond", 3, 0,     { 26, 27, 0x00000001, 22, 22, 0x00000000, 20, 20, 0x00000001 }},
 | 
			
		||||
    { "str", 3, 0,         { 26, 27, 0x00000001, 22, 22, 0x00000000, 20, 20, 0x00000000 }},
 | 
			
		||||
    { "cdp", 2, 0,         { 24, 27, 0x0000000e, 4, 4, 0x00000000 }},
 | 
			
		||||
    { "stc", 2, 0,         { 25, 27, 0x00000006, 20, 20, 0x00000000 }},
 | 
			
		||||
    { "ldc", 2, 0,         { 25, 27, 0x00000006, 20, 20, 0x00000001 }},
 | 
			
		||||
    { "ldrexd", 2, ARMV6K, { 20, 27, 0x0000001B, 4, 7, 0x00000009 }},
 | 
			
		||||
    { "strexd", 2, ARMV6K, { 20, 27, 0x0000001A, 4, 7, 0x00000009 }},
 | 
			
		||||
    { "ldrexh", 2, ARMV6K, { 20, 27, 0x0000001F, 4, 7, 0x00000009 }},
 | 
			
		||||
    { "strexh", 2, ARMV6K, { 20, 27, 0x0000001E, 4, 7, 0x00000009 }},
 | 
			
		||||
    { "nop", 5, ARMV6K,    { 23, 27, 0x00000006, 22, 22, 0x00000000, 20, 21, 0x00000002, 16, 19, 0x00000000, 0, 7, 0x00000000 }},
 | 
			
		||||
    { "yield", 5, ARMV6K,  { 23, 27, 0x00000006, 22, 22, 0x00000000, 20, 21, 0x00000002, 16, 19, 0x00000000, 0, 7, 0x00000001 }},
 | 
			
		||||
    { "wfe", 5, ARMV6K,    { 23, 27, 0x00000006, 22, 22, 0x00000000, 20, 21, 0x00000002, 16, 19, 0x00000000, 0, 7, 0x00000002 }},
 | 
			
		||||
    { "wfi", 5, ARMV6K,    { 23, 27, 0x00000006, 22, 22, 0x00000000, 20, 21, 0x00000002, 16, 19, 0x00000000, 0, 7, 0x00000003 }},
 | 
			
		||||
    { "sev", 5, ARMV6K,    { 23, 27, 0x00000006, 22, 22, 0x00000000, 20, 21, 0x00000002, 16, 19, 0x00000000, 0, 7, 0x00000004 }},
 | 
			
		||||
    { "swi", 1, 0,         { 24, 27, 0x0000000f }},
 | 
			
		||||
    { "bbl", 1, 0,         { 25, 27, 0x00000005 }},
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
const InstructionSetEncodingItem arm_exclusion_code[] = {
 | 
			
		||||
    { "vmla", 0, ARMVFP2,      { 0 }},
 | 
			
		||||
    { "vmls", 0, ARMVFP2,      { 0 }},
 | 
			
		||||
    { "vnmla", 0, ARMVFP2,     { 0 }},
 | 
			
		||||
    { "vnmls", 0, ARMVFP2,     { 0 }},
 | 
			
		||||
    { "vnmul", 0, ARMVFP2,     { 0 }},
 | 
			
		||||
    { "vmul", 0, ARMVFP2,      { 0 }},
 | 
			
		||||
    { "vadd", 0, ARMVFP2,      { 0 }},
 | 
			
		||||
    { "vsub", 0, ARMVFP2,      { 0 }},
 | 
			
		||||
    { "vdiv", 0, ARMVFP2,      { 0 }},
 | 
			
		||||
    { "vmov(i)", 0, ARMVFP3,   { 0 }},
 | 
			
		||||
    { "vmov(r)", 0, ARMVFP3,   { 0 }},
 | 
			
		||||
    { "vabs", 0, ARMVFP2,      { 0 }},
 | 
			
		||||
    { "vneg", 0, ARMVFP2,      { 0 }},
 | 
			
		||||
    { "vsqrt", 0, ARMVFP2,     { 0 }},
 | 
			
		||||
    { "vcmp", 0, ARMVFP2,      { 0 }},
 | 
			
		||||
    { "vcmp2", 0, ARMVFP2,     { 0 }},
 | 
			
		||||
    { "vcvt(bff)", 0, ARMVFP3, { 4, 4, 1 }},
 | 
			
		||||
    { "vcvt(bds)", 0, ARMVFP2, { 0 }},
 | 
			
		||||
    { "vcvt(bfi)", 0, ARMVFP2, { 0 }},
 | 
			
		||||
    { "vmovbrs", 0, ARMVFP2,   { 0 }},
 | 
			
		||||
    { "vmsr", 0, ARMVFP2,      { 0 }},
 | 
			
		||||
    { "vmovbrc", 0, ARMVFP2,   { 0 }},
 | 
			
		||||
    { "vmrs", 0, ARMVFP2,      { 0 }},
 | 
			
		||||
    { "vmovbcr", 0, ARMVFP2,   { 0 }},
 | 
			
		||||
    { "vmovbrrss", 0, ARMVFP2, { 0 }},
 | 
			
		||||
    { "vmovbrrd", 0, ARMVFP2,  { 0 }},
 | 
			
		||||
    { "vstr", 0, ARMVFP2,      { 0 }},
 | 
			
		||||
    { "vpush", 0, ARMVFP2,     { 0 }},
 | 
			
		||||
    { "vstm", 0, ARMVFP2,      { 0 }},
 | 
			
		||||
    { "vpop", 0, ARMVFP2,      { 0 }},
 | 
			
		||||
    { "vldr", 0, ARMVFP2,      { 0 }},
 | 
			
		||||
    { "vldm", 0, ARMVFP2,      { 0 }},
 | 
			
		||||
 | 
			
		||||
    { "srs", 0, 6,         { 0 }},
 | 
			
		||||
    { "rfe", 0, 6,         { 0 }},
 | 
			
		||||
    { "bkpt", 0, 3,        { 0 }},
 | 
			
		||||
    { "blx", 0, 3,         { 0 }},
 | 
			
		||||
    { "cps", 0, 6,         { 0 }},
 | 
			
		||||
    { "pld", 0, 4,         { 0 }},
 | 
			
		||||
    { "setend", 0, 6,      { 0 }},
 | 
			
		||||
    { "clrex", 0, 6,       { 0 }},
 | 
			
		||||
    { "rev16", 0, 6,       { 0 }},
 | 
			
		||||
    { "usad8", 0, 6,       { 0 }},
 | 
			
		||||
    { "sxtb", 0, 6,        { 0 }},
 | 
			
		||||
    { "uxtb", 0, 6,        { 0 }},
 | 
			
		||||
    { "sxth", 0, 6,        { 0 }},
 | 
			
		||||
    { "sxtb16", 0, 6,      { 0 }},
 | 
			
		||||
    { "uxth", 0, 6,        { 0 }},
 | 
			
		||||
    { "uxtb16", 0, 6,      { 0 }},
 | 
			
		||||
    { "cpy", 0, 6,         { 0 }},
 | 
			
		||||
    { "uxtab", 0, 6,       { 0 }},
 | 
			
		||||
    { "ssub8", 0, 6,       { 0 }},
 | 
			
		||||
    { "shsub8", 0, 6,      { 0 }},
 | 
			
		||||
    { "ssubaddx", 0, 6,    { 0 }},
 | 
			
		||||
    { "strex", 0, 6,       { 0 }},
 | 
			
		||||
    { "strexb", 0, 7,      { 0 }},
 | 
			
		||||
    { "swp", 0, 0,         { 0 }},
 | 
			
		||||
    { "swpb", 0, 0,        { 0 }},
 | 
			
		||||
    { "ssub16", 0, 6,      { 0 }},
 | 
			
		||||
    { "ssat16", 0, 6,      { 0 }},
 | 
			
		||||
    { "shsubaddx", 0, 6,   { 0 }},
 | 
			
		||||
    { "qsubaddx", 0, 6,    { 0 }},
 | 
			
		||||
    { "shaddsubx", 0, 6,   { 0 }},
 | 
			
		||||
    { "shadd8", 0, 6,      { 0 }},
 | 
			
		||||
    { "shadd16", 0, 6,     { 0 }},
 | 
			
		||||
    { "sel", 0, 6,         { 0 }},
 | 
			
		||||
    { "saddsubx", 0, 6,    { 0 }},
 | 
			
		||||
    { "sadd8", 0, 6,       { 0 }},
 | 
			
		||||
    { "sadd16", 0, 6,      { 0 }},
 | 
			
		||||
    { "shsub16", 0, 6,     { 0 }},
 | 
			
		||||
    { "umaal", 0, 6,       { 0 }},
 | 
			
		||||
    { "uxtab16", 0, 6,     { 0 }},
 | 
			
		||||
    { "usubaddx", 0, 6,    { 0 }},
 | 
			
		||||
    { "usub8", 0, 6,       { 0 }},
 | 
			
		||||
    { "usub16", 0, 6,      { 0 }},
 | 
			
		||||
    { "usat16", 0, 6,      { 0 }},
 | 
			
		||||
    { "usada8", 0, 6,      { 0 }},
 | 
			
		||||
    { "uqsubaddx", 0, 6,   { 0 }},
 | 
			
		||||
    { "uqsub8", 0, 6,      { 0 }},
 | 
			
		||||
    { "uqsub16", 0, 6,     { 0 }},
 | 
			
		||||
    { "uqaddsubx", 0, 6,   { 0 }},
 | 
			
		||||
    { "uqadd8", 0, 6,      { 0 }},
 | 
			
		||||
    { "uqadd16", 0, 6,     { 0 }},
 | 
			
		||||
    { "sxtab", 0, 6,       { 0 }},
 | 
			
		||||
    { "uhsubaddx", 0, 6,   { 0 }},
 | 
			
		||||
    { "uhsub8", 0, 6,      { 0 }},
 | 
			
		||||
    { "uhsub16", 0, 6,     { 0 }},
 | 
			
		||||
    { "uhaddsubx", 0, 6,   { 0 }},
 | 
			
		||||
    { "uhadd8", 0, 6,      { 0 }},
 | 
			
		||||
    { "uhadd16", 0, 6,     { 0 }},
 | 
			
		||||
    { "uaddsubx", 0, 6,    { 0 }},
 | 
			
		||||
    { "uadd8", 0, 6,       { 0 }},
 | 
			
		||||
    { "uadd16", 0, 6,      { 0 }},
 | 
			
		||||
    { "sxtah", 0, 6,       { 0 }},
 | 
			
		||||
    { "sxtab16", 0, 6,     { 0 }},
 | 
			
		||||
    { "qadd8", 0, 6,       { 0 }},
 | 
			
		||||
    { "bxj", 0, 5,         { 0 }},
 | 
			
		||||
    { "clz", 0, 3,         { 0 }},
 | 
			
		||||
    { "uxtah", 0, 6,       { 0 }},
 | 
			
		||||
    { "bx", 0, 2,          { 0 }},
 | 
			
		||||
    { "rev", 0, 6,         { 0 }},
 | 
			
		||||
    { "blx", 0, 3,         { 0 }},
 | 
			
		||||
    { "revsh", 0, 6,       { 0 }},
 | 
			
		||||
    { "qadd", 0, 4,        { 0 }},
 | 
			
		||||
    { "qadd16", 0, 6,      { 0 }},
 | 
			
		||||
    { "qaddsubx", 0, 6,    { 0 }},
 | 
			
		||||
    { "ldrex", 0, 0,       { 0 }},
 | 
			
		||||
    { "qdadd", 0, 4,       { 0 }},
 | 
			
		||||
    { "qdsub", 0, 4,       { 0 }},
 | 
			
		||||
    { "qsub", 0, 4,        { 0 }},
 | 
			
		||||
    { "ldrexb", 0, 7,      { 0 }},
 | 
			
		||||
    { "qsub8", 0, 6,       { 0 }},
 | 
			
		||||
    { "qsub16", 0, 6,      { 0 }},
 | 
			
		||||
    { "smuad", 0, 6,       { 0 }},
 | 
			
		||||
    { "smmul", 0, 6,       { 0 }},
 | 
			
		||||
    { "smusd", 0, 6,       { 0 }},
 | 
			
		||||
    { "smlsd", 0, 6,       { 0 }},
 | 
			
		||||
    { "smlsld", 0, 6,      { 0 }},
 | 
			
		||||
    { "smmla", 0, 6,       { 0 }},
 | 
			
		||||
    { "smmls", 0, 6,       { 0 }},
 | 
			
		||||
    { "smlald", 0, 6,      { 0 }},
 | 
			
		||||
    { "smlad", 0, 6,       { 0 }},
 | 
			
		||||
    { "smlaw", 0, 4,       { 0 }},
 | 
			
		||||
    { "smulw", 0, 4,       { 0 }},
 | 
			
		||||
    { "pkhtb", 0, 6,       { 0 }},
 | 
			
		||||
    { "pkhbt", 0, 6,       { 0 }},
 | 
			
		||||
    { "smul", 0, 4,        { 0 }},
 | 
			
		||||
    { "smlal", 0, 4,       { 0 }},
 | 
			
		||||
    { "smla", 0, 4,        { 0 }},
 | 
			
		||||
    { "mcrr", 0, 6,        { 0 }},
 | 
			
		||||
    { "mrrc", 0, 6,        { 0 }},
 | 
			
		||||
    { "cmp", 3, 0,         { 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000 }},
 | 
			
		||||
    { "tst", 3, 0,         { 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000 }},
 | 
			
		||||
    { "teq", 3, 0,         { 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000 }},
 | 
			
		||||
    { "cmn", 3, 0,         { 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000 }},
 | 
			
		||||
    { "smull", 0, 0,       { 0 }},
 | 
			
		||||
    { "umull", 0, 0,       { 0 }},
 | 
			
		||||
    { "umlal", 0, 0,       { 0 }},
 | 
			
		||||
    { "smlal", 0, 0,       { 0 }},
 | 
			
		||||
    { "mul", 0, 0,         { 0 }},
 | 
			
		||||
    { "mla", 0, 0,         { 0 }},
 | 
			
		||||
    { "ssat", 0, 6,        { 0 }},
 | 
			
		||||
    { "usat", 0, 6,        { 0 }},
 | 
			
		||||
    { "mrs", 0, 0,         { 0 }},
 | 
			
		||||
    { "msr", 0, 0,         { 0 }},
 | 
			
		||||
    { "and", 3, 0,         { 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000 }},
 | 
			
		||||
    { "bic", 3, 0,         { 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000 }},
 | 
			
		||||
    { "ldm", 0, 0,         { 0 }},
 | 
			
		||||
    { "eor", 3, 0,         { 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000 }},
 | 
			
		||||
    { "add", 3, 0,         { 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000 }},
 | 
			
		||||
    { "rsb", 3, 0,         { 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000 }},
 | 
			
		||||
    { "rsc", 3, 0,         { 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000 }},
 | 
			
		||||
    { "sbc", 3, 0,         { 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000 }},
 | 
			
		||||
    { "adc", 3, 0,         { 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000 }},
 | 
			
		||||
    { "sub", 3, 0,         { 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000 }},
 | 
			
		||||
    { "orr", 3, 0,         { 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000 }},
 | 
			
		||||
    { "mvn", 3, 0,         { 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000 }},
 | 
			
		||||
    { "mov", 3, 0,         { 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000 }},
 | 
			
		||||
    { "stm", 0, 0,         { 0 }},
 | 
			
		||||
    { "ldm", 0, 0,         { 0 }},
 | 
			
		||||
    { "ldrsh", 0, 2,       { 0 }},
 | 
			
		||||
    { "stm", 0, 0,         { 0 }},
 | 
			
		||||
    { "ldm", 0, 0,         { 0 }},
 | 
			
		||||
    { "ldrsb", 0, 2,       { 0 }},
 | 
			
		||||
    { "strd", 0, 4,        { 0 }},
 | 
			
		||||
    { "ldrh", 0, 0,        { 0 }},
 | 
			
		||||
    { "strh", 0, 0,        { 0 }},
 | 
			
		||||
    { "ldrd", 0, 4,        { 0 }},
 | 
			
		||||
    { "strt", 0, 0,        { 0 }},
 | 
			
		||||
    { "strbt", 0, 0,       { 0 }},
 | 
			
		||||
    { "ldrbt", 0, 0,       { 0 }},
 | 
			
		||||
    { "ldrt", 0, 0,        { 0 }},
 | 
			
		||||
    { "mrc", 0, 6,         { 0 }},
 | 
			
		||||
    { "mcr", 0, 0,         { 0 }},
 | 
			
		||||
    { "msr", 0, 0,         { 0 }},
 | 
			
		||||
    { "msr", 0, 0,         { 0 }},
 | 
			
		||||
    { "msr", 0, 0,         { 0 }},
 | 
			
		||||
    { "msr", 0, 0,         { 0 }},
 | 
			
		||||
    { "msr", 0, 0,         { 0 }},
 | 
			
		||||
    { "ldrb", 0, 0,        { 0 }},
 | 
			
		||||
    { "strb", 0, 0,        { 0 }},
 | 
			
		||||
    { "ldr", 0, 0,         { 0 }},
 | 
			
		||||
    { "ldrcond", 1, 0,     { 28, 31, 0x0000000e }},
 | 
			
		||||
    { "str", 0, 0,         { 0 }},
 | 
			
		||||
    { "cdp", 0, 0,         { 0 }},
 | 
			
		||||
    { "stc", 0, 0,         { 0 }},
 | 
			
		||||
    { "ldc", 0, 0,         { 0 }},
 | 
			
		||||
    { "ldrexd", 0, ARMV6K, { 0 }},
 | 
			
		||||
    { "strexd", 0, ARMV6K, { 0 }},
 | 
			
		||||
    { "ldrexh", 0, ARMV6K, { 0 }},
 | 
			
		||||
    { "strexh", 0, ARMV6K, { 0 }},
 | 
			
		||||
    { "nop", 0, ARMV6K,    { 0 }},
 | 
			
		||||
    { "yield", 0, ARMV6K,  { 0 }},
 | 
			
		||||
    { "wfe", 0, ARMV6K,    { 0 }},
 | 
			
		||||
    { "wfi", 0, ARMV6K,    { 0 }},
 | 
			
		||||
    { "sev", 0, ARMV6K,    { 0 }},
 | 
			
		||||
    { "swi", 0, 0,         { 0 }},
 | 
			
		||||
    { "bbl", 0, 0,         { 0 }},
 | 
			
		||||
 | 
			
		||||
    { "bl_1_thumb", 0, INVALID,  { 0 }}, // Should be table[-4]
 | 
			
		||||
    { "bl_2_thumb", 0, INVALID,  { 0 }}, // Should be located at the end of the table[-3]
 | 
			
		||||
    { "blx_1_thumb", 0, INVALID, { 0 }}, // Should be located at table[-2]
 | 
			
		||||
    { "invalid", 0, INVALID,     { 0 }}
 | 
			
		||||
};
 | 
			
		||||
// clang-format on
 | 
			
		||||
 | 
			
		||||
ARMDecodeStatus DecodeARMInstruction(u32 instr, int* idx) {
 | 
			
		||||
    int n = 0;
 | 
			
		||||
    int base = 0;
 | 
			
		||||
    int instr_slots = sizeof(arm_instruction) / sizeof(InstructionSetEncodingItem);
 | 
			
		||||
    ARMDecodeStatus ret = ARMDecodeStatus::FAILURE;
 | 
			
		||||
 | 
			
		||||
    for (int i = 0; i < instr_slots; i++) {
 | 
			
		||||
        n = arm_instruction[i].attribute_value;
 | 
			
		||||
        base = 0;
 | 
			
		||||
 | 
			
		||||
        // 3DS has no VFP3 support
 | 
			
		||||
        if (arm_instruction[i].version == ARMVFP3)
 | 
			
		||||
            continue;
 | 
			
		||||
 | 
			
		||||
        while (n) {
 | 
			
		||||
            if (arm_instruction[i].content[base + 1] == 31 &&
 | 
			
		||||
                arm_instruction[i].content[base] == 0) {
 | 
			
		||||
                // clrex
 | 
			
		||||
                if (instr != arm_instruction[i].content[base + 2]) {
 | 
			
		||||
                    break;
 | 
			
		||||
                }
 | 
			
		||||
            } else if (BITS(instr, arm_instruction[i].content[base],
 | 
			
		||||
                            arm_instruction[i].content[base + 1]) !=
 | 
			
		||||
                       arm_instruction[i].content[base + 2]) {
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            base += 3;
 | 
			
		||||
            n--;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // All conditions are satisfied.
 | 
			
		||||
        if (n == 0)
 | 
			
		||||
            ret = ARMDecodeStatus::SUCCESS;
 | 
			
		||||
 | 
			
		||||
        if (ret == ARMDecodeStatus::SUCCESS) {
 | 
			
		||||
            n = arm_exclusion_code[i].attribute_value;
 | 
			
		||||
            if (n != 0) {
 | 
			
		||||
                base = 0;
 | 
			
		||||
                while (n) {
 | 
			
		||||
                    if (BITS(instr, arm_exclusion_code[i].content[base],
 | 
			
		||||
                             arm_exclusion_code[i].content[base + 1]) !=
 | 
			
		||||
                        arm_exclusion_code[i].content[base + 2]) {
 | 
			
		||||
                        break;
 | 
			
		||||
                    }
 | 
			
		||||
                    base += 3;
 | 
			
		||||
                    n--;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                // All conditions are satisfied.
 | 
			
		||||
                if (n == 0)
 | 
			
		||||
                    ret = ARMDecodeStatus::FAILURE;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (ret == ARMDecodeStatus::SUCCESS) {
 | 
			
		||||
            *idx = i;
 | 
			
		||||
            return ret;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
@ -1,36 +0,0 @@
 | 
			
		||||
// Copyright 2012 Michael Kang, 2015 Citra Emulator Project
 | 
			
		||||
// Licensed under GPLv2 or any later version
 | 
			
		||||
// Refer to the license.txt file included.
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "common/common_types.h"
 | 
			
		||||
 | 
			
		||||
enum class ARMDecodeStatus { SUCCESS, FAILURE };
 | 
			
		||||
 | 
			
		||||
ARMDecodeStatus DecodeARMInstruction(u32 instr, int* idx);
 | 
			
		||||
 | 
			
		||||
struct InstructionSetEncodingItem {
 | 
			
		||||
    const char* name;
 | 
			
		||||
    int attribute_value;
 | 
			
		||||
    int version;
 | 
			
		||||
    u32 content[21];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// ARM versions
 | 
			
		||||
enum {
 | 
			
		||||
    INVALID = 0,
 | 
			
		||||
    ARMALL,
 | 
			
		||||
    ARMV4,
 | 
			
		||||
    ARMV4T,
 | 
			
		||||
    ARMV5T,
 | 
			
		||||
    ARMV5TE,
 | 
			
		||||
    ARMV5TEJ,
 | 
			
		||||
    ARMV6,
 | 
			
		||||
    ARM1176JZF_S,
 | 
			
		||||
    ARMVFP2,
 | 
			
		||||
    ARMVFP3,
 | 
			
		||||
    ARMV6K,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
extern const InstructionSetEncodingItem arm_instruction[];
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@ -1,9 +0,0 @@
 | 
			
		||||
// Copyright 2014 Citra Emulator Project
 | 
			
		||||
// Licensed under GPLv2 or any later version
 | 
			
		||||
// Refer to the license.txt file included.
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
struct ARMul_State;
 | 
			
		||||
 | 
			
		||||
unsigned InterpreterMainLoop(ARMul_State* state);
 | 
			
		||||
@ -1,48 +0,0 @@
 | 
			
		||||
/* Copyright (C)
 | 
			
		||||
* 2011 - Michael.Kang blackfin.kang@gmail.com
 | 
			
		||||
* This program is free software; you can redistribute it and/or
 | 
			
		||||
* modify it under the terms of the GNU General Public License
 | 
			
		||||
* as published by the Free Software Foundation; either version 2
 | 
			
		||||
* of the License, or (at your option) any later version.
 | 
			
		||||
*
 | 
			
		||||
* This program is distributed in the hope that it will be useful,
 | 
			
		||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
* GNU General Public License for more details.
 | 
			
		||||
*
 | 
			
		||||
* You should have received a copy of the GNU General Public License
 | 
			
		||||
* along with this program; if not, write to the Free Software
 | 
			
		||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 | 
			
		||||
*
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "core/arm/skyeye_common/armstate.h"
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Checks if the PC is being read, and if so, word-aligns it.
 | 
			
		||||
 * Used with address calculations.
 | 
			
		||||
 *
 | 
			
		||||
 * @param cpu The ARM CPU state instance.
 | 
			
		||||
 * @param Rn   The register being read.
 | 
			
		||||
 *
 | 
			
		||||
 * @return If the PC is being read, then the word-aligned PC value is returned.
 | 
			
		||||
 *         If the PC is not being read, then the value stored in the register is returned.
 | 
			
		||||
 */
 | 
			
		||||
inline u32 CHECK_READ_REG15_WA(const ARMul_State* cpu, int Rn) {
 | 
			
		||||
    return (Rn == 15) ? ((cpu->Reg[15] & ~0x3) + cpu->GetInstructionSize() * 2) : cpu->Reg[Rn];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Reads the PC. Used for data processing operations that use the PC.
 | 
			
		||||
 *
 | 
			
		||||
 * @param cpu The ARM CPU state instance.
 | 
			
		||||
 * @param Rn   The register being read.
 | 
			
		||||
 *
 | 
			
		||||
 * @return If the PC is being read, then the incremented PC value is returned.
 | 
			
		||||
 *         If the PC is not being read, then the values stored in the register is returned.
 | 
			
		||||
 */
 | 
			
		||||
inline u32 CHECK_READ_REG15(const ARMul_State* cpu, int Rn) {
 | 
			
		||||
    return (Rn == 15) ? ((cpu->Reg[15] & ~0x1) + cpu->GetInstructionSize() * 2) : cpu->Reg[Rn];
 | 
			
		||||
}
 | 
			
		||||
@ -1,390 +0,0 @@
 | 
			
		||||
// Copyright 2012 Michael Kang, 2014 Citra Emulator Project
 | 
			
		||||
// Licensed under GPLv2 or any later version
 | 
			
		||||
// Refer to the license.txt file included.
 | 
			
		||||
 | 
			
		||||
#include <cstddef>
 | 
			
		||||
 | 
			
		||||
// We can provide simple Thumb simulation by decoding the Thumb instruction into its corresponding
 | 
			
		||||
// ARM instruction, and using the existing ARM simulator.
 | 
			
		||||
 | 
			
		||||
#include "core/arm/dyncom/arm_dyncom_thumb.h"
 | 
			
		||||
#include "core/arm/skyeye_common/armsupp.h"
 | 
			
		||||
 | 
			
		||||
// Decode a 16bit Thumb instruction.  The instruction is in the low 16-bits of the tinstr field,
 | 
			
		||||
// with the following Thumb instruction held in the high 16-bits.  Passing in two Thumb instructions
 | 
			
		||||
// allows easier simulation of the special dual BL instruction.
 | 
			
		||||
 | 
			
		||||
ThumbDecodeStatus TranslateThumbInstruction(u32 addr, u32 instr, u32* ainstr, u32* inst_size) {
 | 
			
		||||
    ThumbDecodeStatus valid = ThumbDecodeStatus::UNINITIALIZED;
 | 
			
		||||
    u32 tinstr = GetThumbInstruction(instr, addr);
 | 
			
		||||
 | 
			
		||||
    *ainstr = 0xDEADC0DE; // Debugging to catch non updates
 | 
			
		||||
 | 
			
		||||
    switch ((tinstr & 0xF800) >> 11) {
 | 
			
		||||
    case 0:                                         // LSL
 | 
			
		||||
    case 1:                                         // LSR
 | 
			
		||||
    case 2:                                         // ASR
 | 
			
		||||
        *ainstr = 0xE1B00000                        // base opcode
 | 
			
		||||
                  | ((tinstr & 0x1800) >> (11 - 5)) // shift type
 | 
			
		||||
                  | ((tinstr & 0x07C0) << (7 - 6))  // imm5
 | 
			
		||||
                  | ((tinstr & 0x0038) >> 3)        // Rs
 | 
			
		||||
                  | ((tinstr & 0x0007) << 12);      // Rd
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
    case 3: // ADD/SUB
 | 
			
		||||
    {
 | 
			
		||||
        static const u32 subset[4] = {
 | 
			
		||||
            0xE0900000, // ADDS Rd,Rs,Rn
 | 
			
		||||
            0xE0500000, // SUBS Rd,Rs,Rn
 | 
			
		||||
            0xE2900000, // ADDS Rd,Rs,#imm3
 | 
			
		||||
            0xE2500000  // SUBS Rd,Rs,#imm3
 | 
			
		||||
        };
 | 
			
		||||
        // It is quicker indexing into a table, than performing switch or conditionals:
 | 
			
		||||
        *ainstr = subset[(tinstr & 0x0600) >> 9]     // base opcode
 | 
			
		||||
                  | ((tinstr & 0x01C0) >> 6)         // Rn or imm3
 | 
			
		||||
                  | ((tinstr & 0x0038) << (16 - 3))  // Rs
 | 
			
		||||
                  | ((tinstr & 0x0007) << (12 - 0)); // Rd
 | 
			
		||||
    } break;
 | 
			
		||||
 | 
			
		||||
    case 4: // MOV
 | 
			
		||||
    case 5: // CMP
 | 
			
		||||
    case 6: // ADD
 | 
			
		||||
    case 7: // SUB
 | 
			
		||||
    {
 | 
			
		||||
        static const u32 subset[4] = {
 | 
			
		||||
            0xE3B00000, // MOVS Rd,#imm8
 | 
			
		||||
            0xE3500000, // CMP  Rd,#imm8
 | 
			
		||||
            0xE2900000, // ADDS Rd,Rd,#imm8
 | 
			
		||||
            0xE2500000, // SUBS Rd,Rd,#imm8
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        *ainstr = subset[(tinstr & 0x1800) >> 11]    // base opcode
 | 
			
		||||
                  | ((tinstr & 0x00FF) >> 0)         // imm8
 | 
			
		||||
                  | ((tinstr & 0x0700) << (16 - 8))  // Rn
 | 
			
		||||
                  | ((tinstr & 0x0700) << (12 - 8)); // Rd
 | 
			
		||||
    } break;
 | 
			
		||||
 | 
			
		||||
    case 8: // Arithmetic and high register transfers
 | 
			
		||||
 | 
			
		||||
        // TODO: Since the subsets for both Format 4 and Format 5 instructions are made up of
 | 
			
		||||
        // different ARM encodings, we could save the following conditional, and just have one
 | 
			
		||||
        // large subset
 | 
			
		||||
 | 
			
		||||
        if ((tinstr & (1 << 10)) == 0) {
 | 
			
		||||
            enum otype { t_norm, t_shift, t_neg, t_mul };
 | 
			
		||||
 | 
			
		||||
            static const struct {
 | 
			
		||||
                u32 opcode;
 | 
			
		||||
                otype type;
 | 
			
		||||
            } subset[16] = {
 | 
			
		||||
                {0xE0100000, t_norm},  // ANDS Rd,Rd,Rs
 | 
			
		||||
                {0xE0300000, t_norm},  // EORS Rd,Rd,Rs
 | 
			
		||||
                {0xE1B00010, t_shift}, // MOVS Rd,Rd,LSL Rs
 | 
			
		||||
                {0xE1B00030, t_shift}, // MOVS Rd,Rd,LSR Rs
 | 
			
		||||
                {0xE1B00050, t_shift}, // MOVS Rd,Rd,ASR Rs
 | 
			
		||||
                {0xE0B00000, t_norm},  // ADCS Rd,Rd,Rs
 | 
			
		||||
                {0xE0D00000, t_norm},  // SBCS Rd,Rd,Rs
 | 
			
		||||
                {0xE1B00070, t_shift}, // MOVS Rd,Rd,ROR Rs
 | 
			
		||||
                {0xE1100000, t_norm},  // TST  Rd,Rs
 | 
			
		||||
                {0xE2700000, t_neg},   // RSBS Rd,Rs,#0
 | 
			
		||||
                {0xE1500000, t_norm},  // CMP  Rd,Rs
 | 
			
		||||
                {0xE1700000, t_norm},  // CMN  Rd,Rs
 | 
			
		||||
                {0xE1900000, t_norm},  // ORRS Rd,Rd,Rs
 | 
			
		||||
                {0xE0100090, t_mul},   // MULS Rd,Rd,Rs
 | 
			
		||||
                {0xE1D00000, t_norm},  // BICS Rd,Rd,Rs
 | 
			
		||||
                {0xE1F00000, t_norm}   // MVNS Rd,Rs
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            *ainstr = subset[(tinstr & 0x03C0) >> 6].opcode; // base
 | 
			
		||||
 | 
			
		||||
            switch (subset[(tinstr & 0x03C0) >> 6].type) {
 | 
			
		||||
            case t_norm:
 | 
			
		||||
                *ainstr |= ((tinstr & 0x0007) << 16)   // Rn
 | 
			
		||||
                           | ((tinstr & 0x0007) << 12) // Rd
 | 
			
		||||
                           | ((tinstr & 0x0038) >> 3); // Rs
 | 
			
		||||
                break;
 | 
			
		||||
            case t_shift:
 | 
			
		||||
                *ainstr |= ((tinstr & 0x0007) << 12)         // Rd
 | 
			
		||||
                           | ((tinstr & 0x0007) >> 0)        // Rm
 | 
			
		||||
                           | ((tinstr & 0x0038) << (8 - 3)); // Rs
 | 
			
		||||
                break;
 | 
			
		||||
            case t_neg:
 | 
			
		||||
                *ainstr |= ((tinstr & 0x0007) << 12)          // Rd
 | 
			
		||||
                           | ((tinstr & 0x0038) << (16 - 3)); // Rn
 | 
			
		||||
                break;
 | 
			
		||||
            case t_mul:
 | 
			
		||||
                *ainstr |= ((tinstr & 0x0007) << 16)   // Rd
 | 
			
		||||
                           | ((tinstr & 0x0007) << 8)  // Rs
 | 
			
		||||
                           | ((tinstr & 0x0038) >> 3); // Rm
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            u32 Rd = ((tinstr & 0x0007) >> 0);
 | 
			
		||||
            u32 Rs = ((tinstr & 0x0078) >> 3);
 | 
			
		||||
 | 
			
		||||
            if (tinstr & (1 << 7))
 | 
			
		||||
                Rd += 8;
 | 
			
		||||
 | 
			
		||||
            switch ((tinstr & 0x03C0) >> 6) {
 | 
			
		||||
            case 0x0:                  // ADD Rd,Rd,Rs
 | 
			
		||||
            case 0x1:                  // ADD Rd,Rd,Hs
 | 
			
		||||
            case 0x2:                  // ADD Hd,Hd,Rs
 | 
			
		||||
            case 0x3:                  // ADD Hd,Hd,Hs
 | 
			
		||||
                *ainstr = 0xE0800000   // base
 | 
			
		||||
                          | (Rd << 16) // Rn
 | 
			
		||||
                          | (Rd << 12) // Rd
 | 
			
		||||
                          | (Rs << 0); // Rm
 | 
			
		||||
                break;
 | 
			
		||||
            case 0x4:                  // CMP Rd,Rs
 | 
			
		||||
            case 0x5:                  // CMP Rd,Hs
 | 
			
		||||
            case 0x6:                  // CMP Hd,Rs
 | 
			
		||||
            case 0x7:                  // CMP Hd,Hs
 | 
			
		||||
                *ainstr = 0xE1500000   // base
 | 
			
		||||
                          | (Rd << 16) // Rn
 | 
			
		||||
                          | (Rs << 0); // Rm
 | 
			
		||||
                break;
 | 
			
		||||
            case 0x8:                  // MOV Rd,Rs
 | 
			
		||||
            case 0x9:                  // MOV Rd,Hs
 | 
			
		||||
            case 0xA:                  // MOV Hd,Rs
 | 
			
		||||
            case 0xB:                  // MOV Hd,Hs
 | 
			
		||||
                *ainstr = 0xE1A00000   // base
 | 
			
		||||
                          | (Rd << 12) // Rd
 | 
			
		||||
                          | (Rs << 0); // Rm
 | 
			
		||||
                break;
 | 
			
		||||
            case 0xC:                                 // BX Rs
 | 
			
		||||
            case 0xD:                                 // BX Hs
 | 
			
		||||
                *ainstr = 0xE12FFF10                  // base
 | 
			
		||||
                          | ((tinstr & 0x0078) >> 3); // Rd
 | 
			
		||||
                break;
 | 
			
		||||
            case 0xE:                  // BLX
 | 
			
		||||
            case 0xF:                  // BLX
 | 
			
		||||
                *ainstr = 0xE1200030   // base
 | 
			
		||||
                          | (Rs << 0); // Rm
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
    case 9:                                         // LDR Rd,[PC,#imm8]
 | 
			
		||||
        *ainstr = 0xE59F0000                        // base
 | 
			
		||||
                  | ((tinstr & 0x0700) << (12 - 8)) // Rd
 | 
			
		||||
                  | ((tinstr & 0x00FF) << (2 - 0)); // off8
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
    case 10:
 | 
			
		||||
    case 11: {
 | 
			
		||||
        static const u32 subset[8] = {
 | 
			
		||||
            0xE7800000, // STR   Rd,[Rb,Ro]
 | 
			
		||||
            0xE18000B0, // STRH  Rd,[Rb,Ro]
 | 
			
		||||
            0xE7C00000, // STRB  Rd,[Rb,Ro]
 | 
			
		||||
            0xE19000D0, // LDRSB Rd,[Rb,Ro]
 | 
			
		||||
            0xE7900000, // LDR   Rd,[Rb,Ro]
 | 
			
		||||
            0xE19000B0, // LDRH  Rd,[Rb,Ro]
 | 
			
		||||
            0xE7D00000, // LDRB  Rd,[Rb,Ro]
 | 
			
		||||
            0xE19000F0  // LDRSH Rd,[Rb,Ro]
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        *ainstr = subset[(tinstr & 0xE00) >> 9]     // base
 | 
			
		||||
                  | ((tinstr & 0x0007) << (12 - 0)) // Rd
 | 
			
		||||
                  | ((tinstr & 0x0038) << (16 - 3)) // Rb
 | 
			
		||||
                  | ((tinstr & 0x01C0) >> 6);       // Ro
 | 
			
		||||
    } break;
 | 
			
		||||
 | 
			
		||||
    case 12: // STR Rd,[Rb,#imm5]
 | 
			
		||||
    case 13: // LDR Rd,[Rb,#imm5]
 | 
			
		||||
    case 14: // STRB Rd,[Rb,#imm5]
 | 
			
		||||
    case 15: // LDRB Rd,[Rb,#imm5]
 | 
			
		||||
    {
 | 
			
		||||
        static const u32 subset[4] = {
 | 
			
		||||
            0xE5800000, // STR  Rd,[Rb,#imm5]
 | 
			
		||||
            0xE5900000, // LDR  Rd,[Rb,#imm5]
 | 
			
		||||
            0xE5C00000, // STRB Rd,[Rb,#imm5]
 | 
			
		||||
            0xE5D00000  // LDRB Rd,[Rb,#imm5]
 | 
			
		||||
        };
 | 
			
		||||
        // The offset range defends on whether we are transferring a byte or word value:
 | 
			
		||||
        *ainstr = subset[(tinstr & 0x1800) >> 11]                                // base
 | 
			
		||||
                  | ((tinstr & 0x0007) << (12 - 0))                              // Rd
 | 
			
		||||
                  | ((tinstr & 0x0038) << (16 - 3))                              // Rb
 | 
			
		||||
                  | ((tinstr & 0x07C0) >> (6 - ((tinstr & (1 << 12)) ? 0 : 2))); // off5
 | 
			
		||||
    } break;
 | 
			
		||||
 | 
			
		||||
    case 16:                                        // STRH Rd,[Rb,#imm5]
 | 
			
		||||
    case 17:                                        // LDRH Rd,[Rb,#imm5]
 | 
			
		||||
        *ainstr = ((tinstr & (1 << 11))             // base
 | 
			
		||||
                       ? 0xE1D000B0                 // LDRH
 | 
			
		||||
                       : 0xE1C000B0)                // STRH
 | 
			
		||||
                  | ((tinstr & 0x0007) << (12 - 0)) // Rd
 | 
			
		||||
                  | ((tinstr & 0x0038) << (16 - 3)) // Rb
 | 
			
		||||
                  | ((tinstr & 0x01C0) >> (6 - 1))  // off5, low nibble
 | 
			
		||||
                  | ((tinstr & 0x0600) >> (9 - 8)); // off5, high nibble
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
    case 18:                                        // STR Rd,[SP,#imm8]
 | 
			
		||||
    case 19:                                        // LDR Rd,[SP,#imm8]
 | 
			
		||||
        *ainstr = ((tinstr & (1 << 11))             // base
 | 
			
		||||
                       ? 0xE59D0000                 // LDR
 | 
			
		||||
                       : 0xE58D0000)                // STR
 | 
			
		||||
                  | ((tinstr & 0x0700) << (12 - 8)) // Rd
 | 
			
		||||
                  | ((tinstr & 0x00FF) << 2);       // off8
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
    case 20: // ADD Rd,PC,#imm8
 | 
			
		||||
    case 21: // ADD Rd,SP,#imm8
 | 
			
		||||
 | 
			
		||||
        if ((tinstr & (1 << 11)) == 0) {
 | 
			
		||||
 | 
			
		||||
            // NOTE: The PC value used here should by word aligned. We encode shift-left-by-2 in the
 | 
			
		||||
            // rotate immediate field, so no shift of off8 is needed.
 | 
			
		||||
 | 
			
		||||
            *ainstr = 0xE28F0F00                        // base
 | 
			
		||||
                      | ((tinstr & 0x0700) << (12 - 8)) // Rd
 | 
			
		||||
                      | (tinstr & 0x00FF);              // off8
 | 
			
		||||
        } else {
 | 
			
		||||
            // We encode shift-left-by-2 in the rotate immediate field, so no shift of off8 is
 | 
			
		||||
            // needed.
 | 
			
		||||
            *ainstr = 0xE28D0F00                        // base
 | 
			
		||||
                      | ((tinstr & 0x0700) << (12 - 8)) // Rd
 | 
			
		||||
                      | (tinstr & 0x00FF);              // off8
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
    case 22:
 | 
			
		||||
    case 23:
 | 
			
		||||
        if ((tinstr & 0x0F00) == 0x0000) {
 | 
			
		||||
            // NOTE: The instruction contains a shift left of 2 equivalent (implemented as ROR #30):
 | 
			
		||||
            *ainstr = ((tinstr & (1 << 7)) // base
 | 
			
		||||
                           ? 0xE24DDF00    // SUB
 | 
			
		||||
                           : 0xE28DDF00)   // ADD
 | 
			
		||||
                      | (tinstr & 0x007F); // off7
 | 
			
		||||
        } else if ((tinstr & 0x0F00) == 0x0e00) {
 | 
			
		||||
            // BKPT
 | 
			
		||||
            *ainstr = 0xEF000000                   // base
 | 
			
		||||
                      | BITS(tinstr, 0, 3)         // imm4 field;
 | 
			
		||||
                      | (BITS(tinstr, 4, 7) << 8); // beginning 4 bits of imm12
 | 
			
		||||
        } else if ((tinstr & 0x0F00) == 0x0200) {
 | 
			
		||||
            static const u32 subset[4] = {
 | 
			
		||||
                0xE6BF0070, // SXTH
 | 
			
		||||
                0xE6AF0070, // SXTB
 | 
			
		||||
                0xE6FF0070, // UXTH
 | 
			
		||||
                0xE6EF0070, // UXTB
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            *ainstr = subset[BITS(tinstr, 6, 7)]   // base
 | 
			
		||||
                      | (BITS(tinstr, 0, 2) << 12) // Rd
 | 
			
		||||
                      | BITS(tinstr, 3, 5);        // Rm
 | 
			
		||||
        } else if ((tinstr & 0x0F00) == 0x600) {
 | 
			
		||||
            if (BIT(tinstr, 5) == 0) {
 | 
			
		||||
                // SETEND
 | 
			
		||||
                *ainstr = 0xF1010000               // base
 | 
			
		||||
                          | (BIT(tinstr, 3) << 9); // endian specifier
 | 
			
		||||
            } else {
 | 
			
		||||
                // CPS
 | 
			
		||||
                *ainstr = 0xF1080000                // base
 | 
			
		||||
                          | (BIT(tinstr, 0) << 6)   // fiq bit
 | 
			
		||||
                          | (BIT(tinstr, 1) << 7)   // irq bit
 | 
			
		||||
                          | (BIT(tinstr, 2) << 8)   // abort bit
 | 
			
		||||
                          | (BIT(tinstr, 4) << 18); // enable bit
 | 
			
		||||
            }
 | 
			
		||||
        } else if ((tinstr & 0x0F00) == 0x0a00) {
 | 
			
		||||
            static const u32 subset[4] = {
 | 
			
		||||
                0xE6BF0F30, // REV
 | 
			
		||||
                0xE6BF0FB0, // REV16
 | 
			
		||||
                0,          // undefined
 | 
			
		||||
                0xE6FF0FB0, // REVSH
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            size_t subset_index = BITS(tinstr, 6, 7);
 | 
			
		||||
 | 
			
		||||
            if (subset_index == 2) {
 | 
			
		||||
                valid = ThumbDecodeStatus::UNDEFINED;
 | 
			
		||||
            } else {
 | 
			
		||||
                *ainstr = subset[subset_index]         // base
 | 
			
		||||
                          | (BITS(tinstr, 0, 2) << 12) // Rd
 | 
			
		||||
                          | BITS(tinstr, 3, 5);        // Rm
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            static const u32 subset[4] = {
 | 
			
		||||
                0xE92D0000, // STMDB sp!,{rlist}
 | 
			
		||||
                0xE92D4000, // STMDB sp!,{rlist,lr}
 | 
			
		||||
                0xE8BD0000, // LDMIA sp!,{rlist}
 | 
			
		||||
                0xE8BD8000  // LDMIA sp!,{rlist,pc}
 | 
			
		||||
            };
 | 
			
		||||
            *ainstr = subset[((tinstr & (1 << 11)) >> 10) | ((tinstr & (1 << 8)) >> 8)] // base
 | 
			
		||||
                      | (tinstr & 0x00FF);                                              // mask8
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
    case 24: //  STMIA
 | 
			
		||||
    case 25: //  LDMIA
 | 
			
		||||
        if (tinstr & (1 << 11)) {
 | 
			
		||||
            unsigned int base = 0xE8900000;
 | 
			
		||||
            unsigned int rn = BITS(tinstr, 8, 10);
 | 
			
		||||
 | 
			
		||||
            // Writeback
 | 
			
		||||
            if ((tinstr & (1 << rn)) == 0)
 | 
			
		||||
                base |= (1 << 21);
 | 
			
		||||
 | 
			
		||||
            *ainstr = base                 // base (LDMIA)
 | 
			
		||||
                      | (rn << 16)         // Rn
 | 
			
		||||
                      | (tinstr & 0x00FF); // Register list
 | 
			
		||||
        } else {
 | 
			
		||||
            *ainstr = 0xE8A00000                    // base (STMIA)
 | 
			
		||||
                      | (BITS(tinstr, 8, 10) << 16) // Rn
 | 
			
		||||
                      | (tinstr & 0x00FF);          // Register list
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
    case 26: // Bcc
 | 
			
		||||
    case 27: // Bcc/SWI
 | 
			
		||||
        if ((tinstr & 0x0F00) == 0x0F00) {
 | 
			
		||||
            // Format 17 : SWI
 | 
			
		||||
            *ainstr = 0xEF000000;
 | 
			
		||||
            // Breakpoint must be handled specially.
 | 
			
		||||
            if ((tinstr & 0x00FF) == 0x18)
 | 
			
		||||
                *ainstr |= ((tinstr & 0x00FF) << 16);
 | 
			
		||||
            // New breakpoint value.  See gdb/arm-tdep.c
 | 
			
		||||
            else if ((tinstr & 0x00FF) == 0xFE)
 | 
			
		||||
                *ainstr |= 0x180000; // base |= BKPT mask
 | 
			
		||||
            else
 | 
			
		||||
                *ainstr |= (tinstr & 0x00FF);
 | 
			
		||||
        } else if ((tinstr & 0x0F00) != 0x0E00)
 | 
			
		||||
            valid = ThumbDecodeStatus::BRANCH;
 | 
			
		||||
        else //  UNDEFINED : cc=1110(AL) uses different format
 | 
			
		||||
            valid = ThumbDecodeStatus::UNDEFINED;
 | 
			
		||||
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
    case 28: // B
 | 
			
		||||
        valid = ThumbDecodeStatus::BRANCH;
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
    case 29:
 | 
			
		||||
        if (tinstr & 0x1)
 | 
			
		||||
            valid = ThumbDecodeStatus::UNDEFINED;
 | 
			
		||||
        else
 | 
			
		||||
            valid = ThumbDecodeStatus::BRANCH;
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
    case 30: // BL instruction 1
 | 
			
		||||
 | 
			
		||||
        // There is no single ARM instruction equivalent for this Thumb instruction. To keep the
 | 
			
		||||
        // simulation simple (from the user perspective) we check if the following instruction is
 | 
			
		||||
        // the second half of this BL, and if it is we simulate it immediately
 | 
			
		||||
 | 
			
		||||
        valid = ThumbDecodeStatus::BRANCH;
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
    case 31: // BL instruction 2
 | 
			
		||||
 | 
			
		||||
        // There is no single ARM instruction equivalent for this instruction. Also, it should only
 | 
			
		||||
        // ever be matched with the fmt19 "BL instruction 1" instruction. However, we do allow the
 | 
			
		||||
        // simulation of it on its own, with undefined results if r14 is not suitably initialised.
 | 
			
		||||
 | 
			
		||||
        valid = ThumbDecodeStatus::BRANCH;
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    *inst_size = 2;
 | 
			
		||||
 | 
			
		||||
    return valid;
 | 
			
		||||
}
 | 
			
		||||
@ -1,49 +0,0 @@
 | 
			
		||||
/* Copyright (C)
 | 
			
		||||
* 2011 - Michael.Kang blackfin.kang@gmail.com
 | 
			
		||||
* This program is free software; you can redistribute it and/or
 | 
			
		||||
* modify it under the terms of the GNU General Public License
 | 
			
		||||
* as published by the Free Software Foundation; either version 2
 | 
			
		||||
* of the License, or (at your option) any later version.
 | 
			
		||||
*
 | 
			
		||||
* This program is distributed in the hope that it will be useful,
 | 
			
		||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
* GNU General Public License for more details.
 | 
			
		||||
*
 | 
			
		||||
* You should have received a copy of the GNU General Public License
 | 
			
		||||
* along with this program; if not, write to the Free Software
 | 
			
		||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 | 
			
		||||
*
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
* @file arm_dyncom_thumb.h
 | 
			
		||||
* @brief The thumb dyncom
 | 
			
		||||
* @author Michael.Kang blackfin.kang@gmail.com
 | 
			
		||||
* @version 78.77
 | 
			
		||||
* @date 2011-11-07
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "common/common_types.h"
 | 
			
		||||
 | 
			
		||||
enum class ThumbDecodeStatus {
 | 
			
		||||
    UNDEFINED, // Undefined Thumb instruction
 | 
			
		||||
    DECODED,   // Instruction decoded to ARM equivalent
 | 
			
		||||
    BRANCH,    // Thumb branch (already processed)
 | 
			
		||||
    UNINITIALIZED,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Translates a Thumb mode instruction into its ARM equivalent.
 | 
			
		||||
ThumbDecodeStatus TranslateThumbInstruction(u32 addr, u32 instr, u32* ainstr, u32* inst_size);
 | 
			
		||||
 | 
			
		||||
inline u32 GetThumbInstruction(u32 instr, u32 address) {
 | 
			
		||||
    // Normally you would need to handle instruction endianness,
 | 
			
		||||
    // however, it is fixed to little-endian on the MPCore, so
 | 
			
		||||
    // there's no need to check for this beforehand.
 | 
			
		||||
    if ((address & 0x3) != 0)
 | 
			
		||||
        return instr >> 16;
 | 
			
		||||
 | 
			
		||||
    return instr & 0xFFFF;
 | 
			
		||||
}
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@ -1,494 +0,0 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <cstddef>
 | 
			
		||||
#include "common/common_types.h"
 | 
			
		||||
 | 
			
		||||
struct ARMul_State;
 | 
			
		||||
typedef unsigned int (*shtop_fp_t)(ARMul_State* cpu, unsigned int sht_oper);
 | 
			
		||||
 | 
			
		||||
enum class TransExtData {
 | 
			
		||||
    COND = (1 << 0),
 | 
			
		||||
    NON_BRANCH = (1 << 1),
 | 
			
		||||
    DIRECT_BRANCH = (1 << 2),
 | 
			
		||||
    INDIRECT_BRANCH = (1 << 3),
 | 
			
		||||
    CALL = (1 << 4),
 | 
			
		||||
    RET = (1 << 5),
 | 
			
		||||
    END_OF_PAGE = (1 << 6),
 | 
			
		||||
    THUMB = (1 << 7),
 | 
			
		||||
    SINGLE_STEP = (1 << 8)
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct arm_inst {
 | 
			
		||||
    unsigned int idx;
 | 
			
		||||
    unsigned int cond;
 | 
			
		||||
    TransExtData br;
 | 
			
		||||
    char component[0];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct generic_arm_inst {
 | 
			
		||||
    u32 Ra;
 | 
			
		||||
    u32 Rm;
 | 
			
		||||
    u32 Rn;
 | 
			
		||||
    u32 Rd;
 | 
			
		||||
    u8 op1;
 | 
			
		||||
    u8 op2;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct adc_inst {
 | 
			
		||||
    unsigned int I;
 | 
			
		||||
    unsigned int S;
 | 
			
		||||
    unsigned int Rn;
 | 
			
		||||
    unsigned int Rd;
 | 
			
		||||
    unsigned int shifter_operand;
 | 
			
		||||
    shtop_fp_t shtop_func;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct add_inst {
 | 
			
		||||
    unsigned int I;
 | 
			
		||||
    unsigned int S;
 | 
			
		||||
    unsigned int Rn;
 | 
			
		||||
    unsigned int Rd;
 | 
			
		||||
    unsigned int shifter_operand;
 | 
			
		||||
    shtop_fp_t shtop_func;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct orr_inst {
 | 
			
		||||
    unsigned int I;
 | 
			
		||||
    unsigned int S;
 | 
			
		||||
    unsigned int Rn;
 | 
			
		||||
    unsigned int Rd;
 | 
			
		||||
    unsigned int shifter_operand;
 | 
			
		||||
    shtop_fp_t shtop_func;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct and_inst {
 | 
			
		||||
    unsigned int I;
 | 
			
		||||
    unsigned int S;
 | 
			
		||||
    unsigned int Rn;
 | 
			
		||||
    unsigned int Rd;
 | 
			
		||||
    unsigned int shifter_operand;
 | 
			
		||||
    shtop_fp_t shtop_func;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct eor_inst {
 | 
			
		||||
    unsigned int I;
 | 
			
		||||
    unsigned int S;
 | 
			
		||||
    unsigned int Rn;
 | 
			
		||||
    unsigned int Rd;
 | 
			
		||||
    unsigned int shifter_operand;
 | 
			
		||||
    shtop_fp_t shtop_func;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct bbl_inst {
 | 
			
		||||
    unsigned int L;
 | 
			
		||||
    int signed_immed_24;
 | 
			
		||||
    unsigned int next_addr;
 | 
			
		||||
    unsigned int jmp_addr;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct bx_inst {
 | 
			
		||||
    unsigned int Rm;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct blx_inst {
 | 
			
		||||
    union {
 | 
			
		||||
        s32 signed_immed_24;
 | 
			
		||||
        u32 Rm;
 | 
			
		||||
    } val;
 | 
			
		||||
    unsigned int inst;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct clz_inst {
 | 
			
		||||
    unsigned int Rm;
 | 
			
		||||
    unsigned int Rd;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct cps_inst {
 | 
			
		||||
    unsigned int imod0;
 | 
			
		||||
    unsigned int imod1;
 | 
			
		||||
    unsigned int mmod;
 | 
			
		||||
    unsigned int A, I, F;
 | 
			
		||||
    unsigned int mode;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct clrex_inst {};
 | 
			
		||||
 | 
			
		||||
struct cpy_inst {
 | 
			
		||||
    unsigned int Rm;
 | 
			
		||||
    unsigned int Rd;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct bic_inst {
 | 
			
		||||
    unsigned int I;
 | 
			
		||||
    unsigned int S;
 | 
			
		||||
    unsigned int Rn;
 | 
			
		||||
    unsigned int Rd;
 | 
			
		||||
    unsigned int shifter_operand;
 | 
			
		||||
    shtop_fp_t shtop_func;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct sub_inst {
 | 
			
		||||
    unsigned int I;
 | 
			
		||||
    unsigned int S;
 | 
			
		||||
    unsigned int Rn;
 | 
			
		||||
    unsigned int Rd;
 | 
			
		||||
    unsigned int shifter_operand;
 | 
			
		||||
    shtop_fp_t shtop_func;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct tst_inst {
 | 
			
		||||
    unsigned int I;
 | 
			
		||||
    unsigned int S;
 | 
			
		||||
    unsigned int Rn;
 | 
			
		||||
    unsigned int Rd;
 | 
			
		||||
    unsigned int shifter_operand;
 | 
			
		||||
    shtop_fp_t shtop_func;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct cmn_inst {
 | 
			
		||||
    unsigned int I;
 | 
			
		||||
    unsigned int Rn;
 | 
			
		||||
    unsigned int shifter_operand;
 | 
			
		||||
    shtop_fp_t shtop_func;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct teq_inst {
 | 
			
		||||
    unsigned int I;
 | 
			
		||||
    unsigned int Rn;
 | 
			
		||||
    unsigned int shifter_operand;
 | 
			
		||||
    shtop_fp_t shtop_func;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct stm_inst {
 | 
			
		||||
    unsigned int inst;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct bkpt_inst {
 | 
			
		||||
    u32 imm;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct stc_inst {};
 | 
			
		||||
 | 
			
		||||
struct ldc_inst {};
 | 
			
		||||
 | 
			
		||||
struct swi_inst {
 | 
			
		||||
    unsigned int num;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct cmp_inst {
 | 
			
		||||
    unsigned int I;
 | 
			
		||||
    unsigned int Rn;
 | 
			
		||||
    unsigned int shifter_operand;
 | 
			
		||||
    shtop_fp_t shtop_func;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct mov_inst {
 | 
			
		||||
    unsigned int I;
 | 
			
		||||
    unsigned int S;
 | 
			
		||||
    unsigned int Rd;
 | 
			
		||||
    unsigned int shifter_operand;
 | 
			
		||||
    shtop_fp_t shtop_func;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct mvn_inst {
 | 
			
		||||
    unsigned int I;
 | 
			
		||||
    unsigned int S;
 | 
			
		||||
    unsigned int Rd;
 | 
			
		||||
    unsigned int shifter_operand;
 | 
			
		||||
    shtop_fp_t shtop_func;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct rev_inst {
 | 
			
		||||
    unsigned int Rd;
 | 
			
		||||
    unsigned int Rm;
 | 
			
		||||
    unsigned int op1;
 | 
			
		||||
    unsigned int op2;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct rsb_inst {
 | 
			
		||||
    unsigned int I;
 | 
			
		||||
    unsigned int S;
 | 
			
		||||
    unsigned int Rn;
 | 
			
		||||
    unsigned int Rd;
 | 
			
		||||
    unsigned int shifter_operand;
 | 
			
		||||
    shtop_fp_t shtop_func;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct rsc_inst {
 | 
			
		||||
    unsigned int I;
 | 
			
		||||
    unsigned int S;
 | 
			
		||||
    unsigned int Rn;
 | 
			
		||||
    unsigned int Rd;
 | 
			
		||||
    unsigned int shifter_operand;
 | 
			
		||||
    shtop_fp_t shtop_func;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct sbc_inst {
 | 
			
		||||
    unsigned int I;
 | 
			
		||||
    unsigned int S;
 | 
			
		||||
    unsigned int Rn;
 | 
			
		||||
    unsigned int Rd;
 | 
			
		||||
    unsigned int shifter_operand;
 | 
			
		||||
    shtop_fp_t shtop_func;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct mul_inst {
 | 
			
		||||
    unsigned int S;
 | 
			
		||||
    unsigned int Rd;
 | 
			
		||||
    unsigned int Rs;
 | 
			
		||||
    unsigned int Rm;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct smul_inst {
 | 
			
		||||
    unsigned int Rd;
 | 
			
		||||
    unsigned int Rs;
 | 
			
		||||
    unsigned int Rm;
 | 
			
		||||
    unsigned int x;
 | 
			
		||||
    unsigned int y;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct umull_inst {
 | 
			
		||||
    unsigned int S;
 | 
			
		||||
    unsigned int RdHi;
 | 
			
		||||
    unsigned int RdLo;
 | 
			
		||||
    unsigned int Rs;
 | 
			
		||||
    unsigned int Rm;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct smlad_inst {
 | 
			
		||||
    unsigned int m;
 | 
			
		||||
    unsigned int Rm;
 | 
			
		||||
    unsigned int Rd;
 | 
			
		||||
    unsigned int Ra;
 | 
			
		||||
    unsigned int Rn;
 | 
			
		||||
    unsigned int op1;
 | 
			
		||||
    unsigned int op2;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct smla_inst {
 | 
			
		||||
    unsigned int x;
 | 
			
		||||
    unsigned int y;
 | 
			
		||||
    unsigned int Rm;
 | 
			
		||||
    unsigned int Rd;
 | 
			
		||||
    unsigned int Rs;
 | 
			
		||||
    unsigned int Rn;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct smlalxy_inst {
 | 
			
		||||
    unsigned int x;
 | 
			
		||||
    unsigned int y;
 | 
			
		||||
    unsigned int RdLo;
 | 
			
		||||
    unsigned int RdHi;
 | 
			
		||||
    unsigned int Rm;
 | 
			
		||||
    unsigned int Rn;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct ssat_inst {
 | 
			
		||||
    unsigned int Rn;
 | 
			
		||||
    unsigned int Rd;
 | 
			
		||||
    unsigned int imm5;
 | 
			
		||||
    unsigned int sat_imm;
 | 
			
		||||
    unsigned int shift_type;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct umaal_inst {
 | 
			
		||||
    unsigned int Rn;
 | 
			
		||||
    unsigned int Rm;
 | 
			
		||||
    unsigned int RdHi;
 | 
			
		||||
    unsigned int RdLo;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct umlal_inst {
 | 
			
		||||
    unsigned int S;
 | 
			
		||||
    unsigned int Rm;
 | 
			
		||||
    unsigned int Rs;
 | 
			
		||||
    unsigned int RdHi;
 | 
			
		||||
    unsigned int RdLo;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct smlal_inst {
 | 
			
		||||
    unsigned int S;
 | 
			
		||||
    unsigned int Rm;
 | 
			
		||||
    unsigned int Rs;
 | 
			
		||||
    unsigned int RdHi;
 | 
			
		||||
    unsigned int RdLo;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct smlald_inst {
 | 
			
		||||
    unsigned int RdLo;
 | 
			
		||||
    unsigned int RdHi;
 | 
			
		||||
    unsigned int Rm;
 | 
			
		||||
    unsigned int Rn;
 | 
			
		||||
    unsigned int swap;
 | 
			
		||||
    unsigned int op1;
 | 
			
		||||
    unsigned int op2;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct mla_inst {
 | 
			
		||||
    unsigned int S;
 | 
			
		||||
    unsigned int Rn;
 | 
			
		||||
    unsigned int Rd;
 | 
			
		||||
    unsigned int Rs;
 | 
			
		||||
    unsigned int Rm;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct mrc_inst {
 | 
			
		||||
    unsigned int opcode_1;
 | 
			
		||||
    unsigned int opcode_2;
 | 
			
		||||
    unsigned int cp_num;
 | 
			
		||||
    unsigned int crn;
 | 
			
		||||
    unsigned int crm;
 | 
			
		||||
    unsigned int Rd;
 | 
			
		||||
    unsigned int inst;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct mcr_inst {
 | 
			
		||||
    unsigned int opcode_1;
 | 
			
		||||
    unsigned int opcode_2;
 | 
			
		||||
    unsigned int cp_num;
 | 
			
		||||
    unsigned int crn;
 | 
			
		||||
    unsigned int crm;
 | 
			
		||||
    unsigned int Rd;
 | 
			
		||||
    unsigned int inst;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct mcrr_inst {
 | 
			
		||||
    unsigned int opcode_1;
 | 
			
		||||
    unsigned int cp_num;
 | 
			
		||||
    unsigned int crm;
 | 
			
		||||
    unsigned int rt;
 | 
			
		||||
    unsigned int rt2;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct mrs_inst {
 | 
			
		||||
    unsigned int R;
 | 
			
		||||
    unsigned int Rd;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct msr_inst {
 | 
			
		||||
    unsigned int field_mask;
 | 
			
		||||
    unsigned int R;
 | 
			
		||||
    unsigned int inst;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct pld_inst {};
 | 
			
		||||
 | 
			
		||||
struct sxtb_inst {
 | 
			
		||||
    unsigned int Rd;
 | 
			
		||||
    unsigned int Rm;
 | 
			
		||||
    unsigned int rotate;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct sxtab_inst {
 | 
			
		||||
    unsigned int Rd;
 | 
			
		||||
    unsigned int Rn;
 | 
			
		||||
    unsigned int Rm;
 | 
			
		||||
    unsigned rotate;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct sxtah_inst {
 | 
			
		||||
    unsigned int Rd;
 | 
			
		||||
    unsigned int Rn;
 | 
			
		||||
    unsigned int Rm;
 | 
			
		||||
    unsigned int rotate;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct sxth_inst {
 | 
			
		||||
    unsigned int Rd;
 | 
			
		||||
    unsigned int Rm;
 | 
			
		||||
    unsigned int rotate;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct uxtab_inst {
 | 
			
		||||
    unsigned int Rn;
 | 
			
		||||
    unsigned int Rd;
 | 
			
		||||
    unsigned int rotate;
 | 
			
		||||
    unsigned int Rm;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct uxtah_inst {
 | 
			
		||||
    unsigned int Rn;
 | 
			
		||||
    unsigned int Rd;
 | 
			
		||||
    unsigned int rotate;
 | 
			
		||||
    unsigned int Rm;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct uxth_inst {
 | 
			
		||||
    unsigned int Rd;
 | 
			
		||||
    unsigned int Rm;
 | 
			
		||||
    unsigned int rotate;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct cdp_inst {
 | 
			
		||||
    unsigned int opcode_1;
 | 
			
		||||
    unsigned int CRn;
 | 
			
		||||
    unsigned int CRd;
 | 
			
		||||
    unsigned int cp_num;
 | 
			
		||||
    unsigned int opcode_2;
 | 
			
		||||
    unsigned int CRm;
 | 
			
		||||
    unsigned int inst;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct uxtb_inst {
 | 
			
		||||
    unsigned int Rd;
 | 
			
		||||
    unsigned int Rm;
 | 
			
		||||
    unsigned int rotate;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct swp_inst {
 | 
			
		||||
    unsigned int Rn;
 | 
			
		||||
    unsigned int Rd;
 | 
			
		||||
    unsigned int Rm;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct setend_inst {
 | 
			
		||||
    unsigned int set_bigend;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct b_2_thumb {
 | 
			
		||||
    unsigned int imm;
 | 
			
		||||
};
 | 
			
		||||
struct b_cond_thumb {
 | 
			
		||||
    unsigned int imm;
 | 
			
		||||
    unsigned int cond;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct bl_1_thumb {
 | 
			
		||||
    unsigned int imm;
 | 
			
		||||
};
 | 
			
		||||
struct bl_2_thumb {
 | 
			
		||||
    unsigned int imm;
 | 
			
		||||
};
 | 
			
		||||
struct blx_1_thumb {
 | 
			
		||||
    unsigned int imm;
 | 
			
		||||
    unsigned int instr;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct pkh_inst {
 | 
			
		||||
    unsigned int Rm;
 | 
			
		||||
    unsigned int Rn;
 | 
			
		||||
    unsigned int Rd;
 | 
			
		||||
    unsigned char imm;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Floating point VFPv3 structures
 | 
			
		||||
#define VFP_INTERPRETER_STRUCT
 | 
			
		||||
#include "core/arm/skyeye_common/vfp/vfpinstr.cpp"
 | 
			
		||||
#undef VFP_INTERPRETER_STRUCT
 | 
			
		||||
 | 
			
		||||
typedef void (*get_addr_fp_t)(ARMul_State* cpu, unsigned int inst, unsigned int& virt_addr);
 | 
			
		||||
 | 
			
		||||
struct ldst_inst {
 | 
			
		||||
    unsigned int inst;
 | 
			
		||||
    get_addr_fp_t get_addr;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef arm_inst* ARM_INST_PTR;
 | 
			
		||||
typedef ARM_INST_PTR (*transop_fp_t)(unsigned int, int);
 | 
			
		||||
 | 
			
		||||
extern const transop_fp_t arm_instruction_trans[];
 | 
			
		||||
extern const size_t arm_instruction_trans_len;
 | 
			
		||||
 | 
			
		||||
#define TRANS_CACHE_SIZE (64 * 1024 * 2000)
 | 
			
		||||
extern char trans_cache_buf[TRANS_CACHE_SIZE];
 | 
			
		||||
extern size_t trans_cache_buf_top;
 | 
			
		||||
@ -1,187 +0,0 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
enum {
 | 
			
		||||
    R0 = 0,
 | 
			
		||||
    R1,
 | 
			
		||||
    R2,
 | 
			
		||||
    R3,
 | 
			
		||||
    R4,
 | 
			
		||||
    R5,
 | 
			
		||||
    R6,
 | 
			
		||||
    R7,
 | 
			
		||||
    R8,
 | 
			
		||||
    R9,
 | 
			
		||||
    R10,
 | 
			
		||||
    R11,
 | 
			
		||||
    R12,
 | 
			
		||||
    R13,
 | 
			
		||||
    LR,
 | 
			
		||||
    R15, // PC,
 | 
			
		||||
    CPSR_REG,
 | 
			
		||||
    SPSR_REG,
 | 
			
		||||
 | 
			
		||||
    PHYS_PC,
 | 
			
		||||
    R13_USR,
 | 
			
		||||
    R14_USR,
 | 
			
		||||
    R13_SVC,
 | 
			
		||||
    R14_SVC,
 | 
			
		||||
    R13_ABORT,
 | 
			
		||||
    R14_ABORT,
 | 
			
		||||
    R13_UNDEF,
 | 
			
		||||
    R14_UNDEF,
 | 
			
		||||
    R13_IRQ,
 | 
			
		||||
    R14_IRQ,
 | 
			
		||||
    R8_FIRQ,
 | 
			
		||||
    R9_FIRQ,
 | 
			
		||||
    R10_FIRQ,
 | 
			
		||||
    R11_FIRQ,
 | 
			
		||||
    R12_FIRQ,
 | 
			
		||||
    R13_FIRQ,
 | 
			
		||||
    R14_FIRQ,
 | 
			
		||||
    SPSR_INVALID1,
 | 
			
		||||
    SPSR_INVALID2,
 | 
			
		||||
    SPSR_SVC,
 | 
			
		||||
    SPSR_ABORT,
 | 
			
		||||
    SPSR_UNDEF,
 | 
			
		||||
    SPSR_IRQ,
 | 
			
		||||
    SPSR_FIRQ,
 | 
			
		||||
    MODE_REG, /* That is the cpsr[4 : 0], just for calculation easily */
 | 
			
		||||
    BANK_REG,
 | 
			
		||||
    EXCLUSIVE_TAG,
 | 
			
		||||
    EXCLUSIVE_STATE,
 | 
			
		||||
    EXCLUSIVE_RESULT,
 | 
			
		||||
 | 
			
		||||
    MAX_REG_NUM,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// VFP system registers
 | 
			
		||||
enum VFPSystemRegister {
 | 
			
		||||
    VFP_FPSID,
 | 
			
		||||
    VFP_FPSCR,
 | 
			
		||||
    VFP_FPEXC,
 | 
			
		||||
    VFP_FPINST,
 | 
			
		||||
    VFP_FPINST2,
 | 
			
		||||
    VFP_MVFR0,
 | 
			
		||||
    VFP_MVFR1,
 | 
			
		||||
 | 
			
		||||
    // Not an actual register.
 | 
			
		||||
    // All VFP system registers should be defined above this.
 | 
			
		||||
    VFP_SYSTEM_REGISTER_COUNT
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum CP15Register {
 | 
			
		||||
    // c0 - Information registers
 | 
			
		||||
    CP15_MAIN_ID,
 | 
			
		||||
    CP15_CACHE_TYPE,
 | 
			
		||||
    CP15_TCM_STATUS,
 | 
			
		||||
    CP15_TLB_TYPE,
 | 
			
		||||
    CP15_CPU_ID,
 | 
			
		||||
    CP15_PROCESSOR_FEATURE_0,
 | 
			
		||||
    CP15_PROCESSOR_FEATURE_1,
 | 
			
		||||
    CP15_DEBUG_FEATURE_0,
 | 
			
		||||
    CP15_AUXILIARY_FEATURE_0,
 | 
			
		||||
    CP15_MEMORY_MODEL_FEATURE_0,
 | 
			
		||||
    CP15_MEMORY_MODEL_FEATURE_1,
 | 
			
		||||
    CP15_MEMORY_MODEL_FEATURE_2,
 | 
			
		||||
    CP15_MEMORY_MODEL_FEATURE_3,
 | 
			
		||||
    CP15_ISA_FEATURE_0,
 | 
			
		||||
    CP15_ISA_FEATURE_1,
 | 
			
		||||
    CP15_ISA_FEATURE_2,
 | 
			
		||||
    CP15_ISA_FEATURE_3,
 | 
			
		||||
    CP15_ISA_FEATURE_4,
 | 
			
		||||
 | 
			
		||||
    // c1 - Control registers
 | 
			
		||||
    CP15_CONTROL,
 | 
			
		||||
    CP15_AUXILIARY_CONTROL,
 | 
			
		||||
    CP15_COPROCESSOR_ACCESS_CONTROL,
 | 
			
		||||
 | 
			
		||||
    // c2 - Translation table registers
 | 
			
		||||
    CP15_TRANSLATION_BASE_TABLE_0,
 | 
			
		||||
    CP15_TRANSLATION_BASE_TABLE_1,
 | 
			
		||||
    CP15_TRANSLATION_BASE_CONTROL,
 | 
			
		||||
    CP15_DOMAIN_ACCESS_CONTROL,
 | 
			
		||||
    CP15_RESERVED,
 | 
			
		||||
 | 
			
		||||
    // c5 - Fault status registers
 | 
			
		||||
    CP15_FAULT_STATUS,
 | 
			
		||||
    CP15_INSTR_FAULT_STATUS,
 | 
			
		||||
    CP15_COMBINED_DATA_FSR = CP15_FAULT_STATUS,
 | 
			
		||||
    CP15_INST_FSR,
 | 
			
		||||
 | 
			
		||||
    // c6 - Fault Address registers
 | 
			
		||||
    CP15_FAULT_ADDRESS,
 | 
			
		||||
    CP15_COMBINED_DATA_FAR = CP15_FAULT_ADDRESS,
 | 
			
		||||
    CP15_WFAR,
 | 
			
		||||
    CP15_IFAR,
 | 
			
		||||
 | 
			
		||||
    // c7 - Cache operation registers
 | 
			
		||||
    CP15_WAIT_FOR_INTERRUPT,
 | 
			
		||||
    CP15_PHYS_ADDRESS,
 | 
			
		||||
    CP15_INVALIDATE_INSTR_CACHE,
 | 
			
		||||
    CP15_INVALIDATE_INSTR_CACHE_USING_MVA,
 | 
			
		||||
    CP15_INVALIDATE_INSTR_CACHE_USING_INDEX,
 | 
			
		||||
    CP15_FLUSH_PREFETCH_BUFFER,
 | 
			
		||||
    CP15_FLUSH_BRANCH_TARGET_CACHE,
 | 
			
		||||
    CP15_FLUSH_BRANCH_TARGET_CACHE_ENTRY,
 | 
			
		||||
    CP15_INVALIDATE_DATA_CACHE,
 | 
			
		||||
    CP15_INVALIDATE_DATA_CACHE_LINE_USING_MVA,
 | 
			
		||||
    CP15_INVALIDATE_DATA_CACHE_LINE_USING_INDEX,
 | 
			
		||||
    CP15_INVALIDATE_DATA_AND_INSTR_CACHE,
 | 
			
		||||
    CP15_CLEAN_DATA_CACHE,
 | 
			
		||||
    CP15_CLEAN_DATA_CACHE_LINE_USING_MVA,
 | 
			
		||||
    CP15_CLEAN_DATA_CACHE_LINE_USING_INDEX,
 | 
			
		||||
    CP15_DATA_SYNC_BARRIER,
 | 
			
		||||
    CP15_DATA_MEMORY_BARRIER,
 | 
			
		||||
    CP15_CLEAN_AND_INVALIDATE_DATA_CACHE,
 | 
			
		||||
    CP15_CLEAN_AND_INVALIDATE_DATA_CACHE_LINE_USING_MVA,
 | 
			
		||||
    CP15_CLEAN_AND_INVALIDATE_DATA_CACHE_LINE_USING_INDEX,
 | 
			
		||||
 | 
			
		||||
    // c8 - TLB operations
 | 
			
		||||
    CP15_INVALIDATE_ITLB,
 | 
			
		||||
    CP15_INVALIDATE_ITLB_SINGLE_ENTRY,
 | 
			
		||||
    CP15_INVALIDATE_ITLB_ENTRY_ON_ASID_MATCH,
 | 
			
		||||
    CP15_INVALIDATE_ITLB_ENTRY_ON_MVA,
 | 
			
		||||
    CP15_INVALIDATE_DTLB,
 | 
			
		||||
    CP15_INVALIDATE_DTLB_SINGLE_ENTRY,
 | 
			
		||||
    CP15_INVALIDATE_DTLB_ENTRY_ON_ASID_MATCH,
 | 
			
		||||
    CP15_INVALIDATE_DTLB_ENTRY_ON_MVA,
 | 
			
		||||
    CP15_INVALIDATE_UTLB,
 | 
			
		||||
    CP15_INVALIDATE_UTLB_SINGLE_ENTRY,
 | 
			
		||||
    CP15_INVALIDATE_UTLB_ENTRY_ON_ASID_MATCH,
 | 
			
		||||
    CP15_INVALIDATE_UTLB_ENTRY_ON_MVA,
 | 
			
		||||
 | 
			
		||||
    // c9 - Data cache lockdown register
 | 
			
		||||
    CP15_DATA_CACHE_LOCKDOWN,
 | 
			
		||||
 | 
			
		||||
    // c10 - TLB/Memory map registers
 | 
			
		||||
    CP15_TLB_LOCKDOWN,
 | 
			
		||||
    CP15_PRIMARY_REGION_REMAP,
 | 
			
		||||
    CP15_NORMAL_REGION_REMAP,
 | 
			
		||||
 | 
			
		||||
    // c13 - Thread related registers
 | 
			
		||||
    CP15_PID,
 | 
			
		||||
    CP15_CONTEXT_ID,
 | 
			
		||||
    CP15_THREAD_UPRW, // Thread ID register - User/Privileged Read/Write
 | 
			
		||||
    CP15_THREAD_URO,  // Thread ID register - User Read Only (Privileged R/W)
 | 
			
		||||
    CP15_THREAD_PRW,  // Thread ID register - Privileged R/W only.
 | 
			
		||||
 | 
			
		||||
    // c15 - Performance and TLB lockdown registers
 | 
			
		||||
    CP15_PERFORMANCE_MONITOR_CONTROL,
 | 
			
		||||
    CP15_CYCLE_COUNTER,
 | 
			
		||||
    CP15_COUNT_0,
 | 
			
		||||
    CP15_COUNT_1,
 | 
			
		||||
    CP15_READ_MAIN_TLB_LOCKDOWN_ENTRY,
 | 
			
		||||
    CP15_WRITE_MAIN_TLB_LOCKDOWN_ENTRY,
 | 
			
		||||
    CP15_MAIN_TLB_LOCKDOWN_VIRT_ADDRESS,
 | 
			
		||||
    CP15_MAIN_TLB_LOCKDOWN_PHYS_ADDRESS,
 | 
			
		||||
    CP15_MAIN_TLB_LOCKDOWN_ATTRIBUTE,
 | 
			
		||||
    CP15_TLB_DEBUG_CONTROL,
 | 
			
		||||
 | 
			
		||||
    // Skyeye defined
 | 
			
		||||
    CP15_TLB_FAULT_ADDR,
 | 
			
		||||
    CP15_TLB_FAULT_STATUS,
 | 
			
		||||
 | 
			
		||||
    // Not an actual register.
 | 
			
		||||
    // All registers should be defined above this.
 | 
			
		||||
    CP15_REGISTER_COUNT,
 | 
			
		||||
};
 | 
			
		||||
@ -1,597 +0,0 @@
 | 
			
		||||
// Copyright 2015 Citra Emulator Project
 | 
			
		||||
// Licensed under GPLv2 or any later version
 | 
			
		||||
// Refer to the license.txt file included.
 | 
			
		||||
 | 
			
		||||
#include <algorithm>
 | 
			
		||||
#include "common/logging/log.h"
 | 
			
		||||
#include "common/swap.h"
 | 
			
		||||
#include "core/arm/skyeye_common/armstate.h"
 | 
			
		||||
#include "core/arm/skyeye_common/vfp/vfp.h"
 | 
			
		||||
#include "core/gdbstub/gdbstub.h"
 | 
			
		||||
#include "core/memory.h"
 | 
			
		||||
 | 
			
		||||
ARMul_State::ARMul_State(PrivilegeMode initial_mode) {
 | 
			
		||||
    Reset();
 | 
			
		||||
    ChangePrivilegeMode(initial_mode);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ARMul_State::ChangePrivilegeMode(u32 new_mode) {
 | 
			
		||||
    if (Mode == new_mode)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    if (new_mode != USERBANK) {
 | 
			
		||||
        switch (Mode) {
 | 
			
		||||
        case SYSTEM32MODE: // Shares registers with user mode
 | 
			
		||||
        case USER32MODE:
 | 
			
		||||
            Reg_usr[0] = Reg[13];
 | 
			
		||||
            Reg_usr[1] = Reg[14];
 | 
			
		||||
            break;
 | 
			
		||||
        case IRQ32MODE:
 | 
			
		||||
            Reg_irq[0] = Reg[13];
 | 
			
		||||
            Reg_irq[1] = Reg[14];
 | 
			
		||||
            Spsr[IRQBANK] = Spsr_copy;
 | 
			
		||||
            break;
 | 
			
		||||
        case SVC32MODE:
 | 
			
		||||
            Reg_svc[0] = Reg[13];
 | 
			
		||||
            Reg_svc[1] = Reg[14];
 | 
			
		||||
            Spsr[SVCBANK] = Spsr_copy;
 | 
			
		||||
            break;
 | 
			
		||||
        case ABORT32MODE:
 | 
			
		||||
            Reg_abort[0] = Reg[13];
 | 
			
		||||
            Reg_abort[1] = Reg[14];
 | 
			
		||||
            Spsr[ABORTBANK] = Spsr_copy;
 | 
			
		||||
            break;
 | 
			
		||||
        case UNDEF32MODE:
 | 
			
		||||
            Reg_undef[0] = Reg[13];
 | 
			
		||||
            Reg_undef[1] = Reg[14];
 | 
			
		||||
            Spsr[UNDEFBANK] = Spsr_copy;
 | 
			
		||||
            break;
 | 
			
		||||
        case FIQ32MODE:
 | 
			
		||||
            std::copy(Reg.begin() + 8, Reg.end() - 1, Reg_firq.begin());
 | 
			
		||||
            Spsr[FIQBANK] = Spsr_copy;
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        switch (new_mode) {
 | 
			
		||||
        case USER32MODE:
 | 
			
		||||
            Reg[13] = Reg_usr[0];
 | 
			
		||||
            Reg[14] = Reg_usr[1];
 | 
			
		||||
            Bank = USERBANK;
 | 
			
		||||
            break;
 | 
			
		||||
        case IRQ32MODE:
 | 
			
		||||
            Reg[13] = Reg_irq[0];
 | 
			
		||||
            Reg[14] = Reg_irq[1];
 | 
			
		||||
            Spsr_copy = Spsr[IRQBANK];
 | 
			
		||||
            Bank = IRQBANK;
 | 
			
		||||
            break;
 | 
			
		||||
        case SVC32MODE:
 | 
			
		||||
            Reg[13] = Reg_svc[0];
 | 
			
		||||
            Reg[14] = Reg_svc[1];
 | 
			
		||||
            Spsr_copy = Spsr[SVCBANK];
 | 
			
		||||
            Bank = SVCBANK;
 | 
			
		||||
            break;
 | 
			
		||||
        case ABORT32MODE:
 | 
			
		||||
            Reg[13] = Reg_abort[0];
 | 
			
		||||
            Reg[14] = Reg_abort[1];
 | 
			
		||||
            Spsr_copy = Spsr[ABORTBANK];
 | 
			
		||||
            Bank = ABORTBANK;
 | 
			
		||||
            break;
 | 
			
		||||
        case UNDEF32MODE:
 | 
			
		||||
            Reg[13] = Reg_undef[0];
 | 
			
		||||
            Reg[14] = Reg_undef[1];
 | 
			
		||||
            Spsr_copy = Spsr[UNDEFBANK];
 | 
			
		||||
            Bank = UNDEFBANK;
 | 
			
		||||
            break;
 | 
			
		||||
        case FIQ32MODE:
 | 
			
		||||
            std::copy(Reg_firq.begin(), Reg_firq.end(), Reg.begin() + 8);
 | 
			
		||||
            Spsr_copy = Spsr[FIQBANK];
 | 
			
		||||
            Bank = FIQBANK;
 | 
			
		||||
            break;
 | 
			
		||||
        case SYSTEM32MODE: // Shares registers with user mode.
 | 
			
		||||
            Reg[13] = Reg_usr[0];
 | 
			
		||||
            Reg[14] = Reg_usr[1];
 | 
			
		||||
            Bank = SYSTEMBANK;
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Set the mode bits in the APSR
 | 
			
		||||
        Cpsr = (Cpsr & ~Mode) | new_mode;
 | 
			
		||||
        Mode = new_mode;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Performs a reset
 | 
			
		||||
void ARMul_State::Reset() {
 | 
			
		||||
    VFPInit(this);
 | 
			
		||||
 | 
			
		||||
    // Set stack pointer to the top of the stack
 | 
			
		||||
    Reg[13] = 0x10000000;
 | 
			
		||||
    Reg[15] = 0;
 | 
			
		||||
 | 
			
		||||
    Cpsr = INTBITS | SVC32MODE;
 | 
			
		||||
    Mode = SVC32MODE;
 | 
			
		||||
    Bank = SVCBANK;
 | 
			
		||||
 | 
			
		||||
    ResetMPCoreCP15Registers();
 | 
			
		||||
 | 
			
		||||
    NresetSig = HIGH;
 | 
			
		||||
    NfiqSig = HIGH;
 | 
			
		||||
    NirqSig = HIGH;
 | 
			
		||||
    NtransSig = (Mode & 3) ? HIGH : LOW;
 | 
			
		||||
    abortSig = LOW;
 | 
			
		||||
 | 
			
		||||
    NumInstrs = 0;
 | 
			
		||||
    Emulate = RUN;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Resets certain MPCore CP15 values to their ARM-defined reset values.
 | 
			
		||||
void ARMul_State::ResetMPCoreCP15Registers() {
 | 
			
		||||
    // c0
 | 
			
		||||
    CP15[CP15_MAIN_ID] = 0x410FB024;
 | 
			
		||||
    CP15[CP15_TLB_TYPE] = 0x00000800;
 | 
			
		||||
    CP15[CP15_PROCESSOR_FEATURE_0] = 0x00000111;
 | 
			
		||||
    CP15[CP15_PROCESSOR_FEATURE_1] = 0x00000001;
 | 
			
		||||
    CP15[CP15_DEBUG_FEATURE_0] = 0x00000002;
 | 
			
		||||
    CP15[CP15_MEMORY_MODEL_FEATURE_0] = 0x01100103;
 | 
			
		||||
    CP15[CP15_MEMORY_MODEL_FEATURE_1] = 0x10020302;
 | 
			
		||||
    CP15[CP15_MEMORY_MODEL_FEATURE_2] = 0x01222000;
 | 
			
		||||
    CP15[CP15_MEMORY_MODEL_FEATURE_3] = 0x00000000;
 | 
			
		||||
    CP15[CP15_ISA_FEATURE_0] = 0x00100011;
 | 
			
		||||
    CP15[CP15_ISA_FEATURE_1] = 0x12002111;
 | 
			
		||||
    CP15[CP15_ISA_FEATURE_2] = 0x11221011;
 | 
			
		||||
    CP15[CP15_ISA_FEATURE_3] = 0x01102131;
 | 
			
		||||
    CP15[CP15_ISA_FEATURE_4] = 0x00000141;
 | 
			
		||||
 | 
			
		||||
    // c1
 | 
			
		||||
    CP15[CP15_CONTROL] = 0x00054078;
 | 
			
		||||
    CP15[CP15_AUXILIARY_CONTROL] = 0x0000000F;
 | 
			
		||||
    CP15[CP15_COPROCESSOR_ACCESS_CONTROL] = 0x00000000;
 | 
			
		||||
 | 
			
		||||
    // c2
 | 
			
		||||
    CP15[CP15_TRANSLATION_BASE_TABLE_0] = 0x00000000;
 | 
			
		||||
    CP15[CP15_TRANSLATION_BASE_TABLE_1] = 0x00000000;
 | 
			
		||||
    CP15[CP15_TRANSLATION_BASE_CONTROL] = 0x00000000;
 | 
			
		||||
 | 
			
		||||
    // c3
 | 
			
		||||
    CP15[CP15_DOMAIN_ACCESS_CONTROL] = 0x00000000;
 | 
			
		||||
 | 
			
		||||
    // c7
 | 
			
		||||
    CP15[CP15_PHYS_ADDRESS] = 0x00000000;
 | 
			
		||||
 | 
			
		||||
    // c9
 | 
			
		||||
    CP15[CP15_DATA_CACHE_LOCKDOWN] = 0xFFFFFFF0;
 | 
			
		||||
 | 
			
		||||
    // c10
 | 
			
		||||
    CP15[CP15_TLB_LOCKDOWN] = 0x00000000;
 | 
			
		||||
    CP15[CP15_PRIMARY_REGION_REMAP] = 0x00098AA4;
 | 
			
		||||
    CP15[CP15_NORMAL_REGION_REMAP] = 0x44E048E0;
 | 
			
		||||
 | 
			
		||||
    // c13
 | 
			
		||||
    CP15[CP15_PID] = 0x00000000;
 | 
			
		||||
    CP15[CP15_CONTEXT_ID] = 0x00000000;
 | 
			
		||||
    CP15[CP15_THREAD_UPRW] = 0x00000000;
 | 
			
		||||
    CP15[CP15_THREAD_URO] = 0x00000000;
 | 
			
		||||
    CP15[CP15_THREAD_PRW] = 0x00000000;
 | 
			
		||||
 | 
			
		||||
    // c15
 | 
			
		||||
    CP15[CP15_PERFORMANCE_MONITOR_CONTROL] = 0x00000000;
 | 
			
		||||
    CP15[CP15_MAIN_TLB_LOCKDOWN_VIRT_ADDRESS] = 0x00000000;
 | 
			
		||||
    CP15[CP15_MAIN_TLB_LOCKDOWN_PHYS_ADDRESS] = 0x00000000;
 | 
			
		||||
    CP15[CP15_MAIN_TLB_LOCKDOWN_ATTRIBUTE] = 0x00000000;
 | 
			
		||||
    CP15[CP15_TLB_DEBUG_CONTROL] = 0x00000000;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void CheckMemoryBreakpoint(u32 address, GDBStub::BreakpointType type) {
 | 
			
		||||
    if (GDBStub::IsServerEnabled() && GDBStub::CheckBreakpoint(address, type)) {
 | 
			
		||||
        LOG_DEBUG(Debug, "Found memory breakpoint @ %08x", address);
 | 
			
		||||
        GDBStub::Break(true);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
u8 ARMul_State::ReadMemory8(u32 address) const {
 | 
			
		||||
    CheckMemoryBreakpoint(address, GDBStub::BreakpointType::Read);
 | 
			
		||||
 | 
			
		||||
    return Memory::Read8(address);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
u16 ARMul_State::ReadMemory16(u32 address) const {
 | 
			
		||||
    CheckMemoryBreakpoint(address, GDBStub::BreakpointType::Read);
 | 
			
		||||
 | 
			
		||||
    u16 data = Memory::Read16(address);
 | 
			
		||||
 | 
			
		||||
    if (InBigEndianMode())
 | 
			
		||||
        data = Common::swap16(data);
 | 
			
		||||
 | 
			
		||||
    return data;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
u32 ARMul_State::ReadMemory32(u32 address) const {
 | 
			
		||||
    CheckMemoryBreakpoint(address, GDBStub::BreakpointType::Read);
 | 
			
		||||
 | 
			
		||||
    u32 data = Memory::Read32(address);
 | 
			
		||||
 | 
			
		||||
    if (InBigEndianMode())
 | 
			
		||||
        data = Common::swap32(data);
 | 
			
		||||
 | 
			
		||||
    return data;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
u64 ARMul_State::ReadMemory64(u32 address) const {
 | 
			
		||||
    CheckMemoryBreakpoint(address, GDBStub::BreakpointType::Read);
 | 
			
		||||
 | 
			
		||||
    u64 data = Memory::Read64(address);
 | 
			
		||||
 | 
			
		||||
    if (InBigEndianMode())
 | 
			
		||||
        data = Common::swap64(data);
 | 
			
		||||
 | 
			
		||||
    return data;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ARMul_State::WriteMemory8(u32 address, u8 data) {
 | 
			
		||||
    CheckMemoryBreakpoint(address, GDBStub::BreakpointType::Write);
 | 
			
		||||
 | 
			
		||||
    Memory::Write8(address, data);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ARMul_State::WriteMemory16(u32 address, u16 data) {
 | 
			
		||||
    CheckMemoryBreakpoint(address, GDBStub::BreakpointType::Write);
 | 
			
		||||
 | 
			
		||||
    if (InBigEndianMode())
 | 
			
		||||
        data = Common::swap16(data);
 | 
			
		||||
 | 
			
		||||
    Memory::Write16(address, data);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ARMul_State::WriteMemory32(u32 address, u32 data) {
 | 
			
		||||
    CheckMemoryBreakpoint(address, GDBStub::BreakpointType::Write);
 | 
			
		||||
 | 
			
		||||
    if (InBigEndianMode())
 | 
			
		||||
        data = Common::swap32(data);
 | 
			
		||||
 | 
			
		||||
    Memory::Write32(address, data);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ARMul_State::WriteMemory64(u32 address, u64 data) {
 | 
			
		||||
    CheckMemoryBreakpoint(address, GDBStub::BreakpointType::Write);
 | 
			
		||||
 | 
			
		||||
    if (InBigEndianMode())
 | 
			
		||||
        data = Common::swap64(data);
 | 
			
		||||
 | 
			
		||||
    Memory::Write64(address, data);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Reads from the CP15 registers. Used with implementation of the MRC instruction.
 | 
			
		||||
// Note that since the 3DS does not have the hypervisor extensions, these registers
 | 
			
		||||
// are not implemented.
 | 
			
		||||
u32 ARMul_State::ReadCP15Register(u32 crn, u32 opcode_1, u32 crm, u32 opcode_2) const {
 | 
			
		||||
    // Unprivileged registers
 | 
			
		||||
    if (crn == 13 && opcode_1 == 0 && crm == 0) {
 | 
			
		||||
        if (opcode_2 == 2)
 | 
			
		||||
            return CP15[CP15_THREAD_UPRW];
 | 
			
		||||
 | 
			
		||||
        if (opcode_2 == 3)
 | 
			
		||||
            return CP15[CP15_THREAD_URO];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (InAPrivilegedMode()) {
 | 
			
		||||
        if (crn == 0 && opcode_1 == 0) {
 | 
			
		||||
            if (crm == 0) {
 | 
			
		||||
                if (opcode_2 == 0)
 | 
			
		||||
                    return CP15[CP15_MAIN_ID];
 | 
			
		||||
 | 
			
		||||
                if (opcode_2 == 1)
 | 
			
		||||
                    return CP15[CP15_CACHE_TYPE];
 | 
			
		||||
 | 
			
		||||
                if (opcode_2 == 3)
 | 
			
		||||
                    return CP15[CP15_TLB_TYPE];
 | 
			
		||||
 | 
			
		||||
                if (opcode_2 == 5)
 | 
			
		||||
                    return CP15[CP15_CPU_ID];
 | 
			
		||||
            } else if (crm == 1) {
 | 
			
		||||
                if (opcode_2 == 0)
 | 
			
		||||
                    return CP15[CP15_PROCESSOR_FEATURE_0];
 | 
			
		||||
 | 
			
		||||
                if (opcode_2 == 1)
 | 
			
		||||
                    return CP15[CP15_PROCESSOR_FEATURE_1];
 | 
			
		||||
 | 
			
		||||
                if (opcode_2 == 2)
 | 
			
		||||
                    return CP15[CP15_DEBUG_FEATURE_0];
 | 
			
		||||
 | 
			
		||||
                if (opcode_2 == 4)
 | 
			
		||||
                    return CP15[CP15_MEMORY_MODEL_FEATURE_0];
 | 
			
		||||
 | 
			
		||||
                if (opcode_2 == 5)
 | 
			
		||||
                    return CP15[CP15_MEMORY_MODEL_FEATURE_1];
 | 
			
		||||
 | 
			
		||||
                if (opcode_2 == 6)
 | 
			
		||||
                    return CP15[CP15_MEMORY_MODEL_FEATURE_2];
 | 
			
		||||
 | 
			
		||||
                if (opcode_2 == 7)
 | 
			
		||||
                    return CP15[CP15_MEMORY_MODEL_FEATURE_3];
 | 
			
		||||
            } else if (crm == 2) {
 | 
			
		||||
                if (opcode_2 == 0)
 | 
			
		||||
                    return CP15[CP15_ISA_FEATURE_0];
 | 
			
		||||
 | 
			
		||||
                if (opcode_2 == 1)
 | 
			
		||||
                    return CP15[CP15_ISA_FEATURE_1];
 | 
			
		||||
 | 
			
		||||
                if (opcode_2 == 2)
 | 
			
		||||
                    return CP15[CP15_ISA_FEATURE_2];
 | 
			
		||||
 | 
			
		||||
                if (opcode_2 == 3)
 | 
			
		||||
                    return CP15[CP15_ISA_FEATURE_3];
 | 
			
		||||
 | 
			
		||||
                if (opcode_2 == 4)
 | 
			
		||||
                    return CP15[CP15_ISA_FEATURE_4];
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (crn == 1 && opcode_1 == 0 && crm == 0) {
 | 
			
		||||
            if (opcode_2 == 0)
 | 
			
		||||
                return CP15[CP15_CONTROL];
 | 
			
		||||
 | 
			
		||||
            if (opcode_2 == 1)
 | 
			
		||||
                return CP15[CP15_AUXILIARY_CONTROL];
 | 
			
		||||
 | 
			
		||||
            if (opcode_2 == 2)
 | 
			
		||||
                return CP15[CP15_COPROCESSOR_ACCESS_CONTROL];
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (crn == 2 && opcode_1 == 0 && crm == 0) {
 | 
			
		||||
            if (opcode_2 == 0)
 | 
			
		||||
                return CP15[CP15_TRANSLATION_BASE_TABLE_0];
 | 
			
		||||
 | 
			
		||||
            if (opcode_2 == 1)
 | 
			
		||||
                return CP15[CP15_TRANSLATION_BASE_TABLE_1];
 | 
			
		||||
 | 
			
		||||
            if (opcode_2 == 2)
 | 
			
		||||
                return CP15[CP15_TRANSLATION_BASE_CONTROL];
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (crn == 3 && opcode_1 == 0 && crm == 0 && opcode_2 == 0)
 | 
			
		||||
            return CP15[CP15_DOMAIN_ACCESS_CONTROL];
 | 
			
		||||
 | 
			
		||||
        if (crn == 5 && opcode_1 == 0 && crm == 0) {
 | 
			
		||||
            if (opcode_2 == 0)
 | 
			
		||||
                return CP15[CP15_FAULT_STATUS];
 | 
			
		||||
 | 
			
		||||
            if (opcode_2 == 1)
 | 
			
		||||
                return CP15[CP15_INSTR_FAULT_STATUS];
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (crn == 6 && opcode_1 == 0 && crm == 0) {
 | 
			
		||||
            if (opcode_2 == 0)
 | 
			
		||||
                return CP15[CP15_FAULT_ADDRESS];
 | 
			
		||||
 | 
			
		||||
            if (opcode_2 == 1)
 | 
			
		||||
                return CP15[CP15_WFAR];
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (crn == 7 && opcode_1 == 0 && crm == 4 && opcode_2 == 0)
 | 
			
		||||
            return CP15[CP15_PHYS_ADDRESS];
 | 
			
		||||
 | 
			
		||||
        if (crn == 9 && opcode_1 == 0 && crm == 0 && opcode_2 == 0)
 | 
			
		||||
            return CP15[CP15_DATA_CACHE_LOCKDOWN];
 | 
			
		||||
 | 
			
		||||
        if (crn == 10 && opcode_1 == 0) {
 | 
			
		||||
            if (crm == 0 && opcode_2 == 0)
 | 
			
		||||
                return CP15[CP15_TLB_LOCKDOWN];
 | 
			
		||||
 | 
			
		||||
            if (crm == 2) {
 | 
			
		||||
                if (opcode_2 == 0)
 | 
			
		||||
                    return CP15[CP15_PRIMARY_REGION_REMAP];
 | 
			
		||||
 | 
			
		||||
                if (opcode_2 == 1)
 | 
			
		||||
                    return CP15[CP15_NORMAL_REGION_REMAP];
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (crn == 13 && crm == 0) {
 | 
			
		||||
            if (opcode_2 == 0)
 | 
			
		||||
                return CP15[CP15_PID];
 | 
			
		||||
 | 
			
		||||
            if (opcode_2 == 1)
 | 
			
		||||
                return CP15[CP15_CONTEXT_ID];
 | 
			
		||||
 | 
			
		||||
            if (opcode_2 == 4)
 | 
			
		||||
                return CP15[CP15_THREAD_PRW];
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (crn == 15) {
 | 
			
		||||
            if (opcode_1 == 0 && crm == 12) {
 | 
			
		||||
                if (opcode_2 == 0)
 | 
			
		||||
                    return CP15[CP15_PERFORMANCE_MONITOR_CONTROL];
 | 
			
		||||
 | 
			
		||||
                if (opcode_2 == 1)
 | 
			
		||||
                    return CP15[CP15_CYCLE_COUNTER];
 | 
			
		||||
 | 
			
		||||
                if (opcode_2 == 2)
 | 
			
		||||
                    return CP15[CP15_COUNT_0];
 | 
			
		||||
 | 
			
		||||
                if (opcode_2 == 3)
 | 
			
		||||
                    return CP15[CP15_COUNT_1];
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (opcode_1 == 5 && opcode_2 == 2) {
 | 
			
		||||
                if (crm == 5)
 | 
			
		||||
                    return CP15[CP15_MAIN_TLB_LOCKDOWN_VIRT_ADDRESS];
 | 
			
		||||
 | 
			
		||||
                if (crm == 6)
 | 
			
		||||
                    return CP15[CP15_MAIN_TLB_LOCKDOWN_PHYS_ADDRESS];
 | 
			
		||||
 | 
			
		||||
                if (crm == 7)
 | 
			
		||||
                    return CP15[CP15_MAIN_TLB_LOCKDOWN_ATTRIBUTE];
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (opcode_1 == 7 && crm == 1 && opcode_2 == 0)
 | 
			
		||||
                return CP15[CP15_TLB_DEBUG_CONTROL];
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    LOG_ERROR(Core_ARM, "MRC CRn=%u, CRm=%u, OP1=%u OP2=%u is not implemented. Returning zero.",
 | 
			
		||||
              crn, crm, opcode_1, opcode_2);
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Write to the CP15 registers. Used with implementation of the MCR instruction.
 | 
			
		||||
// Note that since the 3DS does not have the hypervisor extensions, these registers
 | 
			
		||||
// are not implemented.
 | 
			
		||||
void ARMul_State::WriteCP15Register(u32 value, u32 crn, u32 opcode_1, u32 crm, u32 opcode_2) {
 | 
			
		||||
    if (InAPrivilegedMode()) {
 | 
			
		||||
        if (crn == 1 && opcode_1 == 0 && crm == 0) {
 | 
			
		||||
            if (opcode_2 == 0)
 | 
			
		||||
                CP15[CP15_CONTROL] = value;
 | 
			
		||||
            else if (opcode_2 == 1)
 | 
			
		||||
                CP15[CP15_AUXILIARY_CONTROL] = value;
 | 
			
		||||
            else if (opcode_2 == 2)
 | 
			
		||||
                CP15[CP15_COPROCESSOR_ACCESS_CONTROL] = value;
 | 
			
		||||
        } else if (crn == 2 && opcode_1 == 0 && crm == 0) {
 | 
			
		||||
            if (opcode_2 == 0)
 | 
			
		||||
                CP15[CP15_TRANSLATION_BASE_TABLE_0] = value;
 | 
			
		||||
            else if (opcode_2 == 1)
 | 
			
		||||
                CP15[CP15_TRANSLATION_BASE_TABLE_1] = value;
 | 
			
		||||
            else if (opcode_2 == 2)
 | 
			
		||||
                CP15[CP15_TRANSLATION_BASE_CONTROL] = value;
 | 
			
		||||
        } else if (crn == 3 && opcode_1 == 0 && crm == 0 && opcode_2 == 0) {
 | 
			
		||||
            CP15[CP15_DOMAIN_ACCESS_CONTROL] = value;
 | 
			
		||||
        } else if (crn == 5 && opcode_1 == 0 && crm == 0) {
 | 
			
		||||
            if (opcode_2 == 0)
 | 
			
		||||
                CP15[CP15_FAULT_STATUS] = value;
 | 
			
		||||
            else if (opcode_2 == 1)
 | 
			
		||||
                CP15[CP15_INSTR_FAULT_STATUS] = value;
 | 
			
		||||
        } else if (crn == 6 && opcode_1 == 0 && crm == 0) {
 | 
			
		||||
            if (opcode_2 == 0)
 | 
			
		||||
                CP15[CP15_FAULT_ADDRESS] = value;
 | 
			
		||||
            else if (opcode_2 == 1)
 | 
			
		||||
                CP15[CP15_WFAR] = value;
 | 
			
		||||
        } else if (crn == 7 && opcode_1 == 0) {
 | 
			
		||||
            if (crm == 0 && opcode_2 == 4) {
 | 
			
		||||
                CP15[CP15_WAIT_FOR_INTERRUPT] = value;
 | 
			
		||||
            } else if (crm == 4 && opcode_2 == 0) {
 | 
			
		||||
                // NOTE: Not entirely accurate. This should do permission checks.
 | 
			
		||||
                CP15[CP15_PHYS_ADDRESS] = Memory::VirtualToPhysicalAddress(value);
 | 
			
		||||
            } else if (crm == 5) {
 | 
			
		||||
                if (opcode_2 == 0)
 | 
			
		||||
                    CP15[CP15_INVALIDATE_INSTR_CACHE] = value;
 | 
			
		||||
                else if (opcode_2 == 1)
 | 
			
		||||
                    CP15[CP15_INVALIDATE_INSTR_CACHE_USING_MVA] = value;
 | 
			
		||||
                else if (opcode_2 == 2)
 | 
			
		||||
                    CP15[CP15_INVALIDATE_INSTR_CACHE_USING_INDEX] = value;
 | 
			
		||||
                else if (opcode_2 == 6)
 | 
			
		||||
                    CP15[CP15_FLUSH_BRANCH_TARGET_CACHE] = value;
 | 
			
		||||
                else if (opcode_2 == 7)
 | 
			
		||||
                    CP15[CP15_FLUSH_BRANCH_TARGET_CACHE_ENTRY] = value;
 | 
			
		||||
            } else if (crm == 6) {
 | 
			
		||||
                if (opcode_2 == 0)
 | 
			
		||||
                    CP15[CP15_INVALIDATE_DATA_CACHE] = value;
 | 
			
		||||
                else if (opcode_2 == 1)
 | 
			
		||||
                    CP15[CP15_INVALIDATE_DATA_CACHE_LINE_USING_MVA] = value;
 | 
			
		||||
                else if (opcode_2 == 2)
 | 
			
		||||
                    CP15[CP15_INVALIDATE_DATA_CACHE_LINE_USING_INDEX] = value;
 | 
			
		||||
            } else if (crm == 7 && opcode_2 == 0) {
 | 
			
		||||
                CP15[CP15_INVALIDATE_DATA_AND_INSTR_CACHE] = value;
 | 
			
		||||
            } else if (crm == 10) {
 | 
			
		||||
                if (opcode_2 == 0)
 | 
			
		||||
                    CP15[CP15_CLEAN_DATA_CACHE] = value;
 | 
			
		||||
                else if (opcode_2 == 1)
 | 
			
		||||
                    CP15[CP15_CLEAN_DATA_CACHE_LINE_USING_MVA] = value;
 | 
			
		||||
                else if (opcode_2 == 2)
 | 
			
		||||
                    CP15[CP15_CLEAN_DATA_CACHE_LINE_USING_INDEX] = value;
 | 
			
		||||
            } else if (crm == 14) {
 | 
			
		||||
                if (opcode_2 == 0)
 | 
			
		||||
                    CP15[CP15_CLEAN_AND_INVALIDATE_DATA_CACHE] = value;
 | 
			
		||||
                else if (opcode_2 == 1)
 | 
			
		||||
                    CP15[CP15_CLEAN_AND_INVALIDATE_DATA_CACHE_LINE_USING_MVA] = value;
 | 
			
		||||
                else if (opcode_2 == 2)
 | 
			
		||||
                    CP15[CP15_CLEAN_AND_INVALIDATE_DATA_CACHE_LINE_USING_INDEX] = value;
 | 
			
		||||
            }
 | 
			
		||||
        } else if (crn == 8 && opcode_1 == 0) {
 | 
			
		||||
            if (crm == 5) {
 | 
			
		||||
                if (opcode_2 == 0)
 | 
			
		||||
                    CP15[CP15_INVALIDATE_ITLB] = value;
 | 
			
		||||
                else if (opcode_2 == 1)
 | 
			
		||||
                    CP15[CP15_INVALIDATE_ITLB_SINGLE_ENTRY] = value;
 | 
			
		||||
                else if (opcode_2 == 2)
 | 
			
		||||
                    CP15[CP15_INVALIDATE_ITLB_ENTRY_ON_ASID_MATCH] = value;
 | 
			
		||||
                else if (opcode_2 == 3)
 | 
			
		||||
                    CP15[CP15_INVALIDATE_ITLB_ENTRY_ON_MVA] = value;
 | 
			
		||||
            } else if (crm == 6) {
 | 
			
		||||
                if (opcode_2 == 0)
 | 
			
		||||
                    CP15[CP15_INVALIDATE_DTLB] = value;
 | 
			
		||||
                else if (opcode_2 == 1)
 | 
			
		||||
                    CP15[CP15_INVALIDATE_DTLB_SINGLE_ENTRY] = value;
 | 
			
		||||
                else if (opcode_2 == 2)
 | 
			
		||||
                    CP15[CP15_INVALIDATE_DTLB_ENTRY_ON_ASID_MATCH] = value;
 | 
			
		||||
                else if (opcode_2 == 3)
 | 
			
		||||
                    CP15[CP15_INVALIDATE_DTLB_ENTRY_ON_MVA] = value;
 | 
			
		||||
            } else if (crm == 7) {
 | 
			
		||||
                if (opcode_2 == 0)
 | 
			
		||||
                    CP15[CP15_INVALIDATE_UTLB] = value;
 | 
			
		||||
                else if (opcode_2 == 1)
 | 
			
		||||
                    CP15[CP15_INVALIDATE_UTLB_SINGLE_ENTRY] = value;
 | 
			
		||||
                else if (opcode_2 == 2)
 | 
			
		||||
                    CP15[CP15_INVALIDATE_UTLB_ENTRY_ON_ASID_MATCH] = value;
 | 
			
		||||
                else if (opcode_2 == 3)
 | 
			
		||||
                    CP15[CP15_INVALIDATE_UTLB_ENTRY_ON_MVA] = value;
 | 
			
		||||
            }
 | 
			
		||||
        } else if (crn == 9 && opcode_1 == 0 && crm == 0 && opcode_2 == 0) {
 | 
			
		||||
            CP15[CP15_DATA_CACHE_LOCKDOWN] = value;
 | 
			
		||||
        } else if (crn == 10 && opcode_1 == 0) {
 | 
			
		||||
            if (crm == 0 && opcode_2 == 0) {
 | 
			
		||||
                CP15[CP15_TLB_LOCKDOWN] = value;
 | 
			
		||||
            } else if (crm == 2) {
 | 
			
		||||
                if (opcode_2 == 0)
 | 
			
		||||
                    CP15[CP15_PRIMARY_REGION_REMAP] = value;
 | 
			
		||||
                else if (opcode_2 == 1)
 | 
			
		||||
                    CP15[CP15_NORMAL_REGION_REMAP] = value;
 | 
			
		||||
            }
 | 
			
		||||
        } else if (crn == 13 && opcode_1 == 0 && crm == 0) {
 | 
			
		||||
            if (opcode_2 == 0)
 | 
			
		||||
                CP15[CP15_PID] = value;
 | 
			
		||||
            else if (opcode_2 == 1)
 | 
			
		||||
                CP15[CP15_CONTEXT_ID] = value;
 | 
			
		||||
            else if (opcode_2 == 3)
 | 
			
		||||
                CP15[CP15_THREAD_URO] = value;
 | 
			
		||||
            else if (opcode_2 == 4)
 | 
			
		||||
                CP15[CP15_THREAD_PRW] = value;
 | 
			
		||||
        } else if (crn == 15) {
 | 
			
		||||
            if (opcode_1 == 0 && crm == 12) {
 | 
			
		||||
                if (opcode_2 == 0)
 | 
			
		||||
                    CP15[CP15_PERFORMANCE_MONITOR_CONTROL] = value;
 | 
			
		||||
                else if (opcode_2 == 1)
 | 
			
		||||
                    CP15[CP15_CYCLE_COUNTER] = value;
 | 
			
		||||
                else if (opcode_2 == 2)
 | 
			
		||||
                    CP15[CP15_COUNT_0] = value;
 | 
			
		||||
                else if (opcode_2 == 3)
 | 
			
		||||
                    CP15[CP15_COUNT_1] = value;
 | 
			
		||||
            } else if (opcode_1 == 5) {
 | 
			
		||||
                if (crm == 4) {
 | 
			
		||||
                    if (opcode_2 == 2)
 | 
			
		||||
                        CP15[CP15_READ_MAIN_TLB_LOCKDOWN_ENTRY] = value;
 | 
			
		||||
                    else if (opcode_2 == 4)
 | 
			
		||||
                        CP15[CP15_WRITE_MAIN_TLB_LOCKDOWN_ENTRY] = value;
 | 
			
		||||
                } else if (crm == 5 && opcode_2 == 2) {
 | 
			
		||||
                    CP15[CP15_MAIN_TLB_LOCKDOWN_VIRT_ADDRESS] = value;
 | 
			
		||||
                } else if (crm == 6 && opcode_2 == 2) {
 | 
			
		||||
                    CP15[CP15_MAIN_TLB_LOCKDOWN_PHYS_ADDRESS] = value;
 | 
			
		||||
                } else if (crm == 7 && opcode_2 == 2) {
 | 
			
		||||
                    CP15[CP15_MAIN_TLB_LOCKDOWN_ATTRIBUTE] = value;
 | 
			
		||||
                }
 | 
			
		||||
            } else if (opcode_1 == 7 && crm == 1 && opcode_2 == 0) {
 | 
			
		||||
                CP15[CP15_TLB_DEBUG_CONTROL] = value;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Unprivileged registers
 | 
			
		||||
    if (crn == 7 && opcode_1 == 0 && crm == 5 && opcode_2 == 4) {
 | 
			
		||||
        CP15[CP15_FLUSH_PREFETCH_BUFFER] = value;
 | 
			
		||||
    } else if (crn == 7 && opcode_1 == 0 && crm == 10) {
 | 
			
		||||
        if (opcode_2 == 4)
 | 
			
		||||
            CP15[CP15_DATA_SYNC_BARRIER] = value;
 | 
			
		||||
        else if (opcode_2 == 5)
 | 
			
		||||
            CP15[CP15_DATA_MEMORY_BARRIER] = value;
 | 
			
		||||
    } else if (crn == 13 && opcode_1 == 0 && crm == 0 && opcode_2 == 2) {
 | 
			
		||||
        CP15[CP15_THREAD_UPRW] = value;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -1,245 +0,0 @@
 | 
			
		||||
/*  armdefs.h -- ARMulator common definitions:  ARM6 Instruction Emulator.
 | 
			
		||||
    Copyright (C) 1994 Advanced RISC Machines Ltd.
 | 
			
		||||
 | 
			
		||||
    This program is free software; you can redistribute it and/or modify
 | 
			
		||||
    it under the terms of the GNU General Public License as published by
 | 
			
		||||
    the Free Software Foundation; either version 2 of the License, or
 | 
			
		||||
    (at your option) any later version.
 | 
			
		||||
 | 
			
		||||
    This program is distributed in the hope that it will be useful,
 | 
			
		||||
    but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
    GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
    You should have received a copy of the GNU General Public License
 | 
			
		||||
    along with this program; if not, write to the Free Software
 | 
			
		||||
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <array>
 | 
			
		||||
#include <unordered_map>
 | 
			
		||||
#include "common/common_types.h"
 | 
			
		||||
#include "core/arm/skyeye_common/arm_regformat.h"
 | 
			
		||||
 | 
			
		||||
// Signal levels
 | 
			
		||||
enum { LOW = 0, HIGH = 1, LOWHIGH = 1, HIGHLOW = 2 };
 | 
			
		||||
 | 
			
		||||
// Cache types
 | 
			
		||||
enum {
 | 
			
		||||
    NONCACHE = 0,
 | 
			
		||||
    DATACACHE = 1,
 | 
			
		||||
    INSTCACHE = 2,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// ARM privilege modes
 | 
			
		||||
enum PrivilegeMode {
 | 
			
		||||
    USER32MODE = 16,
 | 
			
		||||
    FIQ32MODE = 17,
 | 
			
		||||
    IRQ32MODE = 18,
 | 
			
		||||
    SVC32MODE = 19,
 | 
			
		||||
    ABORT32MODE = 23,
 | 
			
		||||
    UNDEF32MODE = 27,
 | 
			
		||||
    SYSTEM32MODE = 31
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// ARM privilege mode register banks
 | 
			
		||||
enum {
 | 
			
		||||
    USERBANK = 0,
 | 
			
		||||
    FIQBANK = 1,
 | 
			
		||||
    IRQBANK = 2,
 | 
			
		||||
    SVCBANK = 3,
 | 
			
		||||
    ABORTBANK = 4,
 | 
			
		||||
    UNDEFBANK = 5,
 | 
			
		||||
    DUMMYBANK = 6,
 | 
			
		||||
    SYSTEMBANK = 7
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Hardware vector addresses
 | 
			
		||||
enum {
 | 
			
		||||
    ARMResetV = 0,
 | 
			
		||||
    ARMUndefinedInstrV = 4,
 | 
			
		||||
    ARMSWIV = 8,
 | 
			
		||||
    ARMPrefetchAbortV = 12,
 | 
			
		||||
    ARMDataAbortV = 16,
 | 
			
		||||
    ARMAddrExceptnV = 20,
 | 
			
		||||
    ARMIRQV = 24,
 | 
			
		||||
    ARMFIQV = 28,
 | 
			
		||||
    ARMErrorV = 32, // This is an offset, not an address!
 | 
			
		||||
 | 
			
		||||
    ARMul_ResetV = ARMResetV,
 | 
			
		||||
    ARMul_UndefinedInstrV = ARMUndefinedInstrV,
 | 
			
		||||
    ARMul_SWIV = ARMSWIV,
 | 
			
		||||
    ARMul_PrefetchAbortV = ARMPrefetchAbortV,
 | 
			
		||||
    ARMul_DataAbortV = ARMDataAbortV,
 | 
			
		||||
    ARMul_AddrExceptnV = ARMAddrExceptnV,
 | 
			
		||||
    ARMul_IRQV = ARMIRQV,
 | 
			
		||||
    ARMul_FIQV = ARMFIQV
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Coprocessor status values
 | 
			
		||||
enum {
 | 
			
		||||
    ARMul_FIRST = 0,
 | 
			
		||||
    ARMul_TRANSFER = 1,
 | 
			
		||||
    ARMul_BUSY = 2,
 | 
			
		||||
    ARMul_DATA = 3,
 | 
			
		||||
    ARMul_INTERRUPT = 4,
 | 
			
		||||
    ARMul_DONE = 0,
 | 
			
		||||
    ARMul_CANT = 1,
 | 
			
		||||
    ARMul_INC = 3
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Instruction condition codes
 | 
			
		||||
enum ConditionCode {
 | 
			
		||||
    EQ = 0,
 | 
			
		||||
    NE = 1,
 | 
			
		||||
    CS = 2,
 | 
			
		||||
    CC = 3,
 | 
			
		||||
    MI = 4,
 | 
			
		||||
    PL = 5,
 | 
			
		||||
    VS = 6,
 | 
			
		||||
    VC = 7,
 | 
			
		||||
    HI = 8,
 | 
			
		||||
    LS = 9,
 | 
			
		||||
    GE = 10,
 | 
			
		||||
    LT = 11,
 | 
			
		||||
    GT = 12,
 | 
			
		||||
    LE = 13,
 | 
			
		||||
    AL = 14,
 | 
			
		||||
    NV = 15,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Flags for use with the APSR.
 | 
			
		||||
enum : u32 {
 | 
			
		||||
    NBIT = (1U << 31U),
 | 
			
		||||
    ZBIT = (1 << 30),
 | 
			
		||||
    CBIT = (1 << 29),
 | 
			
		||||
    VBIT = (1 << 28),
 | 
			
		||||
    QBIT = (1 << 27),
 | 
			
		||||
    JBIT = (1 << 24),
 | 
			
		||||
    EBIT = (1 << 9),
 | 
			
		||||
    ABIT = (1 << 8),
 | 
			
		||||
    IBIT = (1 << 7),
 | 
			
		||||
    FBIT = (1 << 6),
 | 
			
		||||
    TBIT = (1 << 5),
 | 
			
		||||
 | 
			
		||||
    // Masks for groups of bits in the APSR.
 | 
			
		||||
    MODEBITS = 0x1F,
 | 
			
		||||
    INTBITS = 0x1C0,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Values for Emulate.
 | 
			
		||||
enum {
 | 
			
		||||
    STOP = 0,       // Stop
 | 
			
		||||
    CHANGEMODE = 1, // Change mode
 | 
			
		||||
    ONCE = 2,       // Execute just one iteration
 | 
			
		||||
    RUN = 3         // Continuous execution
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct ARMul_State final {
 | 
			
		||||
public:
 | 
			
		||||
    explicit ARMul_State(PrivilegeMode initial_mode);
 | 
			
		||||
 | 
			
		||||
    void ChangePrivilegeMode(u32 new_mode);
 | 
			
		||||
    void Reset();
 | 
			
		||||
 | 
			
		||||
    // Reads/writes data in big/little endian format based on the
 | 
			
		||||
    // state of the E (endian) bit in the APSR.
 | 
			
		||||
    u8 ReadMemory8(u32 address) const;
 | 
			
		||||
    u16 ReadMemory16(u32 address) const;
 | 
			
		||||
    u32 ReadMemory32(u32 address) const;
 | 
			
		||||
    u64 ReadMemory64(u32 address) const;
 | 
			
		||||
    void WriteMemory8(u32 address, u8 data);
 | 
			
		||||
    void WriteMemory16(u32 address, u16 data);
 | 
			
		||||
    void WriteMemory32(u32 address, u32 data);
 | 
			
		||||
    void WriteMemory64(u32 address, u64 data);
 | 
			
		||||
 | 
			
		||||
    u32 ReadCP15Register(u32 crn, u32 opcode_1, u32 crm, u32 opcode_2) const;
 | 
			
		||||
    void WriteCP15Register(u32 value, u32 crn, u32 opcode_1, u32 crm, u32 opcode_2);
 | 
			
		||||
 | 
			
		||||
    // Exclusive memory access functions
 | 
			
		||||
    bool IsExclusiveMemoryAccess(u32 address) const {
 | 
			
		||||
        return exclusive_state && exclusive_tag == (address & RESERVATION_GRANULE_MASK);
 | 
			
		||||
    }
 | 
			
		||||
    void SetExclusiveMemoryAddress(u32 address) {
 | 
			
		||||
        exclusive_tag = address & RESERVATION_GRANULE_MASK;
 | 
			
		||||
        exclusive_state = true;
 | 
			
		||||
    }
 | 
			
		||||
    void UnsetExclusiveMemoryAddress() {
 | 
			
		||||
        exclusive_tag = 0xFFFFFFFF;
 | 
			
		||||
        exclusive_state = false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Whether or not the given CPU is in big endian mode (E bit is set)
 | 
			
		||||
    bool InBigEndianMode() const {
 | 
			
		||||
        return (Cpsr & (1 << 9)) != 0;
 | 
			
		||||
    }
 | 
			
		||||
    // Whether or not the given CPU is in a mode other than user mode.
 | 
			
		||||
    bool InAPrivilegedMode() const {
 | 
			
		||||
        return (Mode != USER32MODE);
 | 
			
		||||
    }
 | 
			
		||||
    // Note that for the 3DS, a Thumb instruction will only ever be
 | 
			
		||||
    // two bytes in size. Thus we don't need to worry about ThumbEE
 | 
			
		||||
    // or Thumb-2 where instructions can be 4 bytes in length.
 | 
			
		||||
    u32 GetInstructionSize() const {
 | 
			
		||||
        return TFlag ? 2 : 4;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    std::array<u32, 16> Reg{}; // The current register file
 | 
			
		||||
    std::array<u32, 2> Reg_usr{};
 | 
			
		||||
    std::array<u32, 2> Reg_svc{};   // R13_SVC R14_SVC
 | 
			
		||||
    std::array<u32, 2> Reg_abort{}; // R13_ABORT R14_ABORT
 | 
			
		||||
    std::array<u32, 2> Reg_undef{}; // R13 UNDEF R14 UNDEF
 | 
			
		||||
    std::array<u32, 2> Reg_irq{};   // R13_IRQ R14_IRQ
 | 
			
		||||
    std::array<u32, 7> Reg_firq{};  // R8---R14 FIRQ
 | 
			
		||||
    std::array<u32, 7> Spsr{};      // The exception psr's
 | 
			
		||||
    std::array<u32, CP15_REGISTER_COUNT> CP15{};
 | 
			
		||||
 | 
			
		||||
    // FPSID, FPSCR, and FPEXC
 | 
			
		||||
    std::array<u32, VFP_SYSTEM_REGISTER_COUNT> VFP{};
 | 
			
		||||
 | 
			
		||||
    // VFPv2 and VFPv3-D16 has 16 doubleword registers (D0-D16 or S0-S31).
 | 
			
		||||
    // VFPv3-D32/ASIMD may have up to 32 doubleword registers (D0-D31),
 | 
			
		||||
    // and only 32 singleword registers are accessible (S0-S31).
 | 
			
		||||
    std::array<u32, 64> ExtReg{};
 | 
			
		||||
 | 
			
		||||
    u32 Emulate; // To start and stop emulation
 | 
			
		||||
    u32 Cpsr;    // The current PSR
 | 
			
		||||
    u32 Spsr_copy;
 | 
			
		||||
    u32 phys_pc;
 | 
			
		||||
 | 
			
		||||
    u32 Mode; // The current mode
 | 
			
		||||
    u32 Bank; // The current register bank
 | 
			
		||||
 | 
			
		||||
    u32 NFlag, ZFlag, CFlag, VFlag, IFFlags; // Dummy flags for speed
 | 
			
		||||
    unsigned int shifter_carry_out;
 | 
			
		||||
 | 
			
		||||
    u32 TFlag; // Thumb state
 | 
			
		||||
 | 
			
		||||
    unsigned long long NumInstrs; // The number of instructions executed
 | 
			
		||||
    unsigned NumInstrsToExecute;
 | 
			
		||||
 | 
			
		||||
    unsigned NresetSig; // Reset the processor
 | 
			
		||||
    unsigned NfiqSig;
 | 
			
		||||
    unsigned NirqSig;
 | 
			
		||||
 | 
			
		||||
    unsigned abortSig;
 | 
			
		||||
    unsigned NtransSig;
 | 
			
		||||
    unsigned bigendSig;
 | 
			
		||||
    unsigned syscallSig;
 | 
			
		||||
 | 
			
		||||
    // TODO(bunnei): Move this cache to a better place - it should be per codeset (likely per
 | 
			
		||||
    // process for our purposes), not per ARMul_State (which tracks CPU core state).
 | 
			
		||||
    std::unordered_map<u32, std::size_t> instruction_cache;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    void ResetMPCoreCP15Registers();
 | 
			
		||||
 | 
			
		||||
    // Defines a reservation granule of 2 words, which protects the first 2 words starting at the
 | 
			
		||||
    // tag. This is the smallest granule allowed by the v7 spec, and is coincidentally just large
 | 
			
		||||
    // enough to support LDR/STREXD.
 | 
			
		||||
    static const u32 RESERVATION_GRANULE_MASK = 0xFFFFFFF8;
 | 
			
		||||
 | 
			
		||||
    u32 exclusive_tag; // The address for which the local monitor is in exclusive access mode
 | 
			
		||||
    bool exclusive_state;
 | 
			
		||||
};
 | 
			
		||||
@ -1,189 +0,0 @@
 | 
			
		||||
/*  armsupp.c -- ARMulator support code:  ARM6 Instruction Emulator.
 | 
			
		||||
    Copyright (C) 1994 Advanced RISC Machines Ltd.
 | 
			
		||||
 | 
			
		||||
    This program is free software; you can redistribute it and/or modify
 | 
			
		||||
    it under the terms of the GNU General Public License as published by
 | 
			
		||||
    the Free Software Foundation; either version 2 of the License, or
 | 
			
		||||
    (at your option) any later version.
 | 
			
		||||
 | 
			
		||||
    This program is distributed in the hope that it will be useful,
 | 
			
		||||
    but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
    GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
    You should have received a copy of the GNU General Public License
 | 
			
		||||
    along with this program; if not, write to the Free Software
 | 
			
		||||
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
 | 
			
		||||
 | 
			
		||||
#include "common/logging/log.h"
 | 
			
		||||
#include "core/arm/skyeye_common/arm_regformat.h"
 | 
			
		||||
#include "core/arm/skyeye_common/armstate.h"
 | 
			
		||||
#include "core/arm/skyeye_common/armsupp.h"
 | 
			
		||||
 | 
			
		||||
// Unsigned sum of absolute difference
 | 
			
		||||
u8 ARMul_UnsignedAbsoluteDifference(u8 left, u8 right) {
 | 
			
		||||
    if (left > right)
 | 
			
		||||
        return left - right;
 | 
			
		||||
 | 
			
		||||
    return right - left;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Add with carry, indicates if a carry-out or signed overflow occurred.
 | 
			
		||||
u32 AddWithCarry(u32 left, u32 right, u32 carry_in, bool* carry_out_occurred,
 | 
			
		||||
                 bool* overflow_occurred) {
 | 
			
		||||
    u64 unsigned_sum = (u64)left + (u64)right + (u64)carry_in;
 | 
			
		||||
    s64 signed_sum = (s64)(s32)left + (s64)(s32)right + (s64)carry_in;
 | 
			
		||||
    u64 result = (unsigned_sum & 0xFFFFFFFF);
 | 
			
		||||
 | 
			
		||||
    if (carry_out_occurred)
 | 
			
		||||
        *carry_out_occurred = (result != unsigned_sum);
 | 
			
		||||
 | 
			
		||||
    if (overflow_occurred)
 | 
			
		||||
        *overflow_occurred = ((s64)(s32)result != signed_sum);
 | 
			
		||||
 | 
			
		||||
    return (u32)result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Compute whether an addition of A and B, giving RESULT, overflowed.
 | 
			
		||||
bool AddOverflow(u32 a, u32 b, u32 result) {
 | 
			
		||||
    return ((NEG(a) && NEG(b) && POS(result)) || (POS(a) && POS(b) && NEG(result)));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Compute whether a subtraction of A and B, giving RESULT, overflowed.
 | 
			
		||||
bool SubOverflow(u32 a, u32 b, u32 result) {
 | 
			
		||||
    return ((NEG(a) && POS(b) && POS(result)) || (POS(a) && NEG(b) && NEG(result)));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Returns true if the Q flag should be set as a result of overflow.
 | 
			
		||||
bool ARMul_AddOverflowQ(u32 a, u32 b) {
 | 
			
		||||
    u32 result = a + b;
 | 
			
		||||
    if (((result ^ a) & (u32)0x80000000) && ((a ^ b) & (u32)0x80000000) == 0)
 | 
			
		||||
        return true;
 | 
			
		||||
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 8-bit signed saturated addition
 | 
			
		||||
u8 ARMul_SignedSaturatedAdd8(u8 left, u8 right) {
 | 
			
		||||
    u8 result = left + right;
 | 
			
		||||
 | 
			
		||||
    if (((result ^ left) & 0x80) && ((left ^ right) & 0x80) == 0) {
 | 
			
		||||
        if (left & 0x80)
 | 
			
		||||
            result = 0x80;
 | 
			
		||||
        else
 | 
			
		||||
            result = 0x7F;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 8-bit signed saturated subtraction
 | 
			
		||||
u8 ARMul_SignedSaturatedSub8(u8 left, u8 right) {
 | 
			
		||||
    u8 result = left - right;
 | 
			
		||||
 | 
			
		||||
    if (((result ^ left) & 0x80) && ((left ^ right) & 0x80) != 0) {
 | 
			
		||||
        if (left & 0x80)
 | 
			
		||||
            result = 0x80;
 | 
			
		||||
        else
 | 
			
		||||
            result = 0x7F;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 16-bit signed saturated addition
 | 
			
		||||
u16 ARMul_SignedSaturatedAdd16(u16 left, u16 right) {
 | 
			
		||||
    u16 result = left + right;
 | 
			
		||||
 | 
			
		||||
    if (((result ^ left) & 0x8000) && ((left ^ right) & 0x8000) == 0) {
 | 
			
		||||
        if (left & 0x8000)
 | 
			
		||||
            result = 0x8000;
 | 
			
		||||
        else
 | 
			
		||||
            result = 0x7FFF;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 16-bit signed saturated subtraction
 | 
			
		||||
u16 ARMul_SignedSaturatedSub16(u16 left, u16 right) {
 | 
			
		||||
    u16 result = left - right;
 | 
			
		||||
 | 
			
		||||
    if (((result ^ left) & 0x8000) && ((left ^ right) & 0x8000) != 0) {
 | 
			
		||||
        if (left & 0x8000)
 | 
			
		||||
            result = 0x8000;
 | 
			
		||||
        else
 | 
			
		||||
            result = 0x7FFF;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 8-bit unsigned saturated addition
 | 
			
		||||
u8 ARMul_UnsignedSaturatedAdd8(u8 left, u8 right) {
 | 
			
		||||
    u8 result = left + right;
 | 
			
		||||
 | 
			
		||||
    if (result < left)
 | 
			
		||||
        result = 0xFF;
 | 
			
		||||
 | 
			
		||||
    return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 16-bit unsigned saturated addition
 | 
			
		||||
u16 ARMul_UnsignedSaturatedAdd16(u16 left, u16 right) {
 | 
			
		||||
    u16 result = left + right;
 | 
			
		||||
 | 
			
		||||
    if (result < left)
 | 
			
		||||
        result = 0xFFFF;
 | 
			
		||||
 | 
			
		||||
    return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 8-bit unsigned saturated subtraction
 | 
			
		||||
u8 ARMul_UnsignedSaturatedSub8(u8 left, u8 right) {
 | 
			
		||||
    if (left <= right)
 | 
			
		||||
        return 0;
 | 
			
		||||
 | 
			
		||||
    return left - right;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 16-bit unsigned saturated subtraction
 | 
			
		||||
u16 ARMul_UnsignedSaturatedSub16(u16 left, u16 right) {
 | 
			
		||||
    if (left <= right)
 | 
			
		||||
        return 0;
 | 
			
		||||
 | 
			
		||||
    return left - right;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Signed saturation.
 | 
			
		||||
u32 ARMul_SignedSatQ(s32 value, u8 shift, bool* saturation_occurred) {
 | 
			
		||||
    const u32 max = (1 << shift) - 1;
 | 
			
		||||
    const s32 top = (value >> shift);
 | 
			
		||||
 | 
			
		||||
    if (top > 0) {
 | 
			
		||||
        *saturation_occurred = true;
 | 
			
		||||
        return max;
 | 
			
		||||
    } else if (top < -1) {
 | 
			
		||||
        *saturation_occurred = true;
 | 
			
		||||
        return ~max;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    *saturation_occurred = false;
 | 
			
		||||
    return (u32)value;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Unsigned saturation
 | 
			
		||||
u32 ARMul_UnsignedSatQ(s32 value, u8 shift, bool* saturation_occurred) {
 | 
			
		||||
    const u32 max = (1 << shift) - 1;
 | 
			
		||||
 | 
			
		||||
    if (value < 0) {
 | 
			
		||||
        *saturation_occurred = true;
 | 
			
		||||
        return 0;
 | 
			
		||||
    } else if ((u32)value > max) {
 | 
			
		||||
        *saturation_occurred = true;
 | 
			
		||||
        return max;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    *saturation_occurred = false;
 | 
			
		||||
    return (u32)value;
 | 
			
		||||
}
 | 
			
		||||
@ -1,32 +0,0 @@
 | 
			
		||||
// Copyright 2014 Citra Emulator Project
 | 
			
		||||
// Licensed under GPLv2 or any later version
 | 
			
		||||
// Refer to the license.txt file included.
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "common/common_types.h"
 | 
			
		||||
 | 
			
		||||
#define BITS(s, a, b) ((s << ((sizeof(s) * 8 - 1) - b)) >> (sizeof(s) * 8 - b + a - 1))
 | 
			
		||||
#define BIT(s, n) ((s >> (n)) & 1)
 | 
			
		||||
 | 
			
		||||
#define POS(i) ((~(i)) >> 31)
 | 
			
		||||
#define NEG(i) ((i) >> 31)
 | 
			
		||||
 | 
			
		||||
bool AddOverflow(u32, u32, u32);
 | 
			
		||||
bool SubOverflow(u32, u32, u32);
 | 
			
		||||
 | 
			
		||||
u32 AddWithCarry(u32, u32, u32, bool*, bool*);
 | 
			
		||||
bool ARMul_AddOverflowQ(u32, u32);
 | 
			
		||||
 | 
			
		||||
u8 ARMul_SignedSaturatedAdd8(u8, u8);
 | 
			
		||||
u8 ARMul_SignedSaturatedSub8(u8, u8);
 | 
			
		||||
u16 ARMul_SignedSaturatedAdd16(u16, u16);
 | 
			
		||||
u16 ARMul_SignedSaturatedSub16(u16, u16);
 | 
			
		||||
 | 
			
		||||
u8 ARMul_UnsignedSaturatedAdd8(u8, u8);
 | 
			
		||||
u16 ARMul_UnsignedSaturatedAdd16(u16, u16);
 | 
			
		||||
u8 ARMul_UnsignedSaturatedSub8(u8, u8);
 | 
			
		||||
u16 ARMul_UnsignedSaturatedSub16(u16, u16);
 | 
			
		||||
u8 ARMul_UnsignedAbsoluteDifference(u8, u8);
 | 
			
		||||
u32 ARMul_SignedSatQ(s32, u8, bool*);
 | 
			
		||||
u32 ARMul_UnsignedSatQ(s32, u8, bool*);
 | 
			
		||||
@ -1,83 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * arch/arm/include/asm/vfp.h
 | 
			
		||||
 *
 | 
			
		||||
 * VFP register definitions.
 | 
			
		||||
 * First, the standard VFP set.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
// ARM11 MPCore FPSID Information
 | 
			
		||||
// Note that these are used as values and not as flags.
 | 
			
		||||
enum : u32 {
 | 
			
		||||
    VFP_FPSID_IMPLMEN = 0x41, // Implementation code. Should be the same as cp15 0 c0 0
 | 
			
		||||
    VFP_FPSID_SW = 0,         // Software emulation bit value
 | 
			
		||||
    VFP_FPSID_SUBARCH = 0x1,  // Subarchitecture version number
 | 
			
		||||
    VFP_FPSID_PARTNUM = 0x20, // Part number
 | 
			
		||||
    VFP_FPSID_VARIANT = 0xB,  // Variant number
 | 
			
		||||
    VFP_FPSID_REVISION = 0x4  // Revision number
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// FPEXC bits
 | 
			
		||||
enum : u32 {
 | 
			
		||||
    FPEXC_EX = (1U << 31U),
 | 
			
		||||
    FPEXC_EN = (1 << 30),
 | 
			
		||||
    FPEXC_DEX = (1 << 29),
 | 
			
		||||
    FPEXC_FP2V = (1 << 28),
 | 
			
		||||
    FPEXC_VV = (1 << 27),
 | 
			
		||||
    FPEXC_TFV = (1 << 26),
 | 
			
		||||
    FPEXC_LENGTH_BIT = (8),
 | 
			
		||||
    FPEXC_LENGTH_MASK = (7 << FPEXC_LENGTH_BIT),
 | 
			
		||||
    FPEXC_IDF = (1 << 7),
 | 
			
		||||
    FPEXC_IXF = (1 << 4),
 | 
			
		||||
    FPEXC_UFF = (1 << 3),
 | 
			
		||||
    FPEXC_OFF = (1 << 2),
 | 
			
		||||
    FPEXC_DZF = (1 << 1),
 | 
			
		||||
    FPEXC_IOF = (1 << 0),
 | 
			
		||||
    FPEXC_TRAP_MASK = (FPEXC_IDF | FPEXC_IXF | FPEXC_UFF | FPEXC_OFF | FPEXC_DZF | FPEXC_IOF)
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// FPSCR Flags
 | 
			
		||||
enum : u32 {
 | 
			
		||||
    FPSCR_NFLAG = (1U << 31U), // Negative condition flag
 | 
			
		||||
    FPSCR_ZFLAG = (1 << 30),   // Zero condition flag
 | 
			
		||||
    FPSCR_CFLAG = (1 << 29),   // Carry condition flag
 | 
			
		||||
    FPSCR_VFLAG = (1 << 28),   // Overflow condition flag
 | 
			
		||||
 | 
			
		||||
    FPSCR_QC = (1 << 27),            // Cumulative saturation bit
 | 
			
		||||
    FPSCR_AHP = (1 << 26),           // Alternative half-precision control bit
 | 
			
		||||
    FPSCR_DEFAULT_NAN = (1 << 25),   // Default NaN mode control bit
 | 
			
		||||
    FPSCR_FLUSH_TO_ZERO = (1 << 24), // Flush-to-zero mode control bit
 | 
			
		||||
    FPSCR_RMODE_MASK = (3 << 22),    // Rounding Mode bit mask
 | 
			
		||||
    FPSCR_STRIDE_MASK = (3 << 20),   // Vector stride bit mask
 | 
			
		||||
    FPSCR_LENGTH_MASK = (7 << 16),   // Vector length bit mask
 | 
			
		||||
 | 
			
		||||
    FPSCR_IDE = (1 << 15), // Input Denormal exception trap enable.
 | 
			
		||||
    FPSCR_IXE = (1 << 12), // Inexact exception trap enable
 | 
			
		||||
    FPSCR_UFE = (1 << 11), // Undeflow exception trap enable
 | 
			
		||||
    FPSCR_OFE = (1 << 10), // Overflow exception trap enable
 | 
			
		||||
    FPSCR_DZE = (1 << 9),  // Division by Zero exception trap enable
 | 
			
		||||
    FPSCR_IOE = (1 << 8),  // Invalid Operation exception trap enable
 | 
			
		||||
 | 
			
		||||
    FPSCR_IDC = (1 << 7), // Input Denormal cumulative exception bit
 | 
			
		||||
    FPSCR_IXC = (1 << 4), // Inexact cumulative exception bit
 | 
			
		||||
    FPSCR_UFC = (1 << 3), // Undeflow cumulative exception bit
 | 
			
		||||
    FPSCR_OFC = (1 << 2), // Overflow cumulative exception bit
 | 
			
		||||
    FPSCR_DZC = (1 << 1), // Division by Zero cumulative exception bit
 | 
			
		||||
    FPSCR_IOC = (1 << 0), // Invalid Operation cumulative exception bit
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// FPSCR bit offsets
 | 
			
		||||
enum : u32 {
 | 
			
		||||
    FPSCR_RMODE_BIT = 22,
 | 
			
		||||
    FPSCR_STRIDE_BIT = 20,
 | 
			
		||||
    FPSCR_LENGTH_BIT = 16,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// FPSCR rounding modes
 | 
			
		||||
enum : u32 {
 | 
			
		||||
    FPSCR_ROUND_NEAREST = (0 << 22),
 | 
			
		||||
    FPSCR_ROUND_PLUSINF = (1 << 22),
 | 
			
		||||
    FPSCR_ROUND_MINUSINF = (2 << 22),
 | 
			
		||||
    FPSCR_ROUND_TOZERO = (3 << 22)
 | 
			
		||||
};
 | 
			
		||||
@ -1,137 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
    armvfp.c - ARM VFPv3 emulation unit
 | 
			
		||||
    Copyright (C) 2003 Skyeye Develop Group
 | 
			
		||||
    for help please send mail to <skyeye-developer@lists.gro.clinux.org>
 | 
			
		||||
 | 
			
		||||
    This program is free software; you can redistribute it and/or modify
 | 
			
		||||
    it under the terms of the GNU General Public License as published by
 | 
			
		||||
    the Free Software Foundation; either version 2 of the License, or
 | 
			
		||||
    (at your option) any later version.
 | 
			
		||||
 | 
			
		||||
    This program is distributed in the hope that it will be useful,
 | 
			
		||||
    but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
    GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
    You should have received a copy of the GNU General Public License
 | 
			
		||||
    along with this program; if not, write to the Free Software
 | 
			
		||||
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
/* Note: this file handles interface with arm core and vfp registers */
 | 
			
		||||
 | 
			
		||||
#include "common/common_funcs.h"
 | 
			
		||||
#include "common/common_types.h"
 | 
			
		||||
#include "common/logging/log.h"
 | 
			
		||||
#include "core/arm/skyeye_common/armstate.h"
 | 
			
		||||
#include "core/arm/skyeye_common/vfp/asm_vfp.h"
 | 
			
		||||
#include "core/arm/skyeye_common/vfp/vfp.h"
 | 
			
		||||
 | 
			
		||||
void VFPInit(ARMul_State* state) {
 | 
			
		||||
    state->VFP[VFP_FPSID] = VFP_FPSID_IMPLMEN << 24 | VFP_FPSID_SW << 23 | VFP_FPSID_SUBARCH << 16 |
 | 
			
		||||
                            VFP_FPSID_PARTNUM << 8 | VFP_FPSID_VARIANT << 4 | VFP_FPSID_REVISION;
 | 
			
		||||
    state->VFP[VFP_FPEXC] = 0;
 | 
			
		||||
    state->VFP[VFP_FPSCR] = 0;
 | 
			
		||||
 | 
			
		||||
    // ARM11 MPCore instruction register reset values.
 | 
			
		||||
    state->VFP[VFP_FPINST] = 0xEE000A00;
 | 
			
		||||
    state->VFP[VFP_FPINST2] = 0;
 | 
			
		||||
 | 
			
		||||
    // ARM11 MPCore feature register values.
 | 
			
		||||
    state->VFP[VFP_MVFR0] = 0x11111111;
 | 
			
		||||
    state->VFP[VFP_MVFR1] = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void VMOVBRS(ARMul_State* state, u32 to_arm, u32 t, u32 n, u32* value) {
 | 
			
		||||
    if (to_arm) {
 | 
			
		||||
        *value = state->ExtReg[n];
 | 
			
		||||
    } else {
 | 
			
		||||
        state->ExtReg[n] = *value;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void VMOVBRRD(ARMul_State* state, u32 to_arm, u32 t, u32 t2, u32 n, u32* value1, u32* value2) {
 | 
			
		||||
    if (to_arm) {
 | 
			
		||||
        *value2 = state->ExtReg[n * 2 + 1];
 | 
			
		||||
        *value1 = state->ExtReg[n * 2];
 | 
			
		||||
    } else {
 | 
			
		||||
        state->ExtReg[n * 2 + 1] = *value2;
 | 
			
		||||
        state->ExtReg[n * 2] = *value1;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
void VMOVBRRSS(ARMul_State* state, u32 to_arm, u32 t, u32 t2, u32 n, u32* value1, u32* value2) {
 | 
			
		||||
    if (to_arm) {
 | 
			
		||||
        *value1 = state->ExtReg[n + 0];
 | 
			
		||||
        *value2 = state->ExtReg[n + 1];
 | 
			
		||||
    } else {
 | 
			
		||||
        state->ExtReg[n + 0] = *value1;
 | 
			
		||||
        state->ExtReg[n + 1] = *value2;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void VMOVI(ARMul_State* state, u32 single, u32 d, u32 imm) {
 | 
			
		||||
    if (single) {
 | 
			
		||||
        state->ExtReg[d] = imm;
 | 
			
		||||
    } else {
 | 
			
		||||
        /* Check endian please */
 | 
			
		||||
        state->ExtReg[d * 2 + 1] = imm;
 | 
			
		||||
        state->ExtReg[d * 2] = 0;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
void VMOVR(ARMul_State* state, u32 single, u32 d, u32 m) {
 | 
			
		||||
    if (single) {
 | 
			
		||||
        state->ExtReg[d] = state->ExtReg[m];
 | 
			
		||||
    } else {
 | 
			
		||||
        /* Check endian please */
 | 
			
		||||
        state->ExtReg[d * 2 + 1] = state->ExtReg[m * 2 + 1];
 | 
			
		||||
        state->ExtReg[d * 2] = state->ExtReg[m * 2];
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Miscellaneous functions */
 | 
			
		||||
s32 vfp_get_float(ARMul_State* state, unsigned int reg) {
 | 
			
		||||
    LOG_TRACE(Core_ARM, "VFP get float: s%d=[%08x]", reg, state->ExtReg[reg]);
 | 
			
		||||
    return state->ExtReg[reg];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void vfp_put_float(ARMul_State* state, s32 val, unsigned int reg) {
 | 
			
		||||
    LOG_TRACE(Core_ARM, "VFP put float: s%d <= [%08x]", reg, val);
 | 
			
		||||
    state->ExtReg[reg] = val;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
u64 vfp_get_double(ARMul_State* state, unsigned int reg) {
 | 
			
		||||
    u64 result = ((u64)state->ExtReg[reg * 2 + 1]) << 32 | state->ExtReg[reg * 2];
 | 
			
		||||
    LOG_TRACE(Core_ARM, "VFP get double: s[%d-%d]=[%016llx]", reg * 2 + 1, reg * 2, result);
 | 
			
		||||
    return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void vfp_put_double(ARMul_State* state, u64 val, unsigned int reg) {
 | 
			
		||||
    LOG_TRACE(Core_ARM, "VFP put double: s[%d-%d] <= [%08x-%08x]", reg * 2 + 1, reg * 2,
 | 
			
		||||
              (u32)(val >> 32), (u32)(val & 0xffffffff));
 | 
			
		||||
    state->ExtReg[reg * 2] = (u32)(val & 0xffffffff);
 | 
			
		||||
    state->ExtReg[reg * 2 + 1] = (u32)(val >> 32);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Process bitmask of exception conditions. (from vfpmodule.c)
 | 
			
		||||
 */
 | 
			
		||||
void vfp_raise_exceptions(ARMul_State* state, u32 exceptions, u32 inst, u32 fpscr) {
 | 
			
		||||
    LOG_TRACE(Core_ARM, "VFP: raising exceptions %08x", exceptions);
 | 
			
		||||
 | 
			
		||||
    if (exceptions == VFP_EXCEPTION_ERROR) {
 | 
			
		||||
        LOG_CRITICAL(Core_ARM, "unhandled bounce %x", inst);
 | 
			
		||||
        Crash();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /*
 | 
			
		||||
     * If any of the status flags are set, update the FPSCR.
 | 
			
		||||
     * Comparison instructions always return at least one of
 | 
			
		||||
     * these flags set.
 | 
			
		||||
     */
 | 
			
		||||
    if (exceptions & (FPSCR_NFLAG | FPSCR_ZFLAG | FPSCR_CFLAG | FPSCR_VFLAG))
 | 
			
		||||
        fpscr &= ~(FPSCR_NFLAG | FPSCR_ZFLAG | FPSCR_CFLAG | FPSCR_VFLAG);
 | 
			
		||||
 | 
			
		||||
    fpscr |= exceptions;
 | 
			
		||||
 | 
			
		||||
    state->VFP[VFP_FPSCR] = fpscr;
 | 
			
		||||
}
 | 
			
		||||
@ -1,43 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
    vfp/vfp.h - ARM VFPv3 emulation unit - vfp interface
 | 
			
		||||
    Copyright (C) 2003 Skyeye Develop Group
 | 
			
		||||
    for help please send mail to <skyeye-developer@lists.gro.clinux.org>
 | 
			
		||||
 | 
			
		||||
    This program is free software; you can redistribute it and/or modify
 | 
			
		||||
    it under the terms of the GNU General Public License as published by
 | 
			
		||||
    the Free Software Foundation; either version 2 of the License, or
 | 
			
		||||
    (at your option) any later version.
 | 
			
		||||
 | 
			
		||||
    This program is distributed in the hope that it will be useful,
 | 
			
		||||
    but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
    GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
    You should have received a copy of the GNU General Public License
 | 
			
		||||
    along with this program; if not, write to the Free Software
 | 
			
		||||
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "core/arm/skyeye_common/vfp/vfp_helper.h" /* for references to cdp SoftFloat functions */
 | 
			
		||||
 | 
			
		||||
#define VFP_DEBUG_UNTESTED(x) LOG_TRACE(Core_ARM, "in func %s, " #x " untested", __FUNCTION__);
 | 
			
		||||
#define CHECK_VFP_ENABLED
 | 
			
		||||
#define CHECK_VFP_CDP_RET vfp_raise_exceptions(cpu, ret, inst_cream->instr, cpu->VFP[VFP_FPSCR]);
 | 
			
		||||
 | 
			
		||||
void VFPInit(ARMul_State* state);
 | 
			
		||||
 | 
			
		||||
s32 vfp_get_float(ARMul_State* state, u32 reg);
 | 
			
		||||
void vfp_put_float(ARMul_State* state, s32 val, u32 reg);
 | 
			
		||||
u64 vfp_get_double(ARMul_State* state, u32 reg);
 | 
			
		||||
void vfp_put_double(ARMul_State* state, u64 val, u32 reg);
 | 
			
		||||
void vfp_raise_exceptions(ARMul_State* state, u32 exceptions, u32 inst, u32 fpscr);
 | 
			
		||||
u32 vfp_single_cpdo(ARMul_State* state, u32 inst, u32 fpscr);
 | 
			
		||||
u32 vfp_double_cpdo(ARMul_State* state, u32 inst, u32 fpscr);
 | 
			
		||||
 | 
			
		||||
void VMOVBRS(ARMul_State* state, u32 to_arm, u32 t, u32 n, u32* value);
 | 
			
		||||
void VMOVBRRD(ARMul_State* state, u32 to_arm, u32 t, u32 t2, u32 n, u32* value1, u32* value2);
 | 
			
		||||
void VMOVBRRSS(ARMul_State* state, u32 to_arm, u32 t, u32 t2, u32 n, u32* value1, u32* value2);
 | 
			
		||||
void VMOVI(ARMul_State* state, u32 single, u32 d, u32 imm);
 | 
			
		||||
void VMOVR(ARMul_State* state, u32 single, u32 d, u32 imm);
 | 
			
		||||
@ -1,433 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
    vfp/vfp.h - ARM VFPv3 emulation unit - SoftFloat lib helper
 | 
			
		||||
    Copyright (C) 2003 Skyeye Develop Group
 | 
			
		||||
    for help please send mail to <skyeye-developer@lists.gro.clinux.org>
 | 
			
		||||
 | 
			
		||||
    This program is free software; you can redistribute it and/or modify
 | 
			
		||||
    it under the terms of the GNU General Public License as published by
 | 
			
		||||
    the Free Software Foundation; either version 2 of the License, or
 | 
			
		||||
    (at your option) any later version.
 | 
			
		||||
 | 
			
		||||
    This program is distributed in the hope that it will be useful,
 | 
			
		||||
    but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
    GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
    You should have received a copy of the GNU General Public License
 | 
			
		||||
    along with this program; if not, write to the Free Software
 | 
			
		||||
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 *  The following code is derivative from Linux Android kernel vfp
 | 
			
		||||
 *  floating point support.
 | 
			
		||||
 *
 | 
			
		||||
 *  Copyright (C) 2004 ARM Limited.
 | 
			
		||||
 *  Written by Deep Blue Solutions Limited.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software; you can redistribute it and/or modify
 | 
			
		||||
 * it under the terms of the GNU General Public License version 2 as
 | 
			
		||||
 * published by the Free Software Foundation.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <cstdio>
 | 
			
		||||
#include "common/common_types.h"
 | 
			
		||||
#include "core/arm/skyeye_common/armstate.h"
 | 
			
		||||
#include "core/arm/skyeye_common/vfp/asm_vfp.h"
 | 
			
		||||
 | 
			
		||||
#define do_div(n, base)                                                                            \
 | 
			
		||||
    { n /= base; }
 | 
			
		||||
 | 
			
		||||
enum : u32 {
 | 
			
		||||
    FOP_MASK = 0x00b00040,
 | 
			
		||||
    FOP_FMAC = 0x00000000,
 | 
			
		||||
    FOP_FNMAC = 0x00000040,
 | 
			
		||||
    FOP_FMSC = 0x00100000,
 | 
			
		||||
    FOP_FNMSC = 0x00100040,
 | 
			
		||||
    FOP_FMUL = 0x00200000,
 | 
			
		||||
    FOP_FNMUL = 0x00200040,
 | 
			
		||||
    FOP_FADD = 0x00300000,
 | 
			
		||||
    FOP_FSUB = 0x00300040,
 | 
			
		||||
    FOP_FDIV = 0x00800000,
 | 
			
		||||
    FOP_EXT = 0x00b00040
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define FOP_TO_IDX(inst) ((inst & 0x00b00000) >> 20 | (inst & (1 << 6)) >> 4)
 | 
			
		||||
 | 
			
		||||
enum : u32 {
 | 
			
		||||
    FEXT_MASK = 0x000f0080,
 | 
			
		||||
    FEXT_FCPY = 0x00000000,
 | 
			
		||||
    FEXT_FABS = 0x00000080,
 | 
			
		||||
    FEXT_FNEG = 0x00010000,
 | 
			
		||||
    FEXT_FSQRT = 0x00010080,
 | 
			
		||||
    FEXT_FCMP = 0x00040000,
 | 
			
		||||
    FEXT_FCMPE = 0x00040080,
 | 
			
		||||
    FEXT_FCMPZ = 0x00050000,
 | 
			
		||||
    FEXT_FCMPEZ = 0x00050080,
 | 
			
		||||
    FEXT_FCVT = 0x00070080,
 | 
			
		||||
    FEXT_FUITO = 0x00080000,
 | 
			
		||||
    FEXT_FSITO = 0x00080080,
 | 
			
		||||
    FEXT_FTOUI = 0x000c0000,
 | 
			
		||||
    FEXT_FTOUIZ = 0x000c0080,
 | 
			
		||||
    FEXT_FTOSI = 0x000d0000,
 | 
			
		||||
    FEXT_FTOSIZ = 0x000d0080
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define FEXT_TO_IDX(inst) ((inst & 0x000f0000) >> 15 | (inst & (1 << 7)) >> 7)
 | 
			
		||||
 | 
			
		||||
#define vfp_get_sd(inst) ((inst & 0x0000f000) >> 11 | (inst & (1 << 22)) >> 22)
 | 
			
		||||
#define vfp_get_dd(inst) ((inst & 0x0000f000) >> 12 | (inst & (1 << 22)) >> 18)
 | 
			
		||||
#define vfp_get_sm(inst) ((inst & 0x0000000f) << 1 | (inst & (1 << 5)) >> 5)
 | 
			
		||||
#define vfp_get_dm(inst) ((inst & 0x0000000f) | (inst & (1 << 5)) >> 1)
 | 
			
		||||
#define vfp_get_sn(inst) ((inst & 0x000f0000) >> 15 | (inst & (1 << 7)) >> 7)
 | 
			
		||||
#define vfp_get_dn(inst) ((inst & 0x000f0000) >> 16 | (inst & (1 << 7)) >> 3)
 | 
			
		||||
 | 
			
		||||
#define vfp_single(inst) (((inst)&0x0000f00) == 0xa00)
 | 
			
		||||
 | 
			
		||||
inline u32 vfp_shiftright32jamming(u32 val, unsigned int shift) {
 | 
			
		||||
    if (shift) {
 | 
			
		||||
        if (shift < 32)
 | 
			
		||||
            val = val >> shift | ((val << (32 - shift)) != 0);
 | 
			
		||||
        else
 | 
			
		||||
            val = val != 0;
 | 
			
		||||
    }
 | 
			
		||||
    return val;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline u64 vfp_shiftright64jamming(u64 val, unsigned int shift) {
 | 
			
		||||
    if (shift) {
 | 
			
		||||
        if (shift < 64)
 | 
			
		||||
            val = val >> shift | ((val << (64 - shift)) != 0);
 | 
			
		||||
        else
 | 
			
		||||
            val = val != 0;
 | 
			
		||||
    }
 | 
			
		||||
    return val;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline u32 vfp_hi64to32jamming(u64 val) {
 | 
			
		||||
    u32 v;
 | 
			
		||||
    u32 highval = val >> 32;
 | 
			
		||||
    u32 lowval = val & 0xffffffff;
 | 
			
		||||
 | 
			
		||||
    if (lowval >= 1)
 | 
			
		||||
        v = highval | 1;
 | 
			
		||||
    else
 | 
			
		||||
        v = highval;
 | 
			
		||||
 | 
			
		||||
    return v;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline void add128(u64* resh, u64* resl, u64 nh, u64 nl, u64 mh, u64 ml) {
 | 
			
		||||
    *resl = nl + ml;
 | 
			
		||||
    *resh = nh + mh;
 | 
			
		||||
    if (*resl < nl)
 | 
			
		||||
        *resh += 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline void sub128(u64* resh, u64* resl, u64 nh, u64 nl, u64 mh, u64 ml) {
 | 
			
		||||
    *resl = nl - ml;
 | 
			
		||||
    *resh = nh - mh;
 | 
			
		||||
    if (*resl > nl)
 | 
			
		||||
        *resh -= 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline void mul64to128(u64* resh, u64* resl, u64 n, u64 m) {
 | 
			
		||||
    u32 nh, nl, mh, ml;
 | 
			
		||||
    u64 rh, rma, rmb, rl;
 | 
			
		||||
 | 
			
		||||
    nl = static_cast<u32>(n);
 | 
			
		||||
    ml = static_cast<u32>(m);
 | 
			
		||||
    rl = (u64)nl * ml;
 | 
			
		||||
 | 
			
		||||
    nh = n >> 32;
 | 
			
		||||
    rma = (u64)nh * ml;
 | 
			
		||||
 | 
			
		||||
    mh = m >> 32;
 | 
			
		||||
    rmb = (u64)nl * mh;
 | 
			
		||||
    rma += rmb;
 | 
			
		||||
 | 
			
		||||
    rh = (u64)nh * mh;
 | 
			
		||||
    rh += ((u64)(rma < rmb) << 32) + (rma >> 32);
 | 
			
		||||
 | 
			
		||||
    rma <<= 32;
 | 
			
		||||
    rl += rma;
 | 
			
		||||
    rh += (rl < rma);
 | 
			
		||||
 | 
			
		||||
    *resl = rl;
 | 
			
		||||
    *resh = rh;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline void shift64left(u64* resh, u64* resl, u64 n) {
 | 
			
		||||
    *resh = n >> 63;
 | 
			
		||||
    *resl = n << 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline u64 vfp_hi64multiply64(u64 n, u64 m) {
 | 
			
		||||
    u64 rh, rl;
 | 
			
		||||
    mul64to128(&rh, &rl, n, m);
 | 
			
		||||
    return rh | (rl != 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline u64 vfp_estimate_div128to64(u64 nh, u64 nl, u64 m) {
 | 
			
		||||
    u64 mh, ml, remh, reml, termh, terml, z;
 | 
			
		||||
 | 
			
		||||
    if (nh >= m)
 | 
			
		||||
        return ~0ULL;
 | 
			
		||||
    mh = m >> 32;
 | 
			
		||||
    if (mh << 32 <= nh) {
 | 
			
		||||
        z = 0xffffffff00000000ULL;
 | 
			
		||||
    } else {
 | 
			
		||||
        z = nh;
 | 
			
		||||
        do_div(z, mh);
 | 
			
		||||
        z <<= 32;
 | 
			
		||||
    }
 | 
			
		||||
    mul64to128(&termh, &terml, m, z);
 | 
			
		||||
    sub128(&remh, &reml, nh, nl, termh, terml);
 | 
			
		||||
    ml = m << 32;
 | 
			
		||||
    while ((s64)remh < 0) {
 | 
			
		||||
        z -= 0x100000000ULL;
 | 
			
		||||
        add128(&remh, &reml, remh, reml, mh, ml);
 | 
			
		||||
    }
 | 
			
		||||
    remh = (remh << 32) | (reml >> 32);
 | 
			
		||||
    if (mh << 32 <= remh) {
 | 
			
		||||
        z |= 0xffffffff;
 | 
			
		||||
    } else {
 | 
			
		||||
        do_div(remh, mh);
 | 
			
		||||
        z |= remh;
 | 
			
		||||
    }
 | 
			
		||||
    return z;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Operations on unpacked elements
 | 
			
		||||
#define vfp_sign_negate(sign) (sign ^ 0x8000)
 | 
			
		||||
 | 
			
		||||
// Single-precision
 | 
			
		||||
struct vfp_single {
 | 
			
		||||
    s16 exponent;
 | 
			
		||||
    u16 sign;
 | 
			
		||||
    u32 significand;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// VFP_SINGLE_MANTISSA_BITS - number of bits in the mantissa
 | 
			
		||||
// VFP_SINGLE_EXPONENT_BITS - number of bits in the exponent
 | 
			
		||||
// VFP_SINGLE_LOW_BITS - number of low bits in the unpacked significand
 | 
			
		||||
// which are not propagated to the float upon packing.
 | 
			
		||||
#define VFP_SINGLE_MANTISSA_BITS (23)
 | 
			
		||||
#define VFP_SINGLE_EXPONENT_BITS (8)
 | 
			
		||||
#define VFP_SINGLE_LOW_BITS (32 - VFP_SINGLE_MANTISSA_BITS - 2)
 | 
			
		||||
#define VFP_SINGLE_LOW_BITS_MASK ((1 << VFP_SINGLE_LOW_BITS) - 1)
 | 
			
		||||
 | 
			
		||||
// The bit in an unpacked float which indicates that it is a quiet NaN
 | 
			
		||||
#define VFP_SINGLE_SIGNIFICAND_QNAN (1 << (VFP_SINGLE_MANTISSA_BITS - 1 + VFP_SINGLE_LOW_BITS))
 | 
			
		||||
 | 
			
		||||
// Operations on packed single-precision numbers
 | 
			
		||||
#define vfp_single_packed_sign(v) ((v)&0x80000000)
 | 
			
		||||
#define vfp_single_packed_negate(v) ((v) ^ 0x80000000)
 | 
			
		||||
#define vfp_single_packed_abs(v) ((v) & ~0x80000000)
 | 
			
		||||
#define vfp_single_packed_exponent(v)                                                              \
 | 
			
		||||
    (((v) >> VFP_SINGLE_MANTISSA_BITS) & ((1 << VFP_SINGLE_EXPONENT_BITS) - 1))
 | 
			
		||||
#define vfp_single_packed_mantissa(v) ((v) & ((1 << VFP_SINGLE_MANTISSA_BITS) - 1))
 | 
			
		||||
 | 
			
		||||
enum : u32 {
 | 
			
		||||
    VFP_NUMBER = (1 << 0),
 | 
			
		||||
    VFP_ZERO = (1 << 1),
 | 
			
		||||
    VFP_DENORMAL = (1 << 2),
 | 
			
		||||
    VFP_INFINITY = (1 << 3),
 | 
			
		||||
    VFP_NAN = (1 << 4),
 | 
			
		||||
    VFP_NAN_SIGNAL = (1 << 5),
 | 
			
		||||
 | 
			
		||||
    VFP_QNAN = (VFP_NAN),
 | 
			
		||||
    VFP_SNAN = (VFP_NAN | VFP_NAN_SIGNAL)
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
inline int vfp_single_type(const vfp_single* s) {
 | 
			
		||||
    int type = VFP_NUMBER;
 | 
			
		||||
    if (s->exponent == 255) {
 | 
			
		||||
        if (s->significand == 0)
 | 
			
		||||
            type = VFP_INFINITY;
 | 
			
		||||
        else if (s->significand & VFP_SINGLE_SIGNIFICAND_QNAN)
 | 
			
		||||
            type = VFP_QNAN;
 | 
			
		||||
        else
 | 
			
		||||
            type = VFP_SNAN;
 | 
			
		||||
    } else if (s->exponent == 0) {
 | 
			
		||||
        if (s->significand == 0)
 | 
			
		||||
            type |= VFP_ZERO;
 | 
			
		||||
        else
 | 
			
		||||
            type |= VFP_DENORMAL;
 | 
			
		||||
    }
 | 
			
		||||
    return type;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Unpack a single-precision float.  Note that this returns the magnitude
 | 
			
		||||
// of the single-precision float mantissa with the 1. if necessary,
 | 
			
		||||
// aligned to bit 30.
 | 
			
		||||
inline u32 vfp_single_unpack(vfp_single* s, s32 val, u32 fpscr) {
 | 
			
		||||
    u32 exceptions = 0;
 | 
			
		||||
    s->sign = vfp_single_packed_sign(val) >> 16, s->exponent = vfp_single_packed_exponent(val);
 | 
			
		||||
 | 
			
		||||
    u32 significand = ((u32)val << (32 - VFP_SINGLE_MANTISSA_BITS)) >> 2;
 | 
			
		||||
    if (s->exponent && s->exponent != 255)
 | 
			
		||||
        significand |= 0x40000000;
 | 
			
		||||
    s->significand = significand;
 | 
			
		||||
 | 
			
		||||
    // If flush-to-zero mode is enabled, turn the denormal into zero.
 | 
			
		||||
    // On a VFPv2 architecture, the sign of the zero is always positive.
 | 
			
		||||
    if ((fpscr & FPSCR_FLUSH_TO_ZERO) != 0 && (vfp_single_type(s) & VFP_DENORMAL) != 0) {
 | 
			
		||||
        s->sign = 0;
 | 
			
		||||
        s->exponent = 0;
 | 
			
		||||
        s->significand = 0;
 | 
			
		||||
        exceptions |= FPSCR_IDC;
 | 
			
		||||
    }
 | 
			
		||||
    return exceptions;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Re-pack a single-precision float. This assumes that the float is
 | 
			
		||||
// already normalised such that the MSB is bit 30, _not_ bit 31.
 | 
			
		||||
inline s32 vfp_single_pack(const vfp_single* s) {
 | 
			
		||||
    u32 val = (s->sign << 16) + (s->exponent << VFP_SINGLE_MANTISSA_BITS) +
 | 
			
		||||
              (s->significand >> VFP_SINGLE_LOW_BITS);
 | 
			
		||||
    return (s32)val;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
u32 vfp_single_normaliseround(ARMul_State* state, int sd, vfp_single* vs, u32 fpscr, u32 exceptions,
 | 
			
		||||
                              const char* func);
 | 
			
		||||
 | 
			
		||||
// Double-precision
 | 
			
		||||
struct vfp_double {
 | 
			
		||||
    s16 exponent;
 | 
			
		||||
    u16 sign;
 | 
			
		||||
    u64 significand;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// VFP_REG_ZERO is a special register number for vfp_get_double
 | 
			
		||||
// which returns (double)0.0.  This is useful for the compare with
 | 
			
		||||
// zero instructions.
 | 
			
		||||
#ifdef CONFIG_VFPv3
 | 
			
		||||
#define VFP_REG_ZERO 32
 | 
			
		||||
#else
 | 
			
		||||
#define VFP_REG_ZERO 16
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define VFP_DOUBLE_MANTISSA_BITS (52)
 | 
			
		||||
#define VFP_DOUBLE_EXPONENT_BITS (11)
 | 
			
		||||
#define VFP_DOUBLE_LOW_BITS (64 - VFP_DOUBLE_MANTISSA_BITS - 2)
 | 
			
		||||
#define VFP_DOUBLE_LOW_BITS_MASK ((1 << VFP_DOUBLE_LOW_BITS) - 1)
 | 
			
		||||
 | 
			
		||||
// The bit in an unpacked double which indicates that it is a quiet NaN
 | 
			
		||||
#define VFP_DOUBLE_SIGNIFICAND_QNAN (1ULL << (VFP_DOUBLE_MANTISSA_BITS - 1 + VFP_DOUBLE_LOW_BITS))
 | 
			
		||||
 | 
			
		||||
// Operations on packed single-precision numbers
 | 
			
		||||
#define vfp_double_packed_sign(v) ((v) & (1ULL << 63))
 | 
			
		||||
#define vfp_double_packed_negate(v) ((v) ^ (1ULL << 63))
 | 
			
		||||
#define vfp_double_packed_abs(v) ((v) & ~(1ULL << 63))
 | 
			
		||||
#define vfp_double_packed_exponent(v)                                                              \
 | 
			
		||||
    (((v) >> VFP_DOUBLE_MANTISSA_BITS) & ((1 << VFP_DOUBLE_EXPONENT_BITS) - 1))
 | 
			
		||||
#define vfp_double_packed_mantissa(v) ((v) & ((1ULL << VFP_DOUBLE_MANTISSA_BITS) - 1))
 | 
			
		||||
 | 
			
		||||
inline int vfp_double_type(const vfp_double* s) {
 | 
			
		||||
    int type = VFP_NUMBER;
 | 
			
		||||
    if (s->exponent == 2047) {
 | 
			
		||||
        if (s->significand == 0)
 | 
			
		||||
            type = VFP_INFINITY;
 | 
			
		||||
        else if (s->significand & VFP_DOUBLE_SIGNIFICAND_QNAN)
 | 
			
		||||
            type = VFP_QNAN;
 | 
			
		||||
        else
 | 
			
		||||
            type = VFP_SNAN;
 | 
			
		||||
    } else if (s->exponent == 0) {
 | 
			
		||||
        if (s->significand == 0)
 | 
			
		||||
            type |= VFP_ZERO;
 | 
			
		||||
        else
 | 
			
		||||
            type |= VFP_DENORMAL;
 | 
			
		||||
    }
 | 
			
		||||
    return type;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Unpack a double-precision float.  Note that this returns the magnitude
 | 
			
		||||
// of the double-precision float mantissa with the 1. if necessary,
 | 
			
		||||
// aligned to bit 62.
 | 
			
		||||
inline u32 vfp_double_unpack(vfp_double* s, s64 val, u32 fpscr) {
 | 
			
		||||
    u32 exceptions = 0;
 | 
			
		||||
    s->sign = vfp_double_packed_sign(val) >> 48;
 | 
			
		||||
    s->exponent = vfp_double_packed_exponent(val);
 | 
			
		||||
 | 
			
		||||
    u64 significand = ((u64)val << (64 - VFP_DOUBLE_MANTISSA_BITS)) >> 2;
 | 
			
		||||
    if (s->exponent && s->exponent != 2047)
 | 
			
		||||
        significand |= (1ULL << 62);
 | 
			
		||||
    s->significand = significand;
 | 
			
		||||
 | 
			
		||||
    // If flush-to-zero mode is enabled, turn the denormal into zero.
 | 
			
		||||
    // On a VFPv2 architecture, the sign of the zero is always positive.
 | 
			
		||||
    if ((fpscr & FPSCR_FLUSH_TO_ZERO) != 0 && (vfp_double_type(s) & VFP_DENORMAL) != 0) {
 | 
			
		||||
        s->sign = 0;
 | 
			
		||||
        s->exponent = 0;
 | 
			
		||||
        s->significand = 0;
 | 
			
		||||
        exceptions |= FPSCR_IDC;
 | 
			
		||||
    }
 | 
			
		||||
    return exceptions;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Re-pack a double-precision float. This assumes that the float is
 | 
			
		||||
// already normalised such that the MSB is bit 30, _not_ bit 31.
 | 
			
		||||
inline s64 vfp_double_pack(const vfp_double* s) {
 | 
			
		||||
    u64 val = ((u64)s->sign << 48) + ((u64)s->exponent << VFP_DOUBLE_MANTISSA_BITS) +
 | 
			
		||||
              (s->significand >> VFP_DOUBLE_LOW_BITS);
 | 
			
		||||
    return (s64)val;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
u32 vfp_estimate_sqrt_significand(u32 exponent, u32 significand);
 | 
			
		||||
 | 
			
		||||
// A special flag to tell the normalisation code not to normalise.
 | 
			
		||||
#define VFP_NAN_FLAG 0x100
 | 
			
		||||
 | 
			
		||||
// A bit pattern used to indicate the initial (unset) value of the
 | 
			
		||||
// exception mask, in case nothing handles an instruction.  This
 | 
			
		||||
// doesn't include the NAN flag, which get masked out before
 | 
			
		||||
// we check for an error.
 | 
			
		||||
#define VFP_EXCEPTION_ERROR ((u32)-1 & ~VFP_NAN_FLAG)
 | 
			
		||||
 | 
			
		||||
// A flag to tell vfp instruction type.
 | 
			
		||||
//  OP_SCALAR - This operation always operates in scalar mode
 | 
			
		||||
//  OP_SD     - The instruction exceptionally writes to a single precision result.
 | 
			
		||||
//  OP_DD     - The instruction exceptionally writes to a double precision result.
 | 
			
		||||
//  OP_SM     - The instruction exceptionally reads from a single precision operand.
 | 
			
		||||
enum : u32 { OP_SCALAR = (1 << 0), OP_SD = (1 << 1), OP_DD = (1 << 1), OP_SM = (1 << 2) };
 | 
			
		||||
 | 
			
		||||
struct op {
 | 
			
		||||
    u32 (*const fn)(ARMul_State* state, int dd, int dn, int dm, u32 fpscr);
 | 
			
		||||
    u32 flags;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
inline u32 fls(u32 x) {
 | 
			
		||||
    int r = 32;
 | 
			
		||||
 | 
			
		||||
    if (!x)
 | 
			
		||||
        return 0;
 | 
			
		||||
    if (!(x & 0xffff0000u)) {
 | 
			
		||||
        x <<= 16;
 | 
			
		||||
        r -= 16;
 | 
			
		||||
    }
 | 
			
		||||
    if (!(x & 0xff000000u)) {
 | 
			
		||||
        x <<= 8;
 | 
			
		||||
        r -= 8;
 | 
			
		||||
    }
 | 
			
		||||
    if (!(x & 0xf0000000u)) {
 | 
			
		||||
        x <<= 4;
 | 
			
		||||
        r -= 4;
 | 
			
		||||
    }
 | 
			
		||||
    if (!(x & 0xc0000000u)) {
 | 
			
		||||
        x <<= 2;
 | 
			
		||||
        r -= 2;
 | 
			
		||||
    }
 | 
			
		||||
    if (!(x & 0x80000000u)) {
 | 
			
		||||
        x <<= 1;
 | 
			
		||||
        r -= 1;
 | 
			
		||||
    }
 | 
			
		||||
    return r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
u32 vfp_double_multiply(vfp_double* vdd, vfp_double* vdn, vfp_double* vdm, u32 fpscr);
 | 
			
		||||
u32 vfp_double_add(vfp_double* vdd, vfp_double* vdn, vfp_double* vdm, u32 fpscr);
 | 
			
		||||
u32 vfp_double_normaliseround(ARMul_State* state, int dd, vfp_double* vd, u32 fpscr, u32 exceptions,
 | 
			
		||||
                              const char* func);
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@ -8,7 +8,6 @@
 | 
			
		||||
#include "common/logging/log.h"
 | 
			
		||||
#include "core/arm/arm_interface.h"
 | 
			
		||||
#include "core/arm/dynarmic/arm_dynarmic.h"
 | 
			
		||||
#include "core/arm/dyncom/arm_dyncom.h"
 | 
			
		||||
#include "core/arm/unicorn/arm_unicorn.h"
 | 
			
		||||
#include "core/core.h"
 | 
			
		||||
#include "core/core_timing.h"
 | 
			
		||||
@ -142,9 +141,9 @@ System::ResultStatus System::Init(EmuWindow* emu_window, u32 system_mode) {
 | 
			
		||||
    LOG_DEBUG(HW_Memory, "initialized OK");
 | 
			
		||||
 | 
			
		||||
    if (Settings::values.use_cpu_jit) {
 | 
			
		||||
        cpu_core = std::make_unique<ARM_Dynarmic>(USER32MODE);
 | 
			
		||||
        cpu_core = std::make_unique<ARM_Dynarmic>();
 | 
			
		||||
    } else {
 | 
			
		||||
        cpu_core = std::make_unique<ARM_DynCom>(USER32MODE);
 | 
			
		||||
        cpu_core = std::make_unique<ARM_Unicorn>();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    telemetry_session = std::make_unique<Core::TelemetrySession>();
 | 
			
		||||
 | 
			
		||||
@ -547,8 +547,7 @@ static void ReadRegister() {
 | 
			
		||||
                               id - CPSR_REGISTER -
 | 
			
		||||
                               1)); // VFP registers should start at 26, so one after CSPR_REGISTER
 | 
			
		||||
    } else if (id == FPSCR_REGISTER) {
 | 
			
		||||
        IntToGdbHex(reply, Core::CPU().GetVFPSystemReg(VFP_FPSCR)); // Get FPSCR
 | 
			
		||||
        IntToGdbHex(reply + 8, 0);
 | 
			
		||||
        UNIMPLEMENTED();
 | 
			
		||||
    } else {
 | 
			
		||||
        return SendReply("E01");
 | 
			
		||||
    }
 | 
			
		||||
@ -579,8 +578,6 @@ static void ReadRegisters() {
 | 
			
		||||
 | 
			
		||||
    bufptr += (32 * CHAR_BIT);
 | 
			
		||||
 | 
			
		||||
    IntToGdbHex(bufptr, Core::CPU().GetVFPSystemReg(VFP_FPSCR));
 | 
			
		||||
 | 
			
		||||
    SendReply(reinterpret_cast<char*>(buffer));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -602,7 +599,7 @@ static void WriteRegister() {
 | 
			
		||||
    } else if (id > CPSR_REGISTER && id < FPSCR_REGISTER) {
 | 
			
		||||
        Core::CPU().SetVFPReg(id - CPSR_REGISTER - 1, GdbHexToInt(buffer_ptr));
 | 
			
		||||
    } else if (id == FPSCR_REGISTER) {
 | 
			
		||||
        Core::CPU().SetVFPSystemReg(VFP_FPSCR, GdbHexToInt(buffer_ptr));
 | 
			
		||||
        UNIMPLEMENTED();
 | 
			
		||||
    } else {
 | 
			
		||||
        return SendReply("E01");
 | 
			
		||||
    }
 | 
			
		||||
@ -631,7 +628,7 @@ static void WriteRegisters() {
 | 
			
		||||
            Core::CPU().SetVFPReg(reg - CPSR_REGISTER - 1, GdbHexToInt(buffer_ptr + i * CHAR_BIT));
 | 
			
		||||
            i++; // Skip padding
 | 
			
		||||
        } else if (reg == FPSCR_REGISTER) {
 | 
			
		||||
            Core::CPU().SetVFPSystemReg(VFP_FPSCR, GdbHexToInt(buffer_ptr + i * CHAR_BIT));
 | 
			
		||||
            UNIMPLEMENTED();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -26,8 +26,8 @@ namespace Kernel {
 | 
			
		||||
static ResultCode SetHeapSize(VAddr* heap_addr, u64 heap_size) {
 | 
			
		||||
    LOG_TRACE(Kernel_SVC, "called, heap_size=0x%llx", heap_size);
 | 
			
		||||
    auto& process = *g_current_process;
 | 
			
		||||
    CASCADE_RESULT(*heap_addr, process.HeapAllocate(Memory::HEAP_VADDR, heap_size,
 | 
			
		||||
                                                    VMAPermission::ReadWrite));
 | 
			
		||||
    CASCADE_RESULT(*heap_addr,
 | 
			
		||||
                   process.HeapAllocate(Memory::HEAP_VADDR, heap_size, VMAPermission::ReadWrite));
 | 
			
		||||
    return RESULT_SUCCESS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -95,8 +95,7 @@ static ResultCode SendSyncRequest(Handle handle) {
 | 
			
		||||
static ResultCode GetThreadId(u32* thread_id, Handle thread_handle) {
 | 
			
		||||
    LOG_TRACE(Kernel_SVC, "called thread=0x%08X", thread_handle);
 | 
			
		||||
 | 
			
		||||
    const SharedPtr<Thread> thread =
 | 
			
		||||
        g_handle_table.Get<Thread>(thread_handle);
 | 
			
		||||
    const SharedPtr<Thread> thread = g_handle_table.Get<Thread>(thread_handle);
 | 
			
		||||
    if (!thread) {
 | 
			
		||||
        return ERR_INVALID_HANDLE;
 | 
			
		||||
    }
 | 
			
		||||
@ -109,8 +108,7 @@ static ResultCode GetThreadId(u32* thread_id, Handle thread_handle) {
 | 
			
		||||
static ResultCode GetProcessId(u32* process_id, Handle process_handle) {
 | 
			
		||||
    LOG_TRACE(Kernel_SVC, "called process=0x%08X", process_handle);
 | 
			
		||||
 | 
			
		||||
    const SharedPtr<Process> process =
 | 
			
		||||
        g_handle_table.Get<Process>(process_handle);
 | 
			
		||||
    const SharedPtr<Process> process = g_handle_table.Get<Process>(process_handle);
 | 
			
		||||
    if (!process) {
 | 
			
		||||
        return ERR_INVALID_HANDLE;
 | 
			
		||||
    }
 | 
			
		||||
@ -135,10 +133,8 @@ static ResultCode LockMutex(Handle holding_thread_handle, VAddr mutex_addr,
 | 
			
		||||
              "requesting_current_thread_handle=0x%08X",
 | 
			
		||||
              holding_thread_handle, mutex_addr, requesting_thread_handle);
 | 
			
		||||
 | 
			
		||||
    SharedPtr<Thread> holding_thread =
 | 
			
		||||
        g_handle_table.Get<Thread>(holding_thread_handle);
 | 
			
		||||
    SharedPtr<Thread> requesting_thread =
 | 
			
		||||
        g_handle_table.Get<Thread>(requesting_thread_handle);
 | 
			
		||||
    SharedPtr<Thread> holding_thread = g_handle_table.Get<Thread>(holding_thread_handle);
 | 
			
		||||
    SharedPtr<Thread> requesting_thread = g_handle_table.Get<Thread>(requesting_thread_handle);
 | 
			
		||||
 | 
			
		||||
    ASSERT(holding_thread);
 | 
			
		||||
    ASSERT(requesting_thread);
 | 
			
		||||
@ -302,8 +298,7 @@ static ResultCode QueryMemory(MemoryInfo* memory_info, PageInfo* page_info, VAdd
 | 
			
		||||
static void ExitProcess() {
 | 
			
		||||
    LOG_INFO(Kernel_SVC, "Process %u exiting", g_current_process->process_id);
 | 
			
		||||
 | 
			
		||||
    ASSERT_MSG(g_current_process->status == ProcessStatus::Running,
 | 
			
		||||
               "Process has already exited");
 | 
			
		||||
    ASSERT_MSG(g_current_process->status == ProcessStatus::Running, "Process has already exited");
 | 
			
		||||
 | 
			
		||||
    g_current_process->status = ProcessStatus::Exited;
 | 
			
		||||
 | 
			
		||||
@ -369,11 +364,7 @@ static ResultCode CreateThread(Handle* out_handle, VAddr entry_point, u64 arg, V
 | 
			
		||||
 | 
			
		||||
    CASCADE_RESULT(SharedPtr<Thread> thread,
 | 
			
		||||
                   Thread::Create(name, entry_point, priority, arg, processor_id, stack_top,
 | 
			
		||||
                                          g_current_process));
 | 
			
		||||
 | 
			
		||||
    thread->context.fpscr =
 | 
			
		||||
        FPSCR_DEFAULT_NAN | FPSCR_FLUSH_TO_ZERO | FPSCR_ROUND_TOZERO; // 0x03C00000
 | 
			
		||||
 | 
			
		||||
                                  g_current_process));
 | 
			
		||||
    CASCADE_RESULT(thread->guest_handle, g_handle_table.Create(thread));
 | 
			
		||||
    *out_handle = thread->guest_handle;
 | 
			
		||||
 | 
			
		||||
@ -391,8 +382,7 @@ static ResultCode CreateThread(Handle* out_handle, VAddr entry_point, u64 arg, V
 | 
			
		||||
static ResultCode StartThread(Handle thread_handle) {
 | 
			
		||||
    LOG_TRACE(Kernel_SVC, "called thread=0x%08X", thread_handle);
 | 
			
		||||
 | 
			
		||||
    const SharedPtr<Thread> thread =
 | 
			
		||||
        g_handle_table.Get<Thread>(thread_handle);
 | 
			
		||||
    const SharedPtr<Thread> thread = g_handle_table.Get<Thread>(thread_handle);
 | 
			
		||||
    if (!thread) {
 | 
			
		||||
        return ERR_INVALID_HANDLE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -11,7 +11,6 @@
 | 
			
		||||
#include "common/math_util.h"
 | 
			
		||||
#include "common/thread_queue_list.h"
 | 
			
		||||
#include "core/arm/arm_interface.h"
 | 
			
		||||
#include "core/arm/skyeye_common/armstate.h"
 | 
			
		||||
#include "core/core.h"
 | 
			
		||||
#include "core/core_timing.h"
 | 
			
		||||
#include "core/hle/kernel/errors.h"
 | 
			
		||||
@ -365,7 +364,8 @@ static void ResetThreadContext(ARM_Interface::ThreadContext& context, VAddr stac
 | 
			
		||||
    context.cpu_registers[0] = arg;
 | 
			
		||||
    context.pc = entry_point;
 | 
			
		||||
    context.sp = stack_top;
 | 
			
		||||
    context.cpsr = USER32MODE;
 | 
			
		||||
    context.cpsr = 0;
 | 
			
		||||
    context.fpscr = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point, u32 priority,
 | 
			
		||||
@ -504,8 +504,6 @@ SharedPtr<Thread> SetupMainThread(VAddr entry_point, u32 priority,
 | 
			
		||||
    // Register 1 must be a handle to the main thread
 | 
			
		||||
    thread->guest_handle = Kernel::g_handle_table.Create(thread).Unwrap();;
 | 
			
		||||
    thread->context.cpu_registers[1] = thread->guest_handle;
 | 
			
		||||
    thread->context.fpscr =
 | 
			
		||||
        FPSCR_DEFAULT_NAN | FPSCR_FLUSH_TO_ZERO | FPSCR_ROUND_TOZERO | FPSCR_IXC; // 0x03C00010
 | 
			
		||||
 | 
			
		||||
    // Threads by default are dormant, wake up the main thread so it runs when the scheduler fires
 | 
			
		||||
    thread->ResumeFromWait();
 | 
			
		||||
 | 
			
		||||
@ -1,7 +1,6 @@
 | 
			
		||||
set(SRCS
 | 
			
		||||
            common/param_package.cpp
 | 
			
		||||
            core/arm/arm_test_common.cpp
 | 
			
		||||
            core/arm/dyncom/arm_dyncom_vfp_tests.cpp
 | 
			
		||||
            core/file_sys/path_parser.cpp
 | 
			
		||||
            core/memory/memory.cpp
 | 
			
		||||
            glad.cpp
 | 
			
		||||
 | 
			
		||||
@ -1,50 +0,0 @@
 | 
			
		||||
// Copyright 2016 Citra Emulator Project
 | 
			
		||||
// Licensed under GPLv2 or any later version
 | 
			
		||||
// Refer to the license.txt file included.
 | 
			
		||||
 | 
			
		||||
#include <catch.hpp>
 | 
			
		||||
 | 
			
		||||
#include "core/arm/dyncom/arm_dyncom.h"
 | 
			
		||||
#include "core/core_timing.h"
 | 
			
		||||
#include "tests/core/arm/arm_test_common.h"
 | 
			
		||||
 | 
			
		||||
namespace ArmTests {
 | 
			
		||||
 | 
			
		||||
struct VfpTestCase {
 | 
			
		||||
    u32 initial_fpscr;
 | 
			
		||||
    u32 a;
 | 
			
		||||
    u32 b;
 | 
			
		||||
    u32 result;
 | 
			
		||||
    u32 final_fpscr;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
TEST_CASE("ARM_DynCom (vfp): vadd", "[arm_dyncom]") {
 | 
			
		||||
    TestEnvironment test_env(false);
 | 
			
		||||
    test_env.SetMemory32(0, 0xEE321A03); // vadd.f32 s2, s4, s6
 | 
			
		||||
    test_env.SetMemory32(4, 0xEAFFFFFE); // b +#0
 | 
			
		||||
 | 
			
		||||
    ARM_DynCom dyncom(USER32MODE);
 | 
			
		||||
 | 
			
		||||
    std::vector<VfpTestCase> test_cases{{
 | 
			
		||||
#include "vfp_vadd_f32.inc"
 | 
			
		||||
    }};
 | 
			
		||||
 | 
			
		||||
    for (const auto& test_case : test_cases) {
 | 
			
		||||
        dyncom.SetPC(0);
 | 
			
		||||
        dyncom.SetVFPSystemReg(VFP_FPSCR, test_case.initial_fpscr);
 | 
			
		||||
        dyncom.SetVFPReg(4, test_case.a);
 | 
			
		||||
        dyncom.SetVFPReg(6, test_case.b);
 | 
			
		||||
        dyncom.ExecuteInstructions(1);
 | 
			
		||||
        if (dyncom.GetVFPReg(2) != test_case.result ||
 | 
			
		||||
            dyncom.GetVFPSystemReg(VFP_FPSCR) != test_case.final_fpscr) {
 | 
			
		||||
            printf("f: %x\n", test_case.initial_fpscr);
 | 
			
		||||
            printf("a: %x\n", test_case.a);
 | 
			
		||||
            printf("b: %x\n", test_case.b);
 | 
			
		||||
            printf("c: %x (%x)\n", dyncom.GetVFPReg(2), test_case.result);
 | 
			
		||||
            printf("f: %x (%x)\n", dyncom.GetVFPSystemReg(VFP_FPSCR), test_case.final_fpscr);
 | 
			
		||||
            FAIL();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // namespace ArmTests
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
		Loading…
	
		Reference in New Issue
	
	Block a user