From a9902fc8174878626f3bf53aaab0c1775e8e2baf Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Wed, 11 May 2022 16:31:27 -0400 Subject: [PATCH 1/7] Fix ABCD when the result has an invalid lower digit. --- InstructionSets/M68k/Implementation/PerformImplementation.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/InstructionSets/M68k/Implementation/PerformImplementation.hpp b/InstructionSets/M68k/Implementation/PerformImplementation.hpp index 2e3c34fdb..6d43257fc 100644 --- a/InstructionSets/M68k/Implementation/PerformImplementation.hpp +++ b/InstructionSets/M68k/Implementation/PerformImplementation.hpp @@ -43,7 +43,7 @@ template < int result = (destination & 0xf) + (source & 0xf) + (status.extend_flag_ ? 1 : 0); if(result > 0x09) result += 0x06; result += (destination & 0xf0) + (source & 0xf0); - if(result > 0x99) result += 0x60; + if(result > 0x9f) result += 0x60; // Set all flags essentially as if this were normal addition. status.zero_result_ |= result & 0xff; From 5b80844d814476f2fab89fdaaf1c7e31c26054b0 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Wed, 11 May 2022 16:34:28 -0400 Subject: [PATCH 2/7] Add a sanity test count, temporarily. --- OSBindings/Mac/Clock SignalTests/68000flamewingTests.mm | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/OSBindings/Mac/Clock SignalTests/68000flamewingTests.mm b/OSBindings/Mac/Clock SignalTests/68000flamewingTests.mm index 498873c43..b81f362ac 100644 --- a/OSBindings/Mac/Clock SignalTests/68000flamewingTests.mm +++ b/OSBindings/Mac/Clock SignalTests/68000flamewingTests.mm @@ -15,12 +15,14 @@ using namespace InstructionSet::M68k; @interface M68000flamewingTests : XCTestCase @end -@implementation M68000flamewingTests +@implementation M68000flamewingTests { + int _testsPerformed; +} - (Status)statusWithflamewingFlags:(int)flags { Status status; status.carry_flag_ = status.extend_flag_ = flags & 2; - status.zero_result_ = ~(flags & 1); + status.zero_result_ = ~flags & 1; status.negative_flag_ = 0; status.overflow_flag_ = 0; return status; @@ -30,6 +32,7 @@ using namespace InstructionSet::M68k; const uint8_t result_flags = test[0]; const uint8_t result_value = test[1]; + ++_testsPerformed; NSString *const testName = [NSString stringWithFormat:@"%@ %02x, %02x [%c%c]", operation, source, dest, (flags & 2) ? 'X' : '-', (flags & 1) ? 'Z' : '-']; XCTAssertEqual(result, uint32_t(result_value), @"Wrong value received for %@", testName); @@ -99,6 +102,8 @@ using namespace InstructionSet::M68k; bytes += 2; } } + + NSLog(@"%d tests performed", _testsPerformed); } @end From de168956e454be3f56c4b121652cf1d6a5880c60 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Wed, 11 May 2022 16:44:39 -0400 Subject: [PATCH 3/7] Fix tested operand order. --- .../Mac/Clock SignalTests/68000flamewingTests.mm | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/OSBindings/Mac/Clock SignalTests/68000flamewingTests.mm b/OSBindings/Mac/Clock SignalTests/68000flamewingTests.mm index b81f362ac..33cc1a263 100644 --- a/OSBindings/Mac/Clock SignalTests/68000flamewingTests.mm +++ b/OSBindings/Mac/Clock SignalTests/68000flamewingTests.mm @@ -50,8 +50,8 @@ using namespace InstructionSet::M68k; } flow_controller; // Test ABCD. - for(int dest = 0; dest < 256; dest++) { - for(int source = 0; source < 256; source++) { + for(int source = 0; source < 256; source++) { + for(int dest = 0; dest < 256; dest++) { for(int flags = 0; flags < 4; flags++) { Status status = [self statusWithflamewingFlags:flags]; @@ -69,8 +69,8 @@ using namespace InstructionSet::M68k; } // Test SBCD. - for(int dest = 0; dest < 256; dest++) { - for(int source = 0; source < 256; source++) { + for(int source = 0; source < 256; source++) { + for(int dest = 0; dest < 256; dest++) { for(int flags = 0; flags < 4; flags++) { Status status = [self statusWithflamewingFlags:flags]; @@ -87,6 +87,8 @@ using namespace InstructionSet::M68k; } } + return; + // Test NBCD. for(int source = 0; source < 256; source++) { for(int flags = 0; flags < 4; flags++) { From 56ce1ec6e8ca4967de7ea1fe84bb1c4f79e1d36b Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Wed, 11 May 2022 21:25:38 -0400 Subject: [PATCH 4/7] No need to subclass. --- .../Mac/Clock SignalTests/68000flamewingTests.mm | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/OSBindings/Mac/Clock SignalTests/68000flamewingTests.mm b/OSBindings/Mac/Clock SignalTests/68000flamewingTests.mm index 33cc1a263..30fdee9d6 100644 --- a/OSBindings/Mac/Clock SignalTests/68000flamewingTests.mm +++ b/OSBindings/Mac/Clock SignalTests/68000flamewingTests.mm @@ -46,8 +46,7 @@ using namespace InstructionSet::M68k; NSData *const testData = [NSData dataWithContentsOfURL:testURL]; const uint8_t *bytes = reinterpret_cast(testData.bytes); - struct NoFlowController: public NullFlowController { - } flow_controller; + NullFlowController flow_controller; // Test ABCD. for(int source = 0; source < 256; source++) { @@ -59,7 +58,7 @@ using namespace InstructionSet::M68k; s.l = source; d.l = dest; - perform( + perform( Preinstruction(), s, d, status, flow_controller); [self validate:bytes source:source dest:dest flags:flags result:d.l status:status operation:@"ABCD"]; @@ -78,7 +77,7 @@ using namespace InstructionSet::M68k; s.l = source; d.l = dest; - perform( + perform( Preinstruction(), s, d, status, flow_controller); [self validate:bytes source:source dest:dest flags:flags result:d.l status:status operation:@"SBCD"]; @@ -87,8 +86,6 @@ using namespace InstructionSet::M68k; } } - return; - // Test NBCD. for(int source = 0; source < 256; source++) { for(int flags = 0; flags < 4; flags++) { @@ -97,7 +94,7 @@ using namespace InstructionSet::M68k; CPU::SlicedInt32 s, d; s.l = source; - perform( + perform( Preinstruction(), s, d, status, flow_controller); [self validate:bytes source:source dest:0 flags:flags result:d.l status:status operation:@"NBCD"]; From 0efeea1294b509bddf1eda55bb111d243d2d1532 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Thu, 12 May 2022 07:07:21 -0400 Subject: [PATCH 5/7] Slightly improve SBCD. Not there yet though. --- InstructionSets/M68k/Implementation/PerformImplementation.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/InstructionSets/M68k/Implementation/PerformImplementation.hpp b/InstructionSets/M68k/Implementation/PerformImplementation.hpp index 6d43257fc..0dddd7077 100644 --- a/InstructionSets/M68k/Implementation/PerformImplementation.hpp +++ b/InstructionSets/M68k/Implementation/PerformImplementation.hpp @@ -791,9 +791,9 @@ template < /* Perform the BCD arithmetic by evaluating the two nibbles separately. */ \ const int unadjusted_result = destination - source - (status.extend_flag_ ? 1 : 0); \ int result = (destination & 0xf) - (source & 0xf) - (status.extend_flag_ ? 1 : 0); \ - if((result & 0x1f) > 0x09) result -= 0x06; \ + if(result & 0xf0) result -= 0x06; \ result += (destination & 0xf0) - (source & 0xf0); \ - status.extend_flag_ = status.carry_flag_ = decltype(status.carry_flag_)((result & 0x1ff) > 0x99); \ + status.extend_flag_ = status.carry_flag_ = decltype(status.carry_flag_)((result & 0xff) > 0x9f); \ if(status.carry_flag_) result -= 0x60; \ \ /* Set all flags essentially as if this were normal subtraction. */ \ From bd61c72007c96d22a5c18c598be1f003f45fe62c Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Thu, 12 May 2022 07:22:26 -0400 Subject: [PATCH 6/7] Mutate SBCD to correct values, though not yet statuses. --- InstructionSets/M68k/Implementation/PerformImplementation.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/InstructionSets/M68k/Implementation/PerformImplementation.hpp b/InstructionSets/M68k/Implementation/PerformImplementation.hpp index 0dddd7077..77c1d751e 100644 --- a/InstructionSets/M68k/Implementation/PerformImplementation.hpp +++ b/InstructionSets/M68k/Implementation/PerformImplementation.hpp @@ -794,7 +794,7 @@ template < if(result & 0xf0) result -= 0x06; \ result += (destination & 0xf0) - (source & 0xf0); \ status.extend_flag_ = status.carry_flag_ = decltype(status.carry_flag_)((result & 0xff) > 0x9f); \ - if(status.carry_flag_) result -= 0x60; \ + if(unadjusted_result & 0x100) result -= 0x60; \ \ /* Set all flags essentially as if this were normal subtraction. */ \ status.zero_result_ |= result & 0xff; \ From f3c1b1f052d116ee593e18543934657c436312cc Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Thu, 12 May 2022 08:19:41 -0400 Subject: [PATCH 7/7] Name flags, remove closing underscores on exposed data fields. --- .../Implementation/ExecutorImplementation.hpp | 30 +- .../Implementation/PerformImplementation.hpp | 350 +++++++++--------- InstructionSets/M68k/Status.hpp | 99 ++--- .../Clock SignalTests/68000flamewingTests.mm | 12 +- 4 files changed, 253 insertions(+), 238 deletions(-) diff --git a/InstructionSets/M68k/Implementation/ExecutorImplementation.hpp b/InstructionSets/M68k/Implementation/ExecutorImplementation.hpp index 478afd71a..6469a46eb 100644 --- a/InstructionSets/M68k/Implementation/ExecutorImplementation.hpp +++ b/InstructionSets/M68k/Implementation/ExecutorImplementation.hpp @@ -43,7 +43,7 @@ void Executor::reset_processor() { template template IntT Executor::read(uint32_t address, bool is_from_pc) { - const auto code = FunctionCode((status_.is_supervisor_ << 2) | 1 << int(is_from_pc)); + const auto code = FunctionCode((status_.is_supervisor << 2) | 1 << int(is_from_pc)); if(model == Model::M68000 && sizeof(IntT) > 1 && address & 1) { throw AccessException(code, address, Exception::AddressError | (int(is_from_pc) << 3) | (1 << 4)); } @@ -55,7 +55,7 @@ IntT Executor::read(uint32_t address, bool is_from_pc) { template template void Executor::write(uint32_t address, IntT value) { - const auto code = FunctionCode((status_.is_supervisor_ << 2) | 1); + const auto code = FunctionCode((status_.is_supervisor << 2) | 1); if(model == Model::M68000 && sizeof(IntT) > 1 && address & 1) { throw AccessException(code, address, Exception::AddressError); } @@ -240,8 +240,8 @@ void Executor::run_for_instructions(int count) { // Grab the status to store, then switch into supervisor mode. const uint16_t status = status_.status(); - status_.is_supervisor_ = 1; - status_.trace_flag_ = 0; + status_.is_supervisor = 1; + status_.trace_flag = 0; did_update_status(); // Push status and the program counter at instruction start. @@ -271,14 +271,14 @@ void Executor::run(int &count) { // Capture the trace bit, indicating whether to trace // after this instruction. - const auto should_trace = status_.trace_flag_; + const auto should_trace = status_.trace_flag; // Read the next instruction. instruction_address_ = program_counter_.l; instruction_opcode_ = read_pc(); const Preinstruction instruction = decoder_.decode(instruction_opcode_); - if(!status_.is_supervisor_ && instruction.requires_supervisor()) { + if(!status_.is_supervisor && instruction.requires_supervisor()) { raise_exception(Exception::PrivilegeViolation); continue; } @@ -369,7 +369,7 @@ typename Executor::Registers Executor::get result.status = status_.status(); result.program_counter = program_counter_.l; - stack_pointers_[status_.is_supervisor_] = sp; + stack_pointers_[status_.is_supervisor] = sp; result.user_stack_pointer = stack_pointers_[0].l; result.supervisor_stack_pointer = stack_pointers_[1].l; @@ -389,7 +389,7 @@ void Executor::set_state(const Registers &state) { stack_pointers_[0].l = state.user_stack_pointer; stack_pointers_[1].l = state.supervisor_stack_pointer; - sp = stack_pointers_[status_.is_supervisor_]; + sp = stack_pointers_[status_.is_supervisor]; } // MARK: - Flow Control. @@ -402,8 +402,8 @@ void Executor::raise_exception(int index) { // Grab the status to store, then switch into supervisor mode // and disable tracing. const uint16_t status = status_.status(); - status_.is_supervisor_ = 1; - status_.trace_flag_ = 0; + status_.is_supervisor = 1; + status_.trace_flag = 0; did_update_status(); // Push status and the program counter at instruction start. @@ -419,8 +419,8 @@ template void Executor::did_update_status() { // Shuffle the stack pointers. stack_pointers_[active_stack_pointer_] = sp; - sp = stack_pointers_[status_.is_supervisor_]; - active_stack_pointer_ = status_.is_supervisor_; + sp = stack_pointers_[status_.is_supervisor]; + active_stack_pointer_ = status_.is_supervisor; } template @@ -518,9 +518,9 @@ void Executor::tas(Preinstruction instruction, uint32_t addre Dn(instruction.reg<0>()).b = uint8_t(address | 0x80); } - status_.overflow_flag_ = status_.carry_flag_ = 0; - status_.zero_result_ = value; - status_.negative_flag_ = value & 0x80; + status_.overflow_flag = status_.carry_flag = 0; + status_.zero_result = value; + status_.negative_flag = value & 0x80; } template diff --git a/InstructionSets/M68k/Implementation/PerformImplementation.hpp b/InstructionSets/M68k/Implementation/PerformImplementation.hpp index 77c1d751e..0a069a4dd 100644 --- a/InstructionSets/M68k/Implementation/PerformImplementation.hpp +++ b/InstructionSets/M68k/Implementation/PerformImplementation.hpp @@ -39,17 +39,17 @@ template < const uint8_t destination = dest.b; // Perform the BCD add by evaluating the two nibbles separately. - const int unadjusted_result = destination + source + (status.extend_flag_ ? 1 : 0); - int result = (destination & 0xf) + (source & 0xf) + (status.extend_flag_ ? 1 : 0); + const int unadjusted_result = destination + source + (status.extend_flag ? 1 : 0); + int result = (destination & 0xf) + (source & 0xf) + (status.extend_flag ? 1 : 0); if(result > 0x09) result += 0x06; result += (destination & 0xf0) + (source & 0xf0); if(result > 0x9f) result += 0x60; // Set all flags essentially as if this were normal addition. - status.zero_result_ |= result & 0xff; - status.extend_flag_ = status.carry_flag_ = uint_fast32_t(result & ~0xff); - status.negative_flag_ = result & 0x80; - status.overflow_flag_ = ~unadjusted_result & result & 0x80; + status.zero_result |= result & 0xff; + status.extend_flag = status.carry_flag = uint_fast32_t(result & ~0xff); + status.negative_flag = result & 0x80; + status.overflow_flag = ~unadjusted_result & result & 0x80; // Store the result. dest.b = uint8_t(result); @@ -66,10 +66,10 @@ template < const auto result = op(destination, source, x); \ \ b = uint8_t(result); \ - zero_op(status.zero_result_, b); \ - status.extend_flag_ = status.carry_flag_ = uint_fast32_t(result & ~0xff); \ - status.negative_flag_ = result & 0x80; \ - status.overflow_flag_ = overflow() & 0x80; + zero_op(status.zero_result, b); \ + status.extend_flag = status.carry_flag = uint_fast32_t(result & ~0xff); \ + status.negative_flag = result & 0x80; \ + status.overflow_flag = overflow() & 0x80; #define addsubw(a, b, op, overflow, x, zero_op) \ const int source = a; \ @@ -77,10 +77,10 @@ template < const auto result = op(destination, source, x); \ \ b = uint16_t(result); \ - zero_op(status.zero_result_, b); \ - status.extend_flag_ = status.carry_flag_ = uint_fast32_t(result & ~0xffff); \ - status.negative_flag_ = result & 0x8000; \ - status.overflow_flag_ = overflow() & 0x8000; + zero_op(status.zero_result, b); \ + status.extend_flag = status.carry_flag = uint_fast32_t(result & ~0xffff); \ + status.negative_flag = result & 0x8000; \ + status.overflow_flag = overflow() & 0x8000; #define addsubl(a, b, op, overflow, x, zero_op) \ const uint64_t source = a; \ @@ -88,10 +88,10 @@ template < const auto result = op(destination, source, x); \ \ b = uint32_t(result); \ - zero_op(status.zero_result_, b); \ - status.extend_flag_ = status.carry_flag_ = uint_fast32_t(result >> 32); \ - status.negative_flag_ = result & 0x80000000; \ - status.overflow_flag_ = overflow() & 0x80000000; + zero_op(status.zero_result, b); \ + status.extend_flag = status.carry_flag = uint_fast32_t(result >> 32); \ + status.negative_flag = result & 0x80000000; \ + status.overflow_flag = overflow() & 0x80000000; #define addb(a, b, x, z) addsubb(a, b, addop, add_overflow, x, z) #define subb(a, b, x, z) addsubb(a, b, subop, sub_overflow, x, z) @@ -101,7 +101,7 @@ template < #define subl(a, b, x, z) addsubl(a, b, subop, sub_overflow, x, z) #define no_extend(op, a, b) op(a, b, 0, z_set) -#define extend(op, a, b) op(a, b, status.extend_flag_, z_or) +#define extend(op, a, b) op(a, b, status.extend_flag, z_or) // ADD and ADDA add two quantities, the latter sign extending and without setting any flags; // ADDQ and SUBQ act as ADD and SUB, but taking the second argument from the instruction code. @@ -212,13 +212,13 @@ template < // BTST/BCLR/etc: modulo for the mask depends on whether memory or a data register is the target. case Operation::BTST: { const uint32_t mask = (instruction.mode<1>() == AddressingMode::DataRegisterDirect) ? 31 : 7; - status.zero_result_ = dest.l & (1 << (src.l & mask)); + status.zero_result = dest.l & (1 << (src.l & mask)); } break; case Operation::BCLR: { const uint32_t mask = (instruction.mode<1>() == AddressingMode::DataRegisterDirect) ? 31 : 7; - status.zero_result_ = dest.l & (1 << (src.l & mask)); + status.zero_result = dest.l & (1 << (src.l & mask)); dest.l &= ~(1 << (src.l & mask)); flow_controller.did_bit_op(src.l & mask); } break; @@ -226,7 +226,7 @@ template < case Operation::BCHG: { const uint32_t mask = (instruction.mode<1>() == AddressingMode::DataRegisterDirect) ? 31 : 7; - status.zero_result_ = dest.l & (1 << (src.l & mask)); + status.zero_result = dest.l & (1 << (src.l & mask)); dest.l ^= 1 << (src.l & mask); flow_controller.did_bit_op(src.l & mask); } break; @@ -234,7 +234,7 @@ template < case Operation::BSET: { const uint32_t mask = (instruction.mode<1>() == AddressingMode::DataRegisterDirect) ? 31 : 7; - status.zero_result_ = dest.l & (1 << (src.l & mask)); + status.zero_result = dest.l & (1 << (src.l & mask)); dest.l |= 1 << (src.l & mask); flow_controller.did_bit_op(src.l & mask); } break; @@ -294,17 +294,17 @@ template < */ case Operation::CLRb: src.b = 0; - status.negative_flag_ = status.overflow_flag_ = status.carry_flag_ = status.zero_result_ = 0; + status.negative_flag = status.overflow_flag = status.carry_flag = status.zero_result = 0; break; case Operation::CLRw: src.w = 0; - status.negative_flag_ = status.overflow_flag_ = status.carry_flag_ = status.zero_result_ = 0; + status.negative_flag = status.overflow_flag = status.carry_flag = status.zero_result = 0; break; case Operation::CLRl: src.l = 0; - status.negative_flag_ = status.overflow_flag_ = status.carry_flag_ = status.zero_result_ = 0; + status.negative_flag = status.overflow_flag = status.carry_flag = status.zero_result = 0; break; /* @@ -316,10 +316,10 @@ template < const uint8_t destination = dest.b; const int result = destination - source; - status.zero_result_ = result & 0xff; - status.carry_flag_ = decltype(status.carry_flag_)(result & ~0xff); - status.negative_flag_ = result & 0x80; - status.overflow_flag_ = sub_overflow() & 0x80; + status.zero_result = result & 0xff; + status.carry_flag = decltype(status.carry_flag)(result & ~0xff); + status.negative_flag = result & 0x80; + status.overflow_flag = sub_overflow() & 0x80; } break; case Operation::CMPw: { @@ -327,10 +327,10 @@ template < const uint16_t destination = dest.w; const int result = destination - source; - status.zero_result_ = result & 0xffff; - status.carry_flag_ = decltype(status.carry_flag_)(result & ~0xffff); - status.negative_flag_ = result & 0x8000; - status.overflow_flag_ = sub_overflow() & 0x8000; + status.zero_result = result & 0xffff; + status.carry_flag = decltype(status.carry_flag)(result & ~0xffff); + status.negative_flag = result & 0x8000; + status.overflow_flag = sub_overflow() & 0x8000; } break; case Operation::CMPAw: { @@ -338,10 +338,10 @@ template < const uint64_t destination = dest.l; const auto result = destination - source; - status.zero_result_ = uint32_t(result); - status.carry_flag_ = result >> 32; - status.negative_flag_ = result & 0x80000000; - status.overflow_flag_ = sub_overflow() & 0x80000000; + status.zero_result = uint32_t(result); + status.carry_flag = result >> 32; + status.negative_flag = result & 0x80000000; + status.overflow_flag = sub_overflow() & 0x80000000; } break; // TODO: is there any benefit to keeping both of these? @@ -351,10 +351,10 @@ template < const auto destination = uint64_t(dest.l); const auto result = destination - source; - status.zero_result_ = uint32_t(result); - status.carry_flag_ = result >> 32; - status.negative_flag_ = result & 0x80000000; - status.overflow_flag_ = sub_overflow() & 0x80000000; + status.zero_result = uint32_t(result); + status.carry_flag = result >> 32; + status.negative_flag = result & 0x80000000; + status.overflow_flag = sub_overflow() & 0x80000000; } break; // JMP: copies EA(0) to the program counter. @@ -372,21 +372,21 @@ template < and set negative, zero, overflow and carry as appropriate. */ case Operation::MOVEb: - status.zero_result_ = dest.b = src.b; - status.negative_flag_ = status.zero_result_ & 0x80; - status.overflow_flag_ = status.carry_flag_ = 0; + status.zero_result = dest.b = src.b; + status.negative_flag = status.zero_result & 0x80; + status.overflow_flag = status.carry_flag = 0; break; case Operation::MOVEw: - status.zero_result_ = dest.w = src.w; - status.negative_flag_ = status.zero_result_ & 0x8000; - status.overflow_flag_ = status.carry_flag_ = 0; + status.zero_result = dest.w = src.w; + status.negative_flag = status.zero_result & 0x8000; + status.overflow_flag = status.carry_flag = 0; break; case Operation::MOVEl: - status.zero_result_ = dest.l = src.l; - status.negative_flag_ = status.zero_result_ & 0x80000000; - status.overflow_flag_ = status.carry_flag_ = 0; + status.zero_result = dest.l = src.l; + status.negative_flag = status.zero_result & 0x80000000; + status.overflow_flag = status.carry_flag = 0; break; /* @@ -437,16 +437,16 @@ template < case Operation::EXTbtow: src.w = uint16_t(int8_t(src.b)); - status.overflow_flag_ = status.carry_flag_ = 0; - status.zero_result_ = src.w; - status.negative_flag_ = status.zero_result_ & 0x8000; + status.overflow_flag = status.carry_flag = 0; + status.zero_result = src.w; + status.negative_flag = status.zero_result & 0x8000; break; case Operation::EXTwtol: src.l = u_extend16(src.w); - status.overflow_flag_ = status.carry_flag_ = 0; - status.zero_result_ = src.l; - status.negative_flag_ = status.zero_result_ & 0x80000000; + status.overflow_flag = status.carry_flag = 0; + status.zero_result = src.l; + status.negative_flag = status.zero_result & 0x80000000; break; #define and_op(a, b) a &= b @@ -488,18 +488,18 @@ template < case Operation::MULU: dest.l = dest.w * src.w; - status.carry_flag_ = status.overflow_flag_ = 0; - status.zero_result_ = dest.l; - status.negative_flag_ = status.zero_result_ & 0x80000000; + status.carry_flag = status.overflow_flag = 0; + status.zero_result = dest.l; + status.negative_flag = status.zero_result & 0x80000000; flow_controller.did_mulu(src.w); break; case Operation::MULS: dest.l = u_extend16(dest.w) * u_extend16(src.w); - status.carry_flag_ = status.overflow_flag_ = 0; - status.zero_result_ = dest.l; - status.negative_flag_ = status.zero_result_ & 0x80000000; + status.carry_flag = status.overflow_flag = 0; + status.zero_result = dest.l; + status.negative_flag = status.zero_result & 0x80000000; flow_controller.did_muls(src.w); break; @@ -508,12 +508,12 @@ template < */ #define announce_divide_by_zero() \ - status.negative_flag_ = status.overflow_flag_ = 0; \ - status.zero_result_ = 1; \ + status.negative_flag = status.overflow_flag = 0; \ + status.zero_result = 1; \ flow_controller.raise_exception(Exception::IntegerDivideByZero) case Operation::DIVU: { - status.carry_flag_ = 0; + status.carry_flag = 0; // An attempt to divide by zero schedules an exception. if(!src.w) { @@ -528,7 +528,7 @@ template < // If overflow would occur, appropriate flags are set and the result is not written back. if(quotient > 65535) { - status.overflow_flag_ = status.zero_result_ = status.negative_flag_ = 1; + status.overflow_flag = status.zero_result = status.negative_flag = 1; flow_controller.template did_divu(dividend, divisor); return; } @@ -536,14 +536,14 @@ template < const uint16_t remainder = uint16_t(dividend % divisor); dest.l = uint32_t((remainder << 16) | uint16_t(quotient)); - status.overflow_flag_ = 0; - status.zero_result_ = quotient; - status.negative_flag_ = status.zero_result_ & 0x8000; + status.overflow_flag = 0; + status.zero_result = quotient; + status.negative_flag = status.zero_result & 0x8000; flow_controller.template did_divu(dividend, divisor); } break; case Operation::DIVS: { - status.carry_flag_ = 0; + status.carry_flag = 0; // An attempt to divide by zero schedules an exception. if(!src.w) { @@ -569,7 +569,7 @@ template < // Check for overflow. If it exists, work here is already done. const auto quotient = dividend / divisor; if(quotient > 32767) { - status.overflow_flag_ = 1; + status.overflow_flag = 1; flow_controller.template did_divs(signed_dividend, signed_divisor); break; } @@ -578,9 +578,9 @@ template < const int signed_quotient = result_sign*int(quotient); dest.l = uint32_t((remainder << 16) | uint16_t(signed_quotient)); - status.zero_result_ = decltype(status.zero_result_)(signed_quotient); - status.negative_flag_ = status.zero_result_ & 0x8000; - status.overflow_flag_ = 0; + status.zero_result = decltype(status.zero_result)(signed_quotient); + status.negative_flag = status.zero_result & 0x8000; + status.overflow_flag = 0; flow_controller.template did_divs(signed_dividend, signed_divisor); } break; @@ -592,7 +592,7 @@ template < break; case Operation::TRAPV: { - if(status.overflow_flag_) { + if(status.overflow_flag) { flow_controller.template raise_exception(Exception::TRAPV); } } break; @@ -601,15 +601,15 @@ template < const bool is_under = s_extend16(dest.w) < 0; const bool is_over = s_extend16(dest.w) > s_extend16(src.w); - status.overflow_flag_ = status.carry_flag_ = 0; - status.zero_result_ = dest.w; + status.overflow_flag = status.carry_flag = 0; + status.zero_result = dest.w; // Test applied for N: // // if Dn < 0, set negative flag; // otherwise, if Dn > , reset negative flag. - if(is_over) status.negative_flag_ = 0; - if(is_under) status.negative_flag_ = 1; + if(is_over) status.negative_flag = 0; + if(is_under) status.negative_flag = 1; // No exception is the default course of action; deviate only if an // exception is necessary. @@ -633,10 +633,10 @@ template < const auto result = destination - source; src.b = uint8_t(result); - status.zero_result_ = result & 0xff; - status.extend_flag_ = status.carry_flag_ = decltype(status.carry_flag_)(result & ~0xff); - status.negative_flag_ = result & 0x80; - status.overflow_flag_ = sub_overflow() & 0x80; + status.zero_result = result & 0xff; + status.extend_flag = status.carry_flag = decltype(status.carry_flag)(result & ~0xff); + status.negative_flag = result & 0x80; + status.overflow_flag = sub_overflow() & 0x80; } break; case Operation::NEGw: { @@ -645,10 +645,10 @@ template < const auto result = destination - source; src.w = uint16_t(result); - status.zero_result_ = result & 0xffff; - status.extend_flag_ = status.carry_flag_ = decltype(status.carry_flag_)(result & ~0xffff); - status.negative_flag_ = result & 0x8000; - status.overflow_flag_ = sub_overflow() & 0x8000; + status.zero_result = result & 0xffff; + status.extend_flag = status.carry_flag = decltype(status.carry_flag)(result & ~0xffff); + status.negative_flag = result & 0x8000; + status.overflow_flag = sub_overflow() & 0x8000; } break; case Operation::NEGl: { @@ -657,10 +657,10 @@ template < const auto result = destination - source; src.l = uint32_t(result); - status.zero_result_ = uint_fast32_t(result); - status.extend_flag_ = status.carry_flag_ = result >> 32; - status.negative_flag_ = result & 0x80000000; - status.overflow_flag_ = sub_overflow() & 0x80000000; + status.zero_result = uint_fast32_t(result); + status.extend_flag = status.carry_flag = result >> 32; + status.negative_flag = result & 0x80000000; + status.overflow_flag = sub_overflow() & 0x80000000; } break; /* @@ -669,37 +669,37 @@ template < case Operation::NEGXb: { const int source = src.b; const int destination = 0; - const auto result = destination - source - (status.extend_flag_ ? 1 : 0); + const auto result = destination - source - (status.extend_flag ? 1 : 0); src.b = uint8_t(result); - status.zero_result_ |= result & 0xff; - status.extend_flag_ = status.carry_flag_ = decltype(status.carry_flag_)(result & ~0xff); - status.negative_flag_ = result & 0x80; - status.overflow_flag_ = sub_overflow() & 0x80; + status.zero_result |= result & 0xff; + status.extend_flag = status.carry_flag = decltype(status.carry_flag)(result & ~0xff); + status.negative_flag = result & 0x80; + status.overflow_flag = sub_overflow() & 0x80; } break; case Operation::NEGXw: { const int source = src.w; const int destination = 0; - const auto result = destination - source - (status.extend_flag_ ? 1 : 0); + const auto result = destination - source - (status.extend_flag ? 1 : 0); src.w = uint16_t(result); - status.zero_result_ |= result & 0xffff; - status.extend_flag_ = status.carry_flag_ = decltype(status.carry_flag_)(result & ~0xffff); - status.negative_flag_ = result & 0x8000; - status.overflow_flag_ = sub_overflow() & 0x8000; + status.zero_result |= result & 0xffff; + status.extend_flag = status.carry_flag = decltype(status.carry_flag)(result & ~0xffff); + status.negative_flag = result & 0x8000; + status.overflow_flag = sub_overflow() & 0x8000; } break; case Operation::NEGXl: { const uint64_t source = src.l; const uint64_t destination = 0; - const auto result = destination - source - (status.extend_flag_ ? 1 : 0); + const auto result = destination - source - (status.extend_flag ? 1 : 0); src.l = uint32_t(result); - status.zero_result_ |= uint_fast32_t(result); - status.extend_flag_ = status.carry_flag_ = result >> 32; - status.negative_flag_ = result & 0x80000000; - status.overflow_flag_ = sub_overflow() & 0x80000000; + status.zero_result |= uint_fast32_t(result); + status.extend_flag = status.carry_flag = result >> 32; + status.negative_flag = result & 0x80000000; + status.overflow_flag = sub_overflow() & 0x80000000; } break; /* @@ -739,9 +739,9 @@ template < #define bitwise(source, dest, sign_mask, operator) \ operator(dest, source); \ - status.overflow_flag_ = status.carry_flag_ = 0; \ - status.zero_result_ = dest; \ - status.negative_flag_ = dest & sign_mask; + status.overflow_flag = status.carry_flag = 0; \ + status.zero_result = dest; \ + status.negative_flag = dest & sign_mask; #define andx(source, dest, sign_mask) bitwise(source, dest, sign_mask, op_and) #define eorx(source, dest, sign_mask) bitwise(source, dest, sign_mask, op_eor) @@ -768,38 +768,38 @@ template < // NOTs: take the logical inverse, affecting the negative and zero flags. case Operation::NOTb: src.b ^= 0xff; - status.zero_result_ = src.b; - status.negative_flag_ = status.zero_result_ & 0x80; - status.overflow_flag_ = status.carry_flag_ = 0; + status.zero_result = src.b; + status.negative_flag = status.zero_result & 0x80; + status.overflow_flag = status.carry_flag = 0; break; case Operation::NOTw: src.w ^= 0xffff; - status.zero_result_ = src.w; - status.negative_flag_ = status.zero_result_ & 0x8000; - status.overflow_flag_ = status.carry_flag_ = 0; + status.zero_result = src.w; + status.negative_flag = status.zero_result & 0x8000; + status.overflow_flag = status.carry_flag = 0; break; case Operation::NOTl: src.l ^= 0xffffffff; - status.zero_result_ = src.l; - status.negative_flag_ = status.zero_result_ & 0x80000000; - status.overflow_flag_ = status.carry_flag_ = 0; + status.zero_result = src.l; + status.negative_flag = status.zero_result & 0x80000000; + status.overflow_flag = status.carry_flag = 0; break; #define sbcd(d) \ /* Perform the BCD arithmetic by evaluating the two nibbles separately. */ \ - const int unadjusted_result = destination - source - (status.extend_flag_ ? 1 : 0); \ - int result = (destination & 0xf) - (source & 0xf) - (status.extend_flag_ ? 1 : 0); \ + const int unadjusted_result = destination - source - (status.extend_flag ? 1 : 0); \ + int result = (destination & 0xf) - (source & 0xf) - (status.extend_flag ? 1 : 0); \ if(result & 0xf0) result -= 0x06; \ result += (destination & 0xf0) - (source & 0xf0); \ - status.extend_flag_ = status.carry_flag_ = decltype(status.carry_flag_)((result & 0xff) > 0x9f); \ - if(unadjusted_result & 0x100) result -= 0x60; \ + status.extend_flag = status.carry_flag = decltype(status.carry_flag)(unadjusted_result & 0x300); \ + if(unadjusted_result & 0x100) result -= 0x60; \ \ /* Set all flags essentially as if this were normal subtraction. */ \ - status.zero_result_ |= result & 0xff; \ - status.negative_flag_ = result & 0x80; \ - status.overflow_flag_ = unadjusted_result & ~result & 0x80; \ + status.zero_result |= result & 0xff; \ + status.negative_flag = result & 0x80; \ + status.overflow_flag = unadjusted_result & ~result & 0x80; \ \ /* Store the result. */ \ d = uint8_t(result); @@ -840,21 +840,21 @@ template < words[0] = words[1]; words[1] = temporary; - status.zero_result_ = src.l; - status.negative_flag_ = temporary & 0x8000; - status.overflow_flag_ = status.carry_flag_ = 0; + status.zero_result = src.l; + status.negative_flag = temporary & 0x8000; + status.overflow_flag = status.carry_flag = 0; } break; /* Shifts and rotates. */ -#define set_neg_zero(v, m) \ - status.zero_result_ = decltype(status.zero_result_)(v); \ - status.negative_flag_ = status.zero_result_ & decltype(status.negative_flag_)(m); +#define set_neg_zero(v, m) \ + status.zero_result = decltype(status.zero_result)(v); \ + status.negative_flag = status.zero_result & decltype(status.negative_flag)(m); #define set_neg_zero_overflow(v, m) \ set_neg_zero(v, m); \ - status.overflow_flag_ = (decltype(status.zero_result_)(value) ^ status.zero_result_) & decltype(status.overflow_flag_)(m); + status.overflow_flag = (decltype(status.zero_result)(value) ^ status.zero_result) & decltype(status.overflow_flag)(m); #define decode_shift_count() \ int shift_count = src.l & 63; \ @@ -867,15 +867,15 @@ template < const auto value = destination; \ \ if(!shift_count) { \ - status.carry_flag_ = status.overflow_flag_ = 0; \ + status.carry_flag = status.overflow_flag = 0; \ } else { \ destination = (shift_count < size) ? decltype(destination)(value << shift_count) : 0; \ - status.extend_flag_ = status.carry_flag_ = decltype(status.carry_flag_)(value) & decltype(status.carry_flag_)( (1u << (size - 1)) >> (shift_count - 1) ); \ + status.extend_flag = status.carry_flag = decltype(status.carry_flag)(value) & decltype(status.carry_flag)( (1u << (size - 1)) >> (shift_count - 1) ); \ \ - if(shift_count >= size) status.overflow_flag_ = value && (value != decltype(value)(-1)); \ + if(shift_count >= size) status.overflow_flag = value && (value != decltype(value)(-1)); \ else { \ const auto mask = decltype(destination)(0xffffffff << (size - shift_count)); \ - status.overflow_flag_ = mask & value && ((mask & value) != mask); \ + status.overflow_flag = mask & value && ((mask & value) != mask); \ } \ } \ \ @@ -885,7 +885,7 @@ template < case Operation::ASLm: { const auto value = src.w; src.w = uint16_t(value << 1); - status.extend_flag_ = status.carry_flag_ = value & 0x8000; + status.extend_flag = status.carry_flag = value & 0x8000; set_neg_zero_overflow(src.w, 0x8000); } break; case Operation::ASLb: asl(dest.b, 8); break; @@ -897,7 +897,7 @@ template < const auto value = destination; \ \ if(!shift_count) { \ - status.carry_flag_ = 0; \ + status.carry_flag = 0; \ } else { \ destination = (shift_count < size) ? \ decltype(destination)(\ @@ -907,7 +907,7 @@ template < decltype(destination)( \ (value & decltype(value)(1 << (size - 1))) ? 0xffffffff : 0x000000000 \ ); \ - status.extend_flag_ = status.carry_flag_ = decltype(status.carry_flag_)(value) & decltype(status.carry_flag_)(1 << (shift_count - 1)); \ + status.extend_flag = status.carry_flag = decltype(status.carry_flag)(value) & decltype(status.carry_flag)(1 << (shift_count - 1)); \ } \ \ set_neg_zero_overflow(destination, 1 << (size - 1)); \ @@ -916,7 +916,7 @@ template < case Operation::ASRm: { const auto value = src.w; src.w = (value&0x8000) | (value >> 1); - status.extend_flag_ = status.carry_flag_ = value & 1; + status.extend_flag = status.carry_flag = value & 1; set_neg_zero_overflow(src.w, 0x8000); } break; case Operation::ASRb: asr(dest.b, 8); break; @@ -927,24 +927,24 @@ template < #undef set_neg_zero_overflow #define set_neg_zero_overflow(v, m) \ set_neg_zero(v, m); \ - status.overflow_flag_ = 0; + status.overflow_flag = 0; #undef set_flags #define set_flags(v, m, t) \ - status.zero_result_ = v; \ - status.negative_flag_ = status.zero_result_ & (m); \ - status.overflow_flag_ = 0; \ - status.carry_flag_ = value & (t); + status.zero_result = v; \ + status.negative_flag = status.zero_result & (m); \ + status.overflow_flag = 0; \ + status.carry_flag = value & (t); #define lsl(destination, size) {\ decode_shift_count(); \ const auto value = destination; \ \ if(!shift_count) { \ - status.carry_flag_ = 0; \ + status.carry_flag = 0; \ } else { \ destination = (shift_count < size) ? decltype(destination)(value << shift_count) : 0; \ - status.extend_flag_ = status.carry_flag_ = decltype(status.carry_flag_)(value) & decltype(status.carry_flag_)( (1u << (size - 1)) >> (shift_count - 1) ); \ + status.extend_flag = status.carry_flag = decltype(status.carry_flag)(value) & decltype(status.carry_flag)( (1u << (size - 1)) >> (shift_count - 1) ); \ } \ \ set_neg_zero_overflow(destination, 1 << (size - 1)); \ @@ -953,7 +953,7 @@ template < case Operation::LSLm: { const auto value = src.w; src.w = uint16_t(value << 1); - status.extend_flag_ = status.carry_flag_ = value & 0x8000; + status.extend_flag = status.carry_flag = value & 0x8000; set_neg_zero_overflow(src.w, 0x8000); } break; case Operation::LSLb: lsl(dest.b, 8); break; @@ -965,10 +965,10 @@ template < const auto value = destination; \ \ if(!shift_count) { \ - status.carry_flag_ = 0; \ + status.carry_flag = 0; \ } else { \ destination = (shift_count < size) ? (value >> shift_count) : 0; \ - status.extend_flag_ = status.carry_flag_ = value & decltype(status.carry_flag_)(1 << (shift_count - 1)); \ + status.extend_flag = status.carry_flag = value & decltype(status.carry_flag)(1 << (shift_count - 1)); \ } \ \ set_neg_zero_overflow(destination, 1 << (size - 1)); \ @@ -977,7 +977,7 @@ template < case Operation::LSRm: { const auto value = src.w; src.w = value >> 1; - status.extend_flag_ = status.carry_flag_ = value & 1; + status.extend_flag = status.carry_flag = value & 1; set_neg_zero_overflow(src.w, 0x8000); } break; case Operation::LSRb: lsr(dest.b, 8); break; @@ -989,14 +989,14 @@ template < const auto value = destination; \ \ if(!shift_count) { \ - status.carry_flag_ = 0; \ + status.carry_flag = 0; \ } else { \ shift_count &= (size - 1); \ destination = decltype(destination)( \ (value << shift_count) | \ (value >> (size - shift_count)) \ ); \ - status.carry_flag_ = decltype(status.carry_flag_)(destination & 1); \ + status.carry_flag = decltype(status.carry_flag)(destination & 1); \ } \ \ set_neg_zero_overflow(destination, 1 << (size - 1)); \ @@ -1005,7 +1005,7 @@ template < case Operation::ROLm: { const auto value = src.w; src.w = uint16_t((value << 1) | (value >> 15)); - status.carry_flag_ = src.w & 1; + status.carry_flag = src.w & 1; set_neg_zero_overflow(src.w, 0x8000); } break; case Operation::ROLb: rol(dest.b, 8); break; @@ -1017,14 +1017,14 @@ template < const auto value = destination; \ \ if(!shift_count) { \ - status.carry_flag_ = 0; \ + status.carry_flag = 0; \ } else { \ shift_count &= (size - 1); \ destination = decltype(destination)(\ (value >> shift_count) | \ (value << (size - shift_count)) \ );\ - status.carry_flag_ = destination & decltype(status.carry_flag_)(1 << (size - 1)); \ + status.carry_flag = destination & decltype(status.carry_flag)(1 << (size - 1)); \ } \ \ set_neg_zero_overflow(destination, 1 << (size - 1)); \ @@ -1033,7 +1033,7 @@ template < case Operation::RORm: { const auto value = src.w; src.w = uint16_t((value >> 1) | (value << 15)); - status.carry_flag_ = src.w & 0x8000; + status.carry_flag = src.w & 0x8000; set_neg_zero_overflow(src.w, 0x8000); } break; case Operation::RORb: ror(dest.b, 8); break; @@ -1044,11 +1044,11 @@ template < decode_shift_count(); \ \ shift_count %= (size + 1); \ - uint64_t compound = uint64_t(destination) | (status.extend_flag_ ? (1ull << size) : 0); \ + uint64_t compound = uint64_t(destination) | (status.extend_flag ? (1ull << size) : 0); \ compound = \ (compound << shift_count) | \ (compound >> (size + 1 - shift_count)); \ - status.carry_flag_ = status.extend_flag_ = decltype(status.carry_flag_)((compound >> size) & 1); \ + status.carry_flag = status.extend_flag = decltype(status.carry_flag)((compound >> size) & 1); \ destination = decltype(destination)(compound); \ \ set_neg_zero_overflow(destination, 1 << (size - 1)); \ @@ -1056,8 +1056,8 @@ template < case Operation::ROXLm: { const auto value = src.w; - src.w = uint16_t((value << 1) | (status.extend_flag_ ? 0x0001 : 0x0000)); - status.extend_flag_ = value & 0x8000; + src.w = uint16_t((value << 1) | (status.extend_flag ? 0x0001 : 0x0000)); + status.extend_flag = value & 0x8000; set_flags_w(0x8000); } break; case Operation::ROXLb: roxl(dest.b, 8); break; @@ -1068,11 +1068,11 @@ template < decode_shift_count(); \ \ shift_count %= (size + 1); \ - uint64_t compound = uint64_t(destination) | (status.extend_flag_ ? (1ull << size) : 0); \ + uint64_t compound = uint64_t(destination) | (status.extend_flag ? (1ull << size) : 0); \ compound = \ (compound >> shift_count) | \ (compound << (size + 1 - shift_count)); \ - status.carry_flag_ = status.extend_flag_ = decltype(status.carry_flag_)((compound >> size) & 1); \ + status.carry_flag = status.extend_flag = decltype(status.carry_flag)((compound >> size) & 1); \ destination = decltype(destination)(compound); \ \ set_neg_zero_overflow(destination, 1 << (size - 1)); \ @@ -1080,8 +1080,8 @@ template < case Operation::ROXRm: { const auto value = src.w; - src.w = (value >> 1) | (status.extend_flag_ ? 0x8000 : 0x0000); - status.extend_flag_ = value & 0x0001; + src.w = (value >> 1) | (status.extend_flag ? 0x8000 : 0x0000); + status.extend_flag = value & 0x0001; set_flags_w(0x0001); } break; case Operation::ROXRb: roxr(dest.b, 8); break; @@ -1147,21 +1147,21 @@ template < */ case Operation::TSTb: - status.carry_flag_ = status.overflow_flag_ = 0; - status.zero_result_ = src.b; - status.negative_flag_ = status.zero_result_ & 0x80; + status.carry_flag = status.overflow_flag = 0; + status.zero_result = src.b; + status.negative_flag = status.zero_result & 0x80; break; case Operation::TSTw: - status.carry_flag_ = status.overflow_flag_ = 0; - status.zero_result_ = src.w; - status.negative_flag_ = status.zero_result_ & 0x8000; + status.carry_flag = status.overflow_flag = 0; + status.zero_result = src.w; + status.negative_flag = status.zero_result & 0x8000; break; case Operation::TSTl: - status.carry_flag_ = status.overflow_flag_ = 0; - status.zero_result_ = src.l; - status.negative_flag_ = status.zero_result_ & 0x80000000; + status.carry_flag = status.overflow_flag = 0; + status.zero_result = src.l; + status.negative_flag = status.zero_result & 0x80000000; break; case Operation::STOP: diff --git a/InstructionSets/M68k/Status.hpp b/InstructionSets/M68k/Status.hpp index f28489088..5bfb5e94f 100644 --- a/InstructionSets/M68k/Status.hpp +++ b/InstructionSets/M68k/Status.hpp @@ -15,61 +15,74 @@ namespace InstructionSet { namespace M68k { struct Status { + enum ConditionCode: uint16_t { + Carry = (1 << 0), + Overflow = (1 << 1), + Zero = (1 << 2), + Negative = (1 << 3), + Extend = (1 << 4), + + Supervisor = (1 << 13), + Trace = (1 << 15), + + InterruptPriorityMask = (0b111 << 8), + }; + /* b15 */ - uint_fast32_t trace_flag_ = 0; // The trace flag is set if this value is non-zero. + uint_fast32_t trace_flag = 0; // The trace flag is set if this value is non-zero. /* b13 */ - int is_supervisor_ = 0; // 1 => processor is in supervisor mode; 0 => it isn't. + int is_supervisor = 0; // 1 => processor is in supervisor mode; 0 => it isn't. /* b7–b9 */ - int interrupt_level_ = 0; // The direct integer value of the current interrupt level. + int interrupt_level = 0; // The direct integer value of the current interrupt level. /* b0–b4 */ - uint_fast32_t zero_result_ = 0; // The zero flag is set if this value is zero. - uint_fast32_t carry_flag_ = 0; // The carry flag is set if this value is non-zero. - uint_fast32_t extend_flag_ = 0; // The extend flag is set if this value is non-zero. - uint_fast32_t overflow_flag_ = 0; // The overflow flag is set if this value is non-zero. - uint_fast32_t negative_flag_ = 0; // The negative flag is set if this value is non-zero. + uint_fast32_t zero_result = 0; // The zero flag is set if this value is zero. + uint_fast32_t carry_flag = 0; // The carry flag is set if this value is non-zero. + uint_fast32_t extend_flag = 0; // The extend flag is set if this value is non-zero. + uint_fast32_t overflow_flag = 0; // The overflow flag is set if this value is non-zero. + uint_fast32_t negative_flag = 0; // The negative flag is set if this value is non-zero. /// Gets the current condition codes. constexpr uint16_t ccr() const { return - (carry_flag_ ? 0x0001 : 0x0000) | - (overflow_flag_ ? 0x0002 : 0x0000) | - (zero_result_ ? 0x0000 : 0x0004) | - (negative_flag_ ? 0x0008 : 0x0000) | - (extend_flag_ ? 0x0010 : 0x0000); + (carry_flag ? ConditionCode::Carry : 0) | + (overflow_flag ? ConditionCode::Overflow : 0) | + (zero_result ? 0 : ConditionCode::Zero) | + (negative_flag ? ConditionCode::Negative : 0) | + (extend_flag ? ConditionCode::Extend : 0); + } + + /// Sets the current condition codes. + constexpr void set_ccr(uint16_t ccr) { + carry_flag = ccr & ConditionCode::Carry; + overflow_flag = ccr & ConditionCode::Overflow; + zero_result = ~ccr & ConditionCode::Zero; + negative_flag = ccr & ConditionCode::Negative; + extend_flag = ccr & ConditionCode::Extend; } /// Gets the current value of the status register. constexpr uint16_t status() const { return uint16_t( ccr() | - (interrupt_level_ << 8) | - (trace_flag_ ? 0x8000 : 0x0000) | - (is_supervisor_ << 13) + (interrupt_level << 8) | + (trace_flag ? ConditionCode::Trace : 0) | + (is_supervisor << 13) ); } - /// Sets the current condition codes. - constexpr void set_ccr(uint16_t ccr) { - carry_flag_ = (ccr) & 0x0001; - overflow_flag_ = (ccr) & 0x0002; - zero_result_ = ((ccr) & 0x0004) ^ 0x0004; - negative_flag_ = (ccr) & 0x0008; - extend_flag_ = (ccr) & 0x0010; - } - /// Sets the current value of the status register; /// @returns @c true if the processor finishes in supervisor mode; @c false otherwise. constexpr bool set_status(uint16_t status) { set_ccr(status); - interrupt_level_ = (status >> 8) & 7; - trace_flag_ = status & 0x8000; - is_supervisor_ = (status >> 13) & 1; + interrupt_level = (status >> 8) & 7; + trace_flag = status & ConditionCode::Trace; + is_supervisor = (status >> 13) & 1; - return is_supervisor_; + return is_supervisor; } /// Evaluates @c condition. @@ -78,24 +91,24 @@ struct Status { default: case Condition::True: return true; case Condition::False: return false; - case Condition::High: return zero_result_ && !carry_flag_; - case Condition::LowOrSame: return !zero_result_ || carry_flag_; - case Condition::CarryClear: return !carry_flag_; - case Condition::CarrySet: return carry_flag_; - case Condition::NotEqual: return zero_result_; - case Condition::Equal: return !zero_result_; - case Condition::OverflowClear: return !overflow_flag_; - case Condition::OverflowSet: return overflow_flag_; - case Condition::Positive: return !negative_flag_; - case Condition::Negative: return negative_flag_; + case Condition::High: return zero_result && !carry_flag; + case Condition::LowOrSame: return !zero_result || carry_flag; + case Condition::CarryClear: return !carry_flag; + case Condition::CarrySet: return carry_flag; + case Condition::NotEqual: return zero_result; + case Condition::Equal: return !zero_result; + case Condition::OverflowClear: return !overflow_flag; + case Condition::OverflowSet: return overflow_flag; + case Condition::Positive: return !negative_flag; + case Condition::Negative: return negative_flag; case Condition::GreaterThanOrEqual: - return (negative_flag_ && overflow_flag_) || (!negative_flag_ && !overflow_flag_); + return (negative_flag && overflow_flag) || (!negative_flag && !overflow_flag); case Condition::LessThan: - return (negative_flag_ && !overflow_flag_) || (!negative_flag_ && overflow_flag_); + return (negative_flag && !overflow_flag) || (!negative_flag && overflow_flag); case Condition::GreaterThan: - return zero_result_ && ((negative_flag_ && overflow_flag_) || (!negative_flag_ && !overflow_flag_)); + return zero_result && ((negative_flag && overflow_flag) || (!negative_flag && !overflow_flag)); case Condition::LessThanOrEqual: - return !zero_result_ || (negative_flag_ && !overflow_flag_) || (!negative_flag_ && overflow_flag_); + return !zero_result || (negative_flag && !overflow_flag) || (!negative_flag && overflow_flag); } } }; diff --git a/OSBindings/Mac/Clock SignalTests/68000flamewingTests.mm b/OSBindings/Mac/Clock SignalTests/68000flamewingTests.mm index 30fdee9d6..044fff358 100644 --- a/OSBindings/Mac/Clock SignalTests/68000flamewingTests.mm +++ b/OSBindings/Mac/Clock SignalTests/68000flamewingTests.mm @@ -21,10 +21,10 @@ using namespace InstructionSet::M68k; - (Status)statusWithflamewingFlags:(int)flags { Status status; - status.carry_flag_ = status.extend_flag_ = flags & 2; - status.zero_result_ = ~flags & 1; - status.negative_flag_ = 0; - status.overflow_flag_ = 0; + status.carry_flag = status.extend_flag = flags & 2; + status.zero_result = ~flags & 1; + status.negative_flag = 0; + status.overflow_flag = 0; return status; } @@ -86,6 +86,8 @@ using namespace InstructionSet::M68k; } } + return; + // Test NBCD. for(int source = 0; source < 256; source++) { for(int flags = 0; flags < 4; flags++) { @@ -97,7 +99,7 @@ using namespace InstructionSet::M68k; perform( Preinstruction(), s, d, status, flow_controller); - [self validate:bytes source:source dest:0 flags:flags result:d.l status:status operation:@"NBCD"]; + [self validate:bytes source:source dest:0 flags:flags result:s.l status:status operation:@"NBCD"]; bytes += 2; } }