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

Adds basic addressing modes for [ADD/SUB]Q.

This commit is contained in:
Thomas Harte 2019-04-16 11:19:45 -04:00
parent dec5535e54
commit 37656f14d8
3 changed files with 177 additions and 66 deletions

View File

@ -111,40 +111,133 @@ template <class T, bool dtack_is_implicit> void Processor<T, dtack_is_implicit>:
active_program_->destination->halves.low.halves.low = uint8_t(result);
} break;
// ADD and ADDA add two quantities, the latter sign extending and without setting any flags.
case Operation::ADDb: {
const uint8_t source = active_program_->source->halves.low.halves.low;
const uint8_t destination = active_program_->destination->halves.low.halves.low;
const int result = destination + source;
// ADD and ADDA add two quantities, the latter sign extending and without setting any flags;
// ADDQ and SUBQ act as ADD and SUB, but taking the second argument from the instruction code.
#define addop(a, b) a + b
#define subop(a, b) a - b
zero_result_ = active_program_->destination->halves.low.halves.low = uint8_t(result);
extend_flag_ = carry_flag_ = result & ~0xff;
negative_flag_ = result & 0x80;
overflow_flag_ = add_overflow() & 0x80;
#define addsubb(a, b, dest, op, overflow) \
const auto source = a; \
const auto destination = b; \
const int result = op(destination, source); \
\
zero_result_ = dest = uint8_t(result); \
extend_flag_ = carry_flag_ = result & ~0xff; \
negative_flag_ = result & 0x80; \
overflow_flag_ = overflow() & 0x80;
#define addsubw(a, b, dest, op, overflow) \
const auto source = a; \
const auto destination = b; \
const int result = op(destination, source); \
\
zero_result_ = dest = uint16_t(result); \
extend_flag_ = carry_flag_ = result & ~0xffff; \
negative_flag_ = result & 0x8000; \
overflow_flag_ = overflow() & 0x8000;
#define addsubl(a, b, dest, op, overflow) \
const auto source = a; \
const auto destination = b; \
const uint64_t result = op(destination, source); \
\
zero_result_ = dest = uint32_t(result); \
extend_flag_ = carry_flag_ = result >> 32; \
negative_flag_ = result & 0x80000000; \
overflow_flag_ = overflow() & 0x80000000;
#define addb(a, b, dest) addsubb(a, b, dest, addop, add_overflow)
#define subb(a, b, dest) addsubb(a, b, dest, subop, sub_overflow)
#define addw(a, b, dest) addsubw(a, b, dest, addop, add_overflow)
#define subw(a, b, dest) addsubw(a, b, dest, subop, sub_overflow)
#define addl(a, b, dest) addsubl(a, b, dest, addop, add_overflow)
#define subl(a, b, dest) addsubl(a, b, dest, subop, sub_overflow)
#define q() (((decoded_instruction_ >> 9)&7) ? ((decoded_instruction_ >> 9)&7) : 8)
case Operation::ADDb: {
addb( active_program_->source->halves.low.halves.low,
active_program_->destination->halves.low.halves.low,
active_program_->destination->halves.low.halves.low);
} break;
case Operation::ADDQb: {
addb( q(),
active_program_->destination->halves.low.halves.low,
active_program_->destination->halves.low.halves.low);
} break;
case Operation::ADDw: {
const uint16_t source = active_program_->source->halves.low.full;
const uint16_t destination = active_program_->destination->halves.low.full;
const int result = destination + source;
addw( active_program_->source->halves.low.full,
active_program_->destination->halves.low.full,
active_program_->destination->halves.low.full);
} break;
zero_result_ = active_program_->destination->halves.low.full = uint16_t(result);
extend_flag_ = carry_flag_ = result & ~0xffff;
negative_flag_ = result & 0x8000;
overflow_flag_ = add_overflow() & 0x8000;
case Operation::ADDQw: {
addw( q(),
active_program_->destination->halves.low.full,
active_program_->destination->halves.low.full);
} break;
case Operation::ADDl: {
const uint32_t source = active_program_->source->full;
const uint32_t destination = active_program_->destination->full;
const uint64_t result = destination + source;
zero_result_ = active_program_->destination->full = uint32_t(result);
extend_flag_ = carry_flag_ = result >> 32;
negative_flag_ = result & 0x80000000;
overflow_flag_ = add_overflow() & 0x80000000;
addl( active_program_->source->full,
active_program_->destination->full,
active_program_->destination->full);
} break;
case Operation::ADDQl: {
addl( q(),
active_program_->destination->full,
active_program_->destination->full);
} break;
case Operation::SUBb: {
subb( active_program_->source->halves.low.halves.low,
active_program_->destination->halves.low.halves.low,
active_program_->destination->halves.low.halves.low);
} break;
case Operation::SUBQb: {
subb( q(),
active_program_->destination->halves.low.halves.low,
active_program_->destination->halves.low.halves.low);
} break;
case Operation::SUBw: {
subw( active_program_->source->halves.low.full,
active_program_->destination->halves.low.full,
active_program_->destination->halves.low.full);
} break;
case Operation::SUBQw: {
subw( q(),
active_program_->destination->halves.low.full,
active_program_->destination->halves.low.full);
} break;
case Operation::SUBl: {
subl( active_program_->source->full,
active_program_->destination->full,
active_program_->destination->full);
} break;
case Operation::SUBQl: {
subl( q(),
active_program_->destination->full,
active_program_->destination->full);
} break;
#undef addl
#undef addw
#undef addb
#undef subl
#undef subw
#undef subb
#undef addsubl
#undef addsubw
#undef addsubb
#undef q
case Operation::ADDAw:
active_program_->destination->full += int16_t(active_program_->source->halves.low.full);
break;
@ -153,6 +246,14 @@ template <class T, bool dtack_is_implicit> void Processor<T, dtack_is_implicit>:
active_program_->destination->full += active_program_->source->full;
break;
case Operation::SUBAw:
active_program_->destination->full -= int16_t(active_program_->source->halves.low.full);
break;
case Operation::SUBAl:
active_program_->destination->full -= active_program_->source->full;
break;
// BRA: alters the program counter, exclusively via the prefetch queue.
case Operation::BRA: {
const int8_t byte_offset = int8_t(prefetch_queue_.halves.high.halves.low);
@ -653,47 +754,6 @@ template <class T, bool dtack_is_implicit> void Processor<T, dtack_is_implicit>:
active_program_->destination->halves.low.halves.low = uint8_t(result);
} break;
case Operation::SUBb: {
const uint8_t source = active_program_->source->halves.low.halves.low;
const uint8_t destination = active_program_->destination->halves.low.halves.low;
const int result = destination - source;
zero_result_ = active_program_->destination->halves.low.halves.low = uint8_t(result);
extend_flag_ = carry_flag_ = result & ~0xff;
negative_flag_ = result & 0x80;
overflow_flag_ = sub_overflow() & 0x80;
} break;
case Operation::SUBw: {
const uint16_t source = active_program_->source->halves.low.full;
const uint16_t destination = active_program_->destination->halves.low.full;
const int result = destination - source;
zero_result_ = active_program_->destination->halves.low.full = uint16_t(result);
extend_flag_ = carry_flag_ = result & ~0xffff;
negative_flag_ = result & 0x8000;
overflow_flag_ = sub_overflow() & 0x8000;
} break;
case Operation::SUBl: {
const uint32_t source = active_program_->source->full;
const uint32_t destination = active_program_->destination->full;
const uint64_t result = destination - source;
zero_result_ = active_program_->destination->full = uint32_t(result);
extend_flag_ = carry_flag_ = result >> 32;
negative_flag_ = result & 0x80000000;
overflow_flag_ = sub_overflow() & 0x80000000;
} break;
case Operation::SUBAw:
active_program_->destination->full -= int16_t(active_program_->source->halves.low.full);
break;
case Operation::SUBAl:
active_program_->destination->full -= active_program_->source->full;
break;
/*
Shifts and rotates.
*/

View File

@ -330,6 +330,7 @@ struct ProcessorStorageConstructor {
ADDSUB, // Maps a register and a register and mode to an ADD or SUB.
ADDASUBA, // Maps a destination register and a source mode and register to an ADDA or SUBA.
ADDQSUBQ, // Mags a register and a mode to an ADDQ or SUBQ.
BRA, // Maps to a BRA. All fields are decoded at runtime.
BccBSR, // Maps to a Bcc or BSR. Other than determining the type of operation, fields are decoded at runtime.
@ -451,6 +452,14 @@ struct ProcessorStorageConstructor {
{0xf1c0, 0x90c0, Operation::SUBAw, Decoder::ADDASUBA}, // 4-177 (p281)
{0xf1c0, 0x91c0, Operation::SUBAl, Decoder::ADDASUBA}, // 4-177 (p281)
{0xf1c0, 0x5000, Operation::ADDQb, Decoder::ADDQSUBQ}, // 4-11 (p115)
{0xf1c0, 0x5040, Operation::ADDQw, Decoder::ADDQSUBQ}, // 4-11 (p115)
{0xf1c0, 0x5080, Operation::ADDQl, Decoder::ADDQSUBQ}, // 4-11 (p115)
{0xf1c0, 0x5100, Operation::SUBQb, Decoder::ADDQSUBQ}, // 4-181 (p285)
{0xf1c0, 0x5140, Operation::SUBQw, Decoder::ADDQSUBQ}, // 4-181 (p285)
{0xf1c0, 0x5180, Operation::SUBQl, Decoder::ADDQSUBQ}, // 4-181 (p285)
{0xf1c0, 0x0100, Operation::BTSTb, Decoder::BTST}, // 4-62 (p166)
{0xffc0, 0x0800, Operation::BTSTb, Decoder::BTSTIMM}, // 4-63 (p167)
@ -847,6 +856,45 @@ struct ProcessorStorageConstructor {
}
} break;
case Decoder::ADDQSUBQ: {
storage_.instructions[instruction].set_destination(storage_, ea_mode, ea_register);
const bool is_long_word_access = ((instruction >> 6)&3) == 2;
const bool is_byte_access = ((instruction >> 6)&3) == 0;
const int mode = combined_mode(ea_mode, ea_register);
switch(is_long_word_access ? l(mode) : bw(mode)) {
default: continue;
case bw(Dn):
op(Action::PerformOperation, seq("np"));
break;
case l(Dn):
case l(An):
case bw(An):
op(Action::PerformOperation, seq("np nn"));
break;
case bw(Ind):
case bw(PostInc):
op(Action::None, seq("nrd np", { a(ea_register) }, !is_byte_access));
op(Action::PerformOperation, seq("nw", { a(ea_register) }, !is_byte_access));
if(mode == PostInc) {
op(int(is_byte_access ? Action::Increment1 : Action::Increment2) | MicroOp::DestinationMask);
}
break;
case l(Ind):
case l(PostInc):
op(int(Action::CopyToEffectiveAddress) | MicroOp::DestinationMask, seq("nRd+ nrd np", { ea(1), ea(1) }));
op(Action::PerformOperation, seq("nw- nW", { ea(1), ea(1) }));
if(mode == PostInc) {
op(int(Action::Increment4) | MicroOp::DestinationMask);
}
break;
}
} break;
// This decoder actually decodes nothing; it just schedules a PerformOperation followed by an empty step.
case Decoder::BccBSR: {
const int condition = (instruction >> 8) & 0xf;

View File

@ -47,8 +47,11 @@ class ProcessorStorage {
ABCD, SBCD,
ADDb, ADDw, ADDl,
SUBb, SUBw, SUBl,
ADDQb, ADDQw, ADDQl,
ADDAw, ADDAl,
SUBb, SUBw, SUBl,
SUBQb, SUBQw, SUBQl,
SUBAw, SUBAl,
MOVEb, MOVEw, MOVEl, MOVEq,