diff --git a/src/cpus/m68k/decode.rs b/src/cpus/m68k/decode.rs index 13b9286..27f46d5 100644 --- a/src/cpus/m68k/decode.rs +++ b/src/cpus/m68k/decode.rs @@ -179,11 +179,9 @@ impl M68kDecoder { if (ins & 0x040) == 0 { let size = match get_size(ins) { Some(Size::Word) => Size::Word, - // TODO 2021-12-14: the docs for the 68000 show the size field, even though it says it only operates on words - // and according to some other sources, it seems they are parsed and executed on the 68000, so - // I'm removing the check that only allows this on the MC68020 - //Some(Size::Long) if self.cputype >= M68kType::MC68020 => Size::Long, - Some(Size::Long) => Size::Long, + Some(Size::Long) if self.cputype >= M68kType::MC68020 => Size::Long, + // On the 68000, long words in CHK are not supported, but the opcode maps to the word size instruction + Some(Size::Long) => Size::Word, _ => return Err(Error::processor(Exceptions::IllegalInstruction as u32)), }; diff --git a/src/cpus/m68k/execute.rs b/src/cpus/m68k/execute.rs index 00406d9..7f1fe87 100644 --- a/src/cpus/m68k/execute.rs +++ b/src/cpus/m68k/execute.rs @@ -381,8 +381,20 @@ impl M68k { }, //Instruction::BKPT(u8) => { //}, - //Instruction::CHK(Target, Size) => { - //}, + Instruction::CHK(target, reg, size) => { + let upper_bound = sign_extend_to_long(self.get_target_value(target, size, Used::Once)?, size) as i32; + let dreg = sign_extend_to_long(self.state.d_reg[reg as usize], size) as i32; + + self.set_sr(self.state.sr & 0xFFF0); + if dreg < 0 || dreg > upper_bound { + if dreg < 0 { + self.set_flag(Flags::Negative, true); + } else if dreg > upper_bound { + self.set_flag(Flags::Negative, false); + } + self.exception(Exceptions::ChkInstruction as u8, false)?; + } + }, Instruction::CLR(target, size) => { self.set_target_value(target, 0, size, Used::Once)?; // Clear flags except Zero flag @@ -652,8 +664,24 @@ impl M68k { self.set_compare_flags(result, size, carry, overflow); self.set_flag(Flags::Extend, carry); }, - //Instruction::NEGX(Target, Size) => { - //}, + Instruction::NEGX(dest, size) => { + let existing = self.get_target_value(dest, size, Used::Twice)?; + let extend = self.get_flag(Flags::Extend) as u32; + let (result1, carry1) = overflowing_sub_sized(0, existing, size); + let (result2, carry2) = overflowing_sub_sized(result1, extend, size); + let overflow = get_sub_overflow(0, existing, result2, size); + + // Handle flags + let zero = self.get_flag(Flags::Zero); + self.set_compare_flags(result2, size, carry1 || carry2, overflow); + if self.get_flag(Flags::Zero) { + // NEGX can only clear the zero flag, so if it's set, restore it to whatever it was before + self.set_flag(Flags::Zero, zero); + } + self.set_flag(Flags::Extend, carry1 || carry2); + + self.set_target_value(dest, result2, size, Used::Twice)?; + }, Instruction::NOP => { }, Instruction::NOT(target, size) => { let mut value = self.get_target_value(target, size, Used::Twice)?; diff --git a/tests/harte_tests/latest.txt b/tests/harte_tests/latest.txt index 789a15b..80aaf4f 100644 --- a/tests/harte_tests/latest.txt +++ b/tests/harte_tests/latest.txt @@ -1,4 +1,4 @@ -Last run on 2022-09-12 at commit 5a55aa7f63834a24aae1db195a0d3aa7d8943fb9 +Last run on 2022-09-12 at commit 9ff528c4638b7b5757d110ba87c10ab60aa33557 ABCD.json completed: 301 passed, 7764 FAILED ADD.b.json completed, all passed! @@ -26,7 +26,7 @@ BSET.json completed, all passed! BSR.json completed: 4085 passed, 3980 FAILED BTST.json completed: 8052 passed, 13 FAILED Bcc.json completed: 5865 passed, 2200 FAILED -CHK.json completed: 0 passed, 8065 FAILED +CHK.json completed: 7744 passed, 321 FAILED CLR.b.json completed, all passed! CLR.l.json completed: 6882 passed, 1183 FAILED CLR.w.json completed: 6862 passed, 1203 FAILED @@ -77,9 +77,9 @@ NBCD.json completed: 0 passed, 8065 FAILED NEG.b.json completed, all passed! NEG.l.json completed: 7552 passed, 513 FAILED NEG.w.json completed: 7531 passed, 534 FAILED -NEGX.b.json completed: 0 passed, 8065 FAILED -NEGX.l.json completed: 0 passed, 8065 FAILED -NEGX.w.json completed: 0 passed, 8065 FAILED +NEGX.b.json completed, all passed! +NEGX.l.json completed: 7520 passed, 545 FAILED +NEGX.w.json completed: 7510 passed, 555 FAILED NOP.json completed, all passed! NOT.b.json completed, all passed! NOT.l.json completed: 7512 passed, 553 FAILED @@ -125,5 +125,5 @@ TST.l.json completed, all passed! TST.w.json completed, all passed! UNLINK.json completed, all passed! -passed: 860483, failed: 139577, total 86% -completed in 16m 38s +passed: 891322, failed: 108738, total 89% +completed in 13m 52s diff --git a/tests/harte_tests/previous.txt b/tests/harte_tests/previous.txt index ba7e410..789a15b 100644 --- a/tests/harte_tests/previous.txt +++ b/tests/harte_tests/previous.txt @@ -1,4 +1,4 @@ -Last run on 2022-09-11 at commit 42bfabb7434fdff65a1ccacced82ddc6597ed835 +Last run on 2022-09-12 at commit 5a55aa7f63834a24aae1db195a0d3aa7d8943fb9 ABCD.json completed: 301 passed, 7764 FAILED ADD.b.json completed, all passed!