mirror of
https://github.com/TomHarte/CLK.git
synced 2025-02-16 18:30:32 +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.
|
/// Sets the operation and verifies that the current repetition, if any, is compatible, discarding it otherwise.
|
||||||
#define SetOperation(op) \
|
#define SetOperation(op) \
|
||||||
operation_ = rep_operation(op, repetition_);
|
operation_ = rep_operation<model>(op, repetition_);
|
||||||
|
|
||||||
/// Helper macro for those that follow.
|
/// Helper macro for those that follow.
|
||||||
#define SetOpSrcDestSize(op, src, dest, size) \
|
#define SetOpSrcDestSize(op, src, dest, size) \
|
||||||
|
@ -227,7 +227,7 @@ void div(
|
|||||||
destination_high = dividend % source;
|
destination_high = dividend % source;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename IntT, typename ContextT>
|
template <bool invert, typename IntT, typename ContextT>
|
||||||
void idiv(
|
void idiv(
|
||||||
modify_t<IntT> destination_high,
|
modify_t<IntT> destination_high,
|
||||||
modify_t<IntT> destination_low,
|
modify_t<IntT> destination_low,
|
||||||
@ -279,7 +279,14 @@ void idiv(
|
|||||||
// TEMPORARY HACK. Will not work with DWords.
|
// TEMPORARY HACK. Will not work with DWords.
|
||||||
using sIntT = typename std::make_signed<IntT>::type;
|
using sIntT = typename std::make_signed<IntT>::type;
|
||||||
const int32_t dividend = (sIntT(destination_high) << (8 * sizeof(IntT))) + destination_low;
|
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) {
|
if(sIntT(result) != result) {
|
||||||
interrupt(Interrupt::DivideError, context);
|
interrupt(Interrupt::DivideError, context);
|
||||||
return;
|
return;
|
||||||
|
@ -207,10 +207,11 @@ template <
|
|||||||
Primitive::test<IntT>(destination_r(), source_r(), context);
|
Primitive::test<IntT>(destination_r(), source_r(), context);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case Operation::MUL: Primitive::mul<IntT>(pair_high(), pair_low(), source_r(), context); return;
|
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::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::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::INC: Primitive::inc<IntT>(destination_rmw(), context); break;
|
||||||
case Operation::DEC: Primitive::dec<IntT>(destination_rmw(), context); break;
|
case Operation::DEC: Primitive::dec<IntT>(destination_rmw(), context); break;
|
||||||
|
@ -105,14 +105,15 @@ std::string InstructionSet::x86::to_string(Operation operation, DataSize size, M
|
|||||||
case Operation::HLT: return "hlt";
|
case Operation::HLT: return "hlt";
|
||||||
case Operation::WAIT: return "wait";
|
case Operation::WAIT: return "wait";
|
||||||
|
|
||||||
case Operation::ADC: return "adc";
|
case Operation::ADC: return "adc";
|
||||||
case Operation::ADD: return "add";
|
case Operation::ADD: return "add";
|
||||||
case Operation::SBB: return "sbb";
|
case Operation::SBB: return "sbb";
|
||||||
case Operation::SUB: return "sub";
|
case Operation::SUB: return "sub";
|
||||||
case Operation::MUL: return "mul";
|
case Operation::MUL: return "mul";
|
||||||
case Operation::IMUL_1: return "imul";
|
case Operation::IMUL_1: return "imul";
|
||||||
case Operation::DIV: return "div";
|
case Operation::DIV: return "div";
|
||||||
case Operation::IDIV: return "idiv";
|
case Operation::IDIV: return "idiv";
|
||||||
|
case Operation::IDIV_REP: return "idiv";
|
||||||
|
|
||||||
case Operation::INC: return "inc";
|
case Operation::INC: return "inc";
|
||||||
case Operation::DEC: return "dec";
|
case Operation::DEC: return "dec";
|
||||||
|
@ -231,6 +231,8 @@ enum class Operation: uint8_t {
|
|||||||
SETMOC,
|
SETMOC,
|
||||||
/// Set destination to ~0.
|
/// Set destination to ~0.
|
||||||
SETMO,
|
SETMO,
|
||||||
|
/// Perform an IDIV and negative the result.
|
||||||
|
IDIV_REP,
|
||||||
|
|
||||||
//
|
//
|
||||||
// 80186 additions.
|
// 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.
|
/// @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) {
|
constexpr Operation rep_operation(Operation operation, Repetition repetition) {
|
||||||
switch(operation) {
|
switch(operation) {
|
||||||
|
case Operation::IDIV:
|
||||||
|
if constexpr (model == Model::i8086) {
|
||||||
|
return repetition != Repetition::None ? Operation::IDIV_REP : Operation::IDIV;
|
||||||
|
}
|
||||||
|
[[fallthrough]];
|
||||||
|
|
||||||
default: return operation;
|
default: return operation;
|
||||||
|
|
||||||
case Operation::INS:
|
case Operation::INS:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user