diff --git a/Processors/68000Mk2/Implementation/68000Mk2Implementation.hpp b/Processors/68000Mk2/Implementation/68000Mk2Implementation.hpp index 720ec078a..f151740aa 100644 --- a/Processors/68000Mk2/Implementation/68000Mk2Implementation.hpp +++ b/Processors/68000Mk2/Implementation/68000Mk2Implementation.hpp @@ -2522,13 +2522,13 @@ void ProcessorBase::did_bit_op(int bit_position) { } template void ProcessorBase::did_divu(uint32_t dividend, uint32_t divisor) { - if(did_overflow) { - dynamic_instruction_length_ = 3; // Just a quick nn n, and then on to prefetch. + if(!divisor) { + dynamic_instruction_length_ = 4; // nn nn precedes the usual exception activity. return; } - if(!divisor) { - dynamic_instruction_length_ = 4; // nn nn precedes the usual exception activity. + if(did_overflow) { + dynamic_instruction_length_ = 3; // Just a quick nn n, and then on to prefetch. return; } @@ -2561,16 +2561,55 @@ template void ProcessorBase::did_divu(uint32_t dividend, uin } } -template void ProcessorBase::did_divs(int32_t, int32_t) { - // TODO: calculate cost. -} - #define convert_to_bit_count_16(x) \ x = ((x & 0xaaaa) >> 1) + (x & 0x5555); \ x = ((x & 0xcccc) >> 2) + (x & 0x3333); \ x = ((x & 0xf0f0) >> 4) + (x & 0x0f0f); \ x = ((x & 0xff00) >> 8) + (x & 0x00ff); +template void ProcessorBase::did_divs(int32_t dividend, int32_t divisor) { + // The route to spotting divide by 0 is just nn nn. + if(!divisor) { + dynamic_instruction_length_ = 4; // nn nn precedes the usual exception activity. + return; + } + + // It's either five or six microcycles to get into the main loop, depending + // on dividend sign. + dynamic_instruction_length_ = 5 + (dividend < 0); + + if(did_overflow) { + return; + } + + // There's always a cost of four microcycles per bit, plus an additional + // one for each that is non-zero. + // + // The sign bit does not count here; it's the low fifteen bits that matter + // only, in the unsigned version of the result. + dynamic_instruction_length_ += 60; + + int result_bits = abs(dividend / divisor) & 0x7fff; + convert_to_bit_count_16(result_bits); + dynamic_instruction_length_ += result_bits; + + // Determine the tail cost; a divisor of less than 0 leads to one exit, + // a divisor of greater than zero makes the result a function of the + // sign of the dividend. + // + // In all cases, this is counting from 'No more bits' in the Yacht diagram. + if(divisor < 0) { + dynamic_instruction_length_ += 4; + return; + } + + if(dividend < 0) { + dynamic_instruction_length_ += 5; + } else { + dynamic_instruction_length_ += 3; + } +} + template void ProcessorBase::did_mulu(IntT multiplier) { // Count number of bits set. convert_to_bit_count_16(multiplier);