diff --git a/OSBindings/Mac/Clock SignalTests/68000Tests.mm b/OSBindings/Mac/Clock SignalTests/68000Tests.mm index 732987787..4e08429ac 100644 --- a/OSBindings/Mac/Clock SignalTests/68000Tests.mm +++ b/OSBindings/Mac/Clock SignalTests/68000Tests.mm @@ -84,4 +84,11 @@ class RAM68000: public CPU::MC68000::BusHandler { _machine->run_for(HalfCycles(400)); } +- (void)testSBCD { + _machine->set_program({ + 0x8100 // SBCD D0, D1 + }); + _machine->run_for(HalfCycles(400)); +} + @end diff --git a/Processors/68000/Implementation/68000Implementation.hpp b/Processors/68000/Implementation/68000Implementation.hpp index fa2bc0806..43b1a14f1 100644 --- a/Processors/68000/Implementation/68000Implementation.hpp +++ b/Processors/68000/Implementation/68000Implementation.hpp @@ -26,16 +26,37 @@ template void Processor: const uint8_t destination = active_program_->destination->halves.low.halves.low; // Perform the BCD add by evaluating the two nibbles separately. - int result = (source & 0xf) + (destination & 0xf) + (extend_flag_ ? 1 : 0); + int result = (destination & 0xf) + (source & 0xf) + (extend_flag_ ? 1 : 0); if(result > 0x9) result += 0x06; - result += (source & 0xf0) + (destination & 0xf0); + result += (destination & 0xf0) + (source & 0xf0); if(result > 0x90) result += 0x60; // Set all flags essentially as if this were normal addition. zero_flag_ |= result & 0xff; extend_flag_ = carry_flag_ = result & ~0xff; negative_flag_ = result & 0x80; - overflow_flag_ = ~(source ^ destination) & (source ^ result) & 0x80; + overflow_flag_ = ~(source ^ destination) & (destination ^ result) & 0x80; + + // Store the result. + active_program_->destination->halves.low.halves.low = uint8_t(result); + } break; + + case Operation::SBCD: { + // Pull out the two halves, for simplicity. + const uint8_t source = active_program_->source->halves.low.halves.low; + const uint8_t destination = active_program_->destination->halves.low.halves.low; + + // Perform the BCD add by evaluating the two nibbles separately. + int result = (destination & 0xf) - (source & 0xf) - (extend_flag_ ? 1 : 0); + if(result > 0x9) result -= 0x06; + result += (destination & 0xf0) - (source & 0xf0); + if(result > 0x90) result -= 0x60; + + // Set all flags essentially as if this were normal addition. + zero_flag_ |= result & 0xff; + extend_flag_ = carry_flag_ = result & ~0xff; + negative_flag_ = result & 0x80; + overflow_flag_ = (source ^ destination) & (destination ^ result) & 0x80; // Store the result. active_program_->destination->halves.low.halves.low = uint8_t(result); diff --git a/Processors/68000/Implementation/68000Storage.cpp b/Processors/68000/Implementation/68000Storage.cpp index 8bbbcc7ec..7efd2d536 100644 --- a/Processors/68000/Implementation/68000Storage.cpp +++ b/Processors/68000/Implementation/68000Storage.cpp @@ -232,26 +232,21 @@ void ProcessorStorage::install_instructions(const BusStepCollection &bus_step_co const int source = instruction & 7; if(instruction & 8) { - // Install source and destination. instructions[instruction].source = &bus_data_[0]; instructions[instruction].destination = &bus_data_[1]; - all_micro_ops_.emplace_back(); - all_micro_ops_.back().bus_program = &all_bus_steps_[bus_step_collection.double_predec_byte[source][destination]]; - all_micro_ops_.back().action = MicroOp::Action::PredecrementSourceAndDestination1; - all_micro_ops_.emplace_back(); - all_micro_ops_.back().action = MicroOp::Action::PerformOperation; + all_micro_ops_.emplace_back( + MicroOp::Action::PredecrementSourceAndDestination1, + &all_bus_steps_[bus_step_collection.double_predec_byte[source][destination]]); + all_micro_ops_.emplace_back(MicroOp::Action::PerformOperation); all_micro_ops_.emplace_back(); } else { - // Install source and destination. instructions[instruction].source = &data_[source]; instructions[instruction].destination = &data_[destination]; - // For micro-ops, just schedule the proper bus cycle to get the next thing into the prefetch queue, - // then perform the actual operation. - all_micro_ops_.emplace_back(); - all_micro_ops_.back().bus_program = &all_bus_steps_[bus_step_collection.six_step_Dn]; - all_micro_ops_.back().action = MicroOp::Action::PerformOperation; + all_micro_ops_.emplace_back( + MicroOp::Action::PerformOperation, + &all_bus_steps_[bus_step_collection.six_step_Dn]); all_micro_ops_.emplace_back(); } } break; diff --git a/Processors/68000/Implementation/68000Storage.hpp b/Processors/68000/Implementation/68000Storage.hpp index 4d4732e9d..b867f8e5e 100644 --- a/Processors/68000/Implementation/68000Storage.hpp +++ b/Processors/68000/Implementation/68000Storage.hpp @@ -84,6 +84,10 @@ class ProcessorStorage { PredecrementSourceAndDestination4, } action = Action::None; BusStep *bus_program = nullptr; + + MicroOp() {} + MicroOp(Action action) : action(action) {} + MicroOp(Action action, BusStep *bus_program) : action(action), bus_program(bus_program) {} }; /*!