#emulator #arm #table

armv6k

ARMv6K emulator

1 stable release

1.0.0 Feb 17, 2019

#234 in #emulator

Unlicense

5MB
101K SLoC

C++ 68K SLoC // 0.1% comments Bitbake 29K SLoC Visual Studio Project 3K SLoC Python 1K SLoC // 0.3% comments Batch 237 SLoC Shell 212 SLoC // 0.1% comments Visual Studio Solution 106 SLoC Rust 30 SLoC Perl 21 SLoC // 0.4% comments Prolog 21 SLoC JavaScript 2 SLoC // 0.7% comments

rust-armv6k

ARMv6K emulator for Rust. Uses Dynarmic.

Coprocessors or page tables aren't supported.

Usage Example

use armv6k;

static mut MEMORY: [u8; 2048] = [0; 2048];
static mut TICKS_LEFT: u64 = 0;

unsafe extern fn read_8(vaddr: usize) -> u8 {
    if vaddr >= MEMORY.len() {
        panic!("Invalid address: {:08X}", vaddr);
    }
    MEMORY[vaddr]
}

unsafe extern fn read_16(vaddr: usize) -> u16 {
    (read_8(vaddr) as u16) | (read_8(vaddr + 1) as u16) << 8
}

unsafe extern fn read_32(vaddr: usize) -> u32 {
    (read_16(vaddr) as u32) | (read_16(vaddr + 2) as u32) << 16
}

unsafe extern fn read_64(vaddr: usize) -> u64 {
    (read_32(vaddr) as u64) | (read_16(vaddr + 4) as u64) << 32
}

unsafe extern fn write_8(vaddr: usize, value: u8) {
    if vaddr >= MEMORY.len() {
        panic!("Invalid address: {:08X}", vaddr);
    }
    MEMORY[vaddr] = value;
}

unsafe extern fn write_16(vaddr: usize, value: u16) {
    write_8(vaddr, value as u8);
    write_8(vaddr + 1, (value >> 8) as u8);
}

unsafe extern fn write_32(vaddr: usize, value: u32) {
    write_16(vaddr, value as u16);
    write_16(vaddr + 2, (value >> 16) as u16);
}

unsafe extern fn write_64(vaddr: usize, value: u64) {
    write_32(vaddr, value as u32);
    write_32(vaddr + 4, (value >> 32) as u32);
}

unsafe extern fn add_ticks(ticks: u64) {
    if ticks > TICKS_LEFT {
        TICKS_LEFT = 0;
        return;
    }
    TICKS_LEFT -= ticks;
}

unsafe extern fn call_svc(_swi: u32) {}

unsafe extern fn exception_raised(_pc: u32, _exception: i32) {}

unsafe extern fn get_ticks_remaining() -> u64 {
    return TICKS_LEFT
}

unsafe extern fn interpreter_fallback(_pc: u32, _num_instructions: usize) {}

fn main() {
    unsafe {
        armv6k::Initialize(true, true);
        write_16(0, 0x0088);
        write_16(2, 0xE7FE);
        armv6k::SetRegister(0, 1);
        armv6k::SetRegister(1, 2);
        armv6k::SetRegister(15, 0);
        armv6k::SetCpsr(0x00000030);
        armv6k::SetAddTicks(add_ticks);
        armv6k::SetCallSVC(call_svc);
        armv6k::SetExceptionRaised(exception_raised);
        armv6k::SetMemoryRead8(read_8);
        armv6k::SetMemoryRead16(read_16);
        armv6k::SetMemoryRead32(read_32);
        armv6k::SetMemoryRead64(read_64);
        armv6k::SetMemoryWrite8(write_8);
        armv6k::SetMemoryWrite16(write_16);
        armv6k::SetMemoryWrite32(write_32);
        armv6k::SetMemoryWrite64(write_64);
        armv6k::SetGetTicksRemaining(get_ticks_remaining);
        armv6k::SetInterpreterFallback(interpreter_fallback);
        armv6k::Run();
        println!("R0: {}", armv6k::GetRegister(0));
    }
}

No runtime deps