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:
commit
7f4fa914dd
@ -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 */
|
@ -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);
|
||||||
|
@ -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;
|
||||||
|
@ -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>";
|
||||||
|
@ -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 ®isters, Status &status) :
|
FlowController(Memory &memory, Registers ®isters, 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 ®isters_;
|
Registers ®isters_;
|
||||||
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) {
|
||||||
|
Loading…
Reference in New Issue
Block a user