mirror of
https://github.com/TomHarte/CLK.git
synced 2024-12-24 12:30:17 +00:00
Imports SBCD and NBCD tests, and fixes corresponding operation.
This commit is contained in:
parent
c5039a4719
commit
241d29ff7c
@ -105,7 +105,7 @@ class RAM68000: public CPU::MC68000::BusHandler {
|
||||
case Microcycle::SelectByte:
|
||||
ram_[word_address % ram_.size()] = uint16_t(
|
||||
(cycle.value->halves.low << cycle.byte_shift()) |
|
||||
(ram_[word_address] & cycle.untouched_byte_mask())
|
||||
(ram_[word_address % ram_.size()] & cycle.untouched_byte_mask())
|
||||
);
|
||||
break;
|
||||
}
|
||||
@ -4103,6 +4103,68 @@ class CPU::MC68000::ProcessorStorageTests {
|
||||
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 {
|
||||
@ -5038,6 +5100,78 @@ class CPU::MC68000::ProcessorStorageTests {
|
||||
XCTAssertEqual(state.status & Flag::ConditionCodes, Flag::ConditionCodes);
|
||||
}
|
||||
|
||||
// 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 {
|
||||
|
@ -376,7 +376,9 @@ template <class T, bool dtack_is_implicit, bool signal_will_perform> void Proces
|
||||
zero_result_ |= result & 0xff;
|
||||
extend_flag_ = carry_flag_ = uint_fast32_t(result & ~0xff);
|
||||
negative_flag_ = result & 0x80;
|
||||
overflow_flag_ = add_overflow() & 0x80;
|
||||
|
||||
const int unadjusted_result = destination + source + (extend_flag_ ? 1 : 0);
|
||||
overflow_flag_ = ~unadjusted_result & result & 0x80;
|
||||
|
||||
// Store the result.
|
||||
active_program_->destination->halves.low.halves.low = uint8_t(result);
|
||||
@ -1507,16 +1509,17 @@ template <class T, bool dtack_is_implicit, bool signal_will_perform> void Proces
|
||||
#define sbcd() \
|
||||
/* Perform the BCD arithmetic by evaluating the two nibbles separately. */ \
|
||||
int result = (destination & 0xf) - (source & 0xf) - (extend_flag_ ? 1 : 0); \
|
||||
if(result > 0x09) result -= 0x06; \
|
||||
if((result & 0x1f) > 0x09) result -= 0x06; \
|
||||
result += (destination & 0xf0) - (source & 0xf0); \
|
||||
if(result > 0x99) result -= 0x60; \
|
||||
\
|
||||
if((result & 0x1ff) > 0x99) result -= 0x60; \
|
||||
\
|
||||
/* Set all flags essentially as if this were normal subtraction. */ \
|
||||
zero_result_ |= result & 0xff; \
|
||||
extend_flag_ = carry_flag_ = decltype(carry_flag_)(result & ~0xff); \
|
||||
negative_flag_ = result & 0x80; \
|
||||
overflow_flag_ = sub_overflow() & 0x80; \
|
||||
\
|
||||
const int unadjusted_result = destination - source - (extend_flag_ ? 1 : 0); \
|
||||
overflow_flag_ = unadjusted_result &~ result & 0x80; \
|
||||
\
|
||||
/* Store the result. */ \
|
||||
active_program_->destination->halves.low.halves.low = uint8_t(result);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user