dynarmic/README.md

161 lines
3.6 KiB
Markdown
Raw Normal View History

2016-07-01 15:01:06 +02:00
Dynarmic
========
2018-01-12 21:05:17 +01:00
2016-12-19 00:32:08 +01:00
[![Travis CI Build Status](https://api.travis-ci.org/MerryMage/dynarmic.svg?branch=master)](https://travis-ci.org/MerryMage/dynarmic/branches) [![Appveyor CI Build status](https://ci.appveyor.com/api/projects/status/maeiqr41rgm1innm/branch/master?svg=true)](https://ci.appveyor.com/project/MerryMage/dynarmic/branch/master)
2018-01-12 21:05:17 +01:00
A dynamic recompiler for ARM.
### Supported guest architectures
* ARMv6K
* 64-bit ARMv8
2016-12-19 00:32:08 +01:00
2018-01-12 21:05:17 +01:00
### Supported host architectures
2016-07-01 15:01:06 +02:00
2018-01-12 21:05:17 +01:00
* x86-64
There are no plans to support x86-32.
2016-07-01 15:01:06 +02:00
2016-08-12 19:17:31 +02:00
Documentation
-------------
Design documentation can be found at [docs/Design.md](docs/Design.md).
2016-07-01 15:01:06 +02:00
Plans
-----
2018-01-12 21:05:17 +01:00
### Near-term
* Complete ARMv8 support
2016-07-01 15:01:06 +02:00
### Medium-term
2018-01-12 21:05:17 +01:00
* Optimizations
2016-07-01 15:01:06 +02:00
### Long-term
2018-01-12 21:05:17 +01:00
* ARMv7A guest support
* ARMv5 guest support
* ARMv8 host support
2018-04-25 23:25:39 +02:00
Usage Example
-------------
The below is a minimal example. Bring-your-own memory system.
```cpp
#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();
2019-01-31 18:53:00 +01:00
// Here we would expect cpu.Regs()[0] == 8
printf("R0: %u\n", cpu.Regs()[0]);
2018-04-25 23:25:39 +02:00
return 0;
}
```