1
0
mirror of https://github.com/TomHarte/CLK.git synced 2025-02-16 18:30:32 +00:00

Add a faulty attempt at MOVEM.

This commit is contained in:
Thomas Harte 2022-05-20 18:48:19 -04:00
parent 9d79e64f5c
commit a818650027
3 changed files with 149 additions and 3 deletions

View File

@ -156,7 +156,7 @@ struct TestProcessor: public CPU::MC68000Mk2::BusHandler {
// To limit tests run to a subset of files and/or of tests, uncomment and fill in below.
_fileSet = [NSSet setWithArray:@[
// @"chk.json",
@"movem.json",
// Below this line are passing tests.
@"abcd_sbcd.json",
@ -176,7 +176,7 @@ struct TestProcessor: public CPU::MC68000Mk2::BusHandler {
@"ext.json",
@"swap.json",
]]; // 16/32 = 50 % done, as far as the tests go.
// _testSet = [NSSet setWithArray:@[@"BCLR 0122"]];
_testSet = [NSSet setWithArray:@[@"MOVEM 006f (2)"]];
}
- (void)testAll {
@ -287,7 +287,7 @@ struct TestProcessor: public CPU::MC68000Mk2::BusHandler {
NSNumber *const value = [enumerator nextObject];
if(!address || !value) break;
XCTAssertEqual(test68000->ram[address.integerValue ^ 1], value.integerValue, @"%@: Memory at location %@ inconsistent", name, address);
// XCTAssertEqual(test68000->ram[address.integerValue ^ 1], value.integerValue, @"%@: Memory at location %@ inconsistent", name, address);
if(test68000->ram[address.integerValue ^ 1] != value.integerValue) [_failures addObject:name];
}

View File

@ -143,6 +143,9 @@ enum ExecutionState: int {
MOVEPtoR_l,
LogicalToSR,
MOVEMtoR, MOVEMtoR_l_read, MOVEMtoR_w_read, MOVEMtoR_finish,
MOVEMtoM, MOVEMtoM_l_write, MOVEMtoM_w_write, MOVEMtoM_finish,
};
// MARK: - The state machine.
@ -640,6 +643,11 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
Duplicate(ORItoSR, EORItoSR); Duplicate(ANDItoSR, EORItoSR);
StdCASE(EORItoSR, perform_state_ = LogicalToSR);
StdCASE(MOVEMtoRl, perform_state_ = MOVEMtoR);
StdCASE(MOVEMtoRw, perform_state_ = MOVEMtoR);
StdCASE(MOVEMtoMl, perform_state_ = MOVEMtoM);
StdCASE(MOVEMtoMw, perform_state_ = MOVEMtoM);
default:
assert(false);
}
@ -1528,6 +1536,140 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
Prefetch();
MoveToState(Decode);
//
// MOVEM M --> R
//
BeginState(MOVEMtoR):
Prefetch(); // np
post_ea_state_ =
(instruction_.operation == InstructionSet::M68k::Operation::MOVEMtoRl) ?
MOVEMtoR_l_read : MOVEMtoR_w_read;
next_operand_ = 1;
register_index_ = 0;
register_delta_ = 1;
SetDataAddress(effective_address_[1]);
SetupDataAccess(Microcycle::Read, Microcycle::SelectWord);
MoveToState(CalcEffectiveAddress);
BeginState(MOVEMtoR_w_read):
// If there's nothing left to read, move on.
if(!operand_[0].w) {
MoveToState(MOVEMtoR_finish);
}
// Find the next register to read, read it and sign extend it.
while(!(operand_[0].w & 1)) {
operand_[0].w >>= 1;
register_index_ += register_delta_;
}
Access(registers_[register_index_].low);
registers_[register_index_].l = uint32_t(int16_t(registers_[register_index_].w));
effective_address_[1] += 2;
// Drop the bottom bit.
operand_[0].w >>= 1;
register_index_ += register_delta_;
MoveToState(MOVEMtoR_w_read);
BeginState(MOVEMtoR_l_read):
// If there's nothing left to read, move on.
if(!operand_[0].w) {
MoveToState(MOVEMtoR_finish);
}
// Find the next register to read, read it.
while(!(operand_[0].w & 1)) {
operand_[0].w >>= 1;
register_index_ += register_delta_;
}
Access(registers_[register_index_].low);
effective_address_[1] += 2;
Access(registers_[register_index_].high);
effective_address_[1] += 2;
// Drop the bottom bit.
operand_[0].w >>= 1;
register_index_ += register_delta_;
MoveToState(MOVEMtoR_l_read);
BeginState(MOVEMtoR_finish):
// Perform one more read, spuriously.
Access(temporary_value_.low); // nr
Prefetch(); // np
MoveToState(Decode);
//
// MOVEM R --> M
//
BeginState(MOVEMtoM):
Prefetch(); // np
post_ea_state_ =
(instruction_.operation == InstructionSet::M68k::Operation::MOVEMtoMl) ?
MOVEMtoM_l_write : MOVEMtoM_w_write;
next_operand_ = 1;
// Predecrement writes registers the other way around, but still reads the
// mask from LSB.
if(instruction_.mode(1) == Mode::AddressRegisterIndirectWithPredecrement) {
register_index_ = 15;
register_delta_ = -1;
} else {
register_index_ = 0;
register_delta_ = 1;
}
SetDataAddress(effective_address_[1]);
SetupDataAccess(0, Microcycle::SelectWord);
MoveToState(CalcEffectiveAddress);
BeginState(MOVEMtoM_w_write):
// If there's nothing left to read, move on.
if(!operand_[0].w) {
MoveToState(MOVEMtoM_finish);
}
// Find the next register to write, write it.
while(!(operand_[0].w & 1)) {
operand_[0].w >>= 1;
register_index_ += register_delta_;
}
Access(registers_[register_index_].low);
effective_address_[1] += register_delta_ << 1;
// Drop the bottom bit.
operand_[0].w >>= 1;
register_index_ += register_delta_;
MoveToState(MOVEMtoM_w_write);
BeginState(MOVEMtoM_l_write):
// If there's nothing left to read, move on.
if(!operand_[0].w) {
MoveToState(MOVEMtoM_finish);
}
// Find the next register to write, write it.
while(!(operand_[0].w & 1)) {
operand_[0].w >>= 1;
register_index_ += register_delta_;
}
// TODO: switch word order if predecrementing.
Access(registers_[register_index_].high);
effective_address_[1] += register_delta_ << 1;
Access(registers_[register_index_].low);
effective_address_[1] += register_delta_ << 1;
// Drop the bottom bit.
operand_[0].w >>= 1;
register_index_ += register_delta_;
MoveToState(MOVEMtoM_l_write);
BeginState(MOVEMtoM_finish):
Prefetch(); // np
MoveToState(Decode);
//
// Various states TODO.
//

View File

@ -99,6 +99,10 @@ struct ProcessorBase: public InstructionSet::M68k::NullFlowController {
/// determine total operation cost.
bool did_bit_op_high_ = false;
/// Two bits of state for MOVEM, being the curent register and what to
/// add to it to get to the next register.
int register_index_ = 0, register_delta_ = 0;
// A lookup table that aids with effective address calculation in
// predecrement and postincrement modes; index as [size][register]
// and note that [0][7] is 2 rather than 1.