From c447655047a4277e9e95ae18fc1e9df8331f918c Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Mon, 24 Jun 2019 16:51:43 -0400 Subject: [PATCH] Resolves assumption that shifts greater than the bit count of the relevant int are well-defined in C. --- .../Mac/Clock SignalTests/68000Tests.mm | 92 +++++++++++++++++++ .../Implementation/68000Implementation.hpp | 16 ++-- 2 files changed, 102 insertions(+), 6 deletions(-) diff --git a/OSBindings/Mac/Clock SignalTests/68000Tests.mm b/OSBindings/Mac/Clock SignalTests/68000Tests.mm index 17660b150..04ac7f9fa 100644 --- a/OSBindings/Mac/Clock SignalTests/68000Tests.mm +++ b/OSBindings/Mac/Clock SignalTests/68000Tests.mm @@ -1644,6 +1644,98 @@ class CPU::MC68000::ProcessorStorageTests { XCTAssertEqual(16, _machine->get_cycle_count()); } +// MARK: LSL + +- (void)testLSLb_Dn_2 { + _machine->set_program({ + 0xe529 // LSL.b D2, D1 + }); + auto state = _machine->get_processor_state(); + state.data[1] = 0xce3dd567; + state.data[2] = 2; + + _machine->set_processor_state(state); + _machine->run_for_instructions(1); + + state = _machine->get_processor_state(); + XCTAssertEqual(state.data[1], 0xce3dd59c); + XCTAssertEqual(state.data[2], 2); + XCTAssertEqual(state.status & Flag::ConditionCodes, Flag::Extend | Flag::Negative | Flag::Carry); + XCTAssertEqual(10, _machine->get_cycle_count()); +} + +- (void)testLSLb_Dn_69 { + _machine->set_program({ + 0xe529 // LSL.b D2, D1 + }); + auto state = _machine->get_processor_state(); + state.data[1] = 0xce3dd567; + state.data[2] = 0x69; + + _machine->set_processor_state(state); + _machine->run_for_instructions(1); + + state = _machine->get_processor_state(); + XCTAssertEqual(state.data[1], 0xce3dd500); + XCTAssertEqual(state.data[2], 0x69); + XCTAssertEqual(state.status & Flag::ConditionCodes, Flag::Zero); + XCTAssertEqual(88, _machine->get_cycle_count()); +} + +- (void)testLSLw_Dn_0 { + _machine->set_program({ + 0xe569 // LSL.w D2, D1 + }); + auto state = _machine->get_processor_state(); + state.data[1] = 0xce3dd567; + state.data[2] = 0; + + _machine->set_processor_state(state); + _machine->run_for_instructions(1); + + state = _machine->get_processor_state(); + XCTAssertEqual(state.data[1], 0xce3dd567); + XCTAssertEqual(state.data[2], 0); + XCTAssertEqual(state.status & Flag::ConditionCodes, Flag::Negative); + XCTAssertEqual(6, _machine->get_cycle_count()); +} + +- (void)testLSLw_Dn_b { + _machine->set_program({ + 0xe569 // LSL.w D2, D1 + }); + auto state = _machine->get_processor_state(); + state.data[1] = 0xce3dd567; + state.data[2] = 0xb; + + _machine->set_processor_state(state); + _machine->run_for_instructions(1); + + state = _machine->get_processor_state(); + XCTAssertEqual(state.data[1], 0xce3d3800); + XCTAssertEqual(state.data[2], 0xb); + XCTAssertEqual(state.status & Flag::ConditionCodes, Flag::Extend | Flag::Carry); + XCTAssertEqual(28, _machine->get_cycle_count()); +} + +- (void)testLSLl_Dn { + _machine->set_program({ + 0xe5a9 // LSL.l D2, D1 + }); + auto state = _machine->get_processor_state(); + state.data[1] = 0xce3dd567; + state.data[2] = 0x20; + + _machine->set_processor_state(state); + _machine->run_for_instructions(1); + + state = _machine->get_processor_state(); + XCTAssertEqual(state.data[1], 0); + XCTAssertEqual(state.data[2], 0x20); + XCTAssertEqual(state.status & Flag::ConditionCodes, Flag::Extend | Flag::Carry | Flag::Zero); + XCTAssertEqual(72, _machine->get_cycle_count()); +} + // MARK: MOVEM - (void)testMOVEM { diff --git a/Processors/68000/Implementation/68000Implementation.hpp b/Processors/68000/Implementation/68000Implementation.hpp index 5a45d1fa3..a7870eaf8 100644 --- a/Processors/68000/Implementation/68000Implementation.hpp +++ b/Processors/68000/Implementation/68000Implementation.hpp @@ -1557,7 +1557,7 @@ template void Proces if(!shift_count) { \ carry_flag_ = 0; \ } else { \ - destination = decltype(destination)(value << shift_count); \ + destination = (shift_count < size) ? decltype(destination)(value << shift_count) : 0; \ extend_flag_ = carry_flag_ = decltype(carry_flag_)(value) & decltype(carry_flag_)( (1 << (size - 1)) >> (shift_count - 1) ); \ } \ \ @@ -1583,10 +1583,14 @@ template void Proces if(!shift_count) { \ carry_flag_ = 0; \ } else { \ - destination = decltype(destination)(\ - (value >> shift_count) | \ - ((value & decltype(value)(1 << (size - 1)) ? 0xffffffff : 0x000000000) << (size - shift_count)) \ - ); \ + destination = (shift_count < size) ? \ + decltype(destination)(\ + (value >> shift_count) | \ + ((value & decltype(value)(1 << (size - 1)) ? 0xffffffff : 0x000000000) << (size - shift_count)) \ + ) : \ + decltype(destination)( \ + (value & decltype(value)(1 << (size - 1))) ? 0xffffffff : 0x000000000 \ + ); \ extend_flag_ = carry_flag_ = decltype(carry_flag_)(value) & decltype(carry_flag_)(1 << (shift_count - 1)); \ } \ \ @@ -1634,7 +1638,7 @@ template void Proces if(!shift_count) { \ carry_flag_ = 0; \ } else { \ - destination = value >> shift_count; \ + destination = (shift_count < size) ? (value >> shift_count) : 0; \ extend_flag_ = carry_flag_ = value & decltype(carry_flag_)(1 << (shift_count - 1)); \ } \ \