1
0
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:
Thomas Harte 2023-11-09 11:55:04 -05:00
parent bf179e8933
commit 800c76a4fe
5 changed files with 33 additions and 15 deletions

View File

@ -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) \

View File

@ -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;

View File

@ -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;

View File

@ -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";

View File

@ -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: