native_v86_core/cpu/
modrm.rs1use 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}