mirror of
https://github.com/TomHarte/CLK.git
synced 2024-11-26 08:49:37 +00:00
Attempts an implementation of ADDX and SUBX.
Leaving 2005 non-[A/F]-line instructions.
This commit is contained in:
parent
cf547ef569
commit
ab5fcab9bf
@ -124,118 +124,180 @@ template <class T, bool dtack_is_implicit, bool signal_will_perform> void Proces
|
||||
|
||||
// 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
|
||||
#define addop(a, b, x) a + b + (x ? 1 : 0)
|
||||
#define subop(a, b, x) a - b - (x ? 1 : 0)
|
||||
#define z_set(a, b) a = b
|
||||
#define z_or(a, b) a |= b
|
||||
|
||||
#define addsubb(a, b, dest, op, overflow) \
|
||||
#define addsubb(a, b, dest, op, overflow, x, zero_op) \
|
||||
const int source = a; \
|
||||
const int destination = b; \
|
||||
const auto result = op(destination, source); \
|
||||
const auto result = op(destination, source, x); \
|
||||
\
|
||||
zero_result_ = dest = uint8_t(result); \
|
||||
dest = uint8_t(result); \
|
||||
zero_op(zero_result_, dest); \
|
||||
extend_flag_ = carry_flag_ = result & ~0xff; \
|
||||
negative_flag_ = result & 0x80; \
|
||||
overflow_flag_ = overflow() & 0x80;
|
||||
|
||||
#define addsubw(a, b, dest, op, overflow) \
|
||||
#define addsubw(a, b, dest, op, overflow, x, zero_op) \
|
||||
const int source = a; \
|
||||
const int destination = b; \
|
||||
const auto result = op(destination, source); \
|
||||
const auto result = op(destination, source, x); \
|
||||
\
|
||||
zero_result_ = dest = uint16_t(result); \
|
||||
dest = uint16_t(result); \
|
||||
zero_op(zero_result_, dest); \
|
||||
extend_flag_ = carry_flag_ = result & ~0xffff; \
|
||||
negative_flag_ = result & 0x8000; \
|
||||
overflow_flag_ = overflow() & 0x8000;
|
||||
|
||||
#define addsubl(a, b, dest, op, overflow) \
|
||||
#define addsubl(a, b, dest, op, overflow, x, zero_op) \
|
||||
const uint64_t source = a; \
|
||||
const uint64_t destination = b; \
|
||||
const auto result = op(destination, source); \
|
||||
const auto result = op(destination, source, x); \
|
||||
\
|
||||
zero_result_ = dest = uint32_t(result); \
|
||||
dest = uint32_t(result); \
|
||||
zero_op(zero_result_, dest); \
|
||||
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 addb(a, b, dest, x, z) addsubb(a, b, dest, addop, add_overflow, x, z)
|
||||
#define subb(a, b, dest, x, z) addsubb(a, b, dest, subop, sub_overflow, x, z)
|
||||
#define addw(a, b, dest, x, z) addsubw(a, b, dest, addop, add_overflow, x, z)
|
||||
#define subw(a, b, dest, x, z) addsubw(a, b, dest, subop, sub_overflow, x, z)
|
||||
#define addl(a, b, dest, x, z) addsubl(a, b, dest, addop, add_overflow, x, z)
|
||||
#define subl(a, b, dest, x, z) addsubl(a, b, dest, subop, sub_overflow, x, z)
|
||||
|
||||
#define no_extend(op, a, b, c) op(a, b, c, 0, z_set)
|
||||
#define extend(op, a, b, c) op(a, b, c, extend_flag_, z_or)
|
||||
|
||||
#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);
|
||||
no_extend( 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::ADDXb: {
|
||||
extend( 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);
|
||||
no_extend( addb,
|
||||
q(),
|
||||
active_program_->destination->halves.low.halves.low,
|
||||
active_program_->destination->halves.low.halves.low);
|
||||
} break;
|
||||
|
||||
case Operation::ADDw: {
|
||||
addw( active_program_->source->halves.low.full,
|
||||
active_program_->destination->halves.low.full,
|
||||
active_program_->destination->halves.low.full);
|
||||
no_extend( addw,
|
||||
active_program_->source->halves.low.full,
|
||||
active_program_->destination->halves.low.full,
|
||||
active_program_->destination->halves.low.full);
|
||||
} break;
|
||||
|
||||
case Operation::ADDXw: {
|
||||
extend( addw,
|
||||
active_program_->source->halves.low.full,
|
||||
active_program_->destination->halves.low.full,
|
||||
active_program_->destination->halves.low.full);
|
||||
} break;
|
||||
|
||||
case Operation::ADDQw: {
|
||||
addw( q(),
|
||||
active_program_->destination->halves.low.full,
|
||||
active_program_->destination->halves.low.full);
|
||||
no_extend( addw,
|
||||
q(),
|
||||
active_program_->destination->halves.low.full,
|
||||
active_program_->destination->halves.low.full);
|
||||
} break;
|
||||
|
||||
case Operation::ADDl: {
|
||||
addl( active_program_->source->full,
|
||||
active_program_->destination->full,
|
||||
active_program_->destination->full);
|
||||
no_extend( addl,
|
||||
active_program_->source->full,
|
||||
active_program_->destination->full,
|
||||
active_program_->destination->full);
|
||||
} break;
|
||||
|
||||
case Operation::ADDXl: {
|
||||
extend( 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);
|
||||
no_extend( 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);
|
||||
no_extend( 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::SUBXb: {
|
||||
extend( 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);
|
||||
no_extend( 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);
|
||||
no_extend( subw,
|
||||
active_program_->source->halves.low.full,
|
||||
active_program_->destination->halves.low.full,
|
||||
active_program_->destination->halves.low.full);
|
||||
} break;
|
||||
|
||||
case Operation::SUBXw: {
|
||||
extend( 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);
|
||||
no_extend( 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);
|
||||
no_extend( subl,
|
||||
active_program_->source->full,
|
||||
active_program_->destination->full,
|
||||
active_program_->destination->full);
|
||||
} break;
|
||||
|
||||
case Operation::SUBXl: {
|
||||
extend( 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);
|
||||
no_extend( subl,
|
||||
q(),
|
||||
active_program_->destination->full,
|
||||
active_program_->destination->full);
|
||||
} break;
|
||||
|
||||
case Operation::ADDQAl:
|
||||
@ -256,6 +318,13 @@ template <class T, bool dtack_is_implicit, bool signal_will_perform> void Proces
|
||||
#undef addsubw
|
||||
#undef addsubb
|
||||
#undef q
|
||||
#undef z_set
|
||||
#undef z_or
|
||||
#undef no_extend
|
||||
#undef extend
|
||||
#undef addop
|
||||
#undef subop
|
||||
|
||||
|
||||
case Operation::ADDAw:
|
||||
active_program_->destination->full += int16_t(active_program_->source->halves.low.full);
|
||||
|
@ -392,6 +392,7 @@ struct ProcessorStorageConstructor {
|
||||
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, // Maps a register and a mode to an ADDQ or SUBQ.
|
||||
ADDX_SUBX, // Maps source and destination registers, and register/memory mode to an ADDX or SUBX.
|
||||
|
||||
AND_OR_EOR, // Maps a source register, operation mode and destination register and mode to an AND, OR or EOR.
|
||||
|
||||
@ -575,6 +576,14 @@ struct ProcessorStorageConstructor {
|
||||
{0xf1c0, 0x5140, Operation::SUBQw, Decoder::ADDQ_SUBQ}, // 4-181 (p285)
|
||||
{0xf1c0, 0x5180, Operation::SUBQl, Decoder::ADDQ_SUBQ}, // 4-181 (p285)
|
||||
|
||||
{0xf1f0, 0xd100, Operation::ADDXb, Decoder::ADDX_SUBX}, // 4-14 (p118)
|
||||
{0xf1f0, 0xd140, Operation::ADDXw, Decoder::ADDX_SUBX}, // 4-14 (p118)
|
||||
{0xf1f0, 0xd180, Operation::ADDXl, Decoder::ADDX_SUBX}, // 4-14 (p118)
|
||||
|
||||
{0xf1f0, 0x9100, Operation::SUBXb, Decoder::ADDX_SUBX}, // 4-184 (p288)
|
||||
{0xf1f0, 0x9140, Operation::SUBXw, Decoder::ADDX_SUBX}, // 4-184 (p288)
|
||||
{0xf1f0, 0x9180, Operation::SUBXl, Decoder::ADDX_SUBX}, // 4-184 (p288)
|
||||
|
||||
{0xf1c0, 0x0100, Operation::BTSTb, Decoder::BTST}, // 4-62 (p166)
|
||||
{0xffc0, 0x0800, Operation::BTSTb, Decoder::BTSTIMM}, // 4-63 (p167)
|
||||
|
||||
@ -774,8 +783,7 @@ struct ProcessorStorageConstructor {
|
||||
|
||||
if(instruction & 0x100) {
|
||||
// The bit is nominated by a register.
|
||||
const int source_register = (instruction >> 9)&7;
|
||||
storage_.instructions[instruction].set_source(storage_, Dn, source_register);
|
||||
storage_.instructions[instruction].set_source(storage_, Dn, data_register);
|
||||
} else {
|
||||
// The bit is nominated by a constant, that will be obtained right here.
|
||||
storage_.instructions[instruction].set_source(storage_, Imm, 0);
|
||||
@ -1030,9 +1038,8 @@ struct ProcessorStorageConstructor {
|
||||
} break;
|
||||
|
||||
case Decoder::DIVU_DIVS: {
|
||||
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);
|
||||
storage_.instructions[instruction].set_destination(storage_, Dn, data_register);
|
||||
|
||||
const int mode = combined_mode(ea_mode, ea_register);
|
||||
switch(mode) {
|
||||
@ -1077,9 +1084,8 @@ struct ProcessorStorageConstructor {
|
||||
} break;
|
||||
|
||||
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);
|
||||
storage_.instructions[instruction].set_destination(storage_, Dn, data_register);
|
||||
|
||||
const int mode = combined_mode(ea_mode, ea_register);
|
||||
switch(mode) {
|
||||
@ -1428,8 +1434,7 @@ struct ProcessorStorageConstructor {
|
||||
} break;
|
||||
|
||||
case Decoder::ADDA_SUBA: {
|
||||
const int destination_register = (instruction >> 9) & 7;
|
||||
storage_.instructions[instruction].set_destination(storage_, 1, destination_register);
|
||||
storage_.instructions[instruction].set_destination(storage_, 1, data_register);
|
||||
storage_.instructions[instruction].set_source(storage_, ea_mode, ea_register);
|
||||
|
||||
const int mode = combined_mode(ea_mode, ea_register);
|
||||
@ -1603,6 +1608,49 @@ struct ProcessorStorageConstructor {
|
||||
}
|
||||
} break;
|
||||
|
||||
case Decoder::ADDX_SUBX: {
|
||||
if(instruction & 0x8) {
|
||||
// Use predecrementing address registers.
|
||||
storage_.instructions[instruction].set_source(storage_, Ind, ea_register);
|
||||
storage_.instructions[instruction].set_destination(storage_, Ind, data_register);
|
||||
|
||||
if(is_long_word_access) {
|
||||
// Access order is very atypical here: it's lower parts each for both words,
|
||||
// and then also a lower-part-first write.
|
||||
op(int(Action::Decrement2) | MicroOp::SourceMask | MicroOp::DestinationMask);
|
||||
op( int(Action::CopyToEffectiveAddress) | MicroOp::SourceMask | MicroOp::DestinationMask,
|
||||
seq("n nr- nR nrd- nRd+", { ea(0), ea(0), ea(1), ea(1) }));
|
||||
op(int(Action::Decrement2) | MicroOp::SourceMask | MicroOp::DestinationMask);
|
||||
op(Action::PerformOperation, seq("nw- np nW", { ea(1), ea(1) }));
|
||||
} else {
|
||||
const int source_dec = dec(ea_register);
|
||||
const int destination_dec = dec(data_register);
|
||||
|
||||
int first_action;
|
||||
if(source_dec == destination_dec) {
|
||||
first_action = int(Action::Decrement4) | MicroOp::SourceMask | MicroOp::DestinationMask;
|
||||
} else {
|
||||
op(source_dec | MicroOp::SourceMask);
|
||||
first_action = destination_dec | MicroOp::DestinationMask;
|
||||
}
|
||||
|
||||
op(first_action, seq("n nr nrd np", { ea(0), ea(1) }, !is_byte_access));
|
||||
op(Action::PerformOperation, seq("nw", { ea(1) }, !is_byte_access));
|
||||
}
|
||||
} else {
|
||||
// Use data registers.
|
||||
storage_.instructions[instruction].set_source(storage_, Dn, ea_register);
|
||||
storage_.instructions[instruction].set_destination(storage_, Dn, data_register);
|
||||
|
||||
if(is_long_word_access) {
|
||||
op(Action::PerformOperation, seq("np nn"));
|
||||
} else {
|
||||
op(Action::PerformOperation, seq("np"));
|
||||
}
|
||||
}
|
||||
|
||||
} break;
|
||||
|
||||
// This decoder actually decodes nothing; it just schedules a PerformOperation followed by an empty step.
|
||||
case Decoder::Bcc_BSR: {
|
||||
const int condition = (instruction >> 8) & 0xf;
|
||||
@ -1629,8 +1677,7 @@ struct ProcessorStorageConstructor {
|
||||
case Decoder::BTST: {
|
||||
const bool is_bclr = mapping.decoder == Decoder::BCLR;
|
||||
|
||||
const int mask_register = (instruction >> 9) & 7;
|
||||
storage_.instructions[instruction].set_source(storage_, 0, mask_register);
|
||||
storage_.instructions[instruction].set_source(storage_, 0, data_register);
|
||||
storage_.instructions[instruction].set_destination(storage_, ea_mode, ea_register);
|
||||
|
||||
const int mode = combined_mode(ea_mode, ea_register);
|
||||
@ -1753,16 +1800,14 @@ struct ProcessorStorageConstructor {
|
||||
|
||||
// Decodes the format used by ABCD and SBCD.
|
||||
case Decoder::ABCD_SBCD: {
|
||||
const int destination_register = (instruction >> 9) & 7;
|
||||
|
||||
if(instruction & 8) {
|
||||
storage_.instructions[instruction].source = &storage_.source_bus_data_[0];
|
||||
storage_.instructions[instruction].destination = &storage_.destination_bus_data_[0];
|
||||
storage_.instructions[instruction].source_address = &storage_.address_[ea_register];
|
||||
storage_.instructions[instruction].destination_address = &storage_.address_[destination_register];
|
||||
storage_.instructions[instruction].destination_address = &storage_.address_[data_register];
|
||||
|
||||
const int source_dec = dec(ea_register);
|
||||
const int destination_dec = dec(destination_register);
|
||||
const int destination_dec = dec(data_register);
|
||||
|
||||
int first_action = source_dec | MicroOp::SourceMask | MicroOp::DestinationMask;
|
||||
if(source_dec != destination_dec) {
|
||||
@ -1771,11 +1816,11 @@ struct ProcessorStorageConstructor {
|
||||
}
|
||||
|
||||
op( first_action,
|
||||
seq("n nr nr np nw", { a(ea_register), a(destination_register), a(destination_register) }, false));
|
||||
seq("n nr nrd np nw", { a(ea_register), a(data_register), a(data_register) }, false));
|
||||
op(Action::PerformOperation);
|
||||
} else {
|
||||
storage_.instructions[instruction].source = &storage_.data_[ea_register];
|
||||
storage_.instructions[instruction].destination = &storage_.data_[destination_register];
|
||||
storage_.instructions[instruction].destination = &storage_.data_[data_register];
|
||||
|
||||
op(Action::PerformOperation, seq("np n"));
|
||||
}
|
||||
@ -1913,9 +1958,7 @@ struct ProcessorStorageConstructor {
|
||||
} break;
|
||||
|
||||
case Decoder::CMP: {
|
||||
const auto source_register = (instruction >> 9) & 7;
|
||||
|
||||
storage_.instructions[instruction].destination = &storage_.data_[source_register];
|
||||
storage_.instructions[instruction].destination = &storage_.data_[data_register];
|
||||
storage_.instructions[instruction].set_source(storage_, ea_mode, ea_register);
|
||||
|
||||
// Byte accesses are not allowed with address registers.
|
||||
@ -2018,10 +2061,8 @@ struct ProcessorStorageConstructor {
|
||||
if(((op_mode)&3) != 3) continue;
|
||||
is_long_word_access = op_mode == 7;
|
||||
|
||||
const int destination_register = (instruction >> 9) & 7;
|
||||
|
||||
storage_.instructions[instruction].set_source(storage_, ea_mode, ea_register);
|
||||
storage_.instructions[instruction].destination = &storage_.address_[destination_register];
|
||||
storage_.instructions[instruction].destination = &storage_.address_[data_register];
|
||||
|
||||
const int mode = combined_mode(ea_mode, ea_register, true);
|
||||
switch(is_long_word_access ? l(mode) : bw(mode)) {
|
||||
@ -2198,23 +2239,28 @@ struct ProcessorStorageConstructor {
|
||||
} break;
|
||||
|
||||
case Decoder::CMPM: {
|
||||
const int source_register = (instruction >> 9)&7;
|
||||
const int destination_register = ea_register;
|
||||
storage_.instructions[instruction].set_source(storage_, 1, ea_register);
|
||||
storage_.instructions[instruction].set_destination(storage_, 1, data_register);
|
||||
|
||||
storage_.instructions[instruction].set_source(storage_, 1, source_register);
|
||||
storage_.instructions[instruction].set_destination(storage_, 1, destination_register);
|
||||
|
||||
const bool is_byte_operation = operation == Operation::CMPw;
|
||||
const bool is_byte_operation = operation == Operation::CMPb;
|
||||
|
||||
switch(operation) {
|
||||
default: continue;
|
||||
|
||||
case Operation::CMPb: // CMPM.b, (An)+, (An)+
|
||||
case Operation::CMPw: // CMPM.w, (An)+, (An)+
|
||||
op(Action::None, seq("nr nr np", {a(source_register), a(destination_register)}, !is_byte_operation));
|
||||
case Operation::CMPw: { // CMPM.w, (An)+, (An)+
|
||||
op(Action::None, seq("nr nrd np", { a(data_register), a(ea_register) }, !is_byte_operation));
|
||||
op(Action::PerformOperation);
|
||||
op(inc(destination_register) | MicroOp::SourceMask | MicroOp::DestinationMask);
|
||||
break;
|
||||
|
||||
const int source_inc = inc(ea_register);
|
||||
const int destination_inc = inc(data_register);
|
||||
if(destination_inc == source_inc) {
|
||||
op(destination_inc | MicroOp::SourceMask | MicroOp::DestinationMask);
|
||||
} else {
|
||||
op(destination_inc | MicroOp::DestinationMask);
|
||||
op(source_inc | MicroOp::SourceMask);
|
||||
}
|
||||
} break;
|
||||
|
||||
case Operation::CMPl:
|
||||
op( int(Action::CopyToEffectiveAddress) | MicroOp::SourceMask | MicroOp::DestinationMask,
|
||||
@ -2402,8 +2448,7 @@ struct ProcessorStorageConstructor {
|
||||
} break;
|
||||
|
||||
case Decoder::LEA: {
|
||||
const int destination_register = (instruction >> 9) & 7;
|
||||
storage_.instructions[instruction].set_destination(storage_, An, destination_register);
|
||||
storage_.instructions[instruction].set_destination(storage_, An, data_register);
|
||||
|
||||
const int mode = combined_mode(ea_mode, ea_register);
|
||||
storage_.instructions[instruction].source_address = &storage_.address_[ea_register];
|
||||
@ -2537,8 +2582,7 @@ struct ProcessorStorageConstructor {
|
||||
} break;
|
||||
|
||||
case Decoder::MOVEq: {
|
||||
const int destination_register = (instruction >> 9) & 7;
|
||||
storage_.instructions[instruction].destination = &storage_.data_[destination_register];
|
||||
storage_.instructions[instruction].destination = &storage_.data_[data_register];
|
||||
op(Action::PerformOperation, seq("np"));
|
||||
} break;
|
||||
|
||||
@ -2610,17 +2654,16 @@ struct ProcessorStorageConstructor {
|
||||
// Decodes the format used by most MOVEs and all MOVEAs.
|
||||
case Decoder::MOVE: {
|
||||
const int destination_mode = (instruction >> 6) & 7;
|
||||
const int destination_register = (instruction >> 9) & 7;
|
||||
|
||||
storage_.instructions[instruction].set_source(storage_, ea_mode, ea_register);
|
||||
storage_.instructions[instruction].set_destination(storage_, destination_mode, destination_register);
|
||||
storage_.instructions[instruction].set_destination(storage_, destination_mode, data_register);
|
||||
|
||||
// These don't come from the usual place.
|
||||
is_byte_access = mapping.operation == Operation::MOVEb;
|
||||
is_long_word_access = mapping.operation == Operation::MOVEl;
|
||||
|
||||
const int combined_source_mode = combined_mode(ea_mode, ea_register, true, true);
|
||||
const int combined_destination_mode = combined_mode(destination_mode, destination_register, true, true);
|
||||
const int combined_destination_mode = combined_mode(destination_mode, data_register, true, true);
|
||||
const int mode = is_long_word_access ?
|
||||
l2(combined_source_mode, combined_destination_mode) :
|
||||
bw2(combined_source_mode, combined_destination_mode);
|
||||
@ -2712,7 +2755,7 @@ struct ProcessorStorageConstructor {
|
||||
break;
|
||||
|
||||
case bw2(Dn, Ind): // MOVE.bw [An/Dn], (An)[+]
|
||||
op(Action::PerformOperation, seq("nw np", { a(destination_register) }, !is_byte_access));
|
||||
op(Action::PerformOperation, seq("nw np", { a(data_register) }, !is_byte_access));
|
||||
break;
|
||||
|
||||
case l2(PreDec, Ind): // MOVE.l -(An), (An)[+]
|
||||
@ -2725,12 +2768,12 @@ struct ProcessorStorageConstructor {
|
||||
|
||||
case bw2(Ind, Ind): // MOVE.bw (An)[+], (An)[+]
|
||||
op(Action::None, seq("nr", { a(ea_register) }, !is_byte_access));
|
||||
op(Action::PerformOperation, seq("nw np", { a(destination_register) }, !is_byte_access));
|
||||
op(Action::PerformOperation, seq("nw np", { a(data_register) }, !is_byte_access));
|
||||
break;
|
||||
|
||||
case bw2(PreDec, Ind): // MOVE.bw -(An), (An)[+]
|
||||
op(dec(ea_register) | MicroOp::SourceMask, seq("n nr", { a(ea_register) }, !is_byte_access));
|
||||
op(Action::PerformOperation, seq("nw np", { a(destination_register) }, !is_byte_access));
|
||||
op(Action::PerformOperation, seq("nw np", { a(data_register) }, !is_byte_access));
|
||||
break;
|
||||
|
||||
case l2(d16An, Ind): // MOVE.bw (d16, An), (An)[+]
|
||||
@ -2754,7 +2797,7 @@ struct ProcessorStorageConstructor {
|
||||
op( address_action_for_mode(combined_source_mode) | MicroOp::SourceMask,
|
||||
seq(pseq("np nr", combined_source_mode), { ea(0) }, !is_byte_access));
|
||||
op( Action::PerformOperation,
|
||||
seq("nw np", { a(destination_register) }, !is_byte_access));
|
||||
seq("nw np", { a(data_register) }, !is_byte_access));
|
||||
break;
|
||||
|
||||
case l2(XXXl, Ind): // MOVE.l (xxx).l, (An)[+]
|
||||
@ -2775,7 +2818,7 @@ struct ProcessorStorageConstructor {
|
||||
|
||||
case bw2(Imm, Ind): // MOVE.bw #, (An)[+]
|
||||
storage_.instructions[instruction].source = &storage_.prefetch_queue_;
|
||||
op(Action::PerformOperation, seq("np nw np", { a(destination_register) }, !is_byte_access) );
|
||||
op(Action::PerformOperation, seq("np nw np", { a(data_register) }, !is_byte_access) );
|
||||
break;
|
||||
|
||||
//
|
||||
@ -2784,8 +2827,8 @@ struct ProcessorStorageConstructor {
|
||||
|
||||
case bw2(Dn, PreDec): // MOVE.bw [An/Dn], -(An)
|
||||
op(Action::PerformOperation);
|
||||
op( dec(destination_register) | MicroOp::DestinationMask,
|
||||
seq("np nw", { a(destination_register) }, !is_byte_access));
|
||||
op( dec(data_register) | MicroOp::DestinationMask,
|
||||
seq("np nw", { a(data_register) }, !is_byte_access));
|
||||
break;
|
||||
|
||||
case l2(Dn, PreDec): // MOVE.l [An/Dn], -(An)
|
||||
@ -2801,8 +2844,8 @@ struct ProcessorStorageConstructor {
|
||||
case bw2(PreDec, PreDec): // MOVE.bw -(An), -(An)
|
||||
op(dec(ea_register) | MicroOp::SourceMask, seq("n"));
|
||||
case bw2(Ind, PreDec): // MOVE.bw (An)[+], -(An)
|
||||
op(dec(destination_register) | MicroOp::DestinationMask, seq("nr", { a(ea_register) }, !is_byte_access));
|
||||
op(Action::PerformOperation, seq("np nw", { a(destination_register) }, !is_byte_access));
|
||||
op(dec(data_register) | MicroOp::DestinationMask, seq("nr", { a(ea_register) }, !is_byte_access));
|
||||
op(Action::PerformOperation, seq("np nw", { a(data_register) }, !is_byte_access));
|
||||
break;
|
||||
|
||||
case l2(PreDec, PreDec): // MOVE.l -(An), -(An)
|
||||
@ -2825,7 +2868,7 @@ struct ProcessorStorageConstructor {
|
||||
op( address_action_for_mode(combined_source_mode) | MicroOp::SourceMask,
|
||||
seq(pseq("np nr", combined_source_mode), { ea(0) }, !is_byte_access ));
|
||||
op(Action::PerformOperation);
|
||||
op(dec(destination_register) | MicroOp::DestinationMask, seq("np nw", { a(destination_register) }, !is_byte_access));
|
||||
op(dec(data_register) | MicroOp::DestinationMask, seq("np nw", { a(data_register) }, !is_byte_access));
|
||||
break;
|
||||
|
||||
case l2(XXXl, PreDec): // MOVE.l (xxx).w, -(An)
|
||||
@ -2846,7 +2889,7 @@ struct ProcessorStorageConstructor {
|
||||
case bw2(Imm, PreDec): // MOVE.bw #, -(An)
|
||||
op(int(Action::AssembleWordDataFromPrefetch) | MicroOp::SourceMask, seq("np"));
|
||||
op(Action::PerformOperation);
|
||||
op(dec(destination_register) | MicroOp::DestinationMask, seq("np nw", { a(destination_register) }, !is_byte_access));
|
||||
op(dec(data_register) | MicroOp::DestinationMask, seq("np nw", { a(data_register) }, !is_byte_access));
|
||||
break;
|
||||
|
||||
case l2(Imm, PreDec): // MOVE.l #, -(An)
|
||||
@ -3139,7 +3182,7 @@ struct ProcessorStorageConstructor {
|
||||
// If any post-incrementing was involved, do the post increment(s).
|
||||
if(ea_mode == PostInc || destination_mode == PostInc) {
|
||||
const int ea_inc = inc(ea_register);
|
||||
const int destination_inc = inc(destination_register);
|
||||
const int destination_inc = inc(data_register);
|
||||
|
||||
// If there are two increments, and both can be done simultaneously, do that.
|
||||
// Otherwise do one or two individually.
|
||||
|
@ -50,11 +50,13 @@ class ProcessorStorage {
|
||||
ADDQb, ADDQw, ADDQl,
|
||||
ADDAw, ADDAl,
|
||||
ADDQAw, ADDQAl,
|
||||
ADDXb, ADDXw, ADDXl,
|
||||
|
||||
SUBb, SUBw, SUBl,
|
||||
SUBQb, SUBQw, SUBQl,
|
||||
SUBAw, SUBAl,
|
||||
SUBQAw, SUBQAl,
|
||||
SUBXb, SUBXw, SUBXl,
|
||||
|
||||
MOVEb, MOVEw, MOVEl, MOVEq,
|
||||
MOVEAw, MOVEAl,
|
||||
|
Loading…
Reference in New Issue
Block a user