v86 / src /rust /cpu /modrm.rs
peterpeter8585's picture
Upload 553 files
8df6da4 verified
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)? + 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) + 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) + 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)? + base + 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) + read_imm8s()?),
0o200 => get_seg_prefix_ds(read_reg32(EAX) + read_imm32s()?),
0o001 => get_seg_prefix_ds(read_reg32(ECX)),
0o101 => get_seg_prefix_ds(read_reg32(ECX) + read_imm8s()?),
0o201 => get_seg_prefix_ds(read_reg32(ECX) + read_imm32s()?),
0o002 => get_seg_prefix_ds(read_reg32(EDX)),
0o102 => get_seg_prefix_ds(read_reg32(EDX) + read_imm8s()?),
0o202 => get_seg_prefix_ds(read_reg32(EDX) + read_imm32s()?),
0o003 => get_seg_prefix_ds(read_reg32(EBX)),
0o103 => get_seg_prefix_ds(read_reg32(EBX) + read_imm8s()?),
0o203 => get_seg_prefix_ds(read_reg32(EBX) + read_imm32s()?),
0o004 => resolve_sib(false),
0o104 => Ok(resolve_sib(true)? + read_imm8s()?),
0o204 => Ok(resolve_sib(true)? + read_imm32s()?),
0o005 => get_seg_prefix_ds(read_imm32s()?),
0o105 => get_seg_prefix_ss(read_reg32(EBP) + read_imm8s()?),
0o205 => get_seg_prefix_ss(read_reg32(EBP) + read_imm32s()?),
0o006 => get_seg_prefix_ds(read_reg32(ESI)),
0o106 => get_seg_prefix_ds(read_reg32(ESI) + read_imm8s()?),
0o206 => get_seg_prefix_ds(read_reg32(ESI) + read_imm32s()?),
0o007 => get_seg_prefix_ds(read_reg32(EDI)),
0o107 => get_seg_prefix_ds(read_reg32(EDI) + read_imm8s()?),
0o207 => get_seg_prefix_ds(read_reg32(EDI) + read_imm32s()?),
_ => {
dbg_assert!(false);
std::hint::unreachable_unchecked()
},
}
}