No description
Find a file
Lioncash b915364c16 A64/imm: Add full range of comparison operators to Imm template
Makes the comparison interface consistent by providing all of the
relevant members. This also modifies the comparison operators to take
the Imm instance by value, as it's really only a u32 under the covers,
and it's cheaper to shuffle around a u32 than a 64-bit pointer address.
2020-04-22 20:55:06 +01:00
.travis travis: Enable DYNARMIC_USE_LLVM 2020-04-22 20:46:15 +01:00
CMakeModules CMake: Make FindUnicorn introduce a unicorn target 2020-04-22 20:46:16 +01:00
docs docs: Update documentation (2018-02-05) 2020-04-22 20:46:13 +01:00
externals externals: Update catch to 2.4.0 2020-04-22 20:53:46 +01:00
include/dynarmic A64: Implement FastDispatchHint 2020-04-22 20:53:46 +01:00
src A64/imm: Add full range of comparison operators to Imm template 2020-04-22 20:55:06 +01:00
tests emit_x64_vector: Changes to VectorSignedSaturatedDoublingMultiply 2020-04-22 20:55:06 +01:00
.appveyor.yml appveyor: Use a more recent version of boost 2020-04-22 20:39:27 +01:00
.gitmodules externals: Add fmt as a submodule 2016-08-26 13:13:19 +01:00
.travis.yml travis: Make macOS build with Xcode 9.4.1 2020-04-22 20:53:46 +01:00
CMakeLists.txt block_of_code: Hide NX support behind compiler flag 2020-04-22 20:53:46 +01:00
LICENSE.txt Add LICENSE.txt 2016-08-31 21:50:05 +01:00
README.md README: Add usage example 2020-04-22 20:46:17 +01:00

Dynarmic

Travis CI Build Status Appveyor CI Build status

A dynamic recompiler for ARM.

Supported guest architectures

  • ARMv6K
  • 64-bit ARMv8

Supported host architectures

  • x86-64

There are no plans to support x86-32.

Documentation

Design documentation can be found at docs/Design.md.

Plans

Near-term

  • Complete ARMv8 support

Medium-term

  • Optimizations

Long-term

  • ARMv7A guest support
  • ARMv5 guest support
  • ARMv8 host support

Usage Example

The below is a minimal example. Bring-your-own memory system.

#include <array>
#include <cstdint>
#include <cstdio>
#include <exception>

#include <dynarmic/A32/a32.h>
#include <dynarmic/A32/config.h>

using u8 = std::uint8_t;
using u16 = std::uint16_t;
using u32 = std::uint32_t;
using u64 = std::uint64_t;

class MyEnvironment final : public Dynarmic::A32::UserCallbacks {
public:
    u64 ticks_left = 0;
    std::array<u8, 2048> memory{};

    u8 MemoryRead8(u32 vaddr) override {
        if (vaddr >= memory.size()) {
            return 0;
        }
        return memory[vaddr];
    }

    u16 MemoryRead16(u32 vaddr) override {
        return u16(MemoryRead8(vaddr)) | u16(MemoryRead8(vaddr + 1)) << 8;
    }

    u32 MemoryRead32(u32 vaddr) override {
        return u32(MemoryRead16(vaddr)) | u32(MemoryRead16(vaddr + 2)) << 16;
    }

    u64 MemoryRead64(u32 vaddr) override {
        return u64(MemoryRead32(vaddr)) | u64(MemoryRead32(vaddr + 4)) << 32;
    }

    void MemoryWrite8(u32 vaddr, u8 value) override {
        if (vaddr >= memory.size()) {
            return;
        }
        memory[vaddr] = value;
    }

    void MemoryWrite16(u32 vaddr, u16 value) override {
        MemoryWrite8(vaddr, u8(value));
        MemoryWrite8(vaddr + 1, u8(value >> 8));
    }

    void MemoryWrite32(u32 vaddr, u32 value) override {
        MemoryWrite16(vaddr, u16(value));
        MemoryWrite16(vaddr + 2, u16(value >> 16));
    }

    void MemoryWrite64(u32 vaddr, u64 value) override {
        MemoryWrite32(vaddr, u32(value));
        MemoryWrite32(vaddr + 4, u32(value >> 32));
    }

    void InterpreterFallback(u32 pc, size_t num_instructions) override {
        // This is never called in practice.
        std::terminate();
    }

    void CallSVC(u32 swi) override {
        // Do something.
    }

    void ExceptionRaised(u32 pc, Dynarmic::A32::Exception exception) override {
        // Do something.
    }

    void AddTicks(u64 ticks) override {
        if (ticks > ticks_left) {
            ticks_left = 0;
            return;
        }
        ticks_left -= ticks;
    }

    u64 GetTicksRemaining() override {
        return ticks_left;
    }
};

int main(int argc, char** argv) {
    MyEnvironment env;
    Dynarmic::A32::UserConfig user_config;
    user_config.callbacks = &env;
    Dynarmic::A32::Jit cpu{user_config};

    // Execute at least 1 instruction.
    // (Note: More than one instruction may be executed.)
    env.ticks_left = 1;

    // Write some code to memory.
    env.MemoryWrite16(0, 0x0088); // lsls r0, r1, #2
    env.MemoryWrite16(2, 0xE7FE); // b +#0 (infinite loop)

    // Setup registers.
    cpu.Regs()[0] = 1;
    cpu.Regs()[1] = 2;
    cpu.Regs()[15] = 0; // PC = 0
    cpu.SetCpsr(0x00000030); // Thumb mode

    // Execute!
    cpu.Run();

    // Here we would expect jit.Regs()[0] == 8
    printf("R0: %u\n", jit.Regs()[0]);

    return 0;
}