diff --git a/OSBindings/Mac/Clock SignalTests/68000Tests.mm b/OSBindings/Mac/Clock SignalTests/68000Tests.mm index 18ed9809e..eb6a72be7 100644 --- a/OSBindings/Mac/Clock SignalTests/68000Tests.mm +++ b/OSBindings/Mac/Clock SignalTests/68000Tests.mm @@ -889,6 +889,89 @@ class CPU::MC68000::ProcessorStorageTests { XCTAssertEqual(state.status & Flag::ConditionCodes, Flag::ConditionCodes); } +// MARL: ADDX + +- (void)testADDXl_Dn { + _machine->set_program({ + 0xd581 // ADDX.l D1, D2 + }); + auto state = _machine->get_processor_state(); + state.data[1] = 0x12345678; + state.data[2] = 0x12345678; + state.status |= Flag::ConditionCodes; + + _machine->set_processor_state(state); + _machine->run_for_instructions(1); + + state = _machine->get_processor_state(); + XCTAssertEqual(state.data[1], 0x12345678); + XCTAssertEqual(state.data[2], 0x2468acf1); + XCTAssertEqual(state.status & Flag::ConditionCodes, 0); + XCTAssertEqual(8, _machine->get_cycle_count()); +} + +- (void)testADDXb { + _machine->set_program({ + 0xd501 // ADDX.b D1, D2 + }); + auto state = _machine->get_processor_state(); + state.data[1] = 0x80; + state.data[2] = 0x8080; + + _machine->set_processor_state(state); + _machine->run_for_instructions(1); + + state = _machine->get_processor_state(); + XCTAssertEqual(state.data[1], 0x80); + XCTAssertEqual(state.data[2], 0x8000); + XCTAssertEqual(state.status & Flag::ConditionCodes, Flag::Carry | Flag::Overflow | Flag::Extend); + XCTAssertEqual(4, _machine->get_cycle_count()); +} + +- (void)testADDXw { + _machine->set_program({ + 0xd541 // ADDX.w D1, D2 + }); + auto state = _machine->get_processor_state(); + state.data[1] = 0x1ffff; + state.data[2] = 0x18080; + state.status |= Flag::ConditionCodes; + + _machine->set_processor_state(state); + _machine->run_for_instructions(1); + + state = _machine->get_processor_state(); + XCTAssertEqual(state.data[1], 0x1ffff); + XCTAssertEqual(state.data[2], 0x18080); + XCTAssertEqual(state.status & Flag::ConditionCodes, Flag::Carry | Flag::Negative | Flag::Extend); + XCTAssertEqual(4, _machine->get_cycle_count()); +} + +- (void)testADDXl_PreDec { + _machine->set_program({ + 0xd389 // ADDX.l -(A1), -(A1) + }); + auto state = _machine->get_processor_state(); + state.address[1] = 0x3000; + state.status |= Flag::ConditionCodes; + *_machine->ram_at(0x2ff8) = 0x1000; + *_machine->ram_at(0x2ffa) = 0x0000; + *_machine->ram_at(0x2ffc) = 0x7000; + *_machine->ram_at(0x2ffe) = 0x1ff1; + + _machine->set_processor_state(state); + _machine->run_for_instructions(1); + + state = _machine->get_processor_state(); + XCTAssertEqual(state.address[1], 0x2ff8); + XCTAssertEqual(state.status & Flag::ConditionCodes, Flag::Negative | Flag::Overflow); + XCTAssertEqual(*_machine->ram_at(0x2ff8), 0x8000); + XCTAssertEqual(*_machine->ram_at(0x2ffa), 0x1ff2); + XCTAssertEqual(*_machine->ram_at(0x2ffc), 0x7000); + XCTAssertEqual(*_machine->ram_at(0x2ffe), 0x1ff1); + XCTAssertEqual(30, _machine->get_cycle_count()); +} + // MARK: ASL - (void)testASLb_Dn_2 { diff --git a/Processors/68000/Implementation/68000Storage.cpp b/Processors/68000/Implementation/68000Storage.cpp index a5941f0b4..33b7c4328 100644 --- a/Processors/68000/Implementation/68000Storage.cpp +++ b/Processors/68000/Implementation/68000Storage.cpp @@ -1705,24 +1705,21 @@ struct ProcessorStorageConstructor { if(is_long_word_access) { // Access order is very atypical here: it's lower parts each for both words, // and then also a lower-part-first write. - op(int(Action::Decrement2) | MicroOp::SourceMask | MicroOp::DestinationMask); - op( int(Action::CopyToEffectiveAddress) | MicroOp::SourceMask | MicroOp::DestinationMask, - seq("n nr- nR nrd- nRd+", { ea(0), ea(0), ea(1), ea(1) })); - op(int(Action::Decrement2) | MicroOp::SourceMask | MicroOp::DestinationMask); + op(int(Action::Decrement2) | MicroOp::SourceMask); + op( int(Action::CopyToEffectiveAddress) | MicroOp::SourceMask, + seq("n nr- nR", { ea(0), ea(0) })); + op(int(Action::Decrement2) | MicroOp::DestinationMask | MicroOp::SourceMask); + op( int(Action::CopyToEffectiveAddress) | MicroOp::DestinationMask, + seq("nrd- nRd+", { ea(1), ea(1) })); op(Action::PerformOperation, seq("nw- np nW", { ea(1), ea(1) })); + op(int(Action::Decrement2) | MicroOp::DestinationMask); } else { - const int source_dec = dec(ea_register); - const int destination_dec = dec(data_register); - - int first_action; - if(source_dec == destination_dec) { - first_action = int(Action::Decrement4) | MicroOp::SourceMask | MicroOp::DestinationMask; - } else { - op(source_dec | MicroOp::SourceMask); - first_action = destination_dec | MicroOp::DestinationMask; - } - - op(first_action, seq("n nr nrd np", { ea(0), ea(1) }, !is_byte_access)); + op(dec(ea_register) | MicroOp::SourceMask); + op( int(Action::CopyToEffectiveAddress) | MicroOp::SourceMask, + seq("n nr", { ea(0) }, !is_byte_access)); + op(dec(data_register) | MicroOp::DestinationMask); + op( int(Action::CopyToEffectiveAddress) | MicroOp::DestinationMask, + seq("nrd np", { ea(1) }, !is_byte_access)); op(Action::PerformOperation, seq("nw", { ea(1) }, !is_byte_access)); } } else {