mirror of
https://github.com/TomHarte/CLK.git
synced 2025-01-13 07:30:21 +00:00
Implements MULU and MULS.
This commit is contained in:
parent
be722143e1
commit
8f77d1831b
@ -477,6 +477,46 @@ template <class T, bool dtack_is_implicit> void Processor<T, dtack_is_implicit>:
|
||||
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.
|
||||
*/
|
||||
|
@ -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);
|
||||
|
@ -90,6 +90,8 @@ class ProcessorStorage {
|
||||
EORb, EORw, EORl,
|
||||
NOTb, NOTw, NOTl,
|
||||
ORb, ORw, ORl,
|
||||
|
||||
MULU, MULS,
|
||||
};
|
||||
|
||||
/*!
|
||||
|
Loading…
x
Reference in New Issue
Block a user