mirror of
https://github.com/TomHarte/CLK.git
synced 2024-11-22 12:33:29 +00:00
Capture and respond to IDIV_REP.
This commit is contained in:
parent
bf179e8933
commit
800c76a4fe
@ -33,7 +33,7 @@ std::pair<int, typename Decoder<model>::InstructionT> Decoder<model>::decode(con
|
||||
|
||||
/// Sets the operation and verifies that the current repetition, if any, is compatible, discarding it otherwise.
|
||||
#define SetOperation(op) \
|
||||
operation_ = rep_operation(op, repetition_);
|
||||
operation_ = rep_operation<model>(op, repetition_);
|
||||
|
||||
/// Helper macro for those that follow.
|
||||
#define SetOpSrcDestSize(op, src, dest, size) \
|
||||
|
@ -227,7 +227,7 @@ void div(
|
||||
destination_high = dividend % source;
|
||||
}
|
||||
|
||||
template <typename IntT, typename ContextT>
|
||||
template <bool invert, typename IntT, typename ContextT>
|
||||
void idiv(
|
||||
modify_t<IntT> destination_high,
|
||||
modify_t<IntT> destination_low,
|
||||
@ -279,7 +279,14 @@ void idiv(
|
||||
// TEMPORARY HACK. Will not work with DWords.
|
||||
using sIntT = typename std::make_signed<IntT>::type;
|
||||
const int32_t dividend = (sIntT(destination_high) << (8 * sizeof(IntT))) + destination_low;
|
||||
const auto result = dividend / sIntT(source);
|
||||
auto result = dividend / sIntT(source);
|
||||
|
||||
// An 8086 quirk: rep IDIV performs an IDIV that switches the sign on its result,
|
||||
// due to reuse of an internal flag.
|
||||
if constexpr (invert) {
|
||||
result = -result;
|
||||
}
|
||||
|
||||
if(sIntT(result) != result) {
|
||||
interrupt(Interrupt::DivideError, context);
|
||||
return;
|
||||
|
@ -210,7 +210,8 @@ template <
|
||||
case Operation::MUL: Primitive::mul<IntT>(pair_high(), pair_low(), source_r(), context); return;
|
||||
case Operation::IMUL_1: Primitive::imul<IntT>(pair_high(), pair_low(), source_r(), context); return;
|
||||
case Operation::DIV: Primitive::div<IntT>(pair_high(), pair_low(), source_r(), context); return;
|
||||
case Operation::IDIV: Primitive::idiv<IntT>(pair_high(), pair_low(), source_r(), context); return;
|
||||
case Operation::IDIV: Primitive::idiv<false, IntT>(pair_high(), pair_low(), source_r(), context); return;
|
||||
case Operation::IDIV_REP: Primitive::idiv<true, IntT>(pair_high(), pair_low(), source_r(), context); return;
|
||||
|
||||
case Operation::INC: Primitive::inc<IntT>(destination_rmw(), context); break;
|
||||
case Operation::DEC: Primitive::dec<IntT>(destination_rmw(), context); break;
|
||||
|
@ -113,6 +113,7 @@ std::string InstructionSet::x86::to_string(Operation operation, DataSize size, M
|
||||
case Operation::IMUL_1: return "imul";
|
||||
case Operation::DIV: return "div";
|
||||
case Operation::IDIV: return "idiv";
|
||||
case Operation::IDIV_REP: return "idiv";
|
||||
|
||||
case Operation::INC: return "inc";
|
||||
case Operation::DEC: return "dec";
|
||||
|
@ -231,6 +231,8 @@ enum class Operation: uint8_t {
|
||||
SETMOC,
|
||||
/// Set destination to ~0.
|
||||
SETMO,
|
||||
/// Perform an IDIV and negative the result.
|
||||
IDIV_REP,
|
||||
|
||||
//
|
||||
// 80186 additions.
|
||||
@ -474,8 +476,15 @@ enum class Repetition: uint8_t {
|
||||
};
|
||||
|
||||
/// @returns @c true if @c operation supports repetition mode @c repetition; @c false otherwise.
|
||||
template <Model model>
|
||||
constexpr Operation rep_operation(Operation operation, Repetition repetition) {
|
||||
switch(operation) {
|
||||
case Operation::IDIV:
|
||||
if constexpr (model == Model::i8086) {
|
||||
return repetition != Repetition::None ? Operation::IDIV_REP : Operation::IDIV;
|
||||
}
|
||||
[[fallthrough]];
|
||||
|
||||
default: return operation;
|
||||
|
||||
case Operation::INS:
|
||||
|
Loading…
Reference in New Issue
Block a user