1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
use crate::resources::{Operand, GeneralPurposeRegister};
#[derive(Eq, Ord, PartialOrd, PartialEq, Debug, Clone, Copy)]
pub struct ModRM {
mode: AddressingMode,
reg: u8,
rm: u8,
}
impl ModRM {
pub fn to_byte(&self) -> u8 {
Self::mode_field(self.mode.to_byte()) | self.reg | self.rm
}
pub fn new_mi(mode: AddressingMode, rm: &Operand) -> Self {
let rm_byte = if rm.req_sib_byte() {
0x04
} else {
rm.number()
};
Self {
mode,
rm: Self::rm_field(rm_byte),
reg: 0,
}
}
pub fn new_mr(mode: AddressingMode, rm: &Operand, reg: &GeneralPurposeRegister) -> Self {
let rm_byte = if rm.req_sib_byte() {
0x04
} else {
rm.number()
};
Self {
mode,
rm: Self::rm_field(rm_byte),
reg: Self::reg_field(reg.number()),
}
}
pub fn new_rm(mode: AddressingMode, reg: &GeneralPurposeRegister, rm: &Operand) -> Self {
let rm_byte = if rm.req_sib_byte() {
0x04
} else {
rm.number()
};
Self {
mode,
rm: Self::rm_field(rm_byte),
reg: Self::reg_field(reg.number()),
}
}
pub fn mode_field(byte: u8) -> u8 {
byte << 6
}
pub fn rm_field(byte: u8) -> u8 {
byte
}
pub fn reg_field(byte: u8) -> u8 {
byte << 3
}
}
#[derive(Eq, Ord, PartialOrd, PartialEq, Debug, Clone, Copy)]
pub enum AddressingMode {
DISP8,
DISP32,
REGISTER,
DIRECTREG,
}
impl AddressingMode {
pub fn to_byte(&self) -> u8 {
match self {
Self::REGISTER => 0b00,
Self::DISP8 => 0b01,
Self::DISP32 => 0b10,
Self::DIRECTREG => 0b11,
}
}
}