mirror of
https://github.com/TomHarte/CLK.git
synced 2025-07-23 16:24:17 +00:00
Implements MULU and MULS.
This commit is contained in:
@@ -477,6 +477,46 @@ template <class T, bool dtack_is_implicit> void Processor<T, dtack_is_implicit>:
|
|||||||
set_ccr(active_program_->source->full);
|
set_ccr(active_program_->source->full);
|
||||||
break;
|
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.
|
MOVEM: multi-word moves.
|
||||||
*/
|
*/
|
||||||
|
@@ -326,10 +326,7 @@ struct ProcessorStorageConstructor {
|
|||||||
*/
|
*/
|
||||||
void install_instructions() {
|
void install_instructions() {
|
||||||
enum class Decoder {
|
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.
|
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.
|
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.
|
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.
|
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.
|
CMPA, // Maps a destination register and a source mode and register to a CMPA.
|
||||||
CMPM, // Maps to a CMPM.
|
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.
|
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.
|
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.
|
MOVEtoSRCCR, // Maps a source mode and register to a MOVE SR or MOVE CCR.
|
||||||
MOVEq, // Maps a destination register to a MOVEQ.
|
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.
|
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
|
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
|
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.
|
// 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.
|
TST, // Maps a mode and register to a TST.
|
||||||
|
|
||||||
JSR, // Maps a mode and register to a JSR.
|
RTS, // Maps to an RST.
|
||||||
RTS, // Maps
|
|
||||||
};
|
};
|
||||||
|
|
||||||
using Operation = ProcessorStorage::Operation;
|
using Operation = ProcessorStorage::Operation;
|
||||||
@@ -548,6 +549,9 @@ struct ProcessorStorageConstructor {
|
|||||||
{0xffc0, 0x4a40, Operation::TSTw, Decoder::TST}, // 4-192 (p296)
|
{0xffc0, 0x4a40, Operation::TSTw, Decoder::TST}, // 4-192 (p296)
|
||||||
{0xffc0, 0x4a80, Operation::TSTl, 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
|
#ifndef NDEBUG
|
||||||
@@ -590,6 +594,56 @@ struct ProcessorStorageConstructor {
|
|||||||
const int ea_mode = (instruction >> 3) & 7;
|
const int ea_mode = (instruction >> 3) & 7;
|
||||||
|
|
||||||
switch(mapping.decoder) {
|
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: {
|
case Decoder::EORI_ORI_ANDI_SUBI_ADDI: {
|
||||||
const int mode = combined_mode(ea_mode, ea_register);
|
const int mode = combined_mode(ea_mode, ea_register);
|
||||||
const bool is_byte_access = !!((instruction >> 6)&3);
|
const bool is_byte_access = !!((instruction >> 6)&3);
|
||||||
|
@@ -90,6 +90,8 @@ class ProcessorStorage {
|
|||||||
EORb, EORw, EORl,
|
EORb, EORw, EORl,
|
||||||
NOTb, NOTw, NOTl,
|
NOTb, NOTw, NOTl,
|
||||||
ORb, ORw, ORl,
|
ORb, ORw, ORl,
|
||||||
|
|
||||||
|
MULU, MULS,
|
||||||
};
|
};
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
Reference in New Issue
Block a user