native-v86-core 0.1.6

Native Rust x86 CPU interpreter core ported from v86
Documentation
use crate::cpu::cpu::*;
use crate::paging::OrPageFault;

pub unsafe fn resolve_modrm16(modrm_byte: i32) -> OrPageFault<i32> {
    match modrm_byte & !0o070 {
        0o000 => get_seg_prefix_ds(read_reg16(BX) + read_reg16(SI) & 0xFFFF),
        0o100 => get_seg_prefix_ds(read_reg16(BX) + read_reg16(SI) + read_imm8s()? & 0xFFFF),
        0o200 => get_seg_prefix_ds(read_reg16(BX) + read_reg16(SI) + read_imm16()? & 0xFFFF),
        0o001 => get_seg_prefix_ds(read_reg16(BX) + read_reg16(DI) & 0xFFFF),
        0o101 => get_seg_prefix_ds(read_reg16(BX) + read_reg16(DI) + read_imm8s()? & 0xFFFF),
        0o201 => get_seg_prefix_ds(read_reg16(BX) + read_reg16(DI) + read_imm16()? & 0xFFFF),
        0o002 => get_seg_prefix_ss(read_reg16(BP) + read_reg16(SI) & 0xFFFF),
        0o102 => get_seg_prefix_ss(read_reg16(BP) + read_reg16(SI) + read_imm8s()? & 0xFFFF),
        0o202 => get_seg_prefix_ss(read_reg16(BP) + read_reg16(SI) + read_imm16()? & 0xFFFF),
        0o003 => get_seg_prefix_ss(read_reg16(BP) + read_reg16(DI) & 0xFFFF),
        0o103 => get_seg_prefix_ss(read_reg16(BP) + read_reg16(DI) + read_imm8s()? & 0xFFFF),
        0o203 => get_seg_prefix_ss(read_reg16(BP) + read_reg16(DI) + read_imm16()? & 0xFFFF),
        0o004 => get_seg_prefix_ds(read_reg16(SI) & 0xFFFF),
        0o104 => get_seg_prefix_ds(read_reg16(SI) + read_imm8s()? & 0xFFFF),
        0o204 => get_seg_prefix_ds(read_reg16(SI) + read_imm16()? & 0xFFFF),
        0o005 => get_seg_prefix_ds(read_reg16(DI) & 0xFFFF),
        0o105 => get_seg_prefix_ds(read_reg16(DI) + read_imm8s()? & 0xFFFF),
        0o205 => get_seg_prefix_ds(read_reg16(DI) + read_imm16()? & 0xFFFF),
        0o006 => get_seg_prefix_ds(read_imm16()?),
        0o106 => get_seg_prefix_ss(read_reg16(BP) + read_imm8s()? & 0xFFFF),
        0o206 => get_seg_prefix_ss(read_reg16(BP) + read_imm16()? & 0xFFFF),
        0o007 => get_seg_prefix_ds(read_reg16(BX) & 0xFFFF),
        0o107 => get_seg_prefix_ds(read_reg16(BX) + read_imm8s()? & 0xFFFF),
        0o207 => get_seg_prefix_ds(read_reg16(BX) + read_imm16()? & 0xFFFF),
        _ => {
            dbg_assert!(false);
            std::hint::unreachable_unchecked()
        }
    }
}

pub unsafe fn resolve_modrm32_(modrm_byte: i32) -> OrPageFault<i32> {
    let r = (modrm_byte & 7) as u8;
    dbg_assert!(modrm_byte < 192);
    Ok(if r as i32 == 4 {
        if modrm_byte < 64 {
            resolve_sib(false)?
        } else {
            resolve_sib(true)?.wrapping_add(if modrm_byte < 128 {
                read_imm8s()?
            } else {
                read_imm32s()?
            })
        }
    } else if r as i32 == 5 {
        if modrm_byte < 64 {
            get_seg_prefix_ds(read_imm32s()?)?
        } else {
            get_seg_prefix_ss(read_reg32(EBP).wrapping_add(if modrm_byte < 128 {
                read_imm8s()?
            } else {
                read_imm32s()?
            }))?
        }
    } else if modrm_byte < 64 {
        get_seg_prefix_ds(read_reg32(r as i32))?
    } else {
        get_seg_prefix_ds(read_reg32(r as i32).wrapping_add(if modrm_byte < 128 {
            read_imm8s()?
        } else {
            read_imm32s()?
        }))?
    })
}
unsafe fn resolve_sib(with_imm: bool) -> OrPageFault<i32> {
    let sib_byte = read_imm8()?;
    let r = sib_byte & 7;
    let m = sib_byte >> 3 & 7;
    let base;
    let seg;
    if r == 4 {
        base = read_reg32(ESP);
        seg = SS
    } else if r == 5 {
        if with_imm {
            base = read_reg32(EBP);
            seg = SS
        } else {
            base = read_imm32s()?;
            seg = DS
        }
    } else {
        base = read_reg32(r);
        seg = DS
    }
    let offset;
    if m == 4 {
        offset = 0
    } else {
        let s = sib_byte >> 6 & 3;
        offset = read_reg32(m) << s
    }
    Ok(get_seg_prefix(seg)?.wrapping_add(base).wrapping_add(offset))
}

pub unsafe fn resolve_modrm32(modrm_byte: i32) -> OrPageFault<i32> {
    match modrm_byte & !0o070 {
        0o000 => get_seg_prefix_ds(read_reg32(EAX)),
        0o100 => get_seg_prefix_ds(read_reg32(EAX).wrapping_add(read_imm8s()?)),
        0o200 => get_seg_prefix_ds(read_reg32(EAX).wrapping_add(read_imm32s()?)),
        0o001 => get_seg_prefix_ds(read_reg32(ECX)),
        0o101 => get_seg_prefix_ds(read_reg32(ECX).wrapping_add(read_imm8s()?)),
        0o201 => get_seg_prefix_ds(read_reg32(ECX).wrapping_add(read_imm32s()?)),
        0o002 => get_seg_prefix_ds(read_reg32(EDX)),
        0o102 => get_seg_prefix_ds(read_reg32(EDX).wrapping_add(read_imm8s()?)),
        0o202 => get_seg_prefix_ds(read_reg32(EDX).wrapping_add(read_imm32s()?)),
        0o003 => get_seg_prefix_ds(read_reg32(EBX)),
        0o103 => get_seg_prefix_ds(read_reg32(EBX).wrapping_add(read_imm8s()?)),
        0o203 => get_seg_prefix_ds(read_reg32(EBX).wrapping_add(read_imm32s()?)),
        0o004 => resolve_sib(false),
        0o104 => Ok(resolve_sib(true)?.wrapping_add(read_imm8s()?)),
        0o204 => Ok(resolve_sib(true)?.wrapping_add(read_imm32s()?)),
        0o005 => get_seg_prefix_ds(read_imm32s()?),
        0o105 => get_seg_prefix_ss(read_reg32(EBP).wrapping_add(read_imm8s()?)),
        0o205 => get_seg_prefix_ss(read_reg32(EBP).wrapping_add(read_imm32s()?)),
        0o006 => get_seg_prefix_ds(read_reg32(ESI)),
        0o106 => get_seg_prefix_ds(read_reg32(ESI).wrapping_add(read_imm8s()?)),
        0o206 => get_seg_prefix_ds(read_reg32(ESI).wrapping_add(read_imm32s()?)),
        0o007 => get_seg_prefix_ds(read_reg32(EDI)),
        0o107 => get_seg_prefix_ds(read_reg32(EDI).wrapping_add(read_imm8s()?)),
        0o207 => get_seg_prefix_ds(read_reg32(EDI).wrapping_add(read_imm32s()?)),
        _ => {
            dbg_assert!(false);
            std::hint::unreachable_unchecked()
        }
    }
}