ruboy_lib/isa/
mod.rs

1use std::fmt::Display;
2
3mod cycles;
4pub mod decoder;
5mod len;
6
7#[cfg(test)]
8mod testutils;
9
10pub use cycles::*;
11
12#[cfg(feature = "isa_display")]
13pub mod display;
14
15#[derive(Debug, Copy, Clone)]
16pub enum Reg8 {
17    A,
18    B,
19    C,
20    D,
21    E,
22    F,
23    H,
24    L,
25}
26
27#[derive(Debug, Copy, Clone)]
28pub enum Reg16 {
29    AF,
30    BC,
31    DE,
32    HL,
33    SP,
34}
35
36#[derive(Debug, Copy, Clone)]
37pub enum MemLoc {
38    /// 0xFF00 + u8
39    HighMemReg(Reg8),
40    Reg(Reg16),
41    /// 0xFF00 + u8
42    HighMemImm(u8),
43    Imm(u16),
44}
45
46#[derive(Debug, Copy, Clone)]
47pub enum ArithSrc {
48    Reg(Reg8),
49    Imm(u8),
50    Mem(MemLoc),
51}
52
53#[derive(Debug, Copy, Clone)]
54pub enum Ld8Src {
55    Reg(Reg8),
56    Mem(MemLoc),
57    Imm(u8),
58}
59
60#[derive(Debug, Copy, Clone)]
61pub enum Ld8Dst {
62    Mem(MemLoc),
63    Reg(Reg8),
64}
65
66#[derive(Debug, Copy, Clone)]
67pub enum Ld16Src {
68    Reg(Reg16),
69    Imm(u16),
70}
71
72impl Ld16Src {
73    const fn op_size(&self) -> u8 {
74        match self {
75            Ld16Src::Reg(_) => 0,
76            Ld16Src::Imm(_) => 2,
77        }
78    }
79}
80
81#[derive(Debug, Copy, Clone)]
82pub enum Ld16Dst {
83    Mem(MemLoc),
84    Reg(Reg16),
85}
86
87#[derive(Debug, Copy, Clone)]
88pub enum IncDecTarget {
89    Reg8(Reg8),
90    Reg16(Reg16),
91    MemHL,
92}
93
94#[derive(Debug, Copy, Clone)]
95pub enum PrefArithTarget {
96    Reg(Reg8),
97
98    /// Memory location in HL
99    MemHL,
100}
101
102#[derive(Debug, Copy, Clone)]
103pub enum Bit {
104    B0 = 0,
105    B1 = 1,
106    B2 = 2,
107    B3 = 3,
108    B4 = 4,
109    B5 = 5,
110    B6 = 6,
111    B7 = 7,
112}
113
114#[derive(Debug, Copy, Clone)]
115pub enum Condition {
116    Zero,
117    NotZero,
118    Carry,
119    NotCarry,
120}
121
122#[derive(Debug, Copy, Clone)]
123pub enum RsVec {
124    Rst0 = 0x00,
125    Rst1 = 0x08,
126    Rst2 = 0x10,
127    Rst3 = 0x18,
128    Rst4 = 0x20,
129    Rst5 = 0x28,
130    Rst6 = 0x30,
131    Rst7 = 0x38,
132}
133
134#[derive(Debug, Copy, Clone)]
135pub enum Instruction {
136    /// No operation
137    Nop,
138
139    /// Enter low power mode
140    Stop(u8),
141
142    /// Enter low power mode until interrupt
143    Halt,
144
145    /// Enable interrupts _after_ instruction following this one by setting IME
146    EI,
147
148    /// Disable interrupts by clearing IME
149    DI,
150
151    /// Add value from source to register A, store result in A
152    Add(ArithSrc),
153
154    /// Add value from source plus carry flag to register A, store result in A
155    AddCarry(ArithSrc),
156
157    /// Add value from source to register HL, store result in HL
158    AddHL(Reg16),
159
160    /// Add signed value to SP
161    AddSP(i8),
162
163    /// Subtract value from source from register A, store result in A
164    Sub(ArithSrc),
165
166    /// Subtract value from source plus carry flag from register A, store result in A
167    SubCarry(ArithSrc),
168
169    /// Bitwise AND of register A and source, store result in A
170    And(ArithSrc),
171
172    /// Bitwise OR of register A and source, store result in A
173    Or(ArithSrc),
174
175    /// Bitwise XOR of register A and source, store result in A    
176    Xor(ArithSrc),
177
178    /// Subtract value from source from register A, set flags but don't store result
179    Cmp(ArithSrc),
180
181    /// Increment value at target
182    Inc(IncDecTarget),
183
184    /// Decrement value at target
185    Dec(IncDecTarget),
186
187    /// Rotate left
188    RotLeftCircular(PrefArithTarget),
189
190    /// Rotate A left
191    RotLeftCircularA,
192
193    /// Rotate right
194    RotRightCircular(PrefArithTarget),
195
196    /// Rotate A right
197    RotRightCircularA,
198
199    /// Rotate left through carry
200    RotLeft(PrefArithTarget),
201
202    /// Rotate A left through carry
203    RotLeftA,
204
205    /// Rotate right through carry
206    RotRight(PrefArithTarget),
207
208    /// Rotate A right through carry
209    RotRightA,
210
211    /// Shift left arithmetically
212    ShiftLeftArith(PrefArithTarget),
213
214    /// Shift right arithmetically
215    ShiftRightArith(PrefArithTarget),
216
217    /// Swap upper and lower 4 bits
218    Swap(PrefArithTarget),
219
220    /// Shift right locically
221    ShiftRightLogic(PrefArithTarget),
222
223    /// Set zero flag if bit is 0
224    Bit(Bit, PrefArithTarget),
225
226    /// Set bit to 0 (RESET)
227    Res(Bit, PrefArithTarget),
228
229    /// Set bit to 1 (SET)
230    Set(Bit, PrefArithTarget),
231
232    /// Load 8 bit value from source to destination
233    Load8(Ld8Dst, Ld8Src),
234
235    /// Load 16 bit value from source to destination
236    Load16(Ld16Dst, Ld16Src),
237
238    /// Load value from A into address stored in HL, increment HL afterwards
239    LoadAtoHLI,
240
241    /// Load value from A into address stored in HL, decrement HL afterwards
242    LoadAtoHLD,
243
244    /// Load value from address stored in HL into A, increment HL afterwards
245    LoadHLItoA,
246
247    /// Load value from address stored in HL into A, decrement HL afterwards
248    LoadHLDtoA,
249
250    /// Add SP to signed immediate value, store result in HL
251    LoadSPi8toHL(i8),
252
253    /// Jump to address
254    Jump(u16),
255
256    /// Jump to relative address
257    JumpRel(i8),
258
259    /// Jump to address stored in HL
260    JumpHL,
261
262    /// Jump to address if condition is met
263    JumpIf(u16, Condition),
264
265    /// Jump to relative address if condition is met
266    JumpRelIf(i8, Condition),
267
268    /// Call subroutine at address
269    Call(u16),
270
271    /// Call subroutine at address if condition is met
272    CallIf(u16, Condition),
273
274    /// Return from subroutine, AKA pop PC from stack
275    Ret,
276
277    /// Same as [Instruction::Ret], but enables interrupts before returning
278    Reti,
279
280    /// Return from subroutine if condition is met, AKA pop PC from stack if condition is met
281    RetIf(Condition),
282
283    /// Pop value from stack into register
284    Pop(Reg16),
285
286    /// Push value from register onto stack
287    Push(Reg16),
288
289    /// Decimal Adjust Accumulator to get correct BCD representation after an arithmetic
290    /// instruction
291    /// TODO: What does that actually mean
292    DecimalAdjust,
293
294    /// Complement A (A = ~A)
295    ComplementAccumulator,
296
297    /// Set carry flag to 1
298    SetCarryFlag,
299
300    /// Inverts carry flag
301    ComplementCarry,
302
303    /// Call address contained in this instruction.
304    Rst(RsVec),
305
306    /// Illegal instruction, stop CPU. Opcode is provided for debugging
307    IllegalInstruction(u8),
308}
309
310impl Display for Instruction {
311    #[cfg(feature = "isa_display")]
312    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
313        let as_displayable = display::DisplayableInstruction::from(*self);
314
315        write!(
316            f,
317            "{}",
318            as_displayable.with_format(&display::FormatOpts::rgdbs())
319        )
320    }
321
322    #[cfg(not(feature = "isa_display"))]
323    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
324        write!(f, "{:?}", self)
325    }
326}