1
0
mirror of https://github.com/TomHarte/CLK.git synced 2025-08-15 14:27:29 +00:00

Fixed R incrementation and attempted to make the status flags cheaper to write to.

This commit is contained in:
Thomas Harte
2017-05-29 22:23:19 -04:00
parent 4d4695032c
commit c6185baa99
2 changed files with 144 additions and 145 deletions

View File

@@ -63,7 +63,7 @@
</AdditionalOptions> </AdditionalOptions>
</TestAction> </TestAction>
<LaunchAction <LaunchAction
buildConfiguration = "Debug" buildConfiguration = "Release"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0" launchStyle = "0"

View File

@@ -175,7 +175,13 @@ template <class T> class Processor: public MicroOpScheduler<MicroOp> {
RegisterPair ix_, iy_, pc_, sp_; RegisterPair ix_, iy_, pc_, sp_;
bool iff1_, iff2_; bool iff1_, iff2_;
int interrupt_mode_; int interrupt_mode_;
uint8_t sign_result_, zero_result_, bit5_result_, half_carry_flag_, bit3_result_, parity_overflow_flag_, subtract_flag_, carry_flag_; uint8_t sign_result_; // the sign flag is set if the value in sign_result_ is negative
uint8_t zero_result_; // the zero flag is set if the value in zero_result_ is zero
uint8_t half_carry_result_; // the half-carry flag is set if bit 4 of half_carry_result_ is set
uint8_t bit53_result_; // the bit 3 and 5 flags are set if the corresponding bits of bit53_result_ are set
uint8_t parity_overflow_result_; // the parity/overflow flag is set if the corresponding bit of parity_overflow_result_ is set
uint8_t subtract_flag_; // contains a copy of the subtract flag in isolation
uint8_t carry_result_; // the carry flag is set if bit 0 of carry_result_ is set
bool is_halted_; bool is_halted_;
int number_of_cycles_; int number_of_cycles_;
@@ -189,6 +195,8 @@ template <class T> class Processor: public MicroOpScheduler<MicroOp> {
std::vector<MicroOp> all_operations; std::vector<MicroOp> all_operations;
std::vector<MicroOp> fetch_decode_execute; std::vector<MicroOp> fetch_decode_execute;
bool increments_r; bool increments_r;
InstructionPage() : increments_r(true) {}
}; };
InstructionPage *current_instruction_page_; InstructionPage *current_instruction_page_;
@@ -682,11 +690,10 @@ template <class T> class Processor: public MicroOpScheduler<MicroOp> {
schedule_program_program_counter_++; schedule_program_program_counter_++;
#define set_parity(v) \ #define set_parity(v) \
parity_overflow_flag_ = v^1;\ parity_overflow_result_ = v^1;\
parity_overflow_flag_ ^= parity_overflow_flag_ >> 4;\ parity_overflow_result_ ^= parity_overflow_result_ >> 4;\
parity_overflow_flag_ ^= parity_overflow_flag_ << 2;\ parity_overflow_result_ ^= parity_overflow_result_ << 2;\
parity_overflow_flag_ ^= parity_overflow_flag_ >> 1;\ parity_overflow_result_ ^= parity_overflow_result_ >> 1;
parity_overflow_flag_ &= Flag::Parity;
switch(operation->type) { switch(operation->type) {
case MicroOp::BusOperation: case MicroOp::BusOperation:
@@ -721,11 +728,11 @@ template <class T> class Processor: public MicroOpScheduler<MicroOp> {
#pragma mark - Logical #pragma mark - Logical
#define set_logical_flags(hf) \ #define set_logical_flags(hf) \
sign_result_ = zero_result_ = bit5_result_ = bit3_result_ = a_; \ sign_result_ = zero_result_ = bit53_result_ = a_; \
set_parity(a_); \ set_parity(a_); \
half_carry_flag_ = hf; \ half_carry_result_ = hf; \
subtract_flag_ = 0; \ subtract_flag_ = 0; \
carry_flag_ = 0; carry_result_ = 0;
case MicroOp::And: case MicroOp::And:
a_ &= *(uint8_t *)operation->source; a_ &= *(uint8_t *)operation->source;
@@ -747,22 +754,22 @@ template <class T> class Processor: public MicroOpScheduler<MicroOp> {
case MicroOp::CPL: case MicroOp::CPL:
a_ ^= 0xff; a_ ^= 0xff;
subtract_flag_ = Flag::Subtract; subtract_flag_ = Flag::Subtract;
half_carry_flag_ = Flag::HalfCarry; half_carry_result_ = Flag::HalfCarry;
bit5_result_ = bit3_result_ = a_; bit53_result_ = a_;
break; break;
case MicroOp::CCF: case MicroOp::CCF:
half_carry_flag_ = carry_flag_ << 4; half_carry_result_ = carry_result_ << 4;
carry_flag_ ^= Flag::Carry; carry_result_ ^= Flag::Carry;
subtract_flag_ = 0; subtract_flag_ = 0;
bit5_result_ = bit3_result_ = a_; bit53_result_ = a_;
break; break;
case MicroOp::SCF: case MicroOp::SCF:
carry_flag_ = Flag::Carry; carry_result_ = Flag::Carry;
half_carry_flag_ = 0; half_carry_result_ = 0;
subtract_flag_ = 0; subtract_flag_ = 0;
bit5_result_ = bit3_result_ = a_; bit53_result_ = a_;
break; break;
#pragma mark - Flow control #pragma mark - Flow control
@@ -792,11 +799,11 @@ template <class T> class Processor: public MicroOpScheduler<MicroOp> {
sign_result_ = // set sign and zero sign_result_ = // set sign and zero
zero_result_ = (uint8_t)result; zero_result_ = (uint8_t)result;
bit3_result_ = bit5_result_ = value; // set the 5 and 3 flags, which come bit53_result_ = value; // set the 5 and 3 flags, which come
// from the operand atypically // from the operand atypically
carry_flag_ = (result >> 8) & Flag::Carry; carry_result_ = result >> 8;
half_carry_flag_ = halfResult & Flag::HalfCarry; half_carry_result_ = halfResult;
parity_overflow_flag_ = (overflow&0x80) >> 5; parity_overflow_result_ = overflow >> 5;
subtract_flag_ = Flag::Subtract; subtract_flag_ = Flag::Subtract;
} break; } break;
@@ -811,18 +818,17 @@ template <class T> class Processor: public MicroOpScheduler<MicroOp> {
a_ = (uint8_t)result; a_ = (uint8_t)result;
sign_result_ = zero_result_ = sign_result_ = zero_result_ = bit53_result_ = (uint8_t)result;
bit5_result_ = bit3_result_ = (uint8_t)result; carry_result_ = result >> 8;
carry_flag_ = (result >> 8) & Flag::Carry; half_carry_result_ = halfResult;
half_carry_flag_ = halfResult & Flag::HalfCarry; parity_overflow_result_ = overflow >> 5;
parity_overflow_flag_ = (overflow&0x80) >> 5;
subtract_flag_ = Flag::Subtract; subtract_flag_ = Flag::Subtract;
} break; } break;
case MicroOp::SBC8: { case MicroOp::SBC8: {
uint8_t value = *(uint8_t *)operation->source; uint8_t value = *(uint8_t *)operation->source;
int result = a_ - value - carry_flag_; int result = a_ - value - (carry_result_ & Flag::Carry);
int halfResult = (a_&0xf) - (value&0xf) - carry_flag_; int halfResult = (a_&0xf) - (value&0xf) - (carry_result_ & Flag::Carry);
// overflow for a subtraction is when the signs were originally // overflow for a subtraction is when the signs were originally
// different and the result is different again // different and the result is different again
@@ -830,11 +836,10 @@ template <class T> class Processor: public MicroOpScheduler<MicroOp> {
a_ = (uint8_t)result; a_ = (uint8_t)result;
sign_result_ = zero_result_ = sign_result_ = zero_result_ = bit53_result_ = (uint8_t)result;
bit5_result_ = bit3_result_ = (uint8_t)result; carry_result_ = result >> 8;
carry_flag_ = (result >> 8) & Flag::Carry; half_carry_result_ = halfResult;
half_carry_flag_ = halfResult & Flag::HalfCarry; parity_overflow_result_ = overflow >> 5;
parity_overflow_flag_ = (overflow&0x80) >> 5;
subtract_flag_ = Flag::Subtract; subtract_flag_ = Flag::Subtract;
} break; } break;
@@ -849,18 +854,17 @@ template <class T> class Processor: public MicroOpScheduler<MicroOp> {
a_ = (uint8_t)result; a_ = (uint8_t)result;
sign_result_ = zero_result_ = sign_result_ = zero_result_ = bit53_result_ = (uint8_t)result;
bit3_result_ = bit5_result_ = (uint8_t)result; carry_result_ = result >> 8;
carry_flag_ = (result >> 8) & Flag::Carry; half_carry_result_ = halfResult;
half_carry_flag_ = halfResult & Flag::HalfCarry; parity_overflow_result_ = overflow >> 5;
parity_overflow_flag_ = (overflow&0x80) >> 5;
subtract_flag_ = 0; subtract_flag_ = 0;
} break; } break;
case MicroOp::ADC8: { case MicroOp::ADC8: {
uint8_t value = *(uint8_t *)operation->source; uint8_t value = *(uint8_t *)operation->source;
int result = a_ + value + carry_flag_; int result = a_ + value + (carry_result_ & Flag::Carry);
int halfResult = (a_&0xf) + (value&0xf) + carry_flag_; int halfResult = (a_&0xf) + (value&0xf) + (carry_result_ & Flag::Carry);
// overflow for addition is when the signs were originally // overflow for addition is when the signs were originally
// the same and the result is different // the same and the result is different
@@ -868,11 +872,10 @@ template <class T> class Processor: public MicroOpScheduler<MicroOp> {
a_ = (uint8_t)result; a_ = (uint8_t)result;
sign_result_ = zero_result_ = sign_result_ = zero_result_ = bit53_result_ = (uint8_t)result;
bit5_result_ = bit3_result_ = (uint8_t)result; carry_result_ = result >> 8;
carry_flag_ = (result >> 8) & Flag::Carry; half_carry_result_ = halfResult;
half_carry_flag_ = halfResult & Flag::HalfCarry; parity_overflow_result_ = overflow >> 5;
parity_overflow_flag_ = (overflow&0x80) >> 5;
subtract_flag_ = 0; subtract_flag_ = 0;
} break; } break;
@@ -882,11 +885,11 @@ template <class T> class Processor: public MicroOpScheduler<MicroOp> {
int halfResult = -(a_&0xf); int halfResult = -(a_&0xf);
a_ = (uint8_t)result; a_ = (uint8_t)result;
bit5_result_ = bit3_result_ = sign_result_ = zero_result_ = a_; bit53_result_ = sign_result_ = zero_result_ = a_;
parity_overflow_flag_ = overflow ? Flag::Overflow : 0; parity_overflow_result_ = overflow ? Flag::Overflow : 0;
subtract_flag_ = Flag::Subtract; subtract_flag_ = Flag::Subtract;
carry_flag_ = (result >> 8) & Flag::Carry; carry_result_ = result >> 8;
half_carry_flag_ = halfResult & Flag::HalfCarry; half_carry_result_ = halfResult;
} break; } break;
case MicroOp::Increment8: { case MicroOp::Increment8: {
@@ -901,9 +904,9 @@ template <class T> class Processor: public MicroOpScheduler<MicroOp> {
*(uint8_t *)operation->source = (uint8_t)result; *(uint8_t *)operation->source = (uint8_t)result;
// sign, zero and 5 & 3 are set directly from the result // sign, zero and 5 & 3 are set directly from the result
bit5_result_ = bit3_result_ = sign_result_ = zero_result_ = (uint8_t)result; bit53_result_ = sign_result_ = zero_result_ = (uint8_t)result;
half_carry_flag_ = half_result & Flag::HalfCarry; half_carry_result_ = half_result;
parity_overflow_flag_ = (overflow >> 5)&Flag::Overflow; parity_overflow_result_ = overflow >> 5;
subtract_flag_ = 0; subtract_flag_ = 0;
} break; } break;
@@ -919,9 +922,9 @@ template <class T> class Processor: public MicroOpScheduler<MicroOp> {
*(uint8_t *)operation->source = (uint8_t)result; *(uint8_t *)operation->source = (uint8_t)result;
// sign, zero and 5 & 3 are set directly from the result // sign, zero and 5 & 3 are set directly from the result
bit5_result_ = bit3_result_ = sign_result_ = zero_result_ = (uint8_t)result; bit53_result_ = sign_result_ = zero_result_ = (uint8_t)result;
half_carry_flag_ = half_result & Flag::HalfCarry; half_carry_result_ = half_result;
parity_overflow_flag_ = (overflow >> 5)&Flag::Overflow; parity_overflow_result_ = overflow >> 5;
subtract_flag_ = Flag::Subtract; subtract_flag_ = Flag::Subtract;
} break; } break;
@@ -930,13 +933,13 @@ template <class T> class Processor: public MicroOpScheduler<MicroOp> {
int highNibble = a_ >> 4; int highNibble = a_ >> 4;
int amountToAdd = 0; int amountToAdd = 0;
if(carry_flag_) if(carry_result_ & Flag::Carry)
{ {
amountToAdd = (lowNibble > 0x9 || half_carry_flag_) ? 0x66 : 0x60; amountToAdd = (lowNibble > 0x9 || (half_carry_result_ & Flag::HalfCarry)) ? 0x66 : 0x60;
} }
else else
{ {
if(half_carry_flag_) if(half_carry_result_ & Flag::HalfCarry)
{ {
if(lowNibble > 0x9) if(lowNibble > 0x9)
amountToAdd = (highNibble > 0x8) ? 0x66 : 0x06; amountToAdd = (highNibble > 0x8) ? 0x66 : 0x06;
@@ -952,30 +955,30 @@ template <class T> class Processor: public MicroOpScheduler<MicroOp> {
} }
} }
if(!carry_flag_) if(!(carry_result_ & Flag::Carry))
{ {
if(lowNibble > 0x9) if(lowNibble > 0x9)
{ {
if(highNibble > 0x8) carry_flag_ = Flag::Carry; if(highNibble > 0x8) carry_result_ = Flag::Carry;
} }
else else
{ {
if(highNibble > 0x9) carry_flag_ = Flag::Carry; if(highNibble > 0x9) carry_result_ = Flag::Carry;
} }
} }
if(subtract_flag_) if(subtract_flag_)
{ {
a_ -= amountToAdd; a_ -= amountToAdd;
half_carry_flag_ = (half_carry_flag_ && lowNibble < 0x6) ? Flag::HalfCarry : 0; half_carry_result_ = ((half_carry_result_ & Flag::HalfCarry) && lowNibble < 0x6) ? Flag::HalfCarry : 0;
} }
else else
{ {
a_ += amountToAdd; a_ += amountToAdd;
half_carry_flag_ = (lowNibble > 0x9) ? Flag::HalfCarry : 0; half_carry_result_ = (lowNibble > 0x9) ? Flag::HalfCarry : 0;
} }
sign_result_ = zero_result_ = bit3_result_ = bit5_result_ = a_; sign_result_ = zero_result_ = bit53_result_ = a_;
set_parity(a_); set_parity(a_);
} break; } break;
@@ -988,9 +991,9 @@ template <class T> class Processor: public MicroOpScheduler<MicroOp> {
int result = sourceValue + destinationValue; int result = sourceValue + destinationValue;
int halfResult = (sourceValue&0xfff) + (destinationValue&0xfff); int halfResult = (sourceValue&0xfff) + (destinationValue&0xfff);
bit3_result_ = bit5_result_ = (uint8_t)(result >> 8); bit53_result_ = (uint8_t)(result >> 8);
carry_flag_ = (result >> 16) & Flag::Carry; carry_result_ = result >> 16;
half_carry_flag_ = (halfResult >> 8) & Flag::HalfCarry; half_carry_result_ = (halfResult >> 8);
subtract_flag_ = 0; subtract_flag_ = 0;
*(uint16_t *)operation->destination = (uint16_t)result; *(uint16_t *)operation->destination = (uint16_t)result;
@@ -999,19 +1002,18 @@ template <class T> class Processor: public MicroOpScheduler<MicroOp> {
case MicroOp::ADC16: { case MicroOp::ADC16: {
uint16_t sourceValue = *(uint16_t *)operation->source; uint16_t sourceValue = *(uint16_t *)operation->source;
uint16_t destinationValue = *(uint16_t *)operation->destination; uint16_t destinationValue = *(uint16_t *)operation->destination;
int result = sourceValue + destinationValue + carry_flag_; int result = sourceValue + destinationValue + (carry_result_ & Flag::Carry);
int halfResult = (sourceValue&0xfff) + (destinationValue&0xfff) + carry_flag_; int halfResult = (sourceValue&0xfff) + (destinationValue&0xfff) + (carry_result_ & Flag::Carry);
int overflow = (result ^ destinationValue) & ~(destinationValue ^ sourceValue); int overflow = (result ^ destinationValue) & ~(destinationValue ^ sourceValue);
bit5_result_ = bit53_result_ =
bit3_result_ =
sign_result_ = (uint8_t)(result >> 8); sign_result_ = (uint8_t)(result >> 8);
zero_result_ = (uint8_t)(result | sign_result_); zero_result_ = (uint8_t)(result | sign_result_);
subtract_flag_ = 0; subtract_flag_ = 0;
carry_flag_ = result >> 16; carry_result_ = result >> 16;
half_carry_flag_ = (halfResult >> 8) & Flag::HalfCarry; half_carry_result_ = halfResult >> 8;
parity_overflow_flag_ = (overflow & 0x8000) >> 13; parity_overflow_result_ = overflow >> 13;
*(uint16_t *)operation->destination = (uint16_t)result; *(uint16_t *)operation->destination = (uint16_t)result;
} break; } break;
@@ -1019,36 +1021,35 @@ template <class T> class Processor: public MicroOpScheduler<MicroOp> {
case MicroOp::SBC16: { case MicroOp::SBC16: {
uint16_t sourceValue = *(uint16_t *)operation->source; uint16_t sourceValue = *(uint16_t *)operation->source;
uint16_t destinationValue = *(uint16_t *)operation->destination; uint16_t destinationValue = *(uint16_t *)operation->destination;
int result = destinationValue - sourceValue - carry_flag_; int result = destinationValue - sourceValue - (carry_result_ & Flag::Carry);
int halfResult = (destinationValue&0xfff) - (sourceValue&0xfff) - carry_flag_; int halfResult = (destinationValue&0xfff) - (sourceValue&0xfff) - (carry_result_ & Flag::Carry);
// subtraction, so parity rules are: // subtraction, so parity rules are:
// signs of operands were different, // signs of operands were different,
// sign of result is different // sign of result is different
int overflow = (result ^ destinationValue) & (sourceValue ^ destinationValue); int overflow = (result ^ destinationValue) & (sourceValue ^ destinationValue);
bit5_result_ = bit53_result_ =
bit3_result_ =
sign_result_ = (uint8_t)(result >> 8); sign_result_ = (uint8_t)(result >> 8);
zero_result_ = (uint8_t)(result | sign_result_); zero_result_ = (uint8_t)(result | sign_result_);
subtract_flag_ = Flag::Subtract; subtract_flag_ = Flag::Subtract;
carry_flag_ = (result >> 16) & Flag::Carry; carry_result_ = result >> 16;
half_carry_flag_ = (halfResult >> 8) & Flag::HalfCarry; half_carry_result_ = halfResult >> 8;
parity_overflow_flag_ = (overflow & 0x8000) >> 13; parity_overflow_result_ = overflow >> 13;
*(uint16_t *)operation->destination = (uint16_t)result; *(uint16_t *)operation->destination = (uint16_t)result;
} break; } break;
#pragma mark - Conditionals #pragma mark - Conditionals
case MicroOp::TestNZ: if(!zero_result_) { move_to_next_program(); checkSchedule(); } break; case MicroOp::TestNZ: if(!zero_result_) { move_to_next_program(); checkSchedule(); } break;
case MicroOp::TestZ: if(zero_result_) { move_to_next_program(); checkSchedule(); } break; case MicroOp::TestZ: if(zero_result_) { move_to_next_program(); checkSchedule(); } break;
case MicroOp::TestNC: if(carry_flag_) { move_to_next_program(); checkSchedule(); } break; case MicroOp::TestNC: if(carry_result_ & Flag::Carry) { move_to_next_program(); checkSchedule(); } break;
case MicroOp::TestC: if(!carry_flag_) { move_to_next_program(); checkSchedule(); } break; case MicroOp::TestC: if(!(carry_result_ & Flag::Carry)) { move_to_next_program(); checkSchedule(); } break;
case MicroOp::TestPO: if(parity_overflow_flag_) { move_to_next_program(); checkSchedule(); } break; case MicroOp::TestPO: if(parity_overflow_result_ & Flag::Parity) { move_to_next_program(); checkSchedule(); } break;
case MicroOp::TestPE: if(!parity_overflow_flag_) { move_to_next_program(); checkSchedule(); } break; case MicroOp::TestPE: if(!(parity_overflow_result_ & Flag::Parity)) { move_to_next_program(); checkSchedule(); } break;
case MicroOp::TestP: if(sign_result_ & 0x80) { move_to_next_program(); checkSchedule(); } break; case MicroOp::TestP: if(sign_result_ & Flag::Sign) { move_to_next_program(); checkSchedule(); } break;
case MicroOp::TestM: if(!(sign_result_ & 0x80)) { move_to_next_program(); checkSchedule(); } break; case MicroOp::TestM: if(!(sign_result_ & Flag::Sign)) { move_to_next_program(); checkSchedule(); } break;
#pragma mark - Exchange #pragma mark - Exchange
@@ -1091,10 +1092,10 @@ template <class T> class Processor: public MicroOpScheduler<MicroOp> {
bc_.full--; \ bc_.full--; \
de_.full += (operation->type == incr) ? 1 : -1; \ de_.full += (operation->type == incr) ? 1 : -1; \
hl_.full += (operation->type == incr) ? 1 : -1; \ hl_.full += (operation->type == incr) ? 1 : -1; \
bit3_result_ = bit5_result_ = a_ + temp8_; \ bit53_result_ = a_ + temp8_; \
subtract_flag_ = 0; \ subtract_flag_ = 0; \
half_carry_flag_ = 0; \ half_carry_result_ = 0; \
parity_overflow_flag_ = bc_.full ? Flag::Parity : 0; parity_overflow_result_ = bc_.full ? Flag::Parity : 0;
case MicroOp::LDDR: case MicroOp::LDDR:
case MicroOp::LDIR: { case MicroOp::LDIR: {
@@ -1116,10 +1117,10 @@ template <class T> class Processor: public MicroOpScheduler<MicroOp> {
uint8_t result = a_ - temp8_; \ uint8_t result = a_ - temp8_; \
uint8_t halfResult = (a_&0xf) - (temp8_&0xf); \ uint8_t halfResult = (a_&0xf) - (temp8_&0xf); \
\ \
parity_overflow_flag_ = bc_.full ? Flag::Parity : 0; \ parity_overflow_result_ = bc_.full ? Flag::Parity : 0; \
half_carry_flag_ = halfResult & Flag::HalfCarry; \ half_carry_result_ = halfResult; \
subtract_flag_ = Flag::Subtract; \ subtract_flag_ = Flag::Subtract; \
bit5_result_ = bit3_result_ = (uint8_t)((result&0x8) | ((result&0x2) << 4)); \ bit53_result_ = (uint8_t)((result&0x8) | ((result&0x2) << 4)); \
sign_result_ = zero_result_ = result; sign_result_ = zero_result_ = result;
case MicroOp::CPDR: case MicroOp::CPDR:
@@ -1139,18 +1140,18 @@ template <class T> class Processor: public MicroOpScheduler<MicroOp> {
bc_.bytes.high--; \ bc_.bytes.high--; \
hl_.full += (operation->type == incr) ? 1 : -1; \ hl_.full += (operation->type == incr) ? 1 : -1; \
\ \
sign_result_ = zero_result_ = bit3_result_ = bit5_result_ = bc_.bytes.high; \ sign_result_ = zero_result_ = bit53_result_ = bc_.bytes.high; \
subtract_flag_ = (temp8_ >> 6) & Flag::Subtract; \ subtract_flag_ = (temp8_ >> 6) & Flag::Subtract; \
\ \
int next_bc = bc_.bytes.low + ((operation->type == incr) ? 1 : -1); \ int next_bc = bc_.bytes.low + ((operation->type == incr) ? 1 : -1); \
int summation = temp8_ + (next_bc&0xff); \ int summation = temp8_ + (next_bc&0xff); \
\ \
if(summation > 0xff) { \ if(summation > 0xff) { \
carry_flag_ = Flag::Carry; \ carry_result_ = Flag::Carry; \
half_carry_flag_ = Flag::HalfCarry; \ half_carry_result_ = Flag::HalfCarry; \
} else { \ } else { \
carry_flag_ = 0; \ carry_result_ = 0; \
half_carry_flag_ = 0; \ half_carry_result_ = 0; \
} \ } \
\ \
summation = (summation&7) ^ bc_.bytes.high; \ summation = (summation&7) ^ bc_.bytes.high; \
@@ -1173,15 +1174,15 @@ template <class T> class Processor: public MicroOpScheduler<MicroOp> {
bc_.bytes.high--; \ bc_.bytes.high--; \
hl_.full += (operation->type == incr) ? 1 : -1; \ hl_.full += (operation->type == incr) ? 1 : -1; \
\ \
sign_result_ = zero_result_ = bit5_result_ = bit3_result_ = bc_.bytes.high; \ sign_result_ = zero_result_ = bit53_result_ = bc_.bytes.high; \
subtract_flag_ = (temp8_ >> 6) & Flag::Subtract; \ subtract_flag_ = (temp8_ >> 6) & Flag::Subtract; \
\ \
int summation = temp8_ + hl_.bytes.low; \ int summation = temp8_ + hl_.bytes.low; \
if(summation > 0xff) { \ if(summation > 0xff) { \
carry_flag_ = Flag::Carry; \ carry_result_ = Flag::Carry; \
half_carry_flag_ = Flag::HalfCarry; \ half_carry_result_ = Flag::HalfCarry; \
} else { \ } else { \
carry_flag_ = half_carry_flag_ = 0; \ carry_result_ = half_carry_result_ = 0; \
} \ } \
\ \
summation = (summation&7) ^ bc_.bytes.high; \ summation = (summation&7) ^ bc_.bytes.high; \
@@ -1204,10 +1205,10 @@ template <class T> class Processor: public MicroOpScheduler<MicroOp> {
uint8_t result = *(uint8_t *)operation->source & (1 << ((operation_ >> 3)&7)); uint8_t result = *(uint8_t *)operation->source & (1 << ((operation_ >> 3)&7));
sign_result_ = zero_result_ = result; sign_result_ = zero_result_ = result;
bit3_result_ = bit5_result_ = *(uint8_t *)operation->source; // This is a divergence between FUSE and The Undocumented Z80 Documented. bit53_result_ = *(uint8_t *)operation->source; // This is a divergence between FUSE and The Undocumented Z80 Documented.
half_carry_flag_ = Flag::HalfCarry; half_carry_result_ = Flag::HalfCarry;
subtract_flag_ = 0; subtract_flag_ = 0;
parity_overflow_flag_ = result ? 0 : Flag::Parity; parity_overflow_result_ = result ? 0 : Flag::Parity;
} break; } break;
case MicroOp::RES: case MicroOp::RES:
@@ -1221,19 +1222,19 @@ template <class T> class Processor: public MicroOpScheduler<MicroOp> {
#pragma mark - Rotation and shifting #pragma mark - Rotation and shifting
#define set_rotate_flags() \ #define set_rotate_flags() \
bit3_result_ = bit5_result_ = a_; \ bit53_result_ = a_; \
carry_flag_ = new_carry; \ carry_result_ = new_carry; \
subtract_flag_ = half_carry_flag_ = 0; subtract_flag_ = half_carry_result_ = 0;
case MicroOp::RLA: { case MicroOp::RLA: {
uint8_t new_carry = a_ >> 7; uint8_t new_carry = a_ >> 7;
a_ = (uint8_t)((a_ << 1) | carry_flag_); a_ = (uint8_t)((a_ << 1) | (carry_result_ & Flag::Carry));
set_rotate_flags(); set_rotate_flags();
} break; } break;
case MicroOp::RRA: { case MicroOp::RRA: {
uint8_t new_carry = a_ & 1; uint8_t new_carry = a_ & 1;
a_ = (uint8_t)((a_ >> 1) | (carry_flag_ << 7)); a_ = (uint8_t)((a_ >> 1) | (carry_result_ << 7));
set_rotate_flags(); set_rotate_flags();
} break; } break;
@@ -1252,57 +1253,57 @@ template <class T> class Processor: public MicroOpScheduler<MicroOp> {
#undef set_rotate_flags #undef set_rotate_flags
#define set_shift_flags() \ #define set_shift_flags() \
sign_result_ = zero_result_ = bit5_result_ = bit3_result_ = *(uint8_t *)operation->source; \ sign_result_ = zero_result_ = bit53_result_ = *(uint8_t *)operation->source; \
set_parity(sign_result_); \ set_parity(sign_result_); \
half_carry_flag_ = 0; \ half_carry_result_ = 0; \
subtract_flag_ = 0; subtract_flag_ = 0;
case MicroOp::RLC: case MicroOp::RLC:
carry_flag_ = *(uint8_t *)operation->source >> 7; carry_result_ = *(uint8_t *)operation->source >> 7;
*(uint8_t *)operation->source = (uint8_t)((*(uint8_t *)operation->source << 1) | carry_flag_); *(uint8_t *)operation->source = (uint8_t)((*(uint8_t *)operation->source << 1) | carry_result_);
set_shift_flags(); set_shift_flags();
break; break;
case MicroOp::RRC: case MicroOp::RRC:
carry_flag_ = *(uint8_t *)operation->source & 1; carry_result_ = *(uint8_t *)operation->source;
*(uint8_t *)operation->source = (uint8_t)((*(uint8_t *)operation->source >> 1) | (carry_flag_ << 7)); *(uint8_t *)operation->source = (uint8_t)((*(uint8_t *)operation->source >> 1) | (carry_result_ << 7));
set_shift_flags(); set_shift_flags();
break; break;
case MicroOp::RL: { case MicroOp::RL: {
uint8_t next_carry = *(uint8_t *)operation->source >> 7; uint8_t next_carry = *(uint8_t *)operation->source >> 7;
*(uint8_t *)operation->source = (uint8_t)((*(uint8_t *)operation->source << 1) | carry_flag_); *(uint8_t *)operation->source = (uint8_t)((*(uint8_t *)operation->source << 1) | (carry_result_ & Flag::Carry));
carry_flag_ = next_carry; carry_result_ = next_carry;
set_shift_flags(); set_shift_flags();
} break; } break;
case MicroOp::RR: { case MicroOp::RR: {
uint8_t next_carry = *(uint8_t *)operation->source & 1; uint8_t next_carry = *(uint8_t *)operation->source;
*(uint8_t *)operation->source = (uint8_t)((*(uint8_t *)operation->source >> 1) | (carry_flag_ << 7)); *(uint8_t *)operation->source = (uint8_t)((*(uint8_t *)operation->source >> 1) | (carry_result_ << 7));
carry_flag_ = next_carry; carry_result_ = next_carry;
set_shift_flags(); set_shift_flags();
} break; } break;
case MicroOp::SLA: case MicroOp::SLA:
carry_flag_ = *(uint8_t *)operation->source >> 7; carry_result_ = *(uint8_t *)operation->source >> 7;
*(uint8_t *)operation->source = (uint8_t)(*(uint8_t *)operation->source << 1); *(uint8_t *)operation->source = (uint8_t)(*(uint8_t *)operation->source << 1);
set_shift_flags(); set_shift_flags();
break; break;
case MicroOp::SRA: case MicroOp::SRA:
carry_flag_ = *(uint8_t *)operation->source & 1; carry_result_ = *(uint8_t *)operation->source;
*(uint8_t *)operation->source = (uint8_t)((*(uint8_t *)operation->source >> 1) | (*(uint8_t *)operation->source & 0x80)); *(uint8_t *)operation->source = (uint8_t)((*(uint8_t *)operation->source >> 1) | (*(uint8_t *)operation->source & 0x80));
set_shift_flags(); set_shift_flags();
break; break;
case MicroOp::SLL: case MicroOp::SLL:
carry_flag_ = *(uint8_t *)operation->source >> 7; carry_result_ = *(uint8_t *)operation->source >> 7;
*(uint8_t *)operation->source = (uint8_t)(*(uint8_t *)operation->source << 1) | 1; *(uint8_t *)operation->source = (uint8_t)(*(uint8_t *)operation->source << 1) | 1;
set_shift_flags(); set_shift_flags();
break; break;
case MicroOp::SRL: case MicroOp::SRL:
carry_flag_ = *(uint8_t *)operation->source & 1; carry_result_ = *(uint8_t *)operation->source;
*(uint8_t *)operation->source = (uint8_t)((*(uint8_t *)operation->source >> 1)); *(uint8_t *)operation->source = (uint8_t)((*(uint8_t *)operation->source >> 1));
set_shift_flags(); set_shift_flags();
break; break;
@@ -1311,9 +1312,9 @@ template <class T> class Processor: public MicroOpScheduler<MicroOp> {
#define set_decimal_rotate_flags() \ #define set_decimal_rotate_flags() \
subtract_flag_ = 0; \ subtract_flag_ = 0; \
half_carry_flag_ = 0; \ half_carry_result_ = 0; \
set_parity(a_); \ set_parity(a_); \
bit3_result_ = bit5_result_ = zero_result_ = sign_result_ = a_; bit53_result_ = zero_result_ = sign_result_ = a_;
case MicroOp::RRD: { case MicroOp::RRD: {
uint8_t low_nibble = a_ & 0xf; uint8_t low_nibble = a_ & 0xf;
@@ -1354,15 +1355,15 @@ template <class T> class Processor: public MicroOpScheduler<MicroOp> {
#pragma mark - Input #pragma mark - Input
case MicroOp::SetInFlags: case MicroOp::SetInFlags:
subtract_flag_ = half_carry_flag_ = 0; subtract_flag_ = half_carry_result_ = 0;
sign_result_ = zero_result_ = bit3_result_ = bit5_result_ = *(uint8_t *)operation->source; sign_result_ = zero_result_ = bit53_result_ = *(uint8_t *)operation->source;
set_parity(sign_result_); set_parity(sign_result_);
break; break;
case MicroOp::SetAFlags: case MicroOp::SetAFlags:
subtract_flag_ = half_carry_flag_ = 0; subtract_flag_ = half_carry_result_ = 0;
parity_overflow_flag_ = iff2_ ? Flag::Parity : 0; parity_overflow_result_ = iff2_ ? Flag::Parity : 0;
sign_result_ = zero_result_ = bit3_result_ = bit5_result_ = a_; sign_result_ = zero_result_ = bit53_result_ = a_;
break; break;
case MicroOp::SetZero: case MicroOp::SetZero:
@@ -1421,12 +1422,11 @@ template <class T> class Processor: public MicroOpScheduler<MicroOp> {
uint8_t result = uint8_t result =
(sign_result_ & Flag::Sign) | (sign_result_ & Flag::Sign) |
(zero_result_ ? 0 : Flag::Zero) | (zero_result_ ? 0 : Flag::Zero) |
(bit5_result_ & Flag::Bit5) | (bit53_result_ & (Flag::Bit5 | Flag::Bit3)) |
half_carry_flag_ | (half_carry_result_ & Flag::HalfCarry) |
(bit3_result_ & Flag::Bit3) | (parity_overflow_result_ & Flag::Parity) |
parity_overflow_flag_ |
subtract_flag_ | subtract_flag_ |
carry_flag_; (carry_result_ & Flag::Carry);
return result; return result;
} }
@@ -1440,12 +1440,11 @@ template <class T> class Processor: public MicroOpScheduler<MicroOp> {
void set_flags(uint8_t flags) { void set_flags(uint8_t flags) {
sign_result_ = flags; sign_result_ = flags;
zero_result_ = (flags & Flag::Zero) ^ Flag::Zero; zero_result_ = (flags & Flag::Zero) ^ Flag::Zero;
bit5_result_ = flags; bit53_result_ = flags;
half_carry_flag_ = flags & Flag::HalfCarry; half_carry_result_ = flags;
bit3_result_ = flags; parity_overflow_result_ = flags;
parity_overflow_flag_ = flags & Flag::Parity;
subtract_flag_ = flags & Flag::Subtract; subtract_flag_ = flags & Flag::Subtract;
carry_flag_ = flags & Flag::Carry; carry_result_ = flags;
} }
/*! /*!