mirror of
https://github.com/TomHarte/CLK.git
synced 2024-12-26 09:29:45 +00:00
Attempts to correct flags for ASL, ASR, LSL, LSR.
This commit is contained in:
parent
dcb8176d90
commit
fa0accf251
@ -932,10 +932,6 @@ template <class T, bool dtack_is_implicit, bool signal_will_perform> void Proces
|
|||||||
negative_flag_ = zero_result_ & (m); \
|
negative_flag_ = zero_result_ & (m); \
|
||||||
overflow_flag_ = (value ^ zero_result_) & (m);
|
overflow_flag_ = (value ^ zero_result_) & (m);
|
||||||
|
|
||||||
#define set_flags(v, m, t) \
|
|
||||||
set_neg_zero_overflow(v, m) \
|
|
||||||
extend_flag_ = carry_flag_ = value & (t);
|
|
||||||
|
|
||||||
#define decode_shift_count() \
|
#define decode_shift_count() \
|
||||||
int shift_count = (decoded_instruction_ & 32) ? data_[(decoded_instruction_ >> 9) & 7].full&63 : ( ((decoded_instruction_ >> 9)&7) ? ((decoded_instruction_ >> 9)&7) : 8) ; \
|
int shift_count = (decoded_instruction_ & 32) ? data_[(decoded_instruction_ >> 9) & 7].full&63 : ( ((decoded_instruction_ >> 9)&7) ? ((decoded_instruction_ >> 9)&7) : 8) ; \
|
||||||
active_step_->microcycle.length = HalfCycles(4 * shift_count);
|
active_step_->microcycle.length = HalfCycles(4 * shift_count);
|
||||||
@ -944,45 +940,89 @@ template <class T, bool dtack_is_implicit, bool signal_will_perform> void Proces
|
|||||||
#define set_flags_w(t) set_flags(active_program_->destination->halves.low.full, 0x8000, 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)
|
#define set_flags_l(t) set_flags(active_program_->destination->full, 0x80000000, t)
|
||||||
|
|
||||||
#define shift_op(name, op, mb, mw, ml) \
|
#define lsl(destination, size) {\
|
||||||
case Operation::name##b: { \
|
|
||||||
decode_shift_count(); \
|
decode_shift_count(); \
|
||||||
const auto value = active_program_->destination->halves.low.halves.low; \
|
const auto value = destination; \
|
||||||
op(active_program_->destination->halves.low.halves.low, shift_count, 0xff, 7); \
|
|
||||||
set_flags_b(mb); \
|
|
||||||
} break; \
|
|
||||||
\
|
\
|
||||||
case Operation::name##w: { \
|
if(!shift_count) { \
|
||||||
decode_shift_count(); \
|
carry_flag_ = 0; \
|
||||||
const auto value = active_program_->destination->halves.low.full; \
|
} else { \
|
||||||
op(active_program_->destination->halves.low.full, shift_count, 0xffff, 15); \
|
destination = value << shift_count; \
|
||||||
set_flags_w(mw); \
|
extend_flag_ = carry_flag_ = value & ((1 << (size - 1)) >> (shift_count - 1)); \
|
||||||
} break; \
|
} \
|
||||||
\
|
\
|
||||||
case Operation::name##l: { \
|
set_neg_zero_overflow(destination, 1 << (size - 1)); \
|
||||||
decode_shift_count(); \
|
}
|
||||||
const auto value = active_program_->destination->full; \
|
|
||||||
op(active_program_->destination->full, shift_count, 0xffffffff, 31); \
|
case Operation::ASLm:
|
||||||
set_flags_l(ml); \
|
case Operation::LSLm: {
|
||||||
} break; \
|
const auto value = active_program_->destination->halves.low.full;
|
||||||
\
|
active_program_->destination->halves.low.full = value >> 1;
|
||||||
case Operation::name##m: { \
|
extend_flag_ = carry_flag_ = value & 1;
|
||||||
const auto value = active_program_->destination->halves.low.full; \
|
set_neg_zero_overflow(active_program_->destination->halves.low.full, 0x8000);
|
||||||
op(active_program_->destination->halves.low.full, 1, 0xffff, 15); \
|
|
||||||
set_flags_w(mw); \
|
|
||||||
} break;
|
} break;
|
||||||
|
case Operation::ASLb:
|
||||||
|
case Operation::LSLb: lsl(active_program_->destination->halves.low.halves.low, 8); break;
|
||||||
|
case Operation::ASLw:
|
||||||
|
case Operation::LSLw: lsl(active_program_->destination->halves.low.full, 16); break;
|
||||||
|
case Operation::ASLl:
|
||||||
|
case Operation::LSLl: lsl(active_program_->destination->full, 32); break;
|
||||||
|
|
||||||
#define lsl(x, c, m, d) x <<= c
|
#undef lsl
|
||||||
#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)))
|
|
||||||
|
|
||||||
// TODO: carry/extend is incorrect for shifts of greater than one digit.
|
#define lsr(destination, size) {\
|
||||||
|
decode_shift_count(); \
|
||||||
|
const auto value = destination; \
|
||||||
|
\
|
||||||
|
if(!shift_count) { \
|
||||||
|
carry_flag_ = 0; \
|
||||||
|
} else { \
|
||||||
|
destination = value >> shift_count; \
|
||||||
|
extend_flag_ = carry_flag_ = value & (1 << (shift_count - 1)); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
set_neg_zero_overflow(destination, 1 << (size - 1)); \
|
||||||
|
}
|
||||||
|
|
||||||
shift_op(LSL, lsl, 0x80, 0x8000, 0x80000000);
|
case Operation::LSRm: {
|
||||||
shift_op(ASL, lsl, 0x80, 0x8000, 0x80000000);
|
const auto value = active_program_->destination->halves.low.full;
|
||||||
shift_op(LSR, lsr, 0x01, 0x0001, 0x00000001);
|
active_program_->destination->halves.low.full = value >> 1;
|
||||||
shift_op(ASR, asr, 0x01, 0x0001, 0x00000001);
|
extend_flag_ = carry_flag_ = value & 1;
|
||||||
|
set_neg_zero_overflow(active_program_->destination->halves.low.full, 0x8000);
|
||||||
|
} break;
|
||||||
|
case Operation::LSRb: lsr(active_program_->destination->halves.low.halves.low, 8); break;
|
||||||
|
case Operation::LSRw: lsr(active_program_->destination->halves.low.full, 16); break;
|
||||||
|
case Operation::LSRl: lsr(active_program_->destination->full, 32); break;
|
||||||
|
|
||||||
|
#undef lsr
|
||||||
|
|
||||||
|
#define asr(destination, size) {\
|
||||||
|
decode_shift_count(); \
|
||||||
|
const auto value = destination; \
|
||||||
|
\
|
||||||
|
if(!shift_count) { \
|
||||||
|
carry_flag_ = 0; \
|
||||||
|
} else { \
|
||||||
|
destination = \
|
||||||
|
(value >> shift_count) | \
|
||||||
|
((value & (1 << (size - 1)) ? 0xffffffff : 0x000000000) << (size - shift_count)); \
|
||||||
|
extend_flag_ = carry_flag_ = value & (1 << (shift_count - 1)); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
set_neg_zero_overflow(destination, 1 << (size - 1)); \
|
||||||
|
}
|
||||||
|
|
||||||
|
case Operation::ASRm: {
|
||||||
|
const auto value = active_program_->destination->halves.low.full;
|
||||||
|
active_program_->destination->halves.low.full = (value&0x80) | (value >> 1);
|
||||||
|
extend_flag_ = carry_flag_ = value & 1;
|
||||||
|
set_neg_zero_overflow(active_program_->destination->halves.low.full, 0x8000);
|
||||||
|
} break;
|
||||||
|
case Operation::ASRb: asr(active_program_->destination->halves.low.halves.low, 8); break;
|
||||||
|
case Operation::ASRw: asr(active_program_->destination->halves.low.full, 16); break;
|
||||||
|
case Operation::ASRl: asr(active_program_->destination->full, 32); break;
|
||||||
|
|
||||||
|
#undef asr
|
||||||
|
|
||||||
#undef set_flags
|
#undef set_flags
|
||||||
#define set_flags(v, m, t) \
|
#define set_flags(v, m, t) \
|
||||||
|
Loading…
Reference in New Issue
Block a user