mirror of
https://github.com/TomHarte/CLK.git
synced 2025-02-18 16:30:29 +00:00
Add ADC and ADD.
This commit is contained in:
parent
09b2cfad8a
commit
15acb1fc7c
@ -9,10 +9,51 @@
|
|||||||
#ifndef PerformImplementation_h
|
#ifndef PerformImplementation_h
|
||||||
#define PerformImplementation_h
|
#define PerformImplementation_h
|
||||||
|
|
||||||
|
#include "../../../Numeric/Carry.hpp"
|
||||||
|
|
||||||
namespace InstructionSet::x86 {
|
namespace InstructionSet::x86 {
|
||||||
|
|
||||||
namespace Primitive {
|
namespace Primitive {
|
||||||
|
|
||||||
|
//
|
||||||
|
// BEGIN TEMPORARY COPY AND PASTE SECTION.
|
||||||
|
//
|
||||||
|
// The following are largely excised from the M68k PerformImplementation.hpp; if there proves to be no
|
||||||
|
// reason further to specialise them, there'll be a factoring out. In some cases I've tightened the documentation.
|
||||||
|
//
|
||||||
|
|
||||||
|
/// @returns An int of type @c IntT with only the most-significant bit set.
|
||||||
|
template <typename IntT> constexpr IntT top_bit() {
|
||||||
|
static_assert(!std::numeric_limits<IntT>::is_signed);
|
||||||
|
constexpr IntT max = std::numeric_limits<IntT>::max();
|
||||||
|
return max - (max >> 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @returns The number of bits in @c IntT.
|
||||||
|
template <typename IntT> constexpr int bit_size() {
|
||||||
|
return sizeof(IntT) * 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @returns An int with the top bit indicating whether overflow occurred during the calculation of
|
||||||
|
/// • @c lhs + @c rhs (if @c is_add is true); or
|
||||||
|
/// • @c lhs - @c rhs (if @c is_add is false)
|
||||||
|
/// and the result was @c result. All other bits will be clear.
|
||||||
|
template <bool is_add, typename IntT>
|
||||||
|
IntT overflow(IntT lhs, IntT rhs, IntT result) {
|
||||||
|
const IntT output_changed = result ^ rhs;
|
||||||
|
const IntT input_differed = lhs ^ rhs;
|
||||||
|
|
||||||
|
if constexpr (is_add) {
|
||||||
|
return top_bit<IntT>() & output_changed & ~input_differed;
|
||||||
|
} else {
|
||||||
|
return top_bit<IntT>() & output_changed & input_differed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// END COPY AND PASTE SECTION.
|
||||||
|
//
|
||||||
|
|
||||||
void aaa(CPU::RegisterPair16 &ax, Status &status) {
|
void aaa(CPU::RegisterPair16 &ax, Status &status) {
|
||||||
/*
|
/*
|
||||||
IF ((AL AND 0FH) > 9) OR (AF = 1)
|
IF ((AL AND 0FH) > 9) OR (AF = 1)
|
||||||
@ -101,6 +142,42 @@ void aas(CPU::RegisterPair16 &ax, Status &status) {
|
|||||||
ax.halves.low &= 0x0f;
|
ax.halves.low &= 0x0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename IntT>
|
||||||
|
void adc(IntT &destination, IntT source, Status &status) {
|
||||||
|
/*
|
||||||
|
DEST ← DEST + SRC + CF;
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
The OF, SF, ZF, AF, CF, and PF flags are set according to the result.
|
||||||
|
*/
|
||||||
|
const IntT result = destination + source + status.carry_bit<IntT>();
|
||||||
|
|
||||||
|
status.carry = Numeric::carried_out<bit_size<IntT>() - 1>(destination, source, result);
|
||||||
|
status.auxiliary_carry = Numeric::carried_in<4>(destination, source, result);
|
||||||
|
status.sign = status.zero = status.parity = result;
|
||||||
|
status.overflow = overflow<true, IntT>(destination, source, result);
|
||||||
|
|
||||||
|
destination = result;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename IntT>
|
||||||
|
void add(IntT &destination, IntT source, Status &status) {
|
||||||
|
/*
|
||||||
|
DEST ← DEST + SRC;
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
The OF, SF, ZF, AF, CF, and PF flags are set according to the result.
|
||||||
|
*/
|
||||||
|
const IntT result = destination + source;
|
||||||
|
|
||||||
|
status.carry = Numeric::carried_out<bit_size<IntT>() - 1>(destination, source, result);
|
||||||
|
status.auxiliary_carry = Numeric::carried_in<4>(destination, source, result);
|
||||||
|
status.sign = status.zero = status.parity = result;
|
||||||
|
status.overflow = overflow<true, IntT>(destination, source, result);
|
||||||
|
|
||||||
|
destination = result;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <
|
template <
|
||||||
@ -119,6 +196,21 @@ template <
|
|||||||
case Operation::AAD: Primitive::aad(destination, source.halves.low, status); break;
|
case Operation::AAD: Primitive::aad(destination, source.halves.low, status); break;
|
||||||
case Operation::AAM: Primitive::aam(destination, source.halves.low, status); break;
|
case Operation::AAM: Primitive::aam(destination, source.halves.low, status); break;
|
||||||
case Operation::AAS: Primitive::aas(destination, status); break;
|
case Operation::AAS: Primitive::aas(destination, status); break;
|
||||||
|
|
||||||
|
case Operation::ADC:
|
||||||
|
static_assert(operation != Operation::ADC || data_size == DataSize::Byte || data_size == DataSize::Word);
|
||||||
|
switch(data_size) {
|
||||||
|
case DataSize::Byte: Primitive::adc(destination.halves.low, source.halves.low, status); break;
|
||||||
|
case DataSize::Word: Primitive::adc(destination.full, source.full, status); break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case Operation::ADD:
|
||||||
|
static_assert(operation != Operation::ADD || data_size == DataSize::Byte || data_size == DataSize::Word);
|
||||||
|
switch(data_size) {
|
||||||
|
case DataSize::Byte: Primitive::add(destination.halves.low, source.halves.low, status); break;
|
||||||
|
case DataSize::Word: Primitive::add(destination.full, source.full, status); break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
(void)flow_controller;
|
(void)flow_controller;
|
||||||
|
@ -58,12 +58,16 @@ struct Status {
|
|||||||
uint32_t carry;
|
uint32_t carry;
|
||||||
uint32_t auxiliary_carry;
|
uint32_t auxiliary_carry;
|
||||||
uint32_t sign;
|
uint32_t sign;
|
||||||
|
uint32_t overflow;
|
||||||
|
|
||||||
// Zero => set; non-zero => unset.
|
// Zero => set; non-zero => unset.
|
||||||
uint32_t zero;
|
uint32_t zero;
|
||||||
|
|
||||||
// Odd number of bits => set; even => unset.
|
// Odd number of bits => set; even => unset.
|
||||||
uint32_t parity;
|
uint32_t parity;
|
||||||
|
|
||||||
|
// Convenience getters.
|
||||||
|
template <typename IntT> IntT carry_bit() { return carry ? 1 : 0; }
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -197,7 +197,7 @@ constexpr char TestSuiteHome[] = "/Users/tharte/Projects/ProcessorTests/8088/v1"
|
|||||||
|
|
||||||
InstructionSet::x86::perform<
|
InstructionSet::x86::perform<
|
||||||
InstructionSet::x86::Model::i8086,
|
InstructionSet::x86::Model::i8086,
|
||||||
InstructionSet::x86::Operation::AAD,
|
InstructionSet::x86::Operation::ADD,
|
||||||
InstructionSet::x86::DataSize::Byte
|
InstructionSet::x86::DataSize::Byte
|
||||||
>(
|
>(
|
||||||
dest,
|
dest,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user