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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
use super::environment::*;
use super::registers::*;
type OpcodeFn = dyn Fn(&mut Environment) -> ();
pub struct Opcode {
pub name: String,
pub action: Box<OpcodeFn>,
}
impl Opcode {
pub fn execute(&self, env: &mut Environment) {
(self.action)(env);
}
pub fn disasm(&self, env: &Environment) -> String {
let name = format!("{} {}",
env.index_description(), self.name);
if self.name.contains("nn") {
let nn = env.peek16_pc();
let nn_str = format!("{:04x}h", nn);
name.replace("nn", &nn_str)
} else if self.name.contains("n") {
let n = env.peek_pc();
let n_str = format!("{:02x}h", n);
name.replace("n", &n_str)
} else if self.name.contains("d") {
let d = env.peek_pc() as i8 as i16 + 2;
let d_str = format!("{:+x}", d);
name.replace("d", &d_str)
} else {
name
}
}
}
pub fn build_prefix(index: Reg16) -> Opcode {
Opcode {
name: format!("PREFIX {:?}", index),
action: Box::new(move |env: &mut Environment| {
env.set_index(index );
})
}
}
pub fn build_nop() -> Opcode {
Opcode {
name: "NOP".to_string(),
action: Box::new(|_: &mut Environment| {
})
}
}
pub fn build_noni_nop() -> Opcode {
Opcode {
name: "NONINOP".to_string(),
action: Box::new(|_: &mut Environment| {
})
}
}
pub fn build_halt() -> Opcode {
Opcode {
name: "HALT".to_string(),
action: Box::new(move |env: &mut Environment| {
env.state.halted = true;
})
}
}
pub fn build_pop_rr(rr: Reg16) -> Opcode {
Opcode {
name: format!("POP {:?}", rr),
action: Box::new(move |env: &mut Environment| {
let value = env.pop();
env.set_reg16(rr, value);
})
}
}
pub fn build_push_rr(rr: Reg16) -> Opcode {
Opcode {
name: format!("PUSH {:?}", rr),
action: Box::new(move |env: &mut Environment| {
let value = env.reg16_ext(rr);
env.push(value);
})
}
}
pub fn build_conf_interrupts(enable: bool) -> Opcode {
let name = if enable {"EI"} else {"DI"};
Opcode {
name: name.to_string(),
action: Box::new(move |env: &mut Environment| {
env.state.reg.set_interrupts(enable);
})
}
}
pub fn build_im(im: u8) -> Opcode {
Opcode {
name: format!("IM {}", im),
action: Box::new(move |env: &mut Environment| {
env.state.reg.set_interrupt_mode(im);
})
}
}