diff options
Diffstat (limited to 'src/cpu')
-rw-r--r-- | src/cpu/chip.rs | 84 |
1 files changed, 79 insertions, 5 deletions
diff --git a/src/cpu/chip.rs b/src/cpu/chip.rs index f1ebeb8..8c9032e 100644 --- a/src/cpu/chip.rs +++ b/src/cpu/chip.rs @@ -111,6 +111,17 @@ impl Flags { carry: 0, } } + + fn get_cond(&self, cond: u8) -> u16 { + match cond { + 0 => { (self.n as u16) << 8 | self.zero as u16 } + 1 => { self.zero as u16 } + 2 => { (self.n as u16) << 8 | self.carry as u16 } + 3 => { self.carry as u16 } + _ => { panic!("Invalid Condition for Flags!") } + + } + } } #[derive(Debug)] @@ -128,6 +139,7 @@ pub struct Chip { pub byte2: u8, pub byte3: u8, pub flags: Flags, //Lower bits of AF, Flags register + pub ime: u8, // IME (Interrupt) flag pub rom_bank_0: [u8; 16384], pub rom_bank_n: [u8; 16384], pub external_ram_bank_n: [u8; 8192], @@ -153,6 +165,7 @@ impl Chip { byte2: 0, byte3: 0, flags: Flags::new(), + ime: 0, rom_bank_0: [0; 16384], rom_bank_n: [0; 16384], external_ram_bank_n: [00; 8192], @@ -390,7 +403,7 @@ impl Chip { println!("{:b} {:b} {:b}", oct1, oct2, oct3); match (oct1, oct2, oct3) { - (0b11, 0b001, 0b001) => { }, //CB-prefixed instructions + // (0b11, 0b001, 0b001) => { }, //CB-prefixed instructions (0b00, 0b000, 0b000) => { println!("NOOP") }, //noop (0b00, 0b001, 0b000) => { self.ld_u16_sp() }, //LD (u16), SP (0b00, 0b010, 0b000) => { println!("STOP") }, //STOP @@ -409,19 +422,25 @@ impl Chip { (0b01, 0b110, 0b110) => { self.halt() }, //HALT (0b01, dst_r8, src_r8) => { self.ld_r8_r8(src_r8, dst_r8) }, //LD r8, r8 (0b10, op, r8) => { self.alu_a_r8(op, r8); }, //ALU A, r8 - (0b11, 0b000..=0b011, 0b000) => { }, //RET condition + (0b11, 0b000..=0b011, 0b000) => { self.ret_cond(oct2) }, //RET condition (0b11, 0b100, 0b000) => { self.ldh_i16_a() }, //LD (FF00 + u8), A (0b11, 0b101, 0b000) => { self.add_sp_i8() }, //ADD SP, i8 (0b11, 0b110, 0b000) => { self.ldh_a_i16() }, //LD A, (FF00 + u8) (0b11, 0b111, 0b000) => { self.ld_hl_sp_imm8() }, //LD HL, SP + i8 (0b11, 0b000|0b010|0b100|0b110, 0b001) => { self.pop_r16(oct2) }, //POP r16 - (0b11, 0b001|0b011|0b101|0b111, 0b001) => { }, //0: RET, 1: RETI, 2: JP HL, 3: LD SP, HL - (0b11, 0b000..=0b011, 0b010) => { }, //JP + (0b11, 0b001, 0b001) => { self.ret() }, // RET + (0b11, 0b011, 0b001) => { self.reti() }, // RETI + (0b11, 0b101, 0b001) => { self.jp_hl() }, // JP HL + (0b11, 0b111, 0b001) => { self.ld_sp_hl() }, // LD SP, HL + (0b11, 0b000..=0b011, 0b010) => { self.jp_cond(oct2) }, //JP (0b11, 0b100, 0b010) => { self.ldh_c_a() }, //LD (FF00 + C), A (0b11, 0b101, 0b010) => { self.ld_n16_a() }, //LD (u16), A (0b11, 0b110, 0b010) => { self.ldh_a_c() }, //LD A, (FF00 + C) (0b11, 0b111, 0b010) => { self.ld_a_n16() }, //LD A, (u16) - (0b11, opcode, 0b011) => { }, //0: JP u16, 1: CB prefix, 6: DI, 7: EI + (0b11, 0b000, 0b011) => { self.jp_u16() }, //JP u16 + (0b11, 0b001, 0b011) => { }, //CB prefix + (0b11, 0b110, 0b011) => { self.di() }, //DI + (0b11, 0b111, 0b011) => { self.ei() }, //EI (0b11, 0b000..=0b011, 0b100) => { }, //CALL condition (0b11, 0b000|0b010|0b100|0b110, 0b101) => { self.push_r16(oct2) }, //PUSH r16 (0b11, 0b001, 0b101) => { }, //CALL u16 @@ -434,6 +453,61 @@ impl Chip { } + + fn ei(&mut self) { + self.ime = 1; + } + fn di(&mut self) { + self.ime = 0; + } + + // Jump to address u16 + fn jp_u16(&mut self) { + let address = (self.byte2 as u16) << 8 | self.byte3 as u16; + self.pc = address; + } + + // Jump based on condition + fn jp_cond(&mut self, cond: u8) { + // If condition true, JUMP + if self.flags.get_cond(cond) != 0 { + self.jp_u16(); + } + } + + // Load value of HL into SP + fn ld_sp_hl(&mut self) { + self.sp = self.get_r16_register(REGISTER16::SP); + } + // Jump to address to HL + fn jp_hl(&mut self) { + self.pc = self.get_r16_register(REGISTER16::HL); + } + + // Enable interrupts and RETURN + fn reti(&mut self) { + // Enable interrupt + self.ei(); + self.ret(); + } + + // RETURN + fn ret(&mut self) { + let low = self.read_memory(self.sp); + self.sp += 1; + let high = self.read_memory(self.sp); + self.sp += 1; + let value = (((high as u16) << 8) as u16) | (low as u16); + self.pc = value; + } + // RETURN based on condition + fn ret_cond(&mut self, ret_code: u8) { + // If condition true, RET + if self.flags.get_cond(ret_code) != 0 { + self.ret(); + } + } + // Push to stack fn push_r16(&mut self, r16: u8) { let value = self.get_r16stk_register(r16.into()); |