Skip to main content

native_v86_core/cpu/
modrm.rs

1use crate::cpu::cpu::*;
2use crate::paging::OrPageFault;
3
4pub unsafe fn resolve_modrm16(modrm_byte: i32) -> OrPageFault<i32> {
5    match modrm_byte & !0o070 {
6        0o000 => get_seg_prefix_ds(read_reg16(BX) + read_reg16(SI) & 0xFFFF),
7        0o100 => get_seg_prefix_ds(read_reg16(BX) + read_reg16(SI) + read_imm8s()? & 0xFFFF),
8        0o200 => get_seg_prefix_ds(read_reg16(BX) + read_reg16(SI) + read_imm16()? & 0xFFFF),
9        0o001 => get_seg_prefix_ds(read_reg16(BX) + read_reg16(DI) & 0xFFFF),
10        0o101 => get_seg_prefix_ds(read_reg16(BX) + read_reg16(DI) + read_imm8s()? & 0xFFFF),
11        0o201 => get_seg_prefix_ds(read_reg16(BX) + read_reg16(DI) + read_imm16()? & 0xFFFF),
12        0o002 => get_seg_prefix_ss(read_reg16(BP) + read_reg16(SI) & 0xFFFF),
13        0o102 => get_seg_prefix_ss(read_reg16(BP) + read_reg16(SI) + read_imm8s()? & 0xFFFF),
14        0o202 => get_seg_prefix_ss(read_reg16(BP) + read_reg16(SI) + read_imm16()? & 0xFFFF),
15        0o003 => get_seg_prefix_ss(read_reg16(BP) + read_reg16(DI) & 0xFFFF),
16        0o103 => get_seg_prefix_ss(read_reg16(BP) + read_reg16(DI) + read_imm8s()? & 0xFFFF),
17        0o203 => get_seg_prefix_ss(read_reg16(BP) + read_reg16(DI) + read_imm16()? & 0xFFFF),
18        0o004 => get_seg_prefix_ds(read_reg16(SI) & 0xFFFF),
19        0o104 => get_seg_prefix_ds(read_reg16(SI) + read_imm8s()? & 0xFFFF),
20        0o204 => get_seg_prefix_ds(read_reg16(SI) + read_imm16()? & 0xFFFF),
21        0o005 => get_seg_prefix_ds(read_reg16(DI) & 0xFFFF),
22        0o105 => get_seg_prefix_ds(read_reg16(DI) + read_imm8s()? & 0xFFFF),
23        0o205 => get_seg_prefix_ds(read_reg16(DI) + read_imm16()? & 0xFFFF),
24        0o006 => get_seg_prefix_ds(read_imm16()?),
25        0o106 => get_seg_prefix_ss(read_reg16(BP) + read_imm8s()? & 0xFFFF),
26        0o206 => get_seg_prefix_ss(read_reg16(BP) + read_imm16()? & 0xFFFF),
27        0o007 => get_seg_prefix_ds(read_reg16(BX) & 0xFFFF),
28        0o107 => get_seg_prefix_ds(read_reg16(BX) + read_imm8s()? & 0xFFFF),
29        0o207 => get_seg_prefix_ds(read_reg16(BX) + read_imm16()? & 0xFFFF),
30        _ => {
31            dbg_assert!(false);
32            std::hint::unreachable_unchecked()
33        }
34    }
35}
36
37pub unsafe fn resolve_modrm32_(modrm_byte: i32) -> OrPageFault<i32> {
38    let r = (modrm_byte & 7) as u8;
39    dbg_assert!(modrm_byte < 192);
40    Ok(if r as i32 == 4 {
41        if modrm_byte < 64 {
42            resolve_sib(false)?
43        } else {
44            resolve_sib(true)?.wrapping_add(if modrm_byte < 128 {
45                read_imm8s()?
46            } else {
47                read_imm32s()?
48            })
49        }
50    } else if r as i32 == 5 {
51        if modrm_byte < 64 {
52            get_seg_prefix_ds(read_imm32s()?)?
53        } else {
54            get_seg_prefix_ss(read_reg32(EBP).wrapping_add(if modrm_byte < 128 {
55                read_imm8s()?
56            } else {
57                read_imm32s()?
58            }))?
59        }
60    } else if modrm_byte < 64 {
61        get_seg_prefix_ds(read_reg32(r as i32))?
62    } else {
63        get_seg_prefix_ds(read_reg32(r as i32).wrapping_add(if modrm_byte < 128 {
64            read_imm8s()?
65        } else {
66            read_imm32s()?
67        }))?
68    })
69}
70unsafe fn resolve_sib(with_imm: bool) -> OrPageFault<i32> {
71    let sib_byte = read_imm8()?;
72    let r = sib_byte & 7;
73    let m = sib_byte >> 3 & 7;
74    let base;
75    let seg;
76    if r == 4 {
77        base = read_reg32(ESP);
78        seg = SS
79    } else if r == 5 {
80        if with_imm {
81            base = read_reg32(EBP);
82            seg = SS
83        } else {
84            base = read_imm32s()?;
85            seg = DS
86        }
87    } else {
88        base = read_reg32(r);
89        seg = DS
90    }
91    let offset;
92    if m == 4 {
93        offset = 0
94    } else {
95        let s = sib_byte >> 6 & 3;
96        offset = read_reg32(m) << s
97    }
98    Ok(get_seg_prefix(seg)?.wrapping_add(base).wrapping_add(offset))
99}
100
101pub unsafe fn resolve_modrm32(modrm_byte: i32) -> OrPageFault<i32> {
102    match modrm_byte & !0o070 {
103        0o000 => get_seg_prefix_ds(read_reg32(EAX)),
104        0o100 => get_seg_prefix_ds(read_reg32(EAX).wrapping_add(read_imm8s()?)),
105        0o200 => get_seg_prefix_ds(read_reg32(EAX).wrapping_add(read_imm32s()?)),
106        0o001 => get_seg_prefix_ds(read_reg32(ECX)),
107        0o101 => get_seg_prefix_ds(read_reg32(ECX).wrapping_add(read_imm8s()?)),
108        0o201 => get_seg_prefix_ds(read_reg32(ECX).wrapping_add(read_imm32s()?)),
109        0o002 => get_seg_prefix_ds(read_reg32(EDX)),
110        0o102 => get_seg_prefix_ds(read_reg32(EDX).wrapping_add(read_imm8s()?)),
111        0o202 => get_seg_prefix_ds(read_reg32(EDX).wrapping_add(read_imm32s()?)),
112        0o003 => get_seg_prefix_ds(read_reg32(EBX)),
113        0o103 => get_seg_prefix_ds(read_reg32(EBX).wrapping_add(read_imm8s()?)),
114        0o203 => get_seg_prefix_ds(read_reg32(EBX).wrapping_add(read_imm32s()?)),
115        0o004 => resolve_sib(false),
116        0o104 => Ok(resolve_sib(true)?.wrapping_add(read_imm8s()?)),
117        0o204 => Ok(resolve_sib(true)?.wrapping_add(read_imm32s()?)),
118        0o005 => get_seg_prefix_ds(read_imm32s()?),
119        0o105 => get_seg_prefix_ss(read_reg32(EBP).wrapping_add(read_imm8s()?)),
120        0o205 => get_seg_prefix_ss(read_reg32(EBP).wrapping_add(read_imm32s()?)),
121        0o006 => get_seg_prefix_ds(read_reg32(ESI)),
122        0o106 => get_seg_prefix_ds(read_reg32(ESI).wrapping_add(read_imm8s()?)),
123        0o206 => get_seg_prefix_ds(read_reg32(ESI).wrapping_add(read_imm32s()?)),
124        0o007 => get_seg_prefix_ds(read_reg32(EDI)),
125        0o107 => get_seg_prefix_ds(read_reg32(EDI).wrapping_add(read_imm8s()?)),
126        0o207 => get_seg_prefix_ds(read_reg32(EDI).wrapping_add(read_imm32s()?)),
127        _ => {
128            dbg_assert!(false);
129            std::hint::unreachable_unchecked()
130        }
131    }
132}