1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-07-05 10:28:58 +00:00

Implements MULU and MULS.

This commit is contained in:
Thomas Harte 2019-04-16 22:16:43 -04:00
parent be722143e1
commit 8f77d1831b
3 changed files with 102 additions and 6 deletions

View File

@ -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.
*/

View File

@ -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);

View File

@ -90,6 +90,8 @@ class ProcessorStorage {
EORb, EORw, EORl,
NOTb, NOTw, NOTl,
ORb, ORw, ORl,
MULU, MULS,
};
/*!