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}