mirror of
https://github.com/TomHarte/CLK.git
synced 2025-02-19 23:29:05 +00:00
Attempts RO{X}[L/R].
This commit is contained in:
parent
84f4a25bc9
commit
892476973b
@ -678,14 +678,17 @@ template <class T, bool dtack_is_implicit> void Processor<T, dtack_is_implicit>:
|
|||||||
/*
|
/*
|
||||||
Shifts and rotates.
|
Shifts and rotates.
|
||||||
*/
|
*/
|
||||||
|
#define set_neg_zero_overflow(v, m) \
|
||||||
|
zero_result_ = (v); \
|
||||||
|
negative_flag_ = zero_result_ & (m); \
|
||||||
|
overflow_flag_ = (value ^ zero_result_) & (m);
|
||||||
|
|
||||||
#define set_flags(v, m, t) \
|
#define set_flags(v, m, t) \
|
||||||
zero_result_ = v; \
|
set_neg_zero_overflow(v, m) \
|
||||||
negative_flag_ = zero_result_ & m; \
|
extend_flag_ = carry_flag_ = value & (t);
|
||||||
overflow_flag_ = (value ^ zero_result_) & m; \
|
|
||||||
extend_flag_ = carry_flag_ = value & t;
|
|
||||||
|
|
||||||
#define decode_shift_count() \
|
#define decode_shift_count() \
|
||||||
const 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);
|
||||||
|
|
||||||
#define set_flags_b(t) set_flags(active_program_->destination->halves.low.halves.low, 0x80, t)
|
#define set_flags_b(t) set_flags(active_program_->destination->halves.low.halves.low, 0x80, t)
|
||||||
@ -725,6 +728,8 @@ template <class T, bool dtack_is_implicit> void Processor<T, dtack_is_implicit>:
|
|||||||
#define asl(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)))
|
#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.
|
||||||
|
|
||||||
shift_op(LSL, lsl, 0x80, 0x8000, 0x80000000);
|
shift_op(LSL, lsl, 0x80, 0x8000, 0x80000000);
|
||||||
shift_op(ASL, lsl, 0x80, 0x8000, 0x80000000);
|
shift_op(ASL, lsl, 0x80, 0x8000, 0x80000000);
|
||||||
shift_op(LSR, lsr, 0x01, 0x0001, 0x00000001);
|
shift_op(LSR, lsr, 0x01, 0x0001, 0x00000001);
|
||||||
@ -733,41 +738,134 @@ template <class T, bool dtack_is_implicit> void Processor<T, dtack_is_implicit>:
|
|||||||
#undef set_flags
|
#undef set_flags
|
||||||
#define set_flags(v, m, t) \
|
#define set_flags(v, m, t) \
|
||||||
zero_result_ = v; \
|
zero_result_ = v; \
|
||||||
negative_flag_ = zero_result_ & m; \
|
negative_flag_ = zero_result_ & (m); \
|
||||||
overflow_flag_ = 0; \
|
overflow_flag_ = 0; \
|
||||||
carry_flag_ = value & t;
|
carry_flag_ = value & (t);
|
||||||
|
|
||||||
|
#define rol(destination, size) { \
|
||||||
|
decode_shift_count(); \
|
||||||
|
const auto value = destination; \
|
||||||
|
\
|
||||||
|
if(!shift_count) { \
|
||||||
|
carry_flag_ = 0; \
|
||||||
|
} else { \
|
||||||
|
shift_count &= (size - 1); \
|
||||||
|
destination = \
|
||||||
|
(value << shift_count) | \
|
||||||
|
(value >> (size - shift_count)); \
|
||||||
|
carry_flag_ = destination & 1; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
set_neg_zero_overflow(destination, 1 << (size - 1)); \
|
||||||
|
}
|
||||||
|
|
||||||
case Operation::ROLm: {
|
case Operation::ROLm: {
|
||||||
const auto value = active_program_->destination->halves.low.full;
|
const auto value = active_program_->destination->halves.low.full;
|
||||||
active_program_->destination->halves.low.full = (active_program_->destination->halves.low.full << 1) | (value >> 15);
|
active_program_->destination->halves.low.full = (value << 1) | (value >> 15);
|
||||||
set_flags_w(0x8000);
|
carry_flag_ = active_program_->destination->halves.low.full & 1;
|
||||||
|
set_neg_zero_overflow(active_program_->destination->halves.low.full, 0x8000);
|
||||||
} break;
|
} break;
|
||||||
|
case Operation::ROLb: rol(active_program_->destination->halves.low.halves.low, 8); break;
|
||||||
|
case Operation::ROLw: rol(active_program_->destination->halves.low.full, 16); break;
|
||||||
|
case Operation::ROLl: rol(active_program_->destination->full, 32); break;
|
||||||
|
|
||||||
|
#undef rol
|
||||||
|
|
||||||
|
#define ror(destination, size) { \
|
||||||
|
decode_shift_count(); \
|
||||||
|
const auto value = destination; \
|
||||||
|
\
|
||||||
|
if(!shift_count) { \
|
||||||
|
carry_flag_ = 0; \
|
||||||
|
} else { \
|
||||||
|
shift_count &= (size - 1); \
|
||||||
|
destination = \
|
||||||
|
(value >> shift_count) | \
|
||||||
|
(value << (size - shift_count)); \
|
||||||
|
carry_flag_ = destination & (1 << (size - 1)); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
set_neg_zero_overflow(destination, 1 << (size - 1)); \
|
||||||
|
}
|
||||||
|
|
||||||
case Operation::RORm: {
|
case Operation::RORm: {
|
||||||
const auto value = active_program_->destination->halves.low.full;
|
const auto value = active_program_->destination->halves.low.full;
|
||||||
active_program_->destination->halves.low.full = (active_program_->destination->halves.low.full >> 1) | (value << 15);
|
active_program_->destination->halves.low.full = (value >> 1) | (value << 15);
|
||||||
set_flags_w(0x0001);
|
carry_flag_ = active_program_->destination->halves.low.full & 0x8000;
|
||||||
|
set_neg_zero_overflow(active_program_->destination->halves.low.full, 0x8000);
|
||||||
} break;
|
} break;
|
||||||
|
case Operation::RORb: ror(active_program_->destination->halves.low.halves.low, 8); break;
|
||||||
|
case Operation::RORw: ror(active_program_->destination->halves.low.full, 16); break;
|
||||||
|
case Operation::RORl: ror(active_program_->destination->full, 32); break;
|
||||||
|
|
||||||
|
#undef ror
|
||||||
|
|
||||||
|
#define roxl(destination, size) { \
|
||||||
|
decode_shift_count(); \
|
||||||
|
const auto value = destination; \
|
||||||
|
\
|
||||||
|
if(!shift_count) { \
|
||||||
|
carry_flag_ = extend_flag_; \
|
||||||
|
} else { \
|
||||||
|
shift_count %= (size + 1); \
|
||||||
|
destination = \
|
||||||
|
(value << shift_count) | \
|
||||||
|
(value >> (size + 1 - shift_count)) | \
|
||||||
|
((extend_flag_ ? (1 << (size - 1)) : 0) >> (size - shift_count)); \
|
||||||
|
carry_flag_ = extend_flag_ = destination & 1; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
set_neg_zero_overflow(destination, 1 << (size - 1)); \
|
||||||
|
}
|
||||||
|
|
||||||
case Operation::ROXLm: {
|
case Operation::ROXLm: {
|
||||||
const auto value = active_program_->destination->halves.low.full;
|
const auto value = active_program_->destination->halves.low.full;
|
||||||
active_program_->destination->halves.low.full = (active_program_->destination->halves.low.full << 1) | (extend_flag_ ? 0x0001 : 0x0000);
|
active_program_->destination->halves.low.full = (value << 1) | (extend_flag_ ? 0x0001 : 0x0000);
|
||||||
extend_flag_ = value & 0x8000;
|
extend_flag_ = value & 0x8000;
|
||||||
set_flags_w(0x8000);
|
set_flags_w(0x8000);
|
||||||
} break;
|
} break;
|
||||||
|
case Operation::ROXLb: roxl(active_program_->destination->halves.low.halves.low, 8); break;
|
||||||
|
case Operation::ROXLw: roxl(active_program_->destination->halves.low.full, 16); break;
|
||||||
|
case Operation::ROXLl: roxl(active_program_->destination->full, 32); break;
|
||||||
|
|
||||||
|
#undef roxl
|
||||||
|
|
||||||
|
#define roxr(destination, size) { \
|
||||||
|
decode_shift_count(); \
|
||||||
|
const auto value = destination; \
|
||||||
|
\
|
||||||
|
if(!shift_count) { \
|
||||||
|
carry_flag_ = extend_flag_; \
|
||||||
|
} else { \
|
||||||
|
shift_count %= (size + 1); \
|
||||||
|
destination = \
|
||||||
|
(value >> shift_count) | \
|
||||||
|
(value << (size + 1 - shift_count)) | \
|
||||||
|
((extend_flag_ ? 1 : 0) << (size - shift_count)); \
|
||||||
|
carry_flag_ = extend_flag_ = destination & 1; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
set_neg_zero_overflow(destination, 1 << (size - 1)); \
|
||||||
|
}
|
||||||
|
|
||||||
case Operation::ROXRm: {
|
case Operation::ROXRm: {
|
||||||
const auto value = active_program_->destination->halves.low.full;
|
const auto value = active_program_->destination->halves.low.full;
|
||||||
active_program_->destination->halves.low.full = (active_program_->destination->halves.low.full >> 1) | (extend_flag_ ? 0x8000 : 0x0000);
|
active_program_->destination->halves.low.full = (value >> 1) | (extend_flag_ ? 0x8000 : 0x0000);
|
||||||
extend_flag_ = value & 0x0001;
|
extend_flag_ = value & 0x0001;
|
||||||
set_flags_w(0x0001);
|
set_flags_w(0x0001);
|
||||||
} break;
|
} break;
|
||||||
|
case Operation::ROXRb: roxr(active_program_->destination->halves.low.halves.low, 8); break;
|
||||||
|
case Operation::ROXRw: roxr(active_program_->destination->halves.low.full, 16); break;
|
||||||
|
case Operation::ROXRl: roxr(active_program_->destination->full, 32); break;
|
||||||
|
|
||||||
|
#undef roxr
|
||||||
|
|
||||||
#undef set_flags
|
#undef set_flags
|
||||||
#undef decode_shift_count
|
#undef decode_shift_count
|
||||||
#undef set_flags_b
|
#undef set_flags_b
|
||||||
#undef set_flags_w
|
#undef set_flags_w
|
||||||
#undef set_flags_l
|
#undef set_flags_l
|
||||||
|
#undef set_neg_zero_overflow
|
||||||
|
|
||||||
/*
|
/*
|
||||||
TSTs: compare to zero.
|
TSTs: compare to zero.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user