load.rsannotatedload.rssource175 lines · 6.5 KB · raw
1use crate::sm83::bus::BusInterface;
2use crate::sm83::{BusExt, Sm83};
3
4impl Sm83 {
5    // LD r, r': Load value into r from r'
6    pub(super) fn ld_r_r<B: BusInterface>(&mut self, bus: &mut B, opcode: u8) {
7        let value = self.read_register(bus, opcode);
8        self.write_register(bus, opcode >> 3, value);
9    }
10
11    // LD r, u8: Load 8-bit immediate value into r
12    pub(super) fn ld_r_imm<B: BusInterface>(&mut self, bus: &mut B, opcode: u8) {
13        let value = self.fetch_operand(bus);
14        self.write_register(bus, opcode >> 3, value);
15    }
16
17    // LD (BC), A: Load value into address specified by BC from A
18    pub(super) fn ld_bc_a<B: BusInterface>(&mut self, bus: &mut B) {
19        bus.write(self.registers.bc(), self.registers.a);
20    }
21
22    // LD (DE), A: Load value into address specified by DE from A
23    pub(super) fn ld_de_a<B: BusInterface>(&mut self, bus: &mut B) {
24        bus.write(self.registers.de(), self.registers.a);
25    }
26
27    // LD (HL+), A: Load value into address specified by HL from A, then increment HL
28    pub(super) fn ld_hl_a_postinc<B: BusInterface>(&mut self, bus: &mut B) {
29        bus.write(self.registers.hl(), self.registers.a);
30        self.registers.increment_hl();
31    }
32
33    // LD (HL-), A: Load value into address specified by HL from A, then decrement HL
34    pub(super) fn ld_hl_a_postdec<B: BusInterface>(&mut self, bus: &mut B) {
35        bus.write(self.registers.hl(), self.registers.a);
36        self.registers.decrement_hl();
37    }
38
39    // LD A, (BC): Load value into A from address specified by BC
40    pub(super) fn ld_a_bc<B: BusInterface>(&mut self, bus: &mut B) {
41        self.registers.a = bus.read(self.registers.bc());
42    }
43
44    // LD A, (DE): Load value into A from address specified by DE
45    pub(super) fn ld_a_de<B: BusInterface>(&mut self, bus: &mut B) {
46        self.registers.a = bus.read(self.registers.de());
47    }
48
49    // LD A, (HL+): Load value into A from address specified by HL, then increment HL
50    pub(super) fn ld_a_hl_postinc<B: BusInterface>(&mut self, bus: &mut B) {
51        self.registers.a = bus.read(self.registers.hl());
52        self.registers.increment_hl();
53    }
54
55    // LD A, (HL-): Load value into A from address specified by HL, then decrement HL
56    pub(super) fn ld_a_hl_postdec<B: BusInterface>(&mut self, bus: &mut B) {
57        self.registers.a = bus.read(self.registers.hl());
58        self.registers.decrement_hl();
59    }
60
61    // LD (u16), A: Load value into address specified by 16-bit immediate operand from A
62    pub(super) fn ld_indirect_a<B: BusInterface>(&mut self, bus: &mut B) {
63        let address = self.fetch_operand_u16(bus);
64        bus.write(address, self.registers.a);
65    }
66
67    // LD A, (u16): Load value into A from address specified by 16-bit immediate operand
68    pub(super) fn ld_a_indirect<B: BusInterface>(&mut self, bus: &mut B) {
69        let address = self.fetch_operand_u16(bus);
70        self.registers.a = bus.read(address);
71    }
72
73    // LDH (u8), A: Load value into address $FFxx from A, where xx is the 8-bit immediate operand
74    pub(super) fn ldh_imm_a<B: BusInterface>(&mut self, bus: &mut B) {
75        let address_lsb = self.fetch_operand(bus);
76        let address = u16::from_le_bytes([address_lsb, 0xFF]);
77        bus.write(address, self.registers.a);
78    }
79
80    // LDH A, (u8): Load value into A from address $FFxx, where xx is the 8-bit immediate operand
81    pub(super) fn ldh_a_imm<B: BusInterface>(&mut self, bus: &mut B) {
82        let address_lsb = self.fetch_operand(bus);
83        let address = u16::from_le_bytes([address_lsb, 0xFF]);
84        self.registers.a = bus.read(address);
85    }
86
87    // LD ($FF00+C), A: Load value into address $FFxx from A, where xx is the value in C
88    pub(super) fn ld_c_a_high_page<B: BusInterface>(&mut self, bus: &mut B) {
89        let address = u16::from_le_bytes([self.registers.c, 0xFF]);
90        bus.write(address, self.registers.a);
91    }
92
93    // LD A, ($FF00+C): Load value into A from address $FFxx, where xx is the value in C
94    pub(super) fn ld_a_c_high_page<B: BusInterface>(&mut self, bus: &mut B) {
95        let address = u16::from_le_bytes([self.registers.c, 0xFF]);
96        self.registers.a = bus.read(address);
97    }
98
99    // LD rr, nn: Load 16-bit immediate value into register pair (or SP)
100    pub(super) fn ld_rr_nn<B: BusInterface>(&mut self, bus: &mut B, opcode: u8) {
101        let lsb = self.fetch_operand(bus);
102        let msb = self.fetch_operand(bus);
103
104        match (opcode >> 4) & 0x3 {
105            0x0 => {
106                self.registers.b = msb;
107                self.registers.c = lsb;
108            }
109            0x1 => {
110                self.registers.d = msb;
111                self.registers.e = lsb;
112            }
113            0x2 => {
114                self.registers.h = msb;
115                self.registers.l = lsb;
116            }
117            0x3 => {
118                self.registers.sp = u16::from_le_bytes([lsb, msb]);
119            }
120            _ => unreachable!("value & 0x3 is always <= 0x3"),
121        }
122    }
123
124    // LD (u16), SP: Write stack pointer to address specified by 16-bit immediate value
125    pub(super) fn ld_indirect_sp<B: BusInterface>(&mut self, bus: &mut B) {
126        let address = self.fetch_operand_u16(bus);
127        bus.write_u16(address, self.registers.sp);
128    }
129
130    // LD SP, HL: Load into SP from HL
131    pub(super) fn ld_sp_hl<B: BusInterface>(&mut self, bus: &mut B) {
132        self.registers.sp = self.registers.hl();
133        bus.idle();
134    }
135
136    // PUSH: Push onto stack
137    pub(super) fn push_rr<B: BusInterface>(&mut self, bus: &mut B, opcode: u8) {
138        bus.idle();
139
140        let value = match (opcode >> 4) & 0x3 {
141            0x0 => self.registers.bc(),
142            0x1 => self.registers.de(),
143            0x2 => self.registers.hl(),
144            0x3 => self.registers.af(),
145            _ => unreachable!("value & 0x3 is always <= 0x3"),
146        };
147        self.push_stack_u16(bus, value);
148    }
149
150    // POP: Pop off of stack
151    pub(super) fn pop_rr<B: BusInterface>(&mut self, bus: &mut B, opcode: u8) {
152        let lsb = self.pop_stack(bus);
153        let msb = self.pop_stack(bus);
154
155        match (opcode >> 4) & 0x3 {
156            0x0 => {
157                self.registers.b = msb;
158                self.registers.c = lsb;
159            }
160            0x1 => {
161                self.registers.d = msb;
162                self.registers.e = lsb;
163            }
164            0x2 => {
165                self.registers.h = msb;
166                self.registers.l = lsb;
167            }
168            0x3 => {
169                self.registers.a = msb;
170                self.registers.f = lsb.into();
171            }
172            _ => unreachable!("value & 0x3 is always <= 0x3"),
173        }
174    }
175}