1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-07-05 10:28:58 +00:00

Make an effort to withdraw from the high-circuitous stuff of working around the reset sequence.

This commit is contained in:
Thomas Harte 2022-05-25 20:22:38 -04:00
parent 367ad8079a
commit 866787c5d3
6 changed files with 55 additions and 106 deletions

View File

@ -741,10 +741,10 @@
@end
@implementation M68000DIVSTests
- (void)performDIVS:(uint16_t)divisor d1:(uint32_t)d1 {
- (void)performDIVS:(uint16_t)divisor d1:(uint32_t)d1 sp:(uint32_t)sp {
self.machine->set_program({
0x83fc, divisor // DIVS #divisor, D1
});
}, sp);
auto state = self.machine->get_processor_state();
state.registers.data[1] = d1;
state.registers.status |= ConditionCode::AllConditions;
@ -753,6 +753,10 @@
self.machine->run_for_instructions(1);
}
- (void)performDIVS:(uint16_t)divisor d1:(uint32_t)d1 {
[self performDIVS:divisor d1:d1];
}
- (void)performDIVSOverflowTestDivisor:(uint16_t)divisor {
[self performDIVS:divisor d1:0x4768f231];
@ -871,7 +875,7 @@
- (void)testDIVS_12 {
// DIVS.W #$af32, D1
[self performDIVS:0xaf32 d1:0xe1d44];
[self performDIVS:0xaf32 d1:0xe1d44 sp:0];
const auto state = self.machine->get_processor_state();
XCTAssertEqual(state.registers.data[1], 0x39dcffd4);
@ -882,8 +886,7 @@
- (void)testDIVSException {
// DIVS.W #0, D1
const uint32_t initial_sp = 0x5000;
self.machine->set_initial_stack_pointer(initial_sp);
[self performDIVS:0x0 d1:0x1fffffff];
[self performDIVS:0x0 d1:0x1fffffff sp:initial_sp];
// Check register state.registers.
const auto state = self.machine->get_processor_state();
@ -1440,8 +1443,7 @@
- (void)testSUBb_PreDec {
self.machine->set_program({
0x9427 // SUB.b -(A7), D2
});
self.machine->set_initial_stack_pointer(0x2002);
}, 0x2002);
auto state = self.machine->get_processor_state();
state.registers.data[2] = 0x9c40;
*self.machine->ram_at(0x2000) = 0x2710;

View File

@ -155,8 +155,7 @@
- (void)testANDb_PostInc_A7 {
_machine->set_program({
0xc61f // AND.B (A7)+, D3
});
_machine->set_initial_stack_pointer(0x3000);
}, 0x3000);
auto state = _machine->get_processor_state();
state.registers.data[3] = 0x54fff856;
*_machine->ram_at(0x3000) = 0x0053;
@ -1088,8 +1087,7 @@
- (void)testANDISR_supervisor {
_machine->set_program({
0x027c, 0x0700 // ANDI.W #$700, SR
});
_machine->set_initial_stack_pointer(300);
}, 300);
_machine->run_for_instructions(1);
@ -1214,8 +1212,7 @@
- (void)testEORISR_supervisor {
_machine->set_program({
0x0a7c, 0x0700 // EORI.W #$700, SR
});
_machine->set_initial_stack_pointer(300);
}, 300);
_machine->run_for_instructions(1);
@ -1432,8 +1429,7 @@
- (void)testORISR_supervisor {
_machine->set_program({
0x007c, 0x0700 // ORI.W #$700, SR
});
_machine->set_initial_stack_pointer(300);
}, 300);
_machine->run_for_instructions(1);

View File

@ -108,8 +108,7 @@
- (void)testBSRw {
_machine->set_program({
0x6100, 0x0006 // BSR.w $1008
});
_machine->set_initial_stack_pointer(0x3000);
}, 0x3000);
_machine->run_for_instructions(1);
@ -126,8 +125,7 @@
- (void)testBSRb {
_machine->set_program({
0x6106 // BSR.b $1008
});
_machine->set_initial_stack_pointer(0x3000);
}, 0x3000);
_machine->run_for_instructions(1);
@ -146,13 +144,12 @@
- (void)performCHKd1:(uint32_t)d1 d2:(uint32_t)d2 {
_machine->set_program({
0x4581 // CHK D1, D2
});
}, 0);
auto state = _machine->get_processor_state();
state.registers.data[1] = d1;
state.registers.data[2] = d2;
state.registers.status |= ConditionCode::AllConditions;
_machine->set_initial_stack_pointer(0);
_machine->set_processor_state(state);
_machine->run_for_instructions(1);
@ -414,8 +411,7 @@
- (void)testJSR_PC {
_machine->set_program({
0x4eba, 0x000a // JSR (+a)PC ; JSR to $100c
});
_machine->set_initial_stack_pointer(0x2000);
}, 0x2000);
_machine->run_for_instructions(1);
@ -430,8 +426,7 @@
- (void)testJSR_XXXl {
_machine->set_program({
0x4eb9, 0x0000, 0x1008 // JSR ($1008).l
});
_machine->set_initial_stack_pointer(0x2000);
}, 0x2000);
_machine->run_for_instructions(1);
@ -458,8 +453,7 @@
- (void)testRTR {
_machine->set_program({
0x4e77 // RTR
});
_machine->set_initial_stack_pointer(0x2000);
}, 0x2000);
*_machine->ram_at(0x2000) = 0x7fff;
*_machine->ram_at(0x2002) = 0;
*_machine->ram_at(0x2004) = 0xc;
@ -478,8 +472,7 @@
- (void)testRTS {
_machine->set_program({
0x4e75 // RTS
});
_machine->set_initial_stack_pointer(0x2000);
}, 0x2000);
*_machine->ram_at(0x2000) = 0x0000;
*_machine->ram_at(0x2002) = 0x000c;
@ -521,8 +514,7 @@
- (void)testTRAPV_taken {
_machine->set_program({
0x4e76 // TRAPV
});
_machine->set_initial_stack_pointer(0x206);
}, 0x206);
auto state = _machine->get_processor_state();
state.registers.status = 0x702;

View File

@ -292,10 +292,9 @@
- (void)testLINKA1_5 {
_machine->set_program({
0x4e51, 0x0005 // LINK a1, #5
});
}, 0x22222222);
auto state = _machine->get_processor_state();
state.registers.address[1] = 0x11111111;
_machine->set_initial_stack_pointer(0x22222222);
_machine->set_processor_state(state);
_machine->run_for_instructions(1);
@ -311,8 +310,7 @@
- (void)testLINKA7_5 {
_machine->set_program({
0x4e57, 0x0005 // LINK a7, #5
});
_machine->set_initial_stack_pointer(0x22222222);
}, 0x22222222);
_machine->run_for_instructions(1);
@ -326,10 +324,9 @@
- (void)testLINKA1_8000 {
_machine->set_program({
0x4e51, 0x8000 // LINK a1, #$8000
});
}, 0x22222222);
auto state = _machine->get_processor_state();
state.registers.address[1] = 0x11111111;
_machine->set_initial_stack_pointer(0x22222222);
_machine->set_processor_state(state);
_machine->run_for_instructions(1);
@ -395,14 +392,13 @@
- (void)testMOVEMl_fromEverything {
_machine->set_program({
0x48e4, 0xffff // MOVEM.L D0-D7/A0-A7, -(A4)
});
}, 0xffffffff);
auto state = _machine->get_processor_state();
for(int c = 0; c < 8; ++c)
state.registers.data[c] = (c+1) * 0x11111111;
for(int c = 0; c < 7; ++c)
state.registers.address[c] = ((c < 4) ? (c + 9) : (c + 8)) * 0x11111111;
state.registers.address[4] = 0x4000;
_machine->set_initial_stack_pointer(0xffffffff);
_machine->set_processor_state(state);
_machine->run_for_instructions(1);
@ -995,10 +991,9 @@
- (void)testPEA_A1 {
_machine->set_program({
0x4851 // PEA (A1)
});
}, 0x1996);
auto state = _machine->get_processor_state();
state.registers.address[1] = 0x3000ffff;
_machine->set_initial_stack_pointer(0x1996);
_machine->set_processor_state(state);
_machine->run_for_instructions(1);
@ -1014,8 +1009,7 @@
- (void)testPEA_A7 {
_machine->set_program({
0x4857 // PEA (A7)
});
_machine->set_initial_stack_pointer(0x1012);
}, 0x1012);
_machine->run_for_instructions(1);
@ -1029,8 +1023,7 @@
- (void)testPEA_4A7 {
_machine->set_program({
0x486f, 0x0004 // PEA 4(A7)
});
_machine->set_initial_stack_pointer(0x1012);
}, 0x1012);
_machine->run_for_instructions(1);
@ -1044,8 +1037,7 @@
- (void)testPEA_XXXw {
_machine->set_program({
0x4878, 0x3000 // PEA ($3000).w
});
_machine->set_initial_stack_pointer(0x1996);
}, 0x1996);
_machine->run_for_instructions(1);
@ -1059,8 +1051,7 @@
- (void)testPEA_XXXl {
_machine->set_program({
0x4879, 0x1234, 0x5678 // PEA ($12345678)
});
_machine->set_initial_stack_pointer(0x1996);
}, 0x1996);
_machine->run_for_instructions(1);
@ -1235,8 +1226,7 @@
- (void)testUNLINK_A7 {
_machine->set_program({
0x4e5f // UNLNK A7
});
_machine->set_initial_stack_pointer(0x3000);
}, 0x3000);
*_machine->ram_at(0x3000) = 0x0000;
*_machine->ram_at(0x3002) = 0x4000;

View File

@ -148,8 +148,7 @@ class CPU::MC68000::ProcessorStorageTests {
0x82C0, // DIVU; location 0x404
/* Next instruction would be at 0x406 */
});
_machine->set_initial_stack_pointer(0x1000);
}, 0x1000);
_machine->run_for_instructions(4);

View File

@ -23,77 +23,48 @@ using namespace InstructionSet::M68k;
*/
class RAM68000: public CPU::MC68000Mk2::BusHandler {
public:
RAM68000() : m68000_(*this) {
// Setup the /RESET vector.
ram_[0] = 0;
ram_[1] = 0x206; // Supervisor stack pointer.
ram_[2] = 0;
ram_[3] = 0x1000; // Initial PC.
// Ensure the condition codes start unset.
auto state = get_processor_state();
state.registers.status &= ~ConditionCode::AllConditions;
set_processor_state(state);
}
RAM68000() : m68000_(*this) {}
uint32_t initial_pc() const {
return 0x1000;
}
void set_program(const std::vector<uint16_t> &program) {
void set_program(
const std::vector<uint16_t> &program,
uint32_t stack_pointer = 0x206) {
memcpy(&ram_[0x1000 >> 1], program.data(), program.size() * sizeof(uint16_t));
// Add a NOP suffix, to avoid corrupting flags should the attempt to
// run for a certain number of instructions overrun.
ram_[(0x1000 >> 1) + program.size()] = 0x4e71;
}
void set_initial_stack_pointer(uint32_t sp) {
ram_[0] = sp >> 16;
ram_[1] = sp & 0xffff;
// Ensure the condition codes start unset and set the initial program counter
// and supervisor stack pointer.
auto state = get_processor_state();
state.registers.status &= ~ConditionCode::AllConditions;
state.registers.program_counter = initial_pc();
state.registers.supervisor_stack_pointer = stack_pointer;
set_processor_state(state);
}
void will_perform(uint32_t, uint16_t) {
if(!has_run_) {
// Reapply all of initial state except the program counter and stack pointers.
// Also copy the supervisor stack pointer to the user.
const auto state = m68000_.get_state();
initial_state_.registers.program_counter = state.registers.program_counter;
initial_state_.registers.user_stack_pointer = state.registers.supervisor_stack_pointer;
initial_state_.registers.supervisor_stack_pointer = state.registers.supervisor_stack_pointer;
m68000_.set_state(initial_state_);
}
--instructions_remaining_;
if(!instructions_remaining_) {
captured_state_ = m68000_.get_state();
throw StopException();
}
}
void run_for_instructions(int count) {
instructions_remaining_ = count + (has_run_ ? 0 : 1);
finish_reset_if_needed();
instructions_remaining_ = count;
if(!instructions_remaining_) return;
while(instructions_remaining_) {
run_for(HalfCycles(2));
}
try {
while(true) {
run_for(HalfCycles(2000));
}
} catch (const StopException &) {}
}
void run_for(HalfCycles cycles) {
finish_reset_if_needed();
m68000_.run_for(cycles);
}
void finish_reset_if_needed() {
// If the 68000 hasn't run yet, build in the necessary
// cycles to finish the reset program, and set the stored state.
if(!has_run_) {
m68000_.run_for(HalfCycles(80));
duration_ -= HalfCycles(80);
has_run_ = true;
}
}
uint16_t *ram_at(uint32_t address) {
return &ram_[(address >> 1) % ram_.size()];
}
@ -133,12 +104,11 @@ class RAM68000: public CPU::MC68000Mk2::BusHandler {
}
CPU::MC68000Mk2::State get_processor_state() {
return captured_state_;
return m68000_.get_state();
}
void set_processor_state(const CPU::MC68000Mk2::State &state) {
initial_state_ = captured_state_ = state;
m68000_.set_state(state);
m68000_.decode_from_state(state.registers);
}
auto &processor() {
@ -154,12 +124,12 @@ class RAM68000: public CPU::MC68000Mk2::BusHandler {
}
private:
struct StopException {};
CPU::MC68000Mk2::Processor<RAM68000, true, true, true> m68000_;
std::array<uint16_t, 256*1024> ram_{};
int instructions_remaining_;
HalfCycles duration_;
bool has_run_ = false;
CPU::MC68000Mk2::State captured_state_, initial_state_;
};
#endif /* TestRunner68000_h */