1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-06-25 18:30:07 +00:00

Factors BCD out of general arithmetic.

This commit is contained in:
Thomas Harte 2019-06-29 13:31:24 -04:00
parent 6e9a4a48f7
commit ac926f5070
3 changed files with 295 additions and 262 deletions

View File

@ -308,6 +308,7 @@
4B98A1CE1FFADEC500ADF63B /* MSX ROMs in Resources */ = {isa = PBXBuildFile; fileRef = 4B98A1CD1FFADEC400ADF63B /* MSX ROMs */; };
4B9BE400203A0C0600FFAE60 /* MultiSpeaker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B9BE3FE203A0C0600FFAE60 /* MultiSpeaker.cpp */; };
4B9BE401203A0C0600FFAE60 /* MultiSpeaker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B9BE3FE203A0C0600FFAE60 /* MultiSpeaker.cpp */; };
4B9D0C4B22C7D70A00DE1AD3 /* 68000BCDTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4B9D0C4A22C7D70900DE1AD3 /* 68000BCDTests.mm */; };
4B9F11C92272375400701480 /* qltrace.txt.gz in Resources */ = {isa = PBXBuildFile; fileRef = 4B9F11C82272375400701480 /* qltrace.txt.gz */; };
4B9F11CA2272433900701480 /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 4B69FB451C4D950F00B5F0AA /* libz.tbd */; };
4B9F11CC22729B3600701480 /* OPCLOGR2.BIN in Resources */ = {isa = PBXBuildFile; fileRef = 4B9F11CB22729B3500701480 /* OPCLOGR2.BIN */; };
@ -1067,6 +1068,7 @@
4B98A1CD1FFADEC400ADF63B /* MSX ROMs */ = {isa = PBXFileReference; lastKnownFileType = folder; path = "MSX ROMs"; sourceTree = "<group>"; };
4B9BE3FE203A0C0600FFAE60 /* MultiSpeaker.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = MultiSpeaker.cpp; sourceTree = "<group>"; };
4B9BE3FF203A0C0600FFAE60 /* MultiSpeaker.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = MultiSpeaker.hpp; sourceTree = "<group>"; };
4B9D0C4A22C7D70900DE1AD3 /* 68000BCDTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = 68000BCDTests.mm; sourceTree = "<group>"; };
4B9F11C82272375400701480 /* qltrace.txt.gz */ = {isa = PBXFileReference; lastKnownFileType = archive.gzip; path = qltrace.txt.gz; sourceTree = "<group>"; };
4B9F11CB22729B3500701480 /* OPCLOGR2.BIN */ = {isa = PBXFileReference; lastKnownFileType = archive.macbinary; name = OPCLOGR2.BIN; path = "68000 Coverage/OPCLOGR2.BIN"; sourceTree = "<group>"; };
4BA0F68C1EEA0E8400E9489E /* ZX8081.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ZX8081.cpp; path = Data/ZX8081.cpp; sourceTree = "<group>"; };
@ -2929,6 +2931,7 @@
4B85322922778E4200F26553 /* Comparative68000.hpp */,
4B90467222C6FA31000E2074 /* TestRunner68000.hpp */,
4B97ADC722C6FD9B00A22A41 /* 68000ArithmeticTests.mm */,
4B9D0C4A22C7D70900DE1AD3 /* 68000BCDTests.mm */,
4B90467322C6FADD000E2074 /* 68000BitwiseTests.mm */,
4BD388872239E198002D14B5 /* 68000Tests.mm */,
4B924E981E74D22700B76AF1 /* AtariStaticAnalyserTests.mm */,
@ -4207,6 +4210,7 @@
4BFCA12B1ECBE7C400AC40C1 /* ZexallTests.swift in Sources */,
4BB2A9AF1E13367E001A5C23 /* CRCTests.mm in Sources */,
4B3BA0D01D318B44005DD7A7 /* MOS6532Bridge.mm in Sources */,
4B9D0C4B22C7D70A00DE1AD3 /* 68000BCDTests.mm in Sources */,
4B3BA0C31D318AEC005DD7A7 /* C1540Tests.swift in Sources */,
4B1414621B58888700E04248 /* KlausDormannTests.swift in Sources */,
4B1414601B58885000E04248 /* WolfgangLorenzTests.swift in Sources */,

View File

@ -26,134 +26,6 @@
_machine.reset();
}
// MARK: ABCD
- (void)testABCD {
_machine->set_program({
0xc302, // ABCD D2, D1
});
auto state = _machine->get_processor_state();
state.data[1] = 0x1234567a;
state.data[2] = 0xf745ff78;
_machine->set_processor_state(state);
_machine->run_for_instructions(1);
state = _machine->get_processor_state();
XCTAssert(state.status & Flag::Carry);
XCTAssertEqual(state.data[1], 0x12345658);
XCTAssertEqual(state.data[2], 0xf745ff78);
}
- (void)testABCDZero {
_machine->set_program({
0xc302, // ABCD D2, D1
});
auto state = _machine->get_processor_state();
state.data[1] = 0x12345600;
state.data[2] = 0x12345600;
state.status = Flag::Zero;
_machine->set_processor_state(state);
_machine->run_for_instructions(1);
state = _machine->get_processor_state();
XCTAssert(state.status & Flag::Zero);
XCTAssertEqual(state.data[1], 0x12345600);
XCTAssertEqual(state.data[2], 0x12345600);
}
- (void)testABCDNegative {
_machine->set_program({
0xc302, // ABCD D2, D1
});
auto state = _machine->get_processor_state();
state.data[1] = 0x12345645;
state.data[2] = 0x12345654;
state.status = Flag::Zero;
_machine->set_processor_state(state);
_machine->run_for_instructions(1);
state = _machine->get_processor_state();
XCTAssert(state.status & Flag::Negative);
XCTAssertEqual(state.data[1], 0x12345699);
XCTAssertEqual(state.data[2], 0x12345654);
}
- (void)testABCDWithX {
_machine->set_program({
0xc302, // ABCD D2, D1
});
auto state = _machine->get_processor_state();
state.data[1] = 0x12345645;
state.data[2] = 0x12345654;
state.status = Flag::Extend;
_machine->set_processor_state(state);
_machine->run_for_instructions(1);
state = _machine->get_processor_state();
XCTAssert(state.status & Flag::Carry);
XCTAssertEqual(state.data[1], 0x12345600);
XCTAssertEqual(state.data[2], 0x12345654);
}
- (void)testABCDOverflow {
_machine->set_program({
0xc302, // ABCD D2, D1
});
auto state = _machine->get_processor_state();
state.data[1] = 0x1234563e;
state.data[2] = 0x1234563e;
state.status = Flag::Extend;
_machine->set_processor_state(state);
_machine->run_for_instructions(1);
state = _machine->get_processor_state();
XCTAssert(state.status & Flag::Overflow);
XCTAssertEqual(state.data[1], 0x12345683);
XCTAssertEqual(state.data[2], 0x1234563e);
}
- (void)testABCDPredecDifferent {
_machine->set_program({
0xc30a, // ABCD -(A2), -(A1)
});
*_machine->ram_at(0x3000) = 0xa200;
*_machine->ram_at(0x4000) = 0x1900;
auto state = _machine->get_processor_state();
state.address[1] = 0x3001;
state.address[2] = 0x4001;
state.status = Flag::Extend;
_machine->set_processor_state(state);
_machine->run_for_instructions(1);
state = _machine->get_processor_state();
XCTAssert(state.status & Flag::Carry);
XCTAssert(state.status & Flag::Extend);
XCTAssertEqual(state.address[1], 0x3000);
XCTAssertEqual(state.address[2], 0x4000);
XCTAssertEqual(*_machine->ram_at(0x3000), 0x2200);
XCTAssertEqual(*_machine->ram_at(0x4000), 0x1900);
}
- (void)testABCDPredecSame {
_machine->set_program({
0xc309, // ABCD -(A1), -(A1)
});
*_machine->ram_at(0x3000) = 0x19a2;
auto state = _machine->get_processor_state();
state.address[1] = 0x3002;
state.status = Flag::Extend;
_machine->set_processor_state(state);
_machine->run_for_instructions(1);
state = _machine->get_processor_state();
XCTAssert(state.status & Flag::Carry);
XCTAssert(state.status & Flag::Extend);
XCTAssertEqual(state.address[1], 0x3000);
XCTAssertEqual(*_machine->ram_at(0x3000), 0x22a2);
}
// MARK: ADD
- (void)testADDb {
@ -1082,68 +954,6 @@
XCTAssertEqual(74, _machine->get_cycle_count());
}
// MARK: NBCD
- (void)performNBCDd1:(uint32_t)d1 ccr:(uint8_t)ccr {
_machine->set_program({
0x4801 // NBCD D1
});
auto state = _machine->get_processor_state();
state.status |= ccr;
state.data[1] = d1;
_machine->set_processor_state(state);
_machine->run_for_instructions(1);
XCTAssertEqual(6, _machine->get_cycle_count());
}
- (void)testNBCD_Dn {
[self performNBCDd1:0x7a ccr:0];
const auto state = _machine->get_processor_state();
XCTAssertEqual(state.data[1], 0x20);
XCTAssertEqual(state.status & Flag::ConditionCodes, Flag::Extend | Flag::Carry | Flag::Overflow);
}
- (void)testNBCD_Dn_extend {
[self performNBCDd1:0x1234567a ccr:Flag::Extend | Flag::Zero];
const auto state = _machine->get_processor_state();
XCTAssertEqual(state.data[1], 0x1234561f);
XCTAssertEqual(state.status & Flag::ConditionCodes, Flag::Extend | Flag::Carry | Flag::Overflow);
}
- (void)testNBCD_Dn_zero {
[self performNBCDd1:0x12345600 ccr:Flag::Zero];
const auto state = _machine->get_processor_state();
XCTAssertEqual(state.data[1], 0x12345600);
XCTAssertEqual(state.status & Flag::ConditionCodes, Flag::Zero);
}
- (void)testNBCD_Dn_negative {
[self performNBCDd1:0x123456ff ccr:Flag::Extend | Flag::Zero];
const auto state = _machine->get_processor_state();
XCTAssertEqual(state.data[1], 0x1234569a);
XCTAssertEqual(state.status & Flag::ConditionCodes, Flag::Extend | Flag::Carry | Flag::Negative);
}
- (void)testNBCD_Dn_XXXw {
_machine->set_program({
0x4838, 0x3000 // NBCD ($3000).w
});
*_machine->ram_at(0x3000) = 0x0100;
_machine->run_for_instructions(1);
const auto state = _machine->get_processor_state();
XCTAssertEqual(16, _machine->get_cycle_count());
XCTAssertEqual(*_machine->ram_at(0x3000), 0x9900);
XCTAssertEqual(state.status & Flag::ConditionCodes, Flag::Extend | Flag::Carry | Flag::Negative);
}
// MARK: NEG
- (void)performNEGb:(uint32_t)value {
@ -1350,78 +1160,6 @@
XCTAssertEqual(state.status & Flag::ConditionCodes, Flag::Extend | Flag::Carry);
}
// MARK: SBCD
- (void)performSBCDd1:(uint32_t)d1 d2:(uint32_t)d2 ccr:(uint8_t)ccr {
_machine->set_program({
0x8302 // SBCD D2, D1
});
auto state = _machine->get_processor_state();
state.status |= ccr;
state.data[1] = d1;
state.data[2] = d2;
_machine->set_processor_state(state);
_machine->run_for_instructions(1);
state = _machine->get_processor_state();
XCTAssertEqual(6, _machine->get_cycle_count());
XCTAssertEqual(state.data[2], d2);
}
- (void)testSBCD_Dn {
[self performSBCDd1:0x12345689 d2:0xf745ff78 ccr:Flag::Zero];
const auto state = _machine->get_processor_state();
XCTAssertEqual(state.data[1], 0x12345611);
XCTAssertEqual(state.status & Flag::ConditionCodes, 0);
}
- (void)testSBCD_Dn_zero {
[self performSBCDd1:0x123456ff d2:0xf745ffff ccr:Flag::Zero];
const auto state = _machine->get_processor_state();
XCTAssertEqual(state.data[1], 0x12345600);
XCTAssertEqual(state.status & Flag::ConditionCodes, Flag::Zero);
}
- (void)testSBCD_Dn_negative {
[self performSBCDd1:0x12345634 d2:0xf745ff45 ccr:Flag::Extend];
const auto state = _machine->get_processor_state();
XCTAssertEqual(state.data[1], 0x12345688);
XCTAssertEqual(state.status & Flag::ConditionCodes, Flag::Extend | Flag::Carry | Flag::Negative);
}
- (void)testSBCD_Dn_overflow {
[self performSBCDd1:0x123456a9 d2:0xf745ffff ccr:Flag::Extend];
const auto state = _machine->get_processor_state();
XCTAssertEqual(state.data[1], 0x12345643);
XCTAssertEqual(state.status & Flag::ConditionCodes, Flag::Extend | Flag::Carry | Flag::Overflow);
}
- (void)testSBCD_Dn_PreDec {
_machine->set_program({
0x830a // SBCD -(A2), -(A1)
});
*_machine->ram_at(0x3000) = 0xa200;
*_machine->ram_at(0x4000) = 0x1900;
auto state = _machine->get_processor_state();
state.address[1] = 0x3001;
state.address[2] = 0x4001;
state.status |= Flag::Extend;
_machine->set_processor_state(state);
_machine->run_for_instructions(1);
state = _machine->get_processor_state();
XCTAssertEqual(18, _machine->get_cycle_count());
XCTAssertEqual(*_machine->ram_at(0x3000), 0x8200);
XCTAssertEqual(*_machine->ram_at(0x4000), 0x1900);
XCTAssertEqual(state.status & Flag::ConditionCodes, Flag::Negative);
}
// MARK: SUB
- (void)performSUBbIMM:(uint16_t)value d2:(uint32_t)d2 {

View File

@ -0,0 +1,291 @@
//
// 68000BCDTests.m
// Clock SignalTests
//
// Created by Thomas Harte on 29/06/2019.
//
// Largely ported from the tests of the Portable 68k Emulator.
//
#import <XCTest/XCTest.h>
#include "TestRunner68000.hpp"
@interface M68000BCDTests : XCTestCase
@end
@implementation M68000BCDTests {
std::unique_ptr<RAM68000> _machine;
}
- (void)setUp {
_machine.reset(new RAM68000());
}
- (void)tearDown {
_machine.reset();
}
// MARK: ABCD
- (void)testABCD {
_machine->set_program({
0xc302, // ABCD D2, D1
});
auto state = _machine->get_processor_state();
state.data[1] = 0x1234567a;
state.data[2] = 0xf745ff78;
_machine->set_processor_state(state);
_machine->run_for_instructions(1);
state = _machine->get_processor_state();
XCTAssert(state.status & Flag::Carry);
XCTAssertEqual(state.data[1], 0x12345658);
XCTAssertEqual(state.data[2], 0xf745ff78);
}
- (void)testABCDZero {
_machine->set_program({
0xc302, // ABCD D2, D1
});
auto state = _machine->get_processor_state();
state.data[1] = 0x12345600;
state.data[2] = 0x12345600;
state.status = Flag::Zero;
_machine->set_processor_state(state);
_machine->run_for_instructions(1);
state = _machine->get_processor_state();
XCTAssert(state.status & Flag::Zero);
XCTAssertEqual(state.data[1], 0x12345600);
XCTAssertEqual(state.data[2], 0x12345600);
}
- (void)testABCDNegative {
_machine->set_program({
0xc302, // ABCD D2, D1
});
auto state = _machine->get_processor_state();
state.data[1] = 0x12345645;
state.data[2] = 0x12345654;
state.status = Flag::Zero;
_machine->set_processor_state(state);
_machine->run_for_instructions(1);
state = _machine->get_processor_state();
XCTAssert(state.status & Flag::Negative);
XCTAssertEqual(state.data[1], 0x12345699);
XCTAssertEqual(state.data[2], 0x12345654);
}
- (void)testABCDWithX {
_machine->set_program({
0xc302, // ABCD D2, D1
});
auto state = _machine->get_processor_state();
state.data[1] = 0x12345645;
state.data[2] = 0x12345654;
state.status = Flag::Extend;
_machine->set_processor_state(state);
_machine->run_for_instructions(1);
state = _machine->get_processor_state();
XCTAssert(state.status & Flag::Carry);
XCTAssertEqual(state.data[1], 0x12345600);
XCTAssertEqual(state.data[2], 0x12345654);
}
- (void)testABCDOverflow {
_machine->set_program({
0xc302, // ABCD D2, D1
});
auto state = _machine->get_processor_state();
state.data[1] = 0x1234563e;
state.data[2] = 0x1234563e;
state.status = Flag::Extend;
_machine->set_processor_state(state);
_machine->run_for_instructions(1);
state = _machine->get_processor_state();
XCTAssert(state.status & Flag::Overflow);
XCTAssertEqual(state.data[1], 0x12345683);
XCTAssertEqual(state.data[2], 0x1234563e);
}
- (void)testABCDPredecDifferent {
_machine->set_program({
0xc30a, // ABCD -(A2), -(A1)
});
*_machine->ram_at(0x3000) = 0xa200;
*_machine->ram_at(0x4000) = 0x1900;
auto state = _machine->get_processor_state();
state.address[1] = 0x3001;
state.address[2] = 0x4001;
state.status = Flag::Extend;
_machine->set_processor_state(state);
_machine->run_for_instructions(1);
state = _machine->get_processor_state();
XCTAssert(state.status & Flag::Carry);
XCTAssert(state.status & Flag::Extend);
XCTAssertEqual(state.address[1], 0x3000);
XCTAssertEqual(state.address[2], 0x4000);
XCTAssertEqual(*_machine->ram_at(0x3000), 0x2200);
XCTAssertEqual(*_machine->ram_at(0x4000), 0x1900);
}
- (void)testABCDPredecSame {
_machine->set_program({
0xc309, // ABCD -(A1), -(A1)
});
*_machine->ram_at(0x3000) = 0x19a2;
auto state = _machine->get_processor_state();
state.address[1] = 0x3002;
state.status = Flag::Extend;
_machine->set_processor_state(state);
_machine->run_for_instructions(1);
state = _machine->get_processor_state();
XCTAssert(state.status & Flag::Carry);
XCTAssert(state.status & Flag::Extend);
XCTAssertEqual(state.address[1], 0x3000);
XCTAssertEqual(*_machine->ram_at(0x3000), 0x22a2);
}
// MARK: NBCD
- (void)performNBCDd1:(uint32_t)d1 ccr:(uint8_t)ccr {
_machine->set_program({
0x4801 // NBCD D1
});
auto state = _machine->get_processor_state();
state.status |= ccr;
state.data[1] = d1;
_machine->set_processor_state(state);
_machine->run_for_instructions(1);
XCTAssertEqual(6, _machine->get_cycle_count());
}
- (void)testNBCD_Dn {
[self performNBCDd1:0x7a ccr:0];
const auto state = _machine->get_processor_state();
XCTAssertEqual(state.data[1], 0x20);
XCTAssertEqual(state.status & Flag::ConditionCodes, Flag::Extend | Flag::Carry | Flag::Overflow);
}
- (void)testNBCD_Dn_extend {
[self performNBCDd1:0x1234567a ccr:Flag::Extend | Flag::Zero];
const auto state = _machine->get_processor_state();
XCTAssertEqual(state.data[1], 0x1234561f);
XCTAssertEqual(state.status & Flag::ConditionCodes, Flag::Extend | Flag::Carry | Flag::Overflow);
}
- (void)testNBCD_Dn_zero {
[self performNBCDd1:0x12345600 ccr:Flag::Zero];
const auto state = _machine->get_processor_state();
XCTAssertEqual(state.data[1], 0x12345600);
XCTAssertEqual(state.status & Flag::ConditionCodes, Flag::Zero);
}
- (void)testNBCD_Dn_negative {
[self performNBCDd1:0x123456ff ccr:Flag::Extend | Flag::Zero];
const auto state = _machine->get_processor_state();
XCTAssertEqual(state.data[1], 0x1234569a);
XCTAssertEqual(state.status & Flag::ConditionCodes, Flag::Extend | Flag::Carry | Flag::Negative);
}
- (void)testNBCD_Dn_XXXw {
_machine->set_program({
0x4838, 0x3000 // NBCD ($3000).w
});
*_machine->ram_at(0x3000) = 0x0100;
_machine->run_for_instructions(1);
const auto state = _machine->get_processor_state();
XCTAssertEqual(16, _machine->get_cycle_count());
XCTAssertEqual(*_machine->ram_at(0x3000), 0x9900);
XCTAssertEqual(state.status & Flag::ConditionCodes, Flag::Extend | Flag::Carry | Flag::Negative);
}
// MARK: SBCD
- (void)performSBCDd1:(uint32_t)d1 d2:(uint32_t)d2 ccr:(uint8_t)ccr {
_machine->set_program({
0x8302 // SBCD D2, D1
});
auto state = _machine->get_processor_state();
state.status |= ccr;
state.data[1] = d1;
state.data[2] = d2;
_machine->set_processor_state(state);
_machine->run_for_instructions(1);
state = _machine->get_processor_state();
XCTAssertEqual(6, _machine->get_cycle_count());
XCTAssertEqual(state.data[2], d2);
}
- (void)testSBCD_Dn {
[self performSBCDd1:0x12345689 d2:0xf745ff78 ccr:Flag::Zero];
const auto state = _machine->get_processor_state();
XCTAssertEqual(state.data[1], 0x12345611);
XCTAssertEqual(state.status & Flag::ConditionCodes, 0);
}
- (void)testSBCD_Dn_zero {
[self performSBCDd1:0x123456ff d2:0xf745ffff ccr:Flag::Zero];
const auto state = _machine->get_processor_state();
XCTAssertEqual(state.data[1], 0x12345600);
XCTAssertEqual(state.status & Flag::ConditionCodes, Flag::Zero);
}
- (void)testSBCD_Dn_negative {
[self performSBCDd1:0x12345634 d2:0xf745ff45 ccr:Flag::Extend];
const auto state = _machine->get_processor_state();
XCTAssertEqual(state.data[1], 0x12345688);
XCTAssertEqual(state.status & Flag::ConditionCodes, Flag::Extend | Flag::Carry | Flag::Negative);
}
- (void)testSBCD_Dn_overflow {
[self performSBCDd1:0x123456a9 d2:0xf745ffff ccr:Flag::Extend];
const auto state = _machine->get_processor_state();
XCTAssertEqual(state.data[1], 0x12345643);
XCTAssertEqual(state.status & Flag::ConditionCodes, Flag::Extend | Flag::Carry | Flag::Overflow);
}
- (void)testSBCD_Dn_PreDec {
_machine->set_program({
0x830a // SBCD -(A2), -(A1)
});
*_machine->ram_at(0x3000) = 0xa200;
*_machine->ram_at(0x4000) = 0x1900;
auto state = _machine->get_processor_state();
state.address[1] = 0x3001;
state.address[2] = 0x4001;
state.status |= Flag::Extend;
_machine->set_processor_state(state);
_machine->run_for_instructions(1);
state = _machine->get_processor_state();
XCTAssertEqual(18, _machine->get_cycle_count());
XCTAssertEqual(*_machine->ram_at(0x3000), 0x8200);
XCTAssertEqual(*_machine->ram_at(0x4000), 0x1900);
XCTAssertEqual(state.status & Flag::ConditionCodes, Flag::Negative);
}
@end