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:
parent
fbd647080d
commit
033ba75376
@ -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);
|
||||||
|
@ -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.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user