1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-11-23 03:32:32 +00:00

Merge pull request #1195 from TomHarte/8088Flags

Commute: Status -> Flags as per usual x86 naming.
This commit is contained in:
Thomas Harte 2023-11-02 17:05:13 -04:00 committed by GitHub
commit 7f4fa914dd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 201 additions and 200 deletions

View File

@ -1,19 +1,19 @@
// //
// Status.hpp // Flags.hpp
// Clock Signal // Clock Signal
// //
// Created by Thomas Harte on 05/10/2023. // Created by Thomas Harte on 05/10/2023.
// Copyright © 2023 Thomas Harte. All rights reserved. // Copyright © 2023 Thomas Harte. All rights reserved.
// //
#ifndef InstructionSets_x86_Status_hpp #ifndef InstructionSets_x86_Flags_hpp
#define InstructionSets_x86_Status_hpp #define InstructionSets_x86_Flags_hpp
#include "../../Numeric/Carry.hpp" #include "../../Numeric/Carry.hpp"
namespace InstructionSet::x86 { namespace InstructionSet::x86 {
namespace ConditionCode { namespace FlagValue {
// //
// Standard flags. // Standard flags.
@ -77,7 +77,7 @@ enum class Condition {
LessOrEqual LessOrEqual
}; };
class Status { class Flags {
public: public:
using FlagT = uint32_t; using FlagT = uint32_t;
@ -156,33 +156,33 @@ class Status {
// Complete value get and set. // Complete value get and set.
void set(uint16_t value) { void set(uint16_t value) {
set_from<Flag::Carry>(value & ConditionCode::Carry); set_from<Flag::Carry>(value & FlagValue::Carry);
set_from<Flag::AuxiliaryCarry>(value & ConditionCode::AuxiliaryCarry); set_from<Flag::AuxiliaryCarry>(value & FlagValue::AuxiliaryCarry);
set_from<Flag::Overflow>(value & ConditionCode::Overflow); set_from<Flag::Overflow>(value & FlagValue::Overflow);
set_from<Flag::Trap>(value & ConditionCode::Trap); set_from<Flag::Trap>(value & FlagValue::Trap);
set_from<Flag::Interrupt>(value & ConditionCode::Interrupt); set_from<Flag::Interrupt>(value & FlagValue::Interrupt);
set_from<Flag::Direction>(value & ConditionCode::Direction); set_from<Flag::Direction>(value & FlagValue::Direction);
set_from<uint8_t, Flag::Sign>(value); set_from<uint8_t, Flag::Sign>(value);
set_from<Flag::Zero>((~value) & ConditionCode::Zero); set_from<Flag::Zero>((~value) & FlagValue::Zero);
set_from<Flag::ParityOdd>((~value) & ConditionCode::Parity); set_from<Flag::ParityOdd>((~value) & FlagValue::Parity);
} }
uint16_t get() const { uint16_t get() const {
return return
0xf002 | 0xf002 |
(flag<Flag::Carry>() ? ConditionCode::Carry : 0) | (flag<Flag::Carry>() ? FlagValue::Carry : 0) |
(flag<Flag::AuxiliaryCarry>() ? ConditionCode::AuxiliaryCarry : 0) | (flag<Flag::AuxiliaryCarry>() ? FlagValue::AuxiliaryCarry : 0) |
(flag<Flag::Sign>() ? ConditionCode::Sign : 0) | (flag<Flag::Sign>() ? FlagValue::Sign : 0) |
(flag<Flag::Overflow>() ? ConditionCode::Overflow : 0) | (flag<Flag::Overflow>() ? FlagValue::Overflow : 0) |
(flag<Flag::Trap>() ? ConditionCode::Trap : 0) | (flag<Flag::Trap>() ? FlagValue::Trap : 0) |
(flag<Flag::Interrupt>() ? ConditionCode::Interrupt : 0) | (flag<Flag::Interrupt>() ? FlagValue::Interrupt : 0) |
(flag<Flag::Direction>() ? ConditionCode::Direction : 0) | (flag<Flag::Direction>() ? FlagValue::Direction : 0) |
(flag<Flag::Zero>() ? ConditionCode::Zero : 0) | (flag<Flag::Zero>() ? FlagValue::Zero : 0) |
(flag<Flag::ParityOdd>() ? 0 : ConditionCode::Parity); (flag<Flag::ParityOdd>() ? 0 : FlagValue::Parity);
} }
std::string to_string() const { std::string to_string() const {
@ -204,7 +204,7 @@ class Status {
return result; return result;
} }
bool operator ==(const Status &rhs) const { bool operator ==(const Flags &rhs) const {
return get() == rhs.get(); return get() == rhs.get();
} }
@ -230,4 +230,4 @@ class Status {
} }
#endif /* InstructionSets_x86_Status_hpp */ #endif /* InstructionSets_x86_Flags_hpp */

View File

@ -191,18 +191,18 @@ namespace Primitive {
// The below takes a reference in order properly to handle PUSH SP, // The below takes a reference in order properly to handle PUSH SP,
// which should place the value of SP after the push onto the stack. // which should place the value of SP after the push onto the stack.
template <typename IntT, bool Preauthorised, typename ContextT> template <typename IntT, bool preauthorised, typename ContextT>
void push(IntT &value, ContextT &context) { void push(IntT &value, ContextT &context) {
context.registers.sp_ -= sizeof(IntT); context.registers.sp_ -= sizeof(IntT);
context.memory.template access<IntT, Preauthorised ? AccessType::PreauthorisedWrite : AccessType::Write>( context.memory.template access<IntT, preauthorised ? AccessType::PreauthorisedWrite : AccessType::Write>(
Source::SS, Source::SS,
context.registers.sp_) = value; context.registers.sp_) = value;
context.memory.template write_back<IntT>(); context.memory.template write_back<IntT>();
} }
template <typename IntT, bool Preauthorised, typename ContextT> template <typename IntT, bool preauthorised, typename ContextT>
IntT pop(ContextT &context) { IntT pop(ContextT &context) {
const auto value = context.memory.template access<IntT, Preauthorised ? AccessType::PreauthorisedRead : AccessType::Read>( const auto value = context.memory.template access<IntT, preauthorised ? AccessType::PreauthorisedRead : AccessType::Read>(
Source::SS, Source::SS,
context.registers.sp_); context.registers.sp_);
context.registers.sp_ += sizeof(IntT); context.registers.sp_ += sizeof(IntT);
@ -236,12 +236,12 @@ void aaa(CPU::RegisterPair16 &ax, ContextT &context) { // P. 313
The AF and CF flags are set to 1 if the adjustment results in a decimal carry; The AF and CF flags are set to 1 if the adjustment results in a decimal carry;
otherwise they are cleared to 0. The OF, SF, ZF, and PF flags are undefined. otherwise they are cleared to 0. The OF, SF, ZF, and PF flags are undefined.
*/ */
if((ax.halves.low & 0x0f) > 9 || context.status.template flag<Flag::AuxiliaryCarry>()) { if((ax.halves.low & 0x0f) > 9 || context.flags.template flag<Flag::AuxiliaryCarry>()) {
ax.halves.low += 6; ax.halves.low += 6;
++ax.halves.high; ++ax.halves.high;
context.status.template set_from<Flag::Carry, Flag::AuxiliaryCarry>(1); context.flags.template set_from<Flag::Carry, Flag::AuxiliaryCarry>(1);
} else { } else {
context.status.template set_from<Flag::Carry, Flag::AuxiliaryCarry>(0); context.flags.template set_from<Flag::Carry, Flag::AuxiliaryCarry>(0);
} }
ax.halves.low &= 0x0f; ax.halves.low &= 0x0f;
} }
@ -260,7 +260,7 @@ void aad(CPU::RegisterPair16 &ax, uint8_t imm, ContextT &context) {
*/ */
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;
context.status.template set_from<uint8_t, Flag::Zero, Flag::Sign, Flag::ParityOdd>(ax.halves.low); context.flags.template set_from<uint8_t, Flag::Zero, Flag::Sign, Flag::ParityOdd>(ax.halves.low);
} }
template <typename ContextT> template <typename ContextT>
@ -284,7 +284,7 @@ void aam(CPU::RegisterPair16 &ax, uint8_t imm, ContextT &context) {
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;
context.status.template set_from<uint8_t, Flag::Zero, Flag::Sign, Flag::ParityOdd>(ax.halves.low); context.flags.template set_from<uint8_t, Flag::Zero, Flag::Sign, Flag::ParityOdd>(ax.halves.low);
} }
template <typename ContextT> template <typename ContextT>
@ -306,12 +306,12 @@ void aas(CPU::RegisterPair16 &ax, ContextT &context) {
The AF and CF flags are set to 1 if there is a decimal borrow; The AF and CF flags are set to 1 if there is a decimal borrow;
otherwise, they are cleared to 0. The OF, SF, ZF, and PF flags are undefined. otherwise, they are cleared to 0. The OF, SF, ZF, and PF flags are undefined.
*/ */
if((ax.halves.low & 0x0f) > 9 || context.status.template flag<Flag::AuxiliaryCarry>()) { if((ax.halves.low & 0x0f) > 9 || context.flags.template flag<Flag::AuxiliaryCarry>()) {
ax.halves.low -= 6; ax.halves.low -= 6;
--ax.halves.high; --ax.halves.high;
context.status.template set_from<Flag::Carry, Flag::AuxiliaryCarry>(1); context.flags.template set_from<Flag::Carry, Flag::AuxiliaryCarry>(1);
} else { } else {
context.status.template set_from<Flag::Carry, Flag::AuxiliaryCarry>(0); context.flags.template set_from<Flag::Carry, Flag::AuxiliaryCarry>(0);
} }
ax.halves.low &= 0x0f; ax.halves.low &= 0x0f;
} }
@ -347,25 +347,25 @@ void daa(uint8_t &al, ContextT &context) {
The SF, ZF, and PF flags are set according to the result. The OF flag is undefined. The SF, ZF, and PF flags are set according to the result. The OF flag is undefined.
*/ */
const uint8_t old_al = al; const uint8_t old_al = al;
const auto old_carry = context.status.template flag<Flag::Carry>(); const auto old_carry = context.flags.template flag<Flag::Carry>();
context.status.template set_from<Flag::Carry>(0); context.flags.template set_from<Flag::Carry>(0);
if((al & 0x0f) > 0x09 || context.status.template flag<Flag::AuxiliaryCarry>()) { if((al & 0x0f) > 0x09 || context.flags.template flag<Flag::AuxiliaryCarry>()) {
context.status.template set_from<Flag::Carry>(old_carry | (al > 0xf9)); context.flags.template set_from<Flag::Carry>(old_carry | (al > 0xf9));
al += 0x06; al += 0x06;
context.status.template set_from<Flag::AuxiliaryCarry>(1); context.flags.template set_from<Flag::AuxiliaryCarry>(1);
} else { } else {
context.status.template set_from<Flag::AuxiliaryCarry>(0); context.flags.template set_from<Flag::AuxiliaryCarry>(0);
} }
if(old_al > 0x99 || old_carry) { if(old_al > 0x99 || old_carry) {
al += 0x60; al += 0x60;
context.status.template set_from<Flag::Carry>(1); context.flags.template set_from<Flag::Carry>(1);
} else { } else {
context.status.template set_from<Flag::Carry>(0); context.flags.template set_from<Flag::Carry>(0);
} }
context.status.template set_from<uint8_t, Flag::Zero, Flag::Sign, Flag::ParityOdd>(al); context.flags.template set_from<uint8_t, Flag::Zero, Flag::Sign, Flag::ParityOdd>(al);
} }
template <typename ContextT> template <typename ContextT>
@ -399,25 +399,25 @@ void das(uint8_t &al, ContextT &context) {
The SF, ZF, and PF flags are set according to the result. The OF flag is undefined. The SF, ZF, and PF flags are set according to the result. The OF flag is undefined.
*/ */
const uint8_t old_al = al; const uint8_t old_al = al;
const auto old_carry = context.status.template flag<Flag::Carry>(); const auto old_carry = context.flags.template flag<Flag::Carry>();
context.status.template set_from<Flag::Carry>(0); context.flags.template set_from<Flag::Carry>(0);
if((al & 0x0f) > 0x09 || context.status.template flag<Flag::AuxiliaryCarry>()) { if((al & 0x0f) > 0x09 || context.flags.template flag<Flag::AuxiliaryCarry>()) {
context.status.template set_from<Flag::Carry>(old_carry | (al < 0x06)); context.flags.template set_from<Flag::Carry>(old_carry | (al < 0x06));
al -= 0x06; al -= 0x06;
context.status.template set_from<Flag::AuxiliaryCarry>(1); context.flags.template set_from<Flag::AuxiliaryCarry>(1);
} else { } else {
context.status.template set_from<Flag::AuxiliaryCarry>(0); context.flags.template set_from<Flag::AuxiliaryCarry>(0);
} }
if(old_al > 0x99 || old_carry) { if(old_al > 0x99 || old_carry) {
al -= 0x60; al -= 0x60;
context.status.template set_from<Flag::Carry>(1); context.flags.template set_from<Flag::Carry>(1);
} else { } else {
context.status.template set_from<Flag::Carry>(0); context.flags.template set_from<Flag::Carry>(0);
} }
context.status.template set_from<uint8_t, Flag::Zero, Flag::Sign, Flag::ParityOdd>(al); context.flags.template set_from<uint8_t, Flag::Zero, Flag::Sign, Flag::ParityOdd>(al);
} }
template <bool with_carry, typename IntT, typename ContextT> template <bool with_carry, typename IntT, typename ContextT>
@ -428,16 +428,16 @@ void add(IntT &destination, IntT source, ContextT &context) {
/* /*
The OF, SF, ZF, AF, CF, and PF flags are set according to the result. The OF, SF, ZF, AF, CF, and PF flags are set according to the result.
*/ */
const IntT result = destination + source + (with_carry ? context.status.template carry_bit<IntT>() : 0); const IntT result = destination + source + (with_carry ? context.flags.template carry_bit<IntT>() : 0);
context.status.template set_from<Flag::Carry>( context.flags.template set_from<Flag::Carry>(
Numeric::carried_out<true, Numeric::bit_size<IntT>() - 1>(destination, source, result)); Numeric::carried_out<true, Numeric::bit_size<IntT>() - 1>(destination, source, result));
context.status.template set_from<Flag::AuxiliaryCarry>( context.flags.template set_from<Flag::AuxiliaryCarry>(
Numeric::carried_in<4>(destination, source, result)); Numeric::carried_in<4>(destination, source, result));
context.status.template set_from<Flag::Overflow>( context.flags.template set_from<Flag::Overflow>(
Numeric::overflow<true, IntT>(destination, source, result)); Numeric::overflow<true, IntT>(destination, source, result));
context.status.template set_from<IntT, Flag::Zero, Flag::Sign, Flag::ParityOdd>(result); context.flags.template set_from<IntT, Flag::Zero, Flag::Sign, Flag::ParityOdd>(result);
destination = result; destination = result;
} }
@ -450,16 +450,16 @@ void sub(IntT &destination, IntT source, ContextT &context) {
/* /*
The OF, SF, ZF, AF, CF, and PF flags are set according to the result. The OF, SF, ZF, AF, CF, and PF flags are set according to the result.
*/ */
const IntT result = destination - source - (with_borrow ? context.status.template carry_bit<IntT>() : 0); const IntT result = destination - source - (with_borrow ? context.flags.template carry_bit<IntT>() : 0);
context.status.template set_from<Flag::Carry>( context.flags.template set_from<Flag::Carry>(
Numeric::carried_out<false, Numeric::bit_size<IntT>() - 1>(destination, source, result)); Numeric::carried_out<false, Numeric::bit_size<IntT>() - 1>(destination, source, result));
context.status.template set_from<Flag::AuxiliaryCarry>( context.flags.template set_from<Flag::AuxiliaryCarry>(
Numeric::carried_in<4>(destination, source, result)); Numeric::carried_in<4>(destination, source, result));
context.status.template set_from<Flag::Overflow>( context.flags.template set_from<Flag::Overflow>(
Numeric::overflow<false, IntT>(destination, source, result)); Numeric::overflow<false, IntT>(destination, source, result));
context.status.template set_from<IntT, Flag::Zero, Flag::Sign, Flag::ParityOdd>(result); context.flags.template set_from<IntT, Flag::Zero, Flag::Sign, Flag::ParityOdd>(result);
if constexpr (write_back) { if constexpr (write_back) {
destination = result; destination = result;
@ -486,8 +486,8 @@ void test(IntT &destination, IntT source, ContextT &context) {
*/ */
const IntT result = destination & source; const IntT result = destination & source;
context.status.template set_from<Flag::Carry, Flag::Overflow>(0); context.flags.template set_from<Flag::Carry, Flag::Overflow>(0);
context.status.template set_from<IntT, Flag::Zero, Flag::Sign, Flag::ParityOdd>(result); context.flags.template set_from<IntT, Flag::Zero, Flag::Sign, Flag::ParityOdd>(result);
} }
template <typename IntT> template <typename IntT>
@ -519,7 +519,7 @@ void mul(IntT &destination_high, IntT &destination_low, IntT source, ContextT &c
*/ */
destination_high = (destination_low * source) >> (8 * sizeof(IntT)); destination_high = (destination_low * source) >> (8 * sizeof(IntT));
destination_low *= source; destination_low *= source;
context.status.template set_from<Flag::Overflow, Flag::Carry>(destination_high); context.flags.template set_from<Flag::Overflow, Flag::Carry>(destination_high);
} }
template <typename IntT, typename ContextT> template <typename IntT, typename ContextT>
@ -554,7 +554,7 @@ void imul(IntT &destination_high, IntT &destination_low, IntT source, ContextT &
destination_low = IntT(sIntT(destination_low) * sIntT(source)); destination_low = IntT(sIntT(destination_low) * sIntT(source));
const auto sign_extension = (destination_low & Numeric::top_bit<IntT>()) ? IntT(~0) : 0; const auto sign_extension = (destination_low & Numeric::top_bit<IntT>()) ? IntT(~0) : 0;
context.status.template set_from<Flag::Overflow, Flag::Carry>(destination_high != sign_extension); context.flags.template set_from<Flag::Overflow, Flag::Carry>(destination_high != sign_extension);
} }
template <typename IntT, typename ContextT> template <typename IntT, typename ContextT>
@ -681,9 +681,9 @@ void inc(IntT &destination, ContextT &context) {
*/ */
++destination; ++destination;
context.status.template set_from<Flag::Overflow>(destination == Numeric::top_bit<IntT>()); context.flags.template set_from<Flag::Overflow>(destination == Numeric::top_bit<IntT>());
context.status.template set_from<Flag::AuxiliaryCarry>(((destination - 1) ^ destination) & 0x10); context.flags.template set_from<Flag::AuxiliaryCarry>(((destination - 1) ^ destination) & 0x10);
context.status.template set_from<IntT, Flag::Zero, Flag::Sign, Flag::ParityOdd>(destination); context.flags.template set_from<IntT, Flag::Zero, Flag::Sign, Flag::ParityOdd>(destination);
} }
template <typename IntT, typename ContextT> template <typename IntT, typename ContextT>
@ -716,7 +716,7 @@ void loop(IntT &counter, OffsetT displacement, ContextT &context) {
template <typename IntT, typename OffsetT, typename ContextT> template <typename IntT, typename OffsetT, typename ContextT>
void loope(IntT &counter, OffsetT displacement, ContextT &context) { void loope(IntT &counter, OffsetT displacement, ContextT &context) {
--counter; --counter;
if(counter && context.status.template flag<Flag::Zero>()) { if(counter && context.flags.template flag<Flag::Zero>()) {
context.flow_controller.jump(context.registers.ip() + displacement); context.flow_controller.jump(context.registers.ip() + displacement);
} }
} }
@ -724,7 +724,7 @@ void loope(IntT &counter, OffsetT displacement, ContextT &context) {
template <typename IntT, typename OffsetT, typename ContextT> template <typename IntT, typename OffsetT, typename ContextT>
void loopne(IntT &counter, OffsetT displacement, ContextT &context) { void loopne(IntT &counter, OffsetT displacement, ContextT &context) {
--counter; --counter;
if(counter && !context.status.template flag<Flag::Zero>()) { if(counter && !context.flags.template flag<Flag::Zero>()) {
context.flow_controller.jump(context.registers.ip() + displacement); context.flow_controller.jump(context.registers.ip() + displacement);
} }
} }
@ -738,12 +738,12 @@ void dec(IntT &destination, ContextT &context) {
The CF flag is not affected. The CF flag is not affected.
The OF, SF, ZF, AF, and PF flags are set according to the result. The OF, SF, ZF, AF, and PF flags are set according to the result.
*/ */
context.status.template set_from<Flag::Overflow>(destination == Numeric::top_bit<IntT>()); context.flags.template set_from<Flag::Overflow>(destination == Numeric::top_bit<IntT>());
--destination; --destination;
context.status.template set_from<IntT, Flag::Zero, Flag::Sign, Flag::ParityOdd>(destination); context.flags.template set_from<IntT, Flag::Zero, Flag::Sign, Flag::ParityOdd>(destination);
context.status.template set_from<Flag::AuxiliaryCarry>(((destination + 1) ^ destination) & 0x10); context.flags.template set_from<Flag::AuxiliaryCarry>(((destination + 1) ^ destination) & 0x10);
} }
template <typename IntT, typename ContextT> template <typename IntT, typename ContextT>
@ -757,8 +757,8 @@ void and_(IntT &destination, IntT source, ContextT &context) {
*/ */
destination &= source; destination &= source;
context.status.template set_from<Flag::Overflow, Flag::Carry>(0); context.flags.template set_from<Flag::Overflow, Flag::Carry>(0);
context.status.template set_from<IntT, Flag::Zero, Flag::Sign, Flag::ParityOdd>(destination); context.flags.template set_from<IntT, Flag::Zero, Flag::Sign, Flag::ParityOdd>(destination);
} }
template <typename IntT, typename ContextT> template <typename IntT, typename ContextT>
@ -772,8 +772,8 @@ void or_(IntT &destination, IntT source, ContextT &context) {
*/ */
destination |= source; destination |= source;
context.status.template set_from<Flag::Overflow, Flag::Carry>(0); context.flags.template set_from<Flag::Overflow, Flag::Carry>(0);
context.status.template set_from<IntT, Flag::Zero, Flag::Sign, Flag::ParityOdd>(destination); context.flags.template set_from<IntT, Flag::Zero, Flag::Sign, Flag::ParityOdd>(destination);
} }
template <typename IntT, typename ContextT> template <typename IntT, typename ContextT>
@ -787,8 +787,8 @@ void xor_(IntT &destination, IntT source, ContextT &context) {
*/ */
destination ^= source; destination ^= source;
context.status.template set_from<Flag::Overflow, Flag::Carry>(0); context.flags.template set_from<Flag::Overflow, Flag::Carry>(0);
context.status.template set_from<IntT, Flag::Zero, Flag::Sign, Flag::ParityOdd>(destination); context.flags.template set_from<IntT, Flag::Zero, Flag::Sign, Flag::ParityOdd>(destination);
} }
template <typename IntT, typename ContextT> template <typename IntT, typename ContextT>
@ -804,13 +804,13 @@ void neg(IntT &destination, ContextT &context) {
The CF flag cleared to 0 if the source operand is 0; otherwise it is set to 1. The CF flag cleared to 0 if the source operand is 0; otherwise it is set to 1.
The OF, SF, ZF, AF, and PF flags are set according to the result. The OF, SF, ZF, AF, and PF flags are set according to the result.
*/ */
context.status.template set_from<Flag::AuxiliaryCarry>(Numeric::carried_in<4>(IntT(0), destination, IntT(-destination))); context.flags.template set_from<Flag::AuxiliaryCarry>(Numeric::carried_in<4>(IntT(0), destination, IntT(-destination)));
destination = -destination; destination = -destination;
context.status.template set_from<Flag::Carry>(destination); context.flags.template set_from<Flag::Carry>(destination);
context.status.template set_from<Flag::Overflow>(destination == Numeric::top_bit<IntT>()); context.flags.template set_from<Flag::Overflow>(destination == Numeric::top_bit<IntT>());
context.status.template set_from<IntT, Flag::Zero, Flag::Sign, Flag::ParityOdd>(destination); context.flags.template set_from<IntT, Flag::Zero, Flag::Sign, Flag::ParityOdd>(destination);
} }
template <typename IntT> template <typename IntT>
@ -915,7 +915,7 @@ void iret(ContextT &context) {
context.memory.preauthorise_stack_read(sizeof(uint16_t) * 3); context.memory.preauthorise_stack_read(sizeof(uint16_t) * 3);
const auto ip = pop<uint16_t, true>(context); const auto ip = pop<uint16_t, true>(context);
const auto cs = pop<uint16_t, true>(context); const auto cs = pop<uint16_t, true>(context);
context.status.set(pop<uint16_t, true>(context)); context.flags.set(pop<uint16_t, true>(context));
context.flow_controller.jump(cs, ip); context.flow_controller.jump(cs, ip);
} }
@ -984,7 +984,7 @@ void mov(IntT &destination, IntT source) {
template <typename ContextT> template <typename ContextT>
void into(ContextT &context) { void into(ContextT &context) {
if(context.status.template flag<Flag::Overflow>()) { if(context.flags.template flag<Flag::Overflow>()) {
interrupt(Interrupt::OnOverflow, context); interrupt(Interrupt::OnOverflow, context);
} }
} }
@ -994,11 +994,11 @@ void sahf(uint8_t &ah, ContextT &context) {
/* /*
EFLAGS(SF:ZF:0:AF:0:PF:1:CF) AH; EFLAGS(SF:ZF:0:AF:0:PF:1:CF) AH;
*/ */
context.status.template set_from<uint8_t, Flag::Sign>(ah); context.flags.template set_from<uint8_t, Flag::Sign>(ah);
context.status.template set_from<Flag::Zero>(!(ah & 0x40)); context.flags.template set_from<Flag::Zero>(!(ah & 0x40));
context.status.template set_from<Flag::AuxiliaryCarry>(ah & 0x10); context.flags.template set_from<Flag::AuxiliaryCarry>(ah & 0x10);
context.status.template set_from<Flag::ParityOdd>(!(ah & 0x04)); context.flags.template set_from<Flag::ParityOdd>(!(ah & 0x04));
context.status.template set_from<Flag::Carry>(ah & 0x01); context.flags.template set_from<Flag::Carry>(ah & 0x01);
} }
template <typename ContextT> template <typename ContextT>
@ -1007,12 +1007,12 @@ void lahf(uint8_t &ah, ContextT &context) {
AH EFLAGS(SF:ZF:0:AF:0:PF:1:CF); AH EFLAGS(SF:ZF:0:AF:0:PF:1:CF);
*/ */
ah = ah =
(context.status.template flag<Flag::Sign>() ? 0x80 : 0x00) | (context.flags.template flag<Flag::Sign>() ? 0x80 : 0x00) |
(context.status.template flag<Flag::Zero>() ? 0x40 : 0x00) | (context.flags.template flag<Flag::Zero>() ? 0x40 : 0x00) |
(context.status.template flag<Flag::AuxiliaryCarry>() ? 0x10 : 0x00) | (context.flags.template flag<Flag::AuxiliaryCarry>() ? 0x10 : 0x00) |
(context.status.template flag<Flag::ParityOdd>() ? 0x00 : 0x04) | (context.flags.template flag<Flag::ParityOdd>() ? 0x00 : 0x04) |
0x02 | 0x02 |
(context.status.template flag<Flag::Carry>() ? 0x01 : 0x00); (context.flags.template flag<Flag::Carry>() ? 0x01 : 0x00);
} }
template <typename IntT> template <typename IntT>
@ -1034,32 +1034,32 @@ void cwd(IntT &dx, IntT ax) {
// TODO: changes to the interrupt flag do quite a lot more in protected mode. // TODO: changes to the interrupt flag do quite a lot more in protected mode.
template <typename ContextT> template <typename ContextT>
void clc(ContextT &context) { context.status.template set_from<Flag::Carry>(0); } void clc(ContextT &context) { context.flags.template set_from<Flag::Carry>(0); }
template <typename ContextT> template <typename ContextT>
void cld(ContextT &context) { context.status.template set_from<Flag::Direction>(0); } void cld(ContextT &context) { context.flags.template set_from<Flag::Direction>(0); }
template <typename ContextT> template <typename ContextT>
void cli(ContextT &context) { context.status.template set_from<Flag::Interrupt>(0); } void cli(ContextT &context) { context.flags.template set_from<Flag::Interrupt>(0); }
template <typename ContextT> template <typename ContextT>
void stc(ContextT &context) { context.status.template set_from<Flag::Carry>(1); } void stc(ContextT &context) { context.flags.template set_from<Flag::Carry>(1); }
template <typename ContextT> template <typename ContextT>
void std(ContextT &context) { context.status.template set_from<Flag::Direction>(1); } void std(ContextT &context) { context.flags.template set_from<Flag::Direction>(1); }
template <typename ContextT> template <typename ContextT>
void sti(ContextT &context) { context.status.template set_from<Flag::Interrupt>(1); } void sti(ContextT &context) { context.flags.template set_from<Flag::Interrupt>(1); }
template <typename ContextT> template <typename ContextT>
void cmc(ContextT &context) { void cmc(ContextT &context) {
context.status.template set_from<Flag::Carry>(!context.status.template flag<Flag::Carry>()); context.flags.template set_from<Flag::Carry>(!context.flags.template flag<Flag::Carry>());
} }
template <typename ContextT> template <typename ContextT>
void salc(uint8_t &al, ContextT &context) { void salc(uint8_t &al, ContextT &context) {
al = context.status.template flag<Flag::Carry>() ? 0xff : 0x00; al = context.flags.template flag<Flag::Carry>() ? 0xff : 0x00;
} }
template <typename IntT, typename ContextT> template <typename IntT, typename ContextT>
void setmo(IntT &destination, ContextT &context) { void setmo(IntT &destination, ContextT &context) {
destination = ~0; destination = ~0;
context.status.template set_from<Flag::Carry, Flag::AuxiliaryCarry, Flag::Overflow>(0); context.flags.template set_from<Flag::Carry, Flag::AuxiliaryCarry, Flag::Overflow>(0);
context.status.template set_from<IntT, Flag::Sign, Flag::Zero, Flag::ParityOdd>(destination); context.flags.template set_from<IntT, Flag::Sign, Flag::Zero, Flag::ParityOdd>(destination);
} }
template <typename IntT, typename ContextT> template <typename IntT, typename ContextT>
@ -1094,7 +1094,7 @@ void rcl(IntT &destination, uint8_t count, ContextT &context) {
it is undefined for multi-bit rotates. The SF, ZF, AF, and PF flags are not affected. it is undefined for multi-bit rotates. The SF, ZF, AF, and PF flags are not affected.
*/ */
const auto temp_count = count % (Numeric::bit_size<IntT>() + 1); const auto temp_count = count % (Numeric::bit_size<IntT>() + 1);
auto carry = context.status.template carry_bit<IntT>(); auto carry = context.flags.template carry_bit<IntT>();
switch(temp_count) { switch(temp_count) {
case 0: break; case 0: break;
case Numeric::bit_size<IntT>(): { case Numeric::bit_size<IntT>(): {
@ -1112,8 +1112,8 @@ void rcl(IntT &destination, uint8_t count, ContextT &context) {
} break; } break;
} }
context.status.template set_from<Flag::Carry>(carry); context.flags.template set_from<Flag::Carry>(carry);
context.status.template set_from<Flag::Overflow>( context.flags.template set_from<Flag::Overflow>(
((destination >> (Numeric::bit_size<IntT>() - 1)) & 1) ^ carry ((destination >> (Numeric::bit_size<IntT>() - 1)) & 1) ^ carry
); );
} }
@ -1134,8 +1134,8 @@ void rcr(IntT &destination, uint8_t count, ContextT &context) {
tempCOUNT tempCOUNT 1; tempCOUNT tempCOUNT 1;
OD; OD;
*/ */
auto carry = context.status.template carry_bit<IntT>(); auto carry = context.flags.template carry_bit<IntT>();
context.status.template set_from<Flag::Overflow>( context.flags.template set_from<Flag::Overflow>(
((destination >> (Numeric::bit_size<IntT>() - 1)) & 1) ^ carry ((destination >> (Numeric::bit_size<IntT>() - 1)) & 1) ^ carry
); );
@ -1157,7 +1157,7 @@ void rcr(IntT &destination, uint8_t count, ContextT &context) {
} break; } break;
} }
context.status.template set_from<Flag::Carry>(carry); context.flags.template set_from<Flag::Carry>(carry);
} }
template <typename IntT, typename ContextT> template <typename IntT, typename ContextT>
@ -1201,8 +1201,8 @@ void rol(IntT &destination, uint8_t count, ContextT &context) {
(destination >> (Numeric::bit_size<IntT>() - temp_count)); (destination >> (Numeric::bit_size<IntT>() - temp_count));
} }
context.status.template set_from<Flag::Carry>(destination & 1); context.flags.template set_from<Flag::Carry>(destination & 1);
context.status.template set_from<Flag::Overflow>( context.flags.template set_from<Flag::Overflow>(
((destination >> (Numeric::bit_size<IntT>() - 1)) ^ destination) & 1 ((destination >> (Numeric::bit_size<IntT>() - 1)) ^ destination) & 1
); );
} }
@ -1248,8 +1248,8 @@ void ror(IntT &destination, uint8_t count, ContextT &context) {
(destination << (Numeric::bit_size<IntT>() - temp_count)); (destination << (Numeric::bit_size<IntT>() - temp_count));
} }
context.status.template set_from<Flag::Carry>(destination & Numeric::top_bit<IntT>()); context.flags.template set_from<Flag::Carry>(destination & Numeric::top_bit<IntT>());
context.status.template set_from<Flag::Overflow>( context.flags.template set_from<Flag::Overflow>(
(destination ^ (destination << 1)) & Numeric::top_bit<IntT>() (destination ^ (destination << 1)) & Numeric::top_bit<IntT>()
); );
} }
@ -1315,26 +1315,26 @@ void sal(IntT &destination, uint8_t count, ContextT &context) {
switch(count) { switch(count) {
case 0: return; case 0: return;
case Numeric::bit_size<IntT>(): case Numeric::bit_size<IntT>():
context.status.template set_from<Flag::Carry, Flag::Overflow>(destination & 1); context.flags.template set_from<Flag::Carry, Flag::Overflow>(destination & 1);
destination = 0; destination = 0;
break; break;
default: default:
if(count > Numeric::bit_size<IntT>()) { if(count > Numeric::bit_size<IntT>()) {
context.status.template set_from<Flag::Carry, Flag::Overflow>(0); context.flags.template set_from<Flag::Carry, Flag::Overflow>(0);
destination = 0; destination = 0;
} else { } else {
const auto mask = (Numeric::top_bit<IntT>() >> (count - 1)); const auto mask = (Numeric::top_bit<IntT>() >> (count - 1));
context.status.template set_from<Flag::Carry>( context.flags.template set_from<Flag::Carry>(
destination & mask destination & mask
); );
context.status.template set_from<Flag::Overflow>( context.flags.template set_from<Flag::Overflow>(
(destination ^ (destination << 1)) & mask (destination ^ (destination << 1)) & mask
); );
destination <<= count; destination <<= count;
} }
break; break;
} }
context.status.template set_from<IntT, Flag::Sign, Flag::Zero, Flag::ParityOdd>(destination); context.flags.template set_from<IntT, Flag::Sign, Flag::Zero, Flag::ParityOdd>(destination);
} }
template <typename IntT, typename ContextT> template <typename IntT, typename ContextT>
@ -1346,14 +1346,14 @@ void sar(IntT &destination, uint8_t count, ContextT &context) {
const IntT sign = Numeric::top_bit<IntT>() & destination; const IntT sign = Numeric::top_bit<IntT>() & destination;
if(count >= Numeric::bit_size<IntT>()) { if(count >= Numeric::bit_size<IntT>()) {
destination = sign ? IntT(~0) : IntT(0); destination = sign ? IntT(~0) : IntT(0);
context.status.template set_from<Flag::Carry>(sign); context.flags.template set_from<Flag::Carry>(sign);
} else { } else {
const IntT mask = 1 << (count - 1); const IntT mask = 1 << (count - 1);
context.status.template set_from<Flag::Carry>(destination & mask); context.flags.template set_from<Flag::Carry>(destination & mask);
destination = (destination >> count) | (sign ? ~(IntT(~0) >> count) : 0); destination = (destination >> count) | (sign ? ~(IntT(~0) >> count) : 0);
} }
context.status.template set_from<Flag::Overflow>(0); context.flags.template set_from<Flag::Overflow>(0);
context.status.template set_from<IntT, Flag::Sign, Flag::Zero, Flag::ParityOdd>(destination); context.flags.template set_from<IntT, Flag::Sign, Flag::Zero, Flag::ParityOdd>(destination);
} }
template <typename IntT, typename ContextT> template <typename IntT, typename ContextT>
@ -1362,29 +1362,29 @@ void shr(IntT &destination, uint8_t count, ContextT &context) {
return; return;
} }
context.status.template set_from<Flag::Overflow>(Numeric::top_bit<IntT>() & destination); context.flags.template set_from<Flag::Overflow>(Numeric::top_bit<IntT>() & destination);
if(count == Numeric::bit_size<IntT>()) { if(count == Numeric::bit_size<IntT>()) {
context.status.template set_from<Flag::Carry>(Numeric::top_bit<IntT>() & destination); context.flags.template set_from<Flag::Carry>(Numeric::top_bit<IntT>() & destination);
destination = 0; destination = 0;
} else if(count > Numeric::bit_size<IntT>()) { } else if(count > Numeric::bit_size<IntT>()) {
context.status.template set_from<Flag::Carry>(0); context.flags.template set_from<Flag::Carry>(0);
destination = 0; destination = 0;
} else { } else {
const IntT mask = 1 << (count - 1); const IntT mask = 1 << (count - 1);
context.status.template set_from<Flag::Carry>(destination & mask); context.flags.template set_from<Flag::Carry>(destination & mask);
destination >>= count; destination >>= count;
} }
context.status.template set_from<IntT, Flag::Sign, Flag::Zero, Flag::ParityOdd>(destination); context.flags.template set_from<IntT, Flag::Sign, Flag::Zero, Flag::ParityOdd>(destination);
} }
template <typename ContextT> template <typename ContextT>
void popf(ContextT &context) { void popf(ContextT &context) {
context.status.set(pop<uint16_t, false>(context)); context.flags.set(pop<uint16_t, false>(context));
} }
template <typename ContextT> template <typename ContextT>
void pushf(ContextT &context) { void pushf(ContextT &context) {
uint16_t value = context.status.get(); uint16_t value = context.flags.get();
push<uint16_t, false>(value, context); push<uint16_t, false>(value, context);
} }
@ -1403,7 +1403,7 @@ void repeat(AddressT &eCX, ContextT &context) {
} }
if constexpr (repetition != Repetition::Rep) { if constexpr (repetition != Repetition::Rep) {
// If this is RepE or RepNE, also test the zero flag. // If this is RepE or RepNE, also test the zero flag.
if((repetition == Repetition::RepNE) == context.status.template flag<Flag::Zero>()) { if((repetition == Repetition::RepNE) == context.flags.template flag<Flag::Zero>()) {
return; return;
} }
} }
@ -1418,8 +1418,8 @@ void cmps(const InstructionT &instruction, AddressT &eCX, AddressT &eSI, Address
IntT lhs = context.memory.template access<IntT, AccessType::Read>(instruction.data_segment(), eSI); IntT lhs = context.memory.template access<IntT, AccessType::Read>(instruction.data_segment(), eSI);
const IntT rhs = context.memory.template access<IntT, AccessType::Read>(Source::ES, eDI); const IntT rhs = context.memory.template access<IntT, AccessType::Read>(Source::ES, eDI);
eSI += context.status.template direction<AddressT>() * sizeof(IntT); eSI += context.flags.template direction<AddressT>() * sizeof(IntT);
eDI += context.status.template direction<AddressT>() * sizeof(IntT); eDI += context.flags.template direction<AddressT>() * sizeof(IntT);
Primitive::sub<false, false>(lhs, rhs, context); Primitive::sub<false, false>(lhs, rhs, context);
@ -1433,7 +1433,7 @@ void scas(AddressT &eCX, AddressT &eDI, IntT &eAX, ContextT &context) {
} }
const IntT rhs = context.memory.template access<IntT, AccessType::Read>(Source::ES, eDI); const IntT rhs = context.memory.template access<IntT, AccessType::Read>(Source::ES, eDI);
eDI += context.status.template direction<AddressT>() * sizeof(IntT); eDI += context.flags.template direction<AddressT>() * sizeof(IntT);
Primitive::sub<false, false>(eAX, rhs, context); Primitive::sub<false, false>(eAX, rhs, context);
@ -1447,7 +1447,7 @@ void lods(const InstructionT &instruction, AddressT &eCX, AddressT &eSI, IntT &e
} }
eAX = context.memory.template access<IntT, AccessType::Read>(instruction.data_segment(), eSI); eAX = context.memory.template access<IntT, AccessType::Read>(instruction.data_segment(), eSI);
eSI += context.status.template direction<AddressT>() * sizeof(IntT); eSI += context.flags.template direction<AddressT>() * sizeof(IntT);
repeat<AddressT, repetition>(eCX, context); repeat<AddressT, repetition>(eCX, context);
} }
@ -1461,8 +1461,8 @@ void movs(const InstructionT &instruction, AddressT &eCX, AddressT &eSI, Address
context.memory.template access<IntT, AccessType::Write>(Source::ES, eDI) = context.memory.template access<IntT, AccessType::Write>(Source::ES, eDI) =
context.memory.template access<IntT, AccessType::Read>(instruction.data_segment(), eSI); context.memory.template access<IntT, AccessType::Read>(instruction.data_segment(), eSI);
eSI += context.status.template direction<AddressT>() * sizeof(IntT); eSI += context.flags.template direction<AddressT>() * sizeof(IntT);
eDI += context.status.template direction<AddressT>() * sizeof(IntT); eDI += context.flags.template direction<AddressT>() * sizeof(IntT);
repeat<AddressT, repetition>(eCX, context); repeat<AddressT, repetition>(eCX, context);
} }
@ -1474,7 +1474,7 @@ void stos(AddressT &eCX, AddressT &eDI, IntT &eAX, ContextT &context) {
} }
context.memory.template access<IntT, AccessType::Write>(Source::ES, eDI) = eAX; context.memory.template access<IntT, AccessType::Write>(Source::ES, eDI) = eAX;
eDI += context.status.template direction<AddressT>() * sizeof(IntT); eDI += context.flags.template direction<AddressT>() * sizeof(IntT);
repeat<AddressT, repetition>(eCX, context); repeat<AddressT, repetition>(eCX, context);
} }
@ -1489,7 +1489,7 @@ void outs(const InstructionT &instruction, AddressT &eCX, uint16_t port, Address
port, port,
context.memory.template access<IntT, AccessType::Read>(instruction.data_segment(), eSI) context.memory.template access<IntT, AccessType::Read>(instruction.data_segment(), eSI)
); );
eSI += context.status.template direction<AddressT>() * sizeof(IntT); eSI += context.flags.template direction<AddressT>() * sizeof(IntT);
repeat<AddressT, repetition>(eCX, context); repeat<AddressT, repetition>(eCX, context);
} }
@ -1501,7 +1501,7 @@ void ins(AddressT &eCX, uint16_t port, AddressT &eDI, ContextT &context) {
} }
context.memory.template access<IntT, AccessType::Write>(Source::ES, eDI) = context.io.template in<IntT>(port); context.memory.template access<IntT, AccessType::Write>(Source::ES, eDI) = context.io.template in<IntT>(port);
eDI += context.status.template direction<AddressT>() * sizeof(IntT); eDI += context.flags.template direction<AddressT>() * sizeof(IntT);
repeat<AddressT, repetition>(eCX, context); repeat<AddressT, repetition>(eCX, context);
} }
@ -1722,22 +1722,22 @@ template <
case Operation::LEA: Primitive::lea(instruction, destination_w(), context); return; case Operation::LEA: Primitive::lea(instruction, destination_w(), context); return;
case Operation::MOV: Primitive::mov(destination_w(), source_r()); break; case Operation::MOV: Primitive::mov(destination_w(), source_r()); break;
case Operation::JO: jcc(context.status.template condition<Condition::Overflow>()); return; case Operation::JO: jcc(context.flags.template condition<Condition::Overflow>()); return;
case Operation::JNO: jcc(!context.status.template condition<Condition::Overflow>()); return; case Operation::JNO: jcc(!context.flags.template condition<Condition::Overflow>()); return;
case Operation::JB: jcc(context.status.template condition<Condition::Below>()); return; case Operation::JB: jcc(context.flags.template condition<Condition::Below>()); return;
case Operation::JNB: jcc(!context.status.template condition<Condition::Below>()); return; case Operation::JNB: jcc(!context.flags.template condition<Condition::Below>()); return;
case Operation::JZ: jcc(context.status.template condition<Condition::Zero>()); return; case Operation::JZ: jcc(context.flags.template condition<Condition::Zero>()); return;
case Operation::JNZ: jcc(!context.status.template condition<Condition::Zero>()); return; case Operation::JNZ: jcc(!context.flags.template condition<Condition::Zero>()); return;
case Operation::JBE: jcc(context.status.template condition<Condition::BelowOrEqual>()); return; case Operation::JBE: jcc(context.flags.template condition<Condition::BelowOrEqual>()); return;
case Operation::JNBE: jcc(!context.status.template condition<Condition::BelowOrEqual>()); return; case Operation::JNBE: jcc(!context.flags.template condition<Condition::BelowOrEqual>()); return;
case Operation::JS: jcc(context.status.template condition<Condition::Sign>()); return; case Operation::JS: jcc(context.flags.template condition<Condition::Sign>()); return;
case Operation::JNS: jcc(!context.status.template condition<Condition::Sign>()); return; case Operation::JNS: jcc(!context.flags.template condition<Condition::Sign>()); return;
case Operation::JP: jcc(!context.status.template condition<Condition::ParityOdd>()); return; case Operation::JP: jcc(!context.flags.template condition<Condition::ParityOdd>()); return;
case Operation::JNP: jcc(context.status.template condition<Condition::ParityOdd>()); return; case Operation::JNP: jcc(context.flags.template condition<Condition::ParityOdd>()); return;
case Operation::JL: jcc(context.status.template condition<Condition::Less>()); return; case Operation::JL: jcc(context.flags.template condition<Condition::Less>()); return;
case Operation::JNL: jcc(!context.status.template condition<Condition::Less>()); return; case Operation::JNL: jcc(!context.flags.template condition<Condition::Less>()); return;
case Operation::JLE: jcc(context.status.template condition<Condition::LessOrEqual>()); return; case Operation::JLE: jcc(context.flags.template condition<Condition::LessOrEqual>()); return;
case Operation::JNLE: jcc(!context.status.template condition<Condition::LessOrEqual>()); return; case Operation::JNLE: jcc(!context.flags.template condition<Condition::LessOrEqual>()); return;
case Operation::RCL: Primitive::rcl(destination_rmw(), shift_count(), context); break; case Operation::RCL: Primitive::rcl(destination_rmw(), shift_count(), context); break;
case Operation::RCR: Primitive::rcr(destination_rmw(), shift_count(), context); break; case Operation::RCR: Primitive::rcr(destination_rmw(), shift_count(), context); break;
@ -1923,9 +1923,9 @@ template <
const uint16_t ip = context.memory.template access<uint16_t, AccessType::PreauthorisedRead>(address); const uint16_t ip = context.memory.template access<uint16_t, AccessType::PreauthorisedRead>(address);
const uint16_t cs = context.memory.template access<uint16_t, AccessType::PreauthorisedRead>(address + 2); const uint16_t cs = context.memory.template access<uint16_t, AccessType::PreauthorisedRead>(address + 2);
auto flags = context.status.get(); auto flags = context.flags.get();
Primitive::push<uint16_t, true>(flags, context); Primitive::push<uint16_t, true>(flags, context);
context.status.template set_from<Flag::Interrupt, Flag::Trap>(0); context.flags.template set_from<Flag::Interrupt, Flag::Trap>(0);
// Push CS and IP. // Push CS and IP.
Primitive::push<uint16_t, true>(context.registers.cs(), context); Primitive::push<uint16_t, true>(context.registers.cs(), context);

View File

@ -11,7 +11,7 @@
#include "Instruction.hpp" #include "Instruction.hpp"
#include "Model.hpp" #include "Model.hpp"
#include "Status.hpp" #include "Flags.hpp"
namespace InstructionSet::x86 { namespace InstructionSet::x86 {
@ -44,7 +44,7 @@ template <
typename IOT typename IOT
> struct ExecutionContext { > struct ExecutionContext {
FlowControllerT flow_controller; FlowControllerT flow_controller;
Status status; Flags flags;
RegistersT registers; RegistersT registers;
MemoryT memory; MemoryT memory;
IOT io; IOT io;

View File

@ -1125,7 +1125,7 @@
/* Begin PBXFileReference section */ /* Begin PBXFileReference section */
423BDC492AB24699008E37B6 /* 8088Tests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = 8088Tests.mm; sourceTree = "<group>"; }; 423BDC492AB24699008E37B6 /* 8088Tests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = 8088Tests.mm; sourceTree = "<group>"; };
42437B342ACF02A9006DFED1 /* Status.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Status.hpp; sourceTree = "<group>"; }; 42437B342ACF02A9006DFED1 /* Flags.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Flags.hpp; sourceTree = "<group>"; };
42437B352ACF0AA2006DFED1 /* Perform.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Perform.hpp; sourceTree = "<group>"; }; 42437B352ACF0AA2006DFED1 /* Perform.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Perform.hpp; sourceTree = "<group>"; };
42437B382ACF2798006DFED1 /* PerformImplementation.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = PerformImplementation.hpp; sourceTree = "<group>"; }; 42437B382ACF2798006DFED1 /* PerformImplementation.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = PerformImplementation.hpp; sourceTree = "<group>"; };
42437B392AD07465006DFED1 /* Interrupts.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Interrupts.hpp; sourceTree = "<group>"; }; 42437B392AD07465006DFED1 /* Interrupts.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Interrupts.hpp; sourceTree = "<group>"; };
@ -4999,11 +4999,11 @@
4B69DEB52AB79E4F0055B217 /* Instruction.cpp */, 4B69DEB52AB79E4F0055B217 /* Instruction.cpp */,
4BEDA3B825B25563000C2DBD /* Decoder.hpp */, 4BEDA3B825B25563000C2DBD /* Decoder.hpp */,
4BEDA3DB25B2588F000C2DBD /* Instruction.hpp */, 4BEDA3DB25B2588F000C2DBD /* Instruction.hpp */,
42437B392AD07465006DFED1 /* Interrupts.hpp */,
4BE3C69527CBC540000EAD28 /* Model.hpp */, 4BE3C69527CBC540000EAD28 /* Model.hpp */,
42437B352ACF0AA2006DFED1 /* Perform.hpp */, 42437B352ACF0AA2006DFED1 /* Perform.hpp */,
42437B342ACF02A9006DFED1 /* Status.hpp */, 42437B342ACF02A9006DFED1 /* Flags.hpp */,
42437B372ACF2798006DFED1 /* Implementation */, 42437B372ACF2798006DFED1 /* Implementation */,
42437B392AD07465006DFED1 /* Interrupts.hpp */,
); );
path = x86; path = x86;
sourceTree = "<group>"; sourceTree = "<group>";

View File

@ -21,6 +21,7 @@
#include "../../../InstructionSets/x86/Decoder.hpp" #include "../../../InstructionSets/x86/Decoder.hpp"
#include "../../../InstructionSets/x86/Perform.hpp" #include "../../../InstructionSets/x86/Perform.hpp"
#include "../../../InstructionSets/x86/Flags.hpp"
#include "../../../Numeric/RegisterSizes.hpp" #include "../../../Numeric/RegisterSizes.hpp"
namespace { namespace {
@ -29,7 +30,7 @@ namespace {
// provide their real path here. // provide their real path here.
constexpr char TestSuiteHome[] = "/Users/tharte/Projects/ProcessorTests/8088/v1"; constexpr char TestSuiteHome[] = "/Users/tharte/Projects/ProcessorTests/8088/v1";
using Status = InstructionSet::x86::Status; using Flags = InstructionSet::x86::Flags;
struct Registers { struct Registers {
CPU::RegisterPair16 ax_; CPU::RegisterPair16 ax_;
uint8_t &al() { return ax_.halves.low; } uint8_t &al() { return ax_.halves.low; }
@ -287,8 +288,8 @@ struct IO {
}; };
class FlowController { class FlowController {
public: public:
FlowController(Memory &memory, Registers &registers, Status &status) : FlowController(Memory &memory, Registers &registers, Flags &flags) :
memory_(memory), registers_(registers), status_(status) {} memory_(memory), registers_(registers), flags_(flags) {}
// Requirements for perform. // Requirements for perform.
void jump(uint16_t address) { void jump(uint16_t address) {
@ -318,19 +319,19 @@ class FlowController {
private: private:
Memory &memory_; Memory &memory_;
Registers &registers_; Registers &registers_;
Status &status_; Flags &flags_;
bool should_repeat_ = false; bool should_repeat_ = false;
}; };
struct ExecutionSupport { struct ExecutionSupport {
InstructionSet::x86::Status status; Flags flags;
Registers registers; Registers registers;
Memory memory; Memory memory;
FlowController flow_controller; FlowController flow_controller;
IO io; IO io;
static constexpr auto model = InstructionSet::x86::Model::i8086; static constexpr auto model = InstructionSet::x86::Model::i8086;
ExecutionSupport(): memory(registers), flow_controller(memory, registers, status) {} ExecutionSupport(): memory(registers), flow_controller(memory, registers, flags) {}
void clear() { void clear() {
memory.clear(); memory.clear();
@ -494,7 +495,7 @@ struct FailedExecution {
return isEqual; return isEqual;
} }
- (void)populate:(Registers &)registers status:(InstructionSet::x86::Status &)status value:(NSDictionary *)value { - (void)populate:(Registers &)registers flags:(Flags &)flags value:(NSDictionary *)value {
registers.ax_.full = [value[@"ax"] intValue]; registers.ax_.full = [value[@"ax"] intValue];
registers.bx_.full = [value[@"bx"] intValue]; registers.bx_.full = [value[@"bx"] intValue];
registers.cx_.full = [value[@"cx"] intValue]; registers.cx_.full = [value[@"cx"] intValue];
@ -510,25 +511,25 @@ struct FailedExecution {
registers.ss_ = [value[@"ss"] intValue]; registers.ss_ = [value[@"ss"] intValue];
registers.ip_ = [value[@"ip"] intValue]; registers.ip_ = [value[@"ip"] intValue];
const uint16_t flags = [value[@"flags"] intValue]; const uint16_t flags_value = [value[@"flags"] intValue];
status.set(flags); flags.set(flags_value);
// Apply a quick test of flag packing/unpacking. // Apply a quick test of flag packing/unpacking.
constexpr auto defined_flags = static_cast<uint16_t>( constexpr auto defined_flags = static_cast<uint16_t>(
InstructionSet::x86::ConditionCode::Carry | InstructionSet::x86::FlagValue::Carry |
InstructionSet::x86::ConditionCode::Parity | InstructionSet::x86::FlagValue::Parity |
InstructionSet::x86::ConditionCode::AuxiliaryCarry | InstructionSet::x86::FlagValue::AuxiliaryCarry |
InstructionSet::x86::ConditionCode::Zero | InstructionSet::x86::FlagValue::Zero |
InstructionSet::x86::ConditionCode::Sign | InstructionSet::x86::FlagValue::Sign |
InstructionSet::x86::ConditionCode::Trap | InstructionSet::x86::FlagValue::Trap |
InstructionSet::x86::ConditionCode::Interrupt | InstructionSet::x86::FlagValue::Interrupt |
InstructionSet::x86::ConditionCode::Direction | InstructionSet::x86::FlagValue::Direction |
InstructionSet::x86::ConditionCode::Overflow InstructionSet::x86::FlagValue::Overflow
); );
XCTAssert((status.get() & defined_flags) == (flags & defined_flags), XCTAssert((flags.get() & defined_flags) == (flags_value & defined_flags),
"Set status of %04x was returned as %04x", "Set flags of %04x was returned as %04x",
flags & defined_flags, flags_value & defined_flags,
(status.get() & defined_flags) (flags.get() & defined_flags)
); );
} }
@ -544,7 +545,7 @@ struct FailedExecution {
NSDictionary *const final_state = test[@"final"]; NSDictionary *const final_state = test[@"final"];
// Apply initial state. // Apply initial state.
InstructionSet::x86::Status initial_status; Flags initial_flags;
for(NSArray<NSNumber *> *ram in initial_state[@"ram"]) { for(NSArray<NSNumber *> *ram in initial_state[@"ram"]) {
execution_support.memory.seed([ram[0] intValue], [ram[1] intValue]); execution_support.memory.seed([ram[0] intValue], [ram[1] intValue]);
} }
@ -552,8 +553,8 @@ struct FailedExecution {
execution_support.memory.touch([ram[0] intValue]); execution_support.memory.touch([ram[0] intValue]);
} }
Registers initial_registers; Registers initial_registers;
[self populate:initial_registers status:initial_status value:initial_state[@"regs"]]; [self populate:initial_registers flags:initial_flags value:initial_state[@"regs"]];
execution_support.status = initial_status; execution_support.flags = initial_flags;
execution_support.registers = initial_registers; execution_support.registers = initial_registers;
// Execute instruction. // Execute instruction.
@ -571,7 +572,7 @@ struct FailedExecution {
// Compare final state. // Compare final state.
Registers intended_registers; Registers intended_registers;
InstructionSet::x86::Status intended_status; InstructionSet::x86::Flags intended_flags;
bool ramEqual = true; bool ramEqual = true;
int mask_position = 0; int mask_position = 0;
@ -602,21 +603,21 @@ struct FailedExecution {
break; break;
} }
[self populate:intended_registers status:intended_status value:final_state[@"regs"]]; [self populate:intended_registers flags:intended_flags value:final_state[@"regs"]];
const bool registersEqual = intended_registers == execution_support.registers; const bool registersEqual = intended_registers == execution_support.registers;
const bool statusEqual = (intended_status.get() & flags_mask) == (execution_support.status.get() & flags_mask); const bool flagsEqual = (intended_flags.get() & flags_mask) == (execution_support.flags.get() & flags_mask);
if(!statusEqual || !registersEqual || !ramEqual) { if(!flagsEqual || !registersEqual || !ramEqual) {
FailedExecution failure; FailedExecution failure;
failure.instruction = decoded.second; failure.instruction = decoded.second;
failure.test_name = std::string([test[@"name"] UTF8String]); failure.test_name = std::string([test[@"name"] UTF8String]);
NSMutableArray<NSString *> *reasons = [[NSMutableArray alloc] init]; NSMutableArray<NSString *> *reasons = [[NSMutableArray alloc] init];
if(!statusEqual) { if(!flagsEqual) {
Status difference; Flags difference;
difference.set((intended_status.get() ^ execution_support.status.get()) & flags_mask); difference.set((intended_flags.get() ^ execution_support.flags.get()) & flags_mask);
[reasons addObject: [reasons addObject:
[NSString stringWithFormat:@"status differs; errors in %s", [NSString stringWithFormat:@"flags differs; errors in %s",
difference.to_string().c_str()]]; difference.to_string().c_str()]];
} }
if(!registersEqual) { if(!registersEqual) {