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()
}
}
}