Fix ADD, ADC, SUB, SBC, CP; Pass test

This commit is contained in:
Kevin Hamacher 2016-05-29 20:22:10 +02:00
parent 6455732043
commit 7dadc79078
2 changed files with 152 additions and 116 deletions

View File

@ -11,8 +11,8 @@ Display is able to render tiles + sprites, 8x16 sprites are implemented but unte
- Test 01 fails because of DAA
- Test 02 fails because interrupts are not fully implemented.
- Test 03 fails
- Test 04 fails
- Test 03 fails, probably because of flags.
- Test 04 passes
- Test 05 fails
- Test 06 passes (LD R, R)
- Test 07 fails

View File

@ -103,6 +103,90 @@ impl CPU {
}
}
#[inline]
fn adc_r(&mut self, val: u8) {
// Passes the test
let old: u8 = self.regs[REG_A];
let mut new: u8 = old;
let c: u8;
if self.flags & FLAG_C == FLAG_C {
c = 1;
} else {
c = 0;
}
new = new.wrapping_add(val);
new = new.wrapping_add(c);
self.regs[REG_A] = new;
self.clear_flag(FLAG_N);
self.set_clear_flag(FLAG_Z, new == 0);
self.set_clear_flag(FLAG_C, ((val + c) > 0 && new < old) || (c == 1 && new == old));
self.set_clear_flag(FLAG_H, ((old & 0x0F) + (val & 0x0F) + c) > 0x0F);
}
#[inline]
fn add_r(&mut self, val: u8) {
// Passes the test
let old: u8 = self.regs[REG_A];
let new: u8 = old.wrapping_add(val);
let carry: u16 = (old as u16) ^ (val as u16) ^ (new as u16);
self.regs[REG_A] = new;
self.clear_flag(FLAG_N);
self.set_clear_flag(FLAG_Z, new == 0);
self.set_clear_flag(FLAG_C, val > 0 && new < old);
self.set_clear_flag(FLAG_H, carry & 0x10 == 0x10);
}
#[inline]
fn sbc_r(&mut self, val: u8) {
// Passes the test
let old: u8 = self.regs[REG_A];
let mut new: u8 = old as u8;
let c: u8;
if self.flags & FLAG_C == FLAG_C {
c = 1;
} else {
c = 0;
}
new = new.wrapping_sub(val);
new = new.wrapping_sub(c);
self.regs[REG_A] = new;
self.set_flag(FLAG_N);
self.set_clear_flag(FLAG_Z, new == 0);
self.set_clear_flag(FLAG_C, new > old || (new == old && c == 1));
self.set_clear_flag(FLAG_H, ((old & 0x0F) - (val & 0x0F) - c) > 0x0F);
}
#[inline]
fn sub_r(&mut self, val: u8) {
// Passes the test
let old: u8 = self.regs[REG_A];
let new: u8 = old.wrapping_sub(val);
let carry: u16 = (old as u16) ^ (val as u16) ^ (new as u16);
self.regs[REG_A] = new;
self.set_flag(FLAG_N);
self.set_clear_flag(FLAG_Z, new == 0);
self.set_clear_flag(FLAG_C, new > old);
self.set_clear_flag(FLAG_H, carry & 0x10 == 0x10);
}
#[inline]
fn cp_r(&mut self, val: u8) {
// Passes the test
let old: u8 = self.regs[REG_A];
let new: u8 = old.wrapping_sub(val);
let carry: u16 = (old as u16) ^ (val as u16) ^ (new as u16);
self.set_flag(FLAG_N);
self.set_clear_flag(FLAG_Z, new == 0);
self.set_clear_flag(FLAG_C, new > old);
self.set_clear_flag(FLAG_H, carry & 0x10 == 0x10);
}
#[inline]
fn run_prefix_instruction(&mut self) {
let instruction = self.read_byte(self.ip);
@ -561,7 +645,7 @@ impl CPU {
#[inline]
fn rst(&mut self, val: u8) -> u8 {
// Make sure this is correct.
if self.debug {
if self.debug || true {
println!("RST {:02X}", val);
}
self.call(val as u16);
@ -626,7 +710,7 @@ impl CPU {
#[inline]
fn ld_r_r(&mut self, reg_dst: usize, reg_src: usize) -> u8 {
if self.debug {
// println!("LD {}, {}", REG_NAMES[reg_dst], REG_NAMES[reg_src])
println!("LD {}, {}", REG_NAMES[reg_dst], REG_NAMES[reg_src])
}
let sv = self.get_8bit_reg(reg_src);
self.set_8bit_reg(reg_dst, sv);
@ -641,7 +725,7 @@ impl CPU {
fn ld_r_v(&mut self, r: usize) -> u8 {
let val: u8 = self.load_args(1)[0];
if self.debug {
// println!("LD {}, {:02X}", REG_NAMES[r], val);
println!("LD {}, {:02X}", REG_NAMES[r], val);
}
self.set_8bit_reg(r, val);
if r == REG_N_HL {
@ -655,7 +739,7 @@ impl CPU {
fn ld_rr_vv(&mut self, r1: usize, r2: usize) -> u8 {
let val: u16 = to_u16(self.load_args(2));
if self.debug {
// println!("LD {}{}, {:04X}", REG_NAMES[r1], REG_NAMES[r2], val);
println!("LD {}{}, {:04X}", REG_NAMES[r1], REG_NAMES[r2], val);
}
self.set_pair_value(r1, r2, val);
12
@ -676,9 +760,21 @@ impl CPU {
#[inline]
fn add_rr_rr(&mut self, r1: usize, r2: usize, r3: usize, r4: usize) -> u8 {
if self.debug {
println!("ADD {}{}, {}{}", REG_NAMES[r1], REG_NAMES[r2], REG_NAMES[r3], REG_NAMES[r4]);
}
let val1 = self.get_pair_value(r1, r2);
let val2 = self.get_pair_value(r3, r4);
self.set_pair_value(r1, r2, val1.wrapping_add(val2));
let res = val1.wrapping_add(val2);
self.set_pair_value(r1, r2, res);
// We need to update the flags
self.clear_flag(FLAG_N);
// Some magic formula
self.set_clear_flag(FLAG_C, val1 as usize + val2 as usize & 0x10000 == 0x10000);
self.set_clear_flag(FLAG_H, (val1 ^ val2 ^ res) & 0x1000 == 0x1000);
8
}
@ -961,22 +1057,22 @@ impl CPU {
if self.flags & FLAG_N == 0 {
// Lower nibble
if self.flags & FLAG_H > 0 || (v & 0xF) > 9 {
if self.flags & FLAG_H == FLAG_H || (v & 0xF) > 9 {
v += 0x06;
}
// Higher nibble
if self.flags & FLAG_C > 0 || v > 0x9F {
if self.flags & FLAG_C == FLAG_C || v > 0x9F {
v += 0x60;
}
} else {
// Lower nibble
if self.flags & FLAG_H > 0 {
if self.flags & FLAG_H == FLAG_H {
v = v.wrapping_sub(6) & 0xFF;
}
// Higher nibble
if self.flags & FLAG_C > 0 {
if self.flags & FLAG_C == FLAG_C {
v = v.wrapping_sub(0x60);
}
}
@ -989,7 +1085,7 @@ impl CPU {
4
},
0x28 => {
let c = self.flags & FLAG_Z > 0;
let c = self.flags & FLAG_Z == FLAG_Z;
self.jmp_r_condition("Z".to_owned(), c)
},
0x29 => self.add_rr_rr(REG_N_H, REG_N_L, REG_N_H, REG_N_L),
@ -1033,7 +1129,7 @@ impl CPU {
if self.debug {
println!("LD (HL-), A");
}
let mut addr = self.get_pair_value(REG_N_H, REG_N_L);
let addr = self.get_pair_value(REG_N_H, REG_N_L);
self.interconnect.write_byte(addr, self.regs[REG_A]);
self.set_pair_value(REG_N_H, REG_N_L, addr.wrapping_sub(1));
8
@ -1059,7 +1155,7 @@ impl CPU {
4
},
0x38 => {
let c = self.flags & FLAG_C > 0;
let c = self.flags & FLAG_C == FLAG_C;
self.jmp_r_condition("C".to_owned(), c)
},
0x39 => {
@ -1073,8 +1169,8 @@ impl CPU {
self.clear_flag(FLAG_N);
self.set_clear_flag(FLAG_C, old > v);
// TODO: H-carry flag
// Is this correct? I don't know:
self.set_clear_flag(FLAG_H, (old & 0x8 | sp & 0x8) == 1 && v & 0x8 == 0);
8
},
0x3A => {
@ -1131,14 +1227,8 @@ impl CPU {
if self.debug {
println!("ADD {}", REG_NAMES[reg_id]);
}
let old = self.regs[REG_A];
let new = old.wrapping_add(self.get_8bit_reg(reg_id));
self.regs[REG_A] = new;
self.clear_flag(FLAG_N);
self.set_clear_flag(FLAG_Z, new == 0);
self.set_clear_flag(FLAG_C, new < old);
// TODO: H
let v = self.get_8bit_reg(reg_id);
self.add_r(v);
4
}
@ -1149,17 +1239,8 @@ impl CPU {
println!("ADC {}", REG_NAMES[reg_id]);
}
let old = self.regs[REG_A];
let mut new = old.wrapping_add(self.get_8bit_reg(reg_id));
if self.flags & FLAG_C > 0 {
new = new.wrapping_add(1);
}
self.regs[REG_A] = new;
self.clear_flag(FLAG_N);
self.set_clear_flag(FLAG_Z, new == 0);
self.set_clear_flag(FLAG_C, new < old);
// TODO: H
let v = self.get_8bit_reg(reg_id);
self.adc_r(v);
4
}
@ -1169,13 +1250,8 @@ impl CPU {
if self.debug {
println!("SUB {}", REG_NAMES[reg_id]);
}
let old = self.regs[REG_A];
let new = old.wrapping_sub(self.get_8bit_reg(reg_id));
self.regs[REG_A] = new;
self.set_flag(FLAG_N);
self.set_clear_flag(FLAG_Z, new == 0);
self.set_clear_flag(FLAG_C, new > old);
// TODO: H
let r = self.get_8bit_reg(reg_id);
self.sub_r(r);
4
}
@ -1185,16 +1261,8 @@ impl CPU {
if self.debug {
println!("SBC {}", REG_NAMES[reg_id]);
}
let old = self.regs[REG_A];
let mut new = old.wrapping_sub(self.get_8bit_reg(reg_id));
if self.flags & FLAG_C > 0 {
new = new.wrapping_sub(1);
}
self.regs[REG_A] = new;
self.set_flag(FLAG_N);
self.set_clear_flag(FLAG_Z, new == 0);
self.set_clear_flag(FLAG_C, new > old);
let r = self.get_8bit_reg(reg_id);
self.sbc_r(r);
4
}
@ -1252,13 +1320,9 @@ impl CPU {
if self.debug {
println!("CP {}", REG_NAMES[reg_id]);
}
let val = self.get_8bit_reg(reg_id);
let rval = self.regs[REG_A];
self.set_flag(FLAG_N);
self.set_clear_flag(FLAG_C, rval < val);
self.set_clear_flag(FLAG_Z, rval == val);
// TODO H
let v = self.get_8bit_reg(reg_id);
self.cp_r(v);
4
},
@ -1286,24 +1350,19 @@ impl CPU {
if self.debug {
println!("ADD A, {:02X}", val);
}
let o = self.regs[REG_A];
let v = self.regs[REG_A].wrapping_add(val);
self.regs[REG_A] = v;
self.set_clear_flag(FLAG_Z, v == 0);
self.set_clear_flag(FLAG_C, v < o);
self.clear_flag(FLAG_N);
// TOOD H
self.add_r(val);
8
},
0xC7 => self.rst(0x00),
0xC8 => {
let c = self.flags & FLAG_Z > 0;
let c = self.flags & FLAG_Z == FLAG_Z;
self.ret_condition("Z".to_owned(), c)
},
0xC9 => {self.ret(); 16},
0xCA => {
let c = self.flags & FLAG_Z > 0;
let c = self.flags & FLAG_Z == FLAG_Z;
self.jmp_p_condition("Z".to_owned(), c)
}
0xCB => {
@ -1312,7 +1371,7 @@ impl CPU {
12 // TODO: Verify that this is the case for all prefix instructions.
},
0xCC => {
let c = self.flags & FLAG_Z > 0;
let c = self.flags & FLAG_Z == FLAG_Z;
self.call_condition("Z".to_owned(), c)
},
0xCD => self.call_condition("".to_owned(), true),
@ -1321,19 +1380,7 @@ impl CPU {
if self.debug {
println!("ADC A, {:02X}", arg);
}
let o = self.regs[REG_A];
let mut v = self.regs[REG_A].wrapping_add(arg);
if self.flags & FLAG_C > 0 {
v = v.wrapping_add(1);
}
self.regs[REG_A] = v;
self.set_clear_flag(FLAG_Z, v == 0);
self.clear_flag(FLAG_N);
self.set_clear_flag(FLAG_C, v < o);
// TODO: FLAG_H
self.adc_r(arg);
8
},
0xCF => self.rst(0x08),
@ -1360,29 +1407,22 @@ impl CPU {
println!("SUB {:02X}", val);
}
let rval = self.regs[REG_A];
self.set_clear_flag(FLAG_C, val > rval);
self.set_clear_flag(FLAG_Z, val == rval);
self.set_flag(FLAG_N);
self.regs[REG_A] = rval.wrapping_sub(val);
// TODO: FLAG_H
self.sub_r(val);
8
},
0xD7 => self.rst(0x10),
0xD8 => {
let c = self.flags & FLAG_C > 0;
let c = self.flags & FLAG_C == FLAG_C;
self.ret_condition("C".to_owned(), c)
},
0xD9 => self.reti(),
0xDA => {
let c = self.flags & FLAG_C > 0;
let c = self.flags & FLAG_C == FLAG_C;
self.jmp_p_condition("C".to_owned(), c)
},
0xDB => panic!("NON-EXISTING OPCODE"),
0xDC => {
let c = self.flags & FLAG_C > 0;
let c = self.flags & FLAG_C == FLAG_C;
self.call_condition("C".to_owned(), c)
}
0xDD => panic!("NON-EXISTING OPCODE"),
@ -1391,17 +1431,7 @@ impl CPU {
if self.debug {
println!("SBC {:02X}", arg);
}
let o = self.regs[REG_A];
let mut v = self.regs[REG_A].wrapping_sub(arg);
if self.flags & FLAG_C > 0 {
v = v.wrapping_sub(1);
}
self.regs[REG_A] = v;
self.set_clear_flag(FLAG_Z, v == 0);
self.set_clear_flag(FLAG_C, v > o);
self.set_flag(FLAG_N);
// TODO: FLAG_H
self.sbc_r(arg);
8
},
0xDF => self.rst(0x18),
@ -1441,16 +1471,21 @@ impl CPU {
},
0xE7 => self.rst(0x20),
0xE8 => {
let arg = self.load_args(1)[0];
let arg = self.load_args(1)[0] as i8;
if self.debug {
println!("ADD SP, {:02X}", arg);
}
let t = self.sp.wrapping_add(arg as u16);
let t: u16;
if arg > 0 {
t = self.sp.wrapping_add(arg as u16);
} else {
t = self.sp.wrapping_sub((-arg) as u16);
}
let sp = self.sp;
self.clear_flag(FLAG_N);
self.clear_flag(FLAG_Z);
self.set_clear_flag(FLAG_C, t < sp);
// TODO FLAG_H
self.set_clear_flag(FLAG_C, (sp ^ arg as u16 ^ t) & 0x100 == 0x100);
self.set_clear_flag(FLAG_H, (sp ^ arg as u16 ^ t) & 0x10 == 0x10);
self.sp = t;
16
}
@ -1526,21 +1561,26 @@ impl CPU {
},
0xF7 => self.rst(0x30),
0xF8 => {
let arg = self.load_args(1)[0] as i16;
let arg = self.load_args(1)[0] as i8;
if self.debug {
println!("LD HL, SP+{:02X}", arg);
}
self.clear_flag(FLAG_N);
self.clear_flag(FLAG_Z);
let sp = self.sp;
if arg < 0 {
let v: u16 = self.sp.wrapping_sub((-arg) as u16);
self.set_pair_value(REG_N_H, REG_N_L, v);
self.set_clear_flag(FLAG_C, (sp ^ arg as u16 ^ v) & 0x100 == 0x100);
self.set_clear_flag(FLAG_H, (sp ^ arg as u16 ^ v) & 0x10 == 0x10);
} else {
let v: u16 = self.sp.wrapping_add(arg as u16);
self.set_pair_value(REG_N_H, REG_N_L, v);
self.set_clear_flag(FLAG_C, (sp ^ arg as u16 ^ v) & 0x100 == 0x100);
self.set_clear_flag(FLAG_H, (sp ^ arg as u16 ^ v) & 0x10 == 0x10);
}
self.clear_flag(FLAG_N);
self.clear_flag(FLAG_Z);
// TODO: FLAG_H FLAG_C
12
},
0xF9 => {
@ -1570,15 +1610,11 @@ impl CPU {
0xFE => {
let args = self.load_args(1);
let rval = self.regs[REG_A];
if self.debug {
println!("CP {:02X}", args[0]);
}
self.set_flag(FLAG_N);
self.set_clear_flag(FLAG_C, args[0] > rval);
self.set_clear_flag(FLAG_Z, args[0] == rval);
// TODO H
self.cp_r(args[0]);
8
},
0xFF => self.rst(0x38),