1
0
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:
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. /// 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) \

View File

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

View File

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

View File

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

View File

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