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

Implements ASL, ASR, LSL and LSR.

This commit is contained in:
Thomas Harte 2019-04-10 22:31:04 -04:00
parent a07de97df4
commit 43f619a081
3 changed files with 93 additions and 56 deletions

View File

@ -53,16 +53,16 @@ template <class T, bool dtack_is_implicit> void Processor<T, dtack_is_implicit>:
// TODO: unless an interrupt is pending, or the trap flag is set.
const uint16_t next_instruction = prefetch_queue_.halves.high.full;
if(!instructions[next_instruction].micro_operations) {
decoded_instruction_ = prefetch_queue_.halves.high.full;
if(!instructions[decoded_instruction_].micro_operations) {
// TODO: once all instructions are implemnted, this should be an instruction error.
std::cerr << "68000 Abilities exhausted; can't manage instruction " << std::hex << next_instruction << " from " << (program_counter_.full - 4) << std::endl;
std::cerr << "68000 Abilities exhausted; can't manage instruction " << std::hex << decoded_instruction_ << " from " << (program_counter_.full - 4) << std::endl;
return;
} else {
std::cout << "Performing " << std::hex << next_instruction << " from " << (program_counter_.full - 4) << std::endl;
std::cout << "Performing " << std::hex << decoded_instruction_ << " from " << (program_counter_.full - 4) << std::endl;
}
active_program_ = &instructions[next_instruction];
active_program_ = &instructions[decoded_instruction_];
active_micro_op_ = active_program_->micro_operations;
}
@ -523,28 +523,51 @@ template <class T, bool dtack_is_implicit> void Processor<T, dtack_is_implicit>:
overflow_flag_ = (value ^ zero_result_) & m; \
extend_flag_ = carry_flag_ = value & t;
#define decode_shift_count() \
const int shift_count = (decoded_instruction_ & 32) ? data_[(decoded_instruction_ >> 9) & 7].full&63 : (decoded_instruction_ >> 9) & 7; \
active_step_->microcycle.length = HalfCycles(4 * shift_count);
#define set_flags_b(t) set_flags(active_program_->destination->halves.low.halves.low, 0x80, t)
#define set_flags_w(t) set_flags(active_program_->destination->halves.low.full, 0x8000, t)
#define set_flags_l(t) set_flags(active_program_->destination->full, 0x80000000, t)
case Operation::LSLm:
case Operation::ASLm: {
const auto value = active_program_->destination->halves.low.full;
active_program_->destination->halves.low.full <<= 1;
set_flags_w(0x8000);
} break;
#define shift_op(name, op, mb, mw, ml) \
case Operation::name##b: { \
decode_shift_count(); \
const auto value = active_program_->destination->halves.low.halves.low; \
op(active_program_->destination->halves.low.halves.low, shift_count, 0xff, 7); \
set_flags_b(mb); \
} break; \
\
case Operation::name##w: { \
decode_shift_count(); \
const auto value = active_program_->destination->halves.low.full; \
op(active_program_->destination->halves.low.full, shift_count, 0xffff, 15); \
set_flags_w(mw); \
} break; \
\
case Operation::name##l: { \
decode_shift_count(); \
const auto value = active_program_->destination->full; \
op(active_program_->destination->full, shift_count, 0xffffffff, 31); \
set_flags_l(ml); \
} break; \
\
case Operation::name##m: { \
const auto value = active_program_->destination->halves.low.full; \
op(active_program_->destination->halves.low.full, 1, 0xffff, 15); \
set_flags_w(mw); \
} break;
case Operation::LSRm: {
const auto value = active_program_->destination->halves.low.full;
active_program_->destination->halves.low.full >>= 1;
set_flags_w(0x0001);
} break;
#define lsl(x, c, m, d) x <<= c
#define lsr(x, c, m, d) x >>= c
#define asl(x, c, m, d) x <<= c
#define asr(x, c, m, d) x = (x >> c) | (((value >> d) & 1) * (m ^ (m >> c)))
case Operation::ASRm: {
const auto value = active_program_->destination->halves.low.full;
active_program_->destination->halves.low.full = (active_program_->destination->halves.low.full >> 1) | (value & 0x8000);
set_flags_w(0x0001);
} break;
shift_op(LSL, lsl, 0x80, 0x8000, 0x80000000);
shift_op(ASL, lsl, 0x80, 0x8000, 0x80000000);
shift_op(LSR, lsr, 0x01, 0x0001, 0x00000001);
shift_op(ASR, asr, 0x01, 0x0001, 0x00000001);
#undef set_flags
#define set_flags(v, m, t) \
@ -580,6 +603,7 @@ template <class T, bool dtack_is_implicit> void Processor<T, dtack_is_implicit>:
} break;
#undef set_flags
#undef decode_shift_count
#undef set_flags_b
#undef set_flags_w
#undef set_flags_l

View File

@ -59,6 +59,9 @@ struct ProcessorStorageConstructor {
* n: no operation for four cycles; data bus is not used;
* nn: no operation for eight cycles; data bus is not used;
* r: a 'replaceable'-length no operation; data bus is not used and no guarantees are
made about the length of the cycle other than that when it reaches the interpreter,
it is safe to alter the length and leave it altered;
* np: program fetch; reads from the PC and adds two to it, advancing the prefetch queue;
* nW: write MSW of something onto the bus;
* nw: write LSW of something onto the bus;
@ -121,10 +124,17 @@ struct ProcessorStorageConstructor {
// Do nothing (possibly twice).
if(token == "n" || token == "nn") {
steps.push_back(step);
if(token.size() == 2) {
steps.push_back(step);
step.microcycle.length = HalfCycles(8);
}
steps.push_back(step);
continue;
}
// Do nothing, but with a length that definitely won't map it to the other do-nothings.
if(token == "r"){
step.microcycle.length = HalfCycles(0);
steps.push_back(step);
continue;
}
@ -384,45 +394,45 @@ struct ProcessorStorageConstructor {
{0xffc0, 0x4640, Operation::NOTw, Decoder::CLRNEGNEGXNOT}, // 4-148 (p250)
{0xffc0, 0x4680, Operation::NOTl, Decoder::CLRNEGNEGXNOT}, // 4-148 (p250)
{0xf1d8, 0xe000, Operation::ASLb, Decoder::ASLRLSLRROLRROXLRr}, // 4-22 (p126)
{0xf1d8, 0xe040, Operation::ASLw, Decoder::ASLRLSLRROLRROXLRr}, // 4-22 (p126)
{0xf1d8, 0xe080, Operation::ASLl, Decoder::ASLRLSLRROLRROXLRr}, // 4-22 (p126)
{0xffc0, 0xe0c0, Operation::ASLm, Decoder::ASLRLSLRROLRROXLRm}, // 4-22 (p126)
{0xf1d8, 0xe100, Operation::ASLb, Decoder::ASLRLSLRROLRROXLRr}, // 4-22 (p126)
{0xf1d8, 0xe140, Operation::ASLw, Decoder::ASLRLSLRROLRROXLRr}, // 4-22 (p126)
{0xf1d8, 0xe180, Operation::ASLl, Decoder::ASLRLSLRROLRROXLRr}, // 4-22 (p126)
{0xffc0, 0xe1c0, Operation::ASLm, Decoder::ASLRLSLRROLRROXLRm}, // 4-22 (p126)
{0xf1d8, 0xe100, Operation::ASRb, Decoder::ASLRLSLRROLRROXLRr}, // 4-22 (p126)
{0xf1d8, 0xe140, Operation::ASRw, Decoder::ASLRLSLRROLRROXLRr}, // 4-22 (p126)
{0xf1d8, 0xe180, Operation::ASRl, Decoder::ASLRLSLRROLRROXLRr}, // 4-22 (p126)
{0xffc0, 0xe1c0, Operation::ASRm, Decoder::ASLRLSLRROLRROXLRm}, // 4-22 (p126)
{0xf1d8, 0xe000, Operation::ASRb, Decoder::ASLRLSLRROLRROXLRr}, // 4-22 (p126)
{0xf1d8, 0xe040, Operation::ASRw, Decoder::ASLRLSLRROLRROXLRr}, // 4-22 (p126)
{0xf1d8, 0xe080, Operation::ASRl, Decoder::ASLRLSLRROLRROXLRr}, // 4-22 (p126)
{0xffc0, 0xe0c0, Operation::ASRm, Decoder::ASLRLSLRROLRROXLRm}, // 4-22 (p126)
{0xf1d8, 0xe008, Operation::LSLb, Decoder::ASLRLSLRROLRROXLRr}, // 4-113 (p217)
{0xf1d8, 0xe048, Operation::LSLw, Decoder::ASLRLSLRROLRROXLRr}, // 4-113 (p217)
{0xf1d8, 0xe088, Operation::LSLl, Decoder::ASLRLSLRROLRROXLRr}, // 4-113 (p217)
{0xffc0, 0xe2c0, Operation::LSLm, Decoder::ASLRLSLRROLRROXLRm}, // 4-113 (p217)
{0xf1d8, 0xe108, Operation::LSLb, Decoder::ASLRLSLRROLRROXLRr}, // 4-113 (p217)
{0xf1d8, 0xe148, Operation::LSLw, Decoder::ASLRLSLRROLRROXLRr}, // 4-113 (p217)
{0xf1d8, 0xe188, Operation::LSLl, Decoder::ASLRLSLRROLRROXLRr}, // 4-113 (p217)
{0xffc0, 0xe3c0, Operation::LSLm, Decoder::ASLRLSLRROLRROXLRm}, // 4-113 (p217)
{0xf1d8, 0xe108, Operation::LSRb, Decoder::ASLRLSLRROLRROXLRr}, // 4-113 (p217)
{0xf1d8, 0xe148, Operation::LSRw, Decoder::ASLRLSLRROLRROXLRr}, // 4-113 (p217)
{0xf1d8, 0xe188, Operation::LSRl, Decoder::ASLRLSLRROLRROXLRr}, // 4-113 (p217)
{0xffc0, 0xe3c0, Operation::LSRm, Decoder::ASLRLSLRROLRROXLRm}, // 4-113 (p217)
{0xf1d8, 0xe008, Operation::LSRb, Decoder::ASLRLSLRROLRROXLRr}, // 4-113 (p217)
{0xf1d8, 0xe048, Operation::LSRw, Decoder::ASLRLSLRROLRROXLRr}, // 4-113 (p217)
{0xf1d8, 0xe088, Operation::LSRl, Decoder::ASLRLSLRROLRROXLRr}, // 4-113 (p217)
{0xffc0, 0xe2c0, Operation::LSRm, Decoder::ASLRLSLRROLRROXLRm}, // 4-113 (p217)
{0xf1d8, 0xe018, Operation::ROLb, Decoder::ASLRLSLRROLRROXLRr}, // 4-160 (p264)
{0xf1d8, 0xe058, Operation::ROLw, Decoder::ASLRLSLRROLRROXLRr}, // 4-160 (p264)
{0xf1d8, 0xe098, Operation::ROLl, Decoder::ASLRLSLRROLRROXLRr}, // 4-160 (p264)
{0xffc0, 0xe6c0, Operation::ROLm, Decoder::ASLRLSLRROLRROXLRm}, // 4-160 (p264)
{0xf1d8, 0xe118, Operation::ROLb, Decoder::ASLRLSLRROLRROXLRr}, // 4-160 (p264)
{0xf1d8, 0xe158, Operation::ROLw, Decoder::ASLRLSLRROLRROXLRr}, // 4-160 (p264)
{0xf1d8, 0xe198, Operation::ROLl, Decoder::ASLRLSLRROLRROXLRr}, // 4-160 (p264)
{0xffc0, 0xe7c0, Operation::ROLm, Decoder::ASLRLSLRROLRROXLRm}, // 4-160 (p264)
{0xf1d8, 0xe118, Operation::RORb, Decoder::ASLRLSLRROLRROXLRr}, // 4-160 (p264)
{0xf1d8, 0xe158, Operation::RORw, Decoder::ASLRLSLRROLRROXLRr}, // 4-160 (p264)
{0xf1d8, 0xe198, Operation::RORl, Decoder::ASLRLSLRROLRROXLRr}, // 4-160 (p264)
{0xffc0, 0xe7c0, Operation::RORm, Decoder::ASLRLSLRROLRROXLRm}, // 4-160 (p264)
{0xf1d8, 0xe018, Operation::RORb, Decoder::ASLRLSLRROLRROXLRr}, // 4-160 (p264)
{0xf1d8, 0xe058, Operation::RORw, Decoder::ASLRLSLRROLRROXLRr}, // 4-160 (p264)
{0xf1d8, 0xe098, Operation::RORl, Decoder::ASLRLSLRROLRROXLRr}, // 4-160 (p264)
{0xffc0, 0xe6c0, Operation::RORm, Decoder::ASLRLSLRROLRROXLRm}, // 4-160 (p264)
{0xf1d8, 0xe010, Operation::ROXLb, Decoder::ASLRLSLRROLRROXLRr}, // 4-163 (p267)
{0xf1d8, 0xe050, Operation::ROXLw, Decoder::ASLRLSLRROLRROXLRr}, // 4-163 (p267)
{0xf1d8, 0xe090, Operation::ROXLl, Decoder::ASLRLSLRROLRROXLRr}, // 4-163 (p267)
{0xffc0, 0xe4c0, Operation::ROXLm, Decoder::ASLRLSLRROLRROXLRm}, // 4-163 (p267)
{0xf1d8, 0xe110, Operation::ROXLb, Decoder::ASLRLSLRROLRROXLRr}, // 4-163 (p267)
{0xf1d8, 0xe150, Operation::ROXLw, Decoder::ASLRLSLRROLRROXLRr}, // 4-163 (p267)
{0xf1d8, 0xe190, Operation::ROXLl, Decoder::ASLRLSLRROLRROXLRr}, // 4-163 (p267)
{0xffc0, 0xe5c0, Operation::ROXLm, Decoder::ASLRLSLRROLRROXLRm}, // 4-163 (p267)
{0xf1d8, 0xe110, Operation::ROXRb, Decoder::ASLRLSLRROLRROXLRr}, // 4-163 (p267)
{0xf1d8, 0xe150, Operation::ROXRw, Decoder::ASLRLSLRROLRROXLRr}, // 4-163 (p267)
{0xf1d8, 0xe190, Operation::ROXRl, Decoder::ASLRLSLRROLRROXLRr}, // 4-163 (p267)
{0xffc0, 0xe5c0, Operation::ROXRm, Decoder::ASLRLSLRROLRROXLRm}, // 4-163 (p267)
{0xf1d8, 0xe010, Operation::ROXRb, Decoder::ASLRLSLRROLRROXLRr}, // 4-163 (p267)
{0xf1d8, 0xe050, Operation::ROXRw, Decoder::ASLRLSLRROLRROXLRr}, // 4-163 (p267)
{0xf1d8, 0xe090, Operation::ROXRl, Decoder::ASLRLSLRROLRROXLRr}, // 4-163 (p267)
{0xffc0, 0xe4c0, Operation::ROXRm, Decoder::ASLRLSLRROLRROXLRm}, // 4-163 (p267)
};
#ifndef NDEBUG
@ -928,7 +938,9 @@ struct ProcessorStorageConstructor {
} else {
op(Action::None, seq("np n"));
}
op(Action::PerformOperation);
// Use a no-op bus cycle that can have its length filled in later.
op(Action::PerformOperation, seq("r"));
} break;
case Decoder::ASLRLSLRROLRROXLRm: {

View File

@ -282,6 +282,7 @@ class ProcessorStorage {
Program *active_program_ = nullptr;
MicroOp *active_micro_op_ = nullptr;
BusStep *active_step_ = nullptr;
uint16_t decoded_instruction_;
/// Copies address_[7] to the proper stack pointer based on current mode.
void write_back_stack_pointer();