diff --git a/Processors/68000/Implementation/68000Implementation.hpp b/Processors/68000/Implementation/68000Implementation.hpp index d4d8b63ac..ca736e34a 100644 --- a/Processors/68000/Implementation/68000Implementation.hpp +++ b/Processors/68000/Implementation/68000Implementation.hpp @@ -53,16 +53,16 @@ template void Processor: // TODO: unless an interrupt is pending, or the trap flag is set. - const uint16_t next_instruction = prefetch_queue_.halves.high.full; - if(!instructions[next_instruction].micro_operations) { + decoded_instruction_ = prefetch_queue_.halves.high.full; + if(!instructions[decoded_instruction_].micro_operations) { // TODO: once all instructions are implemnted, this should be an instruction error. - std::cerr << "68000 Abilities exhausted; can't manage instruction " << std::hex << next_instruction << " from " << (program_counter_.full - 4) << std::endl; + std::cerr << "68000 Abilities exhausted; can't manage instruction " << std::hex << decoded_instruction_ << " from " << (program_counter_.full - 4) << std::endl; return; } else { - std::cout << "Performing " << std::hex << next_instruction << " from " << (program_counter_.full - 4) << std::endl; + std::cout << "Performing " << std::hex << decoded_instruction_ << " from " << (program_counter_.full - 4) << std::endl; } - active_program_ = &instructions[next_instruction]; + active_program_ = &instructions[decoded_instruction_]; active_micro_op_ = active_program_->micro_operations; } @@ -523,28 +523,51 @@ template void Processor: overflow_flag_ = (value ^ zero_result_) & m; \ extend_flag_ = carry_flag_ = value & t; +#define decode_shift_count() \ + const int shift_count = (decoded_instruction_ & 32) ? data_[(decoded_instruction_ >> 9) & 7].full&63 : (decoded_instruction_ >> 9) & 7; \ + active_step_->microcycle.length = HalfCycles(4 * shift_count); + #define set_flags_b(t) set_flags(active_program_->destination->halves.low.halves.low, 0x80, t) #define set_flags_w(t) set_flags(active_program_->destination->halves.low.full, 0x8000, t) #define set_flags_l(t) set_flags(active_program_->destination->full, 0x80000000, t) - case Operation::LSLm: - case Operation::ASLm: { - const auto value = active_program_->destination->halves.low.full; - active_program_->destination->halves.low.full <<= 1; - set_flags_w(0x8000); - } break; +#define shift_op(name, op, mb, mw, ml) \ + case Operation::name##b: { \ + decode_shift_count(); \ + const auto value = active_program_->destination->halves.low.halves.low; \ + op(active_program_->destination->halves.low.halves.low, shift_count, 0xff, 7); \ + set_flags_b(mb); \ + } break; \ +\ + case Operation::name##w: { \ + decode_shift_count(); \ + const auto value = active_program_->destination->halves.low.full; \ + op(active_program_->destination->halves.low.full, shift_count, 0xffff, 15); \ + set_flags_w(mw); \ + } break; \ +\ + case Operation::name##l: { \ + decode_shift_count(); \ + const auto value = active_program_->destination->full; \ + op(active_program_->destination->full, shift_count, 0xffffffff, 31); \ + set_flags_l(ml); \ + } break; \ +\ + case Operation::name##m: { \ + const auto value = active_program_->destination->halves.low.full; \ + op(active_program_->destination->halves.low.full, 1, 0xffff, 15); \ + set_flags_w(mw); \ + } break; - case Operation::LSRm: { - const auto value = active_program_->destination->halves.low.full; - active_program_->destination->halves.low.full >>= 1; - set_flags_w(0x0001); - } break; +#define lsl(x, c, m, d) x <<= c +#define lsr(x, c, m, d) x >>= c +#define asl(x, c, m, d) x <<= c +#define asr(x, c, m, d) x = (x >> c) | (((value >> d) & 1) * (m ^ (m >> c))) - case Operation::ASRm: { - const auto value = active_program_->destination->halves.low.full; - active_program_->destination->halves.low.full = (active_program_->destination->halves.low.full >> 1) | (value & 0x8000); - set_flags_w(0x0001); - } break; + shift_op(LSL, lsl, 0x80, 0x8000, 0x80000000); + shift_op(ASL, lsl, 0x80, 0x8000, 0x80000000); + shift_op(LSR, lsr, 0x01, 0x0001, 0x00000001); + shift_op(ASR, asr, 0x01, 0x0001, 0x00000001); #undef set_flags #define set_flags(v, m, t) \ @@ -580,6 +603,7 @@ template void Processor: } break; #undef set_flags +#undef decode_shift_count #undef set_flags_b #undef set_flags_w #undef set_flags_l diff --git a/Processors/68000/Implementation/68000Storage.cpp b/Processors/68000/Implementation/68000Storage.cpp index ccae034c0..500e9abf7 100644 --- a/Processors/68000/Implementation/68000Storage.cpp +++ b/Processors/68000/Implementation/68000Storage.cpp @@ -59,6 +59,9 @@ struct ProcessorStorageConstructor { * n: no operation for four cycles; data bus is not used; * nn: no operation for eight cycles; data bus is not used; + * r: a 'replaceable'-length no operation; data bus is not used and no guarantees are + made about the length of the cycle other than that when it reaches the interpreter, + it is safe to alter the length and leave it altered; * np: program fetch; reads from the PC and adds two to it, advancing the prefetch queue; * nW: write MSW of something onto the bus; * nw: write LSW of something onto the bus; @@ -121,10 +124,17 @@ struct ProcessorStorageConstructor { // Do nothing (possibly twice). if(token == "n" || token == "nn") { - steps.push_back(step); if(token.size() == 2) { - steps.push_back(step); + step.microcycle.length = HalfCycles(8); } + steps.push_back(step); + continue; + } + + // Do nothing, but with a length that definitely won't map it to the other do-nothings. + if(token == "r"){ + step.microcycle.length = HalfCycles(0); + steps.push_back(step); continue; } @@ -384,45 +394,45 @@ struct ProcessorStorageConstructor { {0xffc0, 0x4640, Operation::NOTw, Decoder::CLRNEGNEGXNOT}, // 4-148 (p250) {0xffc0, 0x4680, Operation::NOTl, Decoder::CLRNEGNEGXNOT}, // 4-148 (p250) - {0xf1d8, 0xe000, Operation::ASLb, Decoder::ASLRLSLRROLRROXLRr}, // 4-22 (p126) - {0xf1d8, 0xe040, Operation::ASLw, Decoder::ASLRLSLRROLRROXLRr}, // 4-22 (p126) - {0xf1d8, 0xe080, Operation::ASLl, Decoder::ASLRLSLRROLRROXLRr}, // 4-22 (p126) - {0xffc0, 0xe0c0, Operation::ASLm, Decoder::ASLRLSLRROLRROXLRm}, // 4-22 (p126) + {0xf1d8, 0xe100, Operation::ASLb, Decoder::ASLRLSLRROLRROXLRr}, // 4-22 (p126) + {0xf1d8, 0xe140, Operation::ASLw, Decoder::ASLRLSLRROLRROXLRr}, // 4-22 (p126) + {0xf1d8, 0xe180, Operation::ASLl, Decoder::ASLRLSLRROLRROXLRr}, // 4-22 (p126) + {0xffc0, 0xe1c0, Operation::ASLm, Decoder::ASLRLSLRROLRROXLRm}, // 4-22 (p126) - {0xf1d8, 0xe100, Operation::ASRb, Decoder::ASLRLSLRROLRROXLRr}, // 4-22 (p126) - {0xf1d8, 0xe140, Operation::ASRw, Decoder::ASLRLSLRROLRROXLRr}, // 4-22 (p126) - {0xf1d8, 0xe180, Operation::ASRl, Decoder::ASLRLSLRROLRROXLRr}, // 4-22 (p126) - {0xffc0, 0xe1c0, Operation::ASRm, Decoder::ASLRLSLRROLRROXLRm}, // 4-22 (p126) + {0xf1d8, 0xe000, Operation::ASRb, Decoder::ASLRLSLRROLRROXLRr}, // 4-22 (p126) + {0xf1d8, 0xe040, Operation::ASRw, Decoder::ASLRLSLRROLRROXLRr}, // 4-22 (p126) + {0xf1d8, 0xe080, Operation::ASRl, Decoder::ASLRLSLRROLRROXLRr}, // 4-22 (p126) + {0xffc0, 0xe0c0, Operation::ASRm, Decoder::ASLRLSLRROLRROXLRm}, // 4-22 (p126) - {0xf1d8, 0xe008, Operation::LSLb, Decoder::ASLRLSLRROLRROXLRr}, // 4-113 (p217) - {0xf1d8, 0xe048, Operation::LSLw, Decoder::ASLRLSLRROLRROXLRr}, // 4-113 (p217) - {0xf1d8, 0xe088, Operation::LSLl, Decoder::ASLRLSLRROLRROXLRr}, // 4-113 (p217) - {0xffc0, 0xe2c0, Operation::LSLm, Decoder::ASLRLSLRROLRROXLRm}, // 4-113 (p217) + {0xf1d8, 0xe108, Operation::LSLb, Decoder::ASLRLSLRROLRROXLRr}, // 4-113 (p217) + {0xf1d8, 0xe148, Operation::LSLw, Decoder::ASLRLSLRROLRROXLRr}, // 4-113 (p217) + {0xf1d8, 0xe188, Operation::LSLl, Decoder::ASLRLSLRROLRROXLRr}, // 4-113 (p217) + {0xffc0, 0xe3c0, Operation::LSLm, Decoder::ASLRLSLRROLRROXLRm}, // 4-113 (p217) - {0xf1d8, 0xe108, Operation::LSRb, Decoder::ASLRLSLRROLRROXLRr}, // 4-113 (p217) - {0xf1d8, 0xe148, Operation::LSRw, Decoder::ASLRLSLRROLRROXLRr}, // 4-113 (p217) - {0xf1d8, 0xe188, Operation::LSRl, Decoder::ASLRLSLRROLRROXLRr}, // 4-113 (p217) - {0xffc0, 0xe3c0, Operation::LSRm, Decoder::ASLRLSLRROLRROXLRm}, // 4-113 (p217) + {0xf1d8, 0xe008, Operation::LSRb, Decoder::ASLRLSLRROLRROXLRr}, // 4-113 (p217) + {0xf1d8, 0xe048, Operation::LSRw, Decoder::ASLRLSLRROLRROXLRr}, // 4-113 (p217) + {0xf1d8, 0xe088, Operation::LSRl, Decoder::ASLRLSLRROLRROXLRr}, // 4-113 (p217) + {0xffc0, 0xe2c0, Operation::LSRm, Decoder::ASLRLSLRROLRROXLRm}, // 4-113 (p217) - {0xf1d8, 0xe018, Operation::ROLb, Decoder::ASLRLSLRROLRROXLRr}, // 4-160 (p264) - {0xf1d8, 0xe058, Operation::ROLw, Decoder::ASLRLSLRROLRROXLRr}, // 4-160 (p264) - {0xf1d8, 0xe098, Operation::ROLl, Decoder::ASLRLSLRROLRROXLRr}, // 4-160 (p264) - {0xffc0, 0xe6c0, Operation::ROLm, Decoder::ASLRLSLRROLRROXLRm}, // 4-160 (p264) + {0xf1d8, 0xe118, Operation::ROLb, Decoder::ASLRLSLRROLRROXLRr}, // 4-160 (p264) + {0xf1d8, 0xe158, Operation::ROLw, Decoder::ASLRLSLRROLRROXLRr}, // 4-160 (p264) + {0xf1d8, 0xe198, Operation::ROLl, Decoder::ASLRLSLRROLRROXLRr}, // 4-160 (p264) + {0xffc0, 0xe7c0, Operation::ROLm, Decoder::ASLRLSLRROLRROXLRm}, // 4-160 (p264) - {0xf1d8, 0xe118, Operation::RORb, Decoder::ASLRLSLRROLRROXLRr}, // 4-160 (p264) - {0xf1d8, 0xe158, Operation::RORw, Decoder::ASLRLSLRROLRROXLRr}, // 4-160 (p264) - {0xf1d8, 0xe198, Operation::RORl, Decoder::ASLRLSLRROLRROXLRr}, // 4-160 (p264) - {0xffc0, 0xe7c0, Operation::RORm, Decoder::ASLRLSLRROLRROXLRm}, // 4-160 (p264) + {0xf1d8, 0xe018, Operation::RORb, Decoder::ASLRLSLRROLRROXLRr}, // 4-160 (p264) + {0xf1d8, 0xe058, Operation::RORw, Decoder::ASLRLSLRROLRROXLRr}, // 4-160 (p264) + {0xf1d8, 0xe098, Operation::RORl, Decoder::ASLRLSLRROLRROXLRr}, // 4-160 (p264) + {0xffc0, 0xe6c0, Operation::RORm, Decoder::ASLRLSLRROLRROXLRm}, // 4-160 (p264) - {0xf1d8, 0xe010, Operation::ROXLb, Decoder::ASLRLSLRROLRROXLRr}, // 4-163 (p267) - {0xf1d8, 0xe050, Operation::ROXLw, Decoder::ASLRLSLRROLRROXLRr}, // 4-163 (p267) - {0xf1d8, 0xe090, Operation::ROXLl, Decoder::ASLRLSLRROLRROXLRr}, // 4-163 (p267) - {0xffc0, 0xe4c0, Operation::ROXLm, Decoder::ASLRLSLRROLRROXLRm}, // 4-163 (p267) + {0xf1d8, 0xe110, Operation::ROXLb, Decoder::ASLRLSLRROLRROXLRr}, // 4-163 (p267) + {0xf1d8, 0xe150, Operation::ROXLw, Decoder::ASLRLSLRROLRROXLRr}, // 4-163 (p267) + {0xf1d8, 0xe190, Operation::ROXLl, Decoder::ASLRLSLRROLRROXLRr}, // 4-163 (p267) + {0xffc0, 0xe5c0, Operation::ROXLm, Decoder::ASLRLSLRROLRROXLRm}, // 4-163 (p267) - {0xf1d8, 0xe110, Operation::ROXRb, Decoder::ASLRLSLRROLRROXLRr}, // 4-163 (p267) - {0xf1d8, 0xe150, Operation::ROXRw, Decoder::ASLRLSLRROLRROXLRr}, // 4-163 (p267) - {0xf1d8, 0xe190, Operation::ROXRl, Decoder::ASLRLSLRROLRROXLRr}, // 4-163 (p267) - {0xffc0, 0xe5c0, Operation::ROXRm, Decoder::ASLRLSLRROLRROXLRm}, // 4-163 (p267) + {0xf1d8, 0xe010, Operation::ROXRb, Decoder::ASLRLSLRROLRROXLRr}, // 4-163 (p267) + {0xf1d8, 0xe050, Operation::ROXRw, Decoder::ASLRLSLRROLRROXLRr}, // 4-163 (p267) + {0xf1d8, 0xe090, Operation::ROXRl, Decoder::ASLRLSLRROLRROXLRr}, // 4-163 (p267) + {0xffc0, 0xe4c0, Operation::ROXRm, Decoder::ASLRLSLRROLRROXLRm}, // 4-163 (p267) }; #ifndef NDEBUG @@ -928,7 +938,9 @@ struct ProcessorStorageConstructor { } else { op(Action::None, seq("np n")); } - op(Action::PerformOperation); + + // Use a no-op bus cycle that can have its length filled in later. + op(Action::PerformOperation, seq("r")); } break; case Decoder::ASLRLSLRROLRROXLRm: { diff --git a/Processors/68000/Implementation/68000Storage.hpp b/Processors/68000/Implementation/68000Storage.hpp index 971d8ab1a..92939b739 100644 --- a/Processors/68000/Implementation/68000Storage.hpp +++ b/Processors/68000/Implementation/68000Storage.hpp @@ -282,6 +282,7 @@ class ProcessorStorage { Program *active_program_ = nullptr; MicroOp *active_micro_op_ = nullptr; BusStep *active_step_ = nullptr; + uint16_t decoded_instruction_; /// Copies address_[7] to the proper stack pointer based on current mode. void write_back_stack_pointer();