1
0
mirror of https://github.com/TomHarte/CLK.git synced 2025-02-19 23:29:05 +00:00

Standardise repetitive sign/zero/parity sets.

This commit is contained in:
Thomas Harte 2023-10-11 11:15:59 -04:00
parent fbd647080d
commit 033ba75376
2 changed files with 67 additions and 64 deletions

View File

@ -198,8 +198,7 @@ inline void aad(CPU::RegisterPair16 &ax, uint8_t imm, Status &status) {
*/ */
ax.halves.low = ax.halves.low + (ax.halves.high * imm); ax.halves.low = ax.halves.low + (ax.halves.high * imm);
ax.halves.high = 0; ax.halves.high = 0;
status.sign = ax.halves.low & 0x80; status.set_from<uint8_t, Flag::Zero, Flag::Sign, Flag::ParityOdd>(ax.halves.low);
status.parity = status.zero = ax.halves.low;
} }
template <typename FlowControllerT> template <typename FlowControllerT>
@ -223,8 +222,7 @@ inline void aam(CPU::RegisterPair16 &ax, uint8_t imm, Status &status, FlowContro
ax.halves.high = ax.halves.low / imm; ax.halves.high = ax.halves.low / imm;
ax.halves.low = ax.halves.low % imm; ax.halves.low = ax.halves.low % imm;
status.sign = ax.halves.low & 0x80; status.set_from<uint8_t, Flag::Zero, Flag::Sign, Flag::ParityOdd>(ax.halves.low);
status.parity = status.zero = ax.halves.low;
} }
inline void aas(CPU::RegisterPair16 &ax, Status &status) { inline void aas(CPU::RegisterPair16 &ax, Status &status) {
@ -303,8 +301,7 @@ inline void daa(uint8_t &al, Status &status) {
status.carry = 0; status.carry = 0;
} }
status.sign = al & 0x80; status.set_from<uint8_t, Flag::Zero, Flag::Sign, Flag::ParityOdd>(al);
status.zero = status.parity = al;
} }
inline void das(uint8_t &al, Status &status) { inline void das(uint8_t &al, Status &status) {
@ -355,8 +352,7 @@ inline void das(uint8_t &al, Status &status) {
status.carry = 0; status.carry = 0;
} }
status.sign = al & 0x80; status.set_from<uint8_t, Flag::Zero, Flag::Sign, Flag::ParityOdd>(al);
status.zero = status.parity = al;
} }
template <bool with_carry, typename IntT> template <bool with_carry, typename IntT>
@ -371,10 +367,10 @@ void add(IntT &destination, IntT source, Status &status) {
status.carry = Numeric::carried_out<true, Numeric::bit_size<IntT>() - 1>(destination, source, result); status.carry = Numeric::carried_out<true, Numeric::bit_size<IntT>() - 1>(destination, source, result);
status.auxiliary_carry = Numeric::carried_in<4>(destination, source, result); status.auxiliary_carry = Numeric::carried_in<4>(destination, source, result);
status.sign = result & Numeric::top_bit<IntT>();
status.zero = status.parity = result;
status.overflow = Numeric::overflow<true, IntT>(destination, source, result); status.overflow = Numeric::overflow<true, IntT>(destination, source, result);
status.set_from<IntT, Flag::Zero, Flag::Sign, Flag::ParityOdd>(result);
destination = result; destination = result;
} }
@ -390,10 +386,10 @@ void sub(IntT &destination, IntT source, Status &status) {
status.carry = Numeric::carried_out<false, Numeric::bit_size<IntT>() - 1>(destination, source, result); status.carry = Numeric::carried_out<false, Numeric::bit_size<IntT>() - 1>(destination, source, result);
status.auxiliary_carry = Numeric::carried_in<4>(destination, source, result); status.auxiliary_carry = Numeric::carried_in<4>(destination, source, result);
status.sign = result & Numeric::top_bit<IntT>();
status.zero = status.parity = result;
status.overflow = Numeric::overflow<false, IntT>(destination, source, result); status.overflow = Numeric::overflow<false, IntT>(destination, source, result);
status.set_from<IntT, Flag::Zero, Flag::Sign, Flag::ParityOdd>(result);
if constexpr (write_back) { if constexpr (write_back) {
destination = result; destination = result;
} }
@ -419,10 +415,8 @@ void test(IntT &destination, IntT source, Status &status) {
*/ */
const IntT result = destination & source; const IntT result = destination & source;
status.sign = result & Numeric::top_bit<IntT>();
status.zero = result;
status.carry = status.overflow = 0; status.carry = status.overflow = 0;
status.parity = result; status.set_from<IntT, Flag::Zero, Flag::Sign, Flag::ParityOdd>(result);
} }
template <typename IntT> template <typename IntT>
@ -617,9 +611,8 @@ void inc(IntT &destination, Status &status) {
++destination; ++destination;
status.overflow = destination == Numeric::top_bit<IntT>(); status.overflow = destination == Numeric::top_bit<IntT>();
status.sign = destination & Numeric::top_bit<IntT>();
status.zero = status.parity = destination;
status.auxiliary_carry = ((destination - 1) ^ destination) & 0x10; status.auxiliary_carry = ((destination - 1) ^ destination) & 0x10;
status.set_from<IntT, Flag::Zero, Flag::Sign, Flag::ParityOdd>(destination);
} }
template <typename IntT, typename RegistersT, typename FlowControllerT> template <typename IntT, typename RegistersT, typename FlowControllerT>
@ -654,8 +647,7 @@ void dec(IntT &destination, Status &status) {
--destination; --destination;
status.sign = destination & Numeric::top_bit<IntT>(); status.set_from<IntT, Flag::Zero, Flag::Sign, Flag::ParityOdd>(destination);
status.zero = status.parity = destination;
status.auxiliary_carry = ((destination + 1) ^ destination) & 0x10; status.auxiliary_carry = ((destination + 1) ^ destination) & 0x10;
} }
@ -672,8 +664,7 @@ void and_(IntT &destination, IntT source, Status &status) {
status.overflow = 0; status.overflow = 0;
status.carry = 0; status.carry = 0;
status.sign = destination & Numeric::top_bit<IntT>(); status.set_from<IntT, Flag::Zero, Flag::Sign, Flag::ParityOdd>(destination);
status.zero = status.parity = destination;
} }
template <typename IntT> template <typename IntT>
@ -689,8 +680,7 @@ void or_(IntT &destination, IntT source, Status &status) {
status.overflow = 0; status.overflow = 0;
status.carry = 0; status.carry = 0;
status.sign = destination & Numeric::top_bit<IntT>(); status.set_from<IntT, Flag::Zero, Flag::Sign, Flag::ParityOdd>(destination);
status.zero = status.parity = destination;
} }
template <typename IntT> template <typename IntT>
@ -706,8 +696,7 @@ void xor_(IntT &destination, IntT source, Status &status) {
status.overflow = 0; status.overflow = 0;
status.carry = 0; status.carry = 0;
status.sign = destination & Numeric::top_bit<IntT>(); status.set_from<IntT, Flag::Zero, Flag::Sign, Flag::ParityOdd>(destination);
status.zero = status.parity = destination;
} }
template <typename IntT> template <typename IntT>
@ -729,8 +718,7 @@ void neg(IntT &destination, Status &status) {
status.carry = destination; status.carry = destination;
status.overflow = destination == Numeric::top_bit<IntT>(); status.overflow = destination == Numeric::top_bit<IntT>();
status.sign = destination & Numeric::top_bit<IntT>(); status.set_from<IntT, Flag::Zero, Flag::Sign, Flag::ParityOdd>(destination);
status.zero = status.parity = destination;
} }
template <typename IntT> template <typename IntT>
@ -958,112 +946,112 @@ template <
case Operation::JO: case Operation::JO:
Primitive::jump( Primitive::jump(
status.condition<Status::Condition::Overflow>(), status.condition<Condition::Overflow>(),
instruction.displacement(), instruction.displacement(),
registers, registers,
flow_controller); flow_controller);
return; return;
case Operation::JNO: case Operation::JNO:
Primitive::jump( Primitive::jump(
!status.condition<Status::Condition::Overflow>(), !status.condition<Condition::Overflow>(),
instruction.displacement(), instruction.displacement(),
registers, registers,
flow_controller); flow_controller);
return; return;
case Operation::JB: case Operation::JB:
Primitive::jump( Primitive::jump(
status.condition<Status::Condition::Below>(), status.condition<Condition::Below>(),
instruction.displacement(), instruction.displacement(),
registers, registers,
flow_controller); flow_controller);
return; return;
case Operation::JNB: case Operation::JNB:
Primitive::jump( Primitive::jump(
!status.condition<Status::Condition::Below>(), !status.condition<Condition::Below>(),
instruction.displacement(), instruction.displacement(),
registers, registers,
flow_controller); flow_controller);
return; return;
case Operation::JZ: case Operation::JZ:
Primitive::jump( Primitive::jump(
status.condition<Status::Condition::Zero>(), status.condition<Condition::Zero>(),
instruction.displacement(), instruction.displacement(),
registers, registers,
flow_controller); flow_controller);
return; return;
case Operation::JNZ: case Operation::JNZ:
Primitive::jump( Primitive::jump(
!status.condition<Status::Condition::Zero>(), !status.condition<Condition::Zero>(),
instruction.displacement(), instruction.displacement(),
registers, registers,
flow_controller); flow_controller);
return; return;
case Operation::JBE: case Operation::JBE:
Primitive::jump( Primitive::jump(
status.condition<Status::Condition::BelowOrEqual>(), status.condition<Condition::BelowOrEqual>(),
instruction.displacement(), instruction.displacement(),
registers, registers,
flow_controller); flow_controller);
return; return;
case Operation::JNBE: case Operation::JNBE:
Primitive::jump( Primitive::jump(
!status.condition<Status::Condition::BelowOrEqual>(), !status.condition<Condition::BelowOrEqual>(),
instruction.displacement(), instruction.displacement(),
registers, registers,
flow_controller); flow_controller);
return; return;
case Operation::JS: case Operation::JS:
Primitive::jump( Primitive::jump(
status.condition<Status::Condition::Sign>(), status.condition<Condition::Sign>(),
instruction.displacement(), instruction.displacement(),
registers, registers,
flow_controller); flow_controller);
return; return;
case Operation::JNS: case Operation::JNS:
Primitive::jump( Primitive::jump(
!status.condition<Status::Condition::Sign>(), !status.condition<Condition::Sign>(),
instruction.displacement(), instruction.displacement(),
registers, registers,
flow_controller); flow_controller);
return; return;
case Operation::JP: case Operation::JP:
Primitive::jump( Primitive::jump(
!status.condition<Status::Condition::ParityOdd>(), !status.condition<Condition::ParityOdd>(),
instruction.displacement(), instruction.displacement(),
registers, registers,
flow_controller); flow_controller);
return; return;
case Operation::JNP: case Operation::JNP:
Primitive::jump( Primitive::jump(
status.condition<Status::Condition::ParityOdd>(), status.condition<Condition::ParityOdd>(),
instruction.displacement(), instruction.displacement(),
registers, registers,
flow_controller); flow_controller);
return; return;
case Operation::JL: case Operation::JL:
Primitive::jump( Primitive::jump(
status.condition<Status::Condition::Less>(), status.condition<Condition::Less>(),
instruction.displacement(), instruction.displacement(),
registers, registers,
flow_controller); flow_controller);
return; return;
case Operation::JNL: case Operation::JNL:
Primitive::jump( Primitive::jump(
!status.condition<Status::Condition::Less>(), !status.condition<Condition::Less>(),
instruction.displacement(), instruction.displacement(),
registers, registers,
flow_controller); flow_controller);
return; return;
case Operation::JLE: case Operation::JLE:
Primitive::jump( Primitive::jump(
status.condition<Status::Condition::LessOrEqual>(), status.condition<Condition::LessOrEqual>(),
instruction.displacement(), instruction.displacement(),
registers, registers,
flow_controller); flow_controller);
return; return;
case Operation::JNLE: case Operation::JNLE:
Primitive::jump( Primitive::jump(
!status.condition<Status::Condition::LessOrEqual>(), !status.condition<Condition::LessOrEqual>(),
instruction.displacement(), instruction.displacement(),
registers, registers,
flow_controller); flow_controller);

View File

@ -9,6 +9,7 @@
#ifndef InstructionSets_x86_Status_hpp #ifndef InstructionSets_x86_Status_hpp
#define InstructionSets_x86_Status_hpp #define InstructionSets_x86_Status_hpp
#include "../../Numeric/Carry.hpp"
namespace InstructionSet::x86 { namespace InstructionSet::x86 {
@ -53,6 +54,29 @@ static constexpr uint32_t VirtualMode = 1 << 17;
} }
enum class Flag {
Carry,
AuxiliaryCarry,
Sign,
Overflow,
Trap,
Interrupt,
Direction,
Zero,
ParityOdd
};
enum class Condition {
Overflow,
Below,
Zero,
BelowOrEqual,
Sign,
ParityOdd,
Less,
LessOrEqual
};
struct Status { struct Status {
// Non-zero => set; zero => unset. // Non-zero => set; zero => unset.
uint32_t carry; uint32_t carry;
@ -70,17 +94,6 @@ struct Status {
uint32_t parity; uint32_t parity;
// Flag getters. // Flag getters.
enum class Flag {
Carry,
AuxiliaryCarry,
Sign,
Overflow,
Trap,
Interrupt,
Direction,
Zero,
ParityOdd
};
template <Flag flag> bool flag() { template <Flag flag> bool flag() {
switch(flag) { switch(flag) {
case Flag::Carry: return carry; case Flag::Carry: return carry;
@ -96,16 +109,6 @@ struct Status {
} }
// Condition evaluation. // Condition evaluation.
enum class Condition {
Overflow,
Below,
Zero,
BelowOrEqual,
Sign,
ParityOdd,
Less,
LessOrEqual
};
template <Condition test> bool condition() { template <Condition test> bool condition() {
switch(test) { switch(test) {
case Condition::Overflow: return flag<Flag::Overflow>(); case Condition::Overflow: return flag<Flag::Overflow>();
@ -119,6 +122,18 @@ struct Status {
} }
} }
// Convenience setters.
template <typename IntT, Flag... flags> void set_from(IntT value) {
for(const auto flag: {flags...}) {
switch(flag) {
default: break;
case Flag::Zero: zero = value; break;
case Flag::Sign: sign = value & Numeric::top_bit<IntT>(); break;
case Flag::ParityOdd: parity = value; break;
}
}
}
template <typename IntT> IntT carry_bit() const { return carry ? 1 : 0; } template <typename IntT> IntT carry_bit() const { return carry ? 1 : 0; }
bool not_parity_bit() const { bool not_parity_bit() const {
// x86 parity always considers the lowest 8-bits only. // x86 parity always considers the lowest 8-bits only.