diff --git a/Processors/68000/Implementation/68000Implementation.hpp b/Processors/68000/Implementation/68000Implementation.hpp index 3269e91b0..9fd65f495 100644 --- a/Processors/68000/Implementation/68000Implementation.hpp +++ b/Processors/68000/Implementation/68000Implementation.hpp @@ -477,6 +477,46 @@ template void Processor: set_ccr(active_program_->source->full); break; + case Operation::MULU: { + active_program_->destination->full = + active_program_->destination->halves.low.full * active_program_->source->halves.low.full; + carry_flag_ = overflow_flag_ = 0; + zero_result_ = active_program_->destination->full; + negative_flag_ = zero_result_ & 0x80000000; + + // TODO: optimise the below? + int number_of_ones = 0; + auto source = active_program_->source->halves.low.full; + while(source) { + source >>= 1; + ++number_of_ones; + } + + // Time taken = 38 cycles + 2 cycles per 1 in the source. + active_step_->microcycle.length = HalfCycles(4 * number_of_ones + 38*2); + } break; + + case Operation::MULS: { + active_program_->destination->full = + int16_t(active_program_->destination->halves.low.full) * int16_t(active_program_->source->halves.low.full); + carry_flag_ = overflow_flag_ = 0; + zero_result_ = active_program_->destination->full; + negative_flag_ = zero_result_ & 0x80000000; + + // TODO: optimise the below? + int number_of_pairs = 0; + int source = active_program_->source->halves.low.full; + int bit = 0; + while(source | bit) { + number_of_pairs += (bit ^ source) & 1; + bit = source & 1; + source >>= 1; + } + + // Time taken = 38 cycles + 2 cycles per 1 in the source. + active_step_->microcycle.length = HalfCycles(4 * number_of_pairs + 38*2); + } break; + /* MOVEM: multi-word moves. */ diff --git a/Processors/68000/Implementation/68000Storage.cpp b/Processors/68000/Implementation/68000Storage.cpp index ad32686da..09f9b5344 100644 --- a/Processors/68000/Implementation/68000Storage.cpp +++ b/Processors/68000/Implementation/68000Storage.cpp @@ -326,10 +326,7 @@ struct ProcessorStorageConstructor { */ void install_instructions() { enum class Decoder { - EORI_ORI_ANDI_SUBI_ADDI, // Maps a mode and register to one of EORI, ORI, ANDI, SUBI or ADDI. - ABCD_SBCD, // Maps source and desintation registers and a register/memory selection bit to an ABCD or SBCD. - ADD_SUB, // Maps a register and a register and mode to an ADD or SUB. ADDA_SUBA, // Maps a destination register and a source mode and register to an ADDA or SUBA. ADDQ_SUBQ, // Mags a register and a mode to an ADDQ or SUBQ. @@ -350,9 +347,10 @@ struct ProcessorStorageConstructor { CMPA, // Maps a destination register and a source mode and register to a CMPA. CMPM, // Maps to a CMPM. - Scc_DBcc, // Maps a mode and destination register to either a DBcc or Scc. + EORI_ORI_ANDI_SUBI_ADDI, // Maps a mode and register to one of EORI, ORI, ANDI, SUBI or ADDI. JMP, // Maps a mode and register to a JMP. + JSR, // Maps a mode and register to a JSR. LEA, // Maps a destination register and a source mode and register to an LEA. @@ -360,6 +358,8 @@ struct ProcessorStorageConstructor { MOVEtoSRCCR, // Maps a source mode and register to a MOVE SR or MOVE CCR. MOVEq, // Maps a destination register to a MOVEQ. + MULU_MULS, // Maps a destination register and a source mode and register to a MULU or MULS. + RESET, // Maps to a RESET. ASLR_LSLR_ROLR_ROXLRr, // Maps a destination register to a AS[L/R], LS[L/R], RO[L/R], ROX[L/R]; shift quantities are @@ -369,10 +369,11 @@ struct ProcessorStorageConstructor { MOVEM, // Maps a mode and register as they were a 'destination' and sets up bus steps with a suitable // hole for the runtime part to install proper MOVEM activity. + Scc_DBcc, // Maps a mode and destination register to either a DBcc or Scc. + TST, // Maps a mode and register to a TST. - JSR, // Maps a mode and register to a JSR. - RTS, // Maps + RTS, // Maps to an RST. }; using Operation = ProcessorStorage::Operation; @@ -548,6 +549,9 @@ struct ProcessorStorageConstructor { {0xffc0, 0x4a40, Operation::TSTw, Decoder::TST}, // 4-192 (p296) {0xffc0, 0x4a80, Operation::TSTl, Decoder::TST}, // 4-192 (p296) + {0xf1c0, 0xc0c0, Operation::MULU, Decoder::MULU_MULS}, // 4-139 (p243) + {0xf1c0, 0xc1c0, Operation::MULS, Decoder::MULU_MULS}, // 4-136 (p240) + }; #ifndef NDEBUG @@ -590,6 +594,56 @@ struct ProcessorStorageConstructor { const int ea_mode = (instruction >> 3) & 7; switch(mapping.decoder) { + case Decoder::MULU_MULS: { + const int destination_register = (instruction >> 9) & 7; + storage_.instructions[instruction].set_source(storage_, ea_mode, ea_register); + storage_.instructions[instruction].set_destination(storage_, Dn, destination_register); + + const int mode = combined_mode(ea_mode, ea_register); + switch(mode) { + default: continue; + + case Dn: + op(Action::None, seq("np")); + op(Action::PerformOperation, seq("r")); + break; + + case Ind: + case PostInc: + op(Action::None, seq("nr np", { a(ea_register) })); + op(Action::PerformOperation, seq("r")); + if(mode == PostInc) { + op(int(Action::Increment2) | MicroOp::SourceMask); + } + break; + + case PreDec: + op(int(Action::Decrement2) | MicroOp::SourceMask, seq("n nr np", { a(ea_register) })); + op(Action::PerformOperation, seq("r")); + break; + + case d16An: + case d16PC: + case d8AnXn: + case d8PCXn: + op(calc_action_for_mode(mode) | MicroOp::SourceMask, seq(pseq("n np nr np", mode), { ea(0) })); + op(Action::PerformOperation, seq("r")); + break; + + case XXXl: + op(Action::None, seq("np")); + case XXXw: + op(address_assemble_for_mode(mode) | MicroOp::SourceMask, seq("np nr np", { ea(0) })); + op(Action::PerformOperation, seq("r")); + break; + + case Imm: + op(int(Action::AssembleWordDataFromPrefetch) | MicroOp::SourceMask, seq("np np np")); + op(Action::PerformOperation, seq("r")); + break; + } + } break; + case Decoder::EORI_ORI_ANDI_SUBI_ADDI: { const int mode = combined_mode(ea_mode, ea_register); const bool is_byte_access = !!((instruction >> 6)&3); diff --git a/Processors/68000/Implementation/68000Storage.hpp b/Processors/68000/Implementation/68000Storage.hpp index 433e044a9..a5496e1e5 100644 --- a/Processors/68000/Implementation/68000Storage.hpp +++ b/Processors/68000/Implementation/68000Storage.hpp @@ -90,6 +90,8 @@ class ProcessorStorage { EORb, EORw, EORl, NOTb, NOTw, NOTl, ORb, ORw, ORl, + + MULU, MULS, }; /*!